@expcat/tigercat-vue 2.0.0-rc.2 → 2.0.4

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 (183) hide show
  1. package/dist/{chunk-KE6RGD4Y.mjs → chunk-26OI3TEA.mjs} +25 -55
  2. package/dist/{chunk-H26JXVJX.mjs → chunk-2T2NEZRZ.mjs} +1 -1
  3. package/dist/chunk-4HUYX5WW.mjs +239 -0
  4. package/dist/{chunk-EGIQPUEL.mjs → chunk-5C32WCQY.mjs} +8 -6
  5. package/dist/{chunk-QFG452MD.mjs → chunk-5RXYJWNA.mjs} +53 -28
  6. package/dist/{chunk-IDUEWMWN.mjs → chunk-7KCOF5US.mjs} +61 -62
  7. package/dist/{chunk-RHV6DWY6.mjs → chunk-7VHXZX7Y.mjs} +20 -28
  8. package/dist/{chunk-36TZA5BH.mjs → chunk-A5QYJSHK.mjs} +0 -3
  9. package/dist/{chunk-IZRQ7LB3.mjs → chunk-AU6IC6K7.mjs} +1 -1
  10. package/dist/{chunk-O6BN5R6J.mjs → chunk-AUMTHL6N.mjs} +1 -1
  11. package/dist/{chunk-MNSVJBNH.mjs → chunk-B4MDHE3L.mjs} +18 -4
  12. package/dist/{chunk-7JT5ZIHC.mjs → chunk-BCU7GYF6.mjs} +16 -8
  13. package/dist/{chunk-7CPMXNLK.mjs → chunk-BNYA5IUB.mjs} +26 -2
  14. package/dist/{chunk-N7LWKAYS.mjs → chunk-BZ6MVFV7.mjs} +190 -174
  15. package/dist/{chunk-TK3QU367.mjs → chunk-DI6RRAGQ.mjs} +3 -3
  16. package/dist/{chunk-4ZZYQITT.mjs → chunk-FWO7RNGI.mjs} +249 -220
  17. package/dist/{chunk-SUORTZUY.mjs → chunk-GS4SV2HK.mjs} +48 -20
  18. package/dist/{chunk-EUSODI5E.mjs → chunk-HKYRRQS7.mjs} +11 -5
  19. package/dist/{chunk-D4APFWWS.mjs → chunk-IPGPLFUZ.mjs} +18 -4
  20. package/dist/{chunk-IMFHJEUX.mjs → chunk-JALHMWKW.mjs} +20 -7
  21. package/dist/{chunk-OHPXOLNB.mjs → chunk-K3WTQBE4.mjs} +40 -15
  22. package/dist/{chunk-VMYV5EWI.mjs → chunk-KICZSLOX.mjs} +9 -8
  23. package/dist/{chunk-BNNTDSLJ.mjs → chunk-KROVW4AW.mjs} +19 -60
  24. package/dist/{chunk-AQMPCLX7.mjs → chunk-NMAJD353.mjs} +248 -253
  25. package/dist/{chunk-4BO6JNA6.mjs → chunk-OAPIT53X.mjs} +4 -4
  26. package/dist/{chunk-SYRRMZT2.mjs → chunk-OQVGB7X6.mjs} +43 -29
  27. package/dist/{chunk-DWK5GUMB.mjs → chunk-OTGGPXDT.mjs} +26 -19
  28. package/dist/{chunk-5KPO3EDM.mjs → chunk-OTHJIFDV.mjs} +28 -15
  29. package/dist/{chunk-DWPZRG7A.mjs → chunk-PGF7HLLR.mjs} +43 -39
  30. package/dist/chunk-Q7Y22OFX.mjs +330 -0
  31. package/dist/{chunk-3NQUEQJT.mjs → chunk-RID7A5V7.mjs} +54 -38
  32. package/dist/{chunk-CFH5T3V2.mjs → chunk-S5RTMAQN.mjs} +2 -2
  33. package/dist/{chunk-SJ7W5I5H.mjs → chunk-TCV6YPH5.mjs} +1 -1
  34. package/dist/{chunk-LFENEILY.mjs → chunk-WC5MKASU.mjs} +110 -99
  35. package/dist/{chunk-JZCETBUV.mjs → chunk-WUQMFKQ6.mjs} +29 -16
  36. package/dist/{chunk-GWFVBG22.mjs → chunk-XGXZF27U.mjs} +28 -15
  37. package/dist/{chunk-JVQPU4M2.mjs → chunk-ZGA66PSG.mjs} +28 -15
  38. package/dist/components/ActivityFeed.d.mts +6 -6
  39. package/dist/components/ActivityFeed.mjs +3 -3
  40. package/dist/components/Alert.d.mts +3 -3
  41. package/dist/components/Anchor.d.mts +1 -1
  42. package/dist/components/AreaChart.d.mts +3 -3
  43. package/dist/components/AreaChart.mjs +1 -1
  44. package/dist/components/AutoComplete.d.mts +5 -5
  45. package/dist/components/AutoComplete.mjs +2 -1
  46. package/dist/components/Avatar.d.mts +1 -1
  47. package/dist/components/AvatarGroup.d.mts +2 -2
  48. package/dist/components/BackTop.d.mts +3 -3
  49. package/dist/components/Badge.d.mts +4 -4
  50. package/dist/components/BarChart.d.mts +2 -2
  51. package/dist/components/BarChart.mjs +1 -1
  52. package/dist/components/Breadcrumb.d.mts +3 -3
  53. package/dist/components/Button.d.mts +3 -3
  54. package/dist/components/ButtonGroup.d.mts +1 -1
  55. package/dist/components/Calendar.d.mts +2 -2
  56. package/dist/components/Card.d.mts +2 -2
  57. package/dist/components/Carousel.d.mts +2 -2
  58. package/dist/components/Cascader.d.mts +3 -3
  59. package/dist/components/Cascader.mjs +2 -1
  60. package/dist/components/ChartCanvas.d.mts +1 -1
  61. package/dist/components/ChartGrid.d.mts +1 -1
  62. package/dist/components/ChartLegend.d.mts +1 -1
  63. package/dist/components/ChatWindow.d.mts +4 -4
  64. package/dist/components/CodeEditor.d.mts +3 -3
  65. package/dist/components/Collapse.d.mts +1 -1
  66. package/dist/components/CollapsePanel.d.mts +1 -1
  67. package/dist/components/ColorPicker.mjs +2 -1
  68. package/dist/components/ColorSwatch.d.mts +2 -2
  69. package/dist/components/CommentThread.d.mts +2 -2
  70. package/dist/components/CommentThread.mjs +1 -1
  71. package/dist/components/ConfigProvider.d.mts +1 -1
  72. package/dist/components/Container.d.mts +1 -1
  73. package/dist/components/Countdown.d.mts +2 -2
  74. package/dist/components/CronEditor.d.mts +2 -2
  75. package/dist/components/CropUpload.d.mts +1 -1
  76. package/dist/components/CropUpload.mjs +4 -4
  77. package/dist/components/DataExport.d.mts +2 -2
  78. package/dist/components/DataExport.mjs +3 -3
  79. package/dist/components/DataTableWithToolbar.d.mts +11 -11
  80. package/dist/components/DataTableWithToolbar.mjs +6 -6
  81. package/dist/components/DatePicker.d.mts +3 -3
  82. package/dist/components/DatePicker.mjs +2 -1
  83. package/dist/components/Descriptions.d.mts +2 -2
  84. package/dist/components/DonutChart.d.mts +4 -4
  85. package/dist/components/Drawer.d.mts +6 -6
  86. package/dist/components/Drawer.mjs +2 -2
  87. package/dist/components/Dropdown.d.mts +2 -2
  88. package/dist/components/Dropdown.mjs +2 -2
  89. package/dist/components/Empty.d.mts +1 -1
  90. package/dist/components/FileManager.d.mts +2 -2
  91. package/dist/components/FloatButton.d.mts +5 -5
  92. package/dist/components/Form.d.mts +2 -2
  93. package/dist/components/FormItem.mjs +2 -1
  94. package/dist/components/FormWizard.d.mts +5 -5
  95. package/dist/components/FunnelChart.d.mts +3 -3
  96. package/dist/components/Gantt.d.mts +2 -2
  97. package/dist/components/GaugeChart.d.mts +2 -2
  98. package/dist/components/HeatmapChart.d.mts +3 -3
  99. package/dist/components/Icon.d.mts +2 -2
  100. package/dist/components/Image.d.mts +2 -2
  101. package/dist/components/Image.mjs +3 -3
  102. package/dist/components/ImageAnnotation.d.mts +5 -5
  103. package/dist/components/ImageCropper.d.mts +1 -1
  104. package/dist/components/ImageCropper.mjs +1 -1
  105. package/dist/components/ImageViewer.d.mts +1 -1
  106. package/dist/components/InfiniteScroll.d.mts +3 -3
  107. package/dist/components/InfiniteScroll.mjs +1 -1
  108. package/dist/components/Input.d.mts +4 -4
  109. package/dist/components/InputGroup.d.mts +1 -1
  110. package/dist/components/InputNumber.d.mts +1 -1
  111. package/dist/components/Kanban.d.mts +1 -1
  112. package/dist/components/LineChart.d.mts +2 -2
  113. package/dist/components/LineChart.mjs +1 -1
  114. package/dist/components/Link.d.mts +1 -1
  115. package/dist/components/List.d.mts +7 -7
  116. package/dist/components/Loading.d.mts +6 -6
  117. package/dist/components/Loading.mjs +2 -2
  118. package/dist/components/MarkdownEditor.d.mts +5 -5
  119. package/dist/components/Mentions.d.mts +3 -3
  120. package/dist/components/Mentions.mjs +2 -1
  121. package/dist/components/Menu.d.mts +4 -4
  122. package/dist/components/Menu.mjs +2 -2
  123. package/dist/components/Modal.d.mts +8 -8
  124. package/dist/components/Modal.mjs +2 -2
  125. package/dist/components/NotificationCenter.d.mts +5 -5
  126. package/dist/components/NotificationCenter.mjs +3 -3
  127. package/dist/components/NumberKeyboard.d.mts +5 -5
  128. package/dist/components/OrgChart.d.mts +3 -3
  129. package/dist/components/Pagination.d.mts +5 -5
  130. package/dist/components/PieChart.d.mts +4 -4
  131. package/dist/components/Popconfirm.d.mts +4 -4
  132. package/dist/components/Popconfirm.mjs +3 -3
  133. package/dist/components/Popover.d.mts +3 -3
  134. package/dist/components/Popover.mjs +3 -3
  135. package/dist/components/Progress.d.mts +3 -3
  136. package/dist/components/QRCode.d.mts +3 -3
  137. package/dist/components/RadarChart.d.mts +3 -3
  138. package/dist/components/Rate.d.mts +2 -2
  139. package/dist/components/Result.d.mts +1 -1
  140. package/dist/components/RichTextEditor.d.mts +4 -4
  141. package/dist/components/Row.d.mts +1 -1
  142. package/dist/components/ScatterChart.d.mts +2 -2
  143. package/dist/components/ScatterChart.mjs +1 -1
  144. package/dist/components/ScrollSpy.d.mts +3 -3
  145. package/dist/components/Select.d.mts +3 -3
  146. package/dist/components/Select.mjs +2 -1
  147. package/dist/components/Signature.d.mts +5 -5
  148. package/dist/components/Skeleton.d.mts +1 -1
  149. package/dist/components/Space.d.mts +2 -2
  150. package/dist/components/Splitter.d.mts +1 -1
  151. package/dist/components/Spotlight.d.mts +5 -5
  152. package/dist/components/Spotlight.mjs +2 -2
  153. package/dist/components/Steps.d.mts +3 -3
  154. package/dist/components/SunburstChart.d.mts +2 -2
  155. package/dist/components/Table.d.mts +5 -5
  156. package/dist/components/Table.mjs +3 -2
  157. package/dist/components/Tabs.d.mts +4 -4
  158. package/dist/components/Tag.d.mts +2 -2
  159. package/dist/components/TaskBoard.d.mts +2 -2
  160. package/dist/components/Text.d.mts +3 -3
  161. package/dist/components/Textarea.d.mts +3 -3
  162. package/dist/components/TimePicker.d.mts +4 -4
  163. package/dist/components/TimePicker.mjs +2 -1
  164. package/dist/components/Timeline.d.mts +4 -4
  165. package/dist/components/Tooltip.d.mts +3 -3
  166. package/dist/components/Tooltip.mjs +3 -3
  167. package/dist/components/Tour.d.mts +2 -2
  168. package/dist/components/Tour.mjs +2 -2
  169. package/dist/components/Transfer.d.mts +3 -3
  170. package/dist/components/Tree.d.mts +4 -4
  171. package/dist/components/TreeMapChart.d.mts +2 -2
  172. package/dist/components/TreeSelect.d.mts +3 -3
  173. package/dist/components/TreeSelect.mjs +2 -1
  174. package/dist/components/Upload.d.mts +4 -4
  175. package/dist/components/Upload.mjs +1 -1
  176. package/dist/components/VirtualTable.d.mts +3 -3
  177. package/dist/components/VirtualTable.mjs +1 -1
  178. package/dist/components/Watermark.d.mts +1 -1
  179. package/dist/index.d.mts +1 -1
  180. package/dist/index.mjs +4 -2
  181. package/package.json +2 -2
  182. package/dist/chunk-BDTPFPSB.mjs +0 -163
  183. package/dist/chunk-EWUHEW6W.mjs +0 -219
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  useFloatingPopup
3
- } from "./chunk-KE6RGD4Y.mjs";
3
+ } from "./chunk-26OI3TEA.mjs";
4
4
  import {
5
- renderVueBodyTeleport
6
- } from "./chunk-BDTPFPSB.mjs";
5
+ renderVueOverlayTeleport
6
+ } from "./chunk-Q7Y22OFX.mjs";
7
7
 
