@mindlogic-ai/logician-ui 5.0.0-alpha.11 → 5.0.0-alpha.13

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 (89) hide show
  1. package/README.md +1 -0
  2. package/dist/components/Input/Input.d.ts.map +1 -1
  3. package/dist/components/Input/Input.js +4 -0
  4. package/dist/components/Input/Input.js.map +1 -1
  5. package/dist/components/Input/Input.mjs +4 -0
  6. package/dist/components/Input/Input.mjs.map +1 -1
  7. package/dist/components/NavList/NavList.d.ts +34 -0
  8. package/dist/components/NavList/NavList.d.ts.map +1 -0
  9. package/dist/components/NavList/NavList.js +113 -0
  10. package/dist/components/NavList/NavList.js.map +1 -0
  11. package/dist/components/NavList/NavList.mjs +111 -0
  12. package/dist/components/NavList/NavList.mjs.map +1 -0
  13. package/dist/components/NavList/NavList.styles.d.ts +90 -0
  14. package/dist/components/NavList/NavList.styles.d.ts.map +1 -0
  15. package/dist/components/NavList/NavList.styles.js +104 -0
  16. package/dist/components/NavList/NavList.styles.js.map +1 -0
  17. package/dist/components/NavList/NavList.styles.mjs +97 -0
  18. package/dist/components/NavList/NavList.styles.mjs.map +1 -0
  19. package/dist/components/NavList/NavList.translations.json.js +19 -0
  20. package/dist/components/NavList/NavList.translations.json.js.map +1 -0
  21. package/dist/components/NavList/NavList.translations.json.mjs +14 -0
  22. package/dist/components/NavList/NavList.translations.json.mjs.map +1 -0
  23. package/dist/components/NavList/NavList.types.d.ts +131 -0
  24. package/dist/components/NavList/NavList.types.d.ts.map +1 -0
  25. package/dist/components/NavList/NavListContext.d.ts +30 -0
  26. package/dist/components/NavList/NavListContext.d.ts.map +1 -0
  27. package/dist/components/NavList/NavListContext.js +16 -0
  28. package/dist/components/NavList/NavListContext.js.map +1 -0
  29. package/dist/components/NavList/NavListContext.mjs +13 -0
  30. package/dist/components/NavList/NavListContext.mjs.map +1 -0
  31. package/dist/components/NavList/NavListGroup.d.ts +31 -0
  32. package/dist/components/NavList/NavListGroup.d.ts.map +1 -0
  33. package/dist/components/NavList/NavListGroup.js +115 -0
  34. package/dist/components/NavList/NavListGroup.js.map +1 -0
  35. package/dist/components/NavList/NavListGroup.mjs +113 -0
  36. package/dist/components/NavList/NavListGroup.mjs.map +1 -0
  37. package/dist/components/NavList/NavListItem.d.ts +15 -0
  38. package/dist/components/NavList/NavListItem.d.ts.map +1 -0
  39. package/dist/components/NavList/NavListItem.js +269 -0
  40. package/dist/components/NavList/NavListItem.js.map +1 -0
  41. package/dist/components/NavList/NavListItem.mjs +267 -0
  42. package/dist/components/NavList/NavListItem.mjs.map +1 -0
  43. package/dist/components/NavList/NavListSkeleton.d.ts +17 -0
  44. package/dist/components/NavList/NavListSkeleton.d.ts.map +1 -0
  45. package/dist/components/NavList/NavListSkeleton.js +33 -0
  46. package/dist/components/NavList/NavListSkeleton.js.map +1 -0
  47. package/dist/components/NavList/NavListSkeleton.mjs +31 -0
  48. package/dist/components/NavList/NavListSkeleton.mjs.map +1 -0
  49. package/dist/components/NavList/index.d.ts +7 -0
  50. package/dist/components/NavList/index.d.ts.map +1 -0
  51. package/dist/components/Textarea/Textarea.d.ts.map +1 -1
  52. package/dist/components/Textarea/Textarea.js +4 -0
  53. package/dist/components/Textarea/Textarea.js.map +1 -1
  54. package/dist/components/Textarea/Textarea.mjs +4 -0
  55. package/dist/components/Textarea/Textarea.mjs.map +1 -1
  56. package/dist/index.d.ts +2 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +12 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/index.mjs +6 -1
  61. package/dist/index.mjs.map +1 -1
  62. package/dist/utils/focusRing.d.ts +22 -0
  63. package/dist/utils/focusRing.d.ts.map +1 -1
  64. package/dist/utils/focusRing.js +22 -0
  65. package/dist/utils/focusRing.js.map +1 -1
  66. package/dist/utils/focusRing.mjs +21 -1
  67. package/dist/utils/focusRing.mjs.map +1 -1
  68. package/package.json +2 -1
  69. package/src/components/Input/Input.tsx +4 -0
  70. package/src/components/Menu/Menu.usage.mdx +8 -0
  71. package/src/components/NavList/NavList.stories.tsx +895 -0
  72. package/src/components/NavList/NavList.styles.ts +114 -0
  73. package/src/components/NavList/NavList.test.tsx +1254 -0
  74. package/src/components/NavList/NavList.translations.json +9 -0
  75. package/src/components/NavList/NavList.tsx +160 -0
  76. package/src/components/NavList/NavList.types.ts +145 -0
  77. package/src/components/NavList/NavList.usage.mdx +540 -0
  78. package/src/components/NavList/NavListContext.ts +25 -0
  79. package/src/components/NavList/NavListGroup.tsx +243 -0
  80. package/src/components/NavList/NavListItem.tsx +525 -0
  81. package/src/components/NavList/NavListSkeleton.tsx +57 -0
  82. package/src/components/NavList/index.ts +14 -0
  83. package/src/components/Tabs/Tabs.usage.mdx +58 -14
  84. package/src/components/Textarea/Textarea.tsx +4 -0
  85. package/src/components/Tooltip/Tooltip.usage.mdx +8 -0
  86. package/src/components/a11y.kwcag.test.tsx +66 -0
  87. package/src/components/claude.md +1 -1
  88. package/src/index.ts +7 -1
  89. package/src/utils/focusRing.ts +23 -0
