@expcat/tigercat-react 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 (80) 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-POP3TS4Q.mjs → chunk-2WGEHH5A.mjs} +57 -29
  4. package/dist/{chunk-K7MYQISG.mjs → chunk-54HN5BXW.mjs} +10 -4
  5. package/dist/chunk-5CKMYMTS.mjs +292 -0
  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-N6JNLJIN.mjs → chunk-BOGOQ44C.mjs} +6 -2
  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-44CQTGAN.mjs → chunk-E7OTDBI6.mjs} +2 -2
  17. package/dist/{chunk-DJ4PSDQS.mjs → chunk-FYINJRYN.mjs} +2 -2
  18. package/dist/{chunk-KFPQ6DIH.mjs → chunk-GV4F6X3C.mjs} +29 -25
  19. package/dist/chunk-HKAZXG74.mjs +308 -0
  20. package/dist/{chunk-QWUDJC6K.mjs → chunk-HOYBHB7B.mjs} +38 -17
  21. package/dist/{chunk-IZYFETUS.mjs → chunk-HS6KUPTI.mjs} +2 -2
  22. package/dist/{chunk-EKESN747.mjs → chunk-HSBN5MLS.mjs} +1 -1
  23. package/dist/{chunk-AJJJ6HWC.mjs → chunk-K4GIKSZE.mjs} +1 -1
  24. package/dist/{chunk-2UOGBS3C.mjs → chunk-KP6DEYWB.mjs} +27 -6
  25. package/dist/{chunk-PAN256RW.mjs → chunk-KVCI2346.mjs} +59 -55
  26. package/dist/{chunk-3O2WHF3U.mjs → chunk-NCHUEGUW.mjs} +2 -2
  27. package/dist/{chunk-VD55SSP7.mjs → chunk-PD6Q36OO.mjs} +14 -6
  28. package/dist/{chunk-5RVLBNLI.mjs → chunk-RJPNBYK5.mjs} +4 -4
  29. package/dist/{chunk-HXD7KMRP.mjs → chunk-UCBW5RJN.mjs} +31 -2
  30. package/dist/{chunk-5IHOOP5A.mjs → chunk-UD4DTVJZ.mjs} +64 -79
  31. package/dist/{chunk-A6JNS35U.mjs → chunk-UT5BV2VO.mjs} +2 -2
  32. package/dist/{chunk-K6GJMKJR.mjs → chunk-V6P7ZK6O.mjs} +3 -3
  33. package/dist/{chunk-4XGO3OSE.mjs → chunk-XE4YFBOZ.mjs} +12 -17
  34. package/dist/{chunk-YI7NQWUV.mjs → chunk-YI6YWH66.mjs} +14 -30
  35. package/dist/{chunk-SHCBCM2W.mjs → chunk-YIB6ZXZF.mjs} +142 -105
  36. package/dist/{chunk-SZBYEGKU.mjs → chunk-ZCGIZOMT.mjs} +1 -1
  37. package/dist/{chunk-S7IB6YST.mjs → chunk-ZG56T75O.mjs} +25 -40
  38. package/dist/{chunk-44BPUG24.mjs → chunk-ZH5ZBLAN.mjs} +38 -16
  39. package/dist/components/ActivityFeed.mjs +3 -3
  40. package/dist/components/AreaChart.mjs +1 -1
  41. package/dist/components/AutoComplete.mjs +2 -1
  42. package/dist/components/BarChart.mjs +1 -1
  43. package/dist/components/Cascader.mjs +2 -1
  44. package/dist/components/ColorPicker.mjs +2 -1
  45. package/dist/components/CommentThread.mjs +1 -1
  46. package/dist/components/CropUpload.mjs +4 -4
  47. package/dist/components/DataExport.mjs +3 -3
  48. package/dist/components/DataTableWithToolbar.mjs +6 -6
  49. package/dist/components/DatePicker.mjs +2 -1
  50. package/dist/components/Drawer.mjs +2 -2
  51. package/dist/components/Dropdown.mjs +2 -2
  52. package/dist/components/FormItem.mjs +2 -1
  53. package/dist/components/Image.mjs +5 -5
  54. package/dist/components/ImageCropper.mjs +1 -1
  55. package/dist/components/ImageGroup.mjs +3 -3
  56. package/dist/components/ImagePreview.mjs +2 -2
  57. package/dist/components/LineChart.mjs +1 -1
  58. package/dist/components/Loading.mjs +2 -2
  59. package/dist/components/Mentions.mjs +2 -1
  60. package/dist/components/Menu.mjs +2 -2
  61. package/dist/components/Modal.mjs +2 -2
  62. package/dist/components/NotificationCenter.mjs +3 -3
  63. package/dist/components/Popconfirm.mjs +3 -3
  64. package/dist/components/Popover.mjs +3 -3
  65. package/dist/components/ScatterChart.mjs +1 -1
  66. package/dist/components/Select.mjs +2 -1
  67. package/dist/components/Spotlight.mjs +2 -2
  68. package/dist/components/Table.mjs +3 -2
  69. package/dist/components/TimePicker.mjs +2 -1
  70. package/dist/components/Tooltip.mjs +3 -3
  71. package/dist/components/Tour.mjs +2 -2
  72. package/dist/components/TreeSelect.mjs +2 -1
  73. package/dist/components/Upload.mjs +1 -1
  74. package/dist/components/VirtualTable.mjs +1 -1
  75. package/dist/index.d.mts +1 -1
  76. package/dist/index.mjs +4 -2
  77. package/package.json +2 -2
  78. package/dist/chunk-KVARQQAG.mjs +0 -181
  79. package/dist/chunk-SEWNVIHH.mjs +0 -153
  80. package/dist/chunk-XIVU7TWX.mjs +0 -305
