@limetech/lime-elements 38.11.0 → 38.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/index.cjs.js +0 -9
  3. package/dist/cjs/index.cjs.js.map +1 -1
  4. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +209 -111
  5. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
  6. package/dist/cjs/limel-snackbar.cjs.entry.js.map +1 -1
  7. package/dist/cjs/limel-text-editor.cjs.entry.js +7 -1
  8. package/dist/cjs/limel-text-editor.cjs.entry.js.map +1 -1
  9. package/dist/collection/components/snackbar/snackbar.js +1 -1
  10. package/dist/collection/components/snackbar/snackbar.js.map +1 -1
  11. package/dist/collection/components/text-editor/prosemirror-adapter/menu/menu-items.js.map +1 -1
  12. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js +15 -54
  13. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js.map +1 -1
  14. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/node.js +52 -44
  15. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/node.js.map +1 -1
  16. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/view.js +11 -13
  17. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/view.js.map +1 -1
  18. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js.map +1 -1
  19. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/append-transaction-handler.js.map +1 -1
  20. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/detect-trigger-removal.js.map +1 -1
  21. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/get-trigger-event-detail.js.map +1 -1
  22. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/monitor-triggered-text.js.map +1 -1
  23. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/send-trigger-event.js.map +1 -1
  24. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/text-input-handler.js.map +1 -1
  25. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/factory.js.map +1 -1
  26. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/trigger/inserter.js.map +1 -1
  27. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js +54 -8
  28. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js.map +1 -1
  29. package/dist/collection/components/text-editor/text-editor.js +38 -4
  30. package/dist/collection/components/text-editor/text-editor.js.map +1 -1
  31. package/dist/collection/components/text-editor/text-editor.types.js +1 -9
  32. package/dist/collection/components/text-editor/text-editor.types.js.map +1 -1
  33. package/dist/collection/components/text-editor/utils/metadata-utils.js +108 -0
  34. package/dist/collection/components/text-editor/utils/metadata-utils.js.map +1 -0
  35. package/dist/esm/index.js +0 -2
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/limel-prosemirror-adapter.entry.js +209 -111
  38. package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
  39. package/dist/esm/limel-snackbar.entry.js.map +1 -1
  40. package/dist/esm/limel-text-editor.entry.js +7 -1
  41. package/dist/esm/limel-text-editor.entry.js.map +1 -1
  42. package/dist/lime-elements/index.esm.js +1 -1
  43. package/dist/lime-elements/index.esm.js.map +1 -1
  44. package/dist/lime-elements/lime-elements.esm.js +1 -1
  45. package/dist/lime-elements/p-3a87b175.entry.js.map +1 -1
  46. package/dist/lime-elements/p-7b039dab.entry.js +2 -0
  47. package/dist/lime-elements/p-7b039dab.entry.js.map +1 -0
  48. package/dist/lime-elements/{p-033fa919.entry.js → p-7f3045bd.entry.js} +2 -2
  49. package/dist/lime-elements/p-7f3045bd.entry.js.map +1 -0
  50. package/dist/types/components/text-editor/prosemirror-adapter/menu/menu-items.d.ts +2 -2
  51. package/dist/types/components/text-editor/prosemirror-adapter/plugins/image/inserter.d.ts +2 -7
  52. package/dist/types/components/text-editor/prosemirror-adapter/plugins/image/node.d.ts +9 -0
  53. package/dist/types/components/text-editor/prosemirror-adapter/plugins/link-plugin.d.ts +0 -4
  54. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/append-transaction-handler.d.ts +1 -1
  55. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/detect-trigger-removal.d.ts +1 -1
  56. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/get-trigger-event-detail.d.ts +2 -2
  57. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/monitor-triggered-text.d.ts +2 -2
  58. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/send-trigger-event.d.ts +1 -1
  59. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory-helpers/text-input-handler.d.ts +1 -1
  60. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/factory.d.ts +1 -1
  61. package/dist/types/components/text-editor/prosemirror-adapter/plugins/trigger/inserter.d.ts +1 -1
  62. package/dist/types/components/text-editor/prosemirror-adapter/prosemirror-adapter.d.ts +10 -0
  63. package/dist/types/components/text-editor/text-editor.d.ts +10 -0
  64. package/dist/types/components/text-editor/text-editor.types.d.ts +32 -7
  65. package/dist/types/components/text-editor/utils/metadata-utils.d.ts +22 -0
  66. package/dist/types/components.d.ts +17 -4
  67. package/package.json +1 -1
  68. package/dist/cjs/text-editor.types-5e5567e2.js +0 -13
  69. package/dist/cjs/text-editor.types-5e5567e2.js.map +0 -1
  70. package/dist/esm/text-editor.types-e82469d1.js +0 -13
  71. package/dist/esm/text-editor.types-e82469d1.js.map +0 -1
  72. package/dist/lime-elements/p-033fa919.entry.js.map +0 -1
  73. package/dist/lime-elements/p-7006fafe.entry.js +0 -2
  74. package/dist/lime-elements/p-7006fafe.entry.js.map +0 -1
  75. package/dist/lime-elements/p-9ca516ed.js +0 -2
  76. package/dist/lime-elements/p-9ca516ed.js.map +0 -1