@@ -0,0 +1,97 @@
1
+ "use client";
2
+ /**
3
+ * The tokens a row paints, exported so the usage page's token table reads what
4
+ * the component renders.
5
+ *
6
+ * **The current row is a PLACE, not a value** — the same rule as `TAB_RAMP`
7
+ * and the app's nav rail (`NavigationLinkButton.utils.tsx` in factchat-nextjs).
8
+ * It is carried by ink, weight and a neutral fill, never by the brand hue: a
9
+ * rail that spends colour on "you are here" is what stops a success or error
10
+ * colour from registering when it appears.
11
+ *
12
+ * `bg.emphasized` rather than `bg.muted` for the fill, because rails sit on the
13
+ * sidebar wash and the fill has to separate from THAT: in light `bg.muted` is
14
+ * only OKLab dE 0.027 from the wash, under the threshold where two flat areas
15
+ * read as different, and `bg.emphasized` is 0.052 (measured in that file).
16
+ * Hover uses the same fill, so the current row does not change under the
17
+ * pointer and a hovered row previews exactly what selecting it looks like.
18
+ *
19
+ * `currentLabel` is `fg.emphasized`, which the theme aliases to `fg.default`
20
+ * today — so on the stock theme the current row is told apart by WEIGHT and
21
+ * FILL, not by a second ink. The role is still named separately so a theme
22
+ * that splits the two (and the app's nav rail, which reads the same pair)
23
+ * moves the current label without touching the rest.
24
+ *
25
+ * **Pressed is one step past hover**, on every row, current ones included —
26
+ * otherwise a press on the row you are already on gives no sign it landed.
27
+ * No `bg.*` role is darker than `bg.emphasized` in light (it is the top of
28
+ * the `layer.1` ladder), so the step is `border.default`: the next neutral in
29
+ * both modes (light `#D8D2CA` after `#E5DFD9`, dark `#48443E` after
30
+ * `#3F3B34`), the same fill the BottomSheet handle uses. Under
31
+ * `prefers-contrast: more` that token turns into a 3:1 stroke grey and the
32
+ * label would drop to 2.8:1, so high contrast takes `border.strong`, which
33
+ * high contrast leaves alone. `NavList.test.tsx` checks every pair.
34
+ */
35
+ const NAV_LIST_RAMP = {
36
+ label: 'fg.default',
37
+ currentLabel: 'fg.emphasized',
38
+ currentFill: 'bg.emphasized',
39
+ hoverFill: 'bg.emphasized',
40
+ pressedFill: 'border.default',
41
+ pressedFillMoreContrast: 'border.strong',
42
+ trailing: 'fg.muted',
43
+ groupTitle: 'fg.muted',
44
+ };
45
+ /** The pressed fill, with its high-contrast swap. */
46
+ const pressedFill = {
47
+ bg: NAV_LIST_RAMP.pressedFill,
48
+ _moreContrast: { bg: NAV_LIST_RAMP.pressedFillMoreContrast },
49
+ };
50
+ /**
51
+ * Chakra's `_rtl`/`_ltr` and `:dir()` read `dir` ATTRIBUTES, and zag stamps
52
+ * `dir="ltr"` on every part it renders (tooltip triggers — the rows — and the
53
+ * collapsible group) from Ark's locale, before any effect can measure the
54
+ * page. An author `direction` beats the UA rule that maps the attribute, so
55
+ * every stamped element takes the direction it inherits instead: the server
56
+ * render lays an RTL rail out right to left on its first paint.
57
+ */
58
+ const inheritDirection = { direction: 'inherit' };
59
+ /**
60
+ * A locale whose direction is `dir`: the inherited one when it already
61
+ * agrees, so a Korean app keeps formatting in Korean, otherwise a stand-in.
62
+ * Ark has no other way to set the `dir` zag stamps (its hooks omit the prop).
63
+ */
64
+ const localeFor = (inherited, dir) => inherited.dir === dir ? inherited.locale : dir === 'rtl' ? 'ar' : 'en-US';
65
+ /**
66
+ * Map an orientation (or a per-breakpoint object of them) to a style value per
67
+ * breakpoint, so the axis switch is CSS rather than a `useBreakpointValue`
68
+ * that renders the wrong axis on the server.
69
+ */
70
+ const byOrientation = (orientation, vertical, horizontal) => {
71
+ const pick = (o) => o === 'horizontal' ? horizontal : vertical;
72
+ if (typeof orientation === 'string')
73
+ return pick(orientation);
74
+ // A breakpoint object with no `base` still starts vertical — the default —
75
+ // instead of leaving the smallest screens with no axis at all.
76
+ return Object.fromEntries(Object.entries({ base: 'vertical', ...orientation }).map(([bp, o]) => [
77
+ bp,
78
+ pick(o),
79
+ ]));
80
+ };
81
+ /** The list box shared by the root list and every group's list. */
82
+ const listStyles = (orientation) => ({
83
+ listStyleType: 'none',
84
+ m: 0,
85
+ p: 0,
86
+ display: 'flex',
87
+ gap: 0.5,
88
+ minW: 0,
89
+ flexDirection: byOrientation(orientation, 'column', 'row'),
90
+ alignItems: byOrientation(orientation, 'stretch', 'center'),
91
+ // A row never wraps: a strip that grows to three lines as items are added
92
+ // eats the content it navigates. The root scrolls sideways instead.
93
+ flexWrap: 'nowrap',
94
+ });
95
+
96
+ export { NAV_LIST_RAMP, byOrientation, inheritDirection, listStyles, localeFor, pressedFill };
97
+ //# sourceMappingURL=NavList.styles.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavList.styles.mjs","sources":["../../../src/components/NavList/NavList.styles.ts"],"sourcesContent":[null],"names":[],"mappings":";AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;AACI,MAAM,aAAa,GAAG;AAC3B,IAAA,KAAK,EAAE,YAAY;AACnB,IAAA,YAAY,EAAE,eAAe;AAC7B,IAAA,WAAW,EAAE,eAAe;AAC5B,IAAA,SAAS,EAAE,eAAe;AAC1B,IAAA,WAAW,EAAE,gBAAgB;AAC7B,IAAA,uBAAuB,EAAE,eAAe;AACxC,IAAA,QAAQ,EAAE,UAAU;AACpB,IAAA,UAAU,EAAE,UAAU;;AAGxB;AACO,MAAM,WAAW,GAAG;IACzB,EAAE,EAAE,aAAa,CAAC,WAAW;AAC7B,IAAA,aAAa,EAAE,EAAE,EAAE,EAAE,aAAa,CAAC,uBAAuB,EAAE;;AAG9D;;;;;;;AAOG;MACU,gBAAgB,GAAG,EAAE,SAAS,EAAE,SAAS;AAEtD;;;;AAIG;AACI,MAAM,SAAS,GAAG,CACvB,SAAiD,EACjD,GAAkB,KAElB,SAAS,CAAC,GAAG,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,GAAG,GAAG,KAAK,KAAK,GAAG,IAAI,GAAG;AAEpE;;;;AAIG;AACI,MAAM,aAAa,GAAG,CAC3B,WAAyC,EACzC,QAAW,EACX,UAAa,KACY;AACzB,IAAA,MAAM,IAAI,GAAG,CAAC,CAAqB,KACjC,CAAC,KAAK,YAAY,GAAG,UAAU,GAAG,QAAQ;IAC5C,IAAI,OAAO,WAAW,KAAK,QAAQ;AAAE,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC;;;AAG7D,IAAA,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK;QACpE,EAAE;QACF,IAAI,CAAC,CAAuB,CAAC;AAC9B,KAAA,CAAC,CACH;AACH;AAEA;MACa,UAAU,GAAG,CAAC,WAAyC,MACjE;AACC,IAAA,aAAa,EAAE,MAAM;AACrB,IAAA,CAAC,EAAE,CAAC;AACJ,IAAA,CAAC,EAAE,CAAC;AACJ,IAAA,OAAO,EAAE,MAAM;AACf,IAAA,GAAG,EAAE,GAAG;AACR,IAAA,IAAI,EAAE,CAAC;IACP,aAAa,EAAE,aAAa,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC;IAC1D,UAAU,EAAE,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC;;;AAG3D,IAAA,QAAQ,EAAE,QAAQ;AACnB,CAAA;;;;"}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var nav_list_opens_new_window = {
7
+ ko: "새 창 열림",
8
+ en: "opens in a new window",
9
+ zh: "在新窗口中打开",
10
+ ja: "新しいウィンドウで開く",
11
+ es: "se abre en una ventana nueva"
12
+ };
13
+ var NavListTranslations = {
14
+ nav_list_opens_new_window: nav_list_opens_new_window
15
+ };
16
+
17
+ exports.default = NavListTranslations;
18
+ exports.nav_list_opens_new_window = nav_list_opens_new_window;
19
+ //# sourceMappingURL=NavList.translations.json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavList.translations.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ var nav_list_opens_new_window = {
3
+ ko: "새 창 열림",
4
+ en: "opens in a new window",
5
+ zh: "在新窗口中打开",
6
+ ja: "新しいウィンドウで開く",
7
+ es: "se abre en una ventana nueva"
8
+ };
9
+ var NavListTranslations = {
10
+ nav_list_opens_new_window: nav_list_opens_new_window
11
+ };
12
+
13
+ export { NavListTranslations as default, nav_list_opens_new_window };
14
+ //# sourceMappingURL=NavList.translations.json.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavList.translations.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
@@ -0,0 +1,131 @@
1
+ import type { MouseEventHandler, ReactNode } from 'react';
2
+ import type { HTMLChakraProps } from '@chakra-ui/react';
3
+ export type NavListOrientation = 'vertical' | 'horizontal';
4
+ type NavListBreakpoint = 'base' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
5
+ /**
6
+ * One orientation, or one per breakpoint. The media-template rails and the
7
+ * Drive source rail lie down into a sideways-scrolling row below `md`:
8
+ *
9
+ * ```tsx
10
+ * <NavList orientation={{ base: 'horizontal', md: 'vertical' }} />
11
+ * ```
12
+ *
13
+ * The switch is pure CSS (one rule per breakpoint), so it never renders the
14
+ * wrong axis first and corrects itself after hydration.
15
+ */
16
+ export type NavListResponsiveOrientation = NavListOrientation | Partial<Record<NavListBreakpoint, NavListOrientation>>;
17
+ export type NavListProps = Omit<HTMLChakraProps<'ul'>, 'children'> & {
18
+ children?: ReactNode;
19
+ /**
20
+ * `vertical` is a rail; `horizontal` is a single row that scrolls sideways
21
+ * instead of wrapping. Accepts a per-breakpoint object.
22
+ * @default 'vertical'
23
+ */
24
+ orientation?: NavListResponsiveOrientation;
25
+ /**
26
+ * Naming the list makes it a `<nav>` landmark around the list. Leave it off
27
+ * when the list already sits inside a named landmark (the app sidebar) — a
28
+ * second, unnamed `nav` is noise in the landmark menu.
29
+ */
30
+ 'aria-label'?: string;
31
+ /** As `aria-label`, pointing at a visible heading. Also makes it a `<nav>`. */
32
+ 'aria-labelledby'?: string;
33
+ /**
34
+ * The collapsed rail: every row is a 40px icon-only square whose label is
35
+ * still its accessible name (visually hidden) and shows as a tooltip on
36
+ * hover and keyboard focus. `trailingVisual`, `trailingAction` and group
37
+ * titles are hidden; a collapsible group shows its rows. Every row needs a
38
+ * `leadingVisual` in this mode. Vertical only.
39
+ * @default false
40
+ */
41
+ isCollapsed?: boolean;
42
+ };
43
+ export type NavListTrailingActionVisibility = 'always' | 'hover';
44
+ export type NavListItemProps = Omit<HTMLChakraProps<'a'>, 'children' | 'onClick' | 'aria-current' | 'asChild'> & {
45
+ /**
46
+ * The label. With `asChild`, the single link element (e.g. `next/link`)
47
+ * whose own children are the label.
48
+ */
49
+ children?: ReactNode;
50
+ /** Renders an `<a>`. Without `href` (and without `asChild`) the row is a `<button>`. */
51
+ href?: string;
52
+ /**
53
+ * Merge the row onto the one child element instead of rendering an `<a>` —
54
+ * for a router link: `<NavList.Item asChild><NextLink href="/x">X</NextLink></NavList.Item>`.
55
+ * The row is treated as a link.
56
+ */
57
+ asChild?: boolean;
58
+ onClick?: MouseEventHandler<HTMLElement>;
59
+ /**
60
+ * This row is where the user is: `aria-current="page"` on a link,
61
+ * `aria-current="true"` on a button (the active filter of a rail). Shown as
62
+ * an ink label, bold, on a `bg.emphasized` fill.
63
+ */
64
+ isCurrent?: boolean;
65
+ /**
66
+ * A button becomes `disabled`. A link — `asChild` included — is rendered
67
+ * as an `<a role="link" aria-disabled="true">` with no `href`: still
68
+ * announced as a link, out of the tab order, and nothing to open in a new tab.
69
+ */
70
+ isDisabled?: boolean;
71
+ /** Icon before the label. Decorative — the label names the row. */
72
+ leadingVisual?: ReactNode;
73
+ /** Count or badge after the label, in muted text. Read as part of the row's name. */
74
+ trailingVisual?: ReactNode;
75
+ /**
76
+ * A separate control beside the row (more-menu, remove), e.g. an
77
+ * `IconButton` with its own `aria-label`. It is a sibling of the row, never
78
+ * inside it, so there is no interactive element nested in another.
79
+ */
80
+ trailingAction?: ReactNode;
81
+ /**
82
+ * `hover`: the trailing action is transparent until the row is hovered, or
83
+ * focus is anywhere in the row, or the action's own menu is open
84
+ * (`aria-expanded="true"` / `data-state="open"` inside it). It is never
85
+ * removed, so Tab still reaches it — focusing it is what reveals it. Always
86
+ * shown on touch screens (`hover: none`), where there is no hover to reveal it.
87
+ * @default 'always'
88
+ */
89
+ trailingActionVisibility?: NavListTrailingActionVisibility;
90
+ /**
91
+ * A tooltip that adds to the label — a description, or why a row is
92
+ * disabled. It is also the row's accessible DESCRIPTION, through a hidden
93
+ * element that is referenced whether or not the tooltip is open — so a
94
+ * disabled row, which cannot take focus, still says why. It must not repeat
95
+ * the label. In a collapsed list it shows under the label.
96
+ *
97
+ * Label tooltips need no prop: a label cut off by the ellipsis shows itself
98
+ * in full on hover/focus, and every row of a collapsed list shows its label.
99
+ * Those are not wired as a description, because they would read the name twice.
100
+ */
101
+ tooltip?: ReactNode;
102
+ };
103
+ export type NavListGroupProps = Omit<HTMLChakraProps<'li'>, 'children' | 'title'> & {
104
+ children?: ReactNode;
105
+ /**
106
+ * Text above the group's rows, in overline style. Not interactive and not a
107
+ * heading element — it names the group's list (`aria-labelledby`), so it
108
+ * does not add a level to the page outline.
109
+ */
110
+ title?: ReactNode;
111
+ /**
112
+ * The title becomes a `<button aria-expanded>` that shows and hides the
113
+ * group's rows. Needs a `title`. Persisting the state (local storage, a
114
+ * store) is the caller's: pass `isOpen` + `onOpenChange`.
115
+ * @default false
116
+ */
117
+ isCollapsible?: boolean;
118
+ /** Controlled open state of a collapsible group. */
119
+ isOpen?: boolean;
120
+ /** Uncontrolled initial state of a collapsible group. @default true */
121
+ defaultOpen?: boolean;
122
+ onOpenChange?: (isOpen: boolean) => void;
123
+ };
124
+ export type NavListSkeletonProps = Omit<HTMLChakraProps<'ul'>, 'children'> & {
125
+ /** How many placeholder rows. @default 5 */
126
+ count?: number;
127
+ /** Lay the placeholders out like the list they stand in for. @default 'vertical' */
128
+ orientation?: NavListResponsiveOrientation;
129
+ };
130
+ export {};
131
+ //# sourceMappingURL=NavList.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavList.types.d.ts","sourceRoot":"","sources":["../../../src/components/NavList/NavList.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,YAAY,CAAC;AAE3D,KAAK,iBAAiB,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;AAEpE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,4BAA4B,GACpC,kBAAkB,GAClB,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAE3D,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,GAAG;IACnE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;OAIG;IACH,WAAW,CAAC,EAAE,4BAA4B,CAAC;IAC3C;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEjE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,eAAe,CAAC,GAAG,CAAC,EACpB,UAAU,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CACpD,GAAG;IACF;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACzC;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mEAAmE;IACnE,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,qFAAqF;IACrF,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B;;;;OAIG;IACH,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B;;;;;;;OAOG;IACH,wBAAwB,CAAC,EAAE,+BAA+B,CAAC;IAC3D;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,eAAe,CAAC,IAAI,CAAC,EACrB,UAAU,GAAG,OAAO,CACrB,GAAG;IACF,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3E,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,WAAW,CAAC,EAAE,4BAA4B,CAAC;CAC5C,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { NavListResponsiveOrientation } from './NavList.types';
2
+ export declare const NavListContext: import("react").Context<{
3
+ orientation: NavListResponsiveOrientation;
4
+ isCollapsed: boolean;
5
+ /**
6
+ * The direction the list inherits, measured after mount — for the rows'
7
+ * tooltips (their text direction, and which side a collapsed rail's tooltip
8
+ * opens on) and the `dir` attribute zag stamps on its parts. Never for
9
+ * layout: rows inherit `direction` in CSS, so a server render is right
10
+ * before this is known.
11
+ */
12
+ tooltipDir: "ltr" | "rtl";
13
+ /** A row that just became current asks the list to bring it into view. */
14
+ revealCurrent: () => void;
15
+ }>;
16
+ export declare const useNavListContext: () => {
17
+ orientation: NavListResponsiveOrientation;
18
+ isCollapsed: boolean;
19
+ /**
20
+ * The direction the list inherits, measured after mount — for the rows'
21
+ * tooltips (their text direction, and which side a collapsed rail's tooltip
22
+ * opens on) and the `dir` attribute zag stamps on its parts. Never for
23
+ * layout: rows inherit `direction` in CSS, so a server render is right
24
+ * before this is known.
25
+ */
26
+ tooltipDir: "ltr" | "rtl";
27
+ /** A row that just became current asks the list to bring it into view. */
28
+ revealCurrent: () => void;
29
+ };
30
+ //# sourceMappingURL=NavListContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavListContext.d.ts","sourceRoot":"","sources":["../../../src/components/NavList/NavListContext.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAEpE,eAAO,MAAM,cAAc;iBACZ,4BAA4B;iBAC5B,OAAO;IACpB;;;;;;OAMG;gBACS,KAAK,GAAG,KAAK;IACzB,0EAA0E;mBAC3D,MAAM,IAAI;EAMzB,CAAC;AAEH,eAAO,MAAM,iBAAiB;iBAnBf,4BAA4B;iBAC5B,OAAO;IACpB;;;;;;OAMG;gBACS,KAAK,GAAG,KAAK;IACzB,0EAA0E;mBAC3D,MAAM,IAAI;CAQsC,CAAC"}
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var React = require('react');
5
+
6
+ const NavListContext = React.createContext({
7
+ orientation: 'vertical',
8
+ isCollapsed: false,
9
+ tooltipDir: 'ltr',
10
+ revealCurrent: () => { },
11
+ });
12
+ const useNavListContext = () => React.useContext(NavListContext);
13
+
14
+ exports.NavListContext = NavListContext;
15
+ exports.useNavListContext = useNavListContext;
16
+ //# sourceMappingURL=NavListContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavListContext.js","sources":["../../../src/components/NavList/NavListContext.ts"],"sourcesContent":[null],"names":["createContext","useContext"],"mappings":";;;;;AAIO,MAAM,cAAc,GAAGA,mBAAa,CAaxC;AACD,IAAA,WAAW,EAAE,UAAU;AACvB,IAAA,WAAW,EAAE,KAAK;AAClB,IAAA,UAAU,EAAE,KAAK;AACjB,IAAA,aAAa,EAAE,MAAK,EAAE,CAAC;AACxB,CAAA;AAEM,MAAM,iBAAiB,GAAG,MAAMC,gBAAU,CAAC,cAAc;;;;;"}
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { createContext, useContext } from 'react';
3
+
4
+ const NavListContext = createContext({
5
+ orientation: 'vertical',
6
+ isCollapsed: false,
7
+ tooltipDir: 'ltr',
8
+ revealCurrent: () => { },
9
+ });
10
+ const useNavListContext = () => useContext(NavListContext);
11
+
12
+ export { NavListContext, useNavListContext };
13
+ //# sourceMappingURL=NavListContext.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavListContext.mjs","sources":["../../../src/components/NavList/NavListContext.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAIO,MAAM,cAAc,GAAG,aAAa,CAaxC;AACD,IAAA,WAAW,EAAE,UAAU;AACvB,IAAA,WAAW,EAAE,KAAK;AAClB,IAAA,UAAU,EAAE,KAAK;AACjB,IAAA,aAAa,EAAE,MAAK,EAAE,CAAC;AACxB,CAAA;AAEM,MAAM,iBAAiB,GAAG,MAAM,UAAU,CAAC,cAAc;;;;"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * A run of rows under an optional title.
3
+ *
4
+ * Rendered as `<li>` → title + nested `<ul aria-labelledby={title}>`, so a
5
+ * screen reader announces "목록, 공유 드라이브, 3개 항목" on entering it. The
6
+ * title is overline text, not `<h*>`: which heading level a rail's group is
7
+ * can only be known at the call site, and a typography default that decides
8
+ * the outline is exactly the `Subtitle as="h6"` defect in `ACCESSIBILITY.md`.
9
+ *
10
+ * `isCollapsible` turns the title into a disclosure button
11
+ * (`aria-expanded` + `aria-controls`); the list stays labelled by the title
12
+ * text. A collapsed RAIL (`NavList isCollapsed`) shows every group's rows and
13
+ * folds the titles away visually — a column of icons has no room for either.
14
+ *
15
+ * The rows open and close on Collapsible's own motion: Ark's collapsible
16
+ * measures the list into `--height`, the recipe's `expand-height` /
17
+ * `collapse-height` move it, and `animationStyle="presence"` sets the house
18
+ * clock (300ms in, 150ms out) with a fade instead of the height under reduced
19
+ * motion. Ark sets `hidden` once the close has finished, so closed rows are
20
+ * out of the tab order and the accessibility tree; `inert` covers the 150ms
21
+ * the list is still leaving, so a closing row cannot be tabbed into.
22
+ */
23
+ export declare const NavListGroup: import("react").ForwardRefExoticComponent<Omit<import("@chakra-ui/react").HTMLChakraProps<"li">, "title" | "children"> & {
24
+ children?: import("react").ReactNode;
25
+ title?: import("react").ReactNode;
26
+ isCollapsible?: boolean;
27
+ isOpen?: boolean;
28
+ defaultOpen?: boolean;
29
+ onOpenChange?: (isOpen: boolean) => void;
30
+ } & import("react").RefAttributes<HTMLLIElement>>;
31
+ //# sourceMappingURL=NavListGroup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavListGroup.d.ts","sourceRoot":"","sources":["../../../src/components/NavList/NavListGroup.tsx"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,YAAY;;;;;;;iDAmMxB,CAAC"}
@@ -0,0 +1,115 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var React = require('react');
6
+ var react = require('@chakra-ui/react');
7
+ var index = require('../Icon/index.js');
8
+ var Overline = require('../Typography/Overline.js');
9
+ var focusRing = require('../../utils/focusRing.js');
10
+ var NavList_styles = require('./NavList.styles.js');
11
+ var NavListContext = require('./NavListContext.js');
12
+
13
+ /**
14
+ * A run of rows under an optional title.
15
+ *
16
+ * Rendered as `<li>` → title + nested `<ul aria-labelledby={title}>`, so a
17
+ * screen reader announces "목록, 공유 드라이브, 3개 항목" on entering it. The
18
+ * title is overline text, not `<h*>`: which heading level a rail's group is
19
+ * can only be known at the call site, and a typography default that decides
20
+ * the outline is exactly the `Subtitle as="h6"` defect in `ACCESSIBILITY.md`.
21
+ *
22
+ * `isCollapsible` turns the title into a disclosure button
23
+ * (`aria-expanded` + `aria-controls`); the list stays labelled by the title
24
+ * text. A collapsed RAIL (`NavList isCollapsed`) shows every group's rows and
25
+ * folds the titles away visually — a column of icons has no room for either.
26
+ *
27
+ * The rows open and close on Collapsible's own motion: Ark's collapsible
28
+ * measures the list into `--height`, the recipe's `expand-height` /
29
+ * `collapse-height` move it, and `animationStyle="presence"` sets the house
30
+ * clock (300ms in, 150ms out) with a fade instead of the height under reduced
31
+ * motion. Ark sets `hidden` once the close has finished, so closed rows are
32
+ * out of the tab order and the accessibility tree; `inert` covers the 150ms
33
+ * the list is still leaving, so a closing row cannot be tabbed into.
34
+ */
35
+ const NavListGroup = React.forwardRef(({ title, children, isCollapsible = false, isOpen: isOpenProp, defaultOpen = true, onOpenChange, ...rest }, ref) => {
36
+ const { orientation, isCollapsed, tooltipDir } = NavListContext.useNavListContext();
37
+ const inherited = react.useLocaleContext();
38
+ const titleId = React.useId();
39
+ const listId = React.useId();
40
+ const hasTitle = title != null && title !== false;
41
+ const [isOpenState, setIsOpenState] = React.useState(defaultOpen);
42
+ // The disclosure exists whenever the caller asked for one; a collapsed
43
+ // rail only forces it open, so toggling the rail does not remount rows.
44
+ const isDisclosure = isCollapsible && hasTitle;
45
+ const canCollapse = isDisclosure && !isCollapsed;
46
+ const isOpen = !canCollapse || (isOpenProp ?? isOpenState);
47
+ const listRef = React.useRef(null);
48
+ // A DOM property rather than the attribute: React 18 does not know
49
+ // `inert`, and 19 reads it as a boolean.
50
+ React.useEffect(() => {
51
+ if (listRef.current)
52
+ listRef.current.inert = !isOpen;
53
+ }, [isOpen]);
54
+ const toggle = () => {
55
+ const next = !isOpen;
56
+ if (isOpenProp === undefined)
57
+ setIsOpenState(next);
58
+ onOpenChange?.(next);
59
+ };
60
+ // Space on the axis the rows stack along, on both sides of a group: before
61
+ // it unless it opens the list, and before whatever row follows it, so the
62
+ // row after a group does not read as one more member of it.
63
+ const gapBefore = {
64
+ marginTop: NavList_styles.byOrientation(orientation, 3, 0),
65
+ marginInlineStart: NavList_styles.byOrientation(orientation, 0, 3),
66
+ };
67
+ const titleText = (jsxRuntime.jsx(Overline.Overline, { as: "span", id: titleId, display: "block", color: NavList_styles.NAV_LIST_RAMP.groupTitle, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", children: title }));
68
+ let heading = null;
69
+ if (canCollapse) {
70
+ heading = (jsxRuntime.jsxs(react.chakra.button, { type: "button", "aria-expanded": isOpen, "aria-controls": listId, onClick: toggle, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, minH: 8, px: 2.5, borderRadius: "md", bg: "transparent", border: "none", cursor: "pointer", color: NavList_styles.NAV_LIST_RAMP.groupTitle, textAlign: "start", _hover: { bg: NavList_styles.NAV_LIST_RAMP.hoverFill }, _active: NavList_styles.pressedFill, ...focusRing.focusRingInset, children: [titleText, jsxRuntime.jsx(index.ChevronDownIcon, { "aria-hidden": true, boxSize: 4, flexShrink: 0,
71
+ // Closed points to the inline end: right, or left on an RTL page.
72
+ rotate: isOpen ? '0deg' : '-90deg', _rtl: { rotate: isOpen ? '0deg' : '90deg' },
73
+ // Turns with the list, on the same clock as its enter.
74
+ animationStyle: "travel", transitionProperty: "rotate" })] }));
75
+ }
76
+ else if (hasTitle) {
77
+ heading = (jsxRuntime.jsx(react.chakra.span, { display: "block", px: 2.5, py: NavList_styles.byOrientation(orientation, 1, 0), children: titleText }));
78
+ }
79
+ // A collapsed rail has no room for titles. The title folds to no height
80
+ // and fades on the rows' clock instead of being swapped out, so the rows
81
+ // under it slide up with the rail rather than jumping. It stays in the
82
+ // DOM either way: it is what names the group's list.
83
+ if (heading) {
84
+ heading = (jsxRuntime.jsx(react.chakra.div, { display: "grid", gridTemplateRows: isCollapsed ? '0fr' : '1fr', opacity: isCollapsed ? 0 : 1, animationStyle: "feedback", transitionProperty: "grid-template-rows, opacity", children: jsxRuntime.jsx(react.chakra.div, { minH: 0, overflow: "hidden", display: "flex", flexDirection: "column", children: heading }) }));
85
+ }
86
+ const listProps = {
87
+ id: listId,
88
+ 'aria-labelledby': hasTitle ? titleId : undefined,
89
+ ...NavList_styles.listStyles(orientation),
90
+ alignItems: NavList_styles.byOrientation(orientation, 'stretch', 'center'),
91
+ ...NavList_styles.inheritDirection,
92
+ };
93
+ const list = isDisclosure ? (jsxRuntime.jsx(react.Collapsible.Content, { asChild: true, animationStyle: "presence",
94
+ // `hidden` loses to the list's own `display: flex`.
95
+ css: { '&[hidden]': { display: 'none' } }, children: jsxRuntime.jsx(react.chakra.ul, { ref: listRef, ...listProps, children: children }) })) : (jsxRuntime.jsx(react.chakra.ul, { ...listProps, children: children }));
96
+ const group = (jsxRuntime.jsx(react.chakra.li, { ref: ref, display: "flex", flexDirection: NavList_styles.byOrientation(orientation, 'column', 'row'), alignItems: NavList_styles.byOrientation(orientation, 'stretch', 'center'), gap: 0.5, flexShrink: 0, minW: 0, css: {
97
+ '&:not(:first-child)': gapBefore,
98
+ '& + li': gapBefore,
99
+ }, ...NavList_styles.inheritDirection, ...rest, children: jsxRuntime.jsxs(react.LocaleProvider, { locale: inherited.locale, children: [heading, list] }) }));
100
+ if (!isDisclosure)
101
+ return group;
102
+ // The title stays our own button, so `aria-expanded` flips on the click
103
+ // rather than when the closing animation ends, and the rail can force the
104
+ // group open without the button having a say.
105
+ return (
106
+ // Zag stamps `dir` on the group and its list; give it the measured
107
+ // direction so the attributes agree with the layout after mount. The
108
+ // layout does not read it (`inheritDirection`), and the rows inside get
109
+ // the caller's own locale back.
110
+ jsxRuntime.jsx(react.LocaleProvider, { locale: NavList_styles.localeFor(inherited, tooltipDir), children: jsxRuntime.jsx(react.Collapsible.Root, { asChild: true, open: isOpen, ids: { content: listId }, children: group }) }));
111
+ });
112
+ NavListGroup.displayName = 'NavList.Group';
113
+
114
+ exports.NavListGroup = NavListGroup;
115
+ //# sourceMappingURL=NavListGroup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavListGroup.js","sources":["../../../src/components/NavList/NavListGroup.tsx"],"sourcesContent":[null],"names":["forwardRef","useNavListContext","useLocaleContext","useId","useState","useRef","useEffect","byOrientation","_jsx","Overline","NAV_LIST_RAMP","_jsxs","chakra","pressedFill","focusRingInset","ChevronDownIcon","listStyles","inheritDirection","ChakraCollapsible","LocaleProvider","localeFor"],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ "use client";
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { forwardRef, useId, useState, useRef, useEffect } from 'react';
4
+ import { useLocaleContext, chakra, Collapsible, LocaleProvider } from '@chakra-ui/react';
5
+ import { ChevronDownIcon } from '../Icon/index.mjs';
6
+ import { Overline } from '../Typography/Overline.mjs';
7
+ import { focusRingInset } from '../../utils/focusRing.mjs';
8
+ import { byOrientation, NAV_LIST_RAMP, pressedFill, listStyles, inheritDirection, localeFor } from './NavList.styles.mjs';
9
+ import { useNavListContext } from './NavListContext.mjs';
10
+
11
+ /**
12
+ * A run of rows under an optional title.
13
+ *
14
+ * Rendered as `<li>` → title + nested `<ul aria-labelledby={title}>`, so a
15
+ * screen reader announces "목록, 공유 드라이브, 3개 항목" on entering it. The
16
+ * title is overline text, not `<h*>`: which heading level a rail's group is
17
+ * can only be known at the call site, and a typography default that decides
18
+ * the outline is exactly the `Subtitle as="h6"` defect in `ACCESSIBILITY.md`.
19
+ *
20
+ * `isCollapsible` turns the title into a disclosure button
21
+ * (`aria-expanded` + `aria-controls`); the list stays labelled by the title
22
+ * text. A collapsed RAIL (`NavList isCollapsed`) shows every group's rows and
23
+ * folds the titles away visually — a column of icons has no room for either.
24
+ *
25
+ * The rows open and close on Collapsible's own motion: Ark's collapsible
26
+ * measures the list into `--height`, the recipe's `expand-height` /
27
+ * `collapse-height` move it, and `animationStyle="presence"` sets the house
28
+ * clock (300ms in, 150ms out) with a fade instead of the height under reduced
29
+ * motion. Ark sets `hidden` once the close has finished, so closed rows are
30
+ * out of the tab order and the accessibility tree; `inert` covers the 150ms
31
+ * the list is still leaving, so a closing row cannot be tabbed into.
32
+ */
33
+ const NavListGroup = forwardRef(({ title, children, isCollapsible = false, isOpen: isOpenProp, defaultOpen = true, onOpenChange, ...rest }, ref) => {
34
+ const { orientation, isCollapsed, tooltipDir } = useNavListContext();
35
+ const inherited = useLocaleContext();
36
+ const titleId = useId();
37
+ const listId = useId();
38
+ const hasTitle = title != null && title !== false;
39
+ const [isOpenState, setIsOpenState] = useState(defaultOpen);
40
+ // The disclosure exists whenever the caller asked for one; a collapsed
41
+ // rail only forces it open, so toggling the rail does not remount rows.
42
+ const isDisclosure = isCollapsible && hasTitle;
43
+ const canCollapse = isDisclosure && !isCollapsed;
44
+ const isOpen = !canCollapse || (isOpenProp ?? isOpenState);
45
+ const listRef = useRef(null);
46
+ // A DOM property rather than the attribute: React 18 does not know
47
+ // `inert`, and 19 reads it as a boolean.
48
+ useEffect(() => {
49
+ if (listRef.current)
50
+ listRef.current.inert = !isOpen;
51
+ }, [isOpen]);
52
+ const toggle = () => {
53
+ const next = !isOpen;
54
+ if (isOpenProp === undefined)
55
+ setIsOpenState(next);
56
+ onOpenChange?.(next);
57
+ };
58
+ // Space on the axis the rows stack along, on both sides of a group: before
59
+ // it unless it opens the list, and before whatever row follows it, so the
60
+ // row after a group does not read as one more member of it.
61
+ const gapBefore = {
62
+ marginTop: byOrientation(orientation, 3, 0),
63
+ marginInlineStart: byOrientation(orientation, 0, 3),
64
+ };
65
+ const titleText = (jsx(Overline, { as: "span", id: titleId, display: "block", color: NAV_LIST_RAMP.groupTitle, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", children: title }));
66
+ let heading = null;
67
+ if (canCollapse) {
68
+ heading = (jsxs(chakra.button, { type: "button", "aria-expanded": isOpen, "aria-controls": listId, onClick: toggle, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, minH: 8, px: 2.5, borderRadius: "md", bg: "transparent", border: "none", cursor: "pointer", color: NAV_LIST_RAMP.groupTitle, textAlign: "start", _hover: { bg: NAV_LIST_RAMP.hoverFill }, _active: pressedFill, ...focusRingInset, children: [titleText, jsx(ChevronDownIcon, { "aria-hidden": true, boxSize: 4, flexShrink: 0,
69
+ // Closed points to the inline end: right, or left on an RTL page.
70
+ rotate: isOpen ? '0deg' : '-90deg', _rtl: { rotate: isOpen ? '0deg' : '90deg' },
71
+ // Turns with the list, on the same clock as its enter.
72
+ animationStyle: "travel", transitionProperty: "rotate" })] }));
73
+ }
74
+ else if (hasTitle) {
75
+ heading = (jsx(chakra.span, { display: "block", px: 2.5, py: byOrientation(orientation, 1, 0), children: titleText }));
76
+ }
77
+ // A collapsed rail has no room for titles. The title folds to no height
78
+ // and fades on the rows' clock instead of being swapped out, so the rows
79
+ // under it slide up with the rail rather than jumping. It stays in the
80
+ // DOM either way: it is what names the group's list.
81
+ if (heading) {
82
+ heading = (jsx(chakra.div, { display: "grid", gridTemplateRows: isCollapsed ? '0fr' : '1fr', opacity: isCollapsed ? 0 : 1, animationStyle: "feedback", transitionProperty: "grid-template-rows, opacity", children: jsx(chakra.div, { minH: 0, overflow: "hidden", display: "flex", flexDirection: "column", children: heading }) }));
83
+ }
84
+ const listProps = {
85
+ id: listId,
86
+ 'aria-labelledby': hasTitle ? titleId : undefined,
87
+ ...listStyles(orientation),
88
+ alignItems: byOrientation(orientation, 'stretch', 'center'),
89
+ ...inheritDirection,
90
+ };
91
+ const list = isDisclosure ? (jsx(Collapsible.Content, { asChild: true, animationStyle: "presence",
92
+ // `hidden` loses to the list's own `display: flex`.
93
+ css: { '&[hidden]': { display: 'none' } }, children: jsx(chakra.ul, { ref: listRef, ...listProps, children: children }) })) : (jsx(chakra.ul, { ...listProps, children: children }));
94
+ const group = (jsx(chakra.li, { ref: ref, display: "flex", flexDirection: byOrientation(orientation, 'column', 'row'), alignItems: byOrientation(orientation, 'stretch', 'center'), gap: 0.5, flexShrink: 0, minW: 0, css: {
95
+ '&:not(:first-child)': gapBefore,
96
+ '& + li': gapBefore,
97
+ }, ...inheritDirection, ...rest, children: jsxs(LocaleProvider, { locale: inherited.locale, children: [heading, list] }) }));
98
+ if (!isDisclosure)
99
+ return group;
100
+ // The title stays our own button, so `aria-expanded` flips on the click
101
+ // rather than when the closing animation ends, and the rail can force the
102
+ // group open without the button having a say.
103
+ return (
104
+ // Zag stamps `dir` on the group and its list; give it the measured
105
+ // direction so the attributes agree with the layout after mount. The
106
+ // layout does not read it (`inheritDirection`), and the rows inside get
107
+ // the caller's own locale back.
108
+ jsx(LocaleProvider, { locale: localeFor(inherited, tooltipDir), children: jsx(Collapsible.Root, { asChild: true, open: isOpen, ids: { content: listId }, children: group }) }));
109
+ });
110
+ NavListGroup.displayName = 'NavList.Group';
111
+
112
+ export { NavListGroup };
113
+ //# sourceMappingURL=NavListGroup.mjs.map