@expcat/tigercat-react 2.0.0 → 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 (62) hide show
  1. package/dist/{chunk-JTFNGXOC.mjs → chunk-2ENQZECC.mjs} +53 -31
  2. package/dist/{chunk-O5RAMCBV.mjs → chunk-2JYJPNW3.mjs} +1 -1
  3. package/dist/{chunk-NBQ3Q6DD.mjs → chunk-2WGEHH5A.mjs} +1 -1
  4. package/dist/{chunk-K7MYQISG.mjs → chunk-54HN5BXW.mjs} +10 -4
  5. package/dist/{chunk-C6QK5MJT.mjs → chunk-5CKMYMTS.mjs} +1 -1
  6. package/dist/{chunk-Y7K27DVV.mjs → chunk-6H5Y7Y6E.mjs} +42 -28
  7. package/dist/chunk-6MGQAJ62.mjs +203 -0
  8. package/dist/{chunk-TO2URY7X.mjs → chunk-7AFRHC7P.mjs} +90 -61
  9. package/dist/{chunk-MGQWVJHX.mjs → chunk-ALSOPYM5.mjs} +69 -62
  10. package/dist/{chunk-YCKY72BW.mjs → chunk-BOGOQ44C.mjs} +1 -1
  11. package/dist/{chunk-Q327ESD2.mjs → chunk-BUXHI6UK.mjs} +17 -38
  12. package/dist/{chunk-TORX7SG4.mjs → chunk-CC7IOSNI.mjs} +10 -4
  13. package/dist/{chunk-OVE2ZUJJ.mjs → chunk-D33BIMGK.mjs} +1 -1
  14. package/dist/{chunk-PYDWF4ED.mjs → chunk-D3KP72UC.mjs} +34 -9
  15. package/dist/{chunk-ZEP7I6WB.mjs → chunk-DPWRXXXW.mjs} +16 -8
  16. package/dist/chunk-HKAZXG74.mjs +308 -0
  17. package/dist/{chunk-QWUDJC6K.mjs → chunk-HOYBHB7B.mjs} +38 -17
  18. package/dist/{chunk-3RY6M4AK.mjs → chunk-HS6KUPTI.mjs} +1 -1
  19. package/dist/{chunk-EKESN747.mjs → chunk-HSBN5MLS.mjs} +1 -1
  20. package/dist/{chunk-AJJJ6HWC.mjs → chunk-K4GIKSZE.mjs} +1 -1
  21. package/dist/{chunk-2UOGBS3C.mjs → chunk-KP6DEYWB.mjs} +27 -6
  22. package/dist/{chunk-PAN256RW.mjs → chunk-KVCI2346.mjs} +59 -55
  23. package/dist/{chunk-5RVLBNLI.mjs → chunk-RJPNBYK5.mjs} +4 -4
  24. package/dist/{chunk-HELLYIX2.mjs → chunk-V6P7ZK6O.mjs} +3 -3
  25. package/dist/{chunk-4XGO3OSE.mjs → chunk-XE4YFBOZ.mjs} +12 -17
  26. package/dist/{chunk-YI7NQWUV.mjs → chunk-YI6YWH66.mjs} +14 -30
  27. package/dist/{chunk-SHCBCM2W.mjs → chunk-YIB6ZXZF.mjs} +142 -105
  28. package/dist/{chunk-SZBYEGKU.mjs → chunk-ZCGIZOMT.mjs} +1 -1
  29. package/dist/{chunk-S7IB6YST.mjs → chunk-ZG56T75O.mjs} +25 -40
  30. package/dist/{chunk-44BPUG24.mjs → chunk-ZH5ZBLAN.mjs} +38 -16
  31. package/dist/components/ActivityFeed.mjs +3 -3
  32. package/dist/components/AutoComplete.mjs +2 -1
  33. package/dist/components/Cascader.mjs +2 -1
  34. package/dist/components/ColorPicker.mjs +2 -1
  35. package/dist/components/CropUpload.mjs +3 -3
  36. package/dist/components/DataExport.mjs +3 -3
  37. package/dist/components/DataTableWithToolbar.mjs +6 -6
  38. package/dist/components/DatePicker.mjs +2 -1
  39. package/dist/components/Drawer.mjs +2 -2
  40. package/dist/components/Dropdown.mjs +2 -2
  41. package/dist/components/FormItem.mjs +2 -1
  42. package/dist/components/Image.mjs +5 -5
  43. package/dist/components/ImageGroup.mjs +3 -3
  44. package/dist/components/ImagePreview.mjs +2 -2
  45. package/dist/components/Loading.mjs +2 -2
  46. package/dist/components/Mentions.mjs +2 -1
  47. package/dist/components/Menu.mjs +2 -2
  48. package/dist/components/Modal.mjs +2 -2
  49. package/dist/components/NotificationCenter.mjs +3 -3
  50. package/dist/components/Popconfirm.mjs +3 -3
  51. package/dist/components/Popover.mjs +3 -3
  52. package/dist/components/Select.mjs +2 -1
  53. package/dist/components/Spotlight.mjs +2 -2
  54. package/dist/components/Table.mjs +3 -2
  55. package/dist/components/TimePicker.mjs +2 -1
  56. package/dist/components/Tooltip.mjs +3 -3
  57. package/dist/components/Tour.mjs +2 -2
  58. package/dist/components/TreeSelect.mjs +2 -1
  59. package/dist/index.mjs +4 -2
  60. package/package.json +2 -2
  61. package/dist/chunk-KVARQQAG.mjs +0 -181
  62. package/dist/chunk-SEWNVIHH.mjs +0 -153
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  usePopup
3
- } from "./chunk-S7IB6YST.mjs";
3
+ } from "./chunk-ZG56T75O.mjs";
4
4
  import {
5
- renderBodyPortal
6
- } from "./chunk-SEWNVIHH.mjs";
5
+ renderOverlayPortal
6
+ } from "./chunk-HKAZXG74.mjs";
7
7
 