@@ -1,12 +1,16 @@
1
+ import {
2
+ renderOverlayPortal,
3
+ useAnchoredOverlay
4
+ } from "./chunk-HKAZXG74.mjs";
5
+
1
6
  // src/components/Mentions.tsx
2
- import { useState, useMemo, useCallback, useRef, useEffect } from "react";
7
+ import { useState, useMemo, useCallback, useRef } from "react";
3
8
  import { classNames } 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
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -34,6 +38,18 @@ var Mentions = ({
34
38
  const q = query.toLowerCase();
35
39
  return options.filter((o) => !o.disabled && o.label.toLowerCase().includes(q));
36
40
  }, [options, query]);
41
+ const overlay = useAnchoredOverlay({
42
+ enabled: isOpen && filteredOptions.length > 0,
43
+ referenceRef: textareaRef,
44
+ floatingRef: dropdownRef,
45
+ containerRef,
46
+ placement: "bottom-start",
47
+ offset: 4,
48
+ dismissOnOutside: true,
49
+ dismissOnEscape: true,
50
+ restoreFocusOnDismiss: true,
51
+ onDismiss: () => setIsOpen(false)
52
+ });
37
53
  const handleInput = useCallback(
38
54
  (e) => {
39
55
  const newValue = e.target.value;
@@ -83,21 +99,6 @@ var Mentions = ({
83
99
  },
84
100
  [isOpen, filteredOptions, activeIndex, selectOption]
85
101
  );
86
- useEffect(() => {
87
- if (!isOpen) return;
88
- const handler = (e) => {
89
- if (containerRef.current && !containerRef.current.contains(e.target)) {
90
- setIsOpen(false);
91
- }
92
- };
93
- document.addEventListener("mousedown", handler);
94
- return () => document.removeEventListener("mousedown", handler);
95
- }, [isOpen]);
96
- useEffect(() => {
97
- if (!isOpen || filteredOptions.length === 0) return;
98
- if (!textareaRef.current || !dropdownRef.current) return;
99
- void positionMentionsDropdown(textareaRef.current, dropdownRef.current);
100
- }, [isOpen, filteredOptions.length, size, rows, value]);
101
102
  const wrapperClass = classNames("relative", className);
102
103
  return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: wrapperClass, children: [
103
104
  /* @__PURE__ */ jsx(
@@ -113,17 +114,30 @@ var Mentions = ({
113
114
  onKeyDown: handleKeydown
114
115
  }
115
116
  ),
116
- isOpen && filteredOptions.length > 0 && /* @__PURE__ */ jsx("div", { ref: dropdownRef, className: mentionsDropdownClasses, role: "listbox", children: filteredOptions.map((opt, i) => /* @__PURE__ */ jsx(
117
- "div",
118
- {
119
- className: getMentionsOptionClasses(i === activeIndex, !!opt.disabled),
120
- role: "option",
121
- "aria-selected": i === activeIndex,
122
- onClick: () => selectOption(opt),
123
- children: opt.label
124
- },
125
- opt.value
126
- )) })
117
+ renderOverlayPortal(
118
+ isOpen && filteredOptions.length > 0 ? /* @__PURE__ */ jsx(
119
+ "div",
120
+ {
121
+ ref: dropdownRef,
122
+ className: classNames(mentionsDropdownClasses, overlay.floatingClasses),
123
+ style: overlay.floatingStyles,
124
+ "data-positioned": overlay.positioned,
125
+ role: "listbox",
126
+ children: filteredOptions.map((opt, i) => /* @__PURE__ */ jsx(
127
+ "div",
128
+ {
129
+ className: getMentionsOptionClasses(i === activeIndex, !!opt.disabled),
130
+ role: "option",
131
+ "aria-selected": i === activeIndex,
132
+ onClick: () => selectOption(opt),
133
+ children: opt.label
134
+ },
135
+ opt.value
136
+ ))
137
+ }
138
+ ) : null,
139
+ overlay.target
140
+ )
127
141
  ] });
128
142
  };
