@threadlabs/looma 0.1.16 → 0.1.18

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 (133) hide show
  1. package/README.md +2 -1
  2. package/dist/{chunk-SVINNT3E.js → chunk-DTQVRGVL.js} +29 -29
  3. package/dist/{chunk-G53JEAQK.js → chunk-SZJQ3NPX.js} +6 -3
  4. package/dist/chunk-YHXJC5M5.js +341 -0
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/cjs/looma.cjs.js +1 -1
  7. package/dist/cjs/{manager-BOpVXb92.js → manager-C9j3HZay.js} +5 -2
  8. package/dist/cjs/positioning-i0WrCAdF.js +384 -0
  9. package/dist/cjs/ui-affordance-scope.cjs.entry.js +3 -113
  10. package/dist/cjs/ui-context-menu.cjs.entry.js +43 -5
  11. package/dist/cjs/ui-dialog.cjs.entry.js +1 -1
  12. package/dist/cjs/ui-menu.cjs.entry.js +83 -2
  13. package/dist/cjs/ui-popover.cjs.entry.js +43 -3
  14. package/dist/cjs/ui-toast-region.cjs.entry.js +17 -2
  15. package/dist/cjs/ui-tooltip.cjs.entry.js +95 -27
  16. package/dist/cjs/ui-tree-item.cjs.entry.js +1 -1
  17. package/dist/collection/components/ui-context-menu/ui-context-menu.css +21 -4
  18. package/dist/collection/components/ui-context-menu/ui-context-menu.js +43 -4
  19. package/dist/collection/components/ui-menu/ui-menu.css +39 -0
  20. package/dist/collection/components/ui-menu/ui-menu.js +128 -1
  21. package/dist/collection/components/ui-popover/ui-popover.css +31 -0
  22. package/dist/collection/components/ui-popover/ui-popover.js +87 -1
  23. package/dist/collection/components/ui-toast-region/ui-toast-region.css +6 -0
  24. package/dist/collection/components/ui-toast-region/ui-toast-region.js +16 -1
  25. package/dist/collection/components/ui-tooltip/ui-tooltip.css +20 -0
  26. package/dist/collection/components/ui-tooltip/ui-tooltip.js +160 -25
  27. package/dist/collection/components/ui-tree-item/ui-tree-item.css +10 -6
  28. package/dist/collection/input-modality.js +24 -0
  29. package/dist/collection/overlay/manager.js +5 -2
  30. package/dist/collection/overlay/positioning.js +246 -0
  31. package/dist/components/p-CEYIKqYc.js +1 -0
  32. package/dist/components/p-DOulVJT7.js +1 -0
  33. package/dist/components/p-PM9a74r7.js +1 -0
  34. package/dist/components/ui-affordance-scope.js +1 -1
  35. package/dist/components/ui-context-menu.js +1 -1
  36. package/dist/components/ui-dialog.js +1 -1
  37. package/dist/components/ui-menu.js +1 -1
  38. package/dist/components/ui-popover.js +1 -1
  39. package/dist/components/ui-toast-region.js +1 -1
  40. package/dist/components/ui-tooltip.js +1 -1
  41. package/dist/components/ui-tree-item.js +1 -1
  42. package/dist/esm/loader.js +1 -1
  43. package/dist/esm/looma.js +1 -1
  44. package/dist/esm/{manager-CR7f2MQC.js → manager-PM9a74r7.js} +5 -2
  45. package/dist/esm/positioning-Bu0dmLBE.js +379 -0
  46. package/dist/esm/ui-affordance-scope.entry.js +1 -111
  47. package/dist/esm/ui-context-menu.entry.js +43 -5
  48. package/dist/esm/ui-dialog.entry.js +1 -1
  49. package/dist/esm/ui-menu.entry.js +83 -2
  50. package/dist/esm/ui-popover.entry.js +43 -3
  51. package/dist/esm/ui-toast-region.entry.js +17 -2
  52. package/dist/esm/ui-tooltip.entry.js +95 -27
  53. package/dist/esm/ui-tree-item.entry.js +1 -1
  54. package/dist/index.cjs +779 -59
  55. package/dist/index.d.cts +44 -1
  56. package/dist/index.d.ts +44 -1
  57. package/dist/index.js +235 -4
  58. package/dist/looma/looma.esm.js +1 -1
  59. package/dist/looma/p-063f5a89.entry.js +1 -0
  60. package/dist/looma/{p-c6721aba.entry.js → p-11083743.entry.js} +1 -1
  61. package/dist/looma/p-1674cda4.entry.js +1 -0
  62. package/dist/looma/p-2e6f791e.entry.js +1 -0
  63. package/dist/looma/p-54c41576.entry.js +1 -0
  64. package/dist/looma/p-9194a99d.entry.js +1 -0
  65. package/dist/looma/p-Bu0dmLBE.js +1 -0
  66. package/dist/looma/p-PM9a74r7.js +1 -0
  67. package/dist/looma/p-caa8fc7b.entry.js +1 -0
  68. package/dist/looma/{p-ef9ca2ed.entry.js → p-d01960c2.entry.js} +2 -2
  69. package/dist/types/components/ui-context-menu/ui-context-menu.d.ts +6 -0
  70. package/dist/types/components/ui-menu/ui-menu.d.ts +13 -0
  71. package/dist/types/components/ui-popover/ui-popover.d.ts +9 -0
  72. package/dist/types/components/ui-toast-region/ui-toast-region.d.ts +2 -0
  73. package/dist/types/components/ui-tooltip/ui-tooltip.d.ts +16 -1
  74. package/dist/types/components.d.ts +71 -0
  75. package/dist/types/input-modality.d.ts +6 -0
  76. package/dist/types/overlay/manager.d.ts +3 -0
  77. package/dist/types/overlay/positioning.d.ts +33 -0
  78. package/dist/ui-affordance-scope.entry-2W7ZKAGK.js +54 -0
  79. package/dist/{ui-avatar-group.entry-DQDP325O.js → ui-avatar-group.entry-SE5JG2FT.js} +1 -1
  80. package/dist/{ui-avatar.entry-WYIDMOFE.js → ui-avatar.entry-46JDI25A.js} +1 -1
  81. package/dist/{ui-badge.entry-VGHXPEDT.js → ui-badge.entry-U7G3MEC5.js} +1 -1
  82. package/dist/{ui-button.entry-LKPLOJ22.js → ui-button.entry-DELD6KMH.js} +1 -1
  83. package/dist/{ui-checkbox.entry-J74HEA22.js → ui-checkbox.entry-ZUG2P642.js} +1 -1
  84. package/dist/{ui-context-menu.entry-MQM2FCLI.js → ui-context-menu.entry-L4HTK3PV.js} +43 -6
  85. package/dist/{ui-dialog.entry-DQMMDO4Z.js → ui-dialog.entry-TQPYD2YI.js} +2 -2
  86. package/dist/{ui-disclosure.entry-ONF7UZDC.js → ui-disclosure.entry-23TII4YU.js} +1 -1
  87. package/dist/{ui-floating-action-button.entry-FKTGVC5T.js → ui-floating-action-button.entry-FOQYAFJI.js} +1 -1
  88. package/dist/{ui-form-field.entry-M3ISWQNU.js → ui-form-field.entry-SCPG4STY.js} +1 -1
  89. package/dist/{ui-icon-button.entry-AWFIQUHM.js → ui-icon-button.entry-U45ZVAC3.js} +1 -1
  90. package/dist/{ui-input.entry-JZ6RETMT.js → ui-input.entry-3AIA3G4C.js} +1 -1
  91. package/dist/{ui-menu-item.entry-5MFR5LFL.js → ui-menu-item.entry-3QO5TG2J.js} +1 -1
  92. package/dist/ui-menu.entry-JACWGDDG.js +184 -0
  93. package/dist/{ui-popover.entry-ELCMKO6Y.js → ui-popover.entry-2XP4H3S2.js} +46 -4
  94. package/dist/{ui-radio-group.entry-RJHUPPEM.js → ui-radio-group.entry-73IKFMDK.js} +1 -1
  95. package/dist/{ui-radio.entry-3VRDPOY4.js → ui-radio.entry-INJVXUKE.js} +1 -1
  96. package/dist/{ui-search-result-row.entry-J34YPAV7.js → ui-search-result-row.entry-4J732TDC.js} +1 -1
  97. package/dist/{ui-search-shell.entry-IJ4UUP27.js → ui-search-shell.entry-3C2WRVE2.js} +1 -1
  98. package/dist/{ui-select.entry-C6YD3HQ5.js → ui-select.entry-3ZLDGAKX.js} +1 -1
  99. package/dist/{ui-switch.entry-UZDF5QTI.js → ui-switch.entry-5MJRLR2P.js} +1 -1
  100. package/dist/{ui-tabs.entry-YRAKWOMR.js → ui-tabs.entry-F5H7OPBO.js} +1 -1
  101. package/dist/{ui-textarea.entry-JLDKFT3K.js → ui-textarea.entry-BNJ375JB.js} +1 -1
  102. package/dist/{ui-toast-region.entry-GC7C7KXF.js → ui-toast-region.entry-ZUIPJ2JH.js} +20 -3
  103. package/dist/ui-tooltip.entry-DZ4RMF35.js +214 -0
  104. package/dist/{ui-top-bar.entry-5W5UA5KV.js → ui-top-bar.entry-VKRXIUU6.js} +1 -1
  105. package/dist/{ui-tree-item.entry-3LM7IXIK.js → ui-tree-item.entry-NFUQ45OL.js} +2 -2
  106. package/dist/{ui-tree.entry-X4FU42A6.js → ui-tree.entry-H4CWDYI6.js} +1 -1
  107. package/editor/{chunk-RTHHTPWK.js → chunk-3QMBK3XZ.js} +245 -41
  108. package/editor/{chunk-OHD4OS32.js → chunk-OXFYYLUC.js} +632 -236
  109. package/editor/{chunk-CX4QDKSV.js → chunk-ZOUKEZ77.js} +21 -1
  110. package/editor/extensions/index.d.ts +49 -1
  111. package/editor/extensions/index.js +15 -3
  112. package/editor/index.d.ts +3 -2
  113. package/editor/index.js +16 -4
  114. package/editor/ui.d.ts +9 -1
  115. package/editor/ui.js +2 -2
  116. package/editor.css +173 -4
  117. package/package.json +1 -1
  118. package/styles.css +1 -7
  119. package/tokens.css +14 -2
  120. package/vue/editor/index.d.ts +103 -4
  121. package/vue/editor/index.js +199 -114
  122. package/dist/components/p-CR7f2MQC.js +0 -1
  123. package/dist/components/p-QiwSQmKJ.js +0 -1
  124. package/dist/looma/p-2ae73d5b.entry.js +0 -1
  125. package/dist/looma/p-3ac2e0d4.entry.js +0 -1
  126. package/dist/looma/p-65c25c94.entry.js +0 -1
  127. package/dist/looma/p-8c09c724.entry.js +0 -1
  128. package/dist/looma/p-95cd639d.entry.js +0 -1
  129. package/dist/looma/p-96f73d07.entry.js +0 -1
  130. package/dist/looma/p-CR7f2MQC.js +0 -1
  131. package/dist/ui-affordance-scope.entry-PFP2TDKO.js +0 -145
  132. package/dist/ui-menu.entry-IOEIDATQ.js +0 -98
  133. package/dist/ui-tooltip.entry-F26XDTYX.js +0 -145