8
8
  // src/components/Popconfirm.tsx
9
9
  import React, { useMemo, useRef } from "react";
@@ -82,6 +82,9 @@ var Popconfirm = ({
82
82
  containerRef,
83
83
  triggerRef,
84
84
  floatingRef,
85
+ floatingClasses,
86
+ positioned,
87
+ overlayTarget,
85
88
  closeAndRestoreFocus,
86
89
  actualPlacement,
87
90
  floatingStyles: baseFloatingStyles
@@ -106,21 +109,11 @@ var Popconfirm = ({
106
109
  if (disabled) return;
107
110
  setVisible(!currentVisible);
108
111
  };
109
- const contentWrapperStyles = useMemo(
110
- () => ({
111
- position: "absolute",
112
- left: baseFloatingStyles.left,
113
- top: baseFloatingStyles.top,
114
- transformOrigin: baseFloatingStyles.transformOrigin
115
- }),
116
- [baseFloatingStyles]
117
- );
118
112
  const containerClasses = useMemo(
119
113
  () => classNames(getPopconfirmContainerClasses(), className),
120
114
  [className]
121
115
  );
122
116
  const triggerClasses = useMemo(() => getPopconfirmTriggerClasses(disabled), [disabled]);
123
- const contentWrapperClasses = "absolute z-50";
124
117
  const arrowClasses = useMemo(() => getPopconfirmArrowClasses(actualPlacement), [actualPlacement]);
125
118
  const contentClasses = getPopconfirmContentClasses();
126
119
  const titleClasses = getPopconfirmTitleClasses();
@@ -178,13 +171,14 @@ var Popconfirm = ({
178
171
  })();
179
172
  return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: containerClasses, style: mergedStyle, ...divProps, children: [
180
173
  /* @__PURE__ */ jsx("div", { ref: triggerRef, children: triggerNode }),
181
- renderBodyPortal(
174
+ renderOverlayPortal(
182
175
  /* @__PURE__ */ jsx(
183
176
  "div",
184
177
  {
185
178
  ref: floatingRef,
186
- className: contentWrapperClasses,
187
- style: contentWrapperStyles,
179
+ className: floatingClasses,
180
+ style: baseFloatingStyles,
181
+ "data-positioned": positioned,
188
182
  hidden: !currentVisible,
189
183
  "aria-hidden": !currentVisible,
190
184
  children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
@@ -215,7 +209,8 @@ var Popconfirm = ({
215
209
  )
216
210
  ] })
217
211
  }
218
- )
212
+ ),
213
+ overlayTarget
219
214
  )
220
215
  ] });
