@cueplusplus/ui 0.1.0 → 0.3.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 (246) hide show
  1. package/CHANGELOG.md +705 -0
  2. package/dist/brand/_chassis.d.ts +54 -0
  3. package/dist/brand/_chassis.js +81 -0
  4. package/dist/brand/_geometry.js +41 -0
  5. package/dist/brand/cue-logotype.d.ts +29 -0
  6. package/dist/brand/cue-logotype.js +60 -0
  7. package/dist/brand/cue-mark.d.ts +30 -0
  8. package/dist/brand/cue-mark.js +61 -0
  9. package/dist/brand/index.d.ts +5 -0
  10. package/dist/brand/plussie.d.ts +67 -0
  11. package/dist/brand/plussie.js +125 -0
  12. package/dist/chat/agent-pile.js +1 -1
  13. package/dist/chat/ask-box.js +2 -2
  14. package/dist/chat/delegation-card.js +1 -1
  15. package/dist/chat/message.js +2 -2
  16. package/dist/chrome/_edge-scroller.d.ts +45 -0
  17. package/dist/chrome/_edge-scroller.js +149 -0
  18. package/dist/chrome/_glyphs.js +19 -1
  19. package/dist/chrome/_tabs-scroll.d.ts +13 -8
  20. package/dist/chrome/_tabs-scroll.js +13 -8
  21. package/dist/chrome/app-bar.d.ts +103 -0
  22. package/dist/chrome/app-bar.js +175 -0
  23. package/dist/chrome/app-shell.d.ts +125 -0
  24. package/dist/chrome/app-shell.js +167 -0
  25. package/dist/chrome/footer.d.ts +75 -0
  26. package/dist/chrome/footer.js +68 -0
  27. package/dist/chrome/index.d.ts +5 -1
  28. package/dist/chrome/index.js +4 -1
  29. package/dist/chrome/navigation-menu.js +1 -1
  30. package/dist/chrome/page-shell.d.ts +1 -1
  31. package/dist/chrome/page-shell.js +15 -5
  32. package/dist/chrome/segmented-control.d.ts +19 -0
  33. package/dist/chrome/segmented-control.js +40 -21
  34. package/dist/chrome/tabs.js +21 -65
  35. package/dist/chrome/toolbar.d.ts +22 -0
  36. package/dist/chrome/toolbar.js +26 -5
  37. package/dist/configurator/_overrides.js +22 -8
  38. package/dist/configurator/configurator.js +1 -1
  39. package/dist/configurator/panel-sections.js +10 -4
  40. package/dist/dmx/channel-matrix.js +1 -1
  41. package/dist/forms/otp-field.js +1 -1
  42. package/dist/index.d.ts +18 -9
  43. package/dist/index.js +16 -10
  44. package/dist/instruments/data-table.js +1 -1
  45. package/dist/instruments/index.d.ts +2 -2
  46. package/dist/instruments/index.js +2 -2
  47. package/dist/instruments/table.d.ts +14 -1
  48. package/dist/instruments/table.js +20 -1
  49. package/dist/layout/carousel.js +1 -1
  50. package/dist/layout/container.d.ts +1 -1
  51. package/dist/layout/container.js +6 -3
  52. package/dist/layout/index.d.ts +3 -3
  53. package/dist/layout/index.js +3 -3
  54. package/dist/layout/pagination.js +1 -1
  55. package/dist/layout/sidebar.d.ts +23 -3
  56. package/dist/layout/sidebar.js +18 -7
  57. package/dist/midi/spectrum-visualizer.js +1 -1
  58. package/dist/midi/timeline-ruler.js +1 -1
  59. package/dist/overlays/command-palette.js +1 -1
  60. package/dist/overlays/dialog.js +1 -1
  61. package/dist/overlays/dropdown-menu.js +2 -2
  62. package/dist/overlays/hover-card.js +1 -1
  63. package/dist/overlays/index.js +1 -1
  64. package/dist/overlays/popover.js +1 -1
  65. package/dist/overlays/sheet.js +1 -1
  66. package/dist/overlays/toast.js +1 -1
  67. package/dist/primitives/chip.d.ts +1 -1
  68. package/dist/primitives/index.d.ts +1 -1
  69. package/dist/primitives/index.js +1 -1
  70. package/dist/primitives/status-dot.d.ts +7 -0
  71. package/dist/primitives/status-dot.js +8 -1
  72. package/dist/styles.css +58 -2
  73. package/dist/system/density.d.ts +4 -1
  74. package/dist/system/density.js +12 -4
  75. package/dist/system/index.d.ts +4 -4
  76. package/dist/system/portal.d.ts +5 -5
  77. package/dist/system/portal.js +30 -11
  78. package/dist/system/prepaint.d.ts +34 -9
  79. package/dist/system/prepaint.js +48 -25
  80. package/dist/system/theme-provider.d.ts +48 -11
  81. package/dist/system/theme-provider.js +109 -35
  82. package/dist/system/use-density.d.ts +3 -3
  83. package/dist/system/use-density.js +16 -6
  84. package/dist/system/use-theme.d.ts +4 -2
  85. package/dist/system/use-theme.js +4 -2
  86. package/dist/theming/_presets.js +133 -5
  87. package/dist/theming/create-theme.d.ts +2 -2
  88. package/dist/theming/create-theme.js +37 -19
  89. package/dist/theming/serialize.d.ts +1 -1
  90. package/dist/theming/serialize.js +25 -1
  91. package/manifest/components/accordion.json +154 -0
  92. package/manifest/components/agent-pile.json +116 -0
  93. package/manifest/components/alert-dialog.json +190 -0
  94. package/manifest/components/app-bar.json +244 -0
  95. package/manifest/components/app-shell.json +291 -0
  96. package/manifest/components/app-window-frame.json +102 -0
  97. package/manifest/components/ask-box.json +209 -0
  98. package/manifest/components/autocomplete.json +197 -0
  99. package/manifest/components/avatar-group.json +72 -0
  100. package/manifest/components/avatar.json +95 -0
  101. package/manifest/components/breadcrumb.json +74 -0
  102. package/manifest/components/button-group.json +74 -0
  103. package/manifest/components/button.json +125 -0
  104. package/manifest/components/calendar.json +65 -0
  105. package/manifest/components/card.json +140 -0
  106. package/manifest/components/carousel.json +200 -0
  107. package/manifest/components/channel-matrix.json +173 -0
  108. package/manifest/components/chart-container.json +111 -0
  109. package/manifest/components/chart-ramp.json +72 -0
  110. package/manifest/components/chart-swatch.json +65 -0
  111. package/manifest/components/chart-tooltip-content.json +114 -0
  112. package/manifest/components/checkbox-group.json +68 -0
  113. package/manifest/components/checkbox.json +93 -0
  114. package/manifest/components/chip.json +132 -0
  115. package/manifest/components/collapsible.json +120 -0
  116. package/manifest/components/color-area.json +59 -0
  117. package/manifest/components/color-field.json +79 -0
  118. package/manifest/components/color-picker.json +175 -0
  119. package/manifest/components/color-slider.json +75 -0
  120. package/manifest/components/color-swatch.json +68 -0
  121. package/manifest/components/colors-section.json +66 -0
  122. package/manifest/components/combobox.json +198 -0
  123. package/manifest/components/command-palette.json +177 -0
  124. package/manifest/components/composer.json +176 -0
  125. package/manifest/components/container.json +60 -0
  126. package/manifest/components/context-menu.json +121 -0
  127. package/manifest/components/copy-button.json +93 -0
  128. package/manifest/components/cue-logotype.json +96 -0
  129. package/manifest/components/cue-mark.json +97 -0
  130. package/manifest/components/cue-portal-frame.json +55 -0
  131. package/manifest/components/data-table-pagination.json +83 -0
  132. package/manifest/components/data-table-toolbar.json +104 -0
  133. package/manifest/components/date-field.json +80 -0
  134. package/manifest/components/date-picker.json +191 -0
  135. package/manifest/components/date-range-picker.json +191 -0
  136. package/manifest/components/delegation-card.json +144 -0
  137. package/manifest/components/density.json +58 -0
  138. package/manifest/components/description-list.json +84 -0
  139. package/manifest/components/dialog.json +198 -0
  140. package/manifest/components/disclosure.json +109 -0
  141. package/manifest/components/dmx-bar.json +94 -0
  142. package/manifest/components/dmx-strip.json +101 -0
  143. package/manifest/components/drawer.json +179 -0
  144. package/manifest/components/dropdown-menu.json +229 -0
  145. package/manifest/components/empty-state.json +90 -0
  146. package/manifest/components/env-var-input.json +150 -0
  147. package/manifest/components/export-dialog.json +84 -0
  148. package/manifest/components/eyebrow.json +56 -0
  149. package/manifest/components/field-description.json +63 -0
  150. package/manifest/components/field-error.json +77 -0
  151. package/manifest/components/field-label.json +63 -0
  152. package/manifest/components/field.json +79 -0
  153. package/manifest/components/file-upload.json +159 -0
  154. package/manifest/components/flow-background.json +50 -0
  155. package/manifest/components/flow-controls.json +50 -0
  156. package/manifest/components/footer.json +112 -0
  157. package/manifest/components/grid.json +81 -0
  158. package/manifest/components/group-bar.json +102 -0
  159. package/manifest/components/hover-card.json +151 -0
  160. package/manifest/components/icon-button.json +88 -0
  161. package/manifest/components/info-tip.json +98 -0
  162. package/manifest/components/input-group.json +91 -0
  163. package/manifest/components/input.json +89 -0
  164. package/manifest/components/item.json +129 -0
  165. package/manifest/components/kbd.json +52 -0
  166. package/manifest/components/link.json +81 -0
  167. package/manifest/components/log-viewer.json +139 -0
  168. package/manifest/components/menubar.json +157 -0
  169. package/manifest/components/message-list.json +100 -0
  170. package/manifest/components/message.json +116 -0
  171. package/manifest/components/meter.json +114 -0
  172. package/manifest/components/multi-select.json +190 -0
  173. package/manifest/components/musical-time-input.json +113 -0
  174. package/manifest/components/navigation-menu.json +226 -0
  175. package/manifest/components/node-card.json +109 -0
  176. package/manifest/components/node-handle.json +69 -0
  177. package/manifest/components/number-field.json +107 -0
  178. package/manifest/components/otp-field.json +128 -0
  179. package/manifest/components/page-shell.json +96 -0
  180. package/manifest/components/pagination.json +92 -0
  181. package/manifest/components/panel-header.json +77 -0
  182. package/manifest/components/panel.json +71 -0
  183. package/manifest/components/password-input.json +119 -0
  184. package/manifest/components/piano-keyboard.json +120 -0
  185. package/manifest/components/plussie.json +111 -0
  186. package/manifest/components/popover.json +193 -0
  187. package/manifest/components/preset-section.json +73 -0
  188. package/manifest/components/progress.json +95 -0
  189. package/manifest/components/radio-group.json +73 -0
  190. package/manifest/components/radio.json +80 -0
  191. package/manifest/components/rating.json +141 -0
  192. package/manifest/components/resizable.json +88 -0
  193. package/manifest/components/row.json +109 -0
  194. package/manifest/components/scroll-area.json +91 -0
  195. package/manifest/components/scrollable-tabs-list.json +83 -0
  196. package/manifest/components/scrub-input.json +200 -0
  197. package/manifest/components/seam-cell.json +75 -0
  198. package/manifest/components/seam-grid.json +75 -0
  199. package/manifest/components/seam-list.json +56 -0
  200. package/manifest/components/search-input.json +134 -0
  201. package/manifest/components/section-header.json +112 -0
  202. package/manifest/components/segmented-control.json +138 -0
  203. package/manifest/components/select.json +194 -0
  204. package/manifest/components/separator.json +53 -0
  205. package/manifest/components/shape-section.json +66 -0
  206. package/manifest/components/sheet.json +186 -0
  207. package/manifest/components/sidebar.json +198 -0
  208. package/manifest/components/signal-edge.json +56 -0
  209. package/manifest/components/skeleton.json +46 -0
  210. package/manifest/components/slider.json +89 -0
  211. package/manifest/components/sparkline.json +76 -0
  212. package/manifest/components/spectrum-visualizer.json +115 -0
  213. package/manifest/components/spinner.json +61 -0
  214. package/manifest/components/stack.json +96 -0
  215. package/manifest/components/stat.json +87 -0
  216. package/manifest/components/status-bar.json +58 -0
  217. package/manifest/components/status-dot.json +78 -0
  218. package/manifest/components/stepper.json +89 -0
  219. package/manifest/components/switch.json +87 -0
  220. package/manifest/components/table-scroll-region.json +69 -0
  221. package/manifest/components/table.json +155 -0
  222. package/manifest/components/tabs.json +145 -0
  223. package/manifest/components/tags-input.json +190 -0
  224. package/manifest/components/terminal-frame.json +119 -0
  225. package/manifest/components/textarea.json +76 -0
  226. package/manifest/components/theme-configurator.json +124 -0
  227. package/manifest/components/theme-provider.json +134 -0
  228. package/manifest/components/threshold-rail.json +160 -0
  229. package/manifest/components/time-field.json +80 -0
  230. package/manifest/components/timeline-ruler.json +139 -0
  231. package/manifest/components/timeline.json +115 -0
  232. package/manifest/components/title-bar.json +82 -0
  233. package/manifest/components/toast.json +130 -0
  234. package/manifest/components/toggle-group.json +106 -0
  235. package/manifest/components/toggle.json +109 -0
  236. package/manifest/components/token-editor.json +90 -0
  237. package/manifest/components/toolbar.json +163 -0
  238. package/manifest/components/tooltip.json +164 -0
  239. package/manifest/components/tree-visibility-toggle.json +84 -0
  240. package/manifest/components/tree.json +140 -0
  241. package/manifest/components/two-step-button.json +113 -0
  242. package/manifest/components/universe-grid.json +127 -0
  243. package/manifest/components/usage-chart.json +124 -0
  244. package/manifest/manifest.json +2142 -0
  245. package/manifest/tokens.json +138 -0
  246. package/package.json +13 -5
