'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const index = require('./index-1ee80297.js');

let DvnDraggableBox$1 = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
  }
  dragStart(event) {
    this.onDragStart(event);
  }
  dragEnd(event) {
    this.onDragEnd(event);
  }
  render() {
    return (index.h(index.Host, { draggable: "true", style: { display: 'block' } }, index.h("slot", null)));
  }
  get el() { return index.getElement(this); }
};

const dvnDroppableBoxCss = "dvn-droppable-box{display:block}dvn-droppable-box>div{opacity:0;-webkit-transition:opacity 0.3s;transition:opacity 0.3s}dvn-droppable-box>div.has-drag-over{opacity:1}";

let DvnDraggableBox = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.isDraggingOver = false;
    this.dragEnterCount = 0;
  }
  render() {
    return (index.h(index.Host, null, index.h("div", { class: { 'has-drag-over': this.isDraggingOver }, onDragOver: e => e.preventDefault(), onDragEnter: () => {
        this.isDraggingOver = true;
        this.dragEnterCount = this.dragEnterCount + 1;
      }, onDragLeave: () => {
        if (this.dragEnterCount <= 1) {
          this.isDraggingOver = false;
        }
        this.dragEnterCount = this.dragEnterCount - 1;
      }, onDrop: () => {
        this.isDraggingOver = false;
        this.dragEnterCount = 0;
        this.onDrop();
      } }, index.h("slot", null))));
  }
  get el() { return index.getElement(this); }
};
DvnDraggableBox.style = dvnDroppableBoxCss;

const dvnRichEditorCss = "dvn-rich-editor{display:block;position:relative;--actions-container-width:5rem;--content-gap-size:24px;}dvn-rich-editor dvn-icon{width:var(--icon-size);height:var(--icon-size);-ms-flex:0 0 var(--icon-size);flex:0 0 var(--icon-size)}dvn-rich-editor dvn-icon i{vertical-align:top;line-height:var(--icon-size)}dvn-rich-editor .component-area{display:-ms-flexbox;display:flex}dvn-rich-editor .component-area .drag-controls{width:var(--actions-container-width);height:var(--content-gap-size);display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;opacity:0;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;z-index:1;-ms-flex-item-align:start;align-self:flex-start}dvn-rich-editor .component-area .drag-controls:hover{opacity:1}dvn-rich-editor .component-area .drag-controls .drag-icon{cursor:-webkit-grab;cursor:grab;font-size:1.2em;color:var(--color-text-secondary)}dvn-rich-editor .drop-area{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;height:var(--content-gap-size)}dvn-rich-editor .drop-area:hover{-webkit-transition:opacity 0.3s;transition:opacity 0.3s;opacity:1}dvn-rich-editor .drop-area .drop-area-line{height:2px;-ms-flex:1;flex:1;background:var(--color-primary);-ms-flex-item-align:center;align-self:center;margin-left:var(--actions-container-width)}dvn-rich-editor .insert-item-area{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;opacity:0;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;height:var(--content-gap-size);position:relative}dvn-rich-editor .insert-item-area:hover{opacity:1}dvn-rich-editor .insert-item-area .insert-item-area-controls{width:var(--actions-container-width);text-align:right;position:absolute;padding-right:6px}dvn-rich-editor .insert-item-area .insert-item-area-controls>*{z-index:0}dvn-rich-editor .insert-item-area .insert-item-area-line{height:2px;-ms-flex:1;flex:1;background:var(--color-border);margin-left:var(--actions-container-width)}dvn-rich-editor a{color:var(--color-link);text-decoration:none;outline:none}dvn-rich-editor a:hover{color:var(--color-link-hover)}dvn-rich-editor [contenteditable]:focus{outline:0px solid transparent}";