221
216
  };
@@ -1,9 +1,7 @@
1
1
  import {
2
- renderBodyPortal,
3
- useClickOutside,
4
- useEscapeKey,
5
- useFloating
6
- } from "./chunk-SEWNVIHH.mjs";
2
+ renderOverlayPortal,
3
+ useAnchoredOverlay
4
+ } from "./chunk-HKAZXG74.mjs";
7
5
 
8
6
  // src/components/Dropdown.tsx
9
7
  import React, {
@@ -23,9 +21,7 @@ import {
23
21
  getDropdownChevronClasses,
24
22
  getDropdownMenuClasses,
25
23
  getDropdownItemClasses,
26
- getTransformOrigin,
27
24
  injectDropdownStyles,
28
- FLOATING_OVERLAY_Z_INDEX,
29
25
  DROPDOWN_CHEVRON_PATH,
30
26
  DROPDOWN_ENTER_CLASS,
31
27
  handleMenuNavigation,
@@ -164,21 +160,17 @@ var Dropdown = ({
164
160
  handleMenuNavigation(floatingRef.current, event.nativeEvent);
165
161
  }
166
162
  }, []);
167
- useClickOutside({
168
- enabled: trigger === "click" && visible,
169
- refs: [containerRef, floatingRef],
170
- onOutsideClick: () => setVisible(false)
171
- });
172
- useEscapeKey({
173
- enabled: visible,
174
- onEscape: () => setVisible(false)
175
- });
176
- const { x, y, placement } = useFloating({
163
+ const overlay = useAnchoredOverlay({
177
164
  referenceRef: triggerRef,
178
165
  floatingRef,
179
166
  enabled: visible,
180
167
  placement: initialPlacement,
181
- offset
168
+ offset,
169
+ portal,
170
+ containerRef,
171
+ dismissOnOutside: trigger === "click",
172
+ dismissOnEscape: true,
173
+ onDismiss: () => setVisible(false)
182
174
  });
183
175
  useEffect(() => {
184
176
  return () => {
@@ -192,17 +184,8 @@ var Dropdown = ({
192
184
  [className]
193
185
  );
194
186
  const triggerClasses = useMemo(() => getDropdownTriggerClasses(disabled), [disabled]);
195
- const menuWrapperClasses = classNames("absolute", DROPDOWN_ENTER_CLASS);
196
- const menuWrapperStyles = useMemo(
197
- () => ({
198
- position: "absolute",
199
- left: x,
200
- top: y,
201
- zIndex: FLOATING_OVERLAY_Z_INDEX,
202
- transformOrigin: getTransformOrigin(placement)
203
- }),
204
- [x, y, placement]
205
- );
187
+ const menuWrapperClasses = classNames(overlay.floatingClasses, DROPDOWN_ENTER_CLASS);
188
+ const menuWrapperStyles = overlay.floatingStyles;
206
189
  const contextValue = useMemo(
207
190
  () => ({ closeOnClick, handleItemClick }),
208
191
  [closeOnClick, handleItemClick]
@@ -243,6 +226,7 @@ var Dropdown = ({
243
226
  ref: floatingRef,
244
227
  className: menuWrapperClasses,
245
228
  style: menuWrapperStyles,
229
+ "data-positioned": overlay.positioned,
246
230
  hidden: !visible,
247
231
  "data-tiger-dropdown-menu": "",
248
232
  onMouseEnter: handleMouseEnter,
@@ -272,7 +256,7 @@ var Dropdown = ({
272
256
  ]
273
257
  }
274
258
  ),
275
- portal ? renderBodyPortal(menuWrapperNode) : menuWrapperNode
259
+ renderOverlayPortal(menuWrapperNode, overlay.target, !portal)
276
260
  ] }) });
277
261
  };
278
262
 
@@ -1,3 +1,7 @@
1
+ import {
2
+ renderOverlayPortal,
3
+ useAnchoredOverlay
4
+ } from "./chunk-HKAZXG74.mjs";
1
5
  import {
2
6
  useTigerConfig
3
7
  } from "./chunk-YSIXURBW.mjs";
@@ -85,8 +89,22 @@ var Cascader = (props) => {
85
89
  const [uncontrolledSearchValue, setUncontrolledSearchValue] = useState(defaultSearchValue);
86
90
  const searchQuery = searchValue ?? uncontrolledSearchValue;
87
91
  const [activePath, setActivePath] = useState([]);
92
+ const wasOpenRef = useRef(false);
88
93
  const triggerRef = useRef(null);
89
94
  const dropdownRef = useRef(null);
95
+ const overlay = useAnchoredOverlay({
96
+ enabled: isOpen,
97
+ referenceRef: triggerRef,
98
+ floatingRef: dropdownRef,
99
+ placement: "bottom-start",
100
+ offset: 4,
101
+ layout: "fullscreen-sm",
102
+ matchReferenceWidth: true,
103
+ dismissOnOutside: true,
104
+ dismissOnEscape: true,
105
+ restoreFocusOnDismiss: true,
106
+ onDismiss: () => setIsOpen(false)
107
+ });
90
108
  const displayLabel = useMemo(
91
109
  () => getCascaderDisplayLabel(options, value, separator),
92
110
  [options, value, separator]
@@ -105,29 +123,25 @@ var Cascader = (props) => {
105
123
  () => classNames(getCascaderTriggerClasses(size, disabled, isOpen), className),
106
124
  [size, disabled, isOpen, className]
107
125
  );
108
- useEffect(() => {
109
- if (isOpen) {
110
- setActivePath(value ? [...value] : []);
111
- updateSearchValue("");
112
- }
113
- }, [isOpen, value]);
114
- function updateSearchValue(value2) {
115
- if (searchValue === void 0) {
116
- setUncontrolledSearchValue(value2);
117
- }
118
- onSearchChange?.(value2);
119
- }
120
- useEffect(() => {
121
- if (!isOpen) return;
122
- function handleClick(e) {
123
- const target = e.target;
124
- if (triggerRef.current && !triggerRef.current.contains(target) && dropdownRef.current && !dropdownRef.current.contains(target)) {
125
- setIsOpen(false);
126
+ const updateSearchValue = useCallback(
127
+ (nextValue) => {
128
+ if (searchValue === void 0) {
129
+ setUncontrolledSearchValue(nextValue);
126
130
  }
131
+ onSearchChange?.(nextValue);
132
+ },
133
+ [onSearchChange, searchValue]
134
+ );
135
+ useEffect(() => {
136
+ if (!isOpen) {
137
+ wasOpenRef.current = false;
138
+ return;
127
139
  }
128
- document.addEventListener("click", handleClick, true);
129
- return () => document.removeEventListener("click", handleClick, true);
130
- }, [isOpen]);
140
+ if (wasOpenRef.current) return;
141
+ wasOpenRef.current = true;
142
+ setActivePath(value ? [...value] : []);
143
+ updateSearchValue("");
144
+ }, [isOpen, updateSearchValue, value]);
131
145
  const toggleOpen = useCallback(() => {
132
146
  if (disabled) return;
133
147
  setIsOpen((prev) => !prev);
@@ -248,98 +262,121 @@ var Cascader = (props) => {
248
262
  ]
249
263
  }
250
264
  ),
251
- isOpen && /* @__PURE__ */ jsxs(
252
- "div",
253
- {
254
- ref: dropdownRef,
255
- className: classNames(cascaderDropdownClasses, isSearchMode && "flex-col"),
256
- children: [
257
- searchable && /* @__PURE__ */ jsx(
258
- "input",
259
- {
260
- type: "text",
261
- className: cascaderSearchInputClasses,
262
- placeholder: resolveLocaleText("Search...", mergedLocale?.common?.searchPlaceholder),
263
- value: searchQuery,
264
- onChange: (e) => updateSearchValue(e.target.value),
265
- "aria-label": resolveLocaleText(
266
- "Search options",
267
- mergedLocale?.common?.searchPlaceholder
268
- )
269
- }
265
+ renderOverlayPortal(
266
+ isOpen ? /* @__PURE__ */ jsxs(
267
+ "div",
268
+ {
269
+ ref: dropdownRef,
270
+ className: classNames(
271
+ cascaderDropdownClasses,
272
+ isSearchMode && "flex-col",
273
+ overlay.floatingClasses
270
274
  ),
271
- isSearchMode ? (
272
- // Search results
273
- searchResults.length === 0 ? /* @__PURE__ */ jsx("div", { className: cascaderEmptyStateClasses, children: resolveLocaleText("No results found", emptyText, mergedLocale?.common?.emptyText) }) : /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-auto", ...getPickerListboxAria({ id: listboxId }), children: searchResults.map((item) => /* @__PURE__ */ jsx(
274
- "div",
275
+ style: overlay.floatingStyles,
276
+ "data-positioned": overlay.positioned,
277
+ children: [
278
+ searchable && /* @__PURE__ */ jsx(
279
+ "input",
275
280
  {
276
- className: classNames(
277
- cascaderSearchResultClasses,
278
- item.disabled && "opacity-50 cursor-not-allowed"
281
+ type: "text",
282
+ className: cascaderSearchInputClasses,
283
+ placeholder: resolveLocaleText(
284
+ "Search...",
285
+ mergedLocale?.common?.searchPlaceholder
279
286
  ),
280
- ...getPickerOptionAria({
281
- selected: value?.join(",") === item.valuePath.join(","),
282
- disabled: item.disabled
283
- }),
284
- onClick: () => handleSearchResultClick(item.valuePath, item.disabled),
285
- children: typeof searchable === "object" && searchable.render ? searchable.render(searchQuery, item.path) : item.label
286
- },
287
- item.valuePath.join(",")
288
- )) })
289
- ) : (
290
- // Cascading columns
291
- /* @__PURE__ */ jsx("div", { className: "flex", children: columns.map((col, colIndex) => /* @__PURE__ */ jsx(
292
- "div",
293
- {
294
- className: cascaderColumnClasses,
295
- ...getPickerListboxAria({
296
- id: colIndex === 0 ? listboxId : void 0,
297
- label: `Level ${colIndex + 1}`
298
- }),
299
- "aria-label": `Level ${colIndex + 1}`,
300
- children: col.options.map((option) => {
301
- const isSelected = col.selectedValue === option.value;
302
- const hasChildren = isCascaderOptionExpandable(option);
303
- return /* @__PURE__ */ jsxs(
287
+ value: searchQuery,
288
+ onChange: (e) => updateSearchValue(e.target.value),
289
+ "aria-label": resolveLocaleText(
290
+ "Search options",
291
+ mergedLocale?.common?.searchPlaceholder
292
+ )
293
+ }
294
+ ),
295
+ isSearchMode ? (
296
+ // Search results
297
+ searchResults.length === 0 ? /* @__PURE__ */ jsx("div", { className: cascaderEmptyStateClasses, children: resolveLocaleText(
298
+ "No results found",
299
+ emptyText,
300
+ mergedLocale?.common?.emptyText
301
+ ) }) : /* @__PURE__ */ jsx(
302
+ "div",
303
+ {
304
+ className: "max-h-64 overflow-auto",
305
+ ...getPickerListboxAria({ id: listboxId }),
306
+ children: searchResults.map((item) => /* @__PURE__ */ jsx(
304
307
  "div",
305
308
  {
306
- className: getCascaderOptionClasses(isSelected, !!option.disabled, size),
309
+ className: classNames(
310
+ cascaderSearchResultClasses,
311
+ item.disabled && "opacity-50 cursor-not-allowed"
312
+ ),
307
313
  ...getPickerOptionAria({
308
- selected: isSelected,
309
- disabled: !!option.disabled
314
+ selected: value?.join(",") === item.valuePath.join(","),
315
+ disabled: item.disabled
310
316
  }),
311
- onClick: () => handleOptionClick(option, colIndex),
312
- onMouseEnter: () => handleOptionHover(option, colIndex),
313
- children: [
314
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: option.label }),
315
- hasChildren && /* @__PURE__ */ jsx(
316
- "svg",
317
- {
318
- className: "w-4 h-4 text-[var(--tiger-text-muted,#9ca3af)]",
319
- xmlns: "http://www.w3.org/2000/svg",
320
- viewBox: "0 0 20 20",
321
- fill: "currentColor",
322
- children: /* @__PURE__ */ jsx(
323
- "path",
324
- {
325
- fillRule: "evenodd",
326
- d: "M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z",
327
- clipRule: "evenodd"
328
- }
329
- )
330
- }
331
- )
332
- ]
317
+ onClick: () => handleSearchResultClick(item.valuePath, item.disabled),
318
+ children: typeof searchable === "object" && searchable.render ? searchable.render(searchQuery, item.path) : item.label
333
319
  },
334
- option.value
335
- );
336
- })
337
- },
338
- colIndex
339
- )) })
340
- )
341
- ]
342
- }
320
+ item.valuePath.join(",")
321
+ ))
322
+ }
323
+ )
324
+ ) : (
325
+ // Cascading columns
326
+ /* @__PURE__ */ jsx("div", { className: "flex", children: columns.map((col, colIndex) => /* @__PURE__ */ jsx(
327
+ "div",
328
+ {
329
+ className: cascaderColumnClasses,
330
+ ...getPickerListboxAria({
331
+ id: colIndex === 0 ? listboxId : void 0,
332
+ label: `Level ${colIndex + 1}`
333
+ }),
334
+ "aria-label": `Level ${colIndex + 1}`,
335
+ children: col.options.map((option) => {
336
+ const isSelected = col.selectedValue === option.value;
337
+ const hasChildren = isCascaderOptionExpandable(option);
338
+ return /* @__PURE__ */ jsxs(
339
+ "div",
340
+ {
341
+ className: getCascaderOptionClasses(isSelected, !!option.disabled, size),
342
+ ...getPickerOptionAria({
343
+ selected: isSelected,
344
+ disabled: !!option.disabled
345
+ }),
346
+ onClick: () => handleOptionClick(option, colIndex),
347
+ onMouseEnter: () => handleOptionHover(option, colIndex),
348
+ children: [
349
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: option.label }),
350
+ hasChildren && /* @__PURE__ */ jsx(
351
+ "svg",
352
+ {
353
+ className: "w-4 h-4 text-[var(--tiger-text-muted,#9ca3af)]",
354
+ xmlns: "http://www.w3.org/2000/svg",
355
+ viewBox: "0 0 20 20",
356
+ fill: "currentColor",
357
+ children: /* @__PURE__ */ jsx(
358
+ "path",
359
+ {
360
+ fillRule: "evenodd",
361
+ d: "M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z",
362
+ clipRule: "evenodd"
363
+ }
364
+ )
365
+ }
366
+ )
367
+ ]
368
+ },
369
+ option.value
370
+ );
371
+ })
372
+ },
373
+ colIndex
374
+ )) })
375
+ )
376
+ ]
377
+ }
378
+ ) : null,
379
+ overlay.target
343
380
  )
344
381
  ] });
