{"version":3,"sources":["jsdelivr-header.js","/npm/@eox/storytelling@1.9.8/src/main.js"],"names":[],"mappings":"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","file":"/npm/@eox/storytelling@1.9.8/src/main.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@eox/storytelling@1.9.8/src/main.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { LitElement, html } from \"lit\";\nimport { when } from \"lit/directives/when.js\";\nimport markdownit from \"markdown-it\";\nimport markdownitFootnote from \"markdown-it-footnote\";\nimport {\n  getCustomEleHandling,\n  loadMarkdownURL,\n  scrollAnchorClickEvent,\n  scrollIntoView,\n  renderHtmlString,\n  parseNavWithAddSection,\n  validateMarkdownAttrs,\n  addLightBoxScript,\n  addCustomSection,\n  initSavedMarkdown,\n} from \"./helpers\";\nimport DOMPurify from \"isomorphic-dompurify\";\nimport {\n  markdownItConfig,\n  markdownItDecorateImproved,\n} from \"./markdown-it-plugin\";\nimport styleEOX from \"./style.eox.js\";\nimport \"./components/editor\";\nimport {\n  DEFAULT_SENSITIVE_TAGS,\n  SAMPLE_ELEMENTS,\n  CUSTOM_EDITOR_INTERFACES,\n} from \"./enums\";\nimport _debounce from \"lodash.debounce\";\nconst md = /** @type {import(\"./types\").CustomMarkdownIt} */ (\n  markdownit({ html: true, linkify: true })\n);\n\nmd.use(markdownItDecorateImproved).use(markdownItConfig);\nmd.use(markdownitFootnote);\n/**\n * The `eox-storytelling` element enables the creation of interactive, multimedia-rich stories using Markdown and custom sections. It supports advanced features such as slot-based content, remote Markdown loading, live editing with a built-in editor, and custom initialization logic via events.\n *\n * ## Usage\n * Place `<eox-storytelling></eox-storytelling>` in your application and pass Markdown content via the `markdown` property, slot, or a remote URL using the `markdown-url` property. The component automatically renders the story, including custom sections such as maps, images, and videos, using extended Markdown syntax and HTML comments for configuration.\n *\n * ## Features\n * - **Markdown Rendering:** Supports standard and extended Markdown syntax for rich story content.\n * - **Slot Content:** Accepts Markdown via slot for flexible content injection.\n * - **Remote Markdown:** Loads Markdown from external URLs for dynamic stories.\n * - **Live Editor:** Built-in editor for live editing and preview, including image upload and section creation.\n * - **Custom Sections:** Add maps, images, videos, and more using HTML comment configuration.\n * - **Events:** Emits events such as `init` for custom initialization logic (e.g., map projection setup), and `upload:file` for handling file uploads.\n *\n * ## Custom Markdown Extensions\n * In order to add custom functionality to the Markdown rendering, include HTML comments with a specific syntax: `<!--{ key=\"value\" }-->`. Here are some of the supported extensions:\n * - **Section Configuration:** Define sections with attributes like `as`, `id`, `class`, `style`, and more.\n * - **Hero Section:** Create a full-screen hero section using `#` (Header 1) with additional attributes for images or videos.\n * - **Navigation Control:** Use the `nav` attribute to control the visibility of the navigation menu.\n * - **Custom Attributes:** Use HTML comments to define attributes for sections, such as `as`, `class`, `style`, and more.\n *\n * Read the [Markdown with Editor story](./?path=/story/elements-eox-storytelling--markdown-with-editor) for a comprehensive guide on using the editor and Markdown extensions.\n *\n * @element eox-storytelling\n */\nexport class EOxStoryTelling extends LitElement {\n  // Define properties with defaults and types\n  static get properties() {\n    return {\n      markdown: { attribute: \"markdown\", type: String },\n      markdownURL: { attribute: \"markdown-url\", type: String },\n      nav: { state: true, attribute: false, type: Array },\n      showNav: { attribute: \"show-nav\", type: Boolean },\n      showEditor: { attribute: \"show-editor\", type: String },\n      showHeroScrollIndicator: {\n        attribute: \"show-hero-scroll-indicator\",\n        type: Boolean,\n      },\n      noShadow: { attribute: \"no-shadow\", type: Boolean },\n      disableAutosave: { attribute: \"disable-autosave\", type: Boolean },\n      unstyled: { type: Boolean },\n      addCustomSectionIndex: { type: Number, state: true },\n      selectedCustomElement: { type: Object, state: true },\n    };\n  }\n\n  /**\n   * @type {HTMLElement[]} - Generated HTML Elements using markdown\n   */\n  #html;\n\n  /**\n   * Basic config\n   *\n   * @type {Object}\n   */\n  #config = {};\n\n  /**\n   * Debounce update markdown\n   *\n   * @type {Object}\n   */\n  #debounceUpdateMarkdown = null;\n  constructor() {\n    super();\n\n    this.#html = undefined;\n\n    /**\n     * @type {String} - Markdown Content\n     */\n    this.markdown = \"\";\n\n    /**\n     * @type {String} - Markdown Content URL\n     */\n    this.markdownURL = null;\n\n    /**\n     * Render the element without additional styles\n     *\n     * @type {Boolean}\n     */\n    this.unstyled = false;\n\n    /**\n     * Renders the element without a shadow root\n     *\n     * @type {Boolean}\n     */\n    this.noShadow = false;\n\n    /**\n     * Disable auto save\n     *\n     * @type {Boolean}\n     */\n    this.disableAutosave = false;\n\n    /**\n     * Enable or disable editor\n     *\n     * @type {String | \"closed\" | undefined}\n     */\n    this.showEditor = undefined;\n\n    /**\n     * Enable or disable navigation\n     *\n     * @type {Boolean}\n     */\n    this.showNav = false;\n\n    /**\n     * Enable or disable hero scroll indicator\n     *\n     * @type {Boolean}\n     */\n    this.showHeroScrollIndicator = false;\n\n    /**\n     * List of items in navigation\n     *\n     * @type {Array<Object>}\n     */\n    this.nav = [];\n\n    /**\n     * custom section index\n     *\n     * @type {Number}\n     */\n    this.addCustomSectionIndex = -1;\n\n    /**\n     * Selected custom element object\n     *\n     * @type {Object | null}\n     */\n    this.selectedCustomElement = null;\n  }\n\n  /**\n   * @param {Element} element - Dom element\n   */\n  #dispatchInitEvent(element) {\n    /**\n     * Fires when `eox-storytelling` has initialized; allowing to add custom logic\n     * regarding the integrated `eox-maps` etc. The event detail contains the initialized element.\n     */\n    this.dispatchEvent(\n      new CustomEvent(\"init\", {\n        detail: element,\n      }),\n    );\n  }\n\n  /**\n   * Dummy placeholder for file upload event dispatching\n   * as it is actually displatched from ./enums/custom-editor-interface.js\n   */\n  // @ts-expect-error Not used, since it is a dummy placeholder\n  // eslint-disable-next-line\n  #dispatchUploaded() {\n    /**\n     * Fires when a file is uploaded via the built-in editor. The event detail contains the uploaded file as well\n     * as a callback function that can be used to update the file url end handle errors.\n     */\n    this.dispatchEvent(\n      new CustomEvent(\"upload:file\", {\n        detail: \"dummy\",\n        bubbles: true,\n        composed: true,\n      }),\n    );\n  }\n\n  /**\n   * @param {Map} changedProperties - A map of changed properties.\n   */\n  async updated(changedProperties) {\n    // Attempt to fetch new markdown content from the URL if `markdownURL` changed\n    if (changedProperties.has(\"markdownURL\") && this.markdownURL) {\n      this.markdown =\n        (await loadMarkdownURL(this.markdownURL)) || this.markdown;\n      this.requestUpdate();\n    }\n\n    // Check if 'markdown' property itself has changed and generate sanitized html\n    if (changedProperties.has(\"markdown\")) {\n      if (this.markdown) {\n        this.dispatchEvent(\n          /**\n           * Fires when the markdown content has changed. The event detail contains the updated markdown string.\n           */\n          new CustomEvent(\"changed\", {\n            detail: this.markdown,\n          }),\n        );\n      }\n\n      const unsafeHTML = md.render(this.markdown);\n\n      validateMarkdownAttrs(md.attrs.sections, this);\n\n      this.#config = md.config;\n\n      if (typeof this.#config.nav === \"boolean\")\n        this.showNav = this.#config.nav;\n\n      if (this.showNav) this.nav = md.nav;\n\n      this.#html = renderHtmlString(\n        DOMPurify.sanitize(unsafeHTML, {\n          CUSTOM_ELEMENT_HANDLING: getCustomEleHandling(md),\n          ADD_TAGS: DEFAULT_SENSITIVE_TAGS,\n        }),\n        md.sections,\n        this.#dispatchInitEvent.bind(this),\n        this,\n      );\n\n      this.#html = parseNavWithAddSection(\n        this.#html,\n        this.nav,\n        this.showNav,\n        this.showEditor,\n        this,\n      );\n\n      if (this.showEditor !== undefined) {\n        const parent = this.shadowRoot || this;\n        /**\n         * @type {EOxStoryTelling}\n         */\n        const editorDOM = parent.querySelector(\"eox-storytelling-editor\");\n        /**\n         * @type {import(\"@eox/jsonform\").EOxJSONForm}\n         */\n        const jsonFormDOM = editorDOM.querySelector(\"eox-jsonform\");\n\n        // @ts-expect-error Story is not by default part of value, but only in this case\n        if (this.markdown !== jsonFormDOM?.value.Story)\n          editorDOM.markdown = this.markdown;\n      }\n\n      this.requestUpdate();\n    }\n\n    // Check if 'nav' property itself has changed and generate anchor click event\n    if (changedProperties.has(\"nav\"))\n      scrollAnchorClickEvent(this, \".navigation a\");\n  }\n\n  /**\n   * Handles changes to the slot's content, updating the component's internal state.\n   */\n  handleSlotChange() {\n    // Query the shadow DOM for the slot element\n    const slot = this.shadowRoot.querySelector(\"slot\");\n\n    if (slot) {\n      // Retrieve all nodes assigned to the slot, flattening any nested nodes\n      const slottedContent = slot.assignedNodes({ flatten: true });\n\n      // Map each node to its text content, filtering out any non-text nodes, and join into a single string\n      this.markdown = slottedContent\n        .map((node) => (node.textContent ? node.textContent : \"\"))\n        .join(\"\");\n\n      // Request an update to re-render the component with the new content\n      this.requestUpdate();\n    }\n  }\n\n  async firstUpdated() {\n    this.#debounceUpdateMarkdown = _debounce((e) => {\n      if (e.detail) {\n        this.markdown = e.detail.Story;\n        this.requestUpdate();\n      }\n    }, 1000);\n\n    if (!this.disableAutosave) {\n      initSavedMarkdown(this);\n    }\n    addLightBoxScript();\n\n    // Check if this.#html is initialized, if not, wait for it\n    if (this.#html === undefined) await this.waitForHtmlInitialization();\n    scrollIntoView(this);\n  }\n\n  // A utility function to pause execution for a given time\n  async waitForHtmlInitialization() {\n    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n    while (this.#html === undefined) await sleep(100);\n  }\n\n  /**\n   * Overrides createRenderRoot to handle shadow DOM creation based on the noShadow property.\n   */\n  createRenderRoot() {\n    return this.noShadow ? this : super.createRenderRoot();\n  }\n\n  render() {\n    const editorClass = `${\n      this.showEditor !== undefined ? \"editor-enabled\" : \"\"\n    } editor-${this.showEditor}`;\n\n    const navClass = `${this.showNav && this.nav.length ? \"nav-enabled\" : \"\"}`;\n\n    return html`\n      <slot class=\"slot-hide\" @slotchange=${this.handleSlotChange}></slot>\n      <style>\n        :host { display: block; }\n        .slot-hide { display: none; }\n        ${!this.unstyled && styleEOX}\n      </style>\n\n      <div class=\"story-telling ${editorClass} ${navClass}\">\n        <div>${when(this.#html, () => html`${this.#html}`)}</div>\n        ${when(\n          this.showEditor !== undefined,\n          () => html`\n            <eox-storytelling-editor\n              .isNavigation=${Boolean(this.showNav)}\n              .storyId=${this.id}\n              show-editor=${this.showEditor}\n              @change=${this.#debounceUpdateMarkdown}\n              .markdown=${this.markdown}\n              .disableAutosave=${this.disableAutosave}\n            ></eox-storytelling-editor>\n          `,\n        )}\n      </div>\n\n      ${when(\n        this.addCustomSectionIndex > -1,\n        () => html`\n          <div class=\"story-telling-custom-section-list\">\n            <div\n              class=\"overlay-popup\"\n              @click=${() => {\n                this.addCustomSectionIndex = -1;\n                this.selectedCustomElement = null;\n                this.requestUpdate();\n              }}\n            ></div>\n            <div class=\"story-telling-popup\">\n              <div class=\"story-telling-popup-wrapper\">\n                ${SAMPLE_ELEMENTS.map(\n                  (category) => html`\n                    <div class=\"header\">\n                      <h4>${category.name}</h4>\n                      <p>${category.elements.length}</p>\n                    </div>\n                    <hr />\n                    <div class=\"grid-container\">\n                      ${category.elements.map(\n                        (element) =>\n                          html`<div\n                            @click=${() =>\n                              addCustomSection(\n                                this.markdown,\n                                this.addCustomSectionIndex,\n                                element.markdown,\n                                element.fields,\n                                false,\n                                this,\n                              )}\n                            class=\"grid-item\"\n                          >\n                            <icon id=\"${element.id}\"></icon>\n                            <p>${element.name}</p>\n                            <style>\n                              icon#${element.id}::before {\n                                content: url(\"${element.icon}\");\n                              }\n                            </style>\n                          </div>`,\n                      )}\n                    </div>\n                  `,\n                )}\n              </div>\n              ${when(\n                this.selectedCustomElement,\n                () => html`\n                  <div class=\"story-telling-section-fields\">\n                    <div\n                      class=\"story-telling-section-fields-overlay\"\n                      @click=${() => {\n                        this.selectedCustomElement = null;\n                        this.requestUpdate();\n                      }}\n                    ></div>\n                    <div class=\"story-telling-section-fields-wrapper\">\n                      <div class=\"story-telling-section-fields-overflow\">\n                        <eox-jsonform\n                          id=\"storytelling-editor-fields\"\n                          no-shadow\n                          .schema=${this.selectedCustomElement.fields}\n                          .customEditorInterfaces=${CUSTOM_EDITOR_INTERFACES}\n                        ></eox-jsonform>\n                      </div>\n                      <div class=\"story-telling-section-submit-wrapper\">\n                        <button\n                          @click=${() =>\n                            addCustomSection(\n                              this.markdown,\n                              this.addCustomSectionIndex,\n                              this.selectedCustomElement.markdown,\n                              this.selectedCustomElement.fields,\n                              true,\n                              this,\n                            )}\n                        >\n                          Add Section\n                        </button>\n                      </div>\n                    </div>\n                  </div>\n                `,\n              )}\n            </div>\n          </div>\n        `,\n      )}\n    `;\n  }\n}\n\ncustomElements.define(\"eox-storytelling\", EOxStoryTelling);\n"]}