@@ -1 +1 @@
1
- {"file":"limel-snackbar.entry.cjs.js","mappings":";;;;;;;;AAAA;;;;;;MAMa,iBAAiB;EAA9B;IACY,qBAAgB,GAA+B,EAAE,CAAC;GAmD7D;;;;;;EA5CU,GAAG,CAAC,QAAkC;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;;;IAI1C,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,EAAE,CAAC;IAEvB,IAAI,CAAC,gBAAgB,GAAG,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7D,IAAI,CAAC,WAAW,EAAE,CAAC;GACtB;;;;;;EAOM,MAAM,CAAC,QAAkC;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;;;IAI1C,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,EAAE,CAAC;IAEvB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAChD,CAAC,IAAI,KAAK,IAAI,KAAK,QAAQ,CAC9B,CAAC;IACF,IAAI,CAAC,WAAW,EAAE,CAAC;GACtB;EAEO,WAAW;IACf,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,QAAQ;MACnC,QAAQ,CAAC,aAAa,CAClB,IAAI,WAAW,CAAC,cAAc,EAAE;QAC5B,MAAM,EAAE,MAAM;OACjB,CAAC,CACL,CAAC;MACF,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC;KACtE,CAAC,CAAC;GACN;EAEO,UAAU,CAAC,QAAkC;IACjD,OAAO,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;GACzD;;;ACzDL,MAAM,WAAW,GAAG,8pHAA8pH;;ACiBlrH,MAAM,SAAS,GAAG,IAAI,iBAAiB,EAAE,CAAC;AAC1C,MAAM,qBAAqB,GAAG,GAAG,CAAC;MAoCrB,QAAQ;EA8EjB;;;;IA0CO,eAAU,GAAG;MAChB,IAAI,IAAI,CAAC,MAAM,EAAE;QACb,OAAO;OACV;MAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;MACnB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;MACrB,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;MAEzB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE;QACrC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,CAC9B,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,GAAG,CACJ,IAAI,CAAC,OAAO,GAAG,qBAAqB,EACpC,qBAAqB,CACxB,CACJ,CAAC;OACL;KACJ,CAAC;IAEe,gBAAW,GAAG;MAC3B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;QACd,OAAO;OACV;MAED,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;MAEpB,IAAI,IAAI,CAAC,SAAS,EAAE;QAChB,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;OAC9B;MAED,UAAU,CAAC;QACP,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;OACnB,EAAE,qBAAqB,CAAC,CAAC;KAC7B,CAAC;IAwCe,sBAAiB,GAAG;MACjC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;KACtB,CAAC;gBAnMqB,KAAK;;mBAkBF,IAAI;;uBAaA,IAAI;;oBAaL,IAAI;kBAkBR,CAAC;kBAGA,KAAK;mBAGJ,IAAI;IAM3B,IAAI,CAAC,UAAU,GAAGA,+BAAkB,EAAE,CAAC;GAC1C;EAEM,gBAAgB;IACnB,IAAI,IAAI,CAAC,IAAI,EAAE;MACX,qBAAqB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;KAC1C;GACJ;EAGS,aAAa,CAAC,KAA0B;IAC9C,KAAK,CAAC,eAAe,EAAE,CAAC;IACxB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;GAC9B;EAGS,SAAS;IACf,IAAI,IAAI,CAAC,IAAI,EAAE;MACX,IAAI,CAAC,UAAU,EAAE,CAAC;KACrB;SAAM;MACH,IAAI,CAAC,WAAW,EAAE,CAAC;KACtB;IAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC;GAC3B;;;;;EAOM,MAAM,IAAI;;IAEb,OAAO,CAAC,IAAI,CACR,8FAA8F,CACjG,CAAC;IACF,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;MACZ,IAAI,CAAC,UAAU,EAAE,CAAC;KACrB;GACJ;EA0CM,MAAM;IACT,QACIC,mBACI,OAAO,EAAC,QAAQ,EAChB,KAAK,EAAE;QACH,oBAAoB,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI;QAC3D,iCAAiC,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI;OACxD,EACD,KAAK,EAAE;QACH,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,YAAY,EAAE,IAAI,CAAC,OAAO;QAC1B,sBAAsB,EAAE,IAAI;OAC/B,EACD,EAAE,EAAE,IAAI,CAAC,UAAU,EACnB,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,mBACV,IAAI,CAAC,IAAI,GAAG,WAAW,GAAG,SAAS,IAElDA,iBAAK,KAAK,EAAC,SAAS,iBAAa,OAAO,IACpCA,iBAAK,KAAK,EAAC,OAAO,IAAE,IAAI,CAAC,OAAO,CAAO,EACtC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,EACnC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,CACzC,CACF,EACV;GACL;EAEO,YAAY;IAChB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;MACZ,OAAO,SAAS,CAAC;KACpB;IAED,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE;MACtC,OAAO,aAAa,CAAC;KACxB;IAED,OAAO,QAAQ,CAAC;GACnB;EAMO,aAAa,CAAC,UAAkB;IACpC,IAAI,CAAC,UAAU,EAAE;MACb,OAAO;KACV;IAED,QACIA,iBAAK,KAAK,EAAC,SAAS,iBAAa,MAAM,IAClC,IAAI,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAClC,EACR;GACL;EAEO,kBAAkB,CAAC,UAAkB;IACzC,IAAI,CAAC,UAAU,EAAE;MACb,OAAO;KACV;IAED,QACIA,0BAAc,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,iBAAiB,GAAI,EACtE;GACL;EAEO,mBAAmB,CAAC,WAAoB;IAC5C,IAAI,CAAC,WAAW,EAAE;MACd,OAAO;KACV;IAED,MAAM,KAAK,GAAGC,sBAAS,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE/D,QACID,iBAAK,KAAK,EAAC,SAAS,IACf,IAAI,CAAC,0BAA0B,EAAE,EAClCA,+BACI,KAAK,EAAC,gBAAgB,EACtB,IAAI,EAAC,UAAU,EACf,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,IAAI,CAAC,WAAW,mBACV,IAAI,CAAC,UAAU,GAChC,CACA,EACR;GACL;EAEO,0BAA0B;IAC9B,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE;MACtC,OAAO;KACV;IAED,QACIA,iBAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,IAC3CA,oBAAQ,CAAC,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,IAAI,EAAC,oBAAoB,GAAG,EAC3DA,kBACI,KAAK,EAAC,OAAO,EACb,CAAC,EAAC,wDAAwD,EAC1D,MAAM,EAAC,mBAAmB,GAC5B,CACA,EACR;GACL;;;;;;;;;;","names":["createRandomString","h","translate"],"sources":["./src/components/snackbar/container.ts","./src/components/snackbar/snackbar.scss?tag=limel-snackbar&encapsulation=shadow","./src/components/snackbar/snackbar.tsx"],"sourcesContent":["/**\n * Container to keep track of all snackbar elements that gets added to the page.\n * When an element gets added or removed, the container will emit a\n * `changeOffset` event on all elements in the container, letting them know\n * the new offset to where they should position themselves.\n */\nexport class SnackbarContainer {\n private snackbarElements: HTMLLimelSnackbarElement[] = [];\n\n /**\n * Add a new element to the container\n *\n * @param snackbar - element to add\n */\n public add(snackbar: HTMLLimelSnackbarElement) {\n const popover = this.getPopover(snackbar);\n\n // Stencil does not seem to recognise the existance of showPopover\n // @ts-ignore\n popover?.showPopover();\n\n this.snackbarElements = [snackbar, ...this.snackbarElements];\n this.emitOffsets();\n }\n\n /**\n * Remove an element from the container\n *\n * @param snackbar - element to remove\n */\n public remove(snackbar: HTMLLimelSnackbarElement): void {\n const popover = this.getPopover(snackbar);\n\n // Stencil does not seem to recognise the existance of hidePopover\n // @ts-ignore\n popover?.hidePopover();\n\n this.snackbarElements = this.snackbarElements.filter(\n (item) => item !== snackbar,\n );\n this.emitOffsets();\n }\n\n private emitOffsets() {\n let offset = 0;\n this.snackbarElements.forEach((snackbar) => {\n snackbar.dispatchEvent(\n new CustomEvent('changeOffset', {\n detail: offset,\n }),\n );\n offset += this.getPopover(snackbar).getBoundingClientRect().height;\n });\n }\n\n private getPopover(snackbar: HTMLLimelSnackbarElement) {\n return snackbar.shadowRoot.querySelector('[popover]');\n }\n}\n","* {\n box-sizing: border-box;\n}\n\naside {\n background: none;\n border: none;\n inset: unset;\n overflow: visible;\n padding: 0.5rem 0.5rem 0 0.5rem;\n right: 0;\n\n width: var(--limel-snackbar-width, 21rem);\n top: calc(\n var(--snackbar-distance-to-top-edge) + env(safe-area-inset-top, 0)\n );\n\n transition:\n opacity var(--limel-snackbar-opacity-transition-speed, 0.2s) ease,\n top var(--limel-snackbar-top-transition-speed, 0.46s)\n cubic-bezier(1, 0.09, 0, 0.89),\n transform var(--limel-snackbar-top-transition-speed, 0.46s) ease;\n transform: translate3d(0, 0, 0);\n opacity: 1;\n\n &.is-closing {\n transform: translate3d(2rem, 0, 0);\n opacity: 0;\n --limel-snackbar-top-transition-speed: 0.2s;\n --limel-snackbar-opacity-transition-speed: 0.2s;\n }\n}\n\n.surface {\n overflow: hidden;\n\n padding: 0.5rem;\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 0.25rem;\n\n min-height: 3.25rem;\n border-radius: 0.75rem;\n\n background-color: rgb(var(--contrast-1400));\n box-shadow: var(--shadow-depth-8), var(--shadow-depth-16);\n}\n\n.label {\n color: rgb(var(--contrast-100));\n\n -webkit-font-smoothing: antialiased;\n font-size: 0.8125rem;\n font-weight: 400;\n padding: 0 0.25rem;\n\n width: 100%;\n flex-grow: 1;\n}\n\n.actions {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n box-sizing: border-box;\n gap: 0.5rem;\n}\n\n.dismiss,\n.actions {\n --lime-elevated-surface-background-color: rgb(\n var(--contrast-1300)\n ); // background color of the buttons\n}\n\n.dismiss {\n --mdc-theme-on-surface: rgb(var(--contrast-100)); // color of the X icon\n --icon-background-color: var(--lime-elevated-surface-background-color);\n --fill-color: var(--mdc-theme-primary);\n --track-color: rgb(var(--contrast-800), 0.2);\n transition:\n opacity 0.1s ease,\n transform 0.1s ease;\n position: absolute;\n top: -0.375rem;\n left: -0.375rem;\n transform: scale(0.7);\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n svg {\n position: absolute;\n transform: rotate(90deg);\n fill: transparent;\n stroke-dasharray: 100;\n stroke-linecap: round;\n\n aside.open & {\n animation: timeout var(--snackbar-timeout) linear forwards;\n }\n }\n\n .is-closing {\n transform: scale(0.5);\n opacity: 0;\n }\n}\n\n.dismiss-button {\n transform: scale(0.8);\n margin: 0;\n padding: 0;\n}\n\n@keyframes timeout {\n 0% {\n stroke-width: 4;\n stroke-dashoffset: 0;\n opacity: 1;\n }\n 100% {\n stroke-width: 1;\n stroke-dashoffset: -100;\n opacity: 0.7;\n }\n}\n\n@import '../portal/partial-styles/portal-container.scss';\n","import { Languages } from '../date-picker/date.types';\nimport {\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Listen,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport translate from '../../global/translations';\nimport { SnackbarContainer } from './container';\nimport { createRandomString } from 'src/util/random-string';\n\nconst container = new SnackbarContainer();\nconst hideAnimationDuration = 300;\n\n/**\n * A Snackbar –also known as \"Toast\"– is used to inform the end user\n * about an action or a process in the system.\n * The information could vary from announcing that a process has just started,\n * is taking place now, has ended, or has been interrupted or canceled.\n *\n * The information that you provide using a snackbar should be:\n * - temporary\n * - contextual\n * - short\n * - and most importantly, ignorable.\n *\n * It means if the user misses the information, it shouldn't be a big deal.\n *\n * :::note\n * If the information you want to display has a higher importance or priority,\n * and you need to make sure that the user takes an action to dismiss it,\n * consider using the [Banner](/#/component/limel-banner/) component instead.\n * For more complex interactions and for delivering more detailed information,\n * [Dialog](/#/component/limel-dialog/) is a better choice.\n * :::\n *\n * @exampleComponent limel-example-snackbar\n * @exampleComponent limel-example-snackbar-with-action\n * @exampleComponent limel-example-snackbar-with-changing-messages\n * @exampleComponent limel-example-snackbar-dismissible\n * @exampleComponent limel-example-snackbar-persistent\n * @exampleComponent limel-example-snackbar-persistent-non-dismissible\n */\n@Component({\n tag: 'limel-snackbar',\n shadow: true,\n styleUrl: 'snackbar.scss',\n})\nexport class Snackbar {\n /**\n * `true` if the snackbar is open, `false` otherwise.\n */\n @Prop({ reflect: true })\n public open: boolean = false;\n\n /**\n * The text message to display.\n */\n @Prop()\n public message: string;\n\n /**\n * The amount of time in milliseconds to show the snackbar.\n * If set to `-1`, the snackbar will be persistent.\n * This means:\n * - either the end user will need to close it manually,\n * which requires the `dismissible` property to be set to `true`.\n * - or the snackbar needs to be closed programmatically.\n */\n @Prop({ reflect: true })\n // eslint-disable-next-line no-magic-numbers\n public timeout?: number = 5000;\n\n /**\n * The text to display for the action button.\n */\n @Prop()\n public actionText: string;\n\n /**\n * When `true` displays a dismiss button on the snackbar,\n * allowing users to close it.\n */\n @Prop()\n public dismissible: boolean = true;\n\n /**\n * Whether to show the snackbar with space for multiple lines of text\n * @deprecated Setting this property no longer has any effect. The property will be removed in a future major version.\n */\n @Prop()\n public multiline: boolean;\n\n /**\n * Defines the language for translations.\n */\n @Prop()\n public language: Languages = 'en';\n\n @Element()\n private readonly host: HTMLLimelSnackbarElement;\n\n /**\n * Emitted when the action button is pressed\n */\n @Event()\n private readonly action: EventEmitter<void>;\n\n /**\n * Emitted when the snackbar hides itself\n */\n @Event()\n private readonly hide: EventEmitter<void>;\n\n @State()\n private offset: number = 0;\n\n @State()\n private isOpen: boolean = false;\n\n @State()\n private closing: boolean = true;\n\n private readonly snackbarId: string;\n private timeoutId?: number;\n\n public constructor() {\n this.snackbarId = createRandomString();\n }\n\n public componentDidLoad() {\n if (this.open) {\n requestAnimationFrame(this.handleOpen);\n }\n }\n\n @Listen('changeOffset')\n protected onChangeIndex(event: CustomEvent<number>) {\n event.stopPropagation();\n this.offset = event.detail;\n }\n\n @Watch('open')\n protected watchOpen() {\n if (this.open) {\n this.handleOpen();\n } else {\n this.handleClose();\n }\n\n this.isOpen = this.open;\n }\n\n /**\n * Show the snackbar\n * @deprecated Use the `open` property instead.\n */\n @Method()\n public async show() {\n // eslint-disable-next-line no-console\n console.warn(\n 'The `show` method in `limel-snackbar` is deprecated. Please use the `open` property instead.',\n );\n if (!this.open) {\n this.handleOpen();\n }\n }\n\n public handleOpen = () => {\n if (this.isOpen) {\n return;\n }\n\n this.isOpen = true;\n this.closing = false;\n container.add(this.host);\n\n if (this.timeout && this.timeout !== -1) {\n this.timeoutId = window.setTimeout(\n this.handleClose,\n Math.max(\n this.timeout - hideAnimationDuration,\n hideAnimationDuration,\n ),\n );\n }\n };\n\n private readonly handleClose = () => {\n if (!this.isOpen) {\n return;\n }\n\n this.closing = true;\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = undefined;\n }\n\n setTimeout(() => {\n this.isOpen = false;\n container.remove(this.host);\n this.hide.emit();\n this.offset = 0;\n }, hideAnimationDuration);\n };\n\n public render() {\n return (\n <aside\n popover=\"manual\"\n style={{\n '--snackbar-timeout': `${Math.max(this.timeout || 0, 0)}ms`,\n '--snackbar-distance-to-top-edge': `${this.offset}px`,\n }}\n class={{\n open: this.open,\n 'is-closing': this.closing,\n 'limel-portal--parent': true,\n }}\n id={this.snackbarId}\n role={this.setAriaRoles()}\n aria-relevant={this.open ? 'additions' : undefined}\n >\n <div class=\"surface\" aria-atomic=\"false\">\n <div class=\"label\">{this.message}</div>\n {this.renderActions(this.actionText)}\n {this.renderDismissButton(this.dismissible)}\n </div>\n </aside>\n );\n }\n\n private setAriaRoles() {\n if (!this.open) {\n return undefined;\n }\n\n if (!this.timeout || this.timeout === -1) {\n return 'alertdialog';\n }\n\n return 'status';\n }\n\n private readonly handleClickAction = () => {\n this.action.emit();\n };\n\n private renderActions(actionText: string) {\n if (!actionText) {\n return;\n }\n\n return (\n <div class=\"actions\" aria-atomic=\"true\">\n {this.renderActionButton(actionText)}\n </div>\n );\n }\n\n private renderActionButton(actionText: string) {\n if (!actionText) {\n return;\n }\n\n return (\n <limel-button label={actionText} onClick={this.handleClickAction} />\n );\n }\n\n private renderDismissButton(dismissible: boolean) {\n if (!dismissible) {\n return;\n }\n\n const label = translate.get('snackbar.dismiss', this.language);\n\n return (\n <div class=\"dismiss\">\n {this.renderTimeoutVisualization()}\n <limel-icon-button\n class=\"dismiss-button\"\n icon=\"multiply\"\n label={label}\n onClick={this.handleClose}\n aria-controls={this.snackbarId}\n />\n </div>\n );\n }\n\n private renderTimeoutVisualization() {\n if (!this.timeout || this.timeout === -1) {\n return;\n }\n\n return (\n <svg width=\"36\" height=\"36\" viewBox=\"0 0 36 36\">\n <circle r=\"18\" cx=\"18\" cy=\"18\" fill=\"var(--track-color)\" />\n <path\n class=\"track\"\n d=\"M 18,18 m -16,0 a 16,16 0 1,0 32,0 a 16,16 0 1,0 -32,0\"\n stroke=\"var(--fill-color)\"\n />\n </svg>\n );\n }\n}\n"],"version":3}
1
+ {"file":"limel-snackbar.entry.cjs.js","mappings":"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","names":["createRandomString","h","translate"],"sources":["./src/components/snackbar/container.ts","./src/components/snackbar/snackbar.scss?tag=limel-snackbar&encapsulation=shadow","./src/components/snackbar/snackbar.tsx"],"sourcesContent":["/**\n * Container to keep track of all snackbar elements that gets added to the page.\n * When an element gets added or removed, the container will emit a\n * `changeOffset` event on all elements in the container, letting them know\n * the new offset to where they should position themselves.\n */\nexport class SnackbarContainer {\n private snackbarElements: HTMLLimelSnackbarElement[] = [];\n\n /**\n * Add a new element to the container\n *\n * @param snackbar - element to add\n */\n public add(snackbar: HTMLLimelSnackbarElement) {\n const popover = this.getPopover(snackbar);\n\n // Stencil does not seem to recognise the existance of showPopover\n // @ts-ignore\n popover?.showPopover();\n\n this.snackbarElements = [snackbar, ...this.snackbarElements];\n this.emitOffsets();\n }\n\n /**\n * Remove an element from the container\n *\n * @param snackbar - element to remove\n */\n public remove(snackbar: HTMLLimelSnackbarElement): void {\n const popover = this.getPopover(snackbar);\n\n // Stencil does not seem to recognise the existance of hidePopover\n // @ts-ignore\n popover?.hidePopover();\n\n this.snackbarElements = this.snackbarElements.filter(\n (item) => item !== snackbar,\n );\n this.emitOffsets();\n }\n\n private emitOffsets() {\n let offset = 0;\n this.snackbarElements.forEach((snackbar) => {\n snackbar.dispatchEvent(\n new CustomEvent('changeOffset', {\n detail: offset,\n }),\n );\n offset += this.getPopover(snackbar).getBoundingClientRect().height;\n });\n }\n\n private getPopover(snackbar: HTMLLimelSnackbarElement) {\n return snackbar.shadowRoot.querySelector('[popover]');\n }\n}\n","* {\n box-sizing: border-box;\n}\n\naside {\n background: none;\n border: none;\n inset: unset;\n overflow: visible;\n padding: 0.5rem 0.5rem 0 0.5rem;\n right: 0;\n\n width: var(--limel-snackbar-width, 21rem);\n top: calc(\n var(--snackbar-distance-to-top-edge) + env(safe-area-inset-top, 0)\n );\n\n transition:\n opacity var(--limel-snackbar-opacity-transition-speed, 0.2s) ease,\n top var(--limel-snackbar-top-transition-speed, 0.46s)\n cubic-bezier(1, 0.09, 0, 0.89),\n transform var(--limel-snackbar-top-transition-speed, 0.46s) ease;\n transform: translate3d(0, 0, 0);\n opacity: 1;\n\n &.is-closing {\n transform: translate3d(2rem, 0, 0);\n opacity: 0;\n --limel-snackbar-top-transition-speed: 0.2s;\n --limel-snackbar-opacity-transition-speed: 0.2s;\n }\n}\n\n.surface {\n overflow: hidden;\n\n padding: 0.5rem;\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 0.25rem;\n\n min-height: 3.25rem;\n border-radius: 0.75rem;\n\n background-color: rgb(var(--contrast-1400));\n box-shadow: var(--shadow-depth-8), var(--shadow-depth-16);\n}\n\n.label {\n color: rgb(var(--contrast-100));\n\n -webkit-font-smoothing: antialiased;\n font-size: 0.8125rem;\n font-weight: 400;\n padding: 0 0.25rem;\n\n width: 100%;\n flex-grow: 1;\n}\n\n.actions {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n box-sizing: border-box;\n gap: 0.5rem;\n}\n\n.dismiss,\n.actions {\n --lime-elevated-surface-background-color: rgb(\n var(--contrast-1300)\n ); // background color of the buttons\n}\n\n.dismiss {\n --mdc-theme-on-surface: rgb(var(--contrast-100)); // color of the X icon\n --icon-background-color: var(--lime-elevated-surface-background-color);\n --fill-color: var(--mdc-theme-primary);\n --track-color: rgb(var(--contrast-800), 0.2);\n transition:\n opacity 0.1s ease,\n transform 0.1s ease;\n position: absolute;\n top: -0.375rem;\n left: -0.375rem;\n transform: scale(0.7);\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n svg {\n position: absolute;\n transform: rotate(90deg);\n fill: transparent;\n stroke-dasharray: 100;\n stroke-linecap: round;\n\n aside.open & {\n animation: timeout var(--snackbar-timeout) linear forwards;\n }\n }\n\n .is-closing {\n transform: scale(0.5);\n opacity: 0;\n }\n}\n\n.dismiss-button {\n transform: scale(0.8);\n margin: 0;\n padding: 0;\n}\n\n@keyframes timeout {\n 0% {\n stroke-width: 4;\n stroke-dashoffset: 0;\n opacity: 1;\n }\n 100% {\n stroke-width: 1;\n stroke-dashoffset: -100;\n opacity: 0.7;\n }\n}\n\n@import '../portal/partial-styles/portal-container.scss';\n","import { Languages } from '../date-picker/date.types';\nimport {\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Listen,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport translate from '../../global/translations';\nimport { SnackbarContainer } from './container';\nimport { createRandomString } from '../../util/random-string';\n\nconst container = new SnackbarContainer();\nconst hideAnimationDuration = 300;\n\n/**\n * A Snackbar –also known as \"Toast\"– is used to inform the end user\n * about an action or a process in the system.\n * The information could vary from announcing that a process has just started,\n * is taking place now, has ended, or has been interrupted or canceled.\n *\n * The information that you provide using a snackbar should be:\n * - temporary\n * - contextual\n * - short\n * - and most importantly, ignorable.\n *\n * It means if the user misses the information, it shouldn't be a big deal.\n *\n * :::note\n * If the information you want to display has a higher importance or priority,\n * and you need to make sure that the user takes an action to dismiss it,\n * consider using the [Banner](/#/component/limel-banner/) component instead.\n * For more complex interactions and for delivering more detailed information,\n * [Dialog](/#/component/limel-dialog/) is a better choice.\n * :::\n *\n * @exampleComponent limel-example-snackbar\n * @exampleComponent limel-example-snackbar-with-action\n * @exampleComponent limel-example-snackbar-with-changing-messages\n * @exampleComponent limel-example-snackbar-dismissible\n * @exampleComponent limel-example-snackbar-persistent\n * @exampleComponent limel-example-snackbar-persistent-non-dismissible\n */\n@Component({\n tag: 'limel-snackbar',\n shadow: true,\n styleUrl: 'snackbar.scss',\n})\nexport class Snackbar {\n /**\n * `true` if the snackbar is open, `false` otherwise.\n */\n @Prop({ reflect: true })\n public open: boolean = false;\n\n /**\n * The text message to display.\n */\n @Prop()\n public message: string;\n\n /**\n * The amount of time in milliseconds to show the snackbar.\n * If set to `-1`, the snackbar will be persistent.\n * This means:\n * - either the end user will need to close it manually,\n * which requires the `dismissible` property to be set to `true`.\n * - or the snackbar needs to be closed programmatically.\n */\n @Prop({ reflect: true })\n // eslint-disable-next-line no-magic-numbers\n public timeout?: number = 5000;\n\n /**\n * The text to display for the action button.\n */\n @Prop()\n public actionText: string;\n\n /**\n * When `true` displays a dismiss button on the snackbar,\n * allowing users to close it.\n */\n @Prop()\n public dismissible: boolean = true;\n\n /**\n * Whether to show the snackbar with space for multiple lines of text\n * @deprecated Setting this property no longer has any effect. The property will be removed in a future major version.\n */\n @Prop()\n public multiline: boolean;\n\n /**\n * Defines the language for translations.\n */\n @Prop()\n public language: Languages = 'en';\n\n @Element()\n private readonly host: HTMLLimelSnackbarElement;\n\n /**\n * Emitted when the action button is pressed\n */\n @Event()\n private readonly action: EventEmitter<void>;\n\n /**\n * Emitted when the snackbar hides itself\n */\n @Event()\n private readonly hide: EventEmitter<void>;\n\n @State()\n private offset: number = 0;\n\n @State()\n private isOpen: boolean = false;\n\n @State()\n private closing: boolean = true;\n\n private readonly snackbarId: string;\n private timeoutId?: number;\n\n public constructor() {\n this.snackbarId = createRandomString();\n }\n\n public componentDidLoad() {\n if (this.open) {\n requestAnimationFrame(this.handleOpen);\n }\n }\n\n @Listen('changeOffset')\n protected onChangeIndex(event: CustomEvent<number>) {\n event.stopPropagation();\n this.offset = event.detail;\n }\n\n @Watch('open')\n protected watchOpen() {\n if (this.open) {\n this.handleOpen();\n } else {\n this.handleClose();\n }\n\n this.isOpen = this.open;\n }\n\n /**\n * Show the snackbar\n * @deprecated Use the `open` property instead.\n */\n @Method()\n public async show() {\n // eslint-disable-next-line no-console\n console.warn(\n 'The `show` method in `limel-snackbar` is deprecated. Please use the `open` property instead.',\n );\n if (!this.open) {\n this.handleOpen();\n }\n }\n\n public handleOpen = () => {\n if (this.isOpen) {\n return;\n }\n\n this.isOpen = true;\n this.closing = false;\n container.add(this.host);\n\n if (this.timeout && this.timeout !== -1) {\n this.timeoutId = window.setTimeout(\n this.handleClose,\n Math.max(\n this.timeout - hideAnimationDuration,\n hideAnimationDuration,\n ),\n );\n }\n };\n\n private readonly handleClose = () => {\n if (!this.isOpen) {\n return;\n }\n\n this.closing = true;\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = undefined;\n }\n\n setTimeout(() => {\n this.isOpen = false;\n container.remove(this.host);\n this.hide.emit();\n this.offset = 0;\n }, hideAnimationDuration);\n };\n\n public render() {\n return (\n <aside\n popover=\"manual\"\n style={{\n '--snackbar-timeout': `${Math.max(this.timeout || 0, 0)}ms`,\n '--snackbar-distance-to-top-edge': `${this.offset}px`,\n }}\n class={{\n open: this.open,\n 'is-closing': this.closing,\n 'limel-portal--parent': true,\n }}\n id={this.snackbarId}\n role={this.setAriaRoles()}\n aria-relevant={this.open ? 'additions' : undefined}\n >\n <div class=\"surface\" aria-atomic=\"false\">\n <div class=\"label\">{this.message}</div>\n {this.renderActions(this.actionText)}\n {this.renderDismissButton(this.dismissible)}\n </div>\n </aside>\n );\n }\n\n private setAriaRoles() {\n if (!this.open) {\n return undefined;\n }\n\n if (!this.timeout || this.timeout === -1) {\n return 'alertdialog';\n }\n\n return 'status';\n }\n\n private readonly handleClickAction = () => {\n this.action.emit();\n };\n\n private renderActions(actionText: string) {\n if (!actionText) {\n return;\n }\n\n return (\n <div class=\"actions\" aria-atomic=\"true\">\n {this.renderActionButton(actionText)}\n </div>\n );\n }\n\n private renderActionButton(actionText: string) {\n if (!actionText) {\n return;\n }\n\n return (\n <limel-button label={actionText} onClick={this.handleClickAction} />\n );\n }\n\n private renderDismissButton(dismissible: boolean) {\n if (!dismissible) {\n return;\n }\n\n const label = translate.get('snackbar.dismiss', this.language);\n\n return (\n <div class=\"dismiss\">\n {this.renderTimeoutVisualization()}\n <limel-icon-button\n class=\"dismiss-button\"\n icon=\"multiply\"\n label={label}\n onClick={this.handleClose}\n aria-controls={this.snackbarId}\n />\n </div>\n );\n }\n\n private renderTimeoutVisualization() {\n if (!this.timeout || this.timeout === -1) {\n return;\n }\n\n return (\n <svg width=\"36\" height=\"36\" viewBox=\"0 0 36 36\">\n <circle r=\"18\" cx=\"18\" cy=\"18\" fill=\"var(--track-color)\" />\n <path\n class=\"track\"\n d=\"M 18,18 m -16,0 a 16,16 0 1,0 32,0 a 16,16 0 1,0 -32,0\"\n stroke=\"var(--fill-color)\"\n />\n </svg>\n );\n }\n}\n"],"version":3}
@@ -13,6 +13,7 @@ const TextEditor = class {
13
13
  this.change = index.createEvent(this, "change", 7);
14
14
  this.imagePasted = index.createEvent(this, "imagePasted", 7);
15
15
  this.imageRemoved = index.createEvent(this, "imageRemoved", 7);
16
+ this.metadataChange = index.createEvent(this, "metadataChange", 7);
16
17
  this.triggerStart = index.createEvent(this, "triggerStart", 7);
17
18
  this.triggerStop = index.createEvent(this, "triggerStop", 7);
18
19
  this.triggerChange = index.createEvent(this, "triggerChange", 7);
@@ -39,8 +40,13 @@ const TextEditor = class {
39
40
  event.stopPropagation();
40
41
  this.imagePasted.emit(event.detail);
41
42
  };
43
+ this.handleMetadataChange = (event) => {
44
+ event.stopPropagation();
45
+ this.metadataChange.emit(event.detail);
46
+ };
42
47
  this.handleImageRemoved = (event) => {
43
48
  event.stopPropagation();
49
+ // eslint-disable-next-line sonarjs/deprecation
44
50
  this.imageRemoved.emit(event.detail);
45
51
  };
46
52
  this.contentType = 'markdown';
@@ -67,7 +73,7 @@ const TextEditor = class {
67
73
  if (this.readonly) {
68
74
  return (index.h("limel-markdown", { slot: "content", value: this.value, "aria-controls": this.helperTextId, id: this.editorId }));
69
75
  }
70
- return (index.h("limel-prosemirror-adapter", { slot: "content", "aria-placeholder": this.placeholder, contentType: this.contentType, onChange: this.handleChange, onImagePasted: this.handleImagePasted, onImageRemoved: this.handleImageRemoved, customElements: this.customElements, value: this.value, "aria-controls": this.helperTextId, id: this.editorId, "aria-disabled": this.disabled, "aria-invalid": this.invalid, "aria-required": this.required, language: this.language, triggerCharacters: this.triggers, disabled: this.disabled, ui: this.ui }));
76
+ return (index.h("limel-prosemirror-adapter", { slot: "content", "aria-placeholder": this.placeholder, contentType: this.contentType, onChange: this.handleChange, onImagePasted: this.handleImagePasted, onImageRemoved: this.handleImageRemoved, onMetadataChange: this.handleMetadataChange, customElements: this.customElements, value: this.value, "aria-controls": this.helperTextId, id: this.editorId, "aria-disabled": this.disabled, "aria-invalid": this.invalid, "aria-required": this.required, language: this.language, triggerCharacters: this.triggers, disabled: this.disabled, ui: this.ui }));
71
77
  }
72
78
  renderPlaceholder() {
73
79
  if (!this.placeholder || this.value) {
@@ -1 +1 @@
1
- {"file":"limel-text-editor.entry.cjs.js","mappings":"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","names":["h","createRandomString","Host"],"sources":["./src/components/text-editor/text-editor.scss?tag=limel-text-editor&encapsulation=shadow","./src/components/text-editor/text-editor.tsx"],"sourcesContent":["@use '../../style/internal/shared_input-select-picker';\n@use '../../style/mixins.scss';\n\n/**\n * @prop --text-editor-max-height: the tallest height the text editor can become when auto-resizing itself. Defaults to `calc(100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)) - 4rem)`.\n * @prop --text-editor-fade-out-background-color: the color of the fade-out effect at the top and bottom of the text editor, when the text-editor is in readonly state. Defaults to rgb(var(--contrast-100)).\n */\n\n* {\n box-sizing: border-box;\n}\n\n$min-height: 5rem;\n$min-height-condensed: calc($min-height / 2);\n\n:host(limel-text-editor) {\n --limel-notched-outline-z-index: 2; // since `div.toolbar` has `z-index: 1;`\n --limel-prosemirror-adapter-toolbar-opacity: 0.6;\n --limel-text-editor-padding: 0.25rem 1rem 0.75rem 1rem;\n --limel-prosemirror-adapter-toolbar-grid-template-rows: 1fr;\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration: 0.3s;\n --limel-prosemirror-adapter-toolbar-transition-timing-function: cubic-bezier(\n 0.19,\n 0.23,\n 0.26,\n 0.89\n );\n\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n width: 100%;\n min-width: 5rem;\n min-height: $min-height;\n height: 100%;\n max-height: var(\n --text-editor-max-height,\n calc(\n 100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)) -\n 4rem\n )\n );\n padding: 1px; // prevents visual defects that can appear due to the backdrop-filter and closeness to borders\n}\n\n:host(limel-text-editor:focus-within),\n:host(limel-text-editor:not([ui='minimal']):hover) {\n --limel-prosemirror-adapter-toolbar-opacity: 1;\n}\n\n:host(limel-text-editor[ui='minimal']:not(:focus-within)) {\n --limel-prosemirror-adapter-toolbar-grid-template-rows: 0fr;\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration: 0.46s;\n --limel-prosemirror-adapter-action-bar-padding-top-bottom: 0;\n --limel-prosemirror-adapter-toolbar-opacity: 0;\n}\n\n:host(limel-text-editor[ui='minimal']:not(:focus-within)),\n:host(limel-text-editor[ui='no-toolbar']) {\n --limel-text-editor-padding: 0.75rem 1rem 0.75rem 1rem;\n --limel-text-editor-placeholder-top: 0;\n\n min-height: $min-height-condensed;\n limel-prosemirror-adapter {\n min-height: $min-height-condensed;\n }\n}\n\n:host(limel-text-editor:focus-within),\n:host(limel-text-editor:focus) {\n .placeholder {\n opacity: 0;\n }\n}\n\n:host(limel-text-editor[disabled]:not([disabled='false'])) {\n limel-prosemirror-adapter {\n @include shared_input-select-picker.looks-disabled;\n pointer-events: none;\n }\n}\n\n:host(limel-text-editor[readonly]:not([readonly='false'])) {\n --limel-text-editor-padding: 0.75rem 1rem 0.75rem 1rem;\n --limel-text-editor-placeholder-top: 0;\n\n limel-markdown {\n // displayed when `readonly` instead of the adapter\n display: block;\n padding: var(--limel-text-editor-padding);\n\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n height: 100%;\n\n &:before,\n &:after {\n z-index: 1;\n pointer-events: none;\n content: '';\n display: block;\n position: absolute;\n width: 100%;\n }\n &:after {\n height: 1.75rem;\n top: 0;\n background: linear-gradient(\n var(\n --text-editor-fade-out-background-color,\n rgb(var(--contrast-100))\n ),\n transparent\n );\n }\n\n &:before {\n height: 2rem;\n bottom: -0.25rem;\n background: linear-gradient(\n transparent,\n var(\n --text-editor-fade-out-background-color,\n rgb(var(--contrast-100))\n )\n );\n }\n }\n}\n\n.placeholder {\n transition-property: top;\n transition-duration: var(\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration\n );\n transition-timing-function: var(\n --limel-prosemirror-adapter-toolbar-transition-timing-function\n );\n @include mixins.truncate-text;\n pointer-events: none;\n position: absolute;\n top: var(--limel-text-editor-placeholder-top, 2.25rem);\n left: 0;\n right: 0;\n\n padding: var(--limel-text-editor-padding);\n font-style: italic;\n font-size: 0.875rem;\n color: shared_input-select-picker.$input-placeholder-color;\n}\n\nlimel-prosemirror-adapter {\n flex-grow: 1;\n\n min-width: 0;\n min-height: $min-height;\n height: 100%;\n overflow: hidden auto;\n -webkit-overflow-scrolling: touch;\n}\n\n@include mixins.hide-helper-line-when-not-needed(limel-text-editor);\n\n:host(limel-text-editor[allow-resize]) {\n limel-prosemirror-adapter {\n resize: vertical;\n }\n}\n","import { Component, Event, EventEmitter, Host, Prop, h } from '@stencil/core';\nimport { FormComponent } from '../form/form.types';\nimport { Languages } from '../date-picker/date.types';\nimport { createRandomString } from '../../util/random-string';\nimport { CustomElementDefinition } from '../../global/shared-types/custom-element.types';\nimport {\n TriggerCharacter,\n TriggerEventDetail,\n ImageInserter,\n ImageInfo,\n} from './text-editor.types';\nimport { EditorUiType } from './types';\n\n/**\n * A rich text editor that offers a rich text editing experience with markdown support,\n * in the sense that you can easily type markdown syntax and see the rendered\n * result as rich text in real-time. For instance, you can type `# Hello, world!`\n * and see it directly turning to a heading 1 (an `<h1>` HTML element).\n *\n * Naturally, you can use standard keyboard hotkeys such as <kbd>Ctrl</kbd> + <kbd>B</kbd>\n * to toggle bold text, <kbd>Ctrl</kbd> + <kbd>I</kbd> to toggle italic text, and so on.\n *\n * @exampleComponent limel-example-text-editor-basic\n * @exampleComponent limel-example-text-editor-as-form-component\n * @exampleComponent limel-example-text-editor-with-markdown\n * @exampleComponent limel-example-text-editor-with-html\n * @exampleComponent limel-example-text-editor-with-tables\n * @exampleComponent limel-example-text-editor-with-inline-images-file-storage\n * @exampleComponent limel-example-text-editor-with-inline-images-base64\n * @exampleComponent limel-example-text-editor-allow-resize\n * @exampleComponent limel-example-text-editor-size\n * @exampleComponent limel-example-text-editor-ui\n * @exampleComponent limel-example-text-editor-custom-element\n * @exampleComponent limel-example-text-editor-triggers\n * @exampleComponent limel-example-text-editor-composite\n * @beta\n */\n@Component({\n tag: 'limel-text-editor',\n shadow: { delegatesFocus: true },\n styleUrl: 'text-editor.scss',\n})\nexport class TextEditor implements FormComponent<string> {\n /** The type of content that the editor should handle and emit, defaults to `markdown`\n *\n * Assumed to be set only once, so not reactive to changes\n */\n @Prop()\n public contentType: 'markdown' | 'html' = 'markdown';\n\n /**\n * Defines the language for translations.\n */\n @Prop({ reflect: true })\n public language: Languages = 'en';\n\n /**\n * Set to `true` to disable the field.\n * Use `disabled` to indicate that the field can normally be interacted\n * with, but is currently disabled. This tells the user that if certain\n * requirements are met, the field may become enabled again.\n */\n @Prop({ reflect: true })\n public disabled?: boolean = false;\n\n /**\n * Set to `true` to make the component read-only.\n * Use `readonly` when the field is only there to present the data it holds,\n * and will not become possible for the current user to edit.\n * :::note\n * Consider that it might be better to use `limel-markdown`\n * instead of `limel-text-editor` when the goal is visualizing data.\n * :::\n */\n @Prop({ reflect: true })\n public readonly?: boolean = false;\n\n /**\n * Optional helper text to display below the input field when it has focus\n */\n @Prop({ reflect: true })\n public helperText?: string;\n\n /**\n * The placeholder text shown inside the input field,\n * when the field is empty.\n */\n @Prop({ reflect: true })\n public placeholder?: string;\n\n /**\n * The label of the editor\n */\n @Prop({ reflect: true })\n public label?: string;\n\n /**\n * Set to `true` to indicate that the current value of the editor is\n * invalid.\n */\n @Prop({ reflect: true })\n public invalid?: boolean = false;\n\n /**\n * Description of the text inside the editor as markdown\n */\n @Prop({ reflect: true })\n public value: string;\n\n /**\n * A list of custom elements\n *\n * Any `CustomElement` that should be used inside the text editor needs\n * to be defined here.\n *\n * @private\n * @alpha\n */\n @Prop()\n public customElements: CustomElementDefinition[] = [];\n\n /**\n * A set of trigger characters\n *\n * Defining a character here will enable trigger events to be sent if the\n * character is detected in the editor.\n *\n * @private\n * @alpha\n */\n @Prop()\n public triggers: TriggerCharacter[] = [];\n\n /**\n * Set to `true` to indicate that the field is required.\n *\n * :::important\n * An empty but required field is not automatically considered invalid.\n * You must make sure to check the validity of the field on your own,\n * and properly handle the `invalid` state.\n * :::\n */\n @Prop({ reflect: true })\n public required?: boolean = false;\n\n /**\n * Set to `true` to allow the user to vertically resize the editor.\n * Set to `false` to disable the resize functionality.\n */\n @Prop({ reflect: true })\n public allowResize: boolean = true;\n\n /**\n * Specifies the visual appearance of the editor.\n *\n * - `standard`: The default editor appearance with a full toolbar and\n * standard layout.\n * - `minimal`: A compact editor appearance, ideal for limited space\n * scenarios such as mobile devices. In this mode, the toolbar is hidden\n * until the editor is focused.\n * - `no-toolbar`: A basic textarea appearance without any text styling toolbar.\n * This mode is suitable for scenarios where you want to provide a simple\n * text input without any visible formatting options; but still provide\n * support for markdown syntax and rich text, using hotkeys or when pasting.\n */\n @Prop({ reflect: true })\n public ui?: EditorUiType = 'standard';\n\n /**\n * Dispatched when a change is made to the editor\n */\n @Event()\n public change: EventEmitter<string>;\n\n /**\n * Dispatched when a image is pasted into the editor\n *\n * @private\n * @alpha\n */\n @Event()\n private readonly imagePasted: EventEmitter<ImageInserter>;\n\n /**\n * Dispatched when a image is removed from the editor\n *\n * @private\n * @alpha\n */\n @Event()\n private readonly imageRemoved: EventEmitter<ImageInfo>;\n\n /**\n * Dispatched if a trigger character is detected.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerStart: EventEmitter<TriggerEventDetail>;\n\n /**\n * Dispatched if a trigger session is ended. That is if the selection\n * goes outside the trigger input or if something is inserted using the\n * supplied `TextEditor` insert function.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerStop: EventEmitter<TriggerEventDetail>;\n\n /**\n * Dispatched if a input is changed during an active trigger.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerChange: EventEmitter<TriggerEventDetail>;\n\n private readonly helperTextId: string;\n private readonly editorId: string;\n\n public constructor() {\n this.helperTextId = createRandomString();\n this.editorId = createRandomString();\n }\n\n public render() {\n return (\n <Host>\n <limel-notched-outline\n labelId={this.editorId}\n label={this.label}\n required={this.required}\n invalid={this.invalid}\n disabled={this.disabled}\n readonly={this.readonly}\n hasValue={!!this.value}\n hasFloatingLabel={true}\n >\n {this.renderEditor()}\n {this.renderPlaceholder()}\n </limel-notched-outline>\n {this.renderHelperLine()}\n </Host>\n );\n }\n\n private renderEditor() {\n if (this.readonly) {\n return (\n <limel-markdown\n slot=\"content\"\n value={this.value}\n aria-controls={this.helperTextId}\n id={this.editorId}\n />\n );\n }\n\n return (\n <limel-prosemirror-adapter\n slot=\"content\"\n aria-placeholder={this.placeholder}\n contentType={this.contentType}\n onChange={this.handleChange}\n onImagePasted={this.handleImagePasted}\n onImageRemoved={this.handleImageRemoved}\n customElements={this.customElements}\n value={this.value}\n aria-controls={this.helperTextId}\n id={this.editorId}\n aria-disabled={this.disabled}\n aria-invalid={this.invalid}\n aria-required={this.required}\n language={this.language}\n triggerCharacters={this.triggers}\n disabled={this.disabled}\n ui={this.ui}\n />\n );\n }\n\n private renderPlaceholder() {\n if (!this.placeholder || this.value) {\n return;\n }\n\n return (\n <span class=\"placeholder\" aria-hidden=\"true\" slot=\"content\">\n {this.placeholder}\n </span>\n );\n }\n\n private renderHelperLine = () => {\n if (!this.helperText) {\n return;\n }\n\n return (\n <limel-helper-line\n helperText={this.helperText}\n helperTextId={this.helperTextId}\n invalid={this.isInvalid()}\n />\n );\n };\n\n private isInvalid = () => {\n if (this.readonly) {\n // A readonly field can never be invalid.\n return false;\n }\n\n if (this.invalid) {\n return true;\n }\n };\n\n private handleChange = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.change.emit(event.detail);\n };\n\n private handleImagePasted = (event: CustomEvent<ImageInserter>) => {\n event.stopPropagation();\n this.imagePasted.emit(event.detail);\n };\n\n private handleImageRemoved = (event: CustomEvent<ImageInfo>) => {\n event.stopPropagation();\n this.imageRemoved.emit(event.detail);\n };\n}\n"],"version":3}
1
+ {"file":"limel-text-editor.entry.cjs.js","mappings":"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","names":["h","createRandomString","Host"],"sources":["./src/components/text-editor/text-editor.scss?tag=limel-text-editor&encapsulation=shadow","./src/components/text-editor/text-editor.tsx"],"sourcesContent":["@use '../../style/internal/shared_input-select-picker';\n@use '../../style/mixins.scss';\n\n/**\n * @prop --text-editor-max-height: the tallest height the text editor can become when auto-resizing itself. Defaults to `calc(100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)) - 4rem)`.\n * @prop --text-editor-fade-out-background-color: the color of the fade-out effect at the top and bottom of the text editor, when the text-editor is in readonly state. Defaults to rgb(var(--contrast-100)).\n */\n\n* {\n box-sizing: border-box;\n}\n\n$min-height: 5rem;\n$min-height-condensed: calc($min-height / 2);\n\n:host(limel-text-editor) {\n --limel-notched-outline-z-index: 2; // since `div.toolbar` has `z-index: 1;`\n --limel-prosemirror-adapter-toolbar-opacity: 0.6;\n --limel-text-editor-padding: 0.25rem 1rem 0.75rem 1rem;\n --limel-prosemirror-adapter-toolbar-grid-template-rows: 1fr;\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration: 0.3s;\n --limel-prosemirror-adapter-toolbar-transition-timing-function: cubic-bezier(\n 0.19,\n 0.23,\n 0.26,\n 0.89\n );\n\n position: relative;\n isolation: isolate;\n display: flex;\n flex-direction: column;\n\n width: 100%;\n min-width: 5rem;\n min-height: $min-height;\n height: 100%;\n max-height: var(\n --text-editor-max-height,\n calc(\n 100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)) -\n 4rem\n )\n );\n padding: 1px; // prevents visual defects that can appear due to the backdrop-filter and closeness to borders\n}\n\n:host(limel-text-editor:focus-within),\n:host(limel-text-editor:not([ui='minimal']):hover) {\n --limel-prosemirror-adapter-toolbar-opacity: 1;\n}\n\n:host(limel-text-editor[ui='minimal']:not(:focus-within)) {\n --limel-prosemirror-adapter-toolbar-grid-template-rows: 0fr;\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration: 0.46s;\n --limel-prosemirror-adapter-action-bar-padding-top-bottom: 0;\n --limel-prosemirror-adapter-toolbar-opacity: 0;\n}\n\n:host(limel-text-editor[ui='minimal']:not(:focus-within)),\n:host(limel-text-editor[ui='no-toolbar']) {\n --limel-text-editor-padding: 0.75rem 1rem 0.75rem 1rem;\n --limel-text-editor-placeholder-top: 0;\n\n min-height: $min-height-condensed;\n limel-prosemirror-adapter {\n min-height: $min-height-condensed;\n }\n}\n\n:host(limel-text-editor:focus-within),\n:host(limel-text-editor:focus) {\n .placeholder {\n opacity: 0;\n }\n}\n\n:host(limel-text-editor[disabled]:not([disabled='false'])) {\n limel-prosemirror-adapter {\n @include shared_input-select-picker.looks-disabled;\n pointer-events: none;\n }\n}\n\n:host(limel-text-editor[readonly]:not([readonly='false'])) {\n --limel-text-editor-padding: 0.75rem 1rem 0.75rem 1rem;\n --limel-text-editor-placeholder-top: 0;\n\n limel-markdown {\n // displayed when `readonly` instead of the adapter\n display: block;\n padding: var(--limel-text-editor-padding);\n\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n height: 100%;\n\n &:before,\n &:after {\n z-index: 1;\n pointer-events: none;\n content: '';\n display: block;\n position: absolute;\n width: 100%;\n }\n &:after {\n height: 1.75rem;\n top: 0;\n background: linear-gradient(\n var(\n --text-editor-fade-out-background-color,\n rgb(var(--contrast-100))\n ),\n transparent\n );\n }\n\n &:before {\n height: 2rem;\n bottom: -0.25rem;\n background: linear-gradient(\n transparent,\n var(\n --text-editor-fade-out-background-color,\n rgb(var(--contrast-100))\n )\n );\n }\n }\n}\n\n.placeholder {\n transition-property: top;\n transition-duration: var(\n --limel-prosemirror-adapter-toolbar-grid-template-rows-transition-duration\n );\n transition-timing-function: var(\n --limel-prosemirror-adapter-toolbar-transition-timing-function\n );\n @include mixins.truncate-text;\n pointer-events: none;\n position: absolute;\n top: var(--limel-text-editor-placeholder-top, 2.25rem);\n left: 0;\n right: 0;\n\n padding: var(--limel-text-editor-padding);\n font-style: italic;\n font-size: 0.875rem;\n color: shared_input-select-picker.$input-placeholder-color;\n}\n\nlimel-prosemirror-adapter {\n flex-grow: 1;\n\n min-width: 0;\n min-height: $min-height;\n height: 100%;\n overflow: hidden auto;\n -webkit-overflow-scrolling: touch;\n}\n\n@include mixins.hide-helper-line-when-not-needed(limel-text-editor);\n\n:host(limel-text-editor[allow-resize]) {\n limel-prosemirror-adapter {\n resize: vertical;\n }\n}\n","import { Component, Event, EventEmitter, Host, Prop, h } from '@stencil/core';\nimport { FormComponent } from '../form/form.types';\nimport { Languages } from '../date-picker/date.types';\nimport { createRandomString } from '../../util/random-string';\nimport { CustomElementDefinition } from '../../global/shared-types/custom-element.types';\nimport {\n TriggerCharacter,\n TriggerEventDetail,\n ImageInserter,\n EditorImage,\n EditorMetadata,\n} from './text-editor.types';\nimport { EditorUiType } from './types';\n\n/**\n * A rich text editor that offers a rich text editing experience with markdown support,\n * in the sense that you can easily type markdown syntax and see the rendered\n * result as rich text in real-time. For instance, you can type `# Hello, world!`\n * and see it directly turning to a heading 1 (an `<h1>` HTML element).\n *\n * Naturally, you can use standard keyboard hotkeys such as <kbd>Ctrl</kbd> + <kbd>B</kbd>\n * to toggle bold text, <kbd>Ctrl</kbd> + <kbd>I</kbd> to toggle italic text, and so on.\n *\n * @exampleComponent limel-example-text-editor-basic\n * @exampleComponent limel-example-text-editor-as-form-component\n * @exampleComponent limel-example-text-editor-with-markdown\n * @exampleComponent limel-example-text-editor-with-html\n * @exampleComponent limel-example-text-editor-with-tables\n * @exampleComponent limel-example-text-editor-with-inline-images-file-storage\n * @exampleComponent limel-example-text-editor-with-inline-images-base64\n * @exampleComponent limel-example-text-editor-allow-resize\n * @exampleComponent limel-example-text-editor-size\n * @exampleComponent limel-example-text-editor-ui\n * @exampleComponent limel-example-text-editor-custom-element\n * @exampleComponent limel-example-text-editor-triggers\n * @exampleComponent limel-example-text-editor-composite\n * @beta\n */\n@Component({\n tag: 'limel-text-editor',\n shadow: { delegatesFocus: true },\n styleUrl: 'text-editor.scss',\n})\nexport class TextEditor implements FormComponent<string> {\n /** The type of content that the editor should handle and emit, defaults to `markdown`\n *\n * Assumed to be set only once, so not reactive to changes\n */\n @Prop()\n public contentType: 'markdown' | 'html' = 'markdown';\n\n /**\n * Defines the language for translations.\n */\n @Prop({ reflect: true })\n public language: Languages = 'en';\n\n /**\n * Set to `true` to disable the field.\n * Use `disabled` to indicate that the field can normally be interacted\n * with, but is currently disabled. This tells the user that if certain\n * requirements are met, the field may become enabled again.\n */\n @Prop({ reflect: true })\n public disabled?: boolean = false;\n\n /**\n * Set to `true` to make the component read-only.\n * Use `readonly` when the field is only there to present the data it holds,\n * and will not become possible for the current user to edit.\n * :::note\n * Consider that it might be better to use `limel-markdown`\n * instead of `limel-text-editor` when the goal is visualizing data.\n * :::\n */\n @Prop({ reflect: true })\n public readonly?: boolean = false;\n\n /**\n * Optional helper text to display below the input field when it has focus\n */\n @Prop({ reflect: true })\n public helperText?: string;\n\n /**\n * The placeholder text shown inside the input field,\n * when the field is empty.\n */\n @Prop({ reflect: true })\n public placeholder?: string;\n\n /**\n * The label of the editor\n */\n @Prop({ reflect: true })\n public label?: string;\n\n /**\n * Set to `true` to indicate that the current value of the editor is\n * invalid.\n */\n @Prop({ reflect: true })\n public invalid?: boolean = false;\n\n /**\n * Description of the text inside the editor as markdown\n */\n @Prop({ reflect: true })\n public value: string;\n\n /**\n * A list of custom elements\n *\n * Any `CustomElement` that should be used inside the text editor needs\n * to be defined here.\n *\n * @private\n * @alpha\n */\n @Prop()\n public customElements: CustomElementDefinition[] = [];\n\n /**\n * A set of trigger characters\n *\n * Defining a character here will enable trigger events to be sent if the\n * character is detected in the editor.\n *\n * @private\n * @alpha\n */\n @Prop()\n public triggers: TriggerCharacter[] = [];\n\n /**\n * Set to `true` to indicate that the field is required.\n *\n * :::important\n * An empty but required field is not automatically considered invalid.\n * You must make sure to check the validity of the field on your own,\n * and properly handle the `invalid` state.\n * :::\n */\n @Prop({ reflect: true })\n public required?: boolean = false;\n\n /**\n * Set to `true` to allow the user to vertically resize the editor.\n * Set to `false` to disable the resize functionality.\n */\n @Prop({ reflect: true })\n public allowResize: boolean = true;\n\n /**\n * Specifies the visual appearance of the editor.\n *\n * - `standard`: The default editor appearance with a full toolbar and\n * standard layout.\n * - `minimal`: A compact editor appearance, ideal for limited space\n * scenarios such as mobile devices. In this mode, the toolbar is hidden\n * until the editor is focused.\n * - `no-toolbar`: A basic textarea appearance without any text styling toolbar.\n * This mode is suitable for scenarios where you want to provide a simple\n * text input without any visible formatting options; but still provide\n * support for markdown syntax and rich text, using hotkeys or when pasting.\n */\n @Prop({ reflect: true })\n public ui?: EditorUiType = 'standard';\n\n /**\n * Dispatched when a change is made to the editor\n */\n @Event()\n public change: EventEmitter<string>;\n\n /**\n * Dispatched when a image is pasted into the editor\n *\n * @private\n * @alpha\n */\n @Event()\n private readonly imagePasted: EventEmitter<ImageInserter>;\n\n /**\n * Dispatched when a image is removed from the editor\n *\n * @private\n * @alpha\n * @deprecated - This event is deprecated and will be removed in a future version.\n * Use the `metadataChange` event instead to track image removals.\n */\n @Event()\n private readonly imageRemoved: EventEmitter<EditorImage>;\n\n /**\n * Dispatched when the metadata of the editor changes\n *\n * @private\n * @alpha\n */\n @Event()\n private readonly metadataChange: EventEmitter<EditorMetadata>;\n\n /**\n * Dispatched if a trigger character is detected.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerStart: EventEmitter<TriggerEventDetail>;\n\n /**\n * Dispatched if a trigger session is ended. That is if the selection\n * goes outside the trigger input or if something is inserted using the\n * supplied `TextEditor` insert function.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerStop: EventEmitter<TriggerEventDetail>;\n\n /**\n * Dispatched if a input is changed during an active trigger.\n *\n * @private\n * @alpha\n */\n @Event()\n public triggerChange: EventEmitter<TriggerEventDetail>;\n\n private readonly helperTextId: string;\n private readonly editorId: string;\n\n public constructor() {\n this.helperTextId = createRandomString();\n this.editorId = createRandomString();\n }\n\n public render() {\n return (\n <Host>\n <limel-notched-outline\n labelId={this.editorId}\n label={this.label}\n required={this.required}\n invalid={this.invalid}\n disabled={this.disabled}\n readonly={this.readonly}\n hasValue={!!this.value}\n hasFloatingLabel={true}\n >\n {this.renderEditor()}\n {this.renderPlaceholder()}\n </limel-notched-outline>\n {this.renderHelperLine()}\n </Host>\n );\n }\n\n private renderEditor() {\n if (this.readonly) {\n return (\n <limel-markdown\n slot=\"content\"\n value={this.value}\n aria-controls={this.helperTextId}\n id={this.editorId}\n />\n );\n }\n\n return (\n <limel-prosemirror-adapter\n slot=\"content\"\n aria-placeholder={this.placeholder}\n contentType={this.contentType}\n onChange={this.handleChange}\n onImagePasted={this.handleImagePasted}\n onImageRemoved={this.handleImageRemoved}\n onMetadataChange={this.handleMetadataChange}\n customElements={this.customElements}\n value={this.value}\n aria-controls={this.helperTextId}\n id={this.editorId}\n aria-disabled={this.disabled}\n aria-invalid={this.invalid}\n aria-required={this.required}\n language={this.language}\n triggerCharacters={this.triggers}\n disabled={this.disabled}\n ui={this.ui}\n />\n );\n }\n\n private renderPlaceholder() {\n if (!this.placeholder || this.value) {\n return;\n }\n\n return (\n <span class=\"placeholder\" aria-hidden=\"true\" slot=\"content\">\n {this.placeholder}\n </span>\n );\n }\n\n private renderHelperLine = () => {\n if (!this.helperText) {\n return;\n }\n\n return (\n <limel-helper-line\n helperText={this.helperText}\n helperTextId={this.helperTextId}\n invalid={this.isInvalid()}\n />\n );\n };\n\n private isInvalid = () => {\n if (this.readonly) {\n // A readonly field can never be invalid.\n return false;\n }\n\n if (this.invalid) {\n return true;\n }\n };\n\n private handleChange = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.change.emit(event.detail);\n };\n\n private handleImagePasted = (event: CustomEvent<ImageInserter>) => {\n event.stopPropagation();\n this.imagePasted.emit(event.detail);\n };\n\n private handleMetadataChange = (event: CustomEvent<EditorMetadata>) => {\n event.stopPropagation();\n this.metadataChange.emit(event.detail);\n };\n\n private handleImageRemoved = (event: CustomEvent<EditorImage>) => {\n event.stopPropagation();\n // eslint-disable-next-line sonarjs/deprecation\n this.imageRemoved.emit(event.detail);\n };\n}\n"],"version":3}
@@ -1,7 +1,7 @@
1
1
  import { h, } from '@stencil/core';
2
2
  import translate from '../../global/translations';
3
3
  import { SnackbarContainer } from './container';
4
- import { createRandomString } from 'src/util/random-string';
4
+ import { createRandomString } from '../../util/random-string';
5
5
  const container = new SnackbarContainer();
6
6
  const hideAnimationDuration = 300;
7
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"snackbar.js","sourceRoot":"","sources":["../../../src/components/snackbar/snackbar.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Languages } from '../date-picker/date.types';\nimport {\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Listen,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport translate from '../../global/translations';\nimport { SnackbarContainer } from './container';\nimport { createRandomString } from 'src/util/random-string';\n\nconst container = new SnackbarContainer();\nconst hideAnimationDuration = 300;\n\n/**\n * A Snackbar –also known as \"Toast\"– is used to inform the end user\n * about an action or a process in the system.\n * The information could vary from announcing that a process has just started,\n * is taking place now, has ended, or has been interrupted or canceled.\n *\n * The information that you provide using a snackbar should be:\n * - temporary\n * - contextual\n * - short\n * - and most importantly, ignorable.\n *\n * It means if the user misses the information, it shouldn't be a big deal.\n *\n * :::note\n * If the information you want to display has a higher importance or priority,\n * and you need to make sure that the user takes an action to dismiss it,\n * consider using the [Banner](/#/component/limel-banner/) component instead.\n * For more complex interactions and for delivering more detailed information,\n * [Dialog](/#/component/limel-dialog/) is a better choice.\n * :::\n *\n * @exampleComponent limel-example-snackbar\n * @exampleComponent limel-example-snackbar-with-action\n * @exampleComponent limel-example-snackbar-with-changing-messages\n * @exampleComponent limel-example-snackbar-dismissible\n * @exampleComponent limel-example-snackbar-persistent\n * @exampleComponent limel-example-snackbar-persistent-non-dismissible\n */\n@Component({\n tag: 'limel-snackbar',\n shadow: true,\n styleUrl: 'snackbar.scss',\n})\nexport class Snackbar {\n /**\n * `true` if the snackbar is open, `false` otherwise.\n */\n @Prop({ reflect: true })\n public open: boolean = false;\n\n /**\n * The text message to display.\n */\n @Prop()\n public message: string;\n\n /**\n * The amount of time in milliseconds to show the snackbar.\n * If set to `-1`, the snackbar will be persistent.\n * This means:\n * - either the end user will need to close it manually,\n * which requires the `dismissible` property to be set to `true`.\n * - or the snackbar needs to be closed programmatically.\n */\n @Prop({ reflect: true })\n // eslint-disable-next-line no-magic-numbers\n public timeout?: number = 5000;\n\n /**\n * The text to display for the action button.\n */\n @Prop()\n public actionText: string;\n\n /**\n * When `true` displays a dismiss button on the snackbar,\n * allowing users to close it.\n */\n @Prop()\n public dismissible: boolean = true;\n\n /**\n * Whether to show the snackbar with space for multiple lines of text\n * @deprecated Setting this property no longer has any effect. The property will be removed in a future major version.\n */\n @Prop()\n public multiline: boolean;\n\n /**\n * Defines the language for translations.\n */\n @Prop()\n public language: Languages = 'en';\n\n @Element()\n private readonly host: HTMLLimelSnackbarElement;\n\n /**\n * Emitted when the action button is pressed\n */\n @Event()\n private readonly action: EventEmitter<void>;\n\n /**\n * Emitted when the snackbar hides itself\n */\n @Event()\n private readonly hide: EventEmitter<void>;\n\n @State()\n private offset: number = 0;\n\n @State()\n private isOpen: boolean = false;\n\n @State()\n private closing: boolean = true;\n\n private readonly snackbarId: string;\n private timeoutId?: number;\n\n public constructor() {\n this.snackbarId = createRandomString();\n }\n\n public componentDidLoad() {\n if (this.open) {\n requestAnimationFrame(this.handleOpen);\n }\n }\n\n @Listen('changeOffset')\n protected onChangeIndex(event: CustomEvent<number>) {\n event.stopPropagation();\n this.offset = event.detail;\n }\n\n @Watch('open')\n protected watchOpen() {\n if (this.open) {\n this.handleOpen();\n } else {\n this.handleClose();\n }\n\n this.isOpen = this.open;\n }\n\n /**\n * Show the snackbar\n * @deprecated Use the `open` property instead.\n */\n @Method()\n public async show() {\n // eslint-disable-next-line no-console\n console.warn(\n 'The `show` method in `limel-snackbar` is deprecated. Please use the `open` property instead.',\n );\n if (!this.open) {\n this.handleOpen();\n }\n }\n\n public handleOpen = () => {\n if (this.isOpen) {\n return;\n }\n\n this.isOpen = true;\n this.closing = false;\n container.add(this.host);\n\n if (this.timeout && this.timeout !== -1) {\n this.timeoutId = window.setTimeout(\n this.handleClose,\n Math.max(\n this.timeout - hideAnimationDuration,\n hideAnimationDuration,\n ),\n );\n }\n };\n\n private readonly handleClose = () => {\n if (!this.isOpen) {\n return;\n }\n\n this.closing = true;\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = undefined;\n }\n\n setTimeout(() => {\n this.isOpen = false;\n container.remove(this.host);\n this.hide.emit();\n this.offset = 0;\n }, hideAnimationDuration);\n };\n\n public render() {\n return (\n <aside\n popover=\"manual\"\n style={{\n '--snackbar-timeout': `${Math.max(this.timeout || 0, 0)}ms`,\n '--snackbar-distance-to-top-edge': `${this.offset}px`,\n }}\n class={{\n open: this.open,\n 'is-closing': this.closing,\n 'limel-portal--parent': true,\n }}\n id={this.snackbarId}\n role={this.setAriaRoles()}\n aria-relevant={this.open ? 'additions' : undefined}\n >\n <div class=\"surface\" aria-atomic=\"false\">\n <div class=\"label\">{this.message}</div>\n {this.renderActions(this.actionText)}\n {this.renderDismissButton(this.dismissible)}\n </div>\n </aside>\n );\n }\n\n private setAriaRoles() {\n if (!this.open) {\n return undefined;\n }\n\n if (!this.timeout || this.timeout === -1) {\n return 'alertdialog';\n }\n\n return 'status';\n }\n\n private readonly handleClickAction = () => {\n this.action.emit();\n };\n\n private renderActions(actionText: string) {\n if (!actionText) {\n return;\n }\n\n return (\n <div class=\"actions\" aria-atomic=\"true\">\n {this.renderActionButton(actionText)}\n </div>\n );\n }\n\n private renderActionButton(actionText: string) {\n if (!actionText) {\n return;\n }\n\n return (\n <limel-button label={actionText} onClick={this.handleClickAction} />\n );\n }\n\n private renderDismissButton(dismissible: boolean) {\n if (!dismissible) {\n return;\n }\n\n const label = translate.get('snackbar.dismiss', this.language);\n\n return (\n <div class=\"dismiss\">\n {this.renderTimeoutVisualization()}\n <limel-icon-button\n class=\"dismiss-button\"\n icon=\"multiply\"\n label={label}\n onClick={this.handleClose}\n aria-controls={this.snackbarId}\n />\n </div>\n );\n }\n\n private renderTimeoutVisualization() {\n if (!this.timeout || this.timeout === -1) {\n return;\n }\n\n return (\n <svg width=\"36\" height=\"36\" viewBox=\"0 0 36 36\">\n <circle r=\"18\" cx=\"18\" cy=\"18\" fill=\"var(--track-color)\" />\n <path\n class=\"track\"\n d=\"M 18,18 m -16,0 a 16,16 0 1,0 32,0 a 16,16 0 1,0 -32,0\"\n stroke=\"var(--fill-color)\"\n />\n </svg>\n );\n }\n}\n"]}
1
+ {"version":3,"file":"snackbar.js","sourceRoot":"","sources":["../../../src/components/snackbar/snackbar.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Languages } from '../date-picker/date.types';\nimport {\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Listen,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport translate from '../../global/translations';\nimport { SnackbarContainer } from './container';\nimport { createRandomString } from '../../util/random-string';\n\nconst container = new SnackbarContainer();\nconst hideAnimationDuration = 300;\n\n/**\n * A Snackbar –also known as \"Toast\"– is used to inform the end user\n * about an action or a process in the system.\n * The information could vary from announcing that a process has just started,\n * is taking place now, has ended, or has been interrupted or canceled.\n *\n * The information that you provide using a snackbar should be:\n * - temporary\n * - contextual\n * - short\n * - and most importantly, ignorable.\n *\n * It means if the user misses the information, it shouldn't be a big deal.\n *\n * :::note\n * If the information you want to display has a higher importance or priority,\n * and you need to make sure that the user takes an action to dismiss it,\n * consider using the [Banner](/#/component/limel-banner/) component instead.\n * For more complex interactions and for delivering more detailed information,\n * [Dialog](/#/component/limel-dialog/) is a better choice.\n * :::\n *\n * @exampleComponent limel-example-snackbar\n * @exampleComponent limel-example-snackbar-with-action\n * @exampleComponent limel-example-snackbar-with-changing-messages\n * @exampleComponent limel-example-snackbar-dismissible\n * @exampleComponent limel-example-snackbar-persistent\n * @exampleComponent limel-example-snackbar-persistent-non-dismissible\n */\n@Component({\n tag: 'limel-snackbar',\n shadow: true,\n styleUrl: 'snackbar.scss',\n})\nexport class Snackbar {\n /**\n * `true` if the snackbar is open, `false` otherwise.\n */\n @Prop({ reflect: true })\n public open: boolean = false;\n\n /**\n * The text message to display.\n */\n @Prop()\n public message: string;\n\n /**\n * The amount of time in milliseconds to show the snackbar.\n * If set to `-1`, the snackbar will be persistent.\n * This means:\n * - either the end user will need to close it manually,\n * which requires the `dismissible` property to be set to `true`.\n * - or the snackbar needs to be closed programmatically.\n */\n @Prop({ reflect: true })\n // eslint-disable-next-line no-magic-numbers\n public timeout?: number = 5000;\n\n /**\n * The text to display for the action button.\n */\n @Prop()\n public actionText: string;\n\n /**\n * When `true` displays a dismiss button on the snackbar,\n * allowing users to close it.\n */\n @Prop()\n public dismissible: boolean = true;\n\n /**\n * Whether to show the snackbar with space for multiple lines of text\n * @deprecated Setting this property no longer has any effect. The property will be removed in a future major version.\n */\n @Prop()\n public multiline: boolean;\n\n /**\n * Defines the language for translations.\n */\n @Prop()\n public language: Languages = 'en';\n\n @Element()\n private readonly host: HTMLLimelSnackbarElement;\n\n /**\n * Emitted when the action button is pressed\n */\n @Event()\n private readonly action: EventEmitter<void>;\n\n /**\n * Emitted when the snackbar hides itself\n */\n @Event()\n private readonly hide: EventEmitter<void>;\n\n @State()\n private offset: number = 0;\n\n @State()\n private isOpen: boolean = false;\n\n @State()\n private closing: boolean = true;\n\n private readonly snackbarId: string;\n private timeoutId?: number;\n\n public constructor() {\n this.snackbarId = createRandomString();\n }\n\n public componentDidLoad() {\n if (this.open) {\n requestAnimationFrame(this.handleOpen);\n }\n }\n\n @Listen('changeOffset')\n protected onChangeIndex(event: CustomEvent<number>) {\n event.stopPropagation();\n this.offset = event.detail;\n }\n\n @Watch('open')\n protected watchOpen() {\n if (this.open) {\n this.handleOpen();\n } else {\n this.handleClose();\n }\n\n this.isOpen = this.open;\n }\n\n /**\n * Show the snackbar\n * @deprecated Use the `open` property instead.\n */\n @Method()\n public async show() {\n // eslint-disable-next-line no-console\n console.warn(\n 'The `show` method in `limel-snackbar` is deprecated. Please use the `open` property instead.',\n );\n if (!this.open) {\n this.handleOpen();\n }\n }\n\n public handleOpen = () => {\n if (this.isOpen) {\n return;\n }\n\n this.isOpen = true;\n this.closing = false;\n container.add(this.host);\n\n if (this.timeout && this.timeout !== -1) {\n this.timeoutId = window.setTimeout(\n this.handleClose,\n Math.max(\n this.timeout - hideAnimationDuration,\n hideAnimationDuration,\n ),\n );\n }\n };\n\n private readonly handleClose = () => {\n if (!this.isOpen) {\n return;\n }\n\n this.closing = true;\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = undefined;\n }\n\n setTimeout(() => {\n this.isOpen = false;\n container.remove(this.host);\n this.hide.emit();\n this.offset = 0;\n }, hideAnimationDuration);\n };\n\n public render() {\n return (\n <aside\n popover=\"manual\"\n style={{\n '--snackbar-timeout': `${Math.max(this.timeout || 0, 0)}ms`,\n '--snackbar-distance-to-top-edge': `${this.offset}px`,\n }}\n class={{\n open: this.open,\n 'is-closing': this.closing,\n 'limel-portal--parent': true,\n }}\n id={this.snackbarId}\n role={this.setAriaRoles()}\n aria-relevant={this.open ? 'additions' : undefined}\n >\n <div class=\"surface\" aria-atomic=\"false\">\n <div class=\"label\">{this.message}</div>\n {this.renderActions(this.actionText)}\n {this.renderDismissButton(this.dismissible)}\n </div>\n </aside>\n );\n }\n\n private setAriaRoles() {\n if (!this.open) {\n return undefined;\n }\n\n if (!this.timeout || this.timeout === -1) {\n return 'alertdialog';\n }\n\n return 'status';\n }\n\n private readonly handleClickAction = () => {\n this.action.emit();\n };\n\n private renderActions(actionText: string) {\n if (!actionText) {\n return;\n }\n\n return (\n <div class=\"actions\" aria-atomic=\"true\">\n {this.renderActionButton(actionText)}\n </div>\n );\n }\n\n private renderActionButton(actionText: string) {\n if (!actionText) {\n return;\n }\n\n return (\n <limel-button label={actionText} onClick={this.handleClickAction} />\n );\n }\n\n private renderDismissButton(dismissible: boolean) {\n if (!dismissible) {\n return;\n }\n\n const label = translate.get('snackbar.dismiss', this.language);\n\n return (\n <div class=\"dismiss\">\n {this.renderTimeoutVisualization()}\n <limel-icon-button\n class=\"dismiss-button\"\n icon=\"multiply\"\n label={label}\n onClick={this.handleClose}\n aria-controls={this.snackbarId}\n />\n </div>\n );\n }\n\n private renderTimeoutVisualization() {\n if (!this.timeout || this.timeout === -1) {\n return;\n }\n\n return (\n <svg width=\"36\" height=\"36\" viewBox=\"0 0 36 36\">\n <circle r=\"18\" cx=\"18\" cy=\"18\" fill=\"var(--track-color)\" />\n <path\n class=\"track\"\n d=\"M 18,18 m -16,0 a 16,16 0 1,0 32,0 a 16,16 0 1,0 -32,0\"\n stroke=\"var(--fill-color)\"\n />\n </svg>\n );\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"menu-items.js","sourceRoot":"","sources":["../../../../../src/components/text-editor/prosemirror-adapter/menu/menu-items.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,iBAAiB,GAAG,GAIxB,EAAE;EACA,MAAM,YAAY,GAAG,kCAAkC,CAAC;EACxD,IAAI,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE;IACxC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;GAChD;EAED,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC1D,CAAC,CAAC;AAEF,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,iBAAiB,EAAE,CAAC;AAE3C,MAAM,mBAAmB,GAErB;EACA;IACI,KAAK,EAAE,eAAe,CAAC,IAAI;IAC3B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,GAAG,GAAG,IAAI;IACvB,IAAI,EAAE,iBAAiB;IACvB,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD;IACI,KAAK,EAAE,eAAe,CAAC,MAAM;IAC7B,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,GAAG,GAAG,IAAI;IACvB,IAAI,EAAE,mBAAmB;IACzB,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD;IACI,KAAK,EAAE,eAAe,CAAC,aAAa;IACpC,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,GAAG,GAAG,IAAI,KAAK,IAAI;IAChC,IAAI,EAAE,0BAA0B;IAChC,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD;IACI,KAAK,EAAE,eAAe,CAAC,IAAI;IAC3B,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,iBAAiB;IACvB,QAAQ,EAAE,IAAI;GACjB;EACD,EAAE,SAAS,EAAE,IAAI,EAAE;EACnB;IACI,KAAK,EAAE,eAAe,CAAC,UAAU;IACjC,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,0BAA0B;IAChC,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD;IACI,KAAK,EAAE,eAAe,CAAC,WAAW;IAClC,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,yBAAyB;IAC/B,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD,EAAE,SAAS,EAAE,IAAI,EAAE;EACnB;IACI,KAAK,EAAE,eAAe,CAAC,YAAY;IACnC,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,GAAG,GAAG,IAAI,KAAK,IAAI;IAChC,IAAI,EAAE,wBAAwB;IAC9B,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD;IACI,KAAK,EAAE,eAAe,CAAC,YAAY;IACnC,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,GAAG,GAAG,IAAI,KAAK,IAAI;IAChC,IAAI,EAAE,wBAAwB;IAC9B,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD;IACI,KAAK,EAAE,eAAe,CAAC,YAAY;IACnC,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,GAAG,GAAG,IAAI,KAAK,IAAI;IAChC,IAAI,EAAE,wBAAwB;IAC9B,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD,EAAE,SAAS,EAAE,IAAI,EAAE;EACnB;IACI,KAAK,EAAE,eAAe,CAAC,UAAU;IACjC,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,uBAAuB;IAC7B,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD,EAAE,SAAS,EAAE,IAAI,EAAE;EACnB;IACI,KAAK,EAAE,eAAe,CAAC,IAAI;IAC3B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,GAAG,GAAG,KAAK;IACxB,IAAI,EAAE,iBAAiB;IACvB,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;EACD;IACI,KAAK,EAAE,eAAe,CAAC,SAAS;IAChC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,GAAG,GAAG,IAAI,KAAK,IAAI;IAChC,IAAI,EAAE,uBAAuB;IAC7B,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;GAClB;CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;AAE3E,MAAM,CAAC,MAAM,kBAAkB,GAAG;EAC9B,MAAM,EAAE,kBAAkB;EAC1B,EAAE,EAAE,oBAAoB;EACxB,YAAY,EAAE,gBAAgB;EAC9B,YAAY,EAAE,gBAAgB;EAC9B,YAAY,EAAE,gBAAgB;EAC9B,8BAA8B;EAC9B,WAAW,EAAE,2BAA2B;EACxC,YAAY,EAAE,2BAA2B;EACzC,UAAU,EAAE,wBAAwB;EACpC,6BAA6B;EAC7B,UAAU,EAAE,wBAAwB;EACpC,IAAI,EAAE,kBAAkB;EACxB,aAAa,EAAE,2BAA2B;EAC1C,IAAI,EAAE,kBAAkB;CAC3B,CAAC","sourcesContent":["import { ActionBarItem } from 'src/components/action-bar/action-bar.types';\nimport { ListSeparator } from 'src/components/list/list-item.types';\nimport { EditorMenuTypes } from './types';\nimport { cloneDeep } from 'lodash-es';\n\nconst getCommandSymbols = (): {\n mod: string;\n option: string;\n shift: string;\n} => {\n const macUserAgent = /Macintosh|MacIntel|MacPPC|Mac68K/;\n if (macUserAgent.exec(navigator.userAgent)) {\n return { mod: '⌘', option: '⌥', shift: '⇧' };\n }\n\n return { mod: 'Ctrl', option: 'Alt', shift: 'Shift' };\n};\n\nconst { mod, shift } = getCommandSymbols();\n\nconst textEditorMenuItems: Array<\n ActionBarItem<EditorMenuTypes> | ListSeparator\n> = [\n {\n value: EditorMenuTypes.Bold,\n text: 'Bold',\n commandText: `${mod} B`,\n icon: '-lime-text-bold',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.Italic,\n text: 'Italic',\n commandText: `${mod} I`,\n icon: '-lime-text-italic',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.Strikethrough,\n text: 'Strikethrough',\n commandText: `${mod} ${shift} X`,\n icon: '-lime-text-strikethrough',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.Link,\n text: 'Link',\n icon: '-lime-text-link',\n iconOnly: true,\n },\n { separator: true },\n {\n value: EditorMenuTypes.BulletList,\n text: 'Bullet list',\n icon: '-lime-text-bulleted-list',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.OrderedList,\n text: 'Numbered list',\n icon: '-lime-text-ordered-list',\n iconOnly: true,\n selected: false,\n },\n { separator: true },\n {\n value: EditorMenuTypes.HeaderLevel1,\n text: 'Header 1',\n commandText: `${mod} ${shift} 1`,\n icon: '-lime-text-h-heading-1',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.HeaderLevel2,\n text: 'Header 2',\n commandText: `${mod} ${shift} 2`,\n icon: '-lime-text-h-heading-2',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.HeaderLevel3,\n text: 'Header 3',\n commandText: `${mod} ${shift} 3`,\n icon: '-lime-text-h-heading-3',\n iconOnly: true,\n selected: false,\n },\n { separator: true },\n {\n value: EditorMenuTypes.Blockquote,\n text: 'Blockquote',\n icon: '-lime-text-blockquote',\n iconOnly: true,\n selected: false,\n },\n { separator: true },\n {\n value: EditorMenuTypes.Code,\n text: 'Code',\n commandText: `${mod} \\``,\n icon: '-lime-text-code',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.CodeBlock,\n text: 'Code Block',\n commandText: `${mod} ${shift} C`,\n icon: '-lime-text-code-block',\n iconOnly: true,\n selected: false,\n },\n];\n\nexport const getTextEditorMenuItems = () => cloneDeep(textEditorMenuItems);\n\nexport const menuTranslationIDs = {\n strong: 'editor-menu.bold',\n em: 'editor-menu.italic',\n headerlevel1: 'editor-menu.h1',\n headerlevel2: 'editor-menu.h2',\n headerlevel3: 'editor-menu.h3',\n /* eslint-disable camelcase */\n bullet_list: 'editor-menu.bulleted-list',\n ordered_list: 'editor-menu.numbered-list',\n code_block: 'editor-menu.code-block',\n /* eslint-enable camelcase */\n blockquote: 'editor-menu.blockquote',\n link: 'editor-menu.link',\n strikethrough: 'editor-menu.strikethrough',\n code: 'editor-menu.code',\n};\n\nexport type menuTranslationIDs =\n (typeof menuTranslationIDs)[keyof typeof menuTranslationIDs];\n"]}
1
+ {"version":3,"file":"menu-items.js","sourceRoot":"","sources":["../../../../../src/components/text-editor/prosemirror-adapter/menu/menu-items.ts"],"names":[],"mappings":"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","sourcesContent":["import { ActionBarItem } from '../../../action-bar/action-bar.types';\nimport { ListSeparator } from '../../../list/list-item.types';\nimport { EditorMenuTypes } from './types';\nimport { cloneDeep } from 'lodash-es';\n\nconst getCommandSymbols = (): {\n mod: string;\n option: string;\n shift: string;\n} => {\n const macUserAgent = /Macintosh|MacIntel|MacPPC|Mac68K/;\n if (macUserAgent.exec(navigator.userAgent)) {\n return { mod: '⌘', option: '⌥', shift: '⇧' };\n }\n\n return { mod: 'Ctrl', option: 'Alt', shift: 'Shift' };\n};\n\nconst { mod, shift } = getCommandSymbols();\n\nconst textEditorMenuItems: Array<\n ActionBarItem<EditorMenuTypes> | ListSeparator\n> = [\n {\n value: EditorMenuTypes.Bold,\n text: 'Bold',\n commandText: `${mod} B`,\n icon: '-lime-text-bold',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.Italic,\n text: 'Italic',\n commandText: `${mod} I`,\n icon: '-lime-text-italic',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.Strikethrough,\n text: 'Strikethrough',\n commandText: `${mod} ${shift} X`,\n icon: '-lime-text-strikethrough',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.Link,\n text: 'Link',\n icon: '-lime-text-link',\n iconOnly: true,\n },\n { separator: true },\n {\n value: EditorMenuTypes.BulletList,\n text: 'Bullet list',\n icon: '-lime-text-bulleted-list',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.OrderedList,\n text: 'Numbered list',\n icon: '-lime-text-ordered-list',\n iconOnly: true,\n selected: false,\n },\n { separator: true },\n {\n value: EditorMenuTypes.HeaderLevel1,\n text: 'Header 1',\n commandText: `${mod} ${shift} 1`,\n icon: '-lime-text-h-heading-1',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.HeaderLevel2,\n text: 'Header 2',\n commandText: `${mod} ${shift} 2`,\n icon: '-lime-text-h-heading-2',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.HeaderLevel3,\n text: 'Header 3',\n commandText: `${mod} ${shift} 3`,\n icon: '-lime-text-h-heading-3',\n iconOnly: true,\n selected: false,\n },\n { separator: true },\n {\n value: EditorMenuTypes.Blockquote,\n text: 'Blockquote',\n icon: '-lime-text-blockquote',\n iconOnly: true,\n selected: false,\n },\n { separator: true },\n {\n value: EditorMenuTypes.Code,\n text: 'Code',\n commandText: `${mod} \\``,\n icon: '-lime-text-code',\n iconOnly: true,\n selected: false,\n },\n {\n value: EditorMenuTypes.CodeBlock,\n text: 'Code Block',\n commandText: `${mod} ${shift} C`,\n icon: '-lime-text-code-block',\n iconOnly: true,\n selected: false,\n },\n];\n\nexport const getTextEditorMenuItems = () => cloneDeep(textEditorMenuItems);\n\nexport const menuTranslationIDs = {\n strong: 'editor-menu.bold',\n em: 'editor-menu.italic',\n headerlevel1: 'editor-menu.h1',\n headerlevel2: 'editor-menu.h2',\n headerlevel3: 'editor-menu.h3',\n /* eslint-disable camelcase */\n bullet_list: 'editor-menu.bulleted-list',\n ordered_list: 'editor-menu.numbered-list',\n code_block: 'editor-menu.code-block',\n /* eslint-enable camelcase */\n blockquote: 'editor-menu.blockquote',\n link: 'editor-menu.link',\n strikethrough: 'editor-menu.strikethrough',\n code: 'editor-menu.code',\n};\n\nexport type menuTranslationIDs =\n (typeof menuTranslationIDs)[keyof typeof menuTranslationIDs];\n"]}
@@ -1,10 +1,8 @@
1
1
  import { Plugin, PluginKey } from 'prosemirror-state';
2
2
  import { createFileInfo } from '../../../../../util/files';
3
- import { ImageState, } from '../../../text-editor.types';
4
3
  import { Node, Slice, Fragment } from 'prosemirror-model';
5
- import { imageCache } from './node';
6
4
  export const pluginKey = new PluginKey('imageInserterPlugin');
7
- export const createImageInserterPlugin = (imagePastedCallback, imageRemovedCallback) => {
5
+ export const createImageInserterPlugin = (imagePastedCallback) => {
8
6
  return new Plugin({
9
7
  key: pluginKey,
10
8
  props: {
@@ -17,40 +15,7 @@ export const createImageInserterPlugin = (imagePastedCallback, imageRemovedCallb
17
15
  },
18
16
  },
19
17
  },
20
- state: {
21
- init: () => {
22
- return { insertedImages: {} };
23
- },
24
- apply: (tr, pluginState) => {
25
- const newState = Object.assign({}, pluginState);
26
- newState.insertedImages = getImagesFromTransaction(tr);
27
- findAndHandleRemovedImages(imageRemovedCallback, pluginState.insertedImages, newState.insertedImages);
28
- return newState;
29
- },
30
- },
31
- });
32
- };
33
- const getImagesFromTransaction = (tr) => {
34
- const images = {};
35
- tr.doc.descendants((node) => {
36
- if (node.type.name === 'image') {
37
- images[node.attrs.fileInfoId] = node;
38
- }
39
18
  });
40
- return images;
41
- };
42
- const findAndHandleRemovedImages = (imageRemovedCallback, previousImages, newImages) => {
43
- const removedKeys = Object.keys(previousImages).filter((key) => !(key in newImages));
44
- for (const removedKey of removedKeys) {
45
- const removedImage = previousImages[removedKey];
46
- const imageInfo = {
47
- fileInfoId: removedImage.attrs.fileInfoId,
48
- src: removedImage.attrs.src,
49
- state: removedImage.attrs.state,
50
- };
51
- imageRemovedCallback(imageInfo);
52
- imageCache.delete(removedImage.attrs.fileInfoId);
53
- }
54
19
  };
55
20
  export const imageInserterFactory = (view, base64Data, fileInfo) => {
56
21
  return {
@@ -63,12 +28,8 @@ export const imageInserterFactory = (view, base64Data, fileInfo) => {
63
28
  const createThumbnailInserter = (view, base64Data, fileInfo) => () => {
64
29
  const { state, dispatch } = view;
65
30
  const { schema } = state;
66
- const placeholderNode = schema.nodes.image.create({
67
- src: base64Data,
68
- alt: fileInfo.filename,
69
- fileInfoId: fileInfo.id,
70
- state: ImageState.LOADING,
71
- });
31
+ const imageNodeAttrs = createImageNodeAttrs(base64Data, fileInfo, 'loading');
32
+ const placeholderNode = schema.nodes.image.create(imageNodeAttrs);
72
33
  const transaction = state.tr.replaceSelectionWith(placeholderNode);
73
34
  dispatch(transaction);
74
35
  };
@@ -78,12 +39,8 @@ const createImageInserter = (view, fileInfo) => (src) => {
78
39
  const tr = state.tr;
79
40
  state.doc.descendants((node, pos) => {
80
41
  if (node.attrs.fileInfoId === fileInfo.id) {
81
- const imageNode = schema.nodes.image.create({
82
- src: src ? src : node.attrs.src,
83
- alt: fileInfo.filename,
84
- fileInfoId: fileInfo.id,
85
- state: ImageState.SUCCESS,
86
- });
42
+ const imageNodeAttrs = createImageNodeAttrs(src ? src : node.attrs.src, fileInfo, 'success');
43
+ const imageNode = schema.nodes.image.create(imageNodeAttrs);
87
44
  tr.replaceWith(pos, pos + node.nodeSize, imageNode);
88
45
  return false;
89
46
  }
@@ -96,18 +53,22 @@ const createFailedThumbnailInserter = (view, fileInfo) => () => {
96
53
  const tr = state.tr;
97
54
  state.doc.descendants((node, pos) => {
98
55
  if (node.attrs.fileInfoId === fileInfo.id) {
99
- const errorPlaceholderNode = schema.nodes.image.create({
100
- src: node.attrs.src,
101
- alt: fileInfo.filename,
102
- fileInfoId: fileInfo.id,
103
- state: ImageState.FAILED,
104
- });
56
+ const imageNodeAttrs = createImageNodeAttrs(node.attrs.src, fileInfo, 'failed');
57
+ const errorPlaceholderNode = schema.nodes.image.create(imageNodeAttrs);
105
58
  tr.replaceWith(pos, pos + node.nodeSize, errorPlaceholderNode);
106
59
  return false;
107
60
  }
108
61
  });
109
62
  dispatch(tr);
110
63
  };
64
+ function createImageNodeAttrs(src, fileInfo, state) {
65
+ return {
66
+ src: src,
67
+ alt: fileInfo.filename,
68
+ fileInfoId: fileInfo.id,
69
+ state: state,
70
+ };
71
+ }
111
72
  /**
112
73
  * Check if a given ProseMirror node or fragment contains any image nodes.
113
74
  * @param node - The ProseMirror node or fragment to check.
@@ -1 +1 @@
1
- {"version":3,"file":"inserter.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey, Transaction, StateField } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { createFileInfo } from '../../../../../util/files';\nimport { FileInfo } from '../../../../../global/shared-types/file.types';\nimport {\n ImageInserter,\n ImageInfo,\n ImageState,\n} from '../../../text-editor.types';\nimport { Node, Slice, Fragment } from 'prosemirror-model';\nimport { imageCache } from './node';\n\nexport const pluginKey = new PluginKey('imageInserterPlugin');\n\ntype ImagePastedCallback = (data: ImageInserter) => CustomEvent<ImageInserter>;\n\ntype ImageRemovedCallback = (data: ImageInfo) => CustomEvent<ImageInfo>;\n\ntype PluginState = {\n insertedImages: Record<string, Node>;\n};\n\nexport const createImageInserterPlugin = (\n imagePastedCallback: ImagePastedCallback,\n imageRemovedCallback: ImageRemovedCallback,\n) => {\n return new Plugin({\n key: pluginKey,\n props: {\n handlePaste: (view, event, slice) => {\n return processPasteEvent(view, event, slice);\n },\n handleDOMEvents: {\n imagePasted: (_, event) => {\n imagePastedCallback(event.detail);\n },\n },\n },\n state: {\n init: (): PluginState => {\n return { insertedImages: {} };\n },\n apply: (tr, pluginState): PluginState => {\n const newState = { ...pluginState };\n\n newState.insertedImages = getImagesFromTransaction(tr);\n findAndHandleRemovedImages(\n imageRemovedCallback,\n pluginState.insertedImages,\n newState.insertedImages,\n );\n\n return newState;\n },\n } as StateField<PluginState>,\n });\n};\n\nconst getImagesFromTransaction = (tr: Transaction): Record<string, Node> => {\n const images: Record<string, Node> = {};\n tr.doc.descendants((node) => {\n if (node.type.name === 'image') {\n images[node.attrs.fileInfoId] = node;\n }\n });\n\n return images;\n};\n\nconst findAndHandleRemovedImages = (\n imageRemovedCallback: ImageRemovedCallback,\n previousImages: Record<string, Node>,\n newImages: Record<string, Node>,\n) => {\n const removedKeys = Object.keys(previousImages).filter(\n (key) => !(key in newImages),\n );\n\n for (const removedKey of removedKeys) {\n const removedImage = previousImages[removedKey];\n const imageInfo: ImageInfo = {\n fileInfoId: removedImage.attrs.fileInfoId,\n src: removedImage.attrs.src,\n state: removedImage.attrs.state,\n };\n imageRemovedCallback(imageInfo);\n\n imageCache.delete(removedImage.attrs.fileInfoId);\n }\n};\n\nexport const imageInserterFactory = (\n view: EditorView,\n base64Data: string,\n fileInfo: FileInfo,\n): ImageInserter => {\n return {\n fileInfo: fileInfo,\n insertThumbnail: createThumbnailInserter(view, base64Data, fileInfo),\n insertImage: createImageInserter(view, fileInfo),\n insertFailedThumbnail: createFailedThumbnailInserter(view, fileInfo),\n };\n};\n\nconst createThumbnailInserter =\n (view: EditorView, base64Data: string, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const placeholderNode = schema.nodes.image.create({\n src: base64Data,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: ImageState.LOADING,\n });\n\n const transaction = state.tr.replaceSelectionWith(placeholderNode);\n\n dispatch(transaction);\n };\n\nconst createImageInserter =\n (view: EditorView, fileInfo: FileInfo) => (src?: string) => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const imageNode = schema.nodes.image.create({\n src: src ? src : node.attrs.src,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: ImageState.SUCCESS,\n });\n\n tr.replaceWith(pos, pos + node.nodeSize, imageNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\nconst createFailedThumbnailInserter =\n (view: EditorView, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const errorPlaceholderNode = schema.nodes.image.create({\n src: node.attrs.src,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: ImageState.FAILED,\n });\n\n tr.replaceWith(pos, pos + node.nodeSize, errorPlaceholderNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\n/**\n * Check if a given ProseMirror node or fragment contains any image nodes.\n * @param node - The ProseMirror node or fragment to check.\n * @returns A boolean indicating whether the node contains any image nodes.\n */\nconst isImageNode = (node: Node | Fragment): boolean => {\n if (node instanceof Node) {\n if (node.type.name === 'image') {\n return true;\n }\n\n let found = false;\n node.content.forEach((child) => {\n if (isImageNode(child)) {\n found = true;\n }\n });\n\n return found;\n } else if (node instanceof Fragment) {\n let found = false;\n node.forEach((child) => {\n if (isImageNode(child)) {\n found = true;\n }\n });\n\n return found;\n }\n\n return false;\n};\n\n/**\n * Filter out image nodes from a ProseMirror fragment.\n * @param fragment - The ProseMirror fragment to filter.\n * @returns A new fragment with image nodes removed.\n */\nconst filterImageNodes = (fragment: Fragment): Fragment => {\n const filteredChildren: Node[] = [];\n\n fragment.forEach((child) => {\n if (!isImageNode(child)) {\n if (child.content.size > 0) {\n const filteredContent = filterImageNodes(child.content);\n const newNode = child.copy(filteredContent);\n filteredChildren.push(newNode);\n } else {\n filteredChildren.push(child);\n }\n }\n });\n\n return Fragment.fromArray(filteredChildren);\n};\n\n/**\n * Process a paste event and trigger an imagePasted event if an image file is pasted.\n * If an HTML image element is pasted, this image is filtered out from the slice content.\n *\n * @param view - The ProseMirror editor view.\n * @param event - The paste event.\n * @returns A boolean; True if an image file was pasted to prevent default paste behavior, otherwise false.\n */\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n slice: Slice,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const files = Array.from(clipboardData.files || []);\n for (const file of files) {\n if (file.type.startsWith('image/')) {\n const reader = new FileReader();\n reader.onloadend = () => {\n view.dom.dispatchEvent(\n new CustomEvent('imagePasted', {\n detail: imageInserterFactory(\n view,\n reader.result as string,\n createFileInfo(file),\n ),\n }),\n );\n };\n\n reader.readAsDataURL(file);\n }\n }\n\n const filteredSlice = new Slice(\n filterImageNodes(slice.content),\n slice.openStart,\n slice.openEnd,\n );\n\n if (filteredSlice.content.childCount < slice.content.childCount) {\n const { state, dispatch } = view;\n const tr = state.tr.replaceSelection(filteredSlice);\n dispatch(tr);\n\n return true;\n }\n\n return files.length > 0;\n};\n"]}
1
+ {"version":3,"file":"inserter.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG1D,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAC;AAI9D,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACrC,mBAAwC,EAC1C,EAAE;EACA,OAAO,IAAI,MAAM,CAAC;IACd,GAAG,EAAE,SAAS;IACd,KAAK,EAAE;MACH,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAChC,OAAO,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;MACjD,CAAC;MACD,eAAe,EAAE;QACb,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;UACtB,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;OACJ;KACJ;GACJ,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAChC,IAAgB,EAChB,UAAkB,EAClB,QAAkB,EACL,EAAE;EACf,OAAO;IACH,QAAQ,EAAE,QAAQ;IAClB,eAAe,EAAE,uBAAuB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC;IACpE,WAAW,EAAE,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC;IAChD,qBAAqB,EAAE,6BAA6B,CAAC,IAAI,EAAE,QAAQ,CAAC;GACvE,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,uBAAuB,GACzB,CAAC,IAAgB,EAAE,UAAkB,EAAE,QAAkB,EAAE,EAAE,CAAC,GAAG,EAAE;EAC/D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;EACjC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;EAEzB,MAAM,cAAc,GAAG,oBAAoB,CACvC,UAAU,EACV,QAAQ,EACR,SAAS,CACZ,CAAC;EACF,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;EAElE,MAAM,WAAW,GAAG,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC;EAEnE,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEN,MAAM,mBAAmB,GACrB,CAAC,IAAgB,EAAE,QAAkB,EAAE,EAAE,CAAC,CAAC,GAAY,EAAE,EAAE;EACvD,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;EACjC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;EAEzB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;EACpB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAChC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,EAAE,EAAE;MACvC,MAAM,cAAc,GAAG,oBAAoB,CACvC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAC1B,QAAQ,EACR,SAAS,CACZ,CAAC;MACF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;MAE5D,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;MAEpD,OAAO,KAAK,CAAC;KAChB;EACL,CAAC,CAAC,CAAC;EAEH,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjB,CAAC,CAAC;AAEN,MAAM,6BAA6B,GAC/B,CAAC,IAAgB,EAAE,QAAkB,EAAE,EAAE,CAAC,GAAG,EAAE;EAC3C,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;EACjC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;EAEzB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;EACpB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAChC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,EAAE,EAAE;MACvC,MAAM,cAAc,GAAG,oBAAoB,CACvC,IAAI,CAAC,KAAK,CAAC,GAAG,EACd,QAAQ,EACR,QAAQ,CACX,CAAC;MACF,MAAM,oBAAoB,GACtB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;MAE9C,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;MAE/D,OAAO,KAAK,CAAC;KAChB;EACL,CAAC,CAAC,CAAC;EAEH,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjB,CAAC,CAAC;AAEN,SAAS,oBAAoB,CACzB,GAAW,EACX,QAAkB,EAClB,KAAuB;EAEvB,OAAO;IACH,GAAG,EAAE,GAAG;IACR,GAAG,EAAE,QAAQ,CAAC,QAAQ;IACtB,UAAU,EAAE,QAAQ,CAAC,EAAE;IACvB,KAAK,EAAE,KAAK;GACf,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,CAAC,IAAqB,EAAW,EAAE;EACnD,IAAI,IAAI,YAAY,IAAI,EAAE;IACtB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;MAC5B,OAAO,IAAI,CAAC;KACf;IAED,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;MAC3B,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE;QACpB,KAAK,GAAG,IAAI,CAAC;OAChB;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;GAChB;OAAM,IAAI,IAAI,YAAY,QAAQ,EAAE;IACjC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;MACnB,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE;QACpB,KAAK,GAAG,IAAI,CAAC;OAChB;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;GAChB;EAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,CAAC,QAAkB,EAAY,EAAE;EACtD,MAAM,gBAAgB,GAAW,EAAE,CAAC;EAEpC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;IACvB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE;MACrB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE;QACxB,MAAM,eAAe,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5C,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;OAClC;WAAM;QACH,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;OAChC;KACJ;EACL,CAAC,CAAC,CAAC;EAEH,OAAO,QAAQ,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAG,CACtB,IAAgB,EAChB,KAAqB,EACrB,KAAY,EACL,EAAE;EACT,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;EAC1C,IAAI,CAAC,aAAa,EAAE;IAChB,OAAO,KAAK,CAAC;GAChB;EAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;EACpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;IACtB,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;MAChC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;MAChC,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE;QACpB,IAAI,CAAC,GAAG,CAAC,aAAa,CAClB,IAAI,WAAW,CAAC,aAAa,EAAE;UAC3B,MAAM,EAAE,oBAAoB,CACxB,IAAI,EACJ,MAAM,CAAC,MAAgB,EACvB,cAAc,CAAC,IAAI,CAAC,CACvB;SACJ,CAAC,CACL,CAAC;MACN,CAAC,CAAC;MAEF,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;KAC9B;GACJ;EAED,MAAM,aAAa,GAAG,IAAI,KAAK,CAC3B,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,EAC/B,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,OAAO,CAChB,CAAC;EAEF,IAAI,aAAa,CAAC,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE;IAC7D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACpD,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEb,OAAO,IAAI,CAAC;GACf;EAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC","sourcesContent":["import { Plugin, PluginKey } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { createFileInfo } from '../../../../../util/files';\nimport { FileInfo } from '../../../../../global/shared-types/file.types';\nimport { ImageInserter, EditorImageState } from '../../../text-editor.types';\nimport { Node, Slice, Fragment } from 'prosemirror-model';\nimport { ImageNodeAttrs } from './node';\n\nexport const pluginKey = new PluginKey('imageInserterPlugin');\n\ntype ImagePastedCallback = (data: ImageInserter) => CustomEvent<ImageInserter>;\n\nexport const createImageInserterPlugin = (\n imagePastedCallback: ImagePastedCallback,\n) => {\n return new Plugin({\n key: pluginKey,\n props: {\n handlePaste: (view, event, slice) => {\n return processPasteEvent(view, event, slice);\n },\n handleDOMEvents: {\n imagePasted: (_, event) => {\n imagePastedCallback(event.detail);\n },\n },\n },\n });\n};\n\nexport const imageInserterFactory = (\n view: EditorView,\n base64Data: string,\n fileInfo: FileInfo,\n): ImageInserter => {\n return {\n fileInfo: fileInfo,\n insertThumbnail: createThumbnailInserter(view, base64Data, fileInfo),\n insertImage: createImageInserter(view, fileInfo),\n insertFailedThumbnail: createFailedThumbnailInserter(view, fileInfo),\n };\n};\n\nconst createThumbnailInserter =\n (view: EditorView, base64Data: string, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const imageNodeAttrs = createImageNodeAttrs(\n base64Data,\n fileInfo,\n 'loading',\n );\n const placeholderNode = schema.nodes.image.create(imageNodeAttrs);\n\n const transaction = state.tr.replaceSelectionWith(placeholderNode);\n\n dispatch(transaction);\n };\n\nconst createImageInserter =\n (view: EditorView, fileInfo: FileInfo) => (src?: string) => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const imageNodeAttrs = createImageNodeAttrs(\n src ? src : node.attrs.src,\n fileInfo,\n 'success',\n );\n const imageNode = schema.nodes.image.create(imageNodeAttrs);\n\n tr.replaceWith(pos, pos + node.nodeSize, imageNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\nconst createFailedThumbnailInserter =\n (view: EditorView, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const imageNodeAttrs = createImageNodeAttrs(\n node.attrs.src,\n fileInfo,\n 'failed',\n );\n const errorPlaceholderNode =\n schema.nodes.image.create(imageNodeAttrs);\n\n tr.replaceWith(pos, pos + node.nodeSize, errorPlaceholderNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\nfunction createImageNodeAttrs(\n src: string,\n fileInfo: FileInfo,\n state: EditorImageState,\n): ImageNodeAttrs {\n return {\n src: src,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: state,\n };\n}\n\n/**\n * Check if a given ProseMirror node or fragment contains any image nodes.\n * @param node - The ProseMirror node or fragment to check.\n * @returns A boolean indicating whether the node contains any image nodes.\n */\nconst isImageNode = (node: Node | Fragment): boolean => {\n if (node instanceof Node) {\n if (node.type.name === 'image') {\n return true;\n }\n\n let found = false;\n node.content.forEach((child) => {\n if (isImageNode(child)) {\n found = true;\n }\n });\n\n return found;\n } else if (node instanceof Fragment) {\n let found = false;\n node.forEach((child) => {\n if (isImageNode(child)) {\n found = true;\n }\n });\n\n return found;\n }\n\n return false;\n};\n\n/**\n * Filter out image nodes from a ProseMirror fragment.\n * @param fragment - The ProseMirror fragment to filter.\n * @returns A new fragment with image nodes removed.\n */\nconst filterImageNodes = (fragment: Fragment): Fragment => {\n const filteredChildren: Node[] = [];\n\n fragment.forEach((child) => {\n if (!isImageNode(child)) {\n if (child.content.size > 0) {\n const filteredContent = filterImageNodes(child.content);\n const newNode = child.copy(filteredContent);\n filteredChildren.push(newNode);\n } else {\n filteredChildren.push(child);\n }\n }\n });\n\n return Fragment.fromArray(filteredChildren);\n};\n\n/**\n * Process a paste event and trigger an imagePasted event if an image file is pasted.\n * If an HTML image element is pasted, this image is filtered out from the slice content.\n *\n * @param view - The ProseMirror editor view.\n * @param event - The paste event.\n * @returns A boolean; True if an image file was pasted to prevent default paste behavior, otherwise false.\n */\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n slice: Slice,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const files = Array.from(clipboardData.files || []);\n for (const file of files) {\n if (file.type.startsWith('image/')) {\n const reader = new FileReader();\n reader.onloadend = () => {\n view.dom.dispatchEvent(\n new CustomEvent('imagePasted', {\n detail: imageInserterFactory(\n view,\n reader.result as string,\n createFileInfo(file),\n ),\n }),\n );\n };\n\n reader.readAsDataURL(file);\n }\n }\n\n const filteredSlice = new Slice(\n filterImageNodes(slice.content),\n slice.openStart,\n slice.openEnd,\n );\n\n if (filteredSlice.content.childCount < slice.content.childCount) {\n const { state, dispatch } = view;\n const tr = state.tr.replaceSelection(filteredSlice);\n dispatch(tr);\n\n return true;\n }\n\n return files.length > 0;\n};\n"]}