@godxjp/ui 20.0.0 → 20.2.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 (273) hide show
  1. package/README.md +8 -2
  2. package/dist/app/app-provider.js +37 -21
  3. package/dist/app/index.d.ts +2 -0
  4. package/dist/app/index.js +2 -0
  5. package/dist/app/storage.d.ts +17 -0
  6. package/dist/app/storage.js +28 -0
  7. package/dist/app/theme-axes.d.ts +2 -0
  8. package/dist/app/theme-axes.js +45 -0
  9. package/dist/components/charts/chart-cartesian.d.ts +2 -1
  10. package/dist/components/charts/chart-cartesian.js +52 -3
  11. package/dist/components/charts/chart-category-axis.d.ts +55 -0
  12. package/dist/components/charts/chart-category-axis.js +93 -0
  13. package/dist/components/charts/chart-frame.d.ts +10 -1
  14. package/dist/components/charts/chart-frame.js +19 -3
  15. package/dist/components/charts/compact-bar-trend.d.ts +1 -1
  16. package/dist/components/charts/compact-bar-trend.js +2 -0
  17. package/dist/components/charts/pie-chart.d.ts +1 -1
  18. package/dist/components/charts/pie-chart.js +12 -1
  19. package/dist/components/charts/recharts-peer.d.ts +49 -0
  20. package/dist/components/charts/recharts-peer.js +45 -0
  21. package/dist/components/data-display/card.d.ts +12 -1
  22. package/dist/components/data-display/card.js +22 -4
  23. package/dist/components/data-display/code-block.js +6 -2
  24. package/dist/components/data-display/data-table.d.ts +39 -4
  25. package/dist/components/data-display/data-table.js +802 -270
  26. package/dist/components/data-display/descriptions.d.ts +27 -6
  27. package/dist/components/data-display/descriptions.js +58 -17
  28. package/dist/components/data-display/index.d.ts +2 -0
  29. package/dist/components/data-display/index.js +2 -0
  30. package/dist/components/data-display/list-row.d.ts +10 -1
  31. package/dist/components/data-display/list-row.js +7 -1
  32. package/dist/components/data-display/popover.d.ts +9 -3
  33. package/dist/components/data-display/popover.js +65 -11
  34. package/dist/components/data-display/range-timeline.d.ts +38 -0
  35. package/dist/components/data-display/range-timeline.js +161 -0
  36. package/dist/components/data-display/scroll-area.js +13 -2
  37. package/dist/components/data-display/service-launcher-card.js +14 -12
  38. package/dist/components/data-display/table.d.ts +71 -3
  39. package/dist/components/data-display/table.js +56 -18
  40. package/dist/components/data-display/tree-list.js +4 -9
  41. package/dist/components/data-entry/calendar.d.ts +2 -2
  42. package/dist/components/data-entry/calendar.js +23 -3
  43. package/dist/components/data-entry/cascader.d.ts +1 -1
  44. package/dist/components/data-entry/cascader.js +188 -24
  45. package/dist/components/data-entry/color-picker.d.ts +1 -1
  46. package/dist/components/data-entry/color-picker.js +17 -5
  47. package/dist/components/data-entry/control-appearance.d.ts +64 -0
  48. package/dist/components/data-entry/control-appearance.js +39 -0
  49. package/dist/components/data-entry/control-surface.d.ts +61 -0
  50. package/dist/components/data-entry/control-surface.js +39 -0
  51. package/dist/components/data-entry/date-picker.d.ts +1 -1
  52. package/dist/components/data-entry/date-picker.js +344 -113
  53. package/dist/components/data-entry/date-range-picker.d.ts +1 -1
  54. package/dist/components/data-entry/date-range-picker.js +278 -140
  55. package/dist/components/data-entry/form-field.d.ts +1 -1
  56. package/dist/components/data-entry/form-field.js +39 -4
  57. package/dist/components/data-entry/form.d.ts +4 -0
  58. package/dist/components/data-entry/form.js +4 -2
  59. package/dist/components/data-entry/index.d.ts +7 -3
  60. package/dist/components/data-entry/index.js +10 -1
  61. package/dist/components/data-entry/input-otp.d.ts +1 -1
  62. package/dist/components/data-entry/input.d.ts +12 -34
  63. package/dist/components/data-entry/input.js +92 -24
  64. package/dist/components/data-entry/month-picker.d.ts +1 -1
  65. package/dist/components/data-entry/month-picker.js +47 -10
  66. package/dist/components/data-entry/month-range-picker.d.ts +1 -1
  67. package/dist/components/data-entry/month-range-picker.js +51 -11
  68. package/dist/components/data-entry/number-input.d.ts +7 -0
  69. package/dist/components/data-entry/number-input.js +147 -98
  70. package/dist/components/data-entry/password-input.d.ts +1 -1
  71. package/dist/components/data-entry/radio.d.ts +1 -1
  72. package/dist/components/data-entry/radio.js +61 -13
  73. package/dist/components/data-entry/search-input.d.ts +1 -1
  74. package/dist/components/data-entry/search-input.js +16 -2
  75. package/dist/components/data-entry/search-select.d.ts +2 -2
  76. package/dist/components/data-entry/search-select.js +209 -78
  77. package/dist/components/data-entry/select.d.ts +22 -4
  78. package/dist/components/data-entry/select.js +215 -163
  79. package/dist/components/data-entry/slider.d.ts +9 -1
  80. package/dist/components/data-entry/slider.js +87 -9
  81. package/dist/components/data-entry/switch.d.ts +3 -0
  82. package/dist/components/data-entry/switch.js +29 -3
  83. package/dist/components/data-entry/textarea.d.ts +14 -56
  84. package/dist/components/data-entry/textarea.js +80 -33
  85. package/dist/components/data-entry/time-picker.d.ts +2 -2
  86. package/dist/components/data-entry/time-picker.js +333 -109
  87. package/dist/components/data-entry/time-range-picker.d.ts +5 -0
  88. package/dist/components/data-entry/time-range-picker.js +89 -0
  89. package/dist/components/data-entry/transfer.d.ts +1 -1
  90. package/dist/components/data-entry/transfer.js +86 -28
  91. package/dist/components/data-entry/tree-select.d.ts +1 -1
  92. package/dist/components/data-entry/tree-select.js +201 -113
  93. package/dist/components/data-entry/tree-utils.js +7 -14
  94. package/dist/components/data-entry/upload-files.d.ts +2 -0
  95. package/dist/components/data-entry/upload-files.js +31 -0
  96. package/dist/components/data-entry/upload-request.d.ts +4 -0
  97. package/dist/components/data-entry/upload-request.js +53 -0
  98. package/dist/components/data-entry/upload-types.d.ts +28 -0
  99. package/dist/components/data-entry/upload-types.js +2 -0
  100. package/dist/components/data-entry/upload.d.ts +2 -2
  101. package/dist/components/data-entry/upload.js +475 -115
  102. package/dist/components/feedback/dialog.js +19 -19
  103. package/dist/components/feedback/sheet.js +3 -0
  104. package/dist/components/feedback/tooltip.js +3 -0
  105. package/dist/components/general/button.d.ts +2 -1
  106. package/dist/components/general/button.js +7 -1
  107. package/dist/components/general/index.d.ts +1 -0
  108. package/dist/components/general/index.js +2 -0
  109. package/dist/components/general/typography.d.ts +3 -0
  110. package/dist/components/general/typography.js +15 -1
  111. package/dist/components/general/visually-hidden.d.ts +3 -0
  112. package/dist/components/general/visually-hidden.js +9 -0
  113. package/dist/components/layout/app-launcher.d.ts +34 -0
  114. package/dist/components/layout/app-launcher.js +261 -0
  115. package/dist/components/layout/app-shell.d.ts +3 -1
  116. package/dist/components/layout/app-shell.js +34 -14
  117. package/dist/components/layout/auth-shell.d.ts +1 -1
  118. package/dist/components/layout/auth-shell.js +2 -0
  119. package/dist/components/layout/breadcrumb.d.ts +14 -2
  120. package/dist/components/layout/breadcrumb.js +46 -4
  121. package/dist/components/layout/flex.d.ts +1 -1
  122. package/dist/components/layout/flex.js +23 -2
  123. package/dist/components/layout/index.d.ts +3 -0
  124. package/dist/components/layout/index.js +5 -1
  125. package/dist/components/layout/org-switcher.js +20 -1
  126. package/dist/components/layout/page-container.d.ts +1 -1
  127. package/dist/components/layout/page-container.js +5 -3
  128. package/dist/components/layout/responsive-grid.d.ts +16 -2
  129. package/dist/components/layout/responsive-grid.js +29 -2
  130. package/dist/components/layout/sidebar.js +2 -1
  131. package/dist/components/layout/topbar-item.d.ts +3 -0
  132. package/dist/components/layout/topbar-item.js +18 -3
  133. package/dist/components/layout/topbar.d.ts +1 -1
  134. package/dist/components/layout/topbar.js +27 -6
  135. package/dist/components/navigation/dropdown-menu.d.ts +30 -2
  136. package/dist/components/navigation/dropdown-menu.js +73 -11
  137. package/dist/components/navigation/pagination.d.ts +2 -2
  138. package/dist/components/navigation/pagination.js +155 -83
  139. package/dist/components/navigation/steps.d.ts +2 -2
  140. package/dist/components/navigation/steps.js +29 -4
  141. package/dist/components/navigation/tabs.d.ts +5 -33
  142. package/dist/components/navigation/tabs.js +232 -64
  143. package/dist/components/ui/hover-card.js +3 -0
  144. package/dist/components/ui/input-otp.d.ts +26 -28
  145. package/dist/components/ui/input-otp.js +50 -7
  146. package/dist/components/ui/password-input.d.ts +36 -2
  147. package/dist/components/ui/password-input.js +27 -7
  148. package/dist/components/ui/rating.d.ts +25 -0
  149. package/dist/components/ui/rating.js +67 -27
  150. package/dist/components/ui/segmented.d.ts +9 -0
  151. package/dist/components/ui/segmented.js +17 -2
  152. package/dist/components/ui/separator.d.ts +4 -0
  153. package/dist/components/ui/separator.js +13 -0
  154. package/dist/components/ui/tag-input.d.ts +45 -0
  155. package/dist/components/ui/tag-input.js +109 -27
  156. package/dist/form/form-context.d.ts +29 -0
  157. package/dist/form/form-context.js +44 -4
  158. package/dist/form/form-field-array.d.ts +22 -0
  159. package/dist/form/form-field-array.js +50 -0
  160. package/dist/form/form-field-control.d.ts +2 -1
  161. package/dist/form/form-field-control.js +116 -40
  162. package/dist/form/form-root.d.ts +2 -1
  163. package/dist/form/form-root.js +142 -23
  164. package/dist/form/index.d.ts +3 -1
  165. package/dist/form/index.js +12 -1
  166. package/dist/i18n/index.d.ts +1 -1
  167. package/dist/i18n/index.js +3 -1
  168. package/dist/i18n/messages/en.json +59 -6
  169. package/dist/i18n/messages/ja.json +59 -6
  170. package/dist/i18n/messages/vi.json +59 -6
  171. package/dist/i18n/translate.d.ts +19 -0
  172. package/dist/i18n/translate.js +24 -0
  173. package/dist/inertia/index.d.ts +20 -0
  174. package/dist/inertia/index.js +60 -1
  175. package/dist/lib/control-styles.d.ts +25 -3
  176. package/dist/lib/control-styles.js +9 -3
  177. package/dist/lib/datetime/picker-format.d.ts +8 -0
  178. package/dist/lib/datetime/picker-format.js +54 -0
  179. package/dist/lib/overlay-portal.d.ts +18 -0
  180. package/dist/lib/overlay-portal.js +17 -0
  181. package/dist/props/components/app.prop.d.ts +13 -2
  182. package/dist/props/components/charts.prop.d.ts +21 -0
  183. package/dist/props/components/data-display.prop.d.ts +55 -4
  184. package/dist/props/components/data-entry.prop.d.ts +687 -43
  185. package/dist/props/components/form.prop.d.ts +142 -4
  186. package/dist/props/components/general.prop.d.ts +30 -1
  187. package/dist/props/components/index.d.ts +2 -2
  188. package/dist/props/components/layout.prop.d.ts +255 -8
  189. package/dist/props/components/navigation.prop.d.ts +113 -3
  190. package/dist/props/registry.d.ts +376 -10
  191. package/dist/props/registry.js +493 -9
  192. package/dist/props/vocabulary/data.prop.d.ts +179 -1
  193. package/dist/props/vocabulary/index.d.ts +4 -4
  194. package/dist/props/vocabulary/interaction.prop.d.ts +51 -2
  195. package/dist/props/vocabulary/navigation.prop.d.ts +40 -0
  196. package/dist/props/vocabulary/shared.prop.d.ts +33 -0
  197. package/dist/styles/badge-layout.css +2 -1
  198. package/dist/styles/card-layout.css +36 -5
  199. package/dist/styles/chart-layout.css +17 -1
  200. package/dist/styles/control.css +520 -14
  201. package/dist/styles/data-display-layout.css +248 -7
  202. package/dist/styles/data-entry-layout.css +13 -0
  203. package/dist/styles/layout.css +221 -4
  204. package/dist/styles/navigation-layout.css +230 -1
  205. package/dist/styles/shell-layout.css +690 -21
  206. package/dist/styles/table-layout.css +95 -6
  207. package/dist/styles/text-layout.css +5 -0
  208. package/dist/tokens/base.css +1 -0
  209. package/dist/tokens/components/badge.css +1 -0
  210. package/dist/tokens/components/chart.css +6 -0
  211. package/dist/tokens/components/control.css +81 -3
  212. package/dist/tokens/components/data-display.css +9 -0
  213. package/dist/tokens/components/descriptions.css +11 -0
  214. package/dist/tokens/components/flex.css +8 -0
  215. package/dist/tokens/components/navigation.css +55 -0
  216. package/dist/tokens/components/shell.css +100 -5
  217. package/dist/tokens/components/table.css +14 -0
  218. package/dist/tokens/foundation.css +2 -0
  219. package/dist/tokens/semantic/layout.css +9 -0
  220. package/docs/CONSUMER-RULES.md +13 -0
  221. package/docs/DESIGN-AUTHORITY.md +43 -6
  222. package/docs/DEVELOPMENT.md +4 -3
  223. package/docs/FORMS.md +151 -6
  224. package/docs/FRAME-COVERAGE-REPORT.md +29 -16
  225. package/docs/README.md +1 -1
  226. package/docs/STANDARDS-vocabulary-tokens.md +1 -1
  227. package/docs/TESTING.md +15 -6
  228. package/docs/charts/cjk-category-axis.tsx +81 -0
  229. package/docs/data-display/card/index.tsx +22 -0
  230. package/docs/data-display/data-table/examples/antd-parity.tsx +257 -0
  231. package/docs/data-display/data-table/index.tsx +23 -0
  232. package/docs/data-display/descriptions.tsx +41 -0
  233. package/docs/data-display/list-row.tsx +6 -6
  234. package/docs/data-display/scroll-area.tsx +31 -25
  235. package/docs/data-display/table.tsx +104 -45
  236. package/docs/data-display/timeline.tsx +41 -0
  237. package/docs/data-entry/date-picker.tsx +85 -0
  238. package/docs/data-entry/date-range-picker.tsx +26 -0
  239. package/docs/data-entry/form-dynamic-fields.tsx +199 -0
  240. package/docs/data-entry/form.tsx +74 -4
  241. package/docs/data-entry/input-otp.tsx +24 -0
  242. package/docs/data-entry/input.tsx +46 -1
  243. package/docs/data-entry/month-range-picker.tsx +1 -1
  244. package/docs/data-entry/select.tsx +27 -0
  245. package/docs/data-entry/switch.tsx +41 -0
  246. package/docs/data-entry/textarea.tsx +38 -0
  247. package/docs/data-entry/time-picker.tsx +85 -1
  248. package/docs/data-entry/time-range-picker.tsx +55 -0
  249. package/docs/data-entry/transfer.tsx +17 -0
  250. package/docs/data-entry/upload.tsx +56 -12
  251. package/docs/feedback/tooltip.tsx +1 -1
  252. package/docs/general/activity.tsx +2 -2
  253. package/docs/general/button/index.tsx +14 -1
  254. package/docs/general/typography.tsx +14 -1
  255. package/docs/layout/app-launcher.tsx +195 -0
  256. package/docs/layout/app-shell-arrangements.tsx +5 -5
  257. package/docs/layout/app-shell.tsx +11 -0
  258. package/docs/layout/flex.tsx +50 -0
  259. package/docs/layout/responsive-grid.tsx +21 -1
  260. package/docs/layout/topbar.tsx +5 -9
  261. package/docs/navigation/app-setting-picker.tsx +11 -0
  262. package/docs/navigation/breadcrumb.tsx +48 -0
  263. package/docs/navigation/dropdown-menu.tsx +21 -0
  264. package/docs/navigation/pagination.tsx +52 -0
  265. package/docs/navigation/steps.tsx +37 -0
  266. package/docs/navigation/tabs.tsx +97 -1
  267. package/docs/query/button-refetch.tsx +1 -0
  268. package/docs/showcase/settings-security-mfa.tsx +3 -3
  269. package/package.json +24 -4
  270. package/scripts/_agent-setup.mjs +76 -9
  271. package/scripts/init-guinea-pig.mjs +26 -4
  272. package/scripts/ui-audit.mjs +243 -30
  273. package/scripts/visual-audit.mjs +45 -7
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useOverlayPortalContainer } from "../../lib/overlay-portal.js";
3
4
  import * as React from "react";