345
382
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  renderBodyPortal,
3
3
  useEscapeKey
4
- } from "./chunk-SEWNVIHH.mjs";
4
+ } from "./chunk-HKAZXG74.mjs";
5
5
  import {
6
6
  useTigerConfig
7
7
  } from "./chunk-YSIXURBW.mjs";
@@ -1,14 +1,10 @@
1
1
  import {
2
- useClickOutside,
3
- useEscapeKey,
4
- useFloating
5
- } from "./chunk-SEWNVIHH.mjs";
2
+ useAnchoredOverlay
3
+ } from "./chunk-HKAZXG74.mjs";
6
4
 
7
5
  // src/utils/use-popup.ts
8
6
  import { useCallback, useMemo, useRef, useState } from "react";
9
7
  import {
10
- getTransformOrigin,
11
- FLOATING_OVERLAY_Z_INDEX,
12
8
  buildTriggerHandlerMap,
13
9
  restoreFocus
14
10
  } from "@expcat/tigercat-core";
@@ -29,17 +25,6 @@ function usePopup(options) {
29
25
  const containerRef = useRef(null);
30
26
  const triggerRef = useRef(null);
31
27
  const floatingRef = useRef(null);
32
- const {
33
- x,
34
- y,
35
- placement: actualPlacement
36
- } = useFloating({
37
- referenceRef: triggerRef,
38
- floatingRef,
39
- enabled: currentVisible,
40
- placement,
41
- offset
42
- });
43
28
  const setVisible = useCallback(
44
29
  (next) => {
45
30
  if (disabled && next) return;
@@ -71,26 +56,23 @@ function usePopup(options) {
71
56
  if (!disabled) setVisible(false);
72
57
  }, [disabled, setVisible]);
73
58
  const effectiveTrigger = multiTrigger ? trigger : "click";
74
- useClickOutside({
75
- enabled: currentVisible && effectiveTrigger === "click",
76
- refs: [containerRef, floatingRef],
77
- onOutsideClick: closeAndRestoreFocus,
78
- defer: true
79
- });
80
- useEscapeKey({
81
- enabled: currentVisible && effectiveTrigger !== "manual",
82
- onEscape: closeAndRestoreFocus
59
+ const overlay = useAnchoredOverlay({
60
+ enabled: currentVisible,
61
+ referenceRef: triggerRef,
62
+ floatingRef,
63
+ containerRef,
64
+ placement,
65
+ offset,
66
+ dismissOnOutside: effectiveTrigger === "click",
67
+ dismissOnEscape: effectiveTrigger !== "manual",
68
+ onDismiss: (reason) => {
69
+ if (reason === "escape") {
70
+ closeAndRestoreFocus();
71
+ } else {
72
+ setVisible(false);
73
+ }
74
+ }
83
75
  });
84
- const floatingStyles = useMemo(
85
- () => ({
86
- position: "absolute",
87
- left: x,
88
- top: y,
89
- transformOrigin: getTransformOrigin(actualPlacement),
90
- zIndex: FLOATING_OVERLAY_Z_INDEX
91
- }),
92
- [x, y, actualPlacement]
93
- );
94
76
  const triggerHandlers = useMemo(() => {
95
77
  if (!multiTrigger) {
96
78
  return { onClick: handleToggle };
@@ -107,10 +89,13 @@ function usePopup(options) {
107
89
  containerRef,
108
90
  triggerRef,
109
91
  floatingRef,
110
- x,
111
- y,
112
- actualPlacement,
113
- floatingStyles,
92
+ x: overlay.x,
93
+ y: overlay.y,
94
+ actualPlacement: overlay.placement,
95
+ floatingStyles: overlay.floatingStyles,
96
+ floatingClasses: overlay.floatingClasses,
97
+ positioned: overlay.positioned,
98
+ overlayTarget: overlay.target,
114
99
  triggerHandlers,
115
100
  closeAndRestoreFocus
116
101
  };
@@ -4,6 +4,10 @@ import {
4
4
  import {
5
5
  FormItemControlProvider
6
6
  } from "./chunk-F6T3OLTQ.mjs";
7
+ import {
8
+ renderOverlayPortal,
9
+ useAnchoredOverlay
10
+ } from "./chunk-HKAZXG74.mjs";
7
11
 
8
12
  // src/components/FormItem.tsx
9
13
  import React, { useMemo, useEffect, useState, useCallback, useId, useRef } from "react";
@@ -50,6 +54,8 @@ var FormItem = ({
50
54
  const [errorMessage, setErrorMessage] = useState("");
51
55
  const [shakeTrigger, setShakeTrigger] = useState(0);
52
56
  const prevFormErrorRef = useRef("");
57
+ const contentRef = useRef(null);
58
+ const errorRef = useRef(null);
53
59
  const reactId = useId();
54
60
  const baseId = `tiger-form-item-${reactId}`;
55
61
  const labelId = `${baseId}-label`;
@@ -129,6 +135,14 @@ var FormItem = ({
129
135
  }
130
136
  }, [name, formContext, rules]);
131
137
  const hasError = !!errorMessage;
138
+ const popupErrorVisible = showMessage && hasError && errorDisplayMode === "popup";
139
+ const overlay = useAnchoredOverlay({
140
+ enabled: popupErrorVisible,
141
+ referenceRef: contentRef,
142
+ floatingRef: errorRef,
143
+ placement: "bottom-start",
144
+ offset: 4
145
+ });
132
146
  const describedById = useMemo(
133
147
  () => showMessage && hasError ? errorId : void 0,
134
148
  [showMessage, hasError, errorId]
@@ -244,7 +258,7 @@ var FormItem = ({
244
258
  ]
245
259
  }
246
260
  ),
247
- /* @__PURE__ */ jsxs("div", { className: contentClasses, children: [
261
+ /* @__PURE__ */ jsxs("div", { ref: contentRef, className: contentClasses, children: [
248
262
  /* @__PURE__ */ jsx(
249
263
  "div",
250
264
  {
@@ -258,21 +272,29 @@ var FormItem = ({
258
272
  children: /* @__PURE__ */ jsx(FormItemControlProvider, { value: controlValue, children: enhancedChild })
259
273
  }
260
274
  ),
261
- showMessage && /* @__PURE__ */ jsx(
262
- "div",
263
- {
264
- id: hasError ? errorId : void 0,
265
- role: hasError ? "alert" : void 0,
266
- className: errorDisplayMode === "block" ? classNames(
267
- "mt-1 p-2 rounded bg-red-50 border border-red-200 text-red-600 text-sm",
268
- !hasError && "hidden"
269
- ) : errorDisplayMode === "popup" ? classNames(
270
- "absolute z-10 mt-1 px-2 py-1 rounded bg-red-600 text-white text-xs shadow-lg",
271
- !hasError && "hidden"
272
- ) : errorClasses,
273
- "aria-hidden": hasError ? void 0 : true,
274
- children: hasError ? errorMessage : ""
275
- }
275
+ showMessage && renderOverlayPortal(
276
+ /* @__PURE__ */ jsx(
277
+ "div",
278
+ {
279
+ ref: errorRef,
280
+ id: hasError ? errorId : void 0,
281
+ role: hasError ? "alert" : void 0,
282
+ className: errorDisplayMode === "block" ? classNames(
283
+ "mt-1 p-2 rounded bg-red-50 border border-red-200 text-red-600 text-sm",
284
+ !hasError && "hidden"
285
+ ) : errorDisplayMode === "popup" ? classNames(
286
+ "px-2 py-1 rounded bg-red-600 text-white text-xs shadow-lg",
287
+ overlay.floatingClasses,
288
+ !hasError && "hidden"
289
+ ) : errorClasses,
290
+ style: errorDisplayMode === "popup" ? overlay.floatingStyles : void 0,
291
+ "data-positioned": errorDisplayMode === "popup" ? overlay.positioned : void 0,
292
+ "aria-hidden": hasError ? void 0 : true,
293
+ children: hasError ? errorMessage : ""
294
+ }
295
+ ),
296
+ overlay.target,
297
+ errorDisplayMode !== "popup"
276
298
  )
277
299
  ] })
278
300
  ] });
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  ActivityFeed,
3
3
  ActivityFeed_default
4
- } from "../chunk-C6QK5MJT.mjs";
4
+ } from "../chunk-5CKMYMTS.mjs";
5
5
  import "../chunk-QB5472NM.mjs";
6
6
  import "../chunk-XZVQ3PJS.mjs";
7
- import "../chunk-AJJJ6HWC.mjs";
8
- import "../chunk-SEWNVIHH.mjs";
7
+ import "../chunk-K4GIKSZE.mjs";
9
8
  import "../chunk-7EXOY7GD.mjs";
10
9
  import "../chunk-HLS4CHWX.mjs";
11
10
  import "../chunk-IXV5YBCZ.mjs";
11
+ import "../chunk-HKAZXG74.mjs";
12
12
  import "../chunk-OO562MFD.mjs";
13
13
  import "../chunk-FPQMJFFM.mjs";
14
14
  import "../chunk-YSIXURBW.mjs";
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AutoComplete
3
- } from "../chunk-JTFNGXOC.mjs";
3
+ } from "../chunk-2ENQZECC.mjs";
4
+ import "../chunk-HKAZXG74.mjs";
4
5
  import "../chunk-YSIXURBW.mjs";
5
6
  import "../chunk-TGXBCKOU.mjs";
6
7
  export {
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  Cascader
3
- } from "../chunk-SHCBCM2W.mjs";
3
+ } from "../chunk-YIB6ZXZF.mjs";
4
+ import "../chunk-HKAZXG74.mjs";
4
5
  import "../chunk-YSIXURBW.mjs";
5
6
  import "../chunk-TGXBCKOU.mjs";
6
7
  export {