@expcat/tigercat-react 2.0.19 → 2.1.0

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 (82) hide show
  1. package/README.md +25 -16
  2. package/dist/chunk-2YOP55OF.mjs +639 -0
  3. package/dist/{chunk-V6P7ZK6O.mjs → chunk-7EMCZVJ2.mjs} +1 -1
  4. package/dist/chunk-EW43YBPV.mjs +457 -0
  5. package/dist/{chunk-QJE3MZBO.mjs → chunk-FSMJLJFL.mjs} +1 -1
  6. package/dist/{chunk-BOGOQ44C.mjs → chunk-GCY55TBC.mjs} +1 -1
  7. package/dist/chunk-GR3Y3XWP.mjs +47 -0
  8. package/dist/chunk-IGBQGR6G.mjs +234 -0
  9. package/dist/{chunk-D33BIMGK.mjs → chunk-IR7VA6AO.mjs} +11 -1
  10. package/dist/chunk-J76R2S62.mjs +161 -0
  11. package/dist/{chunk-2WGEHH5A.mjs → chunk-JQJM65RJ.mjs} +1 -1
  12. package/dist/{chunk-7AFRHC7P.mjs → chunk-KC55B62J.mjs} +127 -42
  13. package/dist/chunk-KRDHM5KB.mjs +259 -0
  14. package/dist/chunk-M5MZWOHF.mjs +180 -0
  15. package/dist/chunk-MFPVVGNA.mjs +248 -0
  16. package/dist/chunk-NLGLBTSM.mjs +138 -0
  17. package/dist/chunk-NT7GW2FD.mjs +40 -0
  18. package/dist/chunk-OKYMTHFQ.mjs +279 -0
  19. package/dist/{chunk-HHIW7V7B.mjs → chunk-PFL4HNWM.mjs} +1 -8
  20. package/dist/chunk-RUAPTIQ7.mjs +181 -0
  21. package/dist/chunk-SEOG5AGS.mjs +72 -0
  22. package/dist/chunk-TQ6RIFWR.mjs +135 -0
  23. package/dist/chunk-U4M3DC2P.mjs +48 -0
  24. package/dist/{chunk-YIB6ZXZF.mjs → chunk-UETARXIK.mjs} +239 -52
  25. package/dist/chunk-XT43B7ZI.mjs +58 -0
  26. package/dist/components/ActivityFeed.mjs +1 -1
  27. package/dist/components/AreaChart.mjs +2 -2
  28. package/dist/components/AspectRatio.d.mts +10 -0
  29. package/dist/components/AspectRatio.mjs +8 -0
  30. package/dist/components/BarChart.mjs +2 -2
  31. package/dist/components/Cascader.mjs +1 -1
  32. package/dist/components/ChatWindow.mjs +1 -1
  33. package/dist/components/ContextMenu.d.mts +36 -0
  34. package/dist/components/ContextMenu.mjs +17 -0
  35. package/dist/components/DataExport.mjs +1 -1
  36. package/dist/components/DataTableWithToolbar.mjs +5 -5
  37. package/dist/components/Highlight.d.mts +11 -0
  38. package/dist/components/Highlight.mjs +8 -0
  39. package/dist/components/ImageCompare.d.mts +15 -0
  40. package/dist/components/ImageCompare.mjs +8 -0
  41. package/dist/components/InputOTP.d.mts +33 -0
  42. package/dist/components/InputOTP.mjs +12 -0
  43. package/dist/components/Kbd.d.mts +10 -0
  44. package/dist/components/Kbd.mjs +8 -0
  45. package/dist/components/LineChart.mjs +2 -2
  46. package/dist/components/List.mjs +2 -2
  47. package/dist/components/LoadingBar.d.mts +8 -0
  48. package/dist/components/LoadingBar.mjs +138 -0
  49. package/dist/components/LoadingBarContainer.d.mts +8 -0
  50. package/dist/components/LoadingBarContainer.mjs +8 -0
  51. package/dist/components/LoadingBarRoot.d.mts +6 -0
  52. package/dist/components/LoadingBarRoot.mjs +6 -0
  53. package/dist/components/Marquee.d.mts +10 -0
  54. package/dist/components/Marquee.mjs +8 -0
  55. package/dist/components/MaskInput.d.mts +37 -0
  56. package/dist/components/MaskInput.mjs +10 -0
  57. package/dist/components/Masonry.d.mts +10 -0
  58. package/dist/components/Masonry.mjs +8 -0
  59. package/dist/components/NavigationMenu.d.mts +84 -0
  60. package/dist/components/NavigationMenu.mjs +23 -0
  61. package/dist/components/NotificationCenter.mjs +3 -3
  62. package/dist/components/PageHeader.d.mts +34 -0
  63. package/dist/components/PageHeader.mjs +11 -0
  64. package/dist/components/Pagination.mjs +1 -1
  65. package/dist/components/RadarChart.mjs +2 -2
  66. package/dist/components/ScatterChart.mjs +2 -2
  67. package/dist/components/ScrollArea.d.mts +10 -0
  68. package/dist/components/ScrollArea.mjs +8 -0
  69. package/dist/components/SplitButton.d.mts +38 -0
  70. package/dist/components/SplitButton.mjs +12 -0
  71. package/dist/components/Table.mjs +2 -2
  72. package/dist/components/TagsInput.d.mts +41 -0
  73. package/dist/components/TagsInput.mjs +13 -0
  74. package/dist/components/TreeSelect.mjs +2 -1
  75. package/dist/index.d.mts +17 -1
  76. package/dist/index.mjs +355 -0
  77. package/package.json +117 -2
  78. package/dist/{chunk-NCHUEGUW.mjs → chunk-H6MVW5YD.mjs} +3 -3
  79. package/dist/{chunk-UT5BV2VO.mjs → chunk-I4MWOYJS.mjs} +3 -3
  80. package/dist/{chunk-E7OTDBI6.mjs → chunk-NWVNTZOP.mjs} +3 -3
  81. package/dist/{chunk-FYINJRYN.mjs → chunk-RQ4PUK6G.mjs} +3 -3
  82. package/dist/{chunk-KMP5CVNK.mjs → chunk-UKY2EPS3.mjs} +3 -3