@@ -1,12 +1,14 @@
1
- import { SlashMenuItem, SlashMenuAnchorRect } from '@threadlabs/looma/editor';
1
+ import { LoomaMentionItem, SlashMenuAnchorRect, SlashMenuItem, LoomaMentionProvider } from '@threadlabs/looma/editor';
2
2
  export * from '@threadlabs/looma/editor';
3
3
  import * as vue from 'vue';
4
4
  import { PropType } from 'vue';
5
- import { TableContextMenuActionEventDetail, InsertTableEventDetail, TableOverlayActionEventDetail, SlashMenuHighlightEventDetail, SlashMenuSelectEventDetail } from '@threadlabs/looma/editor/ui';
5
+ import { MentionMenuHighlightEventDetail, MentionMenuSelectEventDetail, TableContextMenuActionEventDetail, InsertTableEventDetail, TableOverlayActionEventDetail, SlashMenuHighlightEventDetail, SlashMenuSelectEventDetail } from '@threadlabs/looma/editor/ui';
6
6
  import { JSONContent, AnyExtension, Editor } from '@tiptap/core';
7
7
  import { OverlayTrigger } from '@threadlabs/looma/core';
8
8
 
9
9
  interface VueEditorAdapterEventMap {
10
+ mentionMenuHighlight: MentionMenuHighlightEventDetail;
11
+ mentionMenuSelect: MentionMenuSelectEventDetail;
10
12
  tableAction: TableContextMenuActionEventDetail;
11
13
  insertTable: InsertTableEventDetail;
12
14
  tableOverlayAction: TableOverlayActionEventDetail;
@@ -34,6 +36,10 @@ declare const EditorSlashMenu: vue.DefineComponent<vue.ExtractPropTypes<{
34
36
  type: PropType<SlashMenuAnchorRect | null>;
35
37
  default: null;
36
38
  };
39
+ loading: {
40
+ type: BooleanConstructor;
41
+ default: boolean;
42
+ };
37
43
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
38
44
  [key: string]: any;
39
45
  }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
@@ -57,12 +63,77 @@ declare const EditorSlashMenu: vue.DefineComponent<vue.ExtractPropTypes<{
57
63
  type: PropType<SlashMenuAnchorRect | null>;
58
64
  default: null;
59
65
  };
