@kerebron/extension-menu 0.3.2 → 0.4.1

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/README.md +26 -1
  2. package/assets/custom-menu.css +838 -0
  3. package/assets/menu.css +353 -26
  4. package/esm/_dnt.shims.d.ts +6 -0
  5. package/esm/_dnt.shims.d.ts.map +1 -0
  6. package/esm/_dnt.shims.js +61 -0
  7. package/esm/editor/src/CoreEditor.d.ts +13 -4
  8. package/esm/editor/src/CoreEditor.d.ts.map +1 -1
  9. package/esm/editor/src/CoreEditor.js +64 -12
  10. package/esm/editor/src/Extension.d.ts +6 -1
  11. package/esm/editor/src/Extension.d.ts.map +1 -1
  12. package/esm/editor/src/Extension.js +21 -1
  13. package/esm/editor/src/ExtensionManager.d.ts +5 -6
  14. package/esm/editor/src/ExtensionManager.d.ts.map +1 -1
  15. package/esm/editor/src/ExtensionManager.js +43 -55
  16. package/esm/editor/src/Mark.d.ts +3 -0
  17. package/esm/editor/src/Mark.d.ts.map +1 -1
  18. package/esm/editor/src/Mark.js +11 -0
  19. package/esm/editor/src/Node.d.ts +5 -2
  20. package/esm/editor/src/Node.d.ts.map +1 -1
  21. package/esm/editor/src/Node.js +13 -2
  22. package/esm/editor/src/commands/CommandManager.d.ts +13 -6
  23. package/esm/editor/src/commands/CommandManager.d.ts.map +1 -1
  24. package/esm/editor/src/commands/CommandManager.js +59 -2
  25. package/esm/editor/src/commands/baseCommandFactories.d.ts +3 -0
  26. package/esm/editor/src/commands/baseCommandFactories.d.ts.map +1 -0
  27. package/esm/editor/src/commands/baseCommandFactories.js +836 -0
  28. package/esm/editor/src/commands/keyCommandFactories.d.ts +3 -0
  29. package/esm/editor/src/commands/keyCommandFactories.d.ts.map +1 -0
  30. package/esm/editor/src/commands/keyCommandFactories.js +10 -0
  31. package/esm/editor/src/commands/mod.d.ts +5 -53
  32. package/esm/editor/src/commands/mod.d.ts.map +1 -1
  33. package/esm/editor/src/commands/mod.js +14 -821
  34. package/esm/editor/src/commands/replaceCommandFactories.d.ts +3 -0
  35. package/esm/editor/src/commands/replaceCommandFactories.d.ts.map +1 -0
  36. package/esm/editor/src/commands/replaceCommandFactories.js +94 -0
  37. package/esm/editor/src/commands/types.d.ts +18 -0
  38. package/esm/editor/src/commands/types.d.ts.map +1 -0
  39. package/esm/editor/src/commands/types.js +1 -0
  40. package/esm/editor/src/mod.d.ts +2 -0
  41. package/esm/editor/src/mod.d.ts.map +1 -1
  42. package/esm/editor/src/mod.js +2 -0
  43. package/esm/editor/src/plugins/TrackSelecionPlugin.d.ts +6 -0
  44. package/esm/editor/src/plugins/TrackSelecionPlugin.d.ts.map +1 -0
  45. package/esm/editor/src/plugins/TrackSelecionPlugin.js +24 -0
  46. package/esm/editor/src/types.d.ts +19 -1
  47. package/esm/editor/src/types.d.ts.map +1 -1
  48. package/esm/editor/src/ui.d.ts +15 -0
  49. package/esm/editor/src/ui.d.ts.map +1 -0
  50. package/esm/editor/src/ui.js +16 -0
  51. package/esm/editor/src/utilities/SmartOutput.d.ts +9 -7
  52. package/esm/editor/src/utilities/SmartOutput.d.ts.map +1 -1
  53. package/esm/editor/src/utilities/SmartOutput.js +35 -20
  54. package/esm/extension-menu/src/CustomMenuPlugin.d.ts +61 -0
  55. package/esm/extension-menu/src/CustomMenuPlugin.d.ts.map +1 -0
  56. package/esm/extension-menu/src/CustomMenuPlugin.js +1130 -0
  57. package/esm/extension-menu/src/ExtensionCustomMenu.d.ts +11 -0
  58. package/esm/extension-menu/src/ExtensionCustomMenu.d.ts.map +1 -0
  59. package/esm/extension-menu/src/ExtensionCustomMenu.js +23 -0
  60. package/esm/extension-menu/src/buildMenu.d.ts +5 -0
  61. package/esm/extension-menu/src/buildMenu.d.ts.map +1 -0
  62. package/esm/extension-menu/src/{ExtensionMenu.js → buildMenu.js} +88 -75
  63. package/esm/extension-menu/src/icons.d.ts.map +1 -1
  64. package/esm/extension-menu/src/icons.js +5 -0
  65. package/esm/extension-menu/src/menu.d.ts +1 -8
  66. package/esm/extension-menu/src/menu.d.ts.map +1 -1
  67. package/esm/extension-menu/src/menu.js +9 -51
  68. package/esm/extension-menu/src/mod.d.ts +3 -0
  69. package/esm/extension-menu/src/mod.d.ts.map +1 -0
  70. package/esm/extension-menu/src/mod.js +2 -0
  71. package/package.json +8 -4
  72. package/esm/extension-menu/src/ExtensionMenu.d.ts +0 -17
  73. package/esm/extension-menu/src/ExtensionMenu.d.ts.map +0 -1
  74. package/esm/extension-menu/src/MenuPlugin.d.ts +0 -9
  75. package/esm/extension-menu/src/MenuPlugin.d.ts.map +0 -1
  76. package/esm/extension-menu/src/MenuPlugin.js +0 -245