@@ -0,0 +1,149 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { computeScrollEdges, edgeFadeMask } from "./_tabs-scroll.js";
4
+ import { useComposedRefs } from "../lib/compose.js";
5
+ import { ChevronLeftGlyph, ChevronRightGlyph } from "./_glyphs.js";
6
+ import * as React from "react";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/chrome/_edge-scroller.tsx
9
+ /** Page the strip by most of a screenful, keeping a sliver of context. */
10
+ const NUDGE_FRACTION = .7;
11
+ /**
12
+ * What an overflowing element wears: the scroll axis, the fade, and no
13
+ * scrollbar.
14
+ *
15
+ * A literal rather than a computed string, because Tailwind scans source text —
16
+ * and the mask travels as a custom property so the prefixed and unprefixed
17
+ * properties are written once here instead of twice per render.
18
+ *
19
+ * The property is always set, `none` when nothing overflows, and that word is
20
+ * load-bearing: custom properties **inherit**. Leaving it unset on a strip that
21
+ * fits does not mean "no mask", it means "whatever an ancestor said" — and a
22
+ * `SegmentedControl` inside an overflowing `Toolbar` then wears the bar's fade
23
+ * and loses its own last segment to it. Measured in a real browser at 320px
24
+ * before it was written down. `none` is the initial value either way, so the
25
+ * common case still creates no compositing layer.
26
+ */
27
+ const EDGE_SCROLLER_CLASSES = "overflow-x-auto [mask-image:var(--cue-edge-fade)] [-webkit-mask-image:var(--cue-edge-fade)] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden";
28
+ /**
29
+ * Track which edges of a horizontal scroller still hide content, and hand back
30
+ * the mask and the pager that go with it.
31
+ *
32
+ * @param enabled False to keep the hook mounted but inert — a component whose
33
+ * overflow behaviour is switched off must still call the same hooks in the same
34
+ * order.
35
+ */
36
+ function useEdgeScroll(enabled = true) {
37
+ const ref = React.useRef(null);
38
+ const [edges, setEdges] = React.useState({
39
+ start: false,
40
+ end: false
41
+ });
42
+ const sync = React.useCallback(() => {
43
+ const el = ref.current;
44
+ if (el === null) return;
45
+ setEdges(computeScrollEdges(el.scrollLeft, el.scrollWidth, el.clientWidth));
46
+ }, []);
47
+ React.useEffect(() => {
48
+ if (!enabled) return;
49
+ const el = ref.current;
50
+ if (el === null) return;
51
+ sync();
52
+ el.addEventListener("scroll", sync, { passive: true });
53
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => sync());
54
+ observer?.observe(el);
55
+ let observedChildren = /* @__PURE__ */ new Set();
56
+ const syncObservedChildren = () => {
57
+ const nextChildren = new Set(el.children);
58
+ for (const child of observedChildren) if (!nextChildren.has(child)) observer?.unobserve(child);
59
+ for (const child of nextChildren) if (!observedChildren.has(child)) observer?.observe(child);
60
+ observedChildren = nextChildren;
61
+ sync();
62
+ };
63
+ syncObservedChildren();
64
+ const mutations = typeof MutationObserver === "undefined" ? null : new MutationObserver(() => syncObservedChildren());
65
+ mutations?.observe(el, { childList: true });
66
+ return () => {
67
+ el.removeEventListener("scroll", sync);
68
+ mutations?.disconnect();
69
+ observer?.disconnect();
70
+ };
71
+ }, [enabled, sync]);
72
+ const nudge = React.useCallback((direction) => {
73
+ const el = ref.current;
74
+ el?.scrollBy?.({
75
+ left: direction * el.clientWidth * NUDGE_FRACTION,
76
+ behavior: "smooth"
77
+ });
78
+ }, []);
79
+ const mask = enabled ? edgeFadeMask(edges) : void 0;
80
+ return {
81
+ ref,
82
+ edges: enabled ? edges : {
83
+ start: false,
84
+ end: false
85
+ },
86
+ style: enabled ? { "--cue-edge-fade": mask ?? "none" } : void 0,
87
+ nudge
88
+ };
89
+ }
90
+ /**
91
+ * The pager buttons over an overflowing strip, drawn only for the edges that
92
+ * actually hide something.
93
+ *
94
+ * Absolutely positioned, so the element they sit over must be inside a
95
+ * `relative` frame.
96
+ */
97
+ function EdgeChevrons({ edges, onNudge, previousLabel, nextLabel, className }) {
98
+ const base = "absolute inset-y-0 z-10 flex w-(--cue-space-5) cursor-pointer items-center justify-center text-fg-muted outline-none hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-accent";
99
+ return /* @__PURE__ */ jsxs(Fragment, { children: [edges.start ? /* @__PURE__ */ jsx("button", {
100
+ type: "button",
101
+ "data-slot": "edge-scroll-previous",
102
+ "aria-label": previousLabel,
103
+ onClick: () => onNudge(-1),
104
+ className: cn(base, "left-0", className),
105
+ children: /* @__PURE__ */ jsx(ChevronLeftGlyph, { className: "size-icon-sm" })
106
+ }) : null, edges.end ? /* @__PURE__ */ jsx("button", {
107
+ type: "button",
108
+ "data-slot": "edge-scroll-next",
109
+ "aria-label": nextLabel,
110
+ onClick: () => onNudge(1),
111
+ className: cn(base, "right-0", className),
112
+ children: /* @__PURE__ */ jsx(ChevronRightGlyph, { className: "size-icon-sm" })
113
+ }) : null] });
114
+ }
115
+ /**
116
+ * A `<nav>` that scrolls its links, wrapped in the frame the chevrons need.
117
+ *
118
+ * A component rather than the hook that `Toolbar` and `SegmentedControl` use
119
+ * directly, and for one specific reason: `AppBar` has to be renderable from a
120
+ * **server component** — it is a site header, and the site header is where a
121
+ * framework reads its data — so `app-bar.tsx` carries no `"use client"`
122
+ * directive and cannot call a hook. The client boundary is here instead, around
123
+ * the one part of a bar that has state.
124
+ */
125
+ const EdgeScrollNav = React.forwardRef(function EdgeScrollNav({ className, frameClassName, scrolls = true, previousLabel, nextLabel, style, ...elementProps }, ref) {
126
+ const scroll = useEdgeScroll(scrolls);
127
+ const navRef = useComposedRefs(ref, scroll.ref);
128
+ return /* @__PURE__ */ jsxs("div", {
129
+ "data-slot": "app-bar-nav-frame",
130
+ className: cn("relative flex", frameClassName),
131
+ children: [/* @__PURE__ */ jsx("nav", {
132
+ ref: navRef,
133
+ className: cn(scrolls ? EDGE_SCROLLER_CLASSES : null, className),
134
+ ...elementProps,
135
+ style: {
136
+ ...style,
137
+ ...scroll.style
138
+ }
139
+ }), /* @__PURE__ */ jsx(EdgeChevrons, {
140
+ edges: scroll.edges,
141
+ onNudge: scroll.nudge,
142
+ previousLabel,
143
+ nextLabel,
144
+ className: "bg-surface-1"
145
+ })]
146
+ });
147
+ });
148
+ //#endregion
149
+ export { EDGE_SCROLLER_CLASSES, EdgeChevrons, EdgeScrollNav, useEdgeScroll };
@@ -97,5 +97,23 @@ function EyeOffGlyph(props) {
97
97
  children: [/* @__PURE__ */ jsx("path", { d: "M6.2 4A6.5 6.5 0 0 1 8 3.5C12 3.5 14.5 8 14.5 8a12 12 0 0 1-2.3 2.7M9.8 12a6.5 6.5 0 0 1-1.8.5C4 12.5 1.5 8 1.5 8A12 12 0 0 1 4.4 4.8" }), /* @__PURE__ */ jsx("path", { d: "m2.5 2.5 11 11" })]
98
98
  });