const getTag = (type) => {
  switch (type) {
    case 'h1':
    case 'h2':
    case 'h3':
      return 'dvn-rich-editor-heading-block';
    case 'text':
      return 'dvn-rich-editor-text-block';
    default:
      return 'div';
  }
};
const defaultEditorSettings = {
  enableDrag: true,
  enableBlockCreation: true,
  enableBlockDeletion: true,
  hideDragControls: false,
  blockTypes: ['h1', 'h2', 'h3', 'text'],
  blockSettings: {
    text: {
      textSelectionOptions: ['bold', 'italic', 'strike', 'underline', 'link', 'unlink'],
    }
  },
};
let DvnRichEditor = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.change = index.createEvent(this, "change", 7);
    this.refs = {};
    this.components = [];
    this.isDragging = false;
    this.value = [
      {
        type: 'text',
        id: generateID(16),
        value: {
          placeholder: 'Start composing your masterpiece.',
          text: '',
        },
      },
    ];
    this.lastUpdatedComponent = undefined;
    this.onDragStart = (component) => {
      this.draggedComponent = component;
      this.isDragging = true;
    };
    this.onDragEnd = () => {
      this.isDragging = false;
    };
    this.onDrop = (toIndex) => {
      this.isDragging = false;
      const { components } = this;
      const fromIndex = components.findIndex(c => c.id === this.draggedComponent.id);
      const newList = [...components];
      newList.splice(fromIndex, 1);
      newList.splice(toIndex, 0, this.draggedComponent);
      this.components = newList;
    };
    this.onAddNewItemClick = (type, toIndex) => {
      if (!this.getEditorSettings().enableBlockCreation) {
        return;
      }
      const { components } = this;
      let component;
      switch (type) {
        case 'h1':
          component = { type, value: { text: '' } };
          break;
        case 'h2':
          component = { type, value: { text: '' } };
          break;
        case 'h3':
          component = { type, value: { text: '' } };
          break;
        case 'text':
          component = { type, value: { text: '' } };
          break;
      }
      component.id = generateID(16);
      const newList = [...components];
      newList.splice(toIndex, 0, component);
      this.components = newList;
      // focus on the new component
      setTimeout(() => { var _a, _b; return (_b = (_a = this.refs[component.id]).focusOnInput) === null || _b === void 0 ? void 0 : _b.call(_a); }, 300);
    };
    this.onDeleteItemClick = (index) => {
      if (!this.getEditorSettings().enableBlockDeletion) {
        return;
      }
      const { components } = this;
      const newList = [...components];
      newList.splice(index, 1);
      this.components = newList;
      if (index > 0) {
        // focus on the previous component
        const componentToFocus = this.refs[components[index - 1].id];
        setTimeout(() => { var _a; return (_a = componentToFocus.focusOnInput) === null || _a === void 0 ? void 0 : _a.call(componentToFocus); }, 300);
      }
      else if (index + 1 <= components.length) {
        // focus on the next component
        const componentToFocus = this.refs[components[index + 1].id];
        setTimeout(() => { var _a; return (_a = componentToFocus.focusOnInput) === null || _a === void 0 ? void 0 : _a.call(componentToFocus); }, 300);
      }
    };
    this.onConvertItemClick = async (index, type) => {
      var _a, _b;
      const { components } = this;
      const newList = [...components];
      newList[index].type = type;
      // get raw value without html tags in it
      newList[index].value.text = await ((_b = (_a = this.refs[newList[index].id]).getRawValue) === null || _b === void 0 ? void 0 : _b.call(_a)) || newList[index].value.text;
      newList[index].id = generateID(16);
      this.components = newList;
    };
    this.focusOnNextItem = (index) => {
      var _a;
      const { components } = this;
      if (index + 1 < components.length) {
        // focus on the next component
        const componentToFocus = this.refs[components[index + 1].id];
        (_a = componentToFocus.focusOnInput) === null || _a === void 0 ? void 0 : _a.call(componentToFocus);
      }
    };
    this.focusOnPreviousItem = (index) => {
      var _a;
      const { components } = this;
      if (index > 0) {
        // focus on the next component
        const componentToFocus = this.refs[components[index - 1].id];
        (_a = componentToFocus.focusOnInput) === null || _a === void 0 ? void 0 : _a.call(componentToFocus);
      }
    };
    this.getEditorSettings = () => (Object.assign(Object.assign({}, defaultEditorSettings), (this.editorSettings || {})));
  }
  componentWillLoad() {
    this.components = this.value;
  }
  componentDidUpdate() {
    var _a, _b;
    (_b = (_a = this.lastUpdatedComponent) === null || _a === void 0 ? void 0 : _a.focusOnInput) === null || _b === void 0 ? void 0 : _b.call(_a);
  }
  onAction(event) {
    const isItTheEventThisComponentDispatched = event.target['nodeName'].toLowerCase() === 'dvn-rich-editor';
    if (isItTheEventThisComponentDispatched) {
      return;
    }
    this.lastUpdatedComponent = event.target;
    event.stopImmediatePropagation();
    const data = event.detail;
    this.components = this.components.map(component => {
      if (component.id === data.id) {
        return Object.assign(Object.assign({}, component), { value: data.value });
      }
      return component;
    });
    this.change.emit(this.components);
  }
  render() {
    const { isDragging } = this;
    const editorSettings = this.getEditorSettings();
    const blocks = [
      createDropArea(editorSettings, 0, this.onDrop, this.onAddNewItemClick, isDragging)
    ];
    this.components.forEach((component, i) => {
      const componentArea = renderComponentArea(i, component, editorSettings, el => {
        if (el)
          this.refs[component.id] = el;
      }, this.onConvertItemClick, this.onAddNewItemClick, this.onDeleteItemClick, this.focusOnNextItem, this.focusOnPreviousItem);
      if (!editorSettings.enableDrag) {
        blocks.push(componentArea);
      }
      else {
        blocks.push(index.h("dvn-draggable-box", { key: component.id, onDragEnd: this.onDragEnd, onDragStart: () => this.onDragStart(component) }, componentArea));
      }
      blocks.push(createDropArea(editorSettings, i + 1, this.onDrop, this.onAddNewItemClick, isDragging));
    });
    return (index.h(index.Host, null, blocks));
  }
  get el() { return index.getElement(this); }
};
const renderComponentArea = (index$1, component, editorSettings, setRef, onConvertItemClick, onAddNewItemClick, onDeleteItemClick, focusOnNextItem, focusOnPreviousItem) => {
  const Tag = getTag(component.type);
  return (index.h("div", { class: "component-area" }, index.h("div", { class: "drag-controls", style: { marginTop: getTopOffset(component.type), width: editorSettings.hideDragControls ? '0' : undefined } }, editorSettings.enableDrag &&
    index.h("div", { class: "drag-icon" }, index.h("dvn-icon-button", { iconName: "uil-draggabledots", view: "flat", leaned: true, tagMode: true })), index.h("dvn-rich-editor-component-options", { editorSettings: editorSettings, componentType: component.type, onActionClick: (action) => {
      if (action === 'delete') {
        onDeleteItemClick(index$1);
      }
      else {
        onConvertItemClick(index$1, action);
      }
    } })), index.h(Tag, { key: component.id, id: component.id, value: component.value, type: component.type, editorSettings: editorSettings, ref: setRef, onEnterKeyDown: () => onAddNewItemClick('text', index$1 + 1), onLastBackspaceKeyDown: () => onDeleteItemClick(index$1), onArrowDown: () => focusOnNextItem(index$1), onArrowUp: () => focusOnPreviousItem(index$1) })));
};
const createDropArea = (editorSettings, index$1, onDrop, onAddNewItemClick, isDragging) => {
  if (isDragging) {
    return (index.h("dvn-droppable-box", { key: `drop-area-${index$1}`, onDrop: () => onDrop(index$1) }, index.h("div", { class: "drop-area" }, index.h("div", { class: "drop-area-line" }))));
  }
  if (!editorSettings.enableBlockCreation || editorSettings.blockTypes.length === 0) {
    // just show the area as a placeholder for --content-gap-size
    return index.h("div", { class: "insert-item-area" });
  }
  return (index.h("div", { class: "insert-item-area" }, index.h("div", { class: "insert-item-area-controls" }, index.h("dvn-rich-editor-new-component-options", { index: index$1, availableBlockTypes: editorSettings.blockTypes, onActionClick: onAddNewItemClick })), index.h("div", { class: "insert-item-area-line" })));
};
function generateID(length) {
  let result = '';
  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  const charactersLength = characters.length;
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}
const getTopOffset = (componentType) => {
  switch (componentType) {
    case 'h1':
      return '8px';
    case 'h2':
      return '4px';
    default:
      return undefined;
  }
};
DvnRichEditor.style = dvnRichEditorCss;