66
+ loading: {
67
+ type: BooleanConstructor;
68
+ default: boolean;
69
+ };
60
70
  }>> & Readonly<{}>, {
61
71
  open: boolean;
62
- query: string;
63
72
  items: SlashMenuItem[];
73
+ query: string;
64
74
  selectedIndex: number;
65
75
  anchorRect: SlashMenuAnchorRect | null;
76
+ loading: boolean;
77
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
78
+ declare const EditorMentionMenu: vue.DefineComponent<vue.ExtractPropTypes<{
79
+ open: {
80
+ type: BooleanConstructor;
81
+ default: boolean;
82
+ };
83
+ query: {
84
+ type: StringConstructor;
85
+ default: string;
86
+ };
87
+ items: {
88
+ type: PropType<LoomaMentionItem[]>;
89
+ default: () => never[];
90
+ };
91
+ selectedIndex: {
92
+ type: NumberConstructor;
93
+ default: number;
94
+ };
95
+ anchorRect: {
96
+ type: PropType<SlashMenuAnchorRect | null>;
97
+ default: null;
98
+ };
99
+ loading: {
100
+ type: BooleanConstructor;
101
+ default: boolean;
102
+ };
103
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
104
+ [key: string]: any;
105
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
106
+ open: {
107
+ type: BooleanConstructor;
108
+ default: boolean;
109
+ };
110
+ query: {
111
+ type: StringConstructor;
112
+ default: string;
113
+ };
114
+ items: {
115
+ type: PropType<LoomaMentionItem[]>;
116
+ default: () => never[];
117
+ };
118
+ selectedIndex: {
119
+ type: NumberConstructor;
120
+ default: number;
121
+ };
122
+ anchorRect: {
123
+ type: PropType<SlashMenuAnchorRect | null>;
124
+ default: null;
125
+ };
126
+ loading: {
127
+ type: BooleanConstructor;
128
+ default: boolean;
129
+ };
130
+ }>> & Readonly<{}>, {
131
+ open: boolean;
132
+ items: LoomaMentionItem[];
133
+ query: string;
134
+ selectedIndex: number;
135
+ anchorRect: SlashMenuAnchorRect | null;
136
+ loading: boolean;
66
137
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
67
138
  declare const EditorToolbar: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
68
139
  [key: string]: any;
@@ -82,6 +153,7 @@ declare const EditorTableOverlay: vue.DefineComponent<{}, () => vue.VNode<vue.Re
82
153
  declare const EDITOR_ADAPTER_COMPONENT_TAG_MAP: {
83
154
  readonly EditorToolbar: "ui-editor-toolbar";
84
155
  readonly EditorSlashMenu: "ui-editor-slash-menu";
156
+ readonly EditorMentionMenu: "ui-editor-mention-menu";
85
157
  readonly EditorTableContextMenu: "ui-editor-table-context-menu";
86
158
  readonly EditorTableToolbar: "ui-editor-table-toolbar";
87
159
  readonly EditorInsertTableGrid: "ui-editor-insert-table-grid";
@@ -145,6 +217,18 @@ declare const LoomaEditor: vue.DefineComponent<vue.ExtractPropTypes<{
145
217
  type: PropType<AnyExtension[]>;
146
218
  default: () => never[];
147
219
  };
220
+ mentionItems: {
221
+ type: PropType<LoomaMentionItem[]>;
222
+ default: () => never[];
223
+ };
224
+ mentionProvider: {
225
+ type: PropType<LoomaMentionProvider | undefined>;
226
+ default: undefined;
227
+ };
228
+ mentionLimit: {
229
+ type: NumberConstructor;
230
+ default: number;
231
+ };
148
232
  uploadImage: {
149
233
  type: PropType<LoomaImageUploader | undefined>;
150
234
  default: undefined;
@@ -190,6 +274,18 @@ declare const LoomaEditor: vue.DefineComponent<vue.ExtractPropTypes<{
190
274
  type: PropType<AnyExtension[]>;
191
275
  default: () => never[];
192
276
  };
277
+ mentionItems: {
278
+ type: PropType<LoomaMentionItem[]>;
279
+ default: () => never[];
280
+ };
281
+ mentionProvider: {
282
+ type: PropType<LoomaMentionProvider | undefined>;
283
+ default: undefined;
284
+ };
285
+ mentionLimit: {
286
+ type: NumberConstructor;
287
+ default: number;
288
+ };
193
289
  uploadImage: {
194
290
  type: PropType<LoomaImageUploader | undefined>;
195
291
  default: undefined;
@@ -210,8 +306,11 @@ declare const LoomaEditor: vue.DefineComponent<vue.ExtractPropTypes<{
210
306
  modelValue: JSONContent;
211
307
  editable: boolean;
212
308
  extensions: AnyExtension[];
309
+ mentionItems: LoomaMentionItem[];
310
+ mentionProvider: LoomaMentionProvider | undefined;
311
+ mentionLimit: number;
213
312
  uploadImage: LoomaImageUploader | undefined;
214
313
  resolveImageAttributes: LoomaImageAttributeResolver | undefined;
215
314
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
216
315
 
217
- export { EDITOR_ADAPTER_COMPONENT_TAG_MAP, EditorInsertTableGrid, EditorSlashMenu, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, LoomaEditor, type LoomaImageActivationDetail, type LoomaImageActivationTrigger, type LoomaImageAttributeResolver, type LoomaImageDescriptor, type LoomaImageRenditionAttributes, type LoomaImageRenditionErrorDetail, type LoomaImageUploadResult, type LoomaImageUploader, type VueEditorAdapterEventMap };
316
+ export { EDITOR_ADAPTER_COMPONENT_TAG_MAP, EditorInsertTableGrid, EditorMentionMenu, EditorSlashMenu, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, LoomaEditor, type LoomaImageActivationDetail, type LoomaImageActivationTrigger, type LoomaImageAttributeResolver, type LoomaImageDescriptor, type LoomaImageRenditionAttributes, type LoomaImageRenditionErrorDetail, type LoomaImageUploadResult, type LoomaImageUploader, type VueEditorAdapterEventMap };
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  IconButton,
3
+ Popover,
3
4
  createAdapterComponent,
4
5
  toHTMLElement
5
6
  } from "../chunk-5KWCMTXB.js";
@@ -15,73 +16,86 @@ import {
15
16
  shallowRef,
16
17
  watchEffect
17
18
  } from "vue";
19
+ function createSuggestionMenuAdapter(tag, name, eventPrefix) {
20
+ return defineComponent({
21
+ name,
22
+ inheritAttrs: false,
23
+ props: {
24
+ open: { type: Boolean, default: false },
25
+ query: { type: String, default: "" },
26
+ items: { type: Array, default: () => [] },
27
+ selectedIndex: { type: Number, default: 0 },
28
+ anchorRect: { type: Object, default: null },
29
+ loading: { type: Boolean, default: false }
30
+ },
31
+ setup(props, { attrs }) {
32
+ const elementRef = shallowRef(null);
33
+ watchEffect(() => {
34
+ const element = elementRef.value;
35
+ if (!element) return;
36
+ if (element.open !== props.open) element.open = props.open;
37
+ if (element.query !== props.query) element.query = props.query;
38
+ if (element.items !== props.items) element.items = props.items;
39
+ if (element.selectedIndex !== props.selectedIndex) element.selectedIndex = props.selectedIndex;
40
+ if (element.anchorRect !== props.anchorRect) element.anchorRect = props.anchorRect;
41
+ if (element.loading !== void 0 && element.loading !== props.loading) {
42
+ element.loading = props.loading;
43
+ }
44
+ });
45
+ watchEffect((onCleanup) => {
46
+ const element = elementRef.value;
47
+ if (!element) return;
48
+ const callbackAttrs = attrs;
49
+ const highlightCallback = eventPrefix === "slash" ? callbackAttrs.onSlashMenuHighlight : callbackAttrs.onMentionMenuHighlight;
50
+ const selectCallback = eventPrefix === "slash" ? callbackAttrs.onSlashMenuSelect : callbackAttrs.onMentionMenuSelect;
51
+ const eventBase = `looma-editor-${eventPrefix}-menu`;
52
+ const highlightHandler = typeof highlightCallback === "function" ? (event) => highlightCallback(event.detail) : void 0;
53
+ const selectHandler = typeof selectCallback === "function" ? (event) => selectCallback(event.detail) : void 0;
54
+ if (highlightHandler) element.addEventListener(`${eventBase}-highlight`, highlightHandler);
55
+ if (selectHandler) element.addEventListener(`${eventBase}-select`, selectHandler);
56
+ onCleanup(() => {
57
+ if (highlightHandler) element.removeEventListener(`${eventBase}-highlight`, highlightHandler);
58
+ if (selectHandler) element.removeEventListener(`${eventBase}-select`, selectHandler);
59
+ });
60
+ });
61
+ return () => {
62
+ const callbackAttrs = attrs;
63
+ const {
64
+ onMentionMenuHighlight,
65
+ onMentionMenuSelect,
66
+ onSlashMenuHighlight,
67
+ onSlashMenuSelect,
68
+ ...forwardedAttrs
69
+ } = callbackAttrs;
70
+ void onMentionMenuHighlight;
71
+ void onMentionMenuSelect;
72
+ void onSlashMenuHighlight;
73
+ void onSlashMenuSelect;
74
+ return h(tag, {
75
+ ...forwardedAttrs,
76
+ ref: (value) => {
77
+ elementRef.value = toHTMLElement(value);
78
+ }
79
+ });
80
+ };
81
+ }
82
+ });
83
+ }
18
84
  var EDITOR_EVENT_BINDINGS = [
19
85
  ["looma-editor-table-action", "onTableAction"],
20
86
  ["looma-editor-insert-table", "onInsertTable"],
21
87
  ["looma-editor-table-overlay-action", "onTableOverlayAction"]
22
88
  ];
23
- var EditorSlashMenu = defineComponent({
24
- name: "EditorSlashMenu",
25
- inheritAttrs: false,
26
- props: {
27
- open: { type: Boolean, default: false },
28
- query: { type: String, default: "" },
29
- items: { type: Array, default: () => [] },
30
- selectedIndex: { type: Number, default: 0 },
31
- anchorRect: { type: Object, default: null }
32
- },
33
- setup(props, { attrs }) {
34
- const elementRef = shallowRef(null);
35
- watchEffect(() => {
36
- const element = elementRef.value;
37
- if (!element) return;
38
- if (element.open !== props.open) element.open = props.open;
39
- if (element.query !== props.query) element.query = props.query;
40
- if (element.items !== props.items) element.items = props.items;
41
- if (element.selectedIndex !== props.selectedIndex) element.selectedIndex = props.selectedIndex;
42
- if (element.anchorRect !== props.anchorRect) element.anchorRect = props.anchorRect;
43
- });
44
- watchEffect((onCleanup) => {
45
- const element = elementRef.value;
46
- if (!element) return;
47
- const callbackAttrs = attrs;
48
- const handlers = [
49
- [
50
- "looma-editor-slash-menu-highlight",
51
- typeof callbackAttrs.onSlashMenuHighlight === "function" ? (event) => callbackAttrs.onSlashMenuHighlight?.(
52
- event.detail
53
- ) : void 0
54
- ],
55
- [
56
- "looma-editor-slash-menu-select",
57
- typeof callbackAttrs.onSlashMenuSelect === "function" ? (event) => callbackAttrs.onSlashMenuSelect?.(
58
- event.detail
59
- ) : void 0
60
- ]
61
- ];
62
- for (const [eventName, handler] of handlers) {
63
- if (handler) element.addEventListener(eventName, handler);
64
- }
65
- onCleanup(() => {
66
- for (const [eventName, handler] of handlers) {
67
- if (handler) element.removeEventListener(eventName, handler);
68
- }
69
- });
70
- });
71
- return () => {
72
- const callbackAttrs = attrs;
73
- const { onSlashMenuHighlight, onSlashMenuSelect, ...forwardedAttrs } = callbackAttrs;
74
- void onSlashMenuHighlight;
75
- void onSlashMenuSelect;
76
- return h("ui-editor-slash-menu", {
77
- ...forwardedAttrs,
78
- ref: (value) => {
79
- elementRef.value = toHTMLElement(value);
80
- }
81
- });
82
- };
83
- }
84
- });
89
+ var EditorSlashMenu = createSuggestionMenuAdapter(
90
+ "ui-editor-slash-menu",
91
+ "EditorSlashMenu",
92
+ "slash"
93
+ );
94
+ var EditorMentionMenu = createSuggestionMenuAdapter(
95
+ "ui-editor-mention-menu",
96
+ "EditorMentionMenu",
97
+ "mention"
98
+ );
85
99
  var EditorToolbar = createAdapterComponent("ui-editor-toolbar", "EditorToolbar", EDITOR_EVENT_BINDINGS);
86
100
  var EditorTableContextMenu = createAdapterComponent("ui-editor-table-context-menu", "EditorTableContextMenu", EDITOR_EVENT_BINDINGS);
87
101
  var EditorTableToolbar = createAdapterComponent("ui-editor-table-toolbar", "EditorTableToolbar", EDITOR_EVENT_BINDINGS);
@@ -96,6 +110,7 @@ var EditorTableOverlay = createAdapterComponent(
96
110
  var EDITOR_ADAPTER_COMPONENT_TAG_MAP = {
97
111
  EditorToolbar: "ui-editor-toolbar",
98
112
  EditorSlashMenu: "ui-editor-slash-menu",
113
+ EditorMentionMenu: "ui-editor-mention-menu",
99
114
  EditorTableContextMenu: "ui-editor-table-context-menu",
100
115
  EditorTableToolbar: "ui-editor-table-toolbar",
101
116
  EditorInsertTableGrid: "ui-editor-insert-table-grid",
@@ -104,6 +119,7 @@ var EDITOR_ADAPTER_COMPONENT_TAG_MAP = {
104
119
 
105
120
  // src/editor/LoomaEditor.ts
106
121
  import { BubbleMenu, EditorContent, useEditor } from "@tiptap/vue-3";
122
+ import { TextSelection } from "@tiptap/pm/state";
107
123
  import {
108
124
  defineComponent as defineComponent2,
109
125
  h as h2,
@@ -112,10 +128,13 @@ import {
112
128
  onMounted,
113
129
  reactive,
114
130
  ref,
131
+ useId,
115
132
  watch
116
133
  } from "vue";
117
134
  import {
118
135
  createLoomaSlashCommandExtension,
136
+ createLoomaMentionExtension,
137
+ DEFAULT_MENTION_RESULT_LIMIT,
119
138
  getActiveTableUiState,
120
139
  getDefaultEditorExtensions,
121
140
  handleTableAction,
@@ -125,11 +144,7 @@ import {
125
144
  resolveTableCellAt,
126
145
  shouldShowTextFormattingToolbar
127
146
  } from "@threadlabs/looma/editor";
128
- import {
129
- clampRectToViewport,
130
- getVisualViewportRect,
131
- LOOMA_ICONS
132
- } from "@threadlabs/looma/core";
147
+ import { getVisualViewportRect, LOOMA_ICONS } from "@threadlabs/looma/core";
133
148
 
134
149
  // src/editor/image-delivery.ts
135
150
  import { Extension } from "@tiptap/core";
@@ -313,6 +328,7 @@ function imageUploadContent(image) {
313
328
 
314
329
  // src/editor/LoomaEditor.ts
315
330
  var EMPTY_DOCUMENT = { type: "doc", content: [] };
331
+ var editorInstanceSequence = 0;
316
332
  var EMPTY_CAPABILITIES = {
317
333
  canAddRowBefore: false,
318
334
  canAddRowAfter: false,
@@ -368,6 +384,18 @@ var LoomaEditor = defineComponent2({
368
384
  type: Array,
369
385
  default: () => []
370
386
  },
387
+ mentionItems: {
388
+ type: Array,
389
+ default: () => []
390
+ },
391
+ mentionProvider: {
392
+ type: Function,
393
+ default: void 0
394
+ },
395
+ mentionLimit: {
396
+ type: Number,
397
+ default: DEFAULT_MENTION_RESULT_LIMIT
398
+ },
371
399
  uploadImage: {
372
400
  type: Function,
373
401
  default: void 0
@@ -388,8 +416,7 @@ var LoomaEditor = defineComponent2({
388
416
  setup(props, { attrs, emit, expose }) {
389
417
  const root = ref(null);
390
418
  const fileInput = ref(null);
391
- const tablePickerAnchor = ref(null);
392
- const tablePickerPopover = ref(null);
419
+ const tablePickerAnchorId = `looma-editor-table-picker-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
393
420
  const tableToolbarShell = ref(null);
394
421
  const tableOverlayShell = ref(null);
395
422
  const tableMenuShell = ref(null);
@@ -398,7 +425,6 @@ var LoomaEditor = defineComponent2({
398
425
  const uploading = ref(false);
399
426
  const failedUpload = ref(null);
400
427
  const tablePickerOpen = ref(false);
401
- const tablePickerStyle = ref({});
402
428
  const mobileToolbarStyle = ref({});
403
429
  const mobile = ref(typeof window !== "undefined" && window.innerWidth <= 767);
404
430
  const editorFocused = ref(false);
@@ -418,6 +444,16 @@ var LoomaEditor = defineComponent2({
418
444
  rect: null,
419
445
  select: null
420
446
  });
447
+ const mention = reactive({
448
+ active: false,
449
+ items: [],
450
+ selectedIndex: 0,
451
+ query: "",
452
+ rect: null,
453
+ loading: false,
454
+ highlight: null,
455
+ select: null
456
+ });
421
457
  const tableUi = reactive({
422
458
  toolbarOpen: false,
423
459
  overlayOpen: false,
@@ -438,12 +474,41 @@ var LoomaEditor = defineComponent2({
438
474
  Object.assign(slash, state);
439
475
  }
440
476
  });
477
+ const mentionMenuId = `looma-editor-mention-menu-${++editorInstanceSequence}`;
478
+ const hasConsumerMention = props.extensions.some((extension) => extension.name === "mention");
479
+ const mentionExtension = hasConsumerMention ? null : createLoomaMentionExtension({
480
+ limit: props.mentionLimit,
481
+ menuId: mentionMenuId,
482
+ items: async (query, context) => {
483
+ if (props.mentionProvider) {
484
+ return await props.mentionProvider(query, context);
485
+ }
486
+ return props.mentionItems;
487
+ },
488
+ onStateChange: (state) => {
489
+ Object.assign(mention, state);
490
+ }
491
+ });
441
492
  const imageDelivery = createLoomaImageDeliveryController({
442
493
  resolveAttributes: () => props.resolveImageAttributes
443
494
  });
495
+ let lastFocusedSelection = null;
496
+ const rememberSelection = (instance) => {
497
+ if (!instance.isFocused) return;
498
+ const selection = instance.view.state.selection;
499
+ lastFocusedSelection = {
500
+ bookmark: selection.getBookmark(),
501
+ from: selection.from,
502
+ to: selection.to,
503
+ text: selection instanceof TextSelection
504
+ };
505
+ };
444
506
  const editor = useEditor({
445
507
  extensions: [
446
- ...getDefaultEditorExtensions({ placeholder: props.placeholder }),
508
+ ...getDefaultEditorExtensions({
509
+ placeholder: props.placeholder,
510
+ mention: mentionExtension ?? false
511
+ }),
447
512
  imageDelivery.extension,
448
513
  slashExtension,
449
514
  ...props.extensions
@@ -451,6 +516,8 @@ var LoomaEditor = defineComponent2({
451
516
  content: props.modelValue,
452
517
  editable: props.editable,
453
518
  onCreate: ({ editor: instance }) => emit("ready", instance),
519
+ onFocus: ({ editor: instance }) => rememberSelection(instance),
520
+ onSelectionUpdate: ({ editor: instance }) => rememberSelection(instance),
454
521
  onUpdate: ({ editor: instance }) => {
455
522
  const value = instance.getJSON();
456
523
  emit("update:modelValue", value);
@@ -465,7 +532,30 @@ var LoomaEditor = defineComponent2({
465
532
  watch(() => props.modelValue, (value) => {
466
533
  const instance = editor.value;
467
534
  if (!instance || sameDocument(instance.getJSON(), value)) return;
468
- instance.commands.setContent(value, false);
535
+ const wasFocused = instance.isFocused;
536
+ const previousSelection = lastFocusedSelection ?? {
537
+ bookmark: instance.view.state.selection.getBookmark(),
538
+ from: instance.view.state.selection.from,
539
+ to: instance.view.state.selection.to,
540
+ text: instance.view.state.selection instanceof TextSelection
541
+ };
542
+ if (!wasFocused) {
543
+ instance.commands.setContent(value, false);
544
+ return;
545
+ }
546
+ instance.chain().setContent(value, false).command(({ tr }) => {
547
+ try {
548
+ tr.setSelection(previousSelection.text ? TextSelection.create(tr.doc, previousSelection.from, previousSelection.to) : previousSelection.bookmark.resolve(tr.doc));
549
+ } catch {
550
+ const max = tr.doc.content.size;
551
+ const from = Math.max(1, Math.min(previousSelection.from, max));
552
+ const to = Math.max(from, Math.min(previousSelection.to, max));
553
+ tr.setSelection(TextSelection.create(tr.doc, from, to));
554
+ }
555
+ return true;
556
+ }).run();
557
+ instance.view.focus();
558
+ rememberSelection(instance);
469
559
  }, { deep: true });
470
560
  const closeTableUi = () => {
471
561
  tableUi.toolbarOpen = false;
@@ -574,38 +664,9 @@ var LoomaEditor = defineComponent2({
574
664
  unbindEditorUi(previous);
575
665
  bindEditorUi(instance);
576
666
  }, { immediate: true });
577
- const updateTablePickerPosition = () => {
578
- const anchor = tablePickerAnchor.value;
579
- if (!anchor) return;
580
- const rect = anchor.getBoundingClientRect();
581
- const viewport = getVisualViewportRect(window);
582
- const width = 220;
583
- const popoverHeight = tablePickerPopover.value?.getBoundingClientRect().height || 300;
584
- const target = {
585
- left: rect.left,
586
- top: rect.bottom + 8,
587
- right: rect.left + width,
588
- bottom: rect.bottom + 8 + popoverHeight,
589
- width,
590
- height: popoverHeight
591
- };
592
- const offset = clampRectToViewport(
593
- target,
594
- viewport,
595
- 12
596
- );
597
- const left = target.left + offset.x;
598
- const top = target.top + offset.y;
599
- tablePickerStyle.value = window.innerWidth <= 767 ? {
600
- position: "fixed",
601
- left: `${left}px`,
602
- top: `${Math.max(viewport.top + 12, viewport.bottom - popoverHeight - 64)}px`
603
- } : { position: "fixed", top: `${top}px`, left: `${left}px` };
604
- };
605
667
  const onViewportChange = () => {
606
668
  updateMobileViewport();
607
669
  updateTableUi();
608
- updateTablePickerPosition();
609
670
  tableUi.menuOpen = false;
610
671
  };
611
672
  const onDocumentPointerDown = (event) => {
@@ -618,9 +679,6 @@ var LoomaEditor = defineComponent2({
618
679
  if (inTableUi) setTimeout(() => {
619
680
  tableInteractionActive = false;
620
681
  }, 0);
621
- if (tablePickerOpen.value && !inElement(tablePickerAnchor.value) && !inElement(tablePickerPopover.value)) {
622
- tablePickerOpen.value = false;
623
- }
624
682
  if ((tableUi.toolbarOpen || tableUi.overlayOpen || tableUi.menuOpen) && !inElement(root.value) && !inTableUi) {
625
683
  closeTableUi();
626
684
  }
@@ -858,12 +916,18 @@ var LoomaEditor = defineComponent2({
858
916
  commandButton("Code block", "braces", instance.isActive("codeBlock"), !instance.can().toggleCodeBlock(), () => instance.chain().focus().toggleCodeBlock().run()),
859
917
  commandButton("Divider", "minus", false, !instance.can().setHorizontalRule(), () => instance.chain().focus().setHorizontalRule().run()),
860
918
  h2("span", { class: "ui-editor-toolbar__divider", "aria-hidden": "true" }),
861
- h2("span", { ref: tablePickerAnchor, class: "looma-editor__table-picker-anchor" }, [
862
- commandButton("Insert table", "table", false, false, () => {
919
+ h2(IconButton, {
920
+ id: tablePickerAnchorId,
921
+ class: "looma-editor__toolbar-button",
922
+ label: "Insert table",
923
+ title: "Insert table",
924
+ size: "sm",
925
+ variant: tablePickerOpen.value ? "solid" : "ghost",
926
+ "aria-expanded": tablePickerOpen.value ? "true" : "false",
927
+ onClick: () => {
863
928
  tablePickerOpen.value = !tablePickerOpen.value;
864
- nextTick(updateTablePickerPosition);
865
- })
866
- ]),
929
+ }
930
+ }, () => loomaIcon("table")),
867
931
  commandButton(uploading.value ? "Uploading image" : "Insert image", "image", false, uploading.value || !props.uploadImage, () => fileInput.value?.click()),
868
932
  h2("span", { class: "ui-editor-toolbar__divider", "aria-hidden": "true" }),
869
933
  commandButton("Undo", "undo", false, !instance.can().undo(), () => instance.chain().focus().undo().run()),
@@ -976,17 +1040,21 @@ var LoomaEditor = defineComponent2({
976
1040
  loomaIcon("image"),
977
1041
  h2("span", "Drop image to upload")
978
1042
  ]) : null,
979
- tablePickerOpen.value ? h2("div", {
980
- ref: tablePickerPopover,
1043
+ h2(Popover, {
981
1044
  class: "looma-editor__table-picker-popover",
982
- style: tablePickerStyle.value
983
- }, [h2(EditorInsertTableGrid, {
1045
+ open: tablePickerOpen.value,
1046
+ for: tablePickerAnchorId,
1047
+ placement: mobile.value ? "top-start" : "bottom-start",
1048
+ onClose: () => {
1049
+ tablePickerOpen.value = false;
1050
+ }
1051
+ }, () => [h2(EditorInsertTableGrid, {
984
1052
  open: true,
985
1053
  onInsertTable: (detail) => {
986
1054
  instance?.chain().focus().insertTable(detail).run();
987
1055
  tablePickerOpen.value = false;
988
1056
  }
989
- })]) : null,
1057
+ })]),
990
1058
  slash.active && slash.items.length > 0 ? h2(EditorSlashMenu, {
991
1059
  open: true,
992
1060
  query: slash.query,
@@ -1000,6 +1068,22 @@ var LoomaEditor = defineComponent2({
1000
1068
  slash.select?.(index);
1001
1069
  }
1002
1070
  }) : null,
1071
+ mention.active && (mention.loading || mention.items.length > 0) ? h2(EditorMentionMenu, {
1072
+ id: mentionMenuId,
1073
+ open: true,
1074
+ query: mention.query,
1075
+ items: mention.items,
1076
+ selectedIndex: mention.selectedIndex,
1077
+ anchorRect: mention.rect,
1078
+ loading: mention.loading,
1079
+ onMentionMenuHighlight: ({ index }) => {
1080
+ mention.selectedIndex = index;
1081
+ mention.highlight?.(index);
1082
+ },
1083
+ onMentionMenuSelect: ({ index }) => {
1084
+ mention.select?.(index);
1085
+ }
1086
+ }) : null,
1003
1087
  tableUi.toolbarOpen ? h2("div", {
1004
1088
  ref: tableToolbarShell,
1005
1089
  class: "looma-editor__table-toolbar-shell",
@@ -1029,6 +1113,7 @@ var LoomaEditor = defineComponent2({
1029
1113
  export {
1030
1114
  EDITOR_ADAPTER_COMPONENT_TAG_MAP,
1031
1115
  EditorInsertTableGrid,
1116
+ EditorMentionMenu,
1032
1117
  EditorSlashMenu,
1033
1118
  EditorTableContextMenu,
1034
1119
  EditorTableOverlay,
@@ -1 +0,0 @@
1
- const n=[],t="data-ui-scroll-lock";let e=0,o=!1;function c(){if("undefined"==typeof document)return;const n=document.documentElement;if(e>0)return n.setAttribute(t,"true"),void(n.style.overflow="hidden");n.removeAttribute(t),n.style.removeProperty("overflow")}function u(n){return n.dismissible??!0}function i(n){"Escape"===n.key&&a("escape","keyboard")}function d(n){const t=f();if(!t||!u(t))return;const e=n.target;e instanceof Node&&t.element.contains(e)||a("light-dismiss","pointer")}function r(t){s(t.id),n.push(t),t.modal&&(e+=1,c()),o||"undefined"==typeof document||(document.addEventListener("keydown",i),document.addEventListener("pointerdown",d,{capture:!0}),o=!0)}function s(t){const u=n.findIndex((n=>n.id===t));if(u>=0){const[t]=n.splice(u,1);t?.modal&&(e=Math.max(0,e-1),c())}!o||n.length>0||"undefined"==typeof document||(document.removeEventListener("keydown",i),document.removeEventListener("pointerdown",d,{capture:!0}),o=!1)}function f(){return n.at(-1)}function a(n,t){const e=f();return!!e&&!!(u(e)||"escape"!==n&&"light-dismiss"!==n)&&(e.requestClose(n,t),!0)}export{s as c,r as o,a as r}
@@ -1 +0,0 @@
1
- import{p as e,H as t,h as i,c as r,t as a}from"./p-CIA4RyEp.js";import{d as o,e as s}from"./p-JwSoedEO.js";const n=e(class extends t{constructor(e){super(),!1!==e&&this.__registerHost(),this.__attachShadow()}get host(){return this}open=!1;defaultOpen=!1;internalOpen=!1;syncFromProp(){this.internalOpen=this.open}componentDidLoad(){this.syncFromProp(),this.internalOpen=this.internalOpen||this.defaultOpen,this.host.addEventListener("click",this.onItemClick),this.host.addEventListener("keydown",this.onKeydown)}disconnectedCallback(){this.host.removeEventListener("click",this.onItemClick),this.host.removeEventListener("keydown",this.onKeydown)}getItems(){return Array.from(this.host.querySelectorAll("ui-menu-item"))}isItemDisabled(e){return"true"===e.getAttribute("aria-disabled")||e.hasAttribute("disabled")||"true"===e.getAttribute("disabled")||!0===e.disabled}onItemClick=e=>{const t=e.target.closest?.("ui-menu-item");if(!t||t.getRootNode()!==this.host.getRootNode())return;if(this.isItemDisabled(t))return;const i=t.getAttribute("value")??t.getAttribute("data-value")??"";o(this.host,"select",{value:i,trigger:s(e)}),o(this.host,"close",{open:!1,reason:"action",trigger:s(e)}),this.internalOpen=!1};onKeydown=e=>{const i=this.getItems().filter((e=>!this.isItemDisabled(e)));if(0===i.length)return;const r=e.target.closest?.("ui-menu-item"),a=r&&r instanceof t?i.indexOf(r):-1;if("Enter"!==e.key&&" "!==e.key)"ArrowDown"!==e.key&&"ArrowUp"!==e.key||(e.preventDefault(),i["ArrowDown"===e.key?a<0?0:Math.min(a+1,i.length-1):a<=0?i.length-1:a-1].focus());else if(e.preventDefault(),r&&a>=0){const e=r.getAttribute("value")??r.getAttribute("data-value")??"";o(this.host,"select",{value:e,trigger:"keyboard"}),o(this.host,"close",{open:!1,reason:"action",trigger:"keyboard"}),this.internalOpen=!1}};render(){return i(r,{key:"5e463cbbce272c6b6132a839b818deef3e39a532",role:"menu","aria-orientation":"vertical","data-open":this.internalOpen?"":void 0},i("slot",{key:"feea6a21d41a7b27a6270814bcf0b3f3ded394a1"}))}static get watchers(){return{open:[{syncFromProp:0}]}}static get style(){return":host{--ui-menu-viewport-gap:var(--ui-space-2, 0.5rem);display:flex;flex-direction:column;inline-size:max-content;min-inline-size:min(12rem, calc(100vw - (var(--ui-menu-viewport-gap) * 2)));max-inline-size:calc(100vw - (var(--ui-menu-viewport-gap) * 2));padding:var(--ui-space-1);background:var(--ui-surface-elevated);border:1px solid var(--ui-border-default);border-radius:var(--ui-radius-3);box-shadow:var(--ui-shadow-lg)}::slotted(ui-menu-item){display:block;width:100%;padding:var(--ui-space-2) var(--ui-space-3);text-align:left;background:none;border:none;border-radius:var(--ui-radius-2);color:var(--ui-text-primary);font-size:var(--ui-font-size-md);font-weight:var(--ui-font-medium, 500);cursor:pointer;transition:background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease)}::slotted(ui-menu-item:hover:not([aria-disabled='true']):not([disabled])){background:var(--ui-surface-subtle)}::slotted(ui-menu-item[aria-disabled='true']),::slotted(ui-menu-item[disabled]){opacity:0.6;cursor:not-allowed}"}},[769,"ui-menu",{open:[4],defaultOpen:[4,"default-open"],internalOpen:[32]},void 0,{open:[{syncFromProp:0}]}]);function u(){"undefined"!=typeof customElements&&["ui-menu"].forEach((e=>{"ui-menu"===e&&(customElements.get(a(e))||customElements.define(a(e),n))}))}export{n as U,u as d}
@@ -1 +0,0 @@
1
- import{r as t,g as e,h as i,H as s}from"./p-CEeiinfk.js";import{o as n,c as o,r}from"./p-CR7f2MQC.js";import{d as a}from"./p-JwSoedEO.js";const h=class{constructor(e){t(this,e)}get host(){return e(this)}open=!1;defaultOpen=!1;for;internalOpen=!1;overlayId=`ui-context-menu-${Math.random().toString(36).slice(2,11)}`;trigger=null;contextTarget=null;pointerX=0;pointerY=0;syncFromProp(){this.internalOpen=this.open}syncTarget(){this.resolveTargets(),this.attachTargetListeners()}syncOverlay(){this.syncTriggerState(),this.internalOpen?n({id:this.overlayId,modal:!1,element:this.host,dismissible:!0,requestClose:(t,e)=>this.closeMenu(t,e)}):o(this.overlayId)}componentDidLoad(){this.syncFromProp(),this.internalOpen=this.internalOpen||this.defaultOpen,this.resolveTargets(),this.attachTargetListeners(),this.syncTriggerState(),this.syncOverlay()}componentDidUpdate(){this.resolveTargets(),this.attachTargetListeners(),this.syncTriggerState()}disconnectedCallback(){this.detachTargetListeners(),o(this.overlayId)}resolveTargets(){const t=this.trigger,e=this.contextTarget,i=this.host.querySelector('[slot="trigger"]'),s=this.for?document.getElementById(this.for):null;this.trigger=i,this.contextTarget=s??i??this.host.parentElement,t===this.trigger&&e===this.contextTarget||(t?.removeEventListener("click",this.onTriggerClick),t?.removeEventListener("keydown",this.onTriggerKeydown),e?.removeEventListener("contextmenu",this.onContextMenu))}attachTargetListeners(){this.detachTargetListeners(),this.trigger?.addEventListener("click",this.onTriggerClick),this.trigger?.addEventListener("keydown",this.onTriggerKeydown),this.contextTarget?.addEventListener("contextmenu",this.onContextMenu)}detachTargetListeners(){this.trigger?.removeEventListener("click",this.onTriggerClick),this.trigger?.removeEventListener("keydown",this.onTriggerKeydown),this.contextTarget?.removeEventListener("contextmenu",this.onContextMenu)}syncTriggerState(){this.trigger&&(this.trigger.setAttribute("aria-haspopup","menu"),this.trigger.setAttribute("aria-expanded",this.internalOpen?"true":"false"))}getItems(){return Array.from(this.host.querySelectorAll("ui-menu-item")).filter((t=>!this.isItemDisabled(t)))}focusFirstItem(){requestAnimationFrame((()=>this.getItems()[0]?.focus()))}openMenu(t,e,i){this.pointerX=t,this.pointerY=e,this.internalOpen=!0,a(this.host,"open",{open:!0,reason:"action",trigger:i}),this.focusFirstItem()}openFromTrigger(t){if(!this.trigger)return;const e=this.trigger.getBoundingClientRect();this.openMenu(e.left,e.bottom,t)}closeMenu(t,e,i=!0){this.internalOpen&&(this.internalOpen=!1,a(this.host,"close",{open:!1,reason:t,trigger:e}),i&&this.trigger?.focus())}onTriggerClick=t=>{this.internalOpen?this.closeMenu("action",0===t.detail?"keyboard":"pointer"):this.openFromTrigger(0===t.detail?"keyboard":"pointer")};onTriggerKeydown=t=>{"Enter"!==t.key&&" "!==t.key&&"ArrowDown"!==t.key||(t.preventDefault(),this.internalOpen?this.focusFirstItem():this.openFromTrigger("keyboard"))};onContextMenu=t=>{t.preventDefault(),this.openMenu(t.clientX,t.clientY,"pointer")};isItemDisabled(t){return"true"===t.getAttribute("aria-disabled")||t.hasAttribute("disabled")||"true"===t.getAttribute("disabled")||!0===t.disabled}onKeydown=t=>{if(this.internalOpen){if("Escape"===t.key)return t.preventDefault(),void r("escape","keyboard");if("Enter"===t.key||" "===t.key){const e=t.target.closest?.("ui-menu-item");if(!e||this.isItemDisabled(e))return;t.preventDefault();const i=e.getAttribute("value")??e.getAttribute("data-value")??"";a(this.host,"select",{value:i,trigger:"keyboard"}),this.closeMenu("action","keyboard")}}};onItemClick=t=>{const e=t.target.closest?.("ui-menu-item");if(!e||this.isItemDisabled(e))return;const i=e.getAttribute("value")??e.getAttribute("data-value")??"";a(this.host,"select",{value:i,trigger:"pointer"}),this.closeMenu("action","pointer")};render(){return i(s,{key:"79fbca2c89f1d1fd1f4796ad88d2a599e811a3f9","data-open":this.internalOpen?"":void 0,onKeyDown:this.onKeydown,onClick:this.onItemClick},i("slot",{key:"9308cadfa155930e3e46dfb4a69a847ae388958b",name:"trigger"}),i("div",{key:"16cfba2b32444ac9e3cac1f040f81f17fd5db23c",class:"menu","data-open":this.internalOpen?"":void 0,style:{left:`${this.pointerX}px`,top:`${this.pointerY}px`}},i("ui-menu",{key:"59f18e0df3bb1fe85efa8eeca00b336bbde47c70",open:this.internalOpen},i("slot",{key:"5bdbb7773c9c1ae43ec2e05fca9558482815e28a"}))))}static get watchers(){return{open:[{syncFromProp:0}],for:[{syncTarget:0}],internalOpen:[{syncOverlay:0}]}}};h.style=":host{display:contents}.menu{position:fixed;z-index:var(--ui-z-overlay, 1000);min-width:12rem}.menu[data-open]{display:block}.menu:not([data-open]){display:none !important}";export{h as ui_context_menu}
@@ -1 +0,0 @@
1
- import{r as t,g as a,h as i,H as n}from"./p-CEeiinfk.js";function e(t,a){const i=Math.max(a.left-t.x,0,t.x-a.right),n=Math.max(a.top-t.y,0,t.y-a.bottom);return Math.hypot(i,n)}const o=class{constructor(a){t(this,a)}get host(){return a(this)}nearRadius=16;coordinator=null;componentDidLoad(){this.connectCoordinator()}disconnectedCallback(){this.coordinator?.destroy(),this.coordinator=null}connectCoordinator(){this.coordinator?.destroy(),this.coordinator=function(t,a={}){const i=t.ownerDocument.defaultView??window,n=a.pointerTarget??t,o=a.anchorSelector??"[data-ui-affordance]",r=a.nearRadius??16,s=Number.isFinite(r)?Math.max(0,r):16,c=new AbortController;let d=[],l=null,u=null,h=!1;const p=()=>{for(const{element:t}of d)t.hasAttribute("data-ui-proximity")&&t.removeAttribute("data-ui-proximity");t.hasAttribute("data-ui-interaction")&&t.removeAttribute("data-ui-interaction")},f=()=>{d=Array.from(t.querySelectorAll(o)).filter((t=>!t.hasAttribute("disabled")&&"true"!==t.getAttribute("aria-disabled"))).map((t=>({element:t,rect:t.getBoundingClientRect()}))),h=!1},g=()=>{if(l=null,h&&f(),!u)return void p();let a=!1;for(const t of d){const i=e(u,t.rect)<=s;i&&"near"!==t.element.getAttribute("data-ui-proximity")?t.element.setAttribute("data-ui-proximity","near"):!i&&t.element.hasAttribute("data-ui-proximity")&&t.element.removeAttribute("data-ui-proximity"),a||=i}a&&"engaged"!==t.getAttribute("data-ui-interaction")?t.setAttribute("data-ui-interaction","engaged"):!a&&t.hasAttribute("data-ui-interaction")&&t.removeAttribute("data-ui-interaction")},m=()=>{null===l&&(l=i.requestAnimationFrame(g))},b=()=>{h=!0,m()};return n.addEventListener("pointermove",(t=>{u="touch"===t.pointerType?null:{x:t.clientX,y:t.clientY},m()}),{passive:!0,signal:c.signal}),i.addEventListener("resize",b,{passive:!0,signal:c.signal}),i.addEventListener("scroll",b,{passive:!0,capture:!0,signal:c.signal}),i.visualViewport?.addEventListener("resize",b,{passive:!0,signal:c.signal}),i.visualViewport?.addEventListener("scroll",b,{passive:!0,signal:c.signal}),f(),{refresh:b,destroy(){c.abort(),null!==l&&i.cancelAnimationFrame(l),l=null,u=null,p(),d=[]}}}(this.host,{nearRadius:this.nearRadius})}onSlotChange=()=>{this.coordinator?.refresh()};render(){return i(n,{key:"184b0a908494d480ed23aa14b75d4f7b94e5275b"},i("slot",{key:"570e810db588c1514c6fd85985c9bc4532993a2b",onSlotchange:this.onSlotChange}))}static get watchers(){return{nearRadius:[{connectCoordinator:0}]}}};o.style=":host{display:contents;--ui-affordance-scope-engaged:0}:host([data-ui-interaction='engaged']){--ui-affordance-scope-engaged:1}";export{o as ui_affordance_scope}