{"version":3,"file":"rpg-dialogue.min.js","mappings":"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","sources":["webpack://RPGDialogue/webpack/universalModuleDefinition","webpack://RPGDialogue/webpack/runtime/chunk loaded","webpack://RPGDialogue/./src/ts/DefaultDialogueRenderer.ts","webpack://RPGDialogue/./src/ts/Editor.ts","webpack://RPGDialogue/./src/ts/RPGDialogue.ts","webpack://RPGDialogue/./src/ts/RPGDialogueLogic.ts","webpack://RPGDialogue/./src/ts/RPGDialogueSequence.ts","webpack://RPGDialogue/./src/ts/TouchHandler.ts","webpack://RPGDialogue/./src/ts/detectDarkMode.ts","webpack://RPGDialogue/./src/ts/detectMobileDevice.ts","webpack://RPGDialogue/./src/ts/domHelpers.ts","webpack://RPGDialogue/./src/ts/editorHelpers.ts","webpack://RPGDialogue/./src/ts/editorRenderer.ts","webpack://RPGDialogue/./src/ts/gup.ts","webpack://RPGDialogue/./src/ts/index.ts","webpack://RPGDialogue/./src/ts/metaHelpers.ts","webpack://RPGDialogue/./src/ts/modal.ts","webpack://RPGDialogue/webpack/bootstrap","webpack://RPGDialogue/webpack/runtime/define property getters","webpack://RPGDialogue/webpack/runtime/hasOwnProperty shorthand","webpack://RPGDialogue/webpack/runtime/make namespace object","webpack://RPGDialogue/webpack/runtime/jsonp chunk loading","webpack://RPGDialogue/webpack/startup"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"RPGDialogue\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"RPGDialogue\"] = factory();\n\telse\n\t\troot[\"RPGDialogue\"] = factory();\n})(self, () => {\nreturn ","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","import { IDialogueRenderer } from \"./interfaces\";\n\nexport class DefaultDialogueRenderer implements IDialogueRenderer {\n  private questionNode: HTMLElement;\n  private optionsNode: HTMLElement;\n  // onConversationTerminated: (() => void) | null = null;\n\n  endOfConversationText: string = \"---END OF CONVERSATION---\";\n\n  /**\n   * Creates a new default dialogue renderer for quickly integrating the dialogue logic into\n   * an existing HTML document with prepared two <div> elements for displaying\n   * the question and possible answers.\n   *\n   * @param {string|HTMLElement} questionNodeId - The output container (or ID) for questions.\n   * @param {string|HTMLElement} optionsNodeId - The output container (or ID) for answer options.\n   * @constructor\n   */\n  constructor(questionNodeId: string | HTMLElement, optionsNodeId: string | HTMLElement) {\n    // }, onConversationTerminated?: () => void) {\n    this.questionNode = this.getHTMLElement(questionNodeId);\n    this.optionsNode = this.getHTMLElement(optionsNodeId);\n    // this.onConversationTerminated = onConversationTerminated;\n    if (!this.questionNode) {\n      console.warn(\"[DefaultDialogueRenderer] Warning: the passed questionNode or element id does not exist.\");\n    }\n    if (!this.optionsNode) {\n      console.warn(\"[DefaultDialogueRenderer] Warning: the passed optionsNode or element id does not exist.\");\n    }\n  }\n\n  private getHTMLElement(nodeId: string | HTMLElement): HTMLElement {\n    return typeof nodeId === \"string\" ? (document.getElementById(nodeId) as HTMLElement) : nodeId;\n  }\n\n  //---BEGIN---IDialogueRenderer------------------------------\n  /**\n   * Indicate that the current conversation has ended.\n   * @returns\n   */\n  renderConversationTerminated(): void {\n    this.setQuestionText(this.endOfConversationText, undefined);\n    // if (this.onConversationTerminated) {\n    //   this.onConversationTerminated();\n    // }\n  }\n\n  /**\n   * Set the text in the question node.\n   * @param {string} questionText - The question text to use.\n   * @param {string|null} npcName - The NPC name to use; if no name was defined this is `null`.\n   */\n  setQuestionText(questionText: string, npcName: string | null | undefined): void {\n    if (npcName) {\n      this.questionNode.innerHTML = `<span class=\"rpg-npcname\">${npcName}:</span> ${questionText}`;\n    } else {\n      this.questionNode.innerHTML = questionText;\n    }\n  }\n\n  /**\n   * Clear the options node. Just for upper level use here.\n   */\n  clearAllOptions(): void {\n    this.optionsNode.innerHTML = \"\";\n  }\n\n  /**\n   * Add a new option node with the given answer text and option index. Use\n   * the option index to send the answer.\n   *\n   * @param {number} answerText - The answer text option.\n   * @param {number} optionIndex - The answer option index in the dialogue structure.\n   * @param {function} onOptionSelected - A callback you must trigger when the option is clicked.\n   */\n  addAnswerOption(answerText: string, optionIndex: number, onOptionSelected: () => void): void {\n    var answerNode = document.createElement(\"li\");\n    var answerLinkNode = document.createElement(\"a\");\n    answerLinkNode.innerHTML = answerText;\n    answerLinkNode.setAttribute(\"href\", \"#\");\n    answerLinkNode.addEventListener(\"click\", onOptionSelected);\n    answerNode.appendChild(answerLinkNode);\n    this.optionsNode.appendChild(answerNode);\n  }\n  //---END---IDialogueRenderer------------------------------\n}\n","/**\n * A script for demonstrating the line-point-distance.\n *\n * @require PlotBoilerplate, MouseHandler, gup, dat.gui\n *\n * @author   Ikaros Kappler\n * @date     2023-07-25\n * @version  1.0.0\n **/\n\nimport { gup } from \"./gup\";\nimport { detectDarkMode } from \"./detectDarkMode\";\nimport { KeyHandler, MouseHandler, PBParams, PlotBoilerplate, XYDimension } from \"plotboilerplate\";\nimport { RPGDialogueLogic } from \"./RPGDialogueLogic\";\nimport { IDialogueConfig, IDialogueListener, IGlobalLibs, IMiniQuestionaire, IMiniQuestionaireWithPosition } from \"./interfaces\";\nimport { EditorHelper } from \"./editorHelpers\";\nimport { EditorRenderer } from \"./editorRenderer\";\nimport { TouchHandler } from \"./TouchHandler\";\nimport { FileDrop } from \"plotboilerplate/src/cjs/utils/io/FileDrop\";\nimport { Modal } from \"./modal\";\nimport { detectMobileDevice } from \"./detectMobileDevice\";\nimport { DefaultDialogueRenderer } from \"./DefaultDialogueRenderer\";\n\nexport class Editor {\n  currentMouseHandler: MouseHandler | null = null;\n  currentTouchHandler: TouchHandler | null = null;\n  editorHelpers: EditorHelper;\n  editorRenderer: EditorRenderer;\n  dialogConfig: IDialogueConfig<IMiniQuestionaireWithPosition> | null;\n  pb: PlotBoilerplate;\n  private autosaveTimer: NodeJS.Timer;\n  constructor(dialogueConfigJSONPath: string, isRecoveryFromLocalStorageActive: boolean, globalLibs: IGlobalLibs) {\n    const _self = this;\n    console.log(\"Initializing plotboilerplate\");\n    // Fetch the GET params\n    const GUP = gup();\n    const isDarkmode: boolean = detectDarkMode(GUP);\n    const isMobileDevice: boolean = detectMobileDevice(GUP);\n\n    // All config params are optional.\n    this.pb = new PlotBoilerplate(\n      PlotBoilerplate.utils.safeMergeByKeys(\n        {\n          canvas: document.getElementById(\"my-canvas\") as HTMLCanvasElement,\n          fullSize: true,\n          fitToParent: true,\n          scaleX: 1.0,\n          scaleY: 1.0,\n          rasterGrid: true,\n          drawOrigin: false,\n          rasterAdjustFactor: 2.0,\n          redrawOnResize: true,\n          defaultCanvasWidth: 1024,\n          defaultCanvasHeight: 768,\n          canvasWidthFactor: 1.0,\n          canvasHeightFactor: 1.0,\n          cssScaleX: 1.0,\n          cssScaleY: 1.0,\n          cssUniformScale: true,\n          autoAdjustOffset: true,\n          offsetAdjustXPercent: 50,\n          offsetAdjustYPercent: 50,\n          backgroundColor: isDarkmode ? \"#000000\" : \"#ffffff\",\n          enableMouse: true,\n          enableKeys: true\n        },\n        GUP\n      ) as PBParams\n    );\n\n    const boxSize: XYDimension = {\n      width: 120,\n      height: 20\n    };\n    this.editorHelpers = new EditorHelper(this, this.pb, boxSize);\n    this.editorRenderer = new EditorRenderer(this.pb, boxSize, this.editorHelpers, isDarkmode);\n\n    // +---------------------------------------------------------------------------------\n    // | On 'escape' key press un-select selected items.\n    // +-------------------------------\n    const keyHandler = new KeyHandler({ element: document.getElementsByTagName(\"body\")[0], trackAll: false }).down(\n      \"escape\",\n      () => {\n        // Esc?\n        console.log(\"Escape down\");\n        if (this.editorHelpers.selectedOption) {\n          this.editorHelpers.setSelectedOption(null);\n        } else if (this.editorHelpers.selectedNode) {\n          this.editorHelpers.setSelectedNode(null, null);\n          this.editorHelpers.setSelectedOption(null);\n        }\n      }\n    );\n\n    // +---------------------------------------------------------------------------------\n    // | Make HTML buttons a bit larger on mobile devices.\n    // +-------------------------------\n    console.debug(\"isMobileDevice\", isMobileDevice);\n    if (isMobileDevice) {\n      document.getElementsByTagName(\"body\")[0].classList.add(\"is-mobile-device\");\n    }\n\n    // +---------------------------------------------------------------------------------\n    // | The render method.\n    // +-------------------------------\n    this.pb.config.postDraw = (_draw, _fill) => {\n      if (!_self.dialogConfig) {\n        return;\n      }\n      _self.editorRenderer.renderBoxes(_self.dialogConfig);\n      _self.editorRenderer.renderConnections(_self.dialogConfig);\n    };\n\n    if (isRecoveryFromLocalStorageActive) {\n      console.debug(\"Trying to recover config from localstorage.\");\n      this.tryLoadFromLocalStorage()\n        .then(dc => {\n          _self.handleDialogConfigLoaded(dc);\n        })\n        .catch(() => {\n          console.debug(\"Loading from localstorage failed. Falling back loading from specified path.\");\n          _self.tryLoadFromJSON(dialogueConfigJSONPath, globalLibs);\n        });\n    } else {\n      _self.tryLoadFromJSON(dialogueConfigJSONPath, globalLibs);\n    }\n\n    // Install DnD with FileDrop\n    const fileDrop = new FileDrop(this.pb.eventCatcher);\n    fileDrop.onFileJSONDropped((jsonObject: object) => {\n      console.debug(\"[onFileJSONDropped] jsonObject\", jsonObject);\n      // TODO: properly convert to dialog-config\n      _self.handleDialogConfigLoaded(EditorHelper.fromObject(jsonObject));\n    });\n\n    // Also accept uploads via button\n    const importJSON = () => {\n      document.getElementById(\"input-upload-file\")?.click();\n    };\n    document.getElementById(\"b-import-json\")?.addEventListener(\"click\", importJSON);\n    document.getElementById(\"input-upload-file\")?.addEventListener(\"change\", (_evt: Event) => {\n      var fileInput = document.getElementById(\"input-upload-file\") as HTMLInputElement;\n      if (!fileInput.files || fileInput.files.length === 0) {\n        return;\n      }\n      console.log(\"inputFile\", fileInput.files[0]);\n      var reader = new FileReader();\n      reader.onload = () => {\n        const jsonText = reader.result as string;\n        console.log(reader.result);\n        _self.handleDialogConfigLoaded(EditorHelper.fromObject(JSON.parse(jsonText)));\n      };\n      reader.readAsText(fileInput.files[0]);\n    });\n\n    document.getElementById(\"b-run-test\")?.addEventListener(\"click\", () => {\n      _self.testCurrentDialogueConfig();\n    });\n\n    document.getElementById(\"b-new\")?.addEventListener(\"click\", _self.requestCreateNewGraph());\n    document.getElementById(\"b-show-json\")?.addEventListener(\"click\", _self.showJSON());\n    document.getElementById(\"b-goto-github\")?.addEventListener(\"click\", () => {\n      window.open(\"https://github.com/IkarosKappler/rpg-dialogue\", \"_blank\");\n    });\n  }\n  // END constructor\n\n  private tryStartAutosaveLoop() {\n    if (this.autosaveTimer) {\n      return;\n    }\n    const _self = this;\n    this.autosaveTimer = globalThis.setInterval(() => {\n      _self.tryAutoSave();\n    }, 10000);\n  }\n\n  private tryAutoSave() {\n    if (this.editorHelpers.domHelper.isAutoSave()) {\n      // console.log(\"Putting to localstorage.\");\n      this.putToLocalStorage();\n    }\n  }\n\n  requestCreateNewGraph(): () => void {\n    const _self = this;\n    return () => {\n      _self.editorHelpers.domHelper.modal.setTitle(\"Drop current graph?\");\n      _self.editorHelpers.domHelper.modal.setBody(`Do you really want to create a new graph and lose unsaved changes?`);\n      _self.editorHelpers.domHelper.modal.setFooter(\"\");\n      _self.editorHelpers.domHelper.modal.setActions([\n        Modal.ACTION_CANCEL,\n        {\n          label: \"Yes\",\n          action: () => {\n            _self.editorHelpers.domHelper.modal.close();\n            _self.performNewGraph();\n          }\n        }\n      ]);\n      _self.editorHelpers.domHelper.modal.open();\n    };\n  }\n\n  private performNewGraph() {\n    const newConfig: IDialogueConfig<IMiniQuestionaireWithPosition> = {\n      meta: { name: \"dialogue_A\", npcs: [{ name: \"NPC #0\" }] },\n      graph: {\n        intro: { q: \"Hello world!\", o: [{ a: \"Hello, NPC!\", next: null }], editor: { position: { x: 0, y: 0 } } }\n      }\n    };\n    this.handleDialogConfigLoaded(newConfig);\n  }\n\n  private showJSON() {\n    const _self = this;\n    return () => {\n      const removePositions = _self.editorHelpers.domHelper.isExportWithoutPositions();\n      const dConfig: IDialogueConfig<IMiniQuestionaire> | IDialogueConfig<IMiniQuestionaireWithPosition> = removePositions\n        ? EditorHelper.removePositions(_self.editorHelpers.dialogConfigWithPositions)\n        : _self.editorHelpers.dialogConfigWithPositions;\n      const jsonString = JSON.stringify(dConfig, null, 4);\n      const jsonArea = document.createElement(\"textarea\");\n      jsonArea.setAttribute(\"readonly\", \"true\");\n      jsonArea.innerHTML = jsonString;\n      jsonArea.classList.add(\"json-preview\");\n      _self.editorHelpers.domHelper.modal.setTitle(\"Current Graph as JSON\");\n      _self.editorHelpers.domHelper.modal.setBody(jsonArea);\n      _self.editorHelpers.domHelper.modal.setFooter(\"\");\n      _self.editorHelpers.domHelper.modal.setActions([Modal.ACTION_CLOSE]);\n      _self.editorHelpers.domHelper.modal.open();\n    };\n  }\n\n  /**\n   * Open a modal and test the current dialogue config (runs a RPGDialogueLogic instant).\n   */\n  testCurrentDialogueConfig() {\n    if (!this.dialogConfig) {\n      console.warn(\"Warning: cannot test null dialogue.\");\n      return;\n    }\n    const _self = this;\n    // Create this structure:\n    // <div class=\"rpg-output\">\n    //    <div class=\"rpg-output-question\"></div>\n    //    <ul class=\"rpg-output-options\"></ul>\n    // </div>\n\n    const outputContainer = document.createElement(\"div\");\n    const outputQuestion = document.createElement(\"div\");\n    const outputOptions = document.createElement(\"ul\");\n    outputContainer.classList.add(\"rpg-output\");\n    outputQuestion.classList.add(\"rpg-output-question\");\n    outputOptions.classList.add(\"rpg-output-options\");\n    outputContainer.appendChild(outputQuestion);\n    outputContainer.appendChild(outputOptions);\n\n    const dialogueListener: IDialogueListener<IMiniQuestionaireWithPosition> = (\n      _dialogueConfig: IDialogueConfig<IMiniQuestionaireWithPosition>,\n      nextNodeName: string | null,\n      _oldNodeName: string | null,\n      _selectedOptionIndex: number\n    ) => {\n      // Highlight current node in the graph editor :)\n      _self.editorHelpers.setHighlightedNode(nextNodeName);\n    };\n\n    const rpgLogic = new RPGDialogueLogic(this.dialogConfig, false);\n    rpgLogic.addDialogueChangeListener(dialogueListener);\n    const alternateStartNodeName: string | null = this.editorHelpers.selectedNodeName;\n    this.editorHelpers.setSelectedNode(null, null);\n    rpgLogic.beginConversation(new DefaultDialogueRenderer(outputQuestion, outputOptions), alternateStartNodeName);\n\n    this.editorHelpers.domHelper.modal.setTitle(\"Test\"); // Will be changed later when invoked.\n    this.editorHelpers.domHelper.modal.setBody(outputContainer);\n    this.editorHelpers.domHelper.modal.setFooter(\"\");\n    this.editorHelpers.domHelper.modal.setActions([Modal.ACTION_CLOSE]);\n    this.editorHelpers.domHelper.modal.open();\n  }\n\n  private handleDialogConfigLoaded(config: IDialogueConfig<IMiniQuestionaire>) {\n    // Check if all graph nodes have positions to render.\n    this.dialogConfig = this.editorHelpers.enrichPositions(config);\n    this.editorHelpers.enrichMetaData(this.dialogConfig);\n    // console.debug(\"Enriched meta data\", this.dialogConfig);\n    this.editorHelpers.setDialogConfig(this.dialogConfig);\n\n    // Ad DnD support for boxes.\n    if (this.currentMouseHandler) {\n      this.currentMouseHandler.destroy();\n      this.currentMouseHandler = null;\n    }\n    this.currentMouseHandler = this.editorHelpers.boxMovehandler();\n\n    // Ad DnD support for boxes.\n    if (this.currentTouchHandler) {\n      this.currentTouchHandler.destroy();\n      this.currentTouchHandler = null;\n    }\n    this.currentTouchHandler = new TouchHandler(this.pb, this.dialogConfig, this.editorHelpers);\n\n    this.pb.redraw();\n    this.tryStartAutosaveLoop();\n  }\n\n  private putToLocalStorage() {\n    const jsonString = JSON.stringify(this.dialogConfig);\n    globalThis.localStorage.setItem(\"__rpgeditor.dialogueconfig\", jsonString);\n  }\n\n  private tryLoadFromJSON(dialogueConfigJSONPath: string, globalLibs: IGlobalLibs) {\n    const _self = this;\n    RPGDialogueLogic.loadConfigFromJSON(dialogueConfigJSONPath, globalLibs).then((config: IDialogueConfig<IMiniQuestionaire>) => {\n      console.debug(\"structure\", config);\n      _self.handleDialogConfigLoaded(config);\n    });\n  }\n\n  private tryLoadFromLocalStorage(): Promise<IDialogueConfig<IMiniQuestionaireWithPosition>> {\n    return new Promise<IDialogueConfig<IMiniQuestionaireWithPosition>>((accept, reject) => {\n      const jsonString = globalThis.localStorage.getItem(\"__rpgeditor.dialogueconfig\");\n      if (!jsonString || jsonString === \"\") {\n        reject();\n      } else {\n        try {\n          const jsonObject = JSON.parse(jsonString);\n          if (!jsonObject) {\n            reject();\n            return;\n          }\n          const dialogueConfig = EditorHelper.fromObject(jsonObject);\n          accept(dialogueConfig);\n        } catch (exception) {\n          console.warn(exception);\n          reject();\n        }\n      }\n    });\n  }\n\n  // +---------------------------------------------------------------------------------\n  // | END Editor\n  // +-------------------------------\n}\n","/**\n * This is the main exported library that shozld be exposed to the browser.\n *\n * @author  Ikaros Kappler\n * @date    2023-09-07\n * @version 1.0.0\n */\n\nimport { gup } from \"./gup\";\nimport { detectDarkMode } from \"./detectDarkMode\";\nimport { RPGDialogueLogic } from \"./RPGDialogueLogic\";\nimport { RPGDOMHelpers } from \"./domHelpers\";\nimport { DialogueMetaHelpers } from \"./metaHelpers\";\nimport { Modal } from \"./modal\";\nimport { EditorHelper } from \"./editorHelpers\";\nimport { TouchHandler } from \"./TouchHandler\";\nimport { EditorRenderer } from \"./editorRenderer\";\nimport { Editor } from \"./Editor\";\nimport { RPGDialogueSequence } from \"./RPGDialogueSequence\";\nimport { DefaultDialogueRenderer } from \"./DefaultDialogueRenderer\";\n\nexport const RPGDialogue = () => ({\n  gup: gup,\n  detectDarkMode: detectDarkMode,\n  RPGDialogueLogic: RPGDialogueLogic,\n  RPGDOMHelpers: RPGDOMHelpers,\n  DialogueMetaHelpers: DialogueMetaHelpers,\n  Modal: Modal,\n  EditorHelper: EditorHelper,\n  TouchHandler: TouchHandler,\n  EditorRenderer: EditorRenderer,\n  Editor: Editor,\n  RPGDialogueSequence: RPGDialogueSequence,\n  DefaultDialogueRenderer: DefaultDialogueRenderer\n});\n","/**\n * @author  Ikaros Kappler\n * @date    2023-07-25\n * @version 1.0.0\n */\n\nimport {\n  IAnswer,\n  IDialogueConfig,\n  IDialogueListener,\n  IDialogueNodeType,\n  IDialogueRenderer,\n  IGlobalLibs,\n  IMiniQuestionaire,\n  INpcDialogueMapping,\n  INpcPathMapping\n} from \"./interfaces\";\n\nexport class RPGDialogueLogic<T extends IDialogueNodeType> {\n  name: string;\n  structure: IDialogueConfig<T>;\n  private currentQuestionaireName: string | null;\n  private currentQuestionaire: IMiniQuestionaire | null;\n  private listeners: Array<IDialogueListener<T>>;\n\n  constructor(dialogueStruct: IDialogueConfig<T>, validateStructure: boolean) {\n    this.structure = dialogueStruct;\n    this.listeners = [];\n\n    this.resetToBeginning();\n    if (validateStructure) {\n      this.validate();\n    }\n  }\n\n  addDialogueChangeListener(listener: IDialogueListener<T>) {\n    for (var i = 0; i < this.listeners.length; i++) {\n      if (this.listeners[i] === listener) {\n        return false;\n      }\n    }\n    this.listeners.push(listener);\n    return true;\n  }\n\n  removeDialogueChangeListener(listener: IDialogueListener<T>) {\n    for (var i = 0; i < this.listeners.length; i++) {\n      if (this.listeners[i] === listener) {\n        this.listeners.splice(i, 1);\n        return true;\n      }\n    }\n    return false;\n  }\n\n  private fireStateChange(nextNodeName: string | null, oldNodeName: string | null, selectedOptionIndex: number) {\n    for (var i = 0; i < this.listeners.length; i++) {\n      this.listeners[i](this.structure, nextNodeName, oldNodeName, selectedOptionIndex);\n    }\n  }\n\n  private getCurrentNpcName(): string | null {\n    const npcIndex = this.currentQuestionaire?.npcIndex ?? 0;\n    const npcName = this.structure.meta?.npcs?.length > 0 ? this.structure.meta.npcs[npcIndex].name : null;\n    return npcName;\n  }\n\n  private createSendAnswerCallback = (dialogueRenderer: IDialogueRenderer, optionIndex: number) => {\n    const _self = this;\n    var sendAnswerCallback = () => {\n      // optionIndex: number) => {\n      _self.sendAnswer(optionIndex);\n      if (_self.isEndReached()) {\n        dialogueRenderer.renderConversationTerminated();\n      }\n      dialogueRenderer.clearAllOptions();\n      if (!_self.isEndReached()) {\n        _self.loadCurrentQuestionaire(dialogueRenderer);\n      }\n    };\n    return sendAnswerCallback;\n  };\n\n  loadCurrentQuestionaire(dialogueRenderer: IDialogueRenderer): boolean {\n    if (this.currentQuestionaire) {\n      const npcName = this.getCurrentNpcName();\n      dialogueRenderer.setQuestionText(this.currentQuestionaire.q, npcName);\n      for (var i = 0; i < this.currentQuestionaire.o.length; i++) {\n        const answerCallback = this.createSendAnswerCallback(dialogueRenderer, i);\n        dialogueRenderer.addAnswerOption(this.currentQuestionaire.o[i].a, i, answerCallback);\n      }\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * Get the current mini questionaire or null if no current or next questionaire is available.\n   * @returns\n   */\n  getCurrentQuestionaire(): IMiniQuestionaire | null {\n    return this.currentQuestionaire;\n  }\n\n  /**\n   * Check if the end was reached or if there are more questions available\n   * @returns {boolean} false if there is a current question active.\n   */\n  isEndReached(): boolean {\n    return this.currentQuestionaire === null || this.currentQuestionaire === undefined;\n  }\n\n  /**\n   * Give an answer to the current questionaire. Only valid answer indices will be acceped.\n   * @param {number} index\n   * @returns {boolean} true if the the index is valid.\n   */\n  sendAnswer(index: number): boolean {\n    if (!this.currentQuestionaire || index < 0 || index >= this.currentQuestionaire.o.length) {\n      return false;\n    }\n    const oldQuestionaireName = this.currentQuestionaireName;\n    const selectedAnswer: IAnswer = this.currentQuestionaire.o[index];\n    if (!selectedAnswer) {\n      return false;\n    }\n    if (!selectedAnswer.next) {\n      this.currentQuestionaireName = null;\n      this.currentQuestionaire = null;\n    } else {\n      this.currentQuestionaireName = selectedAnswer.next;\n      const nextQuestionaire: T = this.structure.graph[this.currentQuestionaireName];\n      // Can be the final one!\n      if (!nextQuestionaire.o || nextQuestionaire.o.length === 0) {\n        this.currentQuestionaireName = null;\n        this.currentQuestionaire = null;\n      } else {\n        this.currentQuestionaire = nextQuestionaire;\n      }\n    }\n    this.fireStateChange(this.currentQuestionaireName, oldQuestionaireName, index);\n    // console.log(\"Next questionaire\", this.currentQuestionaire);\n    return true;\n  }\n\n  /**\n   * Find the initial mini questionaire.\n   */\n  resetToBeginning(alternateStartNodeName?: string | null) {\n    this.currentQuestionaireName = alternateStartNodeName ?? \"intro\";\n    console.log(\"Using node node: \", this.currentQuestionaireName, \"param\", alternateStartNodeName);\n    this.currentQuestionaire = this.structure.graph[this.currentQuestionaireName];\n    if (!this.currentQuestionaire) {\n      throw \"Cannot initialize RPGDialogueLogic: structure does not have an initial ('intro') entry\";\n    }\n  }\n\n  /**\n   * Check if the current dialogue is still valid or reached its end.\n   */\n  private validate() {\n    // ...\n  }\n\n  /**\n   * This is a convenient function for quickly integrating the dialogue logic into\n   * an existing HTML document with prepared two <div> elements for displaying\n   * the question and possible answers.\n   *\n   * @param {IDialogueRenderer} dialogueRenderer - The dialogue renderer to use.\n   * @param {string?} alternateStartNodeName - If you don't want to start at 'intro' specify your start node name here.\n   * @returns\n   */\n  beginConversation(dialogueRenderer: IDialogueRenderer, alternateStartNodeName?: string | null): void {\n    console.log(\"beginConversation\", alternateStartNodeName);\n    const _self = this;\n    // Initialize the first question.\n    this.resetToBeginning(alternateStartNodeName);\n    this.loadCurrentQuestionaire(dialogueRenderer);\n    this.fireStateChange(this.currentQuestionaireName, null, -1);\n  }\n\n  /**\n   * Load the dialogue structure from the JSON document at the given path.\n   *\n   * @param {string} path\n   * @returns {Promise<RPGDialogueLogic>}\n   */\n  static loadConfigFromJSON<T extends IDialogueNodeType>(path: string, globalLibs: IGlobalLibs): Promise<IDialogueConfig<T>> {\n    // console.log(\"axios\", axios);\n    return new Promise<IDialogueConfig<T>>((accept: (dialogueStruct: IDialogueConfig<T>) => void, reject: () => void) => {\n      globalLibs.axios\n        .get(path)\n        .then(response => {\n          // handle success\n          console.log(response);\n          // Validate response data?\n          accept(response.data);\n        })\n        .catch(error => {\n          // handle error\n          console.log(error);\n          reject();\n        })\n        .finally(() => {\n          // always executed\n        });\n    });\n  }\n\n  /**\n   * Load the dialogue structure from the JSON document at the given path.\n   *\n   * @param {string} path\n   * @returns {Promise<RPGDialogueLogic>}\n   */\n  static loadFromJSON<T extends IDialogueNodeType>(path: string, globalLibs: IGlobalLibs): Promise<RPGDialogueLogic<T>> {\n    return new Promise<RPGDialogueLogic<T>>((accept: (dialogueStruct: RPGDialogueLogic<T>) => void, reject: () => void) => {\n      RPGDialogueLogic.loadConfigFromJSON<T>(path, globalLibs).then((struct: IDialogueConfig<T>) => {\n        accept(new RPGDialogueLogic<T>(struct, true));\n      });\n    });\n  }\n\n  /**\n   * Pass an array of { npcName: string; path: string } objects and get an\n   * array of { npcName: string; dialogue: RPGDialogueLogic<T> }.\n   *\n   * @param paths\n   * @returns\n   */\n  static loadAllFromJSON<T extends IDialogueNodeType>(\n    paths: INpcPathMapping,\n    globalLibs: IGlobalLibs\n  ): Promise<INpcDialogueMapping<T>> {\n    const promises: Array<Promise<RPGDialogueLogic<T>>> = [];\n    const npcNames = Object.keys(paths);\n    console.log(\"npcNames\", npcNames);\n    for (var i = 0; i < npcNames.length; i++) {\n      const npcName = npcNames[i];\n      const npcPath = paths[npcName];\n      promises.push(RPGDialogueLogic.loadFromJSON(npcPath, globalLibs));\n    }\n    return new Promise((accept, reject) => {\n      Promise.all(promises)\n        .then((dialogues: RPGDialogueLogic<T>[]) => {\n          // tre-map received dialogues back to their npc names\n          // const mapping = dialogues.map((dialogue, index) => ({ npcName: paths[index], dialogue: dialogue }));\n          const mapping: INpcDialogueMapping<T> = {};\n          for (var i = 0; i < npcNames.length; i++) {\n            const name: string = npcNames[i];\n            mapping[name] = dialogues[i];\n          }\n          accept(mapping);\n        })\n        .catch(reject);\n    });\n  }\n}\n","/**\n * A dialogue sequence will use multiple dialogues (RPGDialogueLogic) and\n * put them together to a 'scene experience' with multiple NPCs.\n *\n * E.g.: first talk to NPC A and when that is done talking to NPC B is\n * available.\n */\n\nimport { RPGDialogueLogic } from \"./RPGDialogueLogic\";\nimport { IDialogueConfig, IDialogueListener, IDialogueNodeType, IDialogueRenderer, SequenceMatchingRule } from \"./interfaces\";\n\nexport class RPGDialogueSequence<T extends IDialogueNodeType> {\n  private dialogues: Record<string, RPGDialogueLogic<T>>;\n  private rules: Array<SequenceMatchingRule>;\n\n  /**\n   * Create a sequence from a set of dialgues, each mapped to an NPC name.\n   * @param {Record<string, RPGDialogueLogic<T>>} dialogues\n   */\n  constructor(dialogues: Record<string, RPGDialogueLogic<T>>) {\n    // NOOP\n    this.dialogues = dialogues;\n    this.rules = [];\n    const keys = Object.keys(this.dialogues);\n    for (var i in keys) {\n      const npcName = keys[i];\n      const dlg = this.dialogues[npcName];\n      dlg.addDialogueChangeListener(this.handleDialogueStateChanged(npcName));\n    }\n  }\n\n  private handleDialogueStateChanged(npcName: string): IDialogueListener<T> {\n    return (\n      _dialogueConfig: IDialogueConfig<T>,\n      nextNodeName: string | null,\n      oldNodeName: string | null,\n      selectedOptionIndex: number\n    ) => {\n      // Try to locate matching callback.\n      const matchingRule = this.findRule(npcName, nextNodeName);\n      console.log(\"matchingRule found?\", matchingRule !== null);\n      if (matchingRule) {\n        matchingRule.callback();\n      }\n    };\n  }\n\n  private findRule(npcName: string, nodeName: string): SequenceMatchingRule | null {\n    for (var i in this.rules) {\n      const rule = this.rules[i];\n      if (rule.npcName === npcName && rule.nodeName === nodeName) {\n        return rule;\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Add a rule for node changes to this sequence. Use nodeName=null for end-of-conversation.\n   * The passed callback will be triggered if any of the passed dialogues\n   * enters a state that matches the given rule.\n   *\n   * @param npcName\n   * @param nodeName\n   * @param callback\n   */\n  addRule(npcName: string, nodeName: string | null, callback: (npcName?: string, nodeName?: string) => void) {\n    this.rules.push({ npcName, nodeName, callback });\n  }\n\n  beginConversation(dialogueRenderer: IDialogueRenderer, npcName: string, alternateStartNodeName?: string) {\n    const dialogue = this.dialogues[npcName];\n    dialogue.beginConversation(dialogueRenderer, alternateStartNodeName);\n  }\n}\n","/**\n * A wrapper class for AlloyFinger.\n *\n * @author  Ikaros Kappler\n * @date    2023-07-31\n * @version 1.0.0\n */\n\nimport { AlloyFingerOptions } from \"alloyfinger-typescript/src/cjs/alloy_finger\";\nimport AlloyFinger from \"alloyfinger-typescript\";\nimport { PlotBoilerplate, Vertex, XYCoords } from \"plotboilerplate\";\nimport { EditorHelper } from \"./editorHelpers\";\nimport { IDialogueConfig, IMiniQuestionaireWithPosition, IOptionIdentifyer } from \"./interfaces\";\n\nexport class TouchHandler {\n  private alloyFinger: AlloyFinger;\n  wasTouchUsed: boolean = false;\n\n  constructor(\n    pb: PlotBoilerplate,\n    dialogConfigWithPositions: IDialogueConfig<IMiniQuestionaireWithPosition>,\n    editorHelper: EditorHelper\n  ) {\n    const _self = this;\n\n    // Install a touch handler on the canvas.\n    const relPos = (pos: XYCoords): XYCoords => {\n      const bounds = pb.canvas.getBoundingClientRect();\n      return { x: pos.x - bounds.left, y: pos.y - bounds.top };\n    };\n\n    var draggedNodeName: string | null = null;\n    var draggedNode: IMiniQuestionaireWithPosition | null = null;\n    var draggedOption: IOptionIdentifyer | null;\n    var wasDragged: boolean = false;\n\n    var touchMovePos: Vertex | undefined | null = null;\n    var touchDownPos: Vertex | undefined | null = null;\n    const clearTouch = () => {\n      touchMovePos = null;\n      touchDownPos = null;\n      draggedNodeName = null;\n    };\n    const afProps: AlloyFingerOptions = {\n      touchStart: (evt: TouchEvent) => {\n        console.log(\"Touchstart\");\n        _self.wasTouchUsed = true;\n        if (evt.touches.length == 1) {\n          touchMovePos = new Vertex(relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }));\n          touchDownPos = new Vertex(relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }));\n          draggedNodeName = editorHelper.locateNodeBoxNameAtPos(pb.transformMousePosition(touchMovePos.x, touchMovePos.y));\n          if (draggedNodeName) {\n            draggedNode = dialogConfigWithPositions.graph[draggedNodeName];\n          } else {\n            draggedOption = editorHelper.locateOptionBoxNameAtPos(pb.transformMousePosition(touchMovePos.x, touchMovePos.y));\n          }\n          wasDragged = false;\n        }\n      },\n      touchMove: (evt: TouchEvent) => {\n        console.log(\"touchMove\");\n        _self.wasTouchUsed = true;\n        if (evt.touches.length == 1 && draggedNode) {\n          evt.preventDefault();\n          evt.stopPropagation();\n          if (!touchDownPos || !touchMovePos) {\n            return;\n          }\n          var rel: XYCoords = relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY });\n          var trans: XYCoords = pb.transformMousePosition(rel.x, rel.y);\n          var diff: Vertex = new Vertex(pb.transformMousePosition(touchMovePos.x, touchMovePos.y)).difference(trans);\n          if (draggedNode.editor?.position) {\n            draggedNode.editor.position.x += diff.x;\n            draggedNode.editor.position.y += diff.y;\n          }\n          touchMovePos = new Vertex(relPos({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }));\n          wasDragged = true;\n          pb.redraw();\n        }\n      },\n      touchEnd: (evt: TouchEvent) => {\n        console.log(\"touchEnd\");\n        _self.wasTouchUsed = true;\n        // Note: e.touches.length is 0 here\n        if (draggedNode) {\n          if (!touchDownPos) {\n            return;\n          }\n          if (!wasDragged) {\n            wasDragged = false;\n            if (draggedNode) {\n              if (editorHelper.selectedOption) {\n                // reconnect?\n                if (draggedNodeName) {\n                  editorHelper.handleOptionReconnect(draggedNodeName);\n                }\n              } else {\n                editorHelper.setSelectedOption(null, false);\n                editorHelper.setSelectedNode(draggedNodeName, draggedNode);\n              }\n            } else {\n              // Option can be null, too.\n              editorHelper.setSelectedOption(draggedOption, true);\n              editorHelper.setSelectedNode(null, null);\n            }\n          }\n        }\n        clearTouch();\n      },\n      touchCancel: (evt: TouchEvent) => {\n        console.log(\"touchCancel\");\n        _self.wasTouchUsed = true;\n        clearTouch();\n      }\n    } as unknown as AlloyFingerOptions; // END afProps\n\n    /* tslint:disable-next-line */\n    _self.alloyFinger = globalThis.createAlloyFinger(pb.eventCatcher ? pb.eventCatcher : pb.canvas, afProps);\n  }\n\n  destroy() {\n    this.alloyFinger.destroy();\n  }\n}\n\n/**\n * A class simulating non existing touchenter and touchleave events.\n * Inspired by\n *    https://stackoverflow.com/questions/23111671/touchenter-and-touchleave-events-support\n */\ntype TouchEnterLeaveListener = (element: HTMLElement, event: TouchEvent) => void;\nexport class TouchEnterLeaveHandler {\n  private onTouchLeaveEvents: Array<[string, TouchEnterLeaveListener]> = [];\n  private onTouchEnterEvents: Array<[string, TouchEnterLeaveListener]> = [];\n\n  constructor() {\n    this._init();\n  }\n\n  onTouchEnter(selector: string, fn: TouchEnterLeaveListener) {\n    this.onTouchEnterEvents.push([selector, fn]);\n    return () => {\n      this.onTouchEnterEvents.slice().map((e, i) => {\n        if (e[0] === selector && e[1] === fn) {\n          this.onTouchEnterEvents.splice(1, i);\n        }\n      });\n    };\n  }\n\n  onTouchLeave(selector: string, fn: TouchEnterLeaveListener) {\n    this.onTouchLeaveEvents.push([selector, fn]);\n    return function () {\n      this.onTouchLeaveEvents.slice().map((e, i) => {\n        if (e[0] === selector && e[1] === fn) {\n          this.onTouchLeaveEvents.splice(1, i);\n        }\n      });\n    };\n  }\n\n  private _init() {\n    let lastTouchLeave: Element | null;\n    let lastTouchEnter: Element | null;\n    const _self = this;\n    document.addEventListener(\"touchmove\", e => {\n      const el: Element | null = document.elementFromPoint(e.touches[0].clientX, e.touches[0].clientY);\n      if (!el) {\n        return;\n      }\n\n      _self.onTouchLeaveEvents.map(event => {\n        if (el != lastTouchEnter && lastTouchEnter && lastTouchEnter.matches(event[0])) {\n          if (lastTouchEnter !== lastTouchLeave) {\n            event[1](lastTouchEnter as HTMLElement, e);\n            lastTouchLeave = lastTouchEnter;\n            lastTouchEnter = null;\n          }\n        }\n      });\n\n      _self.onTouchEnterEvents.map(event => {\n        if (el.matches(event[0]) && el !== lastTouchEnter) {\n          lastTouchEnter = el;\n          lastTouchLeave = null;\n          event[1](el as HTMLElement, e);\n        }\n      });\n    });\n  }\n}\n\n// Test\n// onTouchEnter('.area',function(el,e){\n//   el.classList.add('hover')\n// })\n// onTouchLeave('.area',function(el,e){\n//   el.classList.remove('hover')\n// })\n","/**\n * @author  Ikaros Kappler\n * @date    2021-11-07\n * @version 1.0.0\n *\n * @param {Record<string,string>} GUP\n * @returns {boolean}\n */\n\nexport const detectDarkMode = (GUP: Record<string, string>): boolean => {\n  // Respect overrides\n  if (typeof GUP !== \"undefined\" && GUP.hasOwnProperty(\"darkmode\") && GUP[\"darkmode\"]) {\n    var overrideValue = GUP[\"darkmode\"];\n    if (overrideValue === \"0\" || overrideValue.toLowerCase() === \"false\") {\n      return false;\n    } else if (overrideValue === \"1\" || overrideValue.toLowerCase() === \"true\") {\n      return true;\n    }\n  }\n  var hours = new Date().getHours();\n  var isDayTime = hours > 6 && hours < 18;\n  return !isDayTime;\n};\n","/**\n * @date 2023-08-23\n */\n\nexport const detectMobileDevice = (GUP: object): boolean => {\n  // Source\n  //    http://detectmobilebrowsers.com/\n  if (typeof GUP !== \"undefined\" && GUP.hasOwnProperty(\"touchdevice\") && GUP[\"touchdevice\"]) {\n    var overrideValue = GUP[\"touchdevice\"];\n    if (overrideValue === \"0\" || overrideValue.toLowerCase() === \"false\") {\n      return false;\n    } else if (overrideValue === \"1\" || overrideValue.toLowerCase() === \"true\") {\n      return true;\n    }\n  }\n  const userAgent = navigator.userAgent || (navigator as any).vendor || (window as any).opera;\n  return (\n    /(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(\n      userAgent\n    ) ||\n    /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(\n      userAgent.substr(0, 4)\n    )\n  );\n};\n","/**\n * A script for demonstrating the line-point-distance.\n *\n * @require PlotBoilerplate, MouseHandler, gup, dat.gui\n *\n * @author   Ikaros Kappler\n * @date     2023-08-01\n * @version  1.0.0\n **/\n\nimport { TouchEnterLeaveHandler } from \"./TouchHandler\";\nimport { EditorHelper } from \"./editorHelpers\";\nimport { IAnswer, IDialogueConfig, IMiniQuestionaire, IMiniQuestionaireWithPosition } from \"./interfaces\";\nimport { Modal } from \"./modal\";\n\nexport class RPGDOMHelpers {\n  editorHelpers: EditorHelper;\n\n  editorElement: HTMLDivElement;\n  keyElement: HTMLInputElement;\n  npcElement: HTMLSelectElement;\n  qElement: HTMLInputElement;\n\n  optionsElement: HTMLDivElement;\n\n  modal: Modal;\n\n  currentNodeName: string | null;\n  currentGraphNode: IMiniQuestionaire | null;\n\n  currentDraggedAnswerIndex: number = -1;\n  currentDropAnswerIndex: number = -1;\n\n  touchEnterLeaveHandler: TouchEnterLeaveHandler;\n\n  constructor(editorHelpers: EditorHelper) {\n    this.editorHelpers = editorHelpers;\n    this.touchEnterLeaveHandler = new TouchEnterLeaveHandler();\n\n    this.editorElement = document.getElementById(\"attribute-editor\") as HTMLDivElement;\n    this.optionsElement = document.getElementById(\"e-options-container\") as HTMLDivElement;\n\n    this.keyElement = this.editorElement.querySelector(\"input#e-key\") as HTMLInputElement;\n    this.npcElement = this.editorElement.querySelector(\"select#e-npc-index\") as HTMLSelectElement;\n    this.qElement = this.editorElement.querySelector(\"textarea#e-q\") as HTMLInputElement;\n\n    this.qElement.addEventListener(\"change\", this.handleQChanged(this));\n    this.npcElement.addEventListener(\"change\", this.handleNPCIndexChanged(this));\n    this.keyElement.addEventListener(\"change\", this.handleKeyChanged(this));\n\n    this.modal = new Modal();\n\n    document.getElementById(\"b-export-json\")?.addEventListener(\"click\", this.exportJSON(this));\n    document.getElementById(\"b-add-answer-option\")?.addEventListener(\"click\", this.addAnswerOption(this));\n    document.getElementById(\"b-add-dialogue-node\")?.addEventListener(\"click\", this.addDialogueNode(this));\n    document.getElementById(\"b-delete-dialogue-node\")?.addEventListener(\"click\", this.requestRemoveDialogueNode(this));\n  }\n\n  isExportWithoutPositions(): boolean {\n    const checkbox = document.getElementById(\"cb-export-without-positions\") as HTMLInputElement;\n    return checkbox.checked;\n  }\n\n  isAutoSave(): boolean {\n    const checkbox = document.getElementById(\"cb-use-localstorage\") as HTMLInputElement;\n    return checkbox.checked;\n  }\n\n  exportJSON(_self: RPGDOMHelpers): () => void {\n    return () => {\n      const removePositions = _self.isExportWithoutPositions();\n      const dConfig: IDialogueConfig<IMiniQuestionaire> | IDialogueConfig<IMiniQuestionaireWithPosition> = removePositions\n        ? EditorHelper.removePositions(_self.editorHelpers.dialogConfigWithPositions)\n        : _self.editorHelpers.dialogConfigWithPositions;\n      const jsonString = JSON.stringify(dConfig);\n      var blob = new Blob([jsonString], { type: \"application/json\" });\n      var url = URL.createObjectURL(blob);\n      var a = document.createElement(\"a\");\n      a.href = url;\n      a.download = \"dialog-config.json\";\n      a.textContent = \"Download backup.json\";\n      a.click();\n    };\n  }\n\n  addAnswerOption(_self: RPGDOMHelpers): () => void {\n    return () => {\n      if (!_self.currentGraphNode) {\n        console.warn(\"Warnign: cannot add answer options to null.\");\n        return;\n      }\n      const newOption: IAnswer = {\n        a: \"\",\n        next: null\n      };\n      _self.currentGraphNode.o.push(newOption);\n      _self.updateAnswerOptions();\n      _self.editorHelpers.pb.redraw();\n    };\n  }\n\n  private addDialogueNode(_self: RPGDOMHelpers): () => void {\n    return () => {\n      _self.editorHelpers.addNewDialogueNode();\n    };\n  }\n\n  private requestRemoveDialogueNode(_self: RPGDOMHelpers): () => void {\n    return () => {\n      _self.modal.setTitle(\"Delete option?\");\n      _self.modal.setBody(`Do you really want to delete the current dialoge node '${_self.currentNodeName}'?`);\n      _self.modal.setFooter(\"\");\n      _self.modal.setActions([\n        Modal.ACTION_CANCEL,\n        {\n          label: \"Yes\",\n          action: () => {\n            _self.modal.close();\n            _self.removeDialogueNode();\n          }\n        }\n      ]);\n      _self.modal.open();\n    };\n  }\n\n  private removeDialogueNode() {\n    if (!this.currentNodeName) {\n      return;\n    }\n    this.editorHelpers.removeNewDialogueNode(this.currentNodeName);\n    this.toggleVisibility(false);\n  }\n\n  toggleVisibility(isVisible: boolean) {\n    if (isVisible) {\n      this.editorElement.classList.remove(\"d-none\");\n    } else {\n      this.editorElement.classList.add(\"d-none\");\n    }\n  }\n\n  private handleQChanged(_self: RPGDOMHelpers): (changeEvent: Event) => void {\n    return (changeEvent: Event) => {\n      if (!_self.currentGraphNode) {\n        return;\n      }\n      _self.currentGraphNode.q = (changeEvent.target as HTMLInputElement).value;\n      _self.editorHelpers.pb.redraw();\n    };\n  }\n\n  private handleNPCIndexChanged(_self: RPGDOMHelpers): (changeEvent: Event) => void {\n    return (_changeEvent: Event) => {\n      if (!_self.currentGraphNode) {\n        return;\n      }\n      let newIndex: number = parseInt(this.npcElement.value);\n      if (Number.isNaN(newIndex)) {\n        newIndex = -1;\n      }\n      _self.currentGraphNode.npcIndex = newIndex;\n    };\n  }\n\n  private handleKeyChanged(_self: RPGDOMHelpers): (changeEvent: Event) => void {\n    return (_changeEvent: Event) => {\n      if (!_self.currentNodeName) {\n        return;\n      }\n      let newName: string = this.keyElement.value;\n      if (!newName || (newName = newName.trim()).length === 0) {\n        return;\n      }\n      const renameSuccessful = _self.editorHelpers.renameGraphNode(_self.currentNodeName, newName);\n      if (renameSuccessful) {\n        _self.currentNodeName = newName;\n      }\n    };\n  }\n\n  private handleATextChanged(_self: RPGDOMHelpers, answer: IAnswer): (changeEvent: Event) => void {\n    return (changeEvent: Event) => {\n      answer.a = (changeEvent.target as HTMLInputElement).value;\n      _self.editorHelpers.pb.redraw();\n    };\n  }\n\n  private handleASuccessorChanged(_self: RPGDOMHelpers, answer: IAnswer): (changeEvent: Event) => void {\n    return (changeEvent: Event) => {\n      answer.next = (changeEvent.target as HTMLInputElement).value;\n      _self.editorHelpers.pb.redraw();\n    };\n  }\n\n  updateAnswerOptions() {\n    this.showAnswerOptions(this.currentNodeName, this.currentGraphNode);\n  }\n\n  getSelectedNpcIndex() {\n    return typeof this.currentGraphNode?.npcIndex === \"undefined\" || Number.isNaN(this.currentGraphNode.npcIndex)\n      ? 0\n      : this.currentGraphNode.npcIndex;\n  }\n\n  updateNpcSelector() {\n    if (!this.currentGraphNode) {\n      return;\n    }\n    this.npcElement.innerHTML = \"\";\n    const curNpcIndex: number = this.getSelectedNpcIndex();\n    // console.log(\"this.currentGraphNode.npcIndex\", this.currentGraphNode.npcIndex, \"curNpcIndex\", curNpcIndex);\n    for (var i = 0; i < this.editorHelpers.dialogConfigWithPositions.meta.npcs.length; i++) {\n      const npcOption = document.createElement(\"option\");\n      npcOption.setAttribute(\"value\", `${i}`);\n      if (i === 0) {\n        npcOption.innerHTML = `${this.editorHelpers.dialogConfigWithPositions.meta.npcs[i].name} (default)`;\n      } else {\n        npcOption.innerHTML = this.editorHelpers.dialogConfigWithPositions.meta.npcs[i].name;\n      }\n      if (i === curNpcIndex) {\n        npcOption.setAttribute(\"selected\", \"true\");\n        npcOption.selected = true;\n      }\n      this.npcElement.appendChild(npcOption);\n    }\n    this.npcElement.value = `${curNpcIndex}`;\n    this.npcElement.setAttribute(\"value\", `${curNpcIndex}`);\n  }\n\n  toggleDragEnterStyles(target: HTMLElement) {\n    // console.log(\"toggleDragEnterStyles\");\n    const answerIndex = this.currentDraggedAnswerIndex;\n    const dropIndex = parseInt(target.getAttribute(\"data-dropindex\") || \"\");\n    if (target.classList.contains(\"droppable\") && answerIndex !== dropIndex && answerIndex + 1 !== dropIndex) {\n      target.classList.add(\"dragover\");\n    }\n  }\n\n  toggleDragLeaveStyles(target: HTMLElement) {\n    console.log(\"toggleDragLeaveStyles\");\n    if (target.classList.contains(\"droppable\")) {\n      target.classList.remove(\"dragover\");\n    }\n  }\n\n  showAnswerOptions(nodeName: string | null, graphNode: IMiniQuestionaireWithPosition | null) {\n    const _self = this;\n    if (!nodeName) {\n      // console.warn(\"Warning: cannot show answer options for null node.\");\n      return;\n    }\n    this.currentNodeName = nodeName;\n    this.currentGraphNode = graphNode;\n\n    this.keyElement.setAttribute(\"value\", nodeName ? nodeName : \"\");\n    this.keyElement.value = nodeName ? nodeName : \"\";\n    // console.log(\"showAnswerOptions\", this.currentGraphNode);\n    this.updateNpcSelector();\n    this.optionsElement.innerHTML = \"\";\n    this.npcElement.value = !graphNode || Number.isNaN(graphNode.npcIndex) ? \"0\" : `${graphNode.npcIndex}`;\n    this.qElement.setAttribute(\"value\", graphNode ? graphNode.q : \"\");\n    this.qElement.value = graphNode ? graphNode.q : \"\";\n    if (!graphNode) {\n      return;\n    }\n\n    const onDragOver = (ev: DragEvent) => {\n      console.log(\"ondragover\", ev.target);\n      ev.preventDefault();\n      const target = ev.target as HTMLDivElement;\n      _self.toggleDragEnterStyles(target);\n    };\n    const onDragLeave = (ev: DragEvent) => {\n      console.log(\"ondragleave\", ev.target);\n      ev.preventDefault();\n      const target = ev.target as HTMLDivElement;\n      _self.toggleDragLeaveStyles(target);\n    };\n\n    /**\n     * Native browser DnD does not support touch events.\n     * So we need a workaround using our custom TouchEnterLeaverHandler here.\n     */\n    _self.touchEnterLeaveHandler.onTouchEnter(\".a-droparea\", (element: HTMLElement) => {\n      console.log(\"onTouchEnter\", element);\n      if (!element.classList.contains(\"a-droparea\")) {\n        return;\n      }\n      _self.currentDropAnswerIndex = parseInt(element.getAttribute(\"data-dropIndex\") ?? \"\");\n      _self.toggleDragEnterStyles(element);\n    });\n    _self.touchEnterLeaveHandler.onTouchLeave(\".a-droparea\", (element: HTMLElement) => {\n      console.log(\"onTouchLeave\", element);\n      _self.currentDropAnswerIndex = -1;\n      _self.toggleDragLeaveStyles(element);\n    });\n\n    const drop = (ev: DragEvent) => {\n      console.log(\"Drop\", ev);\n      ev.preventDefault();\n      const target = ev.target as HTMLDivElement;\n      // const answerIndex = parseInt(ev.dataTransfer.getData(\"answerindex\"));\n      const answerIndex = _self.currentDraggedAnswerIndex;\n      var dropIndex = parseInt(target.getAttribute(\"data-dropindex\") ?? \"\");\n      console.log(\"Move\", answerIndex, \"to\", dropIndex);\n      // target.appendChild(document.getElementById(data));\n\n      if (!target.classList.contains(\"droppable\") || answerIndex === dropIndex || answerIndex + 1 === dropIndex) {\n        // No real change\n        return;\n      }\n      _self.performDrop(answerIndex, dropIndex);\n    };\n\n    const isTouchDevice: boolean = Boolean(this.editorHelpers.editor.currentTouchHandler?.wasTouchUsed);\n    const dropArea: HTMLDivElement = this.makeADropArea(0, drop, onDragOver, onDragLeave);\n    this.optionsElement.appendChild(dropArea);\n\n    for (var i = 0; i < graphNode.o.length; i++) {\n      const option: IAnswer = graphNode.o[i];\n\n      const answerWrapperElement = document.createElement(\"div\") as HTMLDivElement;\n      const answerControlsElement = this.makeAnswerControlElement(i, isTouchDevice);\n\n      const answerElement = document.createElement(\"div\") as HTMLDivElement;\n      const labelElement = document.createElement(\"div\") as HTMLDivElement;\n      const textElement = document.createElement(\"textarea\") as HTMLTextAreaElement;\n      const selectElement = this.createNodeSelectElement(nodeName, option.next);\n      labelElement.innerHTML = `A#${i}`;\n      labelElement.classList.add(\"e-label\");\n      textElement.innerHTML = option.a;\n\n      answerElement.appendChild(labelElement);\n      answerElement.appendChild(textElement);\n      answerElement.appendChild(selectElement);\n\n      const handleDragStart = (ev: DragEvent) => {\n        // console.log(\"handleDragStart\");\n        _self.currentDraggedAnswerIndex = parseInt((ev.target as HTMLDivElement).getAttribute(\"data-answerindex\") ?? \"\");\n        // console.log(\"handleDragStart\", _self.currentDraggedAnswerIndex);\n        ev.dataTransfer && ev.dataTransfer.setData(\"answerindex\", `${_self.currentDraggedAnswerIndex}`);\n      };\n\n      const handleTouchDragStart = (ev: TouchEvent) => {\n        ev.preventDefault(); // Is this required?\n        var dragStartElement = ev.target as HTMLElement;\n        _self.currentDraggedAnswerIndex = parseInt(dragStartElement.getAttribute(\"data-answerindex\") ?? \"\");\n        if (Number.isNaN(_self.currentDraggedAnswerIndex)) {\n          // touchStart on touch devices is a bit different than dragStart on Desktop devives.\n          // Try to find enclosing draggable element\n          if (dragStartElement.classList.contains(\"a-dnd-element\")) {\n            dragStartElement = (dragStartElement.parentElement as HTMLElement).parentElement as HTMLElement;\n          }\n          // This should not be a node of class 'answer-wrapper-element' and draggable=true\n          if (!dragStartElement.classList.contains(\"answer-wrapper-element\") || !dragStartElement.getAttribute(\"draggable\")) {\n            console.log(\"Cannot find draggable element.\");\n            return;\n          }\n          _self.currentDraggedAnswerIndex = parseInt(dragStartElement.getAttribute(\"data-answerindex\") ?? \"\");\n        }\n        // console.log(\"handleTouchDragStart\", _self.currentDraggedAnswerIndex);\n      };\n\n      const handleTouchDragEnd = (_ev: TouchEvent) => {\n        _self.performDrop(_self.currentDraggedAnswerIndex, _self.currentDropAnswerIndex);\n      };\n      answerWrapperElement.classList.add(\"answer-wrapper-element\");\n      // answerWrapperElement.setAttribute(\"data-answerindex\", `${i}`);\n\n      if (isTouchDevice) {\n        // Regular 'mouse' or Desktop device.\n        // No additional listeners to install.\n      } else {\n        // The TouchHandler already received an only-touch event, so we are\n        // probably currently running on a touch device\n        if (answerControlsElement.dndHandleElement) {\n          answerControlsElement.dndHandleElement.setAttribute(\"draggable\", \"true\");\n          answerControlsElement.dndHandleElement.addEventListener(\"dragstart\", handleDragStart);\n          answerControlsElement.dndHandleElement.addEventListener(\"touchstart\", handleTouchDragStart);\n          answerControlsElement.dndHandleElement.addEventListener(\"touchend\", handleTouchDragEnd);\n          answerControlsElement.dndHandleElement.setAttribute(\"data-answerindex\", `${i}`);\n        }\n      }\n      answerWrapperElement.appendChild(answerElement);\n      answerWrapperElement.appendChild(answerControlsElement.container);\n\n      const dropArea = this.makeADropArea(i + 1, drop, onDragOver, onDragLeave);\n\n      this.optionsElement.appendChild(answerWrapperElement);\n      this.optionsElement.appendChild(dropArea);\n\n      textElement.addEventListener(\"change\", this.handleATextChanged(this, option));\n      selectElement.addEventListener(\"change\", this.handleASuccessorChanged(this, option));\n    }\n  }\n\n  /**\n   * Create a new answer element (consisting of labels, input fields and buttons).\n   * If `isTouchDevice` is true, then a drag element will be added.\n   * Otherwise two up/down-buttons will be added.\n   *\n   * @param {number} index - The answer option index inside the config.\n   * @param {boolean} isTouchDevice - Set to `true` if drag-and-drop handles should be added instead of buttons.\n   * @returns {HTMLDivElement}\n   */\n  private makeAnswerControlElement(\n    index: number,\n    isTouchDevice: boolean\n  ): { container: HTMLDivElement; dndHandleElement: HTMLDivElement | null } {\n    const _self = this;\n    const controlElement = document.createElement(\"div\") as HTMLDivElement;\n    controlElement.classList.add(\"answer-controls-element\");\n\n    var dndElement: HTMLDivElement | null = null;\n    if (isTouchDevice) {\n      const upDownElement = document.createElement(\"div\") as HTMLDivElement;\n      upDownElement.classList.add(\"answer-up-down-element\");\n      const upBtn = document.createElement(\"button\") as HTMLButtonElement;\n      upBtn.innerHTML = \"▴\";\n      if (index === 0) {\n        upBtn.setAttribute(\"disabled\", \"true\");\n      } else {\n        upBtn.addEventListener(\"click\", () => {\n          console.log(\"upBtn\", index, index - 1);\n          _self.performDrop(index, index - 1);\n        });\n      }\n      const downBtn = document.createElement(\"button\") as HTMLButtonElement;\n      downBtn.innerHTML = \"▾\";\n      if (index + 1 === this.currentGraphNode?.o.length) {\n        downBtn.setAttribute(\"disabled\", \"true\");\n      } else {\n        downBtn.addEventListener(\"click\", () => {\n          console.log(\"downBtn\", index, index + 2); // Think of drop zone indices here\n\n          _self.performDrop(index, index + 2); // Think of drop zone indices here\n        });\n      }\n      upDownElement.appendChild(upBtn);\n      upDownElement.appendChild(downBtn);\n      controlElement.appendChild(upDownElement);\n    } else {\n      dndElement = document.createElement(\"div\") as HTMLDivElement;\n      dndElement.classList.add(\"a-dnd-element\");\n      dndElement.innerHTML = \"&vellip;\";\n      controlElement.appendChild(dndElement);\n    }\n\n    const deleteButton = document.createElement(\"button\") as HTMLButtonElement;\n    deleteButton.classList.add(\"a-delete-button\");\n    deleteButton.addEventListener(\"click\", this.requestDeleteOption(index));\n    deleteButton.innerHTML = \"&#x1F5D1;\";\n\n    controlElement.appendChild(deleteButton);\n    return { container: controlElement, dndHandleElement: dndElement };\n  }\n\n  private performDrop(answerIndex: number, dropIndex: number) {\n    if (dropIndex > answerIndex) {\n      dropIndex--;\n    }\n\n    if (this.currentGraphNode) {\n      const old = this.currentGraphNode.o[answerIndex];\n      this.currentGraphNode.o[answerIndex] = this.currentGraphNode.o[dropIndex];\n      this.currentGraphNode.o[dropIndex] = old;\n    }\n\n    // Re-build the list : )\n    this.updateAnswerOptions();\n    this.editorHelpers.pb.redraw();\n  }\n\n  private requestDeleteOption(index: number): () => void {\n    const _self = this;\n    return () => {\n      _self.modal.setTitle(\"Delete option?\");\n      _self.modal.setBody(`Do you really want to delete option #${index}?`);\n      _self.modal.setFooter(\"\");\n      _self.modal.setActions([\n        Modal.ACTION_CANCEL,\n        {\n          label: \"Yes\",\n          action: () => {\n            _self.modal.close();\n            _self.handleDeleteOption(index);\n          }\n        }\n      ]);\n      _self.modal.open();\n    };\n  }\n\n  private handleDeleteOption(index: number) {\n    this.currentGraphNode?.o.splice(index, 1);\n    this.updateAnswerOptions();\n    this.editorHelpers.pb.redraw();\n  }\n\n  private makeADropArea(\n    dropIndex: number,\n    drop: (evt: DragEvent) => void,\n    onDragOver: (evt: DragEvent) => void,\n    onDragLeave: (evt: DragEvent) => void\n  ) {\n    const dropArea: HTMLDivElement = document.createElement(\"div\");\n    dropArea.setAttribute(\"data-dropindex\", `${dropIndex}`);\n    dropArea.classList.add(\"a-droparea\", \"droppable\");\n    dropArea.addEventListener(\"drop\", drop);\n    dropArea.addEventListener(\"dragover\", onDragOver);\n    dropArea.addEventListener(\"dragleave\", onDragLeave);\n    return dropArea;\n  }\n\n  private createNodeSelectElement(currentKey: string, selectedKey): HTMLSelectElement {\n    const selectElement = document.createElement(\"select\") as HTMLSelectElement;\n    if (!this.editorHelpers.dialogConfigWithPositions) {\n      console.warn(\"Warning: cannout populate nodeSelectElement. No dialogConfig set.\");\n    } else {\n      const optionElement = this.createNodeSelectOptionElement(\"\", false, null, false);\n      selectElement.appendChild(optionElement);\n\n      for (var key in this.editorHelpers.dialogConfigWithPositions.graph) {\n        if (!this.editorHelpers.dialogConfigWithPositions.graph.hasOwnProperty(key)) {\n          // return;\n          continue; // !!! is this correct?\n        }\n        const questionaire: IMiniQuestionaire = this.editorHelpers.dialogConfigWithPositions.graph[key];\n        const optionElement = this.createNodeSelectOptionElement(questionaire.q, key === currentKey, key, key === selectedKey);\n\n        selectElement.appendChild(optionElement);\n      }\n    }\n    return selectElement;\n  }\n\n  private createNodeSelectOptionElement(questionaireText: string, isCurrent: boolean, key: string | null, isSelected: boolean) {\n    const optionElement = document.createElement(\"option\") as HTMLOptionElement;\n    optionElement.setAttribute(\"value\", key as string);\n    optionElement.innerHTML = `${key ?? \"\"}: ${EditorHelper.ellipsify(questionaireText, 20)}`;\n    if (isCurrent) {\n      optionElement.setAttribute(\"disabled\", \"true\");\n    }\n    if (isSelected) {\n      optionElement.setAttribute(\"selected\", \"true\");\n    }\n    return optionElement;\n  }\n}\n","/**\n * Helpers for the graph editor.\n *\n * @require PlotBoilerplate\n *\n * @author   Ikaros Kappler\n * @date     2023-07-28\n * @version  1.0.0\n **/\n\nimport { MouseHandler, PlotBoilerplate, XMouseEvent, XYCoords, XYDimension } from \"plotboilerplate\";\nimport { IDialogueConfig, IMiniQuestionaire, IMiniQuestionaireWithPosition, IOptionIdentifyer } from \"./interfaces\";\nimport { RPGDOMHelpers } from \"./domHelpers\";\nimport { EditorRenderer } from \"./editorRenderer\";\nimport { Editor } from \"./Editor\";\nimport { DialogueMetaHelpers } from \"./metaHelpers\";\n\nexport class EditorHelper {\n  editor: Editor;\n  pb: PlotBoilerplate;\n  boxSize: XYDimension;\n\n  // TODO: convert into node identifyer\n  /**\n   * The highlighted node's name or null if none is highlighted.\n   * Used to highlight nodes when the mouse is over.\n   */\n  highlightedNodeName: string | null = null;\n\n  /**\n   * The highlighted node itself or null if none is highligted.\n   * Used to determine rendering colors.\n   */\n  highlightedNode: IMiniQuestionaireWithPosition | null = null;\n\n  /**\n   * The selected node's name or null if none is selected.\n   * Used to determine the node editor's contents.\n   */\n  selectedNodeName: string | null = null;\n\n  /**\n   * The selected node itself or null if none is selected.\n   * Used to determine the node editor's contents.\n   */\n  selectedNode: IMiniQuestionaireWithPosition | null = null;\n\n  /**\n   * The currently selected option or null if none is selected.\n   * Used to re-connect an option with a new successor node.\n   */\n  selectedOption: IOptionIdentifyer | null = null;\n\n  /**\n   * The currently highlighted option.\n   * Used to draw on-mouse-over options with a different color.\n   */\n  hightlightedOption: IOptionIdentifyer | null = null;\n\n  /**\n   * The current mouse position (or null if mouse is not on canvas).\n   * In local relative coordinate system.\n   */\n  relativeMousePosition: XYCoords | null = null;\n\n  domHelper: RPGDOMHelpers;\n\n  dialogConfigWithPositions: IDialogueConfig<IMiniQuestionaireWithPosition>;\n\n  metaHelpers: DialogueMetaHelpers;\n\n  constructor(editor: Editor, pb: PlotBoilerplate, boxSize: XYDimension) {\n    this.editor = editor;\n    this.pb = pb;\n    this.boxSize = boxSize;\n    this.selectedNodeName = null;\n    this.domHelper = new RPGDOMHelpers(this);\n    this.metaHelpers = new DialogueMetaHelpers(this);\n  }\n\n  setDialogConfig(dialogConfigWithPositions: IDialogueConfig<IMiniQuestionaireWithPosition>) {\n    this.dialogConfigWithPositions = dialogConfigWithPositions;\n  }\n\n  setSelectedOption(selectedOption: IOptionIdentifyer | null, noRedraw?: boolean) {\n    console.log(\"Set selected option\", selectedOption);\n    this.selectedOption = selectedOption;\n    if (!noRedraw) {\n      this.pb.redraw();\n    }\n  }\n\n  setHighlightedOption(hightlightedOption: IOptionIdentifyer | null) {\n    // const isRedrawRequired = this.hightlightedOption !== hightlightedOption;\n    const isRedrawRequired = !this.isEqualOptionIdentifyer(this.hightlightedOption, hightlightedOption);\n\n    this.hightlightedOption = hightlightedOption;\n    if (isRedrawRequired) {\n      this.pb.redraw();\n    }\n  }\n\n  setHighlightedNode(nodeName: string | null, noRedraw?: boolean) {\n    this.highlightedNodeName = nodeName;\n    this.highlightedNode = nodeName ? this.dialogConfigWithPositions.graph[nodeName] : null;\n    if (!noRedraw) {\n      this.pb.redraw();\n    }\n  }\n\n  /**\n   * A helper function to create random safe positions in the viewport area.\n   * @param {PlotBoilerplate} pb\n   * @param {XYDimension} boxSize\n   * @returns\n   */\n  getRandomPosition(): XYCoords {\n    const viewport = this.pb.viewport();\n    return {\n      x: viewport.min.x + this.boxSize.width + (viewport.width - 2 * this.boxSize.width) * Math.random(),\n      y: viewport.min.y + this.boxSize.height + (viewport.height - 2 * this.boxSize.height) * Math.random()\n    };\n  }\n\n  setSelectedNode(nodeName: string | null, node: IMiniQuestionaireWithPosition | null) {\n    this.selectedNodeName = nodeName;\n    this.selectedNode = node;\n\n    if (nodeName && node) {\n      // this.domHelper.editorElement.classList.remove(\"d-none\");\n      this.domHelper.toggleVisibility(true);\n      this.domHelper.showAnswerOptions(nodeName, this.selectedNode);\n    } else {\n      // this.domHelper.editorElement.classList.add(\"d-none\");\n      this.domHelper.toggleVisibility(false);\n      this.domHelper.showAnswerOptions(null, null);\n    }\n    this.pb.redraw();\n  }\n\n  /**\n   * A helper function to make sure all graph nodes have valid positions. Those without\n   * valid positions (eg like those being loaded from an incomplete JSON file) will be\n   * assigned to a random position inside the viewport.\n   *\n   * @param {PlotBoilerplate} pb\n   * @param {XYDimension} boxSize\n   * @returns\n   */\n  enrichPositions(baseConfig: IDialogueConfig<IMiniQuestionaire>): IDialogueConfig<IMiniQuestionaireWithPosition> {\n    // Clone?\n    const configWithPositions: IDialogueConfig<IMiniQuestionaireWithPosition> =\n      baseConfig as IDialogueConfig<IMiniQuestionaireWithPosition>;\n\n    for (var nodeName in configWithPositions.graph) {\n      const graphNode: IMiniQuestionaireWithPosition = configWithPositions.graph[nodeName];\n      if (!graphNode) {\n        console.warn(`Warning: graph node ${nodeName} is null or undefined!`);\n        continue;\n      }\n      // Anonymous member check\n      if (!graphNode.hasOwnProperty(\"editor\")) {\n        graphNode.editor = { position: this.getRandomPosition() };\n      } else if (!(graphNode.editor as IMiniQuestionaireWithPosition).hasOwnProperty(\"position\")) {\n        (graphNode.editor as any).position = this.getRandomPosition();\n      } else {\n        if (!(graphNode.editor as any).position.hasOwnProperty(\"x\") || isNaN(graphNode.editor?.position?.x ?? NaN)) {\n          if (graphNode.editor?.position) {\n            graphNode.editor.position.x = this.getRandomPosition().x;\n          }\n        }\n        if (!(graphNode.editor as any).position.hasOwnProperty(\"y\") || isNaN(graphNode.editor?.position?.y ?? NaN)) {\n          if (graphNode.editor?.position) {\n            graphNode.editor.position.y = this.getRandomPosition().y;\n          }\n        }\n      }\n    }\n    return configWithPositions;\n  }\n\n  /**\n   * Check if the meta data is valid and – if not – add missing default fields.\n   * @param dialogueConfig\n   */\n  enrichMetaData(dialogueConfig: Object) {\n    const result = dialogueConfig as IDialogueConfig<IMiniQuestionaireWithPosition>;\n    if (!dialogueConfig.hasOwnProperty(\"meta\")) {\n      result.meta = { name: \"noname\", npcs: [] };\n    }\n    if (!result.meta.npcs) {\n      result.meta.npcs = [];\n    }\n    if (result.meta.npcs.length === 0) {\n      result.meta.npcs.push({ name: \"NPC #0\" });\n    }\n  }\n\n  isPosInGraphNodeBox(pos: XYCoords, graphNode: IMiniQuestionaireWithPosition): boolean {\n    return Boolean(\n      graphNode.editor &&\n        graphNode.editor.position &&\n        graphNode.editor.position.x <= pos.x &&\n        graphNode.editor.position.y <= pos.y &&\n        graphNode.editor.position.x + this.boxSize.width > pos.x &&\n        graphNode.editor.position.y + this.boxSize.height > pos.y\n    );\n  }\n\n  isPosInOptionNodeBox(pos: XYCoords, graphNode: IMiniQuestionaireWithPosition, optionIndex: number): boolean {\n    // EditorRenderer.OPTION_OFFSET_X;\n    return Boolean(\n      graphNode.editor &&\n        graphNode.editor.position &&\n        graphNode.editor.position.x + EditorRenderer.OPTION_OFFSET_X <= pos.x &&\n        graphNode.editor.position.y + (optionIndex + 1) * this.boxSize.height <= pos.y &&\n        graphNode.editor.position.x + EditorRenderer.OPTION_OFFSET_X + this.boxSize.width > pos.x &&\n        graphNode.editor.position.y + (optionIndex + 1) * this.boxSize.height + this.boxSize.height > pos.y\n    );\n  }\n\n  locateNodeBoxNameAtPos(pos: XYCoords): string | null {\n    for (var nodeName in this.dialogConfigWithPositions.graph) {\n      const graphNode: IMiniQuestionaireWithPosition = this.dialogConfigWithPositions.graph[nodeName];\n      if (this.isPosInGraphNodeBox(pos, graphNode)) {\n        return nodeName;\n      }\n    }\n    return null;\n  }\n\n  locateOptionBoxNameAtPos(pos: XYCoords): IOptionIdentifyer | null {\n    for (var nodeName in this.dialogConfigWithPositions.graph) {\n      const graphNode: IMiniQuestionaireWithPosition = this.dialogConfigWithPositions.graph[nodeName];\n      for (var i = 0; i < graphNode.o.length; i++) {\n        if (this.isPosInOptionNodeBox(pos, graphNode, i)) {\n          return { nodeName: nodeName, node: graphNode, optionIndex: i };\n        }\n      }\n    }\n    return null;\n  }\n\n  isNodeHighlighted(nodName: string) {\n    return this.highlightedNodeName === nodName;\n  }\n\n  isOptionHighlighted(nodeName: string, optionIndex: number): boolean {\n    return Boolean(\n      this.hightlightedOption &&\n        this.hightlightedOption.nodeName === nodeName &&\n        this.hightlightedOption.optionIndex === optionIndex\n    );\n  }\n\n  isOptionSelected(nodeName: string, optionIndex: number): boolean {\n    return Boolean(\n      this.selectedOption && this.selectedOption.nodeName === nodeName && this.selectedOption.optionIndex === optionIndex\n    );\n  }\n\n  addNewDialogueNode() {\n    // Place two box units to the right if currently there is a selected node.\n    // Otherwise random position.\n    const position: XYCoords =\n      this.selectedNode && this.selectedNode.editor && this.selectedNode.editor.position\n        ? {\n            x: this.selectedNode.editor.position.x + 2 * this.boxSize.width,\n            y: this.selectedNode.editor.position.y + this.boxSize.height\n          }\n        : this.getRandomPosition();\n    const nodeName = this.randomNodeKey();\n    const newNode: IMiniQuestionaireWithPosition = {\n      q: \"\",\n      o: [{ a: \"\", next: null }],\n      editor: {\n        position: position\n      }\n    };\n    this.dialogConfigWithPositions.graph[nodeName] = newNode;\n    this.selectedNodeName = nodeName;\n    this.selectedNode = newNode;\n    this.domHelper.showAnswerOptions(nodeName, newNode);\n    this.pb.redraw();\n  }\n\n  removeNewDialogueNode(nodeName: string) {\n    delete this.dialogConfigWithPositions.graph[nodeName];\n    this.selectedNodeName = null;\n    this.selectedNode = null;\n    this.domHelper.showAnswerOptions(null, null);\n    this.pb.redraw();\n  }\n\n  boxMovehandler() {\n    const _self = this;\n    // +---------------------------------------------------------------------------------\n    // | Add a mouse listener to track the mouse position.\n    // +-------------------------------\n    var mouseDownPos: XYCoords | null = null;\n    var lastMouseDownPos: XYCoords | null = null;\n    var draggingNode: IMiniQuestionaireWithPosition | null = null;\n    var draggingNodeName: string | null = null;\n    const handler = new MouseHandler(this.pb.eventCatcher)\n      .down((evt: XMouseEvent) => {\n        mouseDownPos = this.pb.transformMousePosition(evt.params.mouseDownPos.x, evt.params.mouseDownPos.y);\n        lastMouseDownPos = { x: evt.params.mouseDownPos.x, y: evt.params.mouseDownPos.y };\n        draggingNodeName = this.locateNodeBoxNameAtPos(mouseDownPos);\n        if (draggingNodeName) {\n          draggingNode = this.dialogConfigWithPositions.graph[draggingNodeName];\n        }\n      })\n      .up((_evt: XMouseEvent) => {\n        mouseDownPos = null;\n        draggingNode = null;\n      })\n      .drag((evt: XMouseEvent) => {\n        if (!mouseDownPos || !draggingNode || !draggingNode.editor || !draggingNode.editor.position) {\n          return;\n        }\n        // const diff = evt.params.dragAmount;\n        draggingNode.editor.position.x += evt.params.dragAmount.x / this.pb.draw.scale.x;\n        draggingNode.editor.position.y += evt.params.dragAmount.y / this.pb.draw.scale.y;\n      })\n      .move((evt: XMouseEvent) => {\n        // console.log(\"move\", evt);\n        // Check if mouse pointer hovers over an option -> set highlighted\n        const mouseMovePos = this.pb.transformMousePosition(evt.params.pos.x, evt.params.pos.y);\n        _self.relativeMousePosition = { x: mouseMovePos.x, y: mouseMovePos.y };\n        const hoveringOptionIdentifyer: IOptionIdentifyer | null = this.locateOptionBoxNameAtPos(mouseMovePos);\n        // Can be null\n        _self.setHighlightedOption(hoveringOptionIdentifyer);\n        if (!hoveringOptionIdentifyer) {\n          // Check if hover on graph node\n          const hoveringNodeName = this.locateNodeBoxNameAtPos(mouseMovePos);\n          this.setHighlightedNode(hoveringNodeName);\n        } else {\n          this.setHighlightedNode(null);\n        }\n      })\n      .click((evt: XMouseEvent) => {\n        // Stop if mouse was moved\n        console.log(\"lastMouseDownPos\", lastMouseDownPos, \" evt.params.pos\", evt.params.pos);\n        if (lastMouseDownPos && (lastMouseDownPos.x !== evt.params.pos.x || lastMouseDownPos.y !== evt.params.pos.y)) {\n          return;\n        }\n        // Check if mouse pointer hovers over an option -> set selected AND select node\n        const mouseClickPos = this.pb.transformMousePosition(evt.params.pos.x, evt.params.pos.y);\n        _self.handleClick(mouseClickPos);\n      });\n\n    return handler;\n  }\n\n  handleClick(mouseClickPos: XYCoords) {\n    const clickedOptionIdentifyer: IOptionIdentifyer | null = this.locateOptionBoxNameAtPos(mouseClickPos);\n    if (clickedOptionIdentifyer) {\n      this.setSelectedOption(clickedOptionIdentifyer);\n    } else {\n      // Otherwise (no option was clicked) check if a node was clicked directly.\n      const clickedNodeName = this.locateNodeBoxNameAtPos(mouseClickPos);\n      console.log(\"Click\", clickedNodeName);\n      if (clickedNodeName) {\n        if (this.selectedOption) {\n          this.handleOptionReconnect(clickedNodeName);\n          this.pb.redraw();\n        } else {\n          this.setSelectedNode(clickedNodeName, this.dialogConfigWithPositions.graph[clickedNodeName]);\n          // this.pb.redraw();\n        }\n      } else {\n        this.setSelectedNode(null, null);\n        // this.selectedNode = null;\n        // this.pb.redraw();\n      }\n      this.setSelectedOption(null, false);\n    }\n  }\n\n  handleOptionReconnect(clickedNodeName: string) {\n    if (!this.selectedOption) {\n      // && !this.selectedNodeName) {\n      // Actually this fuction should not be called at all in that case.\n      console.warn(\"Warn: cannot reconnect option when no option is selected.\");\n      return;\n    }\n    const graph = this.dialogConfigWithPositions.graph;\n    const clickedNode: IMiniQuestionaireWithPosition = graph[clickedNodeName];\n    const sourceNode = this.selectedOption.node;\n    // console.log(\"Reconnect\");\n    sourceNode.o[this.selectedOption.optionIndex].next = clickedNodeName;\n\n    this.domHelper.showAnswerOptions(this.selectedNodeName, this.selectedNode);\n  }\n\n  isEqualOptionIdentifyer(identA: IOptionIdentifyer | null, identB: IOptionIdentifyer | null): boolean {\n    if ((!identA && identB) || (identA && !identB)) {\n      return false;\n    }\n    if (\n      (typeof identA === \"undefined\" && typeof identB !== \"undefined\") ||\n      (typeof identA !== \"undefined\" && typeof identB === \"undefined\")\n    ) {\n      return false;\n    }\n    if (identA === identB || (typeof identA === \"undefined\" && typeof identB === \"undefined\")) {\n      return true;\n    }\n    return identA?.nodeName === identB?.nodeName && identA?.optionIndex === identB?.optionIndex;\n  }\n\n  renameGraphNode(oldName: string, newName: string): boolean {\n    if (!this.dialogConfigWithPositions.graph.hasOwnProperty(oldName)) {\n      console.warn(\"Warning: cannot rename node, because old name does not exist.\", oldName);\n      return false;\n    }\n    if (oldName === \"intro\") {\n      console.warn(\"Warning: cannot rename node, because 'intro' must not be renamed'.\");\n      return false;\n    }\n    if (this.dialogConfigWithPositions.graph.hasOwnProperty(newName)) {\n      console.warn(\"Warning: cannot rename node, because new name already exists.\", newName);\n      return false;\n    }\n    if (newName === oldName) {\n      console.warn(\"Warning: cannot rename node, because old name and new name are the same.\", oldName);\n      return false;\n    }\n    const graphNode = this.dialogConfigWithPositions.graph[oldName];\n    this.dialogConfigWithPositions.graph[newName] = graphNode;\n    delete this.dialogConfigWithPositions.graph[oldName];\n\n    // Update all references\n    for (var nodeName in this.dialogConfigWithPositions.graph) {\n      if (!this.dialogConfigWithPositions.graph.hasOwnProperty(nodeName)) {\n        continue;\n      }\n      const tmpNode = this.dialogConfigWithPositions.graph[nodeName];\n      for (var j = 0; j < tmpNode.o.length; j++) {\n        if (tmpNode.o[j].next === oldName) {\n          tmpNode.o[j].next = newName;\n        }\n      }\n    }\n\n    // Update local selected fields\n    if (oldName === this.selectedNodeName) {\n      this.selectedNodeName = newName;\n      this.selectedNode = this.dialogConfigWithPositions.graph[newName];\n    }\n\n    this.pb.redraw();\n    return true;\n  }\n\n  static ellipsify(text: string, maxLength: number): string {\n    if (!text || text.length <= maxLength) {\n      return text;\n    }\n    return `${text.substring(0, maxLength)}...`;\n  }\n\n  static fromObject(object: object): IDialogueConfig<IMiniQuestionaire> {\n    // Must be of type object\n    if (typeof object !== \"object\") {\n      throw `Cannot convert non-objects to dialogue config: type is ${typeof object}.`;\n    }\n\n    // Must have a 'graph' member.\n    if (!object.hasOwnProperty(\"graph\")) {\n      throw \"Cannot convert object to dialogue config: object missing member `graph`.\";\n    }\n\n    const graph = object[\"graph\"];\n    // Check if 'intro' is present?\n\n    // All members must be of correct type\n    for (var key in object) {\n      if (!object.hasOwnProperty(key)) {\n        continue;\n      }\n      const questionaire = object[key];\n      if (typeof questionaire !== \"object\") {\n        throw \"Cannot converto bject to dialogue config: all graph members must be objects.\";\n      }\n\n      // Check if 'q' (string) and 'o' (array) attributes are present?\n    }\n\n    return object as IDialogueConfig<IMiniQuestionaire>;\n  }\n\n  static removePositions(dialogueConfig: IDialogueConfig<IMiniQuestionaireWithPosition>): IDialogueConfig<IMiniQuestionaire> {\n    const clone: IDialogueConfig<IMiniQuestionaire> = JSON.parse(JSON.stringify(dialogueConfig));\n    for (var nodeName in clone.graph) {\n      const node = clone.graph[nodeName];\n      if (node.hasOwnProperty(\"editor\")) {\n        delete node[\"editor\"];\n      }\n    }\n    return clone;\n  }\n\n  private randomNodeKey(): string {\n    const keys = Object.keys(this.dialogConfigWithPositions.graph);\n    var count = keys.length;\n    let key = \"dia_\" + count;\n    while (this.dialogConfigWithPositions.graph.hasOwnProperty(key)) {\n      key = \"dia_\" + count;\n      count++;\n    }\n    return key;\n  }\n}\n","/**\n * A renderer for the graph editor.\n *\n * @require PlotBoilerplate\n *\n * @author   Ikaros Kappler\n * @date     2023-07-28\n * @version  1.0.0\n **/\nimport { FontOptions, PlotBoilerplate, Vertex, XYCoords, XYDimension, drawutils } from \"plotboilerplate\";\nimport { IAnswer, IDialogueConfig, IMiniQuestionaireWithPosition } from \"./interfaces\";\nimport { EditorHelper } from \"./editorHelpers\";\nimport { getContrastColor } from \"plotboilerplate/src/cjs/utils/algorithms/getContrastColor\";\nimport { Color } from \"plotboilerplate/src/cjs/utils/datastructures/Color\";\n// import { FileDrop } from \"plotboilerplate/src/cjs/utils/io/FileDrop\";\n\nexport class EditorRenderer {\n  pb: PlotBoilerplate;\n  boxSize: XYDimension;\n  editorHelpers: EditorHelper;\n  fontOptions: FontOptions;\n\n  TEXT_MAX_LENGTH = 20;\n  static OPTION_OFFSET_X = 16;\n\n  constructor(pb: PlotBoilerplate, boxSize: XYDimension, editorHelpers: EditorHelper, isDarkmode: boolean) {\n    this.pb = pb;\n    this.boxSize = boxSize;\n    this.editorHelpers = editorHelpers;\n    this.fontOptions = {\n      color: \"black\",\n      fontFamily: \"Arial\",\n      fontSize: 12,\n      fontStyle: \"italic\",\n      fontWeight: \"normal\",\n      lineHeight: 26,\n      textAlign: \"left\",\n      rotation: 0\n    };\n\n    const backgroundColor = isDarkmode ? Color.parse(\"#000000\") : Color.parse(\"#ffffff\");\n    this.fontOptions.color = getContrastColor(backgroundColor).setAlpha(0.8).cssRGBA();\n  }\n\n  renderBoxes(dialogConfig: IDialogueConfig<IMiniQuestionaireWithPosition>) {\n    const nodeNames: string[] = Object.keys(dialogConfig.graph);\n    const count: number = nodeNames.length;\n    for (var i = 0; i < count; i++) {\n      const nodeName = nodeNames[i];\n      const graphNode: IMiniQuestionaireWithPosition = dialogConfig.graph[nodeName];\n      this.renderGraphNode(nodeName, graphNode);\n      this.renderOptions(nodeName, graphNode);\n    }\n    // Render suggested new connection\n    this.renderSuggestedConnection();\n  }\n\n  private renderSuggestedConnection() {\n    if (this.editorHelpers.selectedOption) {\n      const isMousePosInsideOption: boolean = this.editorHelpers.isPosInOptionNodeBox(\n        this.editorHelpers.relativeMousePosition,\n        this.editorHelpers.selectedOption.node,\n        this.editorHelpers.selectedOption.optionIndex\n      );\n      const bezierTargetPosition = this.editorHelpers.highlightedNode\n        ? this.editorHelpers.highlightedNode.editor.position\n        : isMousePosInsideOption\n        ? null\n        : this.editorHelpers.relativeMousePosition;\n      if (bezierTargetPosition) {\n        this.drawBezierConnection(\n          this.editorHelpers.selectedOption.node,\n          this.editorHelpers.selectedOption.optionIndex,\n          bezierTargetPosition,\n          true,\n          true\n        );\n      }\n    }\n  }\n\n  private renderGraphNode(nodeName: string, graphNode: IMiniQuestionaireWithPosition) {\n    const isNodeSelected: boolean = this.editorHelpers.selectedNodeName === nodeName;\n    const isNodeHighlighted: boolean = this.editorHelpers.isNodeHighlighted(nodeName);\n    this.pb.fill.text(nodeName, graphNode.editor.position.x, graphNode.editor.position.y - this.boxSize.height, {\n      ...this.fontOptions,\n      color: \"grey\"\n    });\n    this.pb.draw.rect(\n      graphNode.editor.position,\n      this.boxSize.width,\n      this.boxSize.height,\n      isNodeSelected ? \"rgba(255,128,0,1.0)\" : \"rgba(0,255,0,1.0)\",\n      1.0\n    );\n    // Show initial and terminal nodes with fill color\n    if (!graphNode.o || graphNode.o.length === 0 || nodeName === \"intro\" || isNodeHighlighted) {\n      this.pb.fill.rect(\n        { x: graphNode.editor.position.x, y: graphNode.editor.position.y },\n        this.boxSize.width,\n        this.boxSize.height,\n        isNodeHighlighted ? \"rgba(255,128,0,0.5)\" : isNodeSelected ? \"rgba(255,128,0,0.3)\" : \"rgba(0,255,0,0.3)\",\n        1.0\n      );\n    }\n    this.pb.fill.text(\n      graphNode.q ? (isNodeSelected ? graphNode.q : EditorHelper.ellipsify(graphNode.q, this.TEXT_MAX_LENGTH)) : \"-no text-\",\n      graphNode.editor.position.x,\n      graphNode.editor.position.y,\n      this.fontOptions\n    );\n  }\n\n  private renderOptions(nodeName: string, graphNode: IMiniQuestionaireWithPosition) {\n    const isNodeSelected: boolean = this.editorHelpers.selectedNodeName === nodeName;\n\n    var offsetY = graphNode.editor.position.y + this.boxSize.height;\n    var offsetX = graphNode.editor.position.x + EditorRenderer.OPTION_OFFSET_X;\n    for (var j = 0; j < graphNode.o.length; j++) {\n      const option: IAnswer = graphNode.o[j];\n\n      // Render highlighted option?\n      const otherOptionIsSelected: boolean =\n        this.editorHelpers.selectedOption !== null && !this.editorHelpers.isOptionSelected(nodeName, j);\n      const isHighlighted = !otherOptionIsSelected && this.editorHelpers.isOptionHighlighted(nodeName, j);\n      const isSelected = this.editorHelpers.isOptionSelected(nodeName, j);\n      if (isHighlighted || isSelected) {\n        this.pb.fill.rect({ x: offsetX, y: offsetY }, this.boxSize.width, this.boxSize.height, \"rgba(255,192,0,0.5)\", 1);\n      }\n      this.pb.draw.rect({ x: offsetX, y: offsetY }, this.boxSize.width, this.boxSize.height, \"grey\", 1);\n      this.pb.fill.text(\n        option.a ? (isNodeSelected ? option.a : EditorHelper.ellipsify(option.a, this.TEXT_MAX_LENGTH)) : \"-no text-\",\n        offsetX,\n        offsetY,\n        { ...this.fontOptions, color: isHighlighted || isSelected ? \"black\" : \"grey\" }\n      );\n      if (isHighlighted || isSelected) {\n        // Draw connect indicator when highlighted\n        const zA = new Vertex(graphNode.editor.position).addXY(\n          this.boxSize.width + 16,\n          this.boxSize.height / 2.0 + (j + 1) * (this.boxSize.height + 2) - 2\n        );\n        this.pb.fill.circle(zA, 5, \"orange\");\n      }\n\n      offsetY += this.boxSize.height + 2;\n    }\n  }\n\n  renderConnections(dialogConfig: IDialogueConfig<IMiniQuestionaireWithPosition>) {\n    const nodeNames: string[] = Object.keys(dialogConfig.graph);\n    const count: number = nodeNames.length;\n    for (var i = 0; i < count; i++) {\n      const nodeName = nodeNames[i];\n      const graphNode: IMiniQuestionaireWithPosition = dialogConfig.graph[nodeName];\n      for (var j = 0; j < graphNode.o.length; j++) {\n        const successorName: string = graphNode.o[j].next;\n        if (!successorName) {\n          continue;\n        }\n        const successorNode: IMiniQuestionaireWithPosition = dialogConfig.graph[successorName];\n        if (!successorNode) {\n          continue;\n        }\n        const isHighlighted = this.editorHelpers.isOptionHighlighted(nodeName, j);\n        const otherOptionIsSelected: boolean =\n          this.editorHelpers.selectedOption !== null && !this.editorHelpers.isOptionSelected(nodeName, j);\n\n        const isSelected = this.editorHelpers.isOptionSelected(nodeName, j);\n\n        // this.drawLinearConnection(graphNode, successorNode, j);\n        this.drawBezierConnection(\n          graphNode,\n          j,\n          successorNode.editor.position,\n          isHighlighted && !otherOptionIsSelected,\n          isSelected\n        );\n      }\n    }\n  }\n\n  drawBezierConnection(\n    graphNode: IMiniQuestionaireWithPosition,\n    j: number,\n    successorNodePosition: XYCoords,\n    isHighlighted: boolean,\n    isSelected: boolean\n  ) {\n    // Construct Bézier handles.\n    const zA = new Vertex(graphNode.editor.position).addXY(\n      this.boxSize.width + 16,\n      this.boxSize.height / 2.0 + (j + 1) * (this.boxSize.height + 2) - 2\n    );\n    const zB = new Vertex(successorNodePosition);\n    const cA = zA.clone().addXY(50, 0);\n    const cB = zB.clone().subXY(50, 50);\n\n    const isCanvas = this.pb.canvas instanceof HTMLCanvasElement;\n    if (isCanvas) {\n      // Maybe future versions of PlotBoilerplate support this for Canvas & SVG nodes\n      if (isHighlighted) {\n        (this.pb.draw as drawutils).ctx.setLineDash([10, 6]);\n      } else {\n        (this.pb.draw as drawutils).ctx.setLineDash([0]);\n      }\n    }\n    this.cubicBezierArrow(zA, zB, cA, cB, isHighlighted || isSelected ? \"rgba(0,192,255,0.5)\" : \"rgba(255,192,0,0.5)\", 2);\n\n    if (isCanvas) {\n      (this.pb.draw as drawutils).ctx.setLineDash([0]);\n    }\n  }\n\n  /**\n   * Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.\n   *\n   * @method arrow\n   * @param {Vertex} zA - The start point of the arrow-line.\n   * @param {Vertex} zB - The end point of the arrow-line.\n   * @param {string} color - Any valid CSS color string.\n   * @param {number=} lineWidth - (optional) The line width to use; default is 1.\n   * @return {void}\n   * @instance\n   * @memberof drawutils\n   **/\n  cubicBezierArrow(zA: Vertex, zB: Vertex, cA: Vertex, cB: Vertex, color: string, lineWidth?: number) {\n    var headlen: number = 8; // length of head in pixels\n    var vertices: Array<Vertex> = Vertex.utils\n      .buildArrowHead(cB, zB, headlen, 1.0, 1.0) // this.pb.draw.scale.x, this.pb.draw.scale.y);\n      .map((vertex: Vertex) => {\n        return vertex.scale(1.0 / this.pb.draw.scale.x, zB);\n      });\n    this.pb.draw.cubicBezier(zA, zB, cA, cB, color, lineWidth);\n    this.pb.fill.polyline(vertices, false, color, lineWidth);\n\n    // Draw bezier control lines?\n    // this.pb.draw.line(zA, cA, \"grey\", 1);\n    // this.pb.draw.line(zB, cB, \"grey\", 1);\n  }\n}\n","// Get the URI GET params as an assoc.\n//\n// A nicer version with regex\n// Found at\n//    https://stackoverflow.com/questions/979975/how-to-get-the-value-from-the-get-parameters?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa\nexport const gup = () => {\n  var vars = {};\n  var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, (_m, key: string, value: string, ...args) => {\n    vars[key] = value;\n    return value;\n  });\n  return vars;\n};\n","// export * from \"axios\";\n// export * from \"alloyfinger-typescript\";\n// export * from \"plotboilerplate\";\n\nexport * from \"./gup\";\nexport * from \"./detectDarkMode\";\nexport * from \"./RPGDialogueLogic\";\nexport * from \"./modal\";\nexport * from \"./editorHelpers\";\nexport * from \"./TouchHandler\";\nexport * from \"./domHelpers\";\nexport * from \"./metaHelpers\";\nexport * from \"./editorRenderer\";\nexport * from \"./Editor\";\nexport * from \"./RPGDialogueSequence\";\nexport * from \"./RPGDialogue\";\n","/**\n * Helper to edit dialogue meta data.\n *\n * @author  Ikaros Kappler\n * @date    2023-08-09\n * @version 1.0.0\n */\n\nimport { EditorHelper } from \"./editorHelpers\";\nimport { IDialogueMeta } from \"./interfaces\";\nimport { Modal } from \"./modal\";\n\nexport class DialogueMetaHelpers {\n  private editorHelpers: EditorHelper;\n  private inputName: HTMLInputElement;\n  private inputsNpcNames: HTMLInputElement[];\n  private metaCopy: IDialogueMeta;\n\n  constructor(editorHelpers: EditorHelper) {\n    this.editorHelpers = editorHelpers;\n\n    document.getElementById(\"b-configure-meta\").addEventListener(\"click\", this.handleModalOpen());\n  }\n\n  private handleModalOpen() {\n    const _self = this;\n    return () => {\n      _self.metaCopy = DialogueMetaHelpers.cloneMeta(this.editorHelpers.dialogConfigWithPositions.meta);\n      _self.editorHelpers.domHelper.modal.setTitle(\"Dialogue Config Meta Data\");\n      _self.editorHelpers.domHelper.modal.setBody(_self.buildMetaBody());\n      _self.editorHelpers.domHelper.modal.setFooter(\"\");\n      _self.editorHelpers.domHelper.modal.setActions([{ label: \"Save\", action: _self.handleSave() }, Modal.ACTION_CANCEL]);\n      _self.editorHelpers.domHelper.modal.open();\n    };\n  }\n\n  private updateModalBody() {\n    const newBody = this.buildMetaBody();\n    this.editorHelpers.domHelper.modal.setBody(newBody);\n  }\n\n  private buildMetaBody(): HTMLDivElement {\n    const metaBody = document.createElement(\"div\");\n\n    this.inputName = document.createElement(\"input\");\n    this.inputName.value = this.metaCopy.name;\n    this.inputName.addEventListener(\"change\", this.handleUpdateMetaName());\n    const nameLabel = document.createElement(\"div\");\n    nameLabel.innerHTML = \"Dialogue name\";\n\n    const npcContainer = document.createElement(\"div\");\n    npcContainer.classList.add(\"e-meta-npccontainer\");\n    this.inputsNpcNames = [];\n    for (var i = 0; i < this.metaCopy.npcs.length; i++) {\n      const container = document.createElement(\"div\");\n      const label = document.createElement(\"div\");\n      label.innerHTML = `NPC #${i}`;\n      const npcNameInput = document.createElement(\"input\");\n      npcNameInput.value = this.metaCopy.npcs[i].name;\n      npcNameInput.addEventListener(\"change\", this.handleNpcNameChange(i));\n\n      const btnRemove = document.createElement(\"button\");\n      btnRemove.innerHTML = \"&#x1F5D1;\";\n      btnRemove.addEventListener(\"click\", this.handleDeleteNpc(i));\n\n      container.appendChild(label);\n      container.appendChild(npcNameInput);\n      container.appendChild(btnRemove);\n      npcContainer.appendChild(container);\n\n      this.inputsNpcNames.push(npcNameInput);\n    }\n\n    const btnAddNpc = document.createElement(\"button\");\n    btnAddNpc.innerHTML = \"Add NPC\";\n    btnAddNpc.addEventListener(\"click\", this.handleAddNpc());\n\n    metaBody.appendChild(nameLabel);\n    metaBody.appendChild(this.inputName);\n    metaBody.appendChild(npcContainer);\n    metaBody.appendChild(btnAddNpc);\n    return metaBody;\n  }\n\n  private handleUpdateMetaName(): (event: InputEvent) => void {\n    const _self = this;\n    return (event: InputEvent) => {\n      _self.metaCopy.name = (event.target as HTMLInputElement).value;\n    };\n  }\n\n  private handleNpcNameChange(index: number): (event: InputEvent) => void {\n    const _self = this;\n    return (event: InputEvent) => {\n      _self.metaCopy.npcs[index].name = (event.target as HTMLInputElement).value;\n    };\n  }\n\n  private handleDeleteNpc(index: number): () => void {\n    const _self = this;\n    return () => {\n      _self.metaCopy.npcs.splice(index, 1);\n      _self.updateModalBody();\n    };\n  }\n\n  private handleAddNpc(): () => void {\n    const _self = this;\n    return () => {\n      _self.metaCopy.npcs.push({ name: \"New NPC\" });\n      _self.updateModalBody();\n    };\n  }\n\n  private handleSave(): () => void {\n    const _self = this;\n    return () => {\n      _self.editorHelpers.dialogConfigWithPositions.meta = _self.metaCopy;\n      _self.editorHelpers.domHelper.modal.close();\n      _self.editorHelpers.domHelper.updateNpcSelector();\n    };\n  }\n\n  static cloneMeta(meta: IDialogueMeta): IDialogueMeta {\n    const copy = {} as IDialogueMeta;\n    copy.name = meta.name;\n    copy.npcs = [];\n    for (var i = 0; i < meta.npcs.length; i++) {\n      copy.npcs.push({ name: meta.npcs[i].name });\n    }\n    return copy;\n  }\n}\n","/**\n * Original source: https://www.w3schools.com/howto/howto_css_modals.asp\n *\n * @requires modal.css\n *\n * Converted to a class by\n * @author   Ikaros Kappler\n * @date     2020-09-14\n * @modified 2023-08-09 Ported to typescript.\n * @version  1.1.0\n **/\n\n/*\n      <!-- The Modal -->\n      <div id=\"myModal\" class=\"modal\">\n\n      <!-- Modal content -->\n      <div class=\"modal-content\">\n      <div class=\"modal-header\">\n      <span class=\"close\">&times;</span>\n      <h2>Modal Header</h2>\n      </div>\n      <div class=\"modal-body\">\n      <p>Some text in the Modal Body</p>\n      <p>Some other text...</p>\n      </div>\n      <div class=\"modal-footer\">\n      <h3>Modal Footer</h3>\n      </div>\n      </div>\n\n      </div>\n    */\n\nexport interface IModalAction {\n  label: string;\n  action: string | (() => void);\n}\n\ninterface IModalStruct {\n  modal: {\n    id: string;\n    parent: HTMLDivElement;\n    header: {\n      closeBtn: HTMLSpanElement;\n      content: HTMLHeadingElement;\n    };\n    body: { content: HTMLDivElement };\n    footer: {\n      content: HTMLHeadingElement;\n      actions: HTMLDivElement;\n    };\n  };\n}\n\nexport class Modal {\n  static ACTION_CLOSE: IModalAction = { label: \"Close\", action: \"close\" };\n  static ACTION_CANCEL: IModalAction = { label: \"Cancel\", action: \"close\" };\n  static ACTION_OK: IModalAction = { label: \"OK\", action: \"close\" };\n\n  private static MODAL_COUNTER: number = 0;\n  private modalElements;\n\n  constructor() {\n    this.modalElements = this.buildDOMNode(\"myModal-\" + Modal.MODAL_COUNTER++);\n  }\n\n  setTitle(title: string) {\n    this.modalElements.modal.header.content.innerHTML = title;\n  }\n\n  setBody(bodyContent: HTMLElement | string) {\n    if (Modal.isDOMNode(bodyContent)) {\n      Modal.removeChildNodes(this.modalElements.modal.body.content);\n      this.modalElements.modal.body.content.append(bodyContent);\n    } else {\n      this.modalElements.modal.body.content.innerHTML = bodyContent;\n    }\n  }\n\n  setFooter(title: string) {\n    if (typeof title === \"string\") {\n      this.modalElements.modal.footer.content.innerHTML = title.length == 0 ? \"&nbsp;\" : title;\n    } else {\n      console.log(\"Footer elements?\");\n    }\n  }\n\n  setActions(actions: Array<IModalAction>) {\n    const _self = this;\n    Modal.removeChildNodes(this.modalElements.modal.footer.actions);\n    if (Array.isArray(actions)) {\n      for (var i in actions) {\n        const a: IModalAction = actions[i];\n        var cmd: string | null = null;\n        const btn = document.createElement(\"button\");\n        btn.innerHTML = a.label;\n        if (typeof a.action === \"function\") {\n          btn.addEventListener(\"click\", a.action);\n        } else if ((typeof a === \"string\" && (cmd = a) != null) || (typeof a.action === \"string\" && (cmd = a.action) != null)) {\n          if (cmd === \"cancel\" || cmd === \"ok\" || cmd === \"close\")\n            btn.addEventListener(\"click\", () => {\n              _self.close();\n            });\n        }\n        this.modalElements.modal.footer.actions.appendChild(btn);\n      }\n    }\n  }\n\n  close() {\n    this.modalElements.modal.parent.classList.remove(\"modal-opened\");\n    this.modalElements.modal.parent.classList.add(\"modal-closed\");\n  }\n\n  open() {\n    this.modalElements.modal.parent.classList.remove(\"modal-closed\");\n    this.modalElements.modal.parent.classList.add(\"modal-opened\");\n  }\n\n  private buildDOMNode(id: string): IModalStruct {\n    var _self = this;\n\n    var modal = document.createElement(\"div\");\n    modal.setAttribute(\"id\", id);\n    modal.classList.add(\"modal\");\n    modal.classList.add(\"modal-closed\");\n\n    var content = document.createElement(\"div\");\n    content.classList.add(\"modal-content\");\n\n    var header = document.createElement(\"div\");\n    header.classList.add(\"modal-header\");\n\n    var closeBtn = document.createElement(\"span\");\n    closeBtn.classList.add(\"modal-close\");\n    closeBtn.innerHTML = \"&times;\";\n\n    var h2 = document.createElement(\"h2\");\n    h2.innerHTML = \"Modal Header\";\n\n    var body = document.createElement(\"div\");\n    body.classList.add(\"modal-body\");\n\n    // Body contents?\n    var bodyContent = document.createElement(\"p\");\n    bodyContent.innerHTML = \"Some text in the Modal Body\";\n\n    var footer = document.createElement(\"div\");\n    footer.classList.add(\"modal-footer\");\n\n    var footerContent = document.createElement(\"h3\");\n    var footerActions = document.createElement(\"div\");\n    footerContent.innerHTML = \"Modal Footer\";\n    footerActions.classList.add(\"modal-actions\");\n    footer.appendChild(footerContent);\n    footer.appendChild(footerActions);\n\n    header.appendChild(closeBtn);\n    header.appendChild(h2);\n    content.appendChild(header);\n    body.appendChild(bodyContent);\n    content.appendChild(body);\n    content.appendChild(footer);\n    modal.appendChild(content);\n\n    // When the user clicks on <span> (x), close the modal\n    closeBtn.onclick = () => {\n      _self.close();\n    };\n\n    // Append new modal to body\n    document.getElementsByTagName(\"body\")[0].appendChild(modal);\n\n    return {\n      modal: {\n        id: id,\n        parent: modal,\n        header: {\n          closeBtn: closeBtn,\n          content: h2\n        },\n        body: { content: bodyContent },\n        footer: {\n          content: footerContent,\n          actions: footerActions\n        }\n      }\n    };\n  }\n\n  // https://stackoverflow.com/questions/384286/how-do-you-check-if-a-javascript-object-is-a-dom-object\n  static isDOMNode(obj) {\n    try {\n      //Using W3 DOM2 (works for FF, Opera and Chrome)\n      return obj instanceof HTMLElement;\n    } catch (e) {\n      //Browsers not supporting W3 DOM2 don't have HTMLElement and\n      //an exception is thrown and we end up here. Testing some\n      //properties that all elements have (works on IE7)\n      return (\n        typeof obj === \"object\" && obj.nodeType === 1 && typeof obj.style === \"object\" && typeof obj.ownerDocument === \"object\"\n      );\n    }\n  }\n\n  static removeChildNodes = node => {\n    // Remove all current actions\n    while (node.firstChild) {\n      node.removeChild(node.lastChild);\n    }\n  };\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t48: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkRPGDialogue\"] = self[\"webpackChunkRPGDialogue\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [736], () => (__webpack_require__(294)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["root","factory","exports","module","define","amd","self","deferred","questionNodeId","optionsNodeId","endOfConversationText","this","questionNode","getHTMLElement","optionsNode","console","warn","nodeId","document","getElementById","renderConversationTerminated","setQuestionText","undefined","questionText","npcName","innerHTML","clearAllOptions","addAnswerOption","answerText","optionIndex","onOptionSelected","answerNode","createElement","answerLinkNode","setAttribute","addEventListener","appendChild","DefaultDialogueRenderer","dialogueConfigJSONPath","isRecoveryFromLocalStorageActive","globalLibs","currentMouseHandler","currentTouchHandler","_self","log","GUP","gup","isDarkmode","detectDarkMode","isMobileDevice","detectMobileDevice","pb","PlotBoilerplate","utils","safeMergeByKeys","canvas","fullSize","fitToParent","scaleX","scaleY","rasterGrid","drawOrigin","rasterAdjustFactor","redrawOnResize","defaultCanvasWidth","defaultCanvasHeight","canvasWidthFactor","canvasHeightFactor","cssScaleX","cssScaleY","cssUniformScale","autoAdjustOffset","offsetAdjustXPercent","offsetAdjustYPercent","backgroundColor","enableMouse","enableKeys","boxSize","width","height","editorHelpers","EditorHelper","editorRenderer","EditorRenderer","KeyHandler","element","getElementsByTagName","trackAll","down","selectedOption","setSelectedOption","selectedNode","setSelectedNode","debug","classList","add","config","postDraw","_draw","_fill","dialogConfig","renderBoxes","renderConnections","tryLoadFromLocalStorage","then","dc","handleDialogConfigLoaded","catch","tryLoadFromJSON","FileDrop","eventCatcher","onFileJSONDropped","jsonObject","fromObject","click","_evt","fileInput","files","length","reader","FileReader","onload","jsonText","result","JSON","parse","readAsText","testCurrentDialogueConfig","requestCreateNewGraph","showJSON","window","open","tryStartAutosaveLoop","autosaveTimer","globalThis","setInterval","tryAutoSave","domHelper","isAutoSave","putToLocalStorage","modal","setTitle","setBody","setFooter","setActions","Modal","ACTION_CANCEL","label","action","close","performNewGraph","meta","name","npcs","graph","intro","q","o","a","next","editor","position","x","y","dConfig","isExportWithoutPositions","removePositions","dialogConfigWithPositions","jsonString","stringify","jsonArea","ACTION_CLOSE","outputContainer","outputQuestion","outputOptions","rpgLogic","RPGDialogueLogic","addDialogueChangeListener","_dialogueConfig","nextNodeName","_oldNodeName","_selectedOptionIndex","setHighlightedNode","alternateStartNodeName","selectedNodeName","beginConversation","enrichPositions","enrichMetaData","setDialogConfig","destroy","boxMovehandler","TouchHandler","redraw","localStorage","setItem","loadConfigFromJSON","Promise","accept","reject","getItem","exception","Editor","RPGDialogue","RPGDOMHelpers","DialogueMetaHelpers","RPGDialogueSequence","dialogueStruct","validateStructure","createSendAnswerCallback","dialogueRenderer","sendAnswer","isEndReached","loadCurrentQuestionaire","structure","listeners","resetToBeginning","validate","listener","i","push","removeDialogueChangeListener","splice","fireStateChange","oldNodeName","selectedOptionIndex","getCurrentNpcName","npcIndex","currentQuestionaire","answerCallback","getCurrentQuestionaire","index","oldQuestionaireName","currentQuestionaireName","selectedAnswer","nextQuestionaire","path","axios","get","response","data","error","finally","loadFromJSON","struct","loadAllFromJSON","paths","promises","npcNames","Object","keys","npcPath","all","dialogues","mapping","rules","handleDialogueStateChanged","matchingRule","findRule","callback","nodeName","rule","addRule","editorHelper","wasTouchUsed","draggedOption","relPos","pos","bounds","getBoundingClientRect","left","top","draggedNodeName","draggedNode","wasDragged","touchMovePos","touchDownPos","clearTouch","afProps","touchStart","evt","touches","Vertex","clientX","clientY","locateNodeBoxNameAtPos","transformMousePosition","locateOptionBoxNameAtPos","touchMove","preventDefault","stopPropagation","rel","trans","diff","difference","touchEnd","handleOptionReconnect","touchCancel","alloyFinger","createAlloyFinger","onTouchLeaveEvents","onTouchEnterEvents","_init","onTouchEnter","selector","fn","slice","map","e","onTouchLeave","lastTouchLeave","lastTouchEnter","el","elementFromPoint","event","matches","TouchEnterLeaveHandler","hasOwnProperty","overrideValue","toLowerCase","hours","Date","getHours","userAgent","navigator","vendor","opera","test","substr","currentDraggedAnswerIndex","currentDropAnswerIndex","touchEnterLeaveHandler","editorElement","optionsElement","keyElement","querySelector","npcElement","qElement","handleQChanged","handleNPCIndexChanged","handleKeyChanged","exportJSON","addDialogueNode","requestRemoveDialogueNode","checked","blob","Blob","type","url","URL","createObjectURL","href","download","textContent","currentGraphNode","updateAnswerOptions","addNewDialogueNode","currentNodeName","removeDialogueNode","removeNewDialogueNode","toggleVisibility","isVisible","remove","changeEvent","target","value","_changeEvent","newIndex","parseInt","Number","isNaN","newName","trim","renameGraphNode","handleATextChanged","answer","handleASuccessorChanged","showAnswerOptions","getSelectedNpcIndex","updateNpcSelector","curNpcIndex","npcOption","selected","toggleDragEnterStyles","answerIndex","dropIndex","getAttribute","contains","toggleDragLeaveStyles","graphNode","onDragOver","ev","onDragLeave","drop","performDrop","isTouchDevice","Boolean","dropArea","makeADropArea","option","answerWrapperElement","answerControlsElement","makeAnswerControlElement","answerElement","labelElement","textElement","selectElement","createNodeSelectElement","dndHandleElement","dataTransfer","setData","dragStartElement","parentElement","_ev","container","controlElement","dndElement","upDownElement","upBtn","downBtn","deleteButton","requestDeleteOption","old","handleDeleteOption","currentKey","selectedKey","optionElement","createNodeSelectOptionElement","key","questionaire","questionaireText","isCurrent","isSelected","ellipsify","highlightedNodeName","highlightedNode","hightlightedOption","relativeMousePosition","metaHelpers","noRedraw","setHighlightedOption","isRedrawRequired","isEqualOptionIdentifyer","getRandomPosition","viewport","min","Math","random","node","baseConfig","configWithPositions","NaN","dialogueConfig","isPosInGraphNodeBox","isPosInOptionNodeBox","OPTION_OFFSET_X","isNodeHighlighted","nodName","isOptionHighlighted","isOptionSelected","randomNodeKey","newNode","mouseDownPos","lastMouseDownPos","draggingNode","draggingNodeName","MouseHandler","params","up","drag","dragAmount","draw","scale","move","mouseMovePos","hoveringOptionIdentifyer","hoveringNodeName","mouseClickPos","handleClick","clickedOptionIdentifyer","clickedNodeName","identA","identB","oldName","tmpNode","j","text","maxLength","substring","object","clone","count","TEXT_MAX_LENGTH","fontOptions","color","fontFamily","fontSize","fontStyle","fontWeight","lineHeight","textAlign","rotation","Color","getContrastColor","setAlpha","cssRGBA","nodeNames","renderGraphNode","renderOptions","renderSuggestedConnection","isMousePosInsideOption","bezierTargetPosition","drawBezierConnection","isNodeSelected","fill","rect","offsetY","offsetX","isHighlighted","zA","addXY","circle","successorName","successorNode","otherOptionIsSelected","successorNodePosition","zB","cA","cB","subXY","isCanvas","HTMLCanvasElement","ctx","setLineDash","cubicBezierArrow","lineWidth","vertices","buildArrowHead","vertex","cubicBezier","polyline","vars","location","replace","_m","handleModalOpen","metaCopy","cloneMeta","buildMetaBody","handleSave","updateModalBody","newBody","metaBody","inputName","handleUpdateMetaName","nameLabel","npcContainer","inputsNpcNames","npcNameInput","handleNpcNameChange","btnRemove","handleDeleteNpc","btnAddNpc","handleAddNpc","copy","modalElements","buildDOMNode","MODAL_COUNTER","title","header","content","bodyContent","isDOMNode","removeChildNodes","body","append","footer","actions","Array","isArray","cmd","btn","parent","id","closeBtn","h2","footerContent","footerActions","onclick","obj","HTMLElement","nodeType","style","ownerDocument","ACTION_OK","firstChild","removeChild","lastChild","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","call","m","O","chunkIds","priority","notFulfilled","Infinity","fulfilled","every","r","d","definition","defineProperty","enumerable","prop","prototype","Symbol","toStringTag","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","forEach","bind","__webpack_exports__"],"sourceRoot":""}