8
8
  // src/components/Popover.ts
9
9
  import { defineComponent, computed, h } from "vue";
@@ -53,6 +53,9 @@ var Popover = defineComponent({
53
53
  triggerRef,
54
54
  floatingRef,
55
55
  floatingStyles,
56
+ floatingClasses,
57
+ positioned,
58
+ overlayTarget,
56
59
  triggerHandlers
57
60
  } = useFloatingPopup({ props, emit });
58
61
  const popoverId = createPopoverId();
@@ -100,32 +103,43 @@ var Popover = defineComponent({
100
103
  triggerSlotContent
101
104
  ),
102
105
  // Floating content
103
- currentVisible.value ? renderVueBodyTeleport(
104
- h("div", { ref: floatingRef, style: floatingStyles.value, "aria-hidden": false }, [
105
- h(
106
- "div",
107
- {
108
- id: popoverId,
109
- role: "dialog",
110
- "aria-modal": "false",
111
- "aria-labelledby": hasTitle ? titleId : void 0,
112
- "aria-describedby": hasContent ? contentId : void 0,
113
- class: contentClasses.value
114
- },
115
- [
116
- hasTitle && h(
117
- "div",
118
- { id: titleId, class: POPOVER_TITLE_CLASSES },
119
- slots.title ? slots.title() : props.title
120
- ),
121
- hasContent && h(
122
- "div",
123
- { id: contentId, class: POPOVER_TEXT_CLASSES },
124
- slots.content ? slots.content() : props.content
125
- )
126
- ].filter(Boolean)
127
- )
128
- ])
106
+ currentVisible.value ? renderVueOverlayTeleport(
107
+ h(
108
+ "div",
109
+ {
110
+ ref: floatingRef,
111
+ class: floatingClasses.value,
112
+ style: floatingStyles.value,
113
+ "data-positioned": positioned.value,
114
+ "aria-hidden": false
115
+ },
116
+ [
117
+ h(
118
+ "div",
119
+ {
120
+ id: popoverId,
121
+ role: "dialog",
122
+ "aria-modal": "false",
123
+ "aria-labelledby": hasTitle ? titleId : void 0,
124
+ "aria-describedby": hasContent ? contentId : void 0,
125
+ class: contentClasses.value
126
+ },
127
+ [
128
+ hasTitle && h(
129
+ "div",
130
+ { id: titleId, class: POPOVER_TITLE_CLASSES },
131
+ slots.title ? slots.title() : props.title
132
+ ),
133
+ hasContent && h(
134
+ "div",
135
+ { id: contentId, class: POPOVER_TEXT_CLASSES },
136
+ slots.content ? slots.content() : props.content
137
+ )
138
+ ].filter(Boolean)
139
+ )
140
+ ]
141
+ ),
142
+ overlayTarget.value
129
143
  ) : null
130
144
  ]
131
145
  );
@@ -1,9 +1,13 @@
1
+ import {
2
+ renderVueOverlayTeleport,
3
+ useVueAnchoredOverlay
4
+ } from "./chunk-Q7Y22OFX.mjs";
1
5
  import {
2
6
  useTigerConfig
3
7
  } from "./chunk-UOJOJBEU.mjs";
4
8
 
5
9
  // src/components/Cascader.ts
6
- import { defineComponent, computed, ref, h, watch, onBeforeUnmount } from "vue";
10
+ import { defineComponent, computed, ref, h, watch } from "vue";
7
11
  import {
8
12
  classNames,
9
13
  cascaderBaseClasses,
@@ -122,6 +126,19 @@ var Cascader = defineComponent({
122
126
  const triggerRef = ref(null);
123
127
  const dropdownRef = ref(null);
124
128
  const searchInputRef = ref(null);
129
+ const overlay = useVueAnchoredOverlay({
130
+ enabled: isOpen,
131
+ referenceRef: triggerRef,
132
+ floatingRef: dropdownRef,
133
+ placement: "bottom-start",
134
+ offset: 4,
135
+ layout: "fullscreen-sm",
136
+ matchReferenceWidth: true,
137
+ dismissOnOutside: true,
138
+ dismissOnEscape: true,
139
+ restoreFocusOnDismiss: true,
140
+ onDismiss: closeDropdown
141
+ });
125
142
  const displayLabel = computed(() => {
126
143
  if (!props.modelValue || props.modelValue.length === 0) return "";
127
144
  return getCascaderDisplayLabel(props.options, props.modelValue, props.separator);
@@ -213,22 +230,6 @@ var Cascader = defineComponent({
213
230
  closeDropdown();
214
231
  }
215
232
  }
216
- function handleDocumentClick(e) {
217
- const target = e.target;
218
- if (triggerRef.value && !triggerRef.value.contains(target) && dropdownRef.value && !dropdownRef.value.contains(target)) {
219
- closeDropdown();
220
- }
221
- }
222
- watch(isOpen, (open) => {
223
- if (open) {
224
- document.addEventListener("click", handleDocumentClick, true);
225
- } else {
226
- document.removeEventListener("click", handleDocumentClick, true);
227
- }
228
- });
229
- onBeforeUnmount(() => {
230
- document.removeEventListener("click", handleDocumentClick, true);
231
- });
232
233
  return () => {
233
234
  const hasValue = props.modelValue && props.modelValue.length > 0;
234
235
  const showClear = props.clearable && hasValue && !props.disabled;
@@ -402,7 +403,13 @@ var Cascader = defineComponent({
402
403
  "div",
403
404
  {
404
405
  ref: dropdownRef,
405
- class: classNames(cascaderDropdownClasses, isSearchMode.value && "flex-col")
406
+ class: classNames(
407
+ cascaderDropdownClasses,
408
+ isSearchMode.value && "flex-col",
409
+ overlay.floatingClasses.value
410
+ ),
411
+ style: overlay.floatingStyles.value,
412
+ "data-positioned": overlay.positioned.value
406
413
  },
407
414
  children
408
415
  );
@@ -413,7 +420,7 @@ var Cascader = defineComponent({
413
420
  class: cascaderBaseClasses,
414
421
  "data-testid": "cascader"
415
422
  },
416
- [trigger, dropdownContent]
423
+ [trigger, renderVueOverlayTeleport(dropdownContent, overlay.target.value)]
417
424
  );
418
425
  };
419
426
  }
@@ -459,22 +459,35 @@ var BarChart = defineComponent({
459
459
  y: tooltipPosition.value.y
460
460
  }) : null;
461
461
  if (!props.showLegend) {
462
- return h("div", { class: "inline-block relative" }, [chart, tooltip]);
462
+ return h(
463
+ "div",
464
+ {
465
+ class: classNames(
466
+ "relative",
467
+ props.responsive ? "block w-full min-w-0" : "inline-block"
468
+ )
469
+ },
470
+ [chart, tooltip]
471
+ );
463
472
  }
464
- return h("div", { class: wrapperClasses.value }, [
465
- chart,
466
- h(ChartLegend, {
467
- items: legendItems.value,
468
- position: props.legendPosition,
469
- markerSize: props.legendMarkerSize,
470
- gap: props.legendGap,
471
- interactive: props.hoverable || props.selectable,
472
- onItemClick: handleLegendClick,
473
- onItemHover: handleLegendHover,
474
- onItemLeave: handleLegendLeave
475
- }),
476
- tooltip
477
- ]);
473
+ return h(
474
+ "div",
475
+ { class: classNames(wrapperClasses.value, props.responsive && "w-full min-w-0") },
476
+ [
477
+ chart,
478
+ h(ChartLegend, {
479
+ items: legendItems.value,
480
+ position: props.legendPosition,
481
+ markerSize: props.legendMarkerSize,
482
+ gap: props.legendGap,
483
+ interactive: props.hoverable || props.selectable,
484
+ onItemClick: handleLegendClick,
485
+ onItemHover: handleLegendHover,
486
+ onItemLeave: handleLegendLeave
487
+ }),
488
+ tooltip
489
+ ]
490
+ );
478
491
  };
479
492
  }
480
493
  });
@@ -1,12 +1,16 @@
1
+ import {
2
+ renderVueOverlayTeleport,
3
+ useVueAnchoredOverlay
4
+ } from "./chunk-Q7Y22OFX.mjs";
5
+
1
6
  // src/components/Mentions.ts
2
- import { defineComponent, h, ref, computed, watch, nextTick, onBeforeUnmount } from "vue";
7
+ import { defineComponent, h, ref, computed } from "vue";
3
8
  import { classNames, coerceClassValue } from "@expcat/tigercat-core";
4
9
  import {
5
10
  getMentionsInputClasses,
6
11
  mentionsDropdownClasses,
7
12
  getMentionsOptionClasses,
8
13
  extractMentionQuery,
9
- positionMentionsDropdown,
10
14
  getCyclicIndex
11
15
  } from "@expcat/tigercat-core";
12
16
  var Mentions = defineComponent({
@@ -34,6 +38,19 @@ var Mentions = defineComponent({
34
38
  const q = query.value.toLowerCase();
35
39
  return (props.options || []).filter((o) => !o.disabled && o.label.toLowerCase().includes(q));
36
40
  });
41
+ const overlayEnabled = computed(() => isOpen.value && filteredOptions.value.length > 0);
42
+ const overlay = useVueAnchoredOverlay({
43
+ enabled: overlayEnabled,
44
+ referenceRef: textareaRef,
45
+ floatingRef: dropdownRef,
46
+ containerRef,
47
+ placement: "bottom-start",
48
+ offset: 4,
49
+ dismissOnOutside: true,
50
+ dismissOnEscape: true,
51
+ restoreFocusOnDismiss: true,
52
+ onDismiss: () => isOpen.value = false
53
+ });
37
54
  function handleInput(e) {
38
55
  const target = e.target;
39
56
  const value = target.value;
@@ -77,28 +94,6 @@ var Mentions = defineComponent({
77
94
  isOpen.value = false;
78
95
  }
79
96
  }
80
- function onClickOutside(e) {
81
- if (containerRef.value && !containerRef.value.contains(e.target)) {
82
- isOpen.value = false;
83
- }
84
- }
85
- watch(isOpen, (val) => {
86
- if (val) document.addEventListener("mousedown", onClickOutside);
87
- else document.removeEventListener("mousedown", onClickOutside);
88
- });
89
- watch(
90
- [isOpen, filteredOptions],
91
- async () => {
92
- if (!isOpen.value || filteredOptions.value.length === 0) return;
93
- await nextTick();
94
- if (!textareaRef.value || !dropdownRef.value) return;
95
- await positionMentionsDropdown(textareaRef.value, dropdownRef.value);
96
- },
97
- { flush: "post" }
98
- );
99
- onBeforeUnmount(() => {
100
- document.removeEventListener("mousedown", onClickOutside);
101
- });
102
97
  return () => {
103
98
  const wrapperClass = classNames("relative", coerceClassValue(attrs.class));
104
99
  return h("div", { ref: containerRef, class: wrapperClass }, [
@@ -112,22 +107,31 @@ var Mentions = defineComponent({
112
107
  onInput: handleInput,
113
108
  onKeydown: handleKeydown
114
109
  }),
115
- isOpen.value && filteredOptions.value.length > 0 ? h(
116
- "div",
117
- { ref: dropdownRef, class: mentionsDropdownClasses, role: "listbox" },
118
- filteredOptions.value.map(
119
- (opt, i) => h(
120
- "div",
121
- {
122
- key: opt.value,
123
- class: getMentionsOptionClasses(i === activeIndex.value, !!opt.disabled),
124
- role: "option",
125
- "aria-selected": i === activeIndex.value,
126
- onClick: () => selectOption(opt)
127
- },
128
- opt.label
110
+ isOpen.value && filteredOptions.value.length > 0 ? renderVueOverlayTeleport(
111
+ h(
112
+ "div",
113
+ {
114
+ ref: dropdownRef,
115
+ class: classNames(mentionsDropdownClasses, overlay.floatingClasses.value),
116
+ style: overlay.floatingStyles.value,
117
+ "data-positioned": overlay.positioned.value,
118
+ role: "listbox"
119
+ },
120
+ filteredOptions.value.map(
121
+ (opt, i) => h(
122
+ "div",
123
+ {
124
+ key: opt.value,
125
+ class: getMentionsOptionClasses(i === activeIndex.value, !!opt.disabled),
126
+ role: "option",
127
+ "aria-selected": i === activeIndex.value,
128
+ onClick: () => selectOption(opt)
129
+ },
130
+ opt.label
131
+ )
129
132
  )
130
- )
133
+ ),
134
+ overlay.target.value
131
135
  ) : null
132
136
  ]);
133
137
  };
@@ -0,0 +1,330 @@
1
+ // src/utils/overlay.ts
2
+ import {
3
+ getFocusTrapNavigation,
4
+ getFocusableElements,
5
+ isEventOutside,
6
+ lockBodyScroll,
7
+ computeFloatingPosition,
8
+ autoUpdateFloating,
9
+ resolveAnchoredOverlayTarget,
10
+ getAnchoredOverlayTabTarget,
11
+ getAnchoredOverlayLayoutClasses,
12
+ FLOATING_OVERLAY_Z_INDEX,
13
+ getTransformOrigin,
14
+ restoreFocus,
15
+ registerEscapeDismiss
16
+ } from "@expcat/tigercat-core";
17
+ import { h, ref, computed, Teleport, watch, onBeforeUnmount } from "vue";
18
+ var OVERLAY_LAYER_SELECTOR = "[data-tiger-overlay-layer]";
19
+ function resolveOverlayLayer(element) {
20
+ return element?.closest(OVERLAY_LAYER_SELECTOR) ?? null;
21
+ }
22
+ function useVueClickOutside({
23
+ enabled,
24
+ containerRef,
25
+ refs,
26
+ onOutsideClick,
27
+ defer = false
28
+ }) {
29
+ let timer;
30
+ const handler = (event) => {
31
+ if (!enabled.value) return;
32
+ const elements = refs?.length ? refs.map((ref2) => ref2?.value) : [containerRef?.value];
33
+ if (!elements.some(Boolean)) return;
34
+ if (isEventOutside(event, elements)) {
35
+ onOutsideClick();
36
+ }
37
+ };
38
+ const attach = () => document.addEventListener("click", handler);
39
+ const detach = () => document.removeEventListener("click", handler);
40
+ if (!defer) {
41
+ attach();
42
+ return () => detach();
43
+ }
44
+ timer = window.setTimeout(() => attach(), 0);
45
+ return () => {
46
+ if (timer !== void 0) window.clearTimeout(timer);
47
+ detach();
48
+ };
49
+ }
50
+ function useVueEscapeKey({
51
+ enabled,
52
+ onEscape,
53
+ layerRef
54
+ }) {
55
+ let removeEntry;
56
+ const stop = watch(
57
+ enabled,
58
+ (isEnabled) => {
59
+ removeEntry?.();
60
+ removeEntry = isEnabled ? registerEscapeDismiss(document, onEscape, () => layerRef?.value ?? null) : void 0;
61
+ },
62
+ { immediate: true, flush: "sync" }
63
+ );
64
+ return () => {
65
+ stop();
66
+ removeEntry?.();
67
+ };
68
+ }
69
+ function useVueBodyScrollLock(enabled) {
70
+ watch(
71
+ enabled,
72
+ (isEnabled, _prevEnabled, onCleanup) => {
73
+ if (!isEnabled) return;
74
+ const unlock = lockBodyScroll();
75
+ onCleanup(() => unlock());
76
+ },
77
+ { immediate: true }
78
+ );
79
+ }
80
+ function renderVueBodyTeleport(children, disabled = false) {
81
+ const normalizedChildren = children == null ? [] : Array.isArray(children) ? children : [children];
82
+ return h(Teleport, { to: "body", disabled }, normalizedChildren);
83
+ }
84
+ function renderVueOverlayTeleport(children, target, disabled = false) {
85
+ if (children == null || typeof children === "boolean") return children;
86
+ const layeredChildren = h("div", { class: "contents", "data-tiger-overlay-layer": "" }, [
87
+ children,
88
+ h("div", { class: "contents", "data-tiger-overlay-host": "" })
89
+ ]);
90
+ if (disabled || !target) return layeredChildren;
91
+ return h(Teleport, { to: target }, [layeredChildren]);
92
+ }
93
+ function useVueFocusTrap({ enabled, containerRef }) {
94
+ watch(
95
+ [enabled, containerRef],
96
+ ([isEnabled, container], _previous, onCleanup) => {
97
+ if (!isEnabled || !container) return;
98
+ const ownerDocument = container.ownerDocument;
99
+ const handler = (event) => {
100
+ if (!(event.target instanceof Node) || !container.contains(event.target)) return;
101
+ const focusables = getFocusableElements(container);
102
+ const activeElement = ownerDocument.activeElement;
103
+ const navigation = getFocusTrapNavigation(event, focusables, activeElement);
104
+ if (!navigation.shouldHandle || !navigation.next) return;
105
+ event.preventDefault();
106
+ navigation.next.focus();
107
+ };
108
+ ownerDocument.addEventListener("keydown", handler, true);
109
+ onCleanup(() => ownerDocument.removeEventListener("keydown", handler, true));
110
+ },
111
+ { immediate: true, flush: "post" }
112
+ );
113
+ }
114
+ function useVueFloating(options) {
115
+ const {
116
+ referenceRef,
117
+ floatingRef,
118
+ enabled,
119
+ placement: initialPlacement = "bottom",
120
+ offset: offsetDistance = 8,
121
+ arrowRef,
122
+ onPlacementChange
123
+ } = options;
124
+ const x = ref(0);
125
+ const y = ref(0);
126
+ const placement = ref(initialPlacement);
127
+ const arrowX = ref(void 0);
128
+ const arrowY = ref(void 0);
129
+ const isPositioned = ref(false);
130
+ const referenceWidth = ref(0);
131
+ let cleanup = null;
132
+ let updateRequest = 0;
133
+ const update = async () => {
134
+ const request = ++updateRequest;
135
+ const reference = referenceRef.value;
136
+ const floating = floatingRef.value;
137
+ if (!enabled.value || !reference || !floating) return;
138
+ const floatingOptions = {
139
+ placement: initialPlacement,
140
+ offset: offsetDistance,
141
+ flip: true,
142
+ shift: true,
143
+ arrowElement: arrowRef?.value
144
+ };
145
+ const result = await computeFloatingPosition(
146
+ reference,
147
+ floating,
148
+ floatingOptions
149
+ );
150
+ if (request !== updateRequest || !enabled.value || referenceRef.value !== reference || floatingRef.value !== floating) {
151
+ return;
152
+ }
153
+ referenceWidth.value = reference.getBoundingClientRect().width;
154
+ x.value = result.x;
155
+ y.value = result.y;
156
+ if (result.placement !== placement.value) {
157
+ placement.value = result.placement;
158
+ onPlacementChange?.(result.placement);
159
+ }
160
+ if (result.arrow) {
161
+ arrowX.value = result.arrow.x;
162
+ arrowY.value = result.arrow.y;
163
+ }
164
+ isPositioned.value = true;
165
+ };
166
+ watch(
167
+ [enabled, referenceRef, floatingRef],
168
+ ([isEnabled, reference, floating]) => {
169
+ updateRequest += 1;
170
+ if (cleanup) {
171
+ cleanup();
172
+ cleanup = null;
173
+ }
174
+ if (!isEnabled || !reference || !floating) {
175
+ isPositioned.value = false;
176
+ return;
177
+ }
178
+ update();
179
+ cleanup = autoUpdateFloating(reference, floating, update);
180
+ },
181
+ { immediate: true }
182
+ );
183
+ onBeforeUnmount(() => {
184
+ updateRequest += 1;
185
+ if (cleanup) {
186
+ cleanup();
187
+ cleanup = null;
188
+ }
189
+ });
190
+ return {
191
+ x,
192
+ y,
193
+ placement,
194
+ arrowX,
195
+ arrowY,
196
+ update,
197
+ isPositioned,
198
+ referenceWidth
199
+ };
200
+ }
201
+ function useVueAnchoredOverlay(options) {
202
+ const target = ref(null);
203
+ const floatingLayerRef = computed(
204
+ () => resolveOverlayLayer(options.floatingRef.value) ?? options.floatingRef.value
205
+ );
206
+ const portalEnabled = () => typeof options.portal === "object" ? options.portal.value : options.portal ?? true;
207
+ const optionEnabled = (value) => typeof value === "object" ? value.value : Boolean(value);
208
+ const targetSources = [
209
+ options.enabled,
210
+ options.referenceRef,
211
+ ...typeof options.portal === "object" ? [options.portal] : []
212
+ ];
213
+ watch(
214
+ targetSources,
215
+ () => {
216
+ if (!portalEnabled()) {
217
+ target.value = null;
218
+ return;
219
+ }
220
+ target.value = resolveAnchoredOverlayTarget(options.referenceRef.value);
221
+ },
222
+ { immediate: true, flush: "post" }
223
+ );
224
+ watch(
225
+ [options.enabled, options.floatingRef],
226
+ ([enabled, floating2], _previous, onCleanup) => {
227
+ if (!enabled || !floating2) return;
228
+ const handleTab = (event) => {
229
+ if (event.key !== "Tab") return;
230
+ const target2 = getAnchoredOverlayTabTarget(
231
+ options.referenceRef.value,
232
+ options.floatingRef.value,
233
+ event.shiftKey
234
+ );
235
+ if (!target2) return;
236
+ event.preventDefault();
237
+ window.setTimeout(() => restoreFocus(target2, { preventScroll: true }), 0);
238
+ };
239
+ floating2.addEventListener("keydown", handleTab, true);
240
+ onCleanup(() => floating2.removeEventListener("keydown", handleTab, true));
241
+ },
242
+ { immediate: true, flush: "post" }
243
+ );
244
+ const floating = useVueFloating({
245
+ referenceRef: options.referenceRef,
246
+ floatingRef: options.floatingRef,
247
+ enabled: options.enabled,
248
+ placement: options.placement ?? "bottom-start",
249
+ offset: options.offset ?? 4
250
+ });
251
+ const dismiss = (reason) => {
252
+ options.onDismiss?.(reason);
253
+ if (options.restoreFocusOnDismiss && reason === "escape") {
254
+ window.setTimeout(() => restoreFocus(options.referenceRef.value, { preventScroll: true }), 0);
255
+ }
256
+ };
257
+ let outsideCleanup;
258
+ let escapeCleanup;
259
+ const dismissSources = [
260
+ options.enabled,
261
+ ...typeof options.dismissOnOutside === "object" ? [options.dismissOnOutside] : [],
262
+ ...typeof options.dismissOnEscape === "object" ? [options.dismissOnEscape] : []
263
+ ];
264
+ watch(
265
+ dismissSources,
266
+ ([enabled]) => {
267
+ outsideCleanup?.();
268
+ escapeCleanup?.();
269
+ outsideCleanup = void 0;
270
+ escapeCleanup = void 0;
271
+ if (!enabled) return;
272
+ if (optionEnabled(options.dismissOnOutside)) {
273
+ outsideCleanup = useVueClickOutside({
274
+ enabled: options.enabled,
275
+ refs: [
276
+ options.containerRef,
277
+ options.referenceRef,
278
+ floatingLayerRef,
279
+ ...options.outsideRefs ?? []
280
+ ],
281
+ onOutsideClick: () => dismiss("outside"),
282
+ defer: false
283
+ });
284
+ }
285
+ if (optionEnabled(options.dismissOnEscape)) {
286
+ escapeCleanup = useVueEscapeKey({
287
+ enabled: options.enabled,
288
+ onEscape: () => dismiss("escape"),
289
+ layerRef: floatingLayerRef
290
+ });
291
+ }
292
+ },
293
+ { immediate: true }
294
+ );
295
+ onBeforeUnmount(() => {
296
+ outsideCleanup?.();
297
+ escapeCleanup?.();
298
+ });
299
+ const floatingStyles = computed(() => ({
300
+ "--tiger-overlay-x": `${floating.x.value}px`,
301
+ "--tiger-overlay-y": `${floating.y.value}px`,
302
+ "--tiger-overlay-reference-width": `${floating.referenceWidth.value}px`,
303
+ zIndex: FLOATING_OVERLAY_Z_INDEX,
304
+ transformOrigin: getTransformOrigin(floating.placement.value)
305
+ }));
306
+ const floatingClasses = computed(
307
+ () => getAnchoredOverlayLayoutClasses(
308
+ options.layout ?? "anchored",
309
+ options.matchReferenceWidth ?? false
310
+ )
311
+ );
312
+ return {
313
+ target,
314
+ floatingStyles,
315
+ floatingClasses,
316
+ positioned: floating.isPositioned,
317
+ placement: floating.placement,
318
+ x: floating.x,
319
+ y: floating.y
320
+ };
321
+ }
322
+
323
+ export {
324
+ useVueEscapeKey,
325
+ useVueBodyScrollLock,
326
+ renderVueBodyTeleport,
327
+ renderVueOverlayTeleport,
328
+ useVueFocusTrap,
329
+ useVueAnchoredOverlay
330
+ };