99
99
  }
100
+ /**
101
+ * Three stacked strokes — the navigation trigger's mark.
102
+ *
103
+ * Only ever drawn below the shell's one breakpoint, where the navigation column
104
+ * has become a drawer and the bar needs something to open it with.
105
+ */
106
+ function MenuGlyph(props) {
107
+ return /* @__PURE__ */ jsx("svg", {
108
+ viewBox: "0 0 16 16",
109
+ fill: "none",
110
+ stroke: "currentColor",
111
+ strokeWidth: "1.75",
112
+ strokeLinecap: "round",
113
+ "aria-hidden": "true",
114
+ ...props,
115
+ children: /* @__PURE__ */ jsx("path", { d: "M2.5 4h11M2.5 8h11M2.5 12h11" })
116
+ });
117
+ }
100
118
  //#endregion
101
- export { CaretDownGlyph, ChevronLeftGlyph, ChevronRightGlyph, EyeGlyph, EyeOffGlyph, GhostGlyph };
119
+ export { CaretDownGlyph, ChevronLeftGlyph, ChevronRightGlyph, EyeGlyph, EyeOffGlyph, GhostGlyph, MenuGlyph };
@@ -1,14 +1,19 @@
1
1
  //#region src/chrome/_tabs-scroll.d.ts