129
143
  var Mentions_default = Mentions;
@@ -0,0 +1,203 @@
1
+ import {
2
+ renderOverlayPortal,
3
+ useAnchoredOverlay
4
+ } from "./chunk-HKAZXG74.mjs";
5
+
6
+ // src/components/ColorPicker.tsx
7
+ import { useState, useMemo, useRef, useEffect } from "react";
8
+ import {
9
+ colorPickerBaseClasses,
10
+ getColorPickerTriggerClasses,
11
+ colorPickerPanelClasses,
12
+ colorPickerInputClasses,
13
+ colorPickerPresetClasses,
14
+ hexToRgb,
15
+ rgbToHex,
16
+ rgbToHsv,
17
+ hsvToRgb,
18
+ formatColorString,
19
+ parseColorInput,
20
+ classNames
21
+ } from "@expcat/tigercat-core";
22
+ import { jsx, jsxs } from "react/jsx-runtime";
23
+ var ColorPicker = ({
24
+ value = "#2563eb",
25
+ disabled = false,
26
+ size = "md",
27
+ showAlpha = false,
28
+ format = "hex",
29
+ presets,
30
+ className,
31
+ onChange
32
+ }) => {
33
+ const [isOpen, setIsOpen] = useState(false);
34
+ const [alpha, setAlpha] = useState(1);
35
+ const containerRef = useRef(null);
36
+ const triggerRef = useRef(null);
37
+ const panelRef = useRef(null);
38
+ const overlay = useAnchoredOverlay({
39
+ enabled: isOpen,
40
+ referenceRef: triggerRef,
41
+ floatingRef: panelRef,
42
+ containerRef,
43
+ placement: "bottom-start",
44
+ offset: 4,
45
+ dismissOnOutside: true,
46
+ dismissOnEscape: true,
47
+ restoreFocusOnDismiss: true,
48
+ onDismiss: () => setIsOpen(false)
49
+ });
50
+ const rgb = useMemo(() => hexToRgb(value), [value]);
51
+ const hsv = useMemo(() => rgbToHsv(rgb.r, rgb.g, rgb.b), [rgb]);
52
+ const displayValue = useMemo(
53
+ () => formatColorString(rgb.r, rgb.g, rgb.b, format, showAlpha ? alpha : void 0),
54
+ [rgb, format, showAlpha, alpha]
55
+ );
56
+ const swatchColor = showAlpha ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})` : value;
57
+ const [inputValue, setInputValue] = useState(displayValue);
58
+ useEffect(() => {
59
+ setInputValue(displayValue);
60
+ }, [displayValue]);
61
+ function togglePanel() {
62
+ if (disabled) return;
63
+ setIsOpen((v) => !v);
64
+ }
65
+ function handleTriggerKeyDown(e) {
66
+ if (disabled) return;
67
+ if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
68
+ e.preventDefault();
69
+ setIsOpen((v) => !v);
70
+ } else if (e.key === "Escape" && isOpen) {
71
+ setIsOpen(false);
72
+ }
73
+ }
74
+ function handleHueChange(e) {
75
+ const hue = Number(e.target.value);
76
+ const { r, g, b } = hsvToRgb(hue, hsv.s, hsv.v);
77
+ const hex = rgbToHex(r, g, b);
78
+ onChange?.(hex);
79
+ }
80
+ function handleInputChange(e) {
81
+ const val = e.target.value;
82
+ setInputValue(val);
83
+ const hex = parseColorInput(val);
84
+ if (hex) {
85
+ onChange?.(hex);
86
+ }
87
+ }
88
+ function handleAlphaChange(e) {
89
+ setAlpha(Number(e.target.value) / 100);
90
+ }
91
+ function handlePresetClick(color) {
92
+ onChange?.(color);
93
+ }
94
+ function handlePresetKeyDown(e, color) {
95
+ if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
96
+ e.preventDefault();
97
+ handlePresetClick(color);
98
+ }
99
+ }
100
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: classNames(colorPickerBaseClasses, className), children: [
101
+ /* @__PURE__ */ jsx(
102
+ "div",
103
+ {
104
+ ref: triggerRef,
105
+ className: getColorPickerTriggerClasses(size, disabled),
106
+ style: { backgroundColor: swatchColor },
107
+ role: "button",
108
+ "aria-label": "Pick color",
109
+ "aria-haspopup": "dialog",
110
+ "aria-expanded": isOpen,
111
+ "aria-disabled": disabled || void 0,
112
+ tabIndex: disabled ? -1 : 0,
113
+ onClick: togglePanel,
114
+ onKeyDown: handleTriggerKeyDown
115
+ }
116
+ ),
117
+ renderOverlayPortal(
118
+ isOpen ? /* @__PURE__ */ jsxs(
119
+ "div",
120
+ {
121
+ ref: panelRef,
122
+ className: classNames(colorPickerPanelClasses, overlay.floatingClasses),
123
+ style: overlay.floatingStyles,
124
+ "data-positioned": overlay.positioned,
125
+ children: [
126
+ /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
127
+ /* @__PURE__ */ jsx("label", { className: "block text-xs text-[var(--tiger-text-muted,#6b7280)] mb-1", children: "Hue" }),
128
+ /* @__PURE__ */ jsx(
129
+ "input",
130
+ {
131
+ type: "range",
132
+ min: 0,
133
+ max: 360,
134
+ value: hsv.h,
135
+ className: "w-full h-2 rounded-full cursor-pointer accent-[var(--tiger-primary,#2563eb)]",
136
+ "aria-label": "Hue",
137
+ onChange: handleHueChange
138
+ }
139
+ )
140
+ ] }),
141
+ showAlpha && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
142
+ /* @__PURE__ */ jsx("label", { className: "block text-xs text-[var(--tiger-text-muted,#6b7280)] mb-1", children: "Alpha" }),
143
+ /* @__PURE__ */ jsx(
144
+ "input",
145
+ {
146
+ type: "range",
147
+ min: 0,
148
+ max: 100,
149
+ value: Math.round(alpha * 100),
150
+ className: "w-full h-2 rounded-full cursor-pointer accent-[var(--tiger-primary,#2563eb)]",
151
+ "aria-label": "Alpha",
152
+ onChange: handleAlphaChange
153
+ }
154
+ )
155
+ ] }),
156
+ /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
157
+ /* @__PURE__ */ jsx("label", { className: "block text-xs text-[var(--tiger-text-muted,#6b7280)] mb-1 uppercase", children: format }),
158
+ /* @__PURE__ */ jsx(
159
+ "input",
160
+ {
161
+ type: "text",
162
+ className: colorPickerInputClasses,
163
+ value: inputValue,
164
+ "aria-label": "Color value",
165
+ onChange: handleInputChange
166
+ }
167
+ )
168
+ ] }),
169
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
170
+ /* @__PURE__ */ jsx(
171
+ "div",
172
+ {
173
+ className: "w-8 h-8 rounded border border-[var(--tiger-border,#d1d5db)]",
174
+ style: { backgroundColor: swatchColor },
175
+ "aria-label": "Color preview"
176
+ }
177
+ ),
178
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-[var(--tiger-text,#111827)]", children: displayValue })
179
+ ] }),
180
+ presets && presets.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: presets.map((color) => /* @__PURE__ */ jsx(
181
+ "div",
182
+ {
183
+ className: colorPickerPresetClasses,
184
+ style: { backgroundColor: color },
185
+ role: "button",
186
+ tabIndex: 0,
187
+ "aria-label": `Select ${color}`,
188
+ onClick: () => handlePresetClick(color),
189
+ onKeyDown: (e) => handlePresetKeyDown(e, color)
190
+ },
191
+ color
192
+ )) })
193
+ ]
194
+ }
195
+ ) : null,
196
+ overlay.target
197
+ )
198
+ ] });
199
+ };
200
+
201
+ export {
202
+ ColorPicker
203
+ };
@@ -1,9 +1,13 @@
1
+ import {
2
+ renderOverlayPortal,
3
+ useAnchoredOverlay
4
+ } from "./chunk-HKAZXG74.mjs";
1
5
  import {
2
6
  useTigerConfig
3
7
  } from "./chunk-YSIXURBW.mjs";
4
8
 
5
9
  // src/components/TreeSelect.tsx
6
- import { useState, useMemo, useRef, useEffect, useId } from "react";
10
+ import { useState, useMemo, useRef, useId } from "react";
7
11
  import {
8
12
  resolveLocaleText,
9
13
  mergeTigerLocale,
@@ -84,6 +88,21 @@ var TreeSelect = (props) => {
84
88
  () => defaultExpandAll ? new Set(getAllTreeSelectKeys(treeData)) : /* @__PURE__ */ new Set()
85
89
  );
86
90
  const containerRef = useRef(null);
91
+ const triggerRef = useRef(null);
92
+ const dropdownRef = useRef(null);
93
+ const overlay = useAnchoredOverlay({
94
+ enabled: isOpen,
95
+ referenceRef: triggerRef,
96
+ floatingRef: dropdownRef,
97
+ containerRef,
98
+ placement: "bottom-start",
99
+ offset: 4,
100
+ matchReferenceWidth: true,
101
+ dismissOnOutside: true,
102
+ dismissOnEscape: true,
103
+ restoreFocusOnDismiss: true,
104
+ onDismiss: closeDropdown
105
+ });
87
106
  const displayLabel = useMemo(() => getTreeSelectDisplayLabel(treeData, value), [treeData, value]);
88
107
  const showClearButton = clearable && !disabled && value !== void 0 && (Array.isArray(value) ? value.length > 0 : value !== "");
89
108
  const matchedKeys = useMemo(() => {
@@ -162,20 +181,11 @@ var TreeSelect = (props) => {
162
181
  closeDropdown();
163
182
  }
164
183
  }
165
- useEffect(() => {
166
- if (!isOpen) return;
167
- function handleClickOutside(e) {
168
- if (containerRef.current && !containerRef.current.contains(e.target)) {
169
- closeDropdown();
170
- }
171
- }
172
- document.addEventListener("click", handleClickOutside);
173
- return () => document.removeEventListener("click", handleClickOutside);
174
- }, [isOpen]);
175
184
  return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: classNames(treeSelectBaseClasses, className), ...divProps, children: [
176
185
  /* @__PURE__ */ jsxs(
177
186
  "button",
178
187
  {
188
+ ref: triggerRef,
179
189
  type: "button",
180
190
  className: getTreeSelectTriggerClasses(size, disabled, isOpen),
181
191
  ...getPickerComboboxAria({ expanded: isOpen, listboxId }),
@@ -223,58 +233,77 @@ var TreeSelect = (props) => {
223
233
  ]
224
234
  }
225
235
  ),
226
- isOpen && /* @__PURE__ */ jsxs("div", { ...getPickerListboxAria({ id: listboxId }), className: treeSelectDropdownClasses, children: [
227
- searchable && /* @__PURE__ */ jsx(
228
- "input",
236
+ renderOverlayPortal(
237
+ isOpen ? /* @__PURE__ */ jsxs(
238
+ "div",
229
239
  {
230
- type: "text",
231
- className: treeSelectSearchClasses,
232
- placeholder: resolveLocaleText("Search...", mergedLocale?.common?.searchPlaceholder),
233
- value: searchQuery,
234
- "aria-label": resolveLocaleText("Search tree", mergedLocale?.common?.searchPlaceholder),
235
- onChange: (e) => updateSearchValue(e.target.value)
236
- }
237
- ),
238
- visibleNodes.length > 0 ? visibleNodes.map((flatNode) => {
239
- const { node, level, hasChildren, isExpanded } = flatNode;
240
- const selected = isSelected(node.key);
241
- const indent = level * 20;
242
- return /* @__PURE__ */ jsxs(
243
- "div",
244
- {
245
- ...getPickerOptionAria({ selected, disabled: !!node.disabled }),
246
- className: getTreeSelectNodeClasses(selected, !!node.disabled, size),
247
- style: { paddingLeft: `${indent + 8}px` },
248
- onClick: (e) => {
249
- e.stopPropagation();
250
- handleNodeSelect(node);
251
- },
252
- children: [
253
- hasChildren ? /* @__PURE__ */ jsx(
254
- "span",
240
+ ref: dropdownRef,
241
+ ...getPickerListboxAria({ id: listboxId }),
242
+ className: classNames(treeSelectDropdownClasses, overlay.floatingClasses),
243
+ style: overlay.floatingStyles,
244
+ "data-positioned": overlay.positioned,
245
+ children: [
246
+ searchable && /* @__PURE__ */ jsx(
247
+ "input",
248
+ {
249
+ type: "text",
250
+ className: treeSelectSearchClasses,
251
+ placeholder: resolveLocaleText(
252
+ "Search...",
253
+ mergedLocale?.common?.searchPlaceholder
254
+ ),
255
+ value: searchQuery,
256
+ "aria-label": resolveLocaleText(
257
+ "Search tree",
258
+ mergedLocale?.common?.searchPlaceholder
259
+ ),
260
+ onChange: (e) => updateSearchValue(e.target.value)
261
+ }
262
+ ),
263
+ visibleNodes.length > 0 ? visibleNodes.map((flatNode) => {
264
+ const { node, level, hasChildren, isExpanded } = flatNode;
265
+ const selected = isSelected(node.key);
266
+ const indent = level * 20;
267
+ return /* @__PURE__ */ jsxs(
268
+ "div",
255
269
  {
256
- className: classNames(
257
- "inline-flex items-center justify-center w-4 h-4 mr-1 transition-transform",
258
- isExpanded ? "rotate-90" : ""
259
- ),
260
- onClick: (e) => toggleExpand(node.key, e),
261
- children: /* @__PURE__ */ jsx("svg", { className: "w-3 h-3", viewBox: icon20ViewBox, fill: "currentColor", children: /* @__PURE__ */ jsx(
262
- "path",
263
- {
264
- d: chevronRightSolidIcon20PathD,
265
- fillRule: "evenodd",
266
- clipRule: "evenodd"
267
- }
268
- ) })
269
- }
270
- ) : /* @__PURE__ */ jsx("span", { className: "w-4 mr-1" }),
271
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: node.label })
272
- ]
273
- },
274
- String(node.key)
275
- );
276
- }) : /* @__PURE__ */ jsx("div", { className: treeSelectEmptyClasses, children: resolveLocaleText("No data", emptyText, mergedLocale?.common?.emptyText) })
277
- ] })
270
+ ...getPickerOptionAria({ selected, disabled: !!node.disabled }),
271
+ className: getTreeSelectNodeClasses(selected, !!node.disabled, size),
272
+ style: { paddingLeft: `${indent + 8}px` },
273
+ onClick: (e) => {
274
+ e.stopPropagation();
275
+ handleNodeSelect(node);
276
+ },
277
+ children: [
278
+ hasChildren ? /* @__PURE__ */ jsx(
279
+ "span",
280
+ {
281
+ className: classNames(
282
+ "inline-flex items-center justify-center w-4 h-4 mr-1 transition-transform",
283
+ isExpanded ? "rotate-90" : ""
284
+ ),
285
+ onClick: (e) => toggleExpand(node.key, e),
286
+ children: /* @__PURE__ */ jsx("svg", { className: "w-3 h-3", viewBox: icon20ViewBox, fill: "currentColor", children: /* @__PURE__ */ jsx(
287
+ "path",
288
+ {
289
+ d: chevronRightSolidIcon20PathD,
290
+ fillRule: "evenodd",
291
+ clipRule: "evenodd"
292
+ }
293
+ ) })
294
+ }
295
+ ) : /* @__PURE__ */ jsx("span", { className: "w-4 mr-1" }),
296
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: node.label })
297
+ ]
298
+ },
299
+ String(node.key)
300
+ );
301
+ }) : /* @__PURE__ */ jsx("div", { className: treeSelectEmptyClasses, children: resolveLocaleText("No data", emptyText, mergedLocale?.common?.emptyText) })
302
+ ]
303
+ }
304
+ ) : null,
305
+ overlay.target
306
+ )
278
307
  ] });
279
308
  };
280
309
 
@@ -1,6 +1,10 @@
1
1
  import {
2
2
  useControlledState
3
3
  } from "./chunk-MEFARVQI.mjs";
4
+ import {
5
+ renderOverlayPortal,
6
+ useAnchoredOverlay
7
+ } from "./chunk-HKAZXG74.mjs";
4
8
  import {
5
9
  useTigerConfig
6
10
  } from "./chunk-YSIXURBW.mjs";
@@ -316,19 +320,6 @@ function useTimePickerState(allProps) {
316
320
  const handleInputClick = () => {
317
321
  togglePanel();
318
322
  };
319
- useEffect(() => {
320
- const handleClickOutside = (event) => {
321
- if (panelRef.current && inputWrapperRef.current && !panelRef.current.contains(event.target) && !inputWrapperRef.current.contains(event.target)) {
322
- closePanel();
323
- }
324
- };
325
- if (isOpen) {
326
- document.addEventListener("click", handleClickOutside);
327
- return () => {
328
- document.removeEventListener("click", handleClickOutside);
329
- };
330
- }
331
- }, [isOpen]);
332
323
  useEffect(() => {
333
324
  if (!isOpen) return;
334
325
  const panel = panelRef.current;
@@ -599,6 +590,17 @@ var Icon = ({ path, className }) => /* @__PURE__ */ jsx3(
599
590
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
600
591
  var TimePicker = (allProps) => {
601
592
  const ctx = useTimePickerState(allProps);
593
+ const overlay = useAnchoredOverlay({
594
+ enabled: ctx.isOpen,
595
+ referenceRef: ctx.inputWrapperRef,
596
+ floatingRef: ctx.panelRef,
597
+ placement: "bottom-start",
598
+ offset: 4,
599
+ layout: "bottom-sheet-sm",
600
+ dismissOnOutside: true,
601
+ dismissOnEscape: true,
602
+ onDismiss: ctx.closePanel
603
+ });
602
604
  return /* @__PURE__ */ jsxs3("div", { className: ctx.containerClasses, ...ctx.divProps, children: [
603
605
  /* @__PURE__ */ jsxs3("div", { ref: ctx.inputWrapperRef, className: timePickerInputWrapperClasses, children: [
604
606
  /* @__PURE__ */ jsx4(
@@ -640,55 +642,60 @@ var TimePicker = (allProps) => {
640
642
  }
641
643
  )
642
644
  ] }),
643
- ctx.isOpen && /* @__PURE__ */ jsxs3(
644
- "div",
645
- {
646
- ref: ctx.panelRef,
647
- className: timePickerPanelClasses,
648
- role: "dialog",
649
- "aria-label": ctx.labels.dialog,
650
- onKeyDown: ctx.handlePanelKeyDown,
651
- children: [
652
- ctx.isRangeMode && /* @__PURE__ */ jsxs3("div", { className: timePickerRangeHeaderClasses, children: [
653
- /* @__PURE__ */ jsx4(
654
- "button",
655
- {
656
- type: "button",
657
- className: getTimePickerRangeTabButtonClasses(ctx.activePart === "start"),
658
- onClick: () => ctx.setActivePart("start"),
659
- "aria-label": ctx.labels.start,
660
- "aria-selected": ctx.activePart === "start",
661
- children: ctx.labels.start
662
- }
663
- ),
664
- /* @__PURE__ */ jsx4(
665
- "button",
666
- {
667
- type: "button",
668
- className: getTimePickerRangeTabButtonClasses(ctx.activePart === "end"),
669
- onClick: () => ctx.setActivePart("end"),
670
- "aria-label": ctx.labels.end,
671
- "aria-selected": ctx.activePart === "end",
672
- children: ctx.labels.end
673
- }
674
- )
675
- ] }),
676
- renderTimePickerMobile(ctx),
677
- renderTimePickerDesktop(ctx),
678
- /* @__PURE__ */ jsxs3("div", { className: timePickerFooterClasses, children: [
679
- /* @__PURE__ */ jsx4("button", { type: "button", className: timePickerFooterButtonClasses, onClick: ctx.setNow, children: ctx.labels.now }),
680
- /* @__PURE__ */ jsx4(
681
- "button",
682
- {
683
- type: "button",
684
- className: timePickerFooterButtonClasses,
685
- onClick: ctx.closePanel,
686
- children: ctx.labels.ok
687
- }
688
- )
689
- ] })
690
- ]
691
- }
645
+ renderOverlayPortal(
646
+ ctx.isOpen ? /* @__PURE__ */ jsxs3(
647
+ "div",
648
+ {
649
+ ref: ctx.panelRef,
650
+ className: `${timePickerPanelClasses} ${overlay.floatingClasses}`,
651
+ style: overlay.floatingStyles,
652
+ "data-positioned": overlay.positioned,
653
+ role: "dialog",
654
+ "aria-label": ctx.labels.dialog,
655
+ onKeyDown: ctx.handlePanelKeyDown,
656
+ children: [
657
+ ctx.isRangeMode && /* @__PURE__ */ jsxs3("div", { className: timePickerRangeHeaderClasses, children: [
658
+ /* @__PURE__ */ jsx4(
659
+ "button",
660
+ {
661
+ type: "button",
662
+ className: getTimePickerRangeTabButtonClasses(ctx.activePart === "start"),
663
+ onClick: () => ctx.setActivePart("start"),
664
+ "aria-label": ctx.labels.start,
665
+ "aria-selected": ctx.activePart === "start",
666
+ children: ctx.labels.start
667
+ }
668
+ ),
669
+ /* @__PURE__ */ jsx4(
670
+ "button",
671
+ {
672
+ type: "button",
673
+ className: getTimePickerRangeTabButtonClasses(ctx.activePart === "end"),
674
+ onClick: () => ctx.setActivePart("end"),
675
+ "aria-label": ctx.labels.end,
676
+ "aria-selected": ctx.activePart === "end",
677
+ children: ctx.labels.end
678
+ }
679
+ )
680
+ ] }),
681
+ renderTimePickerMobile(ctx),
682
+ renderTimePickerDesktop(ctx),
683
+ /* @__PURE__ */ jsxs3("div", { className: timePickerFooterClasses, children: [
684
+ /* @__PURE__ */ jsx4("button", { type: "button", className: timePickerFooterButtonClasses, onClick: ctx.setNow, children: ctx.labels.now }),
685
+ /* @__PURE__ */ jsx4(
686
+ "button",
687
+ {
688
+ type: "button",
689
+ className: timePickerFooterButtonClasses,
690
+ onClick: ctx.closePanel,
691
+ children: ctx.labels.ok
692
+ }
693
+ )
694
+ ] })
695
+ ]
696
+ }
697
+ ) : null,
698
+ overlay.target
692
699
  )
693
700
  ] });
694
701
  };