package/README.md CHANGED
@@ -17,7 +17,7 @@ pnpm add @expcat/tigercat-react
17
17
  npm install @expcat/tigercat-react
18
18
  ```
19
19
 
20
- **Requirements:** React 19, Tailwind CSS ≥3.4
20
+ **Requirements:** React / React DOM 19.x, Tailwind CSS 4.x, Node.js 22.13.0
21
21
 
22
22
  ## Quick Start
23
23
 
@@ -35,24 +35,33 @@ function App() {
35
35
 
36
36
  ## Components
37
37
 
38
- | Category | Components |
39
- | -------------- | ------------------------------------------------------------------------------------- |
40
- | **Basic** | Alert, Avatar, Badge, Button, Code, Divider, Icon, Link, Tag, Text |
41
- | **Form** | Input, Select, Checkbox, Radio, Switch, Slider, DatePicker, TimePicker, Upload, Form |
42
- | **Layout** | Card, Container, Grid (Row/Col), Layout, List, Descriptions, Skeleton, Space |
43
- | **Navigation** | Menu, Tabs, Breadcrumb, Pagination, Steps, Dropdown, Tree |
44
- | **Feedback** | Modal, Drawer, Message, Notification, Loading, Popconfirm, Popover, Tooltip, Progress |
45
- | **Data** | Table, Timeline |
46
- | **Charts** | BarChart, LineChart, AreaChart, PieChart, DonutChart, RadarChart, ScatterChart |
38
+ 172 public component entries across 9 categories. The authoritative list with
39
+ import subpaths lives in
40
+ [component-index.md](https://github.com/expcat/Tigercat/blob/main/skills/tigercat/references/component-index.md)
41
+ (generated); the table below is only a sampler.
42
+
43
+ | Category | Count | Examples |
44
+ | -------------- | ----- | ------------------------------------------------------------- |
45
+ | **Basic** | 30 | Button, Alert, Avatar, Badge, Icon, Tag, Text, Result, QRCode |
46
+ | **Form** | 31 | Input, Select, DatePicker, Form, Upload, InputOTP, TagsInput |
47
+ | **Layout** | 19 | Card, Row/Col, Layout, List, Descriptions, Skeleton, Space |
48
+ | **Navigation** | 33 | Menu, Tabs, Breadcrumb, Pagination, Steps, Dropdown, Tree |
49
+ | **Feedback** | 13 | Modal, Drawer, Message, Popover, Tooltip, Progress, Tour |
50
+ | **Data** | 7 | Table, Calendar, Collapse, Timeline, DataExport |
51
+ | **Charts** | 20 | BarChart, LineChart, PieChart, RadarChart, GaugeChart, Gantt |
52
+ | **Advanced** | 12 | VirtualTable, VirtualList, RichTextEditor, CodeEditor |
53
+ | **Composite** | 7 | DataTableWithToolbar, ChatWindow, FormWizard, TaskBoard |
54
+
55
+ `Message` and `notification` are also available as imperative command APIs from
56
+ the package root; `notification` is a command API, not a component.
47
57
 
48
58
  ## Hooks
49
59
 
50
- - `useChartInteraction` - Chart interaction utilities
51
- - `useFormContext` - Form state management
52
- - `useMenuContext` - Menu state access
53
- - `useTabsContext` - Tabs state access
54
- - `useBreadcrumbContext` - Breadcrumb navigation
55
- - `useStepsContext` - Steps state access
60
+ `useTigerConfig`, `useControlledState`, `useDrag`, `useChartInteraction`,
61
+ `useFormController`, plus the component context hooks `useFormContext`,
62
+ `useMenuContext`, `useTabsContext`, `useCollapseContext`, `useAnchorContext`,
63
+ `useBreadcrumbContext` and `useStepsContext`. Signatures are listed in
64
+ [api-summary.md](https://github.com/expcat/Tigercat/blob/main/skills/tigercat/references/shared/api-summary.md).
56
65
 
57
66
  ## License
58
67
 
@@ -0,0 +1,639 @@
1
+ import {
2
+ renderOverlayPortal,
3
+ useAnchoredOverlay
4
+ } from "./chunk-HKAZXG74.mjs";
5
+
6
+ // src/components/NavigationMenu.tsx
7
+ import React, {
8
+ createContext,
9
+ useContext,
10
+ useState,
11
+ useEffect,
12
+ useRef,
13
+ useCallback,
14
+ useMemo,
15
+ useId
16
+ } from "react";
17
+ import {
18
+ classNames,
19
+ getNavigationMenuClasses,
20
+ getNavigationMenuListClasses,
21
+ getNavigationMenuItemClasses,
22
+ getNavigationMenuTriggerClasses,
23
+ getNavigationMenuChevronClasses,
24
+ getNavigationMenuContentClasses,
25
+ getNavigationMenuLinkClasses,
26
+ injectNavigationMenuStyles,
27
+ NAVIGATION_MENU_ENTER_CLASS,
28
+ NAVIGATION_MENU_CHEVRON_PATH,
29
+ NAVIGATION_MENU_BAR_ITEM_ATTR,
30
+ NAVIGATION_MENU_DEFAULT_DELAY_DURATION,
31
+ NAVIGATION_MENU_DEFAULT_SKIP_DELAY_DURATION,
32
+ NAVIGATION_MENU_DEFAULT_OFFSET,
33
+ isNavigationMenuValueOpen,
34
+ isNavigationMenuOpen,
35
+ resolveNavigationMenuOpenValue,
36
+ shouldSkipNavigationMenuOpenDelay,
37
+ isNavigationMenuTriggerOpenKey,
38
+ handleMenubarNavigation,
39
+ handleMenuNavigation,
40
+ initNavigationMenuRovingTabIndex,
41
+ focusFirstMenuItem,
42
+ captureActiveElement,
43
+ restoreFocus,
44
+ getSecureRel
45
+ } from "@expcat/tigercat-core";
46
+ import { jsx, jsxs } from "react/jsx-runtime";
47
+ function containsFocusTarget(container, target) {
48
+ return Boolean(container && target instanceof Node && container.contains(target));
49
+ }
50
+ function getOpenPanelFromMenubar(menubar) {
51
+ if (!menubar) return null;
52
+ const trigger = menubar.querySelector('[aria-expanded="true"][aria-controls]');
53
+ const contentId = trigger?.getAttribute("aria-controls");
54
+ if (!contentId) return null;
55
+ return menubar.ownerDocument.getElementById(contentId);
56
+ }
57
+ var NavigationMenuContext = createContext(null);
58
+ var NavigationMenuItemContext = createContext(null);
59
+ var NavigationMenuContentContext = createContext(
60
+ null
61
+ );
62
+ var NavigationMenuLink = ({
63
+ href,
64
+ target,
65
+ rel,
66
+ disabled = false,
67
+ active = false,
68
+ className,
69
+ style,
70
+ onClick,
71
+ children
72
+ }) => {
73
+ const root = useContext(NavigationMenuContext);
74
+ const item = useContext(NavigationMenuItemContext);
75
+ const content = useContext(NavigationMenuContentContext);
76
+ const inPanel = Boolean(content);
77
+ const isDisabled = disabled || Boolean(item?.disabled);
78
+ const handleClick = (event) => {
79
+ if (isDisabled) {
80
+ event.preventDefault();
81
+ event.stopPropagation();
82
+ return;
83
+ }
84
+ onClick?.(event);
85
+ root?.handleItemClick();
86
+ };
87
+ const handleFocus = () => {
88
+ if (inPanel) return;
89
+ if (!item?.hasPanel) {
90
+ root?.setValue(null, { restoreFocus: false });
91
+ }
92
+ };
93
+ const handleKeyDown = (event) => {
94
+ if (inPanel) return;
95
+ if (root?.menubarRef.current) {
96
+ handleMenubarNavigation(root.menubarRef.current, event.nativeEvent);
97
+ }
98
+ };
99
+ const linkClasses = classNames(
100
+ getNavigationMenuLinkClasses(isDisabled, inPanel, active),
101
+ className
102
+ );
103
+ const computedRel = href ? getSecureRel(target, rel) : void 0;
104
+ const shared = {
105
+ className: linkClasses,
106
+ style,
107
+ role: "menuitem",
108
+ tabIndex: -1,
109
+ [NAVIGATION_MENU_BAR_ITEM_ATTR]: inPanel ? void 0 : "",
110
+ "aria-disabled": isDisabled || void 0,
111
+ "aria-current": active ? "page" : void 0,
112
+ "data-tiger-navigation-menu-link": "",
113
+ "data-active": active ? "true" : void 0,
114
+ onClick: handleClick,
115
+ onFocus: handleFocus,
116
+ onKeyDown: handleKeyDown
117
+ };
118
+ if (href) {
119
+ return /* @__PURE__ */ jsx("a", { href, target, rel: computedRel, ...shared, children });
120
+ }
121
+ return /* @__PURE__ */ jsx("button", { type: "button", disabled: isDisabled, ...shared, children });
122
+ };
123
+ var NavigationMenuTrigger = ({
124
+ disabled = false,
125
+ showArrow,
126
+ className,
127
+ style,
128
+ children
129
+ }) => {
130
+ const root = useContext(NavigationMenuContext);
131
+ const item = useContext(NavigationMenuItemContext);
132
+ const isDisabled = disabled || Boolean(item?.disabled) || Boolean(root?.disabled);
133
+ const arrow = showArrow !== void 0 ? showArrow : item?.showArrow ?? true;
134
+ const handleMouseEnter = () => {
135
+ if (isDisabled) return;
136
+ item?.scheduleOpen();
137
+ };
138
+ const handleMouseLeave = () => {
139
+ item?.scheduleClose();
140
+ };
141
+ const handleFocus = () => {
142
+ if (isDisabled || root?.isFocusOpenSuppressed()) return;
143
+ item?.open();
144
+ };
145
+ const handleClick = (event) => {
146
+ if (isDisabled) {
147
+ event.preventDefault();
148
+ return;
149
+ }
150
+ item?.open();
151
+ };
152
+ const handleKeyDown = (event) => {
153
+ if (isDisabled || !item) return;
154
+ if (root?.menubarRef.current && handleMenubarNavigation(root.menubarRef.current, event.nativeEvent)) {
155
+ return;
156
+ }
157
+ if (isNavigationMenuTriggerOpenKey(event.key) && item.hasPanel) {
158
+ event.preventDefault();
159
+ item.open(true);
160
+ return;
161
+ }
162
+ if (event.key === "Escape" && item.isOpen) {
163
+ event.preventDefault();
164
+ item.close();
165
+ item.triggerRef.current?.focus();
166
+ }
167
+ };
168
+ if (!item) return null;
169
+ const triggerClasses = classNames(
170
+ getNavigationMenuTriggerClasses(isDisabled, item.isOpen),
171
+ className
172
+ );
173
+ return /* @__PURE__ */ jsxs(
174
+ "button",
175
+ {
176
+ ref: item.triggerRef,
177
+ type: "button",
178
+ className: triggerClasses,
179
+ style,
180
+ role: "menuitem",
181
+ tabIndex: -1,
182
+ ...{ [NAVIGATION_MENU_BAR_ITEM_ATTR]: "" },
183
+ "aria-haspopup": "menu",
184
+ "aria-expanded": item.isOpen,
185
+ "aria-controls": item.isOpen ? item.contentId : void 0,
186
+ "aria-disabled": isDisabled || void 0,
187
+ disabled: isDisabled,
188
+ "data-state": item.isOpen ? "open" : "closed",
189
+ "data-tiger-navigation-menu-trigger": "",
190
+ onMouseEnter: handleMouseEnter,
191
+ onMouseLeave: handleMouseLeave,
192
+ onFocus: handleFocus,
193
+ onClick: handleClick,
194
+ onKeyDown: handleKeyDown,
195
+ children: [
196
+ children,
197
+ arrow ? /* @__PURE__ */ jsx(
198
+ "svg",
199
+ {
200
+ className: getNavigationMenuChevronClasses(item.isOpen),
201
+ viewBox: "0 0 24 24",
202
+ fill: "none",
203
+ stroke: "currentColor",
204
+ strokeWidth: "2",
205
+ strokeLinecap: "round",
206
+ strokeLinejoin: "round",
207
+ "aria-hidden": "true",
208
+ children: /* @__PURE__ */ jsx("path", { d: NAVIGATION_MENU_CHEVRON_PATH })
209
+ }
210
+ ) : null
211
+ ]
212
+ }
213
+ );
214
+ };
215
+ var NavigationMenuContent = ({
216
+ mega = false,
217
+ className,
218
+ style,
219
+ children,
220
+ ...divProps
221
+ }) => {
222
+ const root = useContext(NavigationMenuContext);
223
+ const item = useContext(NavigationMenuItemContext);
224
+ const triggerRef = useRef(null);
225
+ const floatingRef = useRef(null);
226
+ const referenceRef = item?.triggerRef ?? triggerRef;
227
+ const contentRef = item?.contentRef ?? floatingRef;
228
+ const isOpen = Boolean(item?.isOpen);
229
+ const portalEnabled = Boolean(root?.portal);
230
+ useEffect(() => {
231
+ if (!item) return;
232
+ item.setHasPanel(true);
233
+ return () => item.setHasPanel(false);
234
+ }, [item]);
235
+ const overlay = useAnchoredOverlay({
236
+ referenceRef,
237
+ floatingRef: contentRef,
238
+ enabled: Boolean(item) && isOpen && !item?.disabled,
239
+ placement: root?.placement ?? "bottom-start",
240
+ offset: root?.offset ?? NAVIGATION_MENU_DEFAULT_OFFSET,
241
+ portal: portalEnabled,
242
+ dismissOnOutside: true,
243
+ dismissOnEscape: true,
244
+ onDismiss: () => item?.close()
245
+ });
246
+ const handleMouseEnter = () => {
247
+ item?.cancelClose();
248
+ };
249
+ const handleMouseLeave = () => {
250
+ item?.scheduleClose();
251
+ };
252
+ const handleFocusOut = (event) => {
253
+ root?.handleFocusLeave(event);
254
+ };
255
+ const handleKeyDown = (event) => {
256
+ if (contentRef.current) {
257
+ handleMenuNavigation(contentRef.current, event.nativeEvent);
258
+ }
259
+ if (event.key === "Escape" || event.key === "ArrowLeft") {
260
+ event.preventDefault();
261
+ event.stopPropagation();
262
+ item?.close();
263
+ item?.triggerRef.current?.focus();
264
+ return;
265
+ }
266
+ if (event.key === "ArrowRight" && root?.menubarRef.current && item?.triggerRef.current) {
267
+ item.triggerRef.current.focus();
268
+ handleMenubarNavigation(root.menubarRef.current, event.nativeEvent);
269
+ }
270
+ };
271
+ if (!item || !root) return null;
272
+ const popup = /* @__PURE__ */ jsx(
273
+ "div",
274
+ {
275
+ ref: contentRef,
276
+ className: classNames(overlay.floatingClasses, NAVIGATION_MENU_ENTER_CLASS),
277
+ style: overlay.floatingStyles,
278
+ "data-positioned": overlay.positioned,
279
+ "data-tiger-navigation-menu-content": "",
280
+ hidden: !isOpen,
281
+ onMouseEnter: handleMouseEnter,
282
+ onMouseLeave: handleMouseLeave,
283
+ onBlur: handleFocusOut,
284
+ onKeyDown: handleKeyDown,
285
+ children: /* @__PURE__ */ jsx(
286
+ "div",
287
+ {
288
+ ...divProps,
289
+ id: item.contentId,
290
+ className: classNames(getNavigationMenuContentClasses(mega), className),
291
+ style,
292
+ role: mega ? "group" : "menu",
293
+ children
294
+ }
295
+ )
296
+ }
297
+ );
298
+ return /* @__PURE__ */ jsx(NavigationMenuContentContext.Provider, { value: { inPanel: true }, children: renderOverlayPortal(popup, overlay.target, !portalEnabled) });
299
+ };
300
+ var NavigationMenuItem = ({
301
+ value: valueProp,
302
+ disabled = false,
303
+ className,
304
+ style,
305
+ children
306
+ }) => {
307
+ const root = useContext(NavigationMenuContext);
308
+ const reactId = useId();
309
+ const autoValue = useMemo(() => `tiger-navigation-menu-item-${reactId}`, [reactId]);
310
+ const itemValue = valueProp ?? autoValue;
311
+ const triggerRef = useRef(null);
312
+ const contentRef = useRef(null);
313
+ const [hasPanel, setHasPanel] = useState(false);
314
+ const isOpen = Boolean(root && !disabled && isNavigationMenuValueOpen(itemValue, root.value));
315
+ const contentId = `${autoValue}-content`;
316
+ const open = useCallback(
317
+ (focusPanel = false) => {
318
+ if (disabled || !root) return;
319
+ root.cancelClose();
320
+ root.setValue(itemValue);
321
+ if (!focusPanel) return;
322
+ requestAnimationFrame(() => {
323
+ const panel = contentRef.current ?? document.getElementById(contentId);
324
+ if (panel) focusFirstMenuItem(panel);
325
+ });
326
+ },
327
+ [contentId, disabled, itemValue, root]
328
+ );
329
+ const close = useCallback(() => {
330
+ if (!root) return;
331
+ if (isOpen) root.setValue(null);
332
+ }, [isOpen, root]);
333
+ const scheduleOpen = useCallback(() => {
334
+ if (disabled || !root) return;
335
+ root.scheduleOpen(itemValue);
336
+ }, [disabled, itemValue, root]);
337
+ const scheduleClose = useCallback(() => {
338
+ root?.scheduleClose(itemValue);
339
+ }, [itemValue, root]);
340
+ const cancelClose = useCallback(() => {
341
+ root?.cancelClose();
342
+ }, [root]);
343
+ const itemContext = useMemo(
344
+ () => ({
345
+ value: itemValue,
346
+ isOpen,
347
+ disabled,
348
+ hasPanel,
349
+ setHasPanel,
350
+ triggerRef,
351
+ contentRef,
352
+ contentId,
353
+ open,
354
+ close,
355
+ scheduleOpen,
356
+ scheduleClose,
357
+ cancelClose,
358
+ showArrow: root?.showArrow ?? true
359
+ }),
360
+ [
361
+ autoValue,
362
+ cancelClose,
363
+ close,
364
+ disabled,
365
+ hasPanel,
366
+ isOpen,
367
+ itemValue,
368
+ open,
369
+ root?.showArrow,
370
+ scheduleClose,
371
+ scheduleOpen
372
+ ]
373
+ );
374
+ return /* @__PURE__ */ jsx(NavigationMenuItemContext.Provider, { value: itemContext, children: /* @__PURE__ */ jsx(
375
+ "li",
376
+ {
377
+ className: classNames(getNavigationMenuItemClasses(), className),
378
+ style,
379
+ role: "none",
380
+ "data-tiger-navigation-menu-item": "",
381
+ "data-state": isOpen ? "open" : "closed",
382
+ children
383
+ }
384
+ ) });
385
+ };
386
+ var NavigationMenuList = ({
387
+ className,
388
+ style,
389
+ children,
390
+ ...ulProps
391
+ }) => {
392
+ const root = useContext(NavigationMenuContext);
393
+ const listRef = useRef(null);
394
+ const setListRef = useCallback(
395
+ (node) => {
396
+ listRef.current = node;
397
+ if (root) {
398
+ ;
399
+ root.menubarRef.current = node;
400
+ }
401
+ },
402
+ [root]
403
+ );
404
+ useEffect(() => {
405
+ if (listRef.current) initNavigationMenuRovingTabIndex(listRef.current);
406
+ });
407
+ return /* @__PURE__ */ jsx(
408
+ "ul",
409
+ {
410
+ ...ulProps,
411
+ ref: setListRef,
412
+ className: classNames(getNavigationMenuListClasses(), className),
413
+ style,
414
+ role: "menubar",
415
+ "data-tiger-navigation-menu-list": "",
416
+ children
417
+ }
418
+ );
419
+ };
420
+ var NavigationMenu = ({
421
+ value: controlledValue,
422
+ defaultValue,
423
+ open: controlledOpen,
424
+ defaultOpen = false,
425
+ disabled = false,
426
+ closeOnClick = true,
427
+ delayDuration = NAVIGATION_MENU_DEFAULT_DELAY_DURATION,
428
+ skipDelayDuration = NAVIGATION_MENU_DEFAULT_SKIP_DELAY_DURATION,
429
+ showArrow = true,
430
+ portal = true,
431
+ offset = NAVIGATION_MENU_DEFAULT_OFFSET,
432
+ placement = "bottom-start",
433
+ className,
434
+ style,
435
+ onValueChange,
436
+ onOpenChange,
437
+ children,
438
+ ...navProps
439
+ }) => {
440
+ const initialValue = defaultValue ?? (defaultOpen ? controlledValue ?? null : null);
441
+ const [internalValue, setInternalValue] = useState(
442
+ isNavigationMenuOpen(initialValue) ? initialValue : null
443
+ );
444
+ const rootRef = useRef(null);
445
+ const menubarRef = useRef(null);
446
+ const previousActiveElementRef = useRef(null);
447
+ const openTimerRef = useRef(null);
448
+ const closeTimerRef = useRef(null);
449
+ const lastOpenAtRef = useRef(0);
450
+ const suppressFocusOpenRef = useRef(false);
451
+ const currentValue = resolveNavigationMenuOpenValue({
452
+ value: controlledValue,
453
+ internalValue,
454
+ open: controlledOpen
455
+ });
456
+ const currentValueRef = useRef(currentValue);
457
+ currentValueRef.current = currentValue;
458
+ const currentOpen = isNavigationMenuOpen(currentValue);
459
+ useEffect(() => {
460
+ injectNavigationMenuStyles();
461
+ }, []);
462
+ const clearTimers = useCallback(() => {
463
+ if (openTimerRef.current) {
464
+ clearTimeout(openTimerRef.current);
465
+ openTimerRef.current = null;
466
+ }
467
+ if (closeTimerRef.current) {
468
+ clearTimeout(closeTimerRef.current);
469
+ closeTimerRef.current = null;
470
+ }
471
+ }, []);
472
+ useEffect(() => () => clearTimers(), [clearTimers]);
473
+ const setValue = useCallback(
474
+ (next, options) => {
475
+ if (disabled && next != null) return;
476
+ clearTimers();
477
+ const resolvedNext = isNavigationMenuOpen(next) ? next : null;
478
+ const wasOpen = isNavigationMenuOpen(currentValueRef.current);
479
+ const willOpen = resolvedNext != null;
480
+ if (willOpen && !wasOpen) {
481
+ const active = captureActiveElement();
482
+ if (active && menubarRef.current?.contains(active)) {
483
+ previousActiveElementRef.current = active;
484
+ }
485
+ }
486
+ currentValueRef.current = resolvedNext;
487
+ if (controlledValue === void 0) {
488
+ setInternalValue(resolvedNext);
489
+ }
490
+ onValueChange?.(resolvedNext);
491
+ onOpenChange?.(willOpen);
492
+ if (!willOpen) {
493
+ suppressFocusOpenRef.current = true;
494
+ if (options?.restoreFocus !== false) {
495
+ restoreFocus(previousActiveElementRef.current);
496
+ }
497
+ previousActiveElementRef.current = null;
498
+ queueMicrotask(() => {
499
+ suppressFocusOpenRef.current = false;
500
+ });
501
+ }
502
+ },
503
+ [clearTimers, controlledValue, disabled, onOpenChange, onValueChange]
504
+ );
505
+ const scheduleOpen = useCallback(
506
+ (itemValue) => {
507
+ if (disabled) return;
508
+ if (closeTimerRef.current) {
509
+ clearTimeout(closeTimerRef.current);
510
+ closeTimerRef.current = null;
511
+ }
512
+ const skip = shouldSkipNavigationMenuOpenDelay(
513
+ lastOpenAtRef.current,
514
+ Date.now(),
515
+ skipDelayDuration
516
+ );
517
+ const delay = skip ? 0 : delayDuration;
518
+ const apply = () => {
519
+ lastOpenAtRef.current = Date.now();
520
+ setValue(itemValue);
521
+ openTimerRef.current = null;
522
+ };
523
+ if (delay <= 0) {
524
+ apply();
525
+ return;
526
+ }
527
+ if (openTimerRef.current) clearTimeout(openTimerRef.current);
528
+ openTimerRef.current = setTimeout(apply, delay);
529
+ },
530
+ [delayDuration, disabled, setValue, skipDelayDuration]
531
+ );
532
+ const scheduleClose = useCallback(
533
+ (itemValue) => {
534
+ if (openTimerRef.current) {
535
+ clearTimeout(openTimerRef.current);
536
+ openTimerRef.current = null;
537
+ }
538
+ const close = () => {
539
+ if (currentValueRef.current === itemValue) setValue(null);
540
+ closeTimerRef.current = null;
541
+ };
542
+ if (skipDelayDuration <= 0) {
543
+ close();
544
+ return;
545
+ }
546
+ if (closeTimerRef.current) clearTimeout(closeTimerRef.current);
547
+ closeTimerRef.current = setTimeout(close, skipDelayDuration);
548
+ },
549
+ [setValue, skipDelayDuration]
550
+ );
551
+ const cancelClose = useCallback(() => {
552
+ if (closeTimerRef.current) {
553
+ clearTimeout(closeTimerRef.current);
554
+ closeTimerRef.current = null;
555
+ }
556
+ }, []);
557
+ const handleItemClick = useCallback(() => {
558
+ if (closeOnClick) setValue(null);
559
+ }, [closeOnClick, setValue]);
560
+ const handleFocusLeave = useCallback(
561
+ (event) => {
562
+ const next = event.relatedTarget;
563
+ if (containsFocusTarget(rootRef.current, next)) return;
564
+ if (containsFocusTarget(getOpenPanelFromMenubar(menubarRef.current), next)) return;
565
+ if (!isNavigationMenuOpen(currentValueRef.current)) return;
566
+ setValue(null, { restoreFocus: false });
567
+ },
568
+ [setValue]
569
+ );
570
+ const isFocusOpenSuppressed = useCallback(() => suppressFocusOpenRef.current, []);
571
+ const contextValue = useMemo(
572
+ () => ({
573
+ value: currentValue,
574
+ setValue,
575
+ scheduleOpen,
576
+ scheduleClose,
577
+ cancelClose,
578
+ closeOnClick,
579
+ handleItemClick,
580
+ handleFocusLeave,
581
+ portal,
582
+ disabled,
583
+ offset,
584
+ placement,
585
+ showArrow,
586
+ menubarRef,
587
+ isFocusOpenSuppressed
588
+ }),
589
+ [
590
+ cancelClose,
591
+ closeOnClick,
592
+ currentValue,
593
+ disabled,
594
+ handleFocusLeave,
595
+ handleItemClick,
596
+ isFocusOpenSuppressed,
597
+ offset,
598
+ placement,
599
+ portal,
600
+ scheduleClose,
601
+ scheduleOpen,
602
+ setValue,
603
+ showArrow
604
+ ]
605
+ );
606
+ const childrenArray = React.Children.toArray(children);
607
+ const hasList = childrenArray.some(
608
+ (child) => React.isValidElement(child) && child.type === NavigationMenuList
609
+ );
610
+ return /* @__PURE__ */ jsx(NavigationMenuContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
611
+ "nav",
612
+ {
613
+ ...navProps,
614
+ ref: rootRef,
615
+ className: classNames(getNavigationMenuClasses(), className),
616
+ style,
617
+ "aria-label": navProps["aria-label"] ?? "Main",
618
+ "data-tiger-navigation-menu": "",
619
+ "data-state": currentOpen ? "open" : "closed",
620
+ onBlur: (event) => {
621
+ navProps.onBlur?.(event);
622
+ handleFocusLeave(event);
623
+ },
624
+ children: hasList ? children : /* @__PURE__ */ jsx(NavigationMenuList, { children })
625
+ }
626
+ ) });
627
+ };
628
+
629
+ export {
630
+ NavigationMenuContext,
631
+ NavigationMenuItemContext,
632
+ NavigationMenuContentContext,
633
+ NavigationMenuLink,
634
+ NavigationMenuTrigger,
635
+ NavigationMenuContent,
636
+ NavigationMenuItem,
637
+ NavigationMenuList,
638
+ NavigationMenu
639
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Table
3
- } from "./chunk-BOGOQ44C.mjs";
3
+ } from "./chunk-GCY55TBC.mjs";
4
4
  import {
5
5
  Select
6
6
  } from "./chunk-KVCI2346.mjs";