2
2
  /**
3
- * Pure geometry for {@link ScrollableTabsList} (see `./tabs.tsx`).
3
+ * Pure geometry for the library's edge-scroll affordance.
4
4
  *
5
- * A separate module from the component on purpose. These are plain functions
5
+ * Written for {@link ScrollableTabsList} (see `./tabs.tsx`) and now the shared
6
+ * arithmetic under every strip in the system that can outgrow its container:
7
+ * the tab list, `Toolbar`, `SegmentedControl` and `AppBar`'s navigation all
8
+ * reach it through `./_edge-scroller`, which is where the React half lives.
9
+ *
10
+ * A separate module from the components on purpose. These are plain functions
6
11
  * over numbers — testable without a DOM, reusable by anything else that needs a
7
- * scroll-edge affordance — and keeping them out of the component file means the
8
- * component file can stay `"use client"` while this one has no directive at
9
- * all. (It is also what makes React Fast Refresh work on the component: a file
10
- * that exports both a component and non-component values gets a full reload
11
- * instead of a hot swap.)
12
+ * scroll-edge affordance — and keeping them out of a component file means that
13
+ * file can stay `"use client"` while this one has no directive at all. (It is
14
+ * also what makes React Fast Refresh work on the component: a file that exports
15
+ * both a component and non-component values gets a full reload instead of a hot
16
+ * swap.)
12
17
  */
13
18
  /** How far the fade reaches in from an overflowing edge, in px. */
14
19
  declare const TAB_FADE_PX = 24;