4
5
  import { chain, mergeRefs } from "@react-aria/utils";
5
6
  import { Dialog as RacDialog, Modal, ModalOverlay } from "react-aria-components";
@@ -12,7 +13,7 @@ import { buttonVariants } from "../general/button.js";
12
13
  import { useTranslation } from "../../i18n/use-translation.js";
13
14
  import { Button } from "../general/button.js";
14
15
  import { Input } from "../data-entry/input.js";
15
- import { Label } from "../data-entry/label.js";
16
+ import { FormField } from "../data-entry/form-field.js";
16
17
  function useOverlayOpenState({ open, defaultOpen, onOpenChange }) {
17
18
  const [uncontrolled, setUncontrolled] = React.useState(defaultOpen ?? false);
18
19
  const isOpen = open ?? uncontrolled;
@@ -58,9 +59,11 @@ function DialogShell({
58
59
  const labels = React.useMemo(() => ({ titleId, descriptionId }), [titleId, descriptionId]);
59
60
  const dataState = state.isOpen ? "open" : "closed";
60
61
  useOverlayCloseFocus(state.isOpen, onCloseAutoFocus);
62
+ const overlayPortalContainer = useOverlayPortalContainer();
61
63
  return /* @__PURE__ */ jsx(
62
64
  ModalOverlay,
63
65
  {
66
+ UNSTABLE_portalContainer: overlayPortalContainer,
64
67
  isOpen: state.isOpen,
65
68
  onOpenChange: state.setOpen,
66
69
  isDismissable,
@@ -407,24 +410,21 @@ function AlertDialog({
407
410
  /* @__PURE__ */ jsx(AlertDialogTitle, { children: title }),
408
411
  description ? /* @__PURE__ */ jsx(AlertDialogDescription, { children: description }) : null
409
412
  ] }),
410
- needsPhrase && /* @__PURE__ */ jsxs("div", { className: "ui-stack-xs", children: [
411
- /* @__PURE__ */ jsx(Label, { htmlFor: inputId, children: t("common.typeToConfirm", { phrase }) }),
412
- /* @__PURE__ */ jsx(
413
- Input,
414
- {
415
- id: inputId,
416
- value: typed,
417
- onChange: (e) => {
418
- setTyped(e.target.value);
419
- },
420
- autoComplete: "off",
421
- spellCheck: false,
422
- placeholder: phrase,
423
- "aria-required": "true",
424
- disabled: busy
425
- }
426
- )
427
- ] }),
413
+ needsPhrase && /* @__PURE__ */ jsx(FormField, { id: inputId, label: t("common.typeToConfirm", { phrase }), children: /* @__PURE__ */ jsx(
414
+ Input,
415
+ {
416
+ id: inputId,
417
+ value: typed,
418
+ onChange: (e) => {
419
+ setTyped(e.target.value);
420
+ },
421
+ autoComplete: "off",
422
+ spellCheck: false,
423
+ placeholder: phrase,
424
+ "aria-required": "true",
425
+ disabled: busy
426
+ }
427
+ ) }),
428
428
  stepUpFailed && /* @__PURE__ */ jsx("p", { id: stepErrorId, role: "alert", className: "ui-dialog-step-up-error", children: t("feedback.alert.stepUpFailed") }),
429
429
  /* @__PURE__ */ jsxs(DialogFooter, { children: [
430
430
  /* @__PURE__ */ jsx(DialogCancel, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", disabled: busy, children: resolvedCancel }) }),
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useOverlayPortalContainer } from "../../lib/overlay-portal.js";
3
4
  import * as React from "react";
4
5
  import { chain, mergeRefs } from "@react-aria/utils";
5
6
  import { Dialog as RacDialog, Modal, ModalOverlay } from "react-aria-components";
@@ -152,9 +153,11 @@ function SheetContent({
152
153
  const mergedStyle = widthSet ? { ...style, ["--sheet-width"]: toCssLength(width) } : style;
153
154
  const dataState = state.isOpen ? "open" : "closed";
154
155
  useOverlayCloseFocus(state.isOpen);
156
+ const overlayPortalContainer = useOverlayPortalContainer();
155
157
  return /* @__PURE__ */ jsx(
156
158
  ModalOverlay,
157
159
  {
160
+ UNSTABLE_portalContainer: overlayPortalContainer,
158
161
  isOpen: state.isOpen,
159
162
  onOpenChange: state.setOpen,
160
163
  isDismissable: true,
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
+ import { useOverlayPortalContainer } from "../../lib/overlay-portal.js";
3
4
  import * as React from "react";
4
5
  import { mergeRefs } from "@react-aria/utils";
5
6
  import {
@@ -74,9 +75,11 @@ function TooltipContent({
74
75
  forceMount: _forceMount,
75
76
  ...props
76
77
  }) {
78
+ const overlayPortalContainer = useOverlayPortalContainer();
77
79
  return /* @__PURE__ */ jsx(
78
80
  AriaTooltip,
79
81
  {
82
+ UNSTABLE_portalContainer: overlayPortalContainer,
80
83
  placement: toPlacement(side, align),
81
84
  offset: sideOffset,
82
85
  crossOffset: alignOffset,
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  declare const buttonVariants: (props?: ({
3
- variant?: "dashed" | "default" | "destructive" | "ghost" | "link" | "outline" | "secondary" | null | undefined;
3
+ variant?: "bare" | "dashed" | "default" | "destructive" | "ghost" | "link" | "outline" | "secondary" | null | undefined;
4
4
  size?: "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xs" | "lg" | "md" | "sm" | "xs" | null | undefined;
5
5
  shape?: "default" | "pill" | "sharp" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -10,6 +10,7 @@ export declare const Button: React.ForwardRefExoticComponent<React.ButtonHTMLAtt
10
10
  size?: import("../../props/index.js").ButtonSizeProp;
11
11
  shape?: import("../../props/index.js").ShapeProp;
12
12
  fullWidth?: boolean;
13
+ fill?: boolean;
13
14
  wrap?: boolean;
14
15
  align?: import("../../props/index.js").TextAlignProp;
15
16
  asChild?: import("../../props/index.js").AsChildProp;
@@ -20,7 +20,11 @@ const buttonVariants = cva("ui-button", {
20
20
  dashed: "ui-button--dashed border border-dashed bg-background hover:bg-accent hover:text-accent-foreground",
21
21
  secondary: "ui-button--secondary bg-secondary text-secondary-foreground hover:bg-secondary/80",
22
22
  ghost: "ui-button--ghost hover:bg-accent hover:text-accent-foreground",
23
- link: "ui-button--link text-primary underline-offset-4 hover:underline"
23
+ link: "ui-button--link text-primary underline-offset-4 hover:underline",
24
+ // NO utilities, deliberately: `bare` is the absence of geometry, and every property it has
25
+ // to unset (the size tier's height and inline inset) is declared in the components layer.
26
+ // A utility here would be the only thing that could out-rank it. See `.ui-button--bare`.
27
+ bare: "ui-button--bare"
24
28
  },
25
29
  size: {
26
30
  default: "ui-button--default-size",
@@ -52,6 +56,7 @@ const Button = React.forwardRef(
52
56
  size,
53
57
  shape,
54
58
  fullWidth = false,
59
+ fill = false,
55
60
  wrap = false,
56
61
  align = "center",
57
62
  asChild = false,
@@ -83,6 +88,7 @@ const Button = React.forwardRef(
83
88
  "data-size": size ?? "default",
84
89
  "data-shape": shape ?? "default",
85
90
  "data-full-width": fullWidth ? "" : void 0,
91
+ "data-fill": fill ? "" : void 0,
86
92
  "data-wrap": wrap ? "" : void 0,
87
93
  "data-align": align === "center" ? void 0 : align,
88
94
  "data-loading": isLoading ? "" : void 0,
@@ -8,3 +8,4 @@ export { Reveal } from "./reveal.js";
8
8
  export type { RevealProp, RevealProps } from "./reveal.js";
9
9
  export { Activity } from "./activity.js";
10
10
  export type { ActivityProp, ActivityProps } from "./activity.js";
11
+ export { VisuallyHidden } from "./visually-hidden.js";
@@ -3,6 +3,7 @@ import { Text, Heading } from "./typography.js";
3
3
  import { Logo } from "./logo.js";
4
4
  import { Reveal } from "./reveal.js";
5
5
  import { Activity } from "./activity.js";
6
+ import { VisuallyHidden } from "./visually-hidden.js";
6
7
  export {
7
8
  Activity,
8
9
  Button,
@@ -10,5 +11,6 @@ export {
10
11
  Logo,
11
12
  Reveal,
12
13
  Text,
14
+ VisuallyHidden,
13
15
  buttonVariants
14
16
  };
@@ -14,7 +14,10 @@ export declare const Text: React.ForwardRefExoticComponent<Omit<React.HTMLAttrib
14
14
  align?: import("../../props/index.js").TextAlignProp;
15
15
  truncate?: boolean;
16
16
  clamp?: number;
17
+ whitespace?: import("../../props/index.js").TextWhitespaceProp;
17
18
  tabular?: boolean;
19
+ decoration?: "none" | "underline" | "line-through";
20
+ chip?: boolean;
18
21
  mono?: boolean;
19
22
  htmlFor?: string;
20
23
  href?: string;
@@ -12,7 +12,10 @@ const Text = React.forwardRef(
12
12
  align,
13
13
  truncate,
14
14
  clamp,
15
+ whitespace,
15
16
  tabular,
17
+ decoration,
18
+ chip,
16
19
  mono,
17
20
  link,
18
21
  className,
@@ -21,6 +24,7 @@ const Text = React.forwardRef(
21
24
  ...props
22
25
  }, ref) => {
23
26
  const clampLines = typeof clamp === "number" && Number.isFinite(clamp) && clamp >= 1 ? Math.floor(clamp) : void 0;
27
+ const truncating = truncate === true && clampLines === void 0;
24
28
  if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
25
29
  if (clamp !== void 0 && clampLines === void 0) {
26
30
  console.warn(
@@ -32,6 +36,11 @@ const Text = React.forwardRef(
32
36
  "Text: `truncate` and `clamp` are mutually exclusive \u2014 `clamp` takes precedence; drop `truncate`."
33
37
  );
34
38
  }
39
+ if (whitespace === "pre-wrap" && truncating) {
40
+ console.warn(
41
+ 'Text: `truncate` and `whitespace="pre-wrap"` are mutually exclusive \u2014 `truncate` takes precedence (one line, one ellipsis); use `clamp` to keep preserved line breaks and still bound the height.'
42
+ );
43
+ }
35
44
  }
36
45
  const typography = {
37
46
  "data-slot": "text",
@@ -40,10 +49,15 @@ const Text = React.forwardRef(
40
49
  "data-link": link ? "" : void 0,
41
50
  "data-weight": weight,
42
51
  "data-align": align,
43
- "data-truncate": truncate && clampLines === void 0 ? "" : void 0,
52
+ "data-truncate": truncating ? "" : void 0,
44
53
  "data-clamp": clampLines !== void 0 ? "" : void 0,
54
+ // Inert default: `normal` is CSS's own behaviour, so it emits no attribute and there is no
55
+ // `[data-whitespace="normal"]` rule to lose a specificity argument with anything.
56
+ "data-whitespace": whitespace === "pre-wrap" && !truncating ? "pre-wrap" : void 0,
45
57
  style: clampLines !== void 0 ? { ...style, "--text-clamp": clampLines } : style,
46
58
  "data-tabular": tabular ? "" : void 0,
59
+ "data-decoration": decoration,
60
+ "data-chip": chip ? "" : void 0,
47
61
  "data-mono": mono ? "" : void 0,
48
62
  className: cn("ui-text", className),
49
63
  ...props
@@ -0,0 +1,3 @@
1
+ import * as React from "react";
2
+ /** Accessible text without a visible layout box. */
3
+ export declare const VisuallyHidden: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1,9 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../lib/utils.js";
4
+ const VisuallyHidden = React.forwardRef(function VisuallyHidden2({ className, ...props }, ref) {
5
+ return /* @__PURE__ */ jsx("span", { ...props, ref, className: cn("sr-only", className) });
6
+ });
7
+ export {
8
+ VisuallyHidden
9
+ };
@@ -0,0 +1,34 @@
1
+ import * as React from "react";
2
+ import type { AppLauncherProp } from "../../props/components/layout.prop.js";
3
+ export type { AppLauncherApp, AppLauncherGroup, AppLauncherLabels, AppLauncherProp, AppLauncherProp as AppLauncherProps, } from "../../props/components/layout.prop.js";
4
+ /** Arbitrary `data-*` hooks — the one escape hatch this closed component keeps open. */
5
+ type DataAttributes = {
6
+ [key: `data-${string}`]: string | number | boolean | undefined;
7
+ };
8
+ /**
9
+ * AppLauncher — the nine-dot app grid in the topbar: the platform's standard way to change app.
10
+ *
11
+ * THE TRIGGER IS A `TopbarItem`, NOT A `Button`. A bar cell is as tall as the bar, its hover IS the
12
+ * bar's surface, and its focus mark is hosted inside it; a `Button variant="ghost"` in the same slot
13
+ * draws a `--control-height` pill floating in a taller strip, with its own hover fill and its own
14
+ * ring drawn around that pill. That was the 20.0.0 correction, and it is why nothing here emits a
15
+ * height: the cell stretches to whatever the bar's height happens to be (`--app-shell-bar-height`,
16
+ * `--topbar-height`, or the coarse-pointer override), so it names none of them.
17
+ *
18
+ * The panel is the SAME responsive contract as `OrgSwitcher`: a desktop popover above
19
+ * `--sheet-responsive-breakpoint-width` and a focus-trapped bottom Sheet at/below it, through the
20
+ * shared `useSheetResponsiveMode()` hook rather than a component-local media query.
21
+ *
22
+ * ## Related — two components this is repeatedly confused with
23
+ *
24
+ * - `ServiceLauncherCard` (data-display) is a launcher tile too, but a PAGE-SIZED one: status,
25
+ * hostname, plan, an action button, a reason it is locked. It belongs on a service-catalogue page,
26
+ * where choosing is a considered act. The tile here is bar-sized — mark plus name, the whole tile
27
+ * one link — because changing app is a reflex. Neither is built out of the other, and a grid of
28
+ * `ServiceLauncherCard`s inside a popover is the wrong component, not a smaller version of this.
29
+ * - `AppShellProp.navRail` says the SAME platform scope as a docked column. Pick ONE: the launcher
30
+ * for a platform with MANY apps where switching is occasional (Google Workspace), the rail for a
31
+ * single product where switching workspace is constant enough to be worth permanent screen width
32
+ * (Slack). Shipping both puts one scope in two places and makes neither authoritative.
33
+ */
34
+ export declare function AppLauncher({ apps, groups, labels, columns, linkComponent, loading, error, onRetry, responsive, appearance, side, align, open, onOpenChange, className, ...rest }: AppLauncherProp & Pick<React.ComponentPropsWithoutRef<"button">, "id"> & DataAttributes): React.JSX.Element;
@@ -0,0 +1,261 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Grip, Loader2, RotateCcw } from "lucide-react";
5
+ import { cn } from "../../lib/utils.js";
6
+ import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
7
+ import {
8
+ Dialog,
9
+ DialogContent,
10
+ DialogHeader,
11
+ DialogTitle,
12
+ DialogTrigger
13
+ } from "../feedback/dialog.js";
14
+ import {
15
+ Sheet,
16
+ SheetBody,
17
+ SheetContent,
18
+ SheetHeader,
19
+ SheetTrigger,
20
+ useSheetResponsiveMode
21
+ } from "../feedback/sheet.js";
22
+ import { Button } from "../general/button.js";
23
+ import { TopbarItem } from "./topbar-item.js";
24
+ function AppMark({ app }) {
25
+ return /* @__PURE__ */ jsx("span", { className: "ui-app-launcher-mark", "aria-hidden": "true", children: app.icon ?? app.name.trim().charAt(0).toUpperCase() });
26
+ }
27
+ function AppLauncherTile({
28
+ app,
29
+ linkComponent: Link,
30
+ externalHint,
31
+ close
32
+ }) {
33
+ const children = /* @__PURE__ */ jsxs(Fragment, { children: [
34
+ /* @__PURE__ */ jsx(AppMark, { app }),
35
+ /* @__PURE__ */ jsx("span", { className: "ui-app-launcher-name", children: app.name }),
36
+ app.external && externalHint != null ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: externalHint }) : null
37
+ ] });
38
+ const linkProps = {
39
+ href: app.href,
40
+ className: "ui-app-launcher-tile ui-focus-ring",
41
+ "data-active": app.current ? "true" : void 0,
42
+ "aria-current": app.current ? "page" : void 0,
43
+ onClick: close,
44
+ children
45
+ };
46
+ return /* @__PURE__ */ jsx("li", { className: "ui-app-launcher-cell", "data-app": app.id, children: app.external || Link == null ? /* @__PURE__ */ jsx(
47
+ "a",
48
+ {
49
+ ...linkProps,
50
+ target: app.external ? "_blank" : void 0,
51
+ rel: app.external ? "noreferrer noopener" : void 0
52
+ }
53
+ ) : /* @__PURE__ */ jsx(Link, { ...linkProps }) });
54
+ }
55
+ function AppLauncherGrid({
56
+ apps,
57
+ linkComponent,
58
+ externalHint,
59
+ close,
60
+ ...props
61
+ }) {
62
+ return /* @__PURE__ */ jsx("ul", { className: "ui-app-launcher-grid", ...props, children: apps.map((app) => /* @__PURE__ */ jsx(
63
+ AppLauncherTile,
64
+ {
65
+ app,
66
+ linkComponent,
67
+ externalHint,
68
+ close
69
+ },
70
+ app.id
71
+ )) });
72
+ }
73
+ function AppLauncherSection({
74
+ label,
75
+ apps,
76
+ linkComponent,
77
+ externalHint,
78
+ close
79
+ }) {
80
+ const labelId = React.useId();
81
+ return /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": labelId, className: "ui-app-launcher-group", children: [
82
+ /* @__PURE__ */ jsx("span", { id: labelId, className: "ui-app-launcher-group-label", children: label }),
83
+ /* @__PURE__ */ jsx(
84
+ AppLauncherGrid,
85
+ {
86
+ apps,
87
+ linkComponent,
88
+ externalHint,
89
+ close
90
+ }
91
+ )
92
+ ] });
93
+ }
94
+ function AppLauncherPanel({
95
+ apps,
96
+ groups,
97
+ labels,
98
+ columns,
99
+ linkComponent,
100
+ loading,
101
+ error,
102
+ onRetry,
103
+ close
104
+ }) {
105
+ if (loading) {
106
+ return /* @__PURE__ */ jsxs("div", { className: "ui-app-launcher-state", role: "status", children: [
107
+ /* @__PURE__ */ jsx(Loader2, { className: "ui-app-launcher-spinner", "aria-hidden": "true" }),
108
+ /* @__PURE__ */ jsx("span", { children: labels.loading })
109
+ ] });
110
+ }
111
+ if (error != null) {
112
+ return /* @__PURE__ */ jsxs("div", { className: "ui-app-launcher-state", role: "alert", children: [
113
+ /* @__PURE__ */ jsx("span", { children: error }),
114
+ onRetry != null ? /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: onRetry, children: [
115
+ /* @__PURE__ */ jsx(RotateCcw, { "aria-hidden": "true" }),
116
+ labels.retry
117
+ ] }) : null
118
+ ] });
119
+ }
120
+ if (!apps.length && (groups ?? []).every((group) => !group.apps.length)) {
121
+ return /* @__PURE__ */ jsx("div", { className: "ui-app-launcher-state", role: "status", children: /* @__PURE__ */ jsx("span", { children: labels.empty }) });
122
+ }
123
+ return /* @__PURE__ */ jsxs(
124
+ "div",
125
+ {
126
+ className: "ui-app-launcher-panel",
127
+ style: columns == null ? void 0 : { "--app-launcher-columns": String(columns) },
128
+ children: [
129
+ apps.length ? /* @__PURE__ */ jsx(
130
+ AppLauncherGrid,
131
+ {
132
+ apps,
133
+ linkComponent,
134
+ externalHint: labels.externalHint,
135
+ close,
136
+ "aria-label": labels.title
137
+ }
138
+ ) : null,
139
+ groups?.map((group) => /* @__PURE__ */ jsx(
140
+ AppLauncherSection,
141
+ {
142
+ label: group.label,
143
+ apps: group.apps,
144
+ linkComponent,
145
+ externalHint: labels.externalHint,
146
+ close
147
+ },
148
+ group.label
149
+ ))
150
+ ]
151
+ }
152
+ );
153
+ }
154
+ function AppLauncher({
155
+ apps,
156
+ groups,
157
+ labels,
158
+ columns,
159
+ linkComponent,
160
+ loading = false,
161
+ error,
162
+ onRetry,
163
+ responsive = "auto",
164
+ appearance = "bar",
165
+ side,
166
+ align,
167
+ open,
168
+ onOpenChange,
169
+ className,
170
+ ...rest
171
+ }) {
172
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);
173
+ const controlled = open !== void 0;
174
+ const resolvedOpen = controlled ? open : uncontrolledOpen;
175
+ const setOpen = React.useCallback(
176
+ (nextOpen) => {
177
+ if (!controlled) {
178
+ setUncontrolledOpen(nextOpen);
179
+ }
180
+ onOpenChange?.(nextOpen);
181
+ },
182
+ [controlled, onOpenChange]
183
+ );
184
+ const compactViewport = useSheetResponsiveMode("auto") === "bottom";
185
+ const sheet = responsive === "sheet" || responsive === "auto" && compactViewport;
186
+ const launchpad = responsive === "fullscreen";
187
+ const close = React.useCallback(() => {
188
+ setOpen(false);
189
+ }, [setOpen]);
190
+ const triggerProps = {
191
+ className: cn("ui-app-launcher-trigger", className),
192
+ "aria-label": labels.trigger,
193
+ ...rest
194
+ };
195
+ const trigger = appearance === "bar" ? /* @__PURE__ */ jsx(TopbarItem, { ...triggerProps, children: /* @__PURE__ */ jsx(Grip, { "aria-hidden": "true" }) }) : /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", ...triggerProps, children: /* @__PURE__ */ jsx(Grip, { "aria-hidden": "true" }) });
196
+ const panel = /* @__PURE__ */ jsx(
197
+ AppLauncherPanel,
198
+ {
199
+ apps,
200
+ groups,
201
+ labels,
202
+ columns,
203
+ linkComponent,
204
+ loading,
205
+ error,
206
+ onRetry,
207
+ close
208
+ }
209
+ );
210
+ if (launchpad) {
211
+ return /* @__PURE__ */ jsxs(Dialog, { open: resolvedOpen, onOpenChange: setOpen, children: [
212
+ /* @__PURE__ */ jsx(DialogTrigger, { asChild: true, children: trigger }),
213
+ /* @__PURE__ */ jsxs(
214
+ DialogContent,
215
+ {
216
+ className: "ui-app-launcher-launchpad",
217
+ overlayClassName: "ui-app-launcher-launchpad-overlay",
218
+ children: [
219
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: labels.title }) }),
220
+ panel
221
+ ]
222
+ }
223
+ )
224
+ ] });
225
+ }
226
+ if (sheet) {
227
+ return /* @__PURE__ */ jsxs(Sheet, { open: resolvedOpen, onOpenChange: setOpen, children: [
228
+ /* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: trigger }),
229
+ /* @__PURE__ */ jsxs(
230
+ SheetContent,
231
+ {
232
+ responsive: "bottom",
233
+ className: "ui-app-launcher-sheet",
234
+ style: {
235
+ "--sheet-bottom-max-height": "var(--app-launcher-sheet-max-height)"
236
+ },
237
+ children: [
238
+ /* @__PURE__ */ jsx(SheetHeader, { title: labels.title }),
239
+ /* @__PURE__ */ jsx(SheetBody, { children: panel })
240
+ ]
241
+ }
242
+ )
243
+ ] });
244
+ }
245
+ return /* @__PURE__ */ jsxs(Popover, { open: resolvedOpen, onOpenChange: setOpen, children: [
246
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }),
247
+ /* @__PURE__ */ jsx(
248
+ PopoverContent,
249
+ {
250
+ side: side ?? (appearance === "bar" ? "bottom" : "right"),
251
+ align: align ?? (appearance === "bar" ? "end" : "start"),
252
+ className: "ui-app-launcher-popover",
253
+ "aria-label": labels.title,
254
+ children: panel
255
+ }
256
+ )
257
+ ] });
258
+ }
259
+ export {
260
+ AppLauncher
261
+ };
@@ -1,4 +1,6 @@
1
1
  import * as React from "react";
2
2
  import type { AppShellProp } from "../../props/components/layout.prop.js";
3
3
  export type { AppShellProp, AppShellProp as AppShellProps, } from "../../props/components/layout.prop.js";
4
- export declare function AppShell({ sidebar, topbar, topbarLeft, topbarRight, logo, breadcrumb, footer, children, sidebarCollapsed, responsiveNavigation, topbarSpan, navRail, navRailLabel, mobileNav, mobileNavLabel, mobileNavOpen, onMobileNavOpenChange, }: AppShellProp): React.JSX.Element;
4
+ /** Same rail boundary as shell-layout.css; SSR starts in docked mode. */
5
+ export declare function useAppShellNavigationMode(): "drawer" | "docked";
6
+ export declare function AppShell({ sidebar, topbar, topbarLeft, topbarRight, logo, breadcrumb, footer, children, sidebarCollapsed, responsiveNavigation, topbarSpan, navRail, navRailPosition, navRailEnd, navRailLabel, mobileNav, mobileNavLabel, mobileNavOpen, onMobileNavOpenChange, }: AppShellProp): React.JSX.Element;