package/assets/menu.css CHANGED
@@ -1,32 +1,79 @@
1
- /* Base menu and toolbar styles */
1
+ /* Base menu and toolbar styles - Google Docs style with overflow */
2
2
  .kb-menu {
3
3
  margin: 0;
4
4
  line-height: 1;
5
- font-size: var(--kb-text-sm);
6
- }
7
-
8
- /* Mobile-first toolbar */
9
- .kb-menu {
5
+ font-size: 14px;
6
+ font-family:
7
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
8
+ Arial, sans-serif;
10
9
  position: sticky;
11
10
  top: 0;
12
11
  display: flex;
13
- flex-wrap: wrap;
14
- gap: var(--kb-space-xs);
15
- padding: var(--kb-space-sm);
16
- background: var(--kb-color-surface);
17
- border-bottom: 1px solid var(--kb-color-border);
18
- z-index: var(--kb-z-dropdown);
19
- overflow-x: auto;
20
- -webkit-overflow-scrolling: touch;
21
- scrollbar-width: none;
22
- -ms-overflow-style: none;
12
+ flex-wrap: nowrap;
13
+ align-items: center;
14
+ gap: 0;
15
+ padding: 4px 8px;
16
+ background: #f9f9f9;
17
+ border-bottom: 1px solid #dadce0;
18
+ z-index: var(--kb-z-dropdown, 1000);
19
+ overflow: visible;
23
20
  }
24
21
 