@@ -45,7 +50,7 @@ declare function computeScrollEdges(scrollLeft: number, scrollWidth: number, cli
45
50
  * an overlay would have to re-create that background as an opaque colour and
46
51
  * would drift the moment the theme changed. Masking fades the content itself
47
52
  * and lets whatever is behind show through, so it matches by construction in
48
- * all eight themes and both modes.
53
+ * every theme and both modes.
49
54
  *
50
55
  * This softens the cut; it is NOT the whole affordance. What sits at an
51
56
  * overflowing edge is often the gap between two tabs, and fading empty space is
@@ -1,14 +1,19 @@
1
1
  //#region src/chrome/_tabs-scroll.ts
2
2
  /**
3
- * Pure geometry for {@link ScrollableTabsList} (see `./tabs.tsx`).
3
+ * Pure geometry for the library's edge-scroll affordance.
4
4
  *
5
- * A separate module from the component on purpose. These are plain functions
5
+ * Written for {@link ScrollableTabsList} (see `./tabs.tsx`) and now the shared
6
+ * arithmetic under every strip in the system that can outgrow its container:
7
+ * the tab list, `Toolbar`, `SegmentedControl` and `AppBar`'s navigation all
8
+ * reach it through `./_edge-scroller`, which is where the React half lives.
9
+ *
10
+ * A separate module from the components on purpose. These are plain functions
6
11
  * over numbers — testable without a DOM, reusable by anything else that needs a
7
- * scroll-edge affordance — and keeping them out of the component file means the
8
- * component file can stay `"use client"` while this one has no directive at
9
- * all. (It is also what makes React Fast Refresh work on the component: a file
10
- * that exports both a component and non-component values gets a full reload
11
- * instead of a hot swap.)
12
+ * scroll-edge affordance — and keeping them out of a component file means that
13
+ * file can stay `"use client"` while this one has no directive at all. (It is
14
+ * also what makes React Fast Refresh work on the component: a file that exports
15
+ * both a component and non-component values gets a full reload instead of a hot
16
+ * swap.)
12
17
  */
13
18
  /** How far the fade reaches in from an overflowing edge, in px. */
14
19
  const TAB_FADE_PX = 24;
@@ -48,7 +53,7 @@ function computeScrollEdges(scrollLeft, scrollWidth, clientWidth) {
48
53
  * an overlay would have to re-create that background as an opaque colour and
49
54
  * would drift the moment the theme changed. Masking fades the content itself
50
55
  * and lets whatever is behind show through, so it matches by construction in
51
- * all eight themes and both modes.
56
+ * every theme and both modes.
52
57
  *
53
58
  * This softens the cut; it is NOT the whole affordance. What sits at an
54
59
  * overflowing edge is often the gap between two tabs, and fading empty space is
@@ -0,0 +1,103 @@
1
+ import { BarOverflow } from "./_edge-scroller.js";
2
+ import { LinkProps } from "../layout/link.js";
3
+ import { SeparatorProps } from "../primitives/separator.js";
4
+ import * as React from "react";
5
+ //#region src/chrome/app-bar.d.ts
6
+ interface AppBarRootProps extends React.ComponentPropsWithoutRef<"header"> {
7
+ /**
8
+ * Keep the bar at the top of the viewport as the page scrolls. Defaults to
9
+ * `true`.
10
+ *
11
+ * Set it `false` inside `AppShell`, where nothing scrolls the document and a
12
+ * sticky bar would be solving a problem the shell has already solved.
13
+ */
14
+ sticky?: boolean;
15
+ }
16
+ type AppBarBrandProps = Omit<LinkProps, "variant" | "external">;
17
+ interface AppBarNavProps extends Omit<React.ComponentPropsWithoutRef<"nav">, "children"> {
18
+ /** Where the links sit when they are narrower than the space. Defaults to `"end"`. */
19
+ align?: "start" | "center" | "end";
20
+ /**
21
+ * What the navigation does when the links do not fit. Defaults to `"scroll"`.
22
+ *
23
+ * The same behaviour `Toolbar` and `SegmentedControl` have, from the same
24
+ * module: the links scroll inside the bar, the overflowing edge is faded and
25
+ * a pager chevron appears there. This is what lets the bar survive a phone
26
+ * without a viewport breakpoint.
27
+ */
28
+ overflow?: BarOverflow;
29
+ /** Accessible name for the chevron that reveals links off the leading edge. */
30
+ previousLabel?: string;
31
+ /** Accessible name for the chevron that reveals links off the trailing edge. */
32
+ nextLabel?: string;
33
+ /** Extra classes for the frame around the `<nav>`, which is what takes the remaining width. */
34
+ frameClassName?: string;
35
+ /** The links, and any separators between clusters of them. */
36
+ children?: React.ReactNode;
37
+ }
38
+ /**
39
+ * Which of the bar's two registers a link is set in.
40
+ *
41
+ * `muted` is furniture — the sections a reader scans past. `strong` is a
42
+ * destination, and the difference is the point: a run of eight identical muted
43
+ * words has no shape, and the one entry that matters disappears into it. Split
44
+ * the run with an {@link AppBarSeparator} and set the second cluster `strong`,
45
+ * and the bar reads as one list, differently weighted, rather than as two
46
+ * navigations.
47
+ */
48
+ type AppBarRegister = "muted" | "strong";
49
+ interface AppBarLinkProps extends LinkProps {
50
+ /** Which register the link is set in. Defaults to `"muted"`. */
51
+ register?: AppBarRegister;
52
+ /**
53
+ * This is the page the reader is on.
54
+ *
55
+ * Inks the link with the accent and sets `aria-current="page"` — the same
56
+ * bargain `Sidebar.Item` makes, so the current destination is announced and
57
+ * not merely coloured. Overrides `register`: a current page is never
58
+ * furniture.
59
+ */
60
+ active?: boolean;
61
+ }
62
+ type AppBarSeparatorProps = Omit<SeparatorProps, "orientation">;
63
+ type AppBarActionsProps = React.ComponentPropsWithoutRef<"div">;
64
+ /**
65
+ * The horizontal bar a site or an application wears across the top: brand slot,
66
+ * navigation slot, actions slot, one chrome rung tall.
67
+ *
68
+ * `AppShell` is the frame for a screen that owns the viewport; this is the bar
69
+ * for a document that scrolls — a marketing page, a documentation site, a
70
+ * console's public half. `NavigationMenu` is neither: it is the *menu* that
71
+ * goes inside `AppBar.Nav` when a section has children.
72
+ *
73
+ * Six parts. `Root` is the `<header>`, `Brand` the leading link, `Nav` the
74
+ * `<nav>` landmark that takes the remaining width and scrolls when the links
75
+ * outgrow it, `Link` one destination in one of two registers, `Separator` the
76
+ * seam between clusters, and `Actions` the trailing controls.
77
+ *
78
+ * @example
79
+ * <AppBar.Root>
80
+ * <AppBar.Brand render={<NextLink href="/" />}>
81
+ * <Eyebrow>@cueplusplus/ui</Eyebrow>
82
+ * </AppBar.Brand>
83
+ * <AppBar.Nav aria-label="Sections">
84
+ * <AppBar.Link render={<NextLink href="/docs" />}>Docs</AppBar.Link>
85
+ * <AppBar.Link render={<NextLink href="/theming" />}>Theming</AppBar.Link>
86
+ * <AppBar.Separator />
87
+ * <AppBar.Link render={<NextLink href="/gallery" />} register="strong">Gallery</AppBar.Link>
88
+ * <AppBar.Link external render={<a href="https://skills.cueplusplus.com" />}>Skills</AppBar.Link>
89
+ * </AppBar.Nav>
90
+ * <AppBar.Separator />
91
+ * <AppBar.Actions><ThemePicker /></AppBar.Actions>
92
+ * </AppBar.Root>
93
+ */
94
+ declare const AppBar: {
95
+ Root: React.ForwardRefExoticComponent<AppBarRootProps & React.RefAttributes<HTMLElement>>;
96
+ Brand: React.ForwardRefExoticComponent<AppBarBrandProps & React.RefAttributes<HTMLAnchorElement>>;
97
+ Nav: React.ForwardRefExoticComponent<AppBarNavProps & React.RefAttributes<HTMLElement>>;
98
+ Link: React.ForwardRefExoticComponent<AppBarLinkProps & React.RefAttributes<HTMLAnchorElement>>;
99
+ Separator: React.ForwardRefExoticComponent<Omit<AppBarSeparatorProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
100
+ Actions: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
101
+ };
102
+ //#endregion
103
+ export { AppBar, AppBarActionsProps, AppBarBrandProps, AppBarLinkProps, AppBarNavProps, AppBarRegister, AppBarRootProps, AppBarSeparatorProps };
@@ -0,0 +1,175 @@
1
+ import { cn } from "../lib/cn.js";
2
+ import { Link } from "../layout/link.js";
3
+ import { Separator } from "../primitives/separator.js";
4
+ import { EdgeScrollNav } from "./_edge-scroller.js";
5
+ import * as React from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+ //#region src/chrome/app-bar.tsx
8
+ /**
9
+ * The bar across the top of a document: brand, navigation, actions.
10
+ *
11
+ * One rung of the chrome ladder tall, from `--cue-chrome-toolbar` — the same
12
+ * token `Toolbar` and the docs site's hand-rolled header use, so a page that
13
+ * stacks a bar on a toolbar gets two equal strips rather than two guesses.
14
+ *
15
+ * Sticky by default, and translucent because of it: a bar pinned over scrolling
16
+ * content needs a ground, and `bg-surface-1/95` plus `backdrop-blur` says
17
+ * "there is content under this" where an opaque fill would claim the content
18
+ * ends here. `z-40` is above the page and below the `z-50` this library's
19
+ * overlays float at, so a menu opened from the bar is never behind it.
20
+ *
21
+ * **This is a bar, not a menu.** `NavigationMenu` is the mega-menu — triggers
22
+ * that open panels — and it goes *inside* an `AppBar.Nav` when a section has
23
+ * children. This component is the strip it sits in.
24
+ *
25
+ * Static markup — no `"use client"` on this module, deliberately: a site header
26
+ * is where a framework reads its data, so the bar has to be renderable from a
27
+ * server component. The one part with state is the navigation's scroller, and
28
+ * the client boundary is drawn around that alone (`_edge-scroller.tsx`).
29
+ *
30
+ * It adds **no viewport breakpoint**. `AppShell` holds the library's only one,
31
+ * for navigation shape, and a horizontal bar does not need it: the brand and
32
+ * the actions are `shrink-0`, the navigation between them takes the remaining
33
+ * width and scrolls inside it, so a 390px viewport gets the same bar with a
34
+ * shorter window onto the same links rather than a second layout to maintain.
35
+ *
36
+ * @example
37
+ * <AppBar.Root>
38
+ * <AppBar.Brand render={<NextLink href="/" />}>
39
+ * <Eyebrow>@cueplusplus/ui</Eyebrow>
40
+ * <Chip tone="accent" variant="outline">0.1.0</Chip>
41
+ * </AppBar.Brand>
42
+ * <AppBar.Nav aria-label="Sections">
43
+ * <AppBar.Link render={<NextLink href="/docs" />}>Docs</AppBar.Link>
44
+ * <AppBar.Separator />
45
+ * <AppBar.Link render={<NextLink href="/gallery" />} register="strong">Gallery</AppBar.Link>
46
+ * </AppBar.Nav>
47
+ * <AppBar.Actions>
48
+ * <ThemePicker />
49
+ * </AppBar.Actions>
50
+ * </AppBar.Root>
51
+ */
52
+ const AppBarRoot = React.forwardRef(function AppBarRoot({ className, sticky = true, ...elementProps }, ref) {
53
+ return /* @__PURE__ */ jsx("header", {
54
+ ref,
55
+ "data-slot": "app-bar",
56
+ className: cn("flex h-(--cue-chrome-toolbar) w-full shrink-0 items-center gap-(--cue-space-4) border-b border-border bg-surface-1/95 px-(--cue-space-5) backdrop-blur", sticky ? "sticky top-0 z-40" : null, className),
57
+ ...elementProps
58
+ });
59
+ });
60
+ /**
61
+ * The leading slot, and the way home.
62
+ *
63
+ * A link rather than a box, because that is what a brand in a bar is: pass
64
+ * `href`, or `render={<NextLink href="/" />}` to go through a router. It sets
65
+ * the bar's own type register (mono, UI size, full-contrast ink) so a wordmark
66
+ * and a version chip sit on one baseline without a class of their own.
67
+ *
68
+ * `shrink-0`: the brand is the one thing in the bar that must never be
69
+ * compressed, because a half-drawn wordmark reads as a broken page.
70
+ */
71
+ const AppBarBrand = React.forwardRef(function AppBarBrand({ className, ...linkProps }, ref) {
72
+ return /* @__PURE__ */ jsx(Link, {
73
+ ref,
74
+ className: cn("flex shrink-0 items-center gap-(--cue-space-3) font-mono text-(length:--cue-text-ui) text-fg", className),
75
+ ...linkProps
76
+ });
77
+ });
78
+ /** Where a nav that does not fill its frame sits. */
79
+ const NAV_ALIGN = {
80
+ start: "justify-start",
81
+ center: "justify-center",
82
+ end: "justify-end"
83
+ };
84
+ /**
85
+ * The `<nav>` landmark between the brand and the actions, and the one part of
86
+ * the bar that gives up width.
87
+ *
88
+ * Name it: `aria-label="Sections"`, or whatever this bar's links are. A
89
+ * document with more than one navigation and no names on them is a screen
90
+ * reader listing "navigation, navigation".
91
+ *
92
+ * The alignment sits on the frame rather than on the scrolling `<nav>` itself,
93
+ * and that is load-bearing: `justify-content: flex-end` on a scroll container
94
+ * pushes the overflow off the *start* edge, where several browsers cannot
95
+ * scroll to reach it. Aligning the frame and letting the nav grow from its
96
+ * start keeps every link reachable at every width.
97
+ */
98
+ const AppBarNav = React.forwardRef(function AppBarNav({ className, frameClassName, align = "end", overflow = "scroll", previousLabel = "Show earlier links", nextLabel = "Show later links", ...elementProps }, ref) {
99
+ return /* @__PURE__ */ jsx(EdgeScrollNav, {
100
+ ref,
101
+ "data-slot": "app-bar-nav",
102
+ scrolls: overflow === "scroll",
103
+ previousLabel,
104
+ nextLabel,
105
+ frameClassName: cn("min-w-0 flex-1", NAV_ALIGN[align], frameClassName),
106
+ className: cn("flex min-w-0 items-center gap-(--cue-space-4)", className),
107
+ ...elementProps
108
+ });
109
+ });
110
+ const REGISTERS = {
111
+ muted: "text-fg-muted",
112
+ strong: "text-fg"
113
+ };
114
+ /**
115
+ * The horizontal bar a site or an application wears across the top: brand slot,
116
+ * navigation slot, actions slot, one chrome rung tall.
117
+ *
118
+ * `AppShell` is the frame for a screen that owns the viewport; this is the bar
119
+ * for a document that scrolls — a marketing page, a documentation site, a
120
+ * console's public half. `NavigationMenu` is neither: it is the *menu* that
121
+ * goes inside `AppBar.Nav` when a section has children.
122
+ *
123
+ * Six parts. `Root` is the `<header>`, `Brand` the leading link, `Nav` the
124
+ * `<nav>` landmark that takes the remaining width and scrolls when the links
125
+ * outgrow it, `Link` one destination in one of two registers, `Separator` the
126
+ * seam between clusters, and `Actions` the trailing controls.
127
+ *
128
+ * @example
129
+ * <AppBar.Root>
130
+ * <AppBar.Brand render={<NextLink href="/" />}>
131
+ * <Eyebrow>@cueplusplus/ui</Eyebrow>
132
+ * </AppBar.Brand>
133
+ * <AppBar.Nav aria-label="Sections">
134
+ * <AppBar.Link render={<NextLink href="/docs" />}>Docs</AppBar.Link>
135
+ * <AppBar.Link render={<NextLink href="/theming" />}>Theming</AppBar.Link>
136
+ * <AppBar.Separator />
137
+ * <AppBar.Link render={<NextLink href="/gallery" />} register="strong">Gallery</AppBar.Link>
138
+ * <AppBar.Link external render={<a href="https://skills.cueplusplus.com" />}>Skills</AppBar.Link>
139
+ * </AppBar.Nav>
140
+ * <AppBar.Separator />
141
+ * <AppBar.Actions><ThemePicker /></AppBar.Actions>
142
+ * </AppBar.Root>
143
+ */
144
+ const AppBar = {
145
+ Root: AppBarRoot,
146
+ Brand: AppBarBrand,
147
+ Nav: AppBarNav,
148
+ Link: React.forwardRef(function AppBarLink({ className, register = "muted", active = false, ...linkProps }, ref) {
149
+ return /* @__PURE__ */ jsx(Link, {
150
+ ref,
151
+ "data-active": active ? "" : void 0,
152
+ "aria-current": active ? "page" : void 0,
153
+ className: cn("shrink-0 font-mono text-(length:--cue-text-ui)", active ? "text-accent" : REGISTERS[register], className),
154
+ ...linkProps
155
+ });
156
+ }),
157
+ Separator: React.forwardRef(function AppBarSeparator({ className, ...elementProps }, ref) {
158
+ return /* @__PURE__ */ jsx(Separator, {
159
+ ref,
160
+ orientation: "vertical",
161
+ className: cn("h-(--cue-space-5)", className),
162
+ ...elementProps
163
+ });
164
+ }),
165
+ Actions: React.forwardRef(function AppBarActions({ className, ...elementProps }, ref) {
166
+ return /* @__PURE__ */ jsx("div", {
167
+ ref,
168
+ "data-slot": "app-bar-actions",
169
+ className: cn("flex shrink-0 items-center gap-(--cue-space-4)", className),
170
+ ...elementProps
171
+ });
172
+ })
173
+ };
174
+ //#endregion
175
+ export { AppBar };
@@ -0,0 +1,125 @@
1
+ import { SidebarLandmark, SidebarRootProps } from "../layout/sidebar.js";
2
+ import * as React from "react";
3
+ //#region src/chrome/app-shell.d.ts
4
+ interface AppShellRootProps extends React.ComponentPropsWithoutRef<"div"> {
5
+ /** Whether the mobile navigation drawer is open, when controlled. Pass with `onNavOpenChange`. */
6
+ navOpen?: boolean;
7
+ /** Initial open state of the mobile navigation drawer when uncontrolled. Defaults to `false`. */
8
+ defaultNavOpen?: boolean;
9
+ /** Called with the next open state whenever the drawer is opened or dismissed. */
10
+ onNavOpenChange?: (open: boolean) => void;
11
+ }
12
+ type AppShellBodyProps = React.ComponentPropsWithoutRef<"div">;
13
+ interface AppShellSidebarProps extends SidebarRootProps {
14
+ /** The drawer's heading, and its accessible name. Defaults to `"Navigation"`. */
15
+ drawerTitle?: React.ReactNode;
16
+ /** Accessible name for the drawer's close affordance. Defaults to `"Close navigation"`. */
17
+ closeLabel?: string;
18
+ /** Extra classes for the drawer's popup surface. */
19
+ drawerClassName?: string;
20
+ /**
21
+ * Draw the column's collapse rail. Defaults to `true`.
22
+ *
23
+ * The shell renders the `Sidebar.Rail` itself rather than taking one in
24
+ * `children`, because collapsing is a property of the *column* and the same
25
+ * children are also the drawer's: a rail passed as a child would be laid out
26
+ * inside the overlay, where there is nothing to collapse.
27
+ */
28
+ collapsible?: boolean;
29
+ /**
30
+ * Which landmark **both** shapes announce as. Defaults to `"navigation"`.
31
+ *
32
+ * One prop rather than two, because the column and the drawer are one
33
+ * navigation wearing two shapes: the answer cannot differ by viewport.
34
+ */
35
+ landmark?: SidebarLandmark;
36
+ }
37
+ interface AppShellNavTriggerProps extends Omit<React.ComponentPropsWithoutRef<"button">, "children"> {
38
+ /** Accessible name for the control. Defaults to `"Open navigation"`. */
39
+ label?: string;
40
+ /** The icon it draws. Defaults to the shell's own three-stroke glyph. */
41
+ icon?: React.ElementType;
42
+ /**
43
+ * Which rung of the control ladder the button takes. Defaults to `"md"`.
44
+ *
45
+ * The rest of the window furniture in this library is built at `"sm"`, and
46
+ * that is right for a mouse — but this control renders *only* below the `md`
47
+ * breakpoint, which is to say only on a touch screen, where `sm` (20px at
48
+ * normal density) is under the 24×24 CSS-pixel floor WCAG 2.2 SC 2.5.8 sets.
49
+ * `"md"` is 24px at normal and large, and the token layer's
50
+ * `@media (pointer: coarse)` rule lifts ultra-compact to the same 24px, so
51
+ * the default clears the floor at every density a finger can reach it at.
52
+ */
53
+ size?: "sm" | "md" | "lg";
54
+ }
55
+ interface AppShellContentProps extends React.ComponentPropsWithoutRef<"main"> {
56
+ /**
57
+ * Render the `<main>` landmark. Defaults to `true`.
58
+ *
59
+ * Set it `false` when the shell is embedded in a document that already has a
60
+ * `<main>` — a specimen, a screenshot, a shell shown inside a device frame on
61
+ * a page of prose. A document may have only one, and a nested one is a defect
62
+ * rather than a nicety.
63
+ */
64
+ main?: boolean;
65
+ }
66
+ interface AppShellScrollerProps extends React.ComponentPropsWithoutRef<"div"> {
67
+ /** Draw the standard work-area gutters. Defaults to `true`. */
68
+ padded?: boolean;
69
+ }
70
+ interface AppShellAsideProps extends React.ComponentPropsWithoutRef<"aside"> {
71
+ /** Width of the column. Any CSS length. Defaults to `"18rem"`. */
72
+ width?: string;
73
+ }
74
+ /**
75
+ * The console frame: title bar, navigation, work area, status bar — one
76
+ * viewport tall, with exactly one thing scrolling.
77
+ *
78
+ * Every console screen in this system is the same five parts in the same
79
+ * arrangement, and the value here is not the parts (they already exist as
80
+ * `TitleBar`, `Sidebar`, `Toolbar` and `StatusBar`) but the arithmetic between
81
+ * them: `h-dvh` on the frame rather than `min-h-dvh`, an unbroken `min-h-0`
82
+ * chain from the frame down to the scroller, `min-w-0` on the content column,
83
+ * and a scroller that is not the document. Get one of those wrong and the
84
+ * status bar leaves the screen or the navigation column gets shoved off the
85
+ * side; the shell exists so no page has to get them right again.
86
+ *
87
+ * The bars are ordinary children — `TitleBar` and `StatusBar` are already
88
+ * `shrink-0` and need no wrapper — so a shell reads as the page's outline.
89
+ *
90
+ * This is also the only component in the library with a viewport breakpoint:
91
+ * below `md` the navigation column becomes a drawer and a trigger appears in
92
+ * the bar. See {@link AppShellSidebar} for the ruling.
93
+ *
94
+ * @example
95
+ * <AppShell.Root>
96
+ * <TitleBar center="main-stage.cue" actions={<Chip tone="ok">live</Chip>}>
97
+ * <AppShell.NavTrigger />
98
+ * <Eyebrow>CUE++</Eyebrow>
99
+ * </TitleBar>
100
+ * <AppShell.Body>
101
+ * <AppShell.Sidebar aria-label="Console" drawerTitle="Console">
102
+ * <Sidebar.Section label="Show">
103
+ * <Sidebar.Item icon={List} active>Cues</Sidebar.Item>
104
+ * </Sidebar.Section>
105
+ * </AppShell.Sidebar>
106
+ * <AppShell.Content>
107
+ * <Toolbar.Root aria-label="Playback"><Toolbar.Button icon={Play}>Go</Toolbar.Button></Toolbar.Root>
108
+ * <AppShell.Scroller><Panel>…</Panel></AppShell.Scroller>
109
+ * </AppShell.Content>
110
+ * <AppShell.Aside aria-label="Inspector">…</AppShell.Aside>
111
+ * </AppShell.Body>
112
+ * <StatusBar><StatusBar.Item tone="ok">Art-Net</StatusBar.Item></StatusBar>
113
+ * </AppShell.Root>
114
+ */
115
+ declare const AppShell: {
116
+ Root: React.ForwardRefExoticComponent<AppShellRootProps & React.RefAttributes<HTMLDivElement>>;
117
+ Body: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
118
+ Sidebar: React.ForwardRefExoticComponent<AppShellSidebarProps & React.RefAttributes<HTMLElement>>;
119
+ NavTrigger: React.ForwardRefExoticComponent<AppShellNavTriggerProps & React.RefAttributes<HTMLButtonElement>>;
120
+ Content: React.ForwardRefExoticComponent<AppShellContentProps & React.RefAttributes<HTMLElement>>;
121
+ Scroller: React.ForwardRefExoticComponent<AppShellScrollerProps & React.RefAttributes<HTMLDivElement>>;
122
+ Aside: React.ForwardRefExoticComponent<AppShellAsideProps & React.RefAttributes<HTMLElement>>;
123
+ };
124
+ //#endregion
125
+ export { AppShell, AppShellAsideProps, AppShellBodyProps, AppShellContentProps, AppShellNavTriggerProps, AppShellRootProps, AppShellScrollerProps, AppShellSidebarProps };