const newComponentActionsTexts = [{
    name: 'h1',
    title: 'Heading 1',
    icon: 'uil-letter-english-a',
    iconSize: 'large',
    iconText: 'H1',
  }, {
    name: 'h2',
    title: 'Heading 2',
    icon: 'uil-letter-english-a',
    iconSize: 'medium',
    iconText: 'H2',
  }, {
    name: 'h3',
    title: 'Heading 3',
    icon: 'uil-letter-english-a',
    iconSize: 'small',
    iconText: 'H3',
  }, {
    name: 'text',
    title: 'Text',
    icon: 'uil-text',
    iconText: 'T',
  }];
const newComponentActions = [
  ...newComponentActionsTexts,
];

const dvnRichEditorComponentOptionsCss = "dvn-rich-editor-component-options{display:block;position:relative}dvn-rich-editor-component-options dvn-info-summary.highlighted{color:var(--color-primary)}dvn-rich-editor-component-options dvn-info-summary.highlighted .title{color:var(--color-primary)}dvn-rich-editor-component-options dvn-info-summary dvn-icon{min-width:var(--font-size-large);text-align:center;vertical-align:middle}";

const actions = [{
    name: 'delete',
    title: 'Delete',
    icon: 'uil-trash-alt',
  }];
let DvnRichEditorComponentOptions$1 = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
  }
  render() {
    const conversionOptions = getConversionOptions(this.componentType)
      .filter(co => this.editorSettings.blockTypes.includes(co.name));
    const actionsToShow = actions.filter(a => this.editorSettings.enableBlockDeletion || a.name !== 'delete');
    if (conversionOptions.length === 0 && actionsToShow.length === 0) {
      // no need to show the menu if no option is available
      return null;
    }
    return (index.h(index.Host, null, index.h("dvn-dropdown", { placement: "rightTop", trigger: "click", leaned: true }, index.h("dvn-icon-button", { iconName: "uil-angle-right-b", view: "ghost", iconScale: "large" }), index.h("div", { slot: "content" }, index.h("dvn-menu", { leaned: true, width: "200px" }, conversionOptions.map(action => (index.h("dvn-menu-item", { highlighted: action.name === this.componentType, onClick: () => this.onActionClick(action.name) }, index.h("dvn-info-summary", { extraClass: action.name === this.componentType ? 'highlighted' : undefined, title: action.name === this.componentType ? index.h("b", null, action.title) : action.title, leaned: true }, action.icon &&
      index.h("dvn-icon", { slot: "media", iconName: `uil ${action.icon}`, scale: action.iconSize }))))), conversionOptions.length > 0 &&
      index.h("hr", { class: "leaned-vertically" }), actionsToShow.map(action => (index.h("dvn-menu-item", { onClick: () => this.onActionClick(action.name) }, index.h("dvn-info-summary", { title: action.title, leaned: true }, index.h("dvn-icon", { slot: "media", iconName: `uil ${action.icon}` }))))))))));
  }
};
const getConversionOptions = (componentType) => {
  if (['text', 'h1', 'h2', 'h3'].includes(componentType)) {
    return newComponentActionsTexts;
  }
  return [];
};
DvnRichEditorComponentOptions$1.style = dvnRichEditorComponentOptionsCss;