25
- .kb-menu::-webkit-scrollbar {
22
+ /* Content host - main toolbar items */
23
+ .kb-menu__content {
24
+ display: flex;
25
+ flex: 1;
26
+ align-items: center;
27
+ gap: 0;
28
+ overflow: hidden;
29
+ }
30
+
31
+ /* Overflow toggle button (3-dot menu) */
32
+ .kb-overflow-toggle {
33
+ display: none; /* shown by JS when needed */
34
+ min-width: 30px;
35
+ min-height: 30px;
36
+ padding: 6px;
37
+ border: none;
38
+ background: transparent;
39
+ color: #3c4043;
40
+ cursor: pointer;
41
+ border-radius: 2px;
42
+ margin-left: 4px;
43
+ flex-shrink: 0;
44
+ }
45
+
46
+ .kb-overflow-toggle:hover {
47
+ background: rgba(60, 64, 67, 0.08);
48
+ }
49
+
50
+ .kb-overflow-toggle svg {
51
+ width: 18px;
52
+ height: 18px;
53
+ fill: currentColor;
54
+ }
55
+
56
+ /* Overflow row - second row for overflowed items */
57
+ .kb-menu__overflow-row {
26
58
  display: none;
59
+ flex-wrap: wrap;
60
+ gap: 4px;
61
+ padding: 8px;
62
+ background: #f9f9f9;
63
+ border-bottom: 1px solid #dadce0;
27
64
  }
28
65
 
29
- /* Mobile: bottom-anchored toolbar for one-handed use */
66
+ .kb-menu--overflow-open .kb-menu__overflow-row {
67
+ display: flex;
68
+ position: absolute;
69
+ }
70
+
71
+ /* When narrow, show overflow toggle */
72
+ .kb-menu--narrow .kb-overflow-toggle {
73
+ display: inline-flex;
74
+ }
75
+
76
+ /* Mobile: bottom-anchored toolbar */
30
77
  @media (max-width: 767px) {
31
78
  .kb-menu {
32
79
  position: fixed;
@@ -35,17 +82,33 @@
35
82
  right: 0;
36
83
  top: auto;
37
84
  border-bottom: none;
38
- border-top: 1px solid var(--kb-color-border);
39
- box-shadow: var(--kb-shadow-lg);
85
+ border-top: 1px solid #dadce0;
86
+ box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
40
87
  backdrop-filter: blur(10px);
41
- background: rgba(255, 255, 255, 0.95);
88
+ background: rgba(249, 249, 249, 0.95);
89
+ padding: 8px;
90
+ }
91
+
92
+ .kb-menu__overflow-row {
93
+ position: fixed;
94
+ bottom: 60px;
95
+ left: 0;
96
+ right: 0;
97
+ border-top: 1px solid #dadce0;
98
+ border-bottom: none;
99
+ box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
42
100
  }
43
101
 
44
102
  /* Add bottom padding to editor content to prevent overlap */
45
- .kb-component {
46
- padding-bottom: calc(
47
- var(--kb-touch-target-comfortable) + var(--kb-space-md) * 2
48
- );
103
+ .kb-component,
104
+ .ProseMirror {
105
+ padding-bottom: 60px !important;
106
+ }
107
+
108
+ .kb-overflow-toggle {
109
+ min-width: 44px;
110
+ min-height: 44px;
111
+ padding: 10px;
49
112
  }
50
113
  }
51
114
 
@@ -229,7 +292,7 @@
229
292
  }
230
293
 
231
294
  /* Accessibility: High contrast mode support */
232
- @media (prefers-contrast: high) {
295
+ @media (prefers-contrast: more) {
233
296
  .kb-dropdown__item,
234
297
  .kb-dropdown__item:focus {
235
298
  outline-width: 3px;
@@ -537,3 +600,267 @@
537
600
  border-color: var(--kb-color-primary);
538
601
  }
539
602
  }
603
+
604
+ /* ===========================
605
+ Google-Docs–style toolbar for kb-menu
606
+ (main look + overflow behavior)
607
+ =========================== */
608
+
609
+ :root {
610
+ --kb-bg: #fff;
611
+ --kb-fg: #1f1f1f;
612
+ --kb-subtle: #5f6368;
613
+ --kb-border: #e0e0e0;
614
+ --kb-hover: #f1f3f4;
615
+ --kb-active: #e8f0fe;
616
+ --kb-focus: #1a73e8;
617
+ --kb-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.08);
618
+
619
+ --kb-height: 48px;
620
+ --kb-btn-h: 34px;
621
+ --kb-radius: 10px;
622
+
623
+ --kb-gap: 8px;
624
+ --kb-icon: 18px;
625
+ --kb-font: 13px;
626
+ }
627
+
628
+ /* Keep light toolbar even for dark pages (like Google Docs) */
629
+ @media (prefers-color-scheme: dark) {
630
+ :root {
631
+ --kb-bg: #ffffff;
632
+ --kb-fg: #1f1f1f;
633
+ --kb-subtle: #5f6368;
634
+ --kb-border: #e6e7e8;
635
+ --kb-hover: #f3f4f5;
636
+ --kb-active: #e8f0fe;
637
+ }
638
+ }
639
+
640
+ /* Wrapper around toolbar + editor (plugin inserts this) */
641
+ .kb-menu__wrapper {
642
+ z-index: 50;
643
+ padding: 8px 12px; /* spacing around the pill */
644
+ background: transparent;
645
+ }
646
+
647
+ /* The toolbar element */
648
+ .kb-menu {
649
+ background: var(--kb-bg);
650
+ border: 1px solid var(--kb-border);
651
+ border-radius: var(--kb-radius);
652
+ box-shadow: var(--kb-shadow);
653
+
654
+ min-height: var(--kb-height);
655
+ display: flex;
656
+ align-items: center;
657
+ gap: var(--kb-gap);
658
+ padding: 0 8px;
659
+
660
+ container-type: inline-size;
661
+ }
662
+
663
+ /* Spacer used when floating */
664
+ .kb-menu__spacer {
665
+ height: var(--kb-height);
666
+ }
667
+
668
+ /* Items and separators from renderGrouped */
669
+ .kb-menu__item {
670
+ display: inline-flex;
671
+ align-items: center;
672
+ }
673
+ .kb-menu__separator {
674
+ width: 1px;
675
+ height: 22px;
676
+ background: var(--kb-border);
677
+ flex: 0 0 auto;
678
+ margin: 0 2px;
679
+ }
680
+
681
+ /* Buttons */
682
+ .kb-menu__button {
683
+ height: var(--kb-btn-h);
684
+ min-width: 34px;
685
+ display: inline-flex;
686
+ align-items: center;
687
+ justify-content: center;
688
+ gap: 6px;
689
+ padding: 6px 10px;
690
+ border-radius: 8px;
691
+ border: 1px solid transparent;
692
+ background: transparent;
693
+ color: var(--kb-fg);
694
+ font:
695
+ 500 var(--kb-font)/1.2 system-ui,
696
+ -apple-system,
697
+ 'Segoe UI',
698
+ Roboto,
699
+ Arial;
700
+ cursor: pointer;
701
+ user-select: none;
702
+ white-space: nowrap;
703
+ }
704
+ .kb-menu__button svg,
705
+ .kb-menu__button .kb-icon {
706
+ width: var(--kb-icon);
707
+ height: var(--kb-icon);
708
+ fill: currentColor;
709
+ }
710
+ .kb-menu__button:hover {
711
+ background: var(--kb-hover);
712
+ }
713
+ .kb-menu__button:focus-visible {
714
+ outline: 2px solid var(--kb-focus);
715
+ outline-offset: 2px;
716
+ background: var(--kb-hover);
717
+ }
718
+ .kb-menu__button--active,
719
+ .kb-menu__button[aria-pressed='true'] {
720
+ background: var(--kb-active);
721
+ border-color: #d2e3fc;
722
+ }
723
+ .kb-menu__button--disabled,
724
+ .kb-menu__button[aria-disabled='true'] {
725
+ opacity: 0.5;
726
+ cursor: default;
727
+ pointer-events: none;
728
+ }
729
+ .kb-menu__button--icon-only > span {
730
+ display: none;
731
+ }
732
+
733
+ /* Dropdowns */
734
+ .kb-dropdown {
735
+ position: relative;
736
+ display: inline-flex;
737
+ align-items: center;
738
+ }
739
+ .kb-dropdown__label {
740
+ height: var(--kb-btn-h);
741
+ display: inline-flex;
742
+ align-items: center;
743
+ gap: 6px;
744
+ padding: 6px 10px;
745
+ border-radius: 8px;
746
+ border: 1px solid transparent;
747
+ background: transparent;
748
+ color: var(--kb-fg);
749
+ font:
750
+ 500 var(--kb-font)/1.2 system-ui,
751
+ -apple-system,
752
+ 'Segoe UI',
753
+ Roboto,
754
+ Arial;
755
+ cursor: pointer;
756
+ }
757
+ .kb-dropdown__label:hover {
758
+ background: var(--kb-hover);
759
+ }
760
+ .kb-dropdown--open .kb-dropdown__label {
761
+ background: var(--kb-active);
762
+ border-color: #d2e3fc;
763
+ }
764
+ .kb-dropdown__menu {
765
+ position: absolute;
766
+ top: calc(100% + 6px);
767
+ left: 0;
768
+ min-width: 240px;
769
+ max-height: 60vh;
770
+ overflow: auto;
771
+ background: var(--kb-bg);
772
+ color: var(--kb-fg);
773
+ border: 1px solid var(--kb-border);
774
+ border-radius: 10px;
775
+ box-shadow: var(--kb-shadow);
776
+ padding: 6px;
777
+ display: grid;
778
+ gap: 2px;
779
+ z-index: 100;
780
+ }
781
+ .kb-dropdown__item {
782
+ display: contents;
783
+ }
784
+ .kb-dropdown__item .kb-menu__button {
785
+ justify-content: flex-start;
786
+ width: 100%;
787
+ border-radius: 8px;
788
+ }
789
+
790
+ /* Submenus */
791
+ .kb-submenu {
792
+ position: relative;
793
+ display: inline-flex;
794
+ align-items: center;
795
+ }
796
+ .kb-submenu__label {
797
+ height: var(--kb-btn-h);
798
+ display: inline-flex;
799
+ align-items: center;
800
+ gap: 6px;
801
+ padding: 6px 10px;
802
+ border-radius: 8px;
803
+ }
804
+ .kb-submenu__label:hover {
805
+ background: var(--kb-hover);
806
+ }
807
+ .kb-submenu__content {
808
+ position: absolute;
809
+ top: calc(100% + 6px);
810
+ left: 0;
811
+ min-width: 220px;
812
+ max-height: 60vh;
813
+ overflow: auto;
814
+ background: var(--kb-bg);
815
+ border: 1px solid var(--kb-border);
816
+ border-radius: 10px;
817
+ box-shadow: var(--kb-shadow);
818
+ padding: 6px;
819
+ display: none;
820
+ z-index: 100;
821
+ }
822
+ .kb-submenu--open .kb-submenu__content {
823
+ display: block;
824
+ }
825
+
826
+ /* --------- Overflow behavior --------- */
827
+
828
+ /* Hidden until narrow AND there is overflow (JS toggles display) */
829
+ .kb-overflow-toggle {
830
+ display: none;
831
+ }
832
+
833
+ /* Second row container (hidden until toggled open) */
834
+ .kb-menu__overflow-row {
835
+ display: none;
836
+ margin: 6px 12px 0; /* align with wrapper padding */
837
+ padding: 6px;
838
+ background: var(--kb-bg);
839
+ border: 1px solid var(--kb-border);
840
+ border-radius: 10px;
841
+ box-shadow: var(--kb-shadow);
842
+ gap: 6px;
843
+ align-items: center;
844
+ flex-wrap: wrap;
845
+ }
846
+
847
+ /* When narrow, show 3-dots (JS may still hide if empty) */
848
+ .kb-menu--narrow .kb-overflow-toggle {
849
+ display: inline-flex;
850
+ }
851
+
852
+ /* When toggled open, show the overflow row */
853
+ .kb-menu--overflow-open .kb-menu__overflow-row {
854
+ display: flex;
855
+ }
856
+
857
+ /* On very small/mobile, put overflow row ABOVE the main bar */
858
+ @media (max-width: 600px) {
859
+ .kb-menu__wrapper {
860
+ display: flex;
861
+ flex-direction: column;
862
+ }
863
+ .kb-menu--overflow-open .kb-menu__overflow-row {
864
+ order: -1;
865
+ }
866
+ }
@@ -0,0 +1,6 @@
1
+ import { Deno } from "@deno/shim-deno";
2
+ export { Deno } from "@deno/shim-deno";
3
+ export declare const dntGlobalThis: Omit<typeof globalThis, "Deno"> & {
4
+ Deno: typeof Deno;
5
+ };
6
+ //# sourceMappingURL=_dnt.shims.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_dnt.shims.d.ts","sourceRoot":"","sources":["../src/_dnt.shims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAKvC,eAAO,MAAM,aAAa;;CAA2C,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { Deno } from "@deno/shim-deno";
2
+ export { Deno } from "@deno/shim-deno";
3
+ const dntGlobals = {
4
+ Deno,
5
+ };
6
+ export const dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
7
+ function createMergeProxy(baseObj, extObj) {
8
+ return new Proxy(baseObj, {
9
+ get(_target, prop, _receiver) {
10
+ if (prop in extObj) {
11
+ return extObj[prop];
12
+ }
13
+ else {
14
+ return baseObj[prop];
15
+ }
16
+ },
17
+ set(_target, prop, value) {
18
+ if (prop in extObj) {
19
+ delete extObj[prop];
20
+ }
21
+ baseObj[prop] = value;
22
+ return true;
23
+ },
24
+ deleteProperty(_target, prop) {
25
+ let success = false;
26
+ if (prop in extObj) {
27
+ delete extObj[prop];
28
+ success = true;
29
+ }
30
+ if (prop in baseObj) {
31
+ delete baseObj[prop];
32
+ success = true;
33
+ }
34
+ return success;
35
+ },
36
+ ownKeys(_target) {
37
+ const baseKeys = Reflect.ownKeys(baseObj);
38
+ const extKeys = Reflect.ownKeys(extObj);
39
+ const extKeysSet = new Set(extKeys);
40
+ return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
41
+ },
42
+ defineProperty(_target, prop, desc) {
43
+ if (prop in extObj) {
44
+ delete extObj[prop];
45
+ }
46
+ Reflect.defineProperty(baseObj, prop, desc);
47
+ return true;
48
+ },
49
+ getOwnPropertyDescriptor(_target, prop) {
50
+ if (prop in extObj) {
51
+ return Reflect.getOwnPropertyDescriptor(extObj, prop);
52
+ }
53
+ else {
54
+ return Reflect.getOwnPropertyDescriptor(baseObj, prop);
55
+ }
56
+ },
57
+ has(_target, prop) {
58
+ return prop in extObj || prop in baseObj;
59
+ },
60
+ });
61
+ }
@@ -1,19 +1,27 @@
1
1
  import { EditorView } from 'prosemirror-view';
2
2
  import { Node as ProseMirrorNode, Schema } from 'prosemirror-model';
3
- import type { EditorOptions, JSONContent } from './types.js';
3
+ import type { EditorConfig, JSONContent } from './types.js';
4
4
  import { EditorState, Transaction } from 'prosemirror-state';
5
5
  import { DummyEditorView } from './DummyEditorView.js';
6
6
  import { ChainedCommands } from './commands/mod.js';
7
7
  import { Extension } from './Extension.js';
8
+ import { EditorUi } from './ui.js';
8
9
  export declare class CoreEditor extends EventTarget {
9
- readonly options: Partial<EditorOptions>;
10
+ readonly config: Partial<EditorConfig>;
10
11
  private extensionManager;
11
12
  private commandManager;
12
13
  view: EditorView | DummyEditorView;
13
14
  state: EditorState;
14
- constructor(options?: Partial<EditorOptions>);
15
+ ui: EditorUi;
16
+ constructor(config?: Partial<EditorConfig>);
15
17
  getExtension<T extends Extension>(name: string): T | undefined;
16
18
  get schema(): Schema<any, any>;
19
+ get run(): {
20
+ [key: string]: (...args: any[]) => boolean;
21
+ };
22
+ get commandFactories(): {
23
+ [key: string]: import("./commands/types.js").CommandFactory;
24
+ };
17
25
  chain(): ChainedCommands;
18
26
  can(): ChainedCommands;
19
27
  private createView;
@@ -25,7 +33,8 @@ export declare class CoreEditor extends EventTarget {
25
33
  loadDocument(mediaType: string, content: Uint8Array): Promise<void>;
26
34
  saveDocument(mediaType: string): Promise<Uint8Array>;
27
35
  getJSON(): JSONContent;
28
- clone(options?: Partial<EditorOptions>): CoreEditor;
36
+ clone(options?: Partial<EditorConfig>): CoreEditor;
29
37
  debug(doc?: ProseMirrorNode): void;
38
+ destroy(): void;
30
39
  }
31
40
  //# sourceMappingURL=CoreEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CoreEditor.d.ts","sourceRoot":"","sources":["../../../src/editor/src/CoreEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGpE,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAc3C,qBAAa,UAAW,SAAQ,WAAW;IACzC,SAAgB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAG7C;IACF,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,cAAc,CAAiB;IAChC,IAAI,EAAG,UAAU,GAAG,eAAe,CAAC;IACpC,KAAK,EAAG,WAAW,CAAC;gBAEf,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM;IA4BhD,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAI9D,IAAW,MAAM,qBAEhB;IAEM,KAAK,IAAI,eAAe;IAIxB,GAAG,IAAI,eAAe;IAI7B,OAAO,CAAC,UAAU;IAqBX,mBAAmB,CAAC,WAAW,EAAE,WAAW;IAcnD,OAAO,CAAC,YAAY;IAcb,aAAa;IASb,WAAW,CAAC,OAAO,EAAE,GAAG;IAyBxB,WAAW;IAIL,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;IA0BnD,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAY1D,OAAO,IAAI,WAAW;IAItB,KAAK,CAAC,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,UAAU;IAOvD,KAAK,CAAC,GAAG,CAAC,EAAE,eAAe;CAMnC"}
1
+ {"version":3,"file":"CoreEditor.d.ts","sourceRoot":"","sources":["../../../src/editor/src/CoreEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGpE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAa,QAAQ,EAAE,MAAM,SAAS,CAAC;AAc9C,qBAAa,UAAW,SAAQ,WAAW;IACzC,SAAgB,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAG3C;IACF,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,cAAc,CAAiB;IAChC,IAAI,EAAG,UAAU,GAAG,eAAe,CAAC;IACpC,KAAK,EAAG,WAAW,CAAC;IACpB,EAAE,EAAE,QAAQ,CAAmB;gBAE1B,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IA+B9C,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAI9D,IAAW,MAAM,qBAEhB;IAED,IAAW,GAAG;;MAEb;IAED,IAAW,gBAAgB;;MAE1B;IAEM,KAAK,IAAI,eAAe;IAIxB,GAAG,IAAI,eAAe;IAI7B,OAAO,CAAC,UAAU;IA8CX,mBAAmB,CAAC,WAAW,EAAE,WAAW;IAsBnD,OAAO,CAAC,YAAY;IAcb,aAAa;IASb,WAAW,CAAC,OAAO,EAAE,GAAG;IAyBxB,WAAW;IAIL,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;IA0BnD,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAY1D,OAAO,IAAI,WAAW;IAItB,KAAK,CAAC,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,UAAU;IAOtD,KAAK,CAAC,GAAG,CAAC,EAAE,eAAe;IAO3B,OAAO;CAOf"}
@@ -6,6 +6,7 @@ import { CommandManager } from './commands/CommandManager.js';
6
6
  import { nodeToTreeString } from './nodeToTreeString.js';
7
7
  import { DummyEditorView } from './DummyEditorView.js';
8
8
  import { createNodeFromObject } from './utilities/createNodeFromContent.js';
9
+ import { defaultUi } from './ui.js';
9
10
  function ensureDocSchema(doc, schema) {
10
11
  if (doc.type.schema === schema) {
11
12
  return doc;
@@ -14,9 +15,9 @@ function ensureDocSchema(doc, schema) {
14
15
  return ProseMirrorNode.fromJSON(schema, json);
15
16
  }
16
17
  export class CoreEditor extends EventTarget {
17
- constructor(options = {}) {
18
+ constructor(config = {}) {
18
19
  super();
19
- Object.defineProperty(this, "options", {
20
+ Object.defineProperty(this, "config", {
20
21
  enumerable: true,
21
22
  configurable: true,
22
23
  writable: true,
@@ -49,20 +50,27 @@ export class CoreEditor extends EventTarget {
49
50
  writable: true,
50
51
  value: void 0
51
52
  });
52
- this.options = {
53
- ...this.options,
54
- ...options,
53
+ Object.defineProperty(this, "ui", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: defaultUi(this)
58
+ });
59
+ this.config = {
60
+ ...this.config,
61
+ ...config,
55
62
  };
56
- this.extensionManager = new ExtensionManager(this.options.extensions || [], this);
63
+ this.commandManager = new CommandManager(this);
64
+ this.extensionManager = new ExtensionManager(this.config.extensions || [], this, this.commandManager);
65
+ this.extensionManager.created();
57
66
  // const content = this.options.content ? this.options.content : {
58
67
  // type: this.extensionManager.schema.topNodeType.name,
59
68
  // content: this.extensionManager.schema.topNodeType.spec.EMPTY_DOC,
60
69
  // };
61
- const content = this.options.content
62
- ? this.options.content
70
+ const content = this.config.content
71
+ ? this.config.content
63
72
  : this.extensionManager.schema.topNodeType.spec.EMPTY_DOC;
64
73
  this.createView(content);
65
- this.commandManager = new CommandManager(this, this.extensionManager.commandFactories);
66
74
  this.setupPlugins();
67
75
  }
68
76
  getExtension(name) {
@@ -71,6 +79,12 @@ export class CoreEditor extends EventTarget {
71
79
  get schema() {
72
80
  return this.extensionManager.schema;
73
81
  }
82
+ get run() {
83
+ return this.commandManager.run;
84
+ }
85
+ get commandFactories() {
86
+ return this.commandManager.commandFactories;
87
+ }
74
88
  chain() {
75
89
  return this.commandManager.createChain();
76
90
  }
@@ -80,14 +94,30 @@ export class CoreEditor extends EventTarget {
80
94
  createView(content) {
81
95
  const doc = createNodeFromObject(content, this.schema);
82
96
  this.state = EditorState.create({ doc });
83
- if (this.options.element) {
84
- this.view = new EditorView(this.options.element, {
97
+ if (this.config.element) {
98
+ const view = new EditorView(this.config.element, {
85
99
  state: this.state,
86
100
  attributes: {
87
101
  class: 'kb-editor',
88
102
  },
89
103
  dispatchTransaction: (tx) => this.dispatchTransaction(tx),
90
104
  });
105
+ this.view = view;
106
+ const parent = this.config.element.parentNode;
107
+ if (parent) {
108
+ const observer = new MutationObserver((mutations) => {
109
+ for (const mutation of mutations) {
110
+ for (const removedNode of mutation.removedNodes) {
111
+ if (removedNode.contains(view.dom)) {
112
+ // Editor DOM was removed
113
+ observer.disconnect(); // Prevent multiple calls
114
+ view.destroy();
115
+ return;
116
+ }
117
+ }
118
+ }
119
+ });
120
+ }
91
121
  }
92
122
  else {
93
123
  this.view = new DummyEditorView({
@@ -95,6 +125,13 @@ export class CoreEditor extends EventTarget {
95
125
  dispatchTransaction: (tx) => this.dispatchTransaction(tx),
96
126
  });
97
127
  }
128
+ const event = new CustomEvent('doc:loaded', {
129
+ detail: {
130
+ editor: this,
131
+ doc,
132
+ },
133
+ });
134
+ this.dispatchEvent(event);
98
135
  }
99
136
  dispatchTransaction(transaction) {
100
137
  this.state = this.state.apply(transaction);
@@ -108,6 +145,14 @@ export class CoreEditor extends EventTarget {
108
145
  });
109
146
  this.dispatchEvent(event);
110
147
  }
148
+ if (transaction.docChanged) {
149
+ const event = new CustomEvent('changed', {
150
+ detail: {
151
+ editor: this,
152
+ },
153
+ });
154
+ this.dispatchEvent(event);
155
+ }
111
156
  }
112
157
  setupPlugins() {
113
158
  this.state = this.state.reconfigure({
@@ -188,7 +233,7 @@ export class CoreEditor extends EventTarget {
188
233
  clone(options = {}) {
189
234
  return new CoreEditor({
190
235
  ...options,
191
- extensions: [...(this.options.extensions || [])],
236
+ extensions: [...(this.config.extensions || [])],
192
237
  });
193
238
  }
194
239
  debug(doc) {
@@ -197,4 +242,11 @@ export class CoreEditor extends EventTarget {
197
242
  }
198
243
  console.debug(nodeToTreeString(doc));
199
244
  }
245
+ destroy() {
246
+ const event = new CustomEvent('beforeDestroy', {
247
+ detail: {},
248
+ });
249
+ this.dispatchEvent(event);
250
+ this.view.destroy();
251
+ }
200
252
  }
@@ -15,9 +15,14 @@ export declare abstract class Extension {
15
15
  protected config: Partial<ExtensionConfig>;
16
16
  readonly type = "extension";
17
17
  abstract name: string;
18
+ protected editor: CoreEditor;
19
+ readonly conflicts?: Array<string>;
18
20
  constructor(config?: Partial<ExtensionConfig>);
21
+ setEditor(editor: CoreEditor): void;
22
+ getEditor(): CoreEditor;
23
+ created(): void;
19
24
  getInputRules(): InputRule[];
20
- getProseMirrorPlugins(editor: CoreEditor, schema: Schema): Plugin[];
25
+ getProseMirrorPlugins(): Plugin[];
21
26
  getCommandFactories(editor: CoreEditor): Partial<CommandFactories>;
22
27
  getKeyboardShortcuts(editor: CoreEditor): Partial<CommandShortcuts>;
23
28
  getConverters(editor: CoreEditor, schema: Schema): Record<string, Converter>;