const dvnRichEditorNewComponentOptionsCss = "dvn-rich-editor-new-component-options{display:block;position:relative}dvn-rich-editor-new-component-options dvn-icon{min-width:var(--font-size-large);text-align:center;vertical-align:middle}";

let DvnRichEditorComponentOptions = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.isMenuExpanded = false;
  }
  render() {
    const { availableBlockTypes } = this;
    // filter the options based on the available block types
    const actions = availableBlockTypes
      ? newComponentActions.filter(a => availableBlockTypes.includes(a.name))
      : newComponentActions;
    return (index.h(index.Host, { style: { zIndex: this.isMenuExpanded ? '100' : undefined } }, index.h("dvn-dropdown", { placement: "rightTop", trigger: "click", leaned: true, onExpandChange: (expanded) => this.isMenuExpanded = expanded }, index.h("dvn-icon-button", { iconName: "uil-plus", view: "flat", scale: "small" }), index.h("div", { slot: "content" }, index.h("dvn-menu", { leaned: true, width: "200px" }, actions.map(action => (index.h("dvn-menu-item", { onClick: () => this.onActionClick(action.name, this.index) }, index.h("dvn-info-summary", { title: action.title, leaned: true }, action.icon &&
      index.h("dvn-icon", { slot: "media", iconName: `uil ${action.icon}`, scale: action.iconSize }))))))))));
  }
};
DvnRichEditorComponentOptions.style = dvnRichEditorNewComponentOptionsCss;

exports.dvn_draggable_box = DvnDraggableBox$1;
exports.dvn_droppable_box = DvnDraggableBox;
exports.dvn_rich_editor = DvnRichEditor;
exports.dvn_rich_editor_component_options = DvnRichEditorComponentOptions$1;
exports.dvn_rich_editor_new_component_options = DvnRichEditorComponentOptions;
