@godxjp/ui 18.4.0 → 18.6.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 (159) hide show
  1. package/README.md +16 -1
  2. package/dist/app/theme-axes.d.ts +11 -3
  3. package/dist/app/theme-axes.js +2 -1
  4. package/dist/components/charts/chart-frame.d.ts +17 -3
  5. package/dist/components/charts/chart-frame.js +7 -1
  6. package/dist/components/charts/chart-summary.d.ts +21 -0
  7. package/dist/components/charts/chart-summary.js +32 -5
  8. package/dist/components/charts/compact-bar-trend.d.ts +30 -0
  9. package/dist/components/charts/compact-bar-trend.js +74 -0
  10. package/dist/components/charts/index.d.ts +6 -0
  11. package/dist/components/charts/index.js +2 -0
  12. package/dist/components/data-display/badge.d.ts +8 -0
  13. package/dist/components/data-display/badge.js +7 -1
  14. package/dist/components/data-display/data-table.d.ts +40 -4
  15. package/dist/components/data-display/data-table.js +69 -2
  16. package/dist/components/data-display/empty-state.js +1 -1
  17. package/dist/components/data-display/index.d.ts +4 -2
  18. package/dist/components/data-display/index.js +10 -1
  19. package/dist/components/data-display/list-row.d.ts +41 -4
  20. package/dist/components/data-display/list-row.js +23 -3
  21. package/dist/components/data-display/qr-code.d.ts +1 -1
  22. package/dist/components/data-display/service-launcher-card.d.ts +40 -0
  23. package/dist/components/data-display/service-launcher-card.js +97 -0
  24. package/dist/components/data-display/table.d.ts +47 -2
  25. package/dist/components/data-display/table.js +29 -4
  26. package/dist/components/data-entry/command-palette.d.ts +37 -0
  27. package/dist/components/data-entry/command-palette.js +125 -0
  28. package/dist/components/data-entry/command.d.ts +10 -10
  29. package/dist/components/data-entry/index.d.ts +3 -0
  30. package/dist/components/data-entry/index.js +2 -0
  31. package/dist/components/data-entry/input-otp.d.ts +1 -0
  32. package/dist/components/feedback/dialog.d.ts +16 -1
  33. package/dist/components/feedback/dialog.js +46 -33
  34. package/dist/components/feedback/index.d.ts +5 -2
  35. package/dist/components/feedback/index.js +8 -2
  36. package/dist/components/feedback/sheet.d.ts +26 -4
  37. package/dist/components/feedback/sheet.js +54 -7
  38. package/dist/components/feedback/two-factor-setup.d.ts +31 -0
  39. package/dist/components/feedback/two-factor-setup.js +97 -0
  40. package/dist/components/general/index.d.ts +1 -1
  41. package/dist/components/general/logo.d.ts +49 -9
  42. package/dist/components/general/logo.js +67 -14
  43. package/dist/components/layout/app-shell.d.ts +1 -1
  44. package/dist/components/layout/app-shell.js +55 -30
  45. package/dist/components/layout/auth-account-summary.d.ts +5 -0
  46. package/dist/components/layout/auth-account-summary.js +31 -0
  47. package/dist/components/layout/auth-divider.d.ts +7 -0
  48. package/dist/components/layout/auth-divider.js +21 -0
  49. package/dist/components/layout/auth-footer.d.ts +5 -0
  50. package/dist/components/layout/auth-footer.js +24 -0
  51. package/dist/components/layout/auth-identity.d.ts +5 -0
  52. package/dist/components/layout/auth-identity.js +17 -0
  53. package/dist/components/layout/auth-shell.d.ts +9 -1
  54. package/dist/components/layout/auth-shell.js +25 -6
  55. package/dist/components/layout/auth-stack.d.ts +4 -0
  56. package/dist/components/layout/auth-stack.js +8 -0
  57. package/dist/components/layout/centered-shell.d.ts +5 -2
  58. package/dist/components/layout/centered-shell.js +29 -19
  59. package/dist/components/layout/error-surface.d.ts +35 -0
  60. package/dist/components/layout/error-surface.js +155 -0
  61. package/dist/components/layout/flex.d.ts +1 -1
  62. package/dist/components/layout/flex.js +4 -0
  63. package/dist/components/layout/index.d.ts +23 -3
  64. package/dist/components/layout/index.js +21 -2
  65. package/dist/components/layout/legal-document-shell.d.ts +34 -0
  66. package/dist/components/layout/legal-document-shell.js +186 -0
  67. package/dist/components/layout/master-detail.d.ts +24 -0
  68. package/dist/components/layout/master-detail.js +48 -0
  69. package/dist/components/layout/org-switcher.d.ts +9 -0
  70. package/dist/components/layout/org-switcher.js +218 -0
  71. package/dist/components/layout/page-container.d.ts +1 -1
  72. package/dist/components/layout/page-container.js +7 -2
  73. package/dist/components/layout/sidebar-link.d.ts +43 -0
  74. package/dist/components/layout/sidebar-link.js +13 -0
  75. package/dist/components/layout/sidebar.d.ts +42 -5
  76. package/dist/components/layout/sidebar.js +170 -85
  77. package/dist/components/navigation/app-setting-picker.js +17 -6
  78. package/dist/components/navigation/filter-bar.d.ts +12 -3
  79. package/dist/components/navigation/filter-bar.js +8 -2
  80. package/dist/components/navigation/index.d.ts +2 -2
  81. package/dist/components/navigation/index.js +3 -1
  82. package/dist/components/navigation/steps.js +38 -19
  83. package/dist/components/navigation/tabs-scroll.d.ts +70 -0
  84. package/dist/components/navigation/tabs-scroll.js +76 -0
  85. package/dist/components/navigation/tabs.js +47 -23
  86. package/dist/components/ui/avatar.d.ts +2 -1
  87. package/dist/components/ui/avatar.js +2 -1
  88. package/dist/components/ui/input-otp.d.ts +4 -1
  89. package/dist/components/ui/input-otp.js +2 -1
  90. package/dist/components/ui/toggle-group.d.ts +7 -4
  91. package/dist/components/ui/toggle-group.js +32 -21
  92. package/dist/email/brand-mark.d.ts +108 -0
  93. package/dist/email/brand-mark.js +88 -0
  94. package/dist/email/color.d.ts +53 -0
  95. package/dist/email/color.js +37 -0
  96. package/dist/email/geometry.d.ts +120 -0
  97. package/dist/email/geometry.js +90 -0
  98. package/dist/email/index.d.ts +83 -0
  99. package/dist/email/index.js +82 -0
  100. package/dist/email/inline-style.d.ts +27 -0
  101. package/dist/email/inline-style.js +26 -0
  102. package/dist/email/tokens.generated.d.ts +167 -0
  103. package/dist/email/tokens.generated.js +162 -0
  104. package/dist/email/urgency.d.ts +22 -0
  105. package/dist/email/urgency.js +14 -0
  106. package/dist/i18n/messages/en.json +36 -3
  107. package/dist/i18n/messages/ja.json +36 -3
  108. package/dist/i18n/messages/vi.json +36 -3
  109. package/dist/inertia/index.d.ts +50 -0
  110. package/dist/inertia/index.js +5 -0
  111. package/dist/props/components/app.prop.d.ts +11 -1
  112. package/dist/props/components/charts.prop.d.ts +40 -1
  113. package/dist/props/components/data-display.prop.d.ts +75 -1
  114. package/dist/props/components/data-entry.prop.d.ts +6 -0
  115. package/dist/props/components/feedback.prop.d.ts +10 -0
  116. package/dist/props/components/index.d.ts +3 -3
  117. package/dist/props/components/layout.prop.d.ts +560 -10
  118. package/dist/props/components/layout.prop.js +1 -0
  119. package/dist/props/components/navigation.prop.d.ts +24 -2
  120. package/dist/props/registry.d.ts +433 -8
  121. package/dist/props/registry.js +527 -9
  122. package/dist/props/vocabulary/data.prop.d.ts +27 -0
  123. package/dist/props/vocabulary/index.d.ts +3 -3
  124. package/dist/props/vocabulary/interaction.prop.d.ts +10 -1
  125. package/dist/props/vocabulary/layout.prop.d.ts +49 -0
  126. package/dist/styles/base.css +8 -2
  127. package/dist/styles/card-layout.css +161 -7
  128. package/dist/styles/chart-layout.css +97 -0
  129. package/dist/styles/control.css +76 -2
  130. package/dist/styles/data-display-layout.css +78 -6
  131. package/dist/styles/dialog-layout.css +105 -4
  132. package/dist/styles/fonts.css +15 -4
  133. package/dist/styles/index.css +11 -3
  134. package/dist/styles/layout.css +466 -1
  135. package/dist/styles/logo-layout.css +95 -0
  136. package/dist/styles/navigation-layout.css +152 -0
  137. package/dist/styles/shell-layout.css +790 -40
  138. package/dist/styles/table-layout.css +164 -1
  139. package/dist/theme/dxs.canonical.css +77 -0
  140. package/dist/tokens/axes.css +40 -0
  141. package/dist/tokens/base.css +6 -0
  142. package/dist/tokens/components/card.css +48 -0
  143. package/dist/tokens/components/chart.css +47 -0
  144. package/dist/tokens/components/control.css +16 -0
  145. package/dist/tokens/components/data-display.css +13 -0
  146. package/dist/tokens/components/email.css +93 -0
  147. package/dist/tokens/components/error-surface.css +36 -0
  148. package/dist/tokens/components/feedback.css +17 -0
  149. package/dist/tokens/components/legal-document.css +67 -0
  150. package/dist/tokens/components/list-row.css +43 -2
  151. package/dist/tokens/components/logo.css +74 -0
  152. package/dist/tokens/components/navigation.css +28 -0
  153. package/dist/tokens/components/sheet.css +19 -0
  154. package/dist/tokens/components/shell.css +210 -0
  155. package/dist/tokens/components/sidebar.css +33 -0
  156. package/dist/tokens/components/table.css +45 -0
  157. package/dist/tokens/foundation.css +31 -2
  158. package/dist/tokens/semantic/layout.css +69 -2
  159. package/package.json +22 -5
@@ -1,4 +1,4 @@
1
- import { Badge } from "./badge.js";
1
+ import { Badge, StatusBadge } from "./badge.js";
2
2
  import { ListRow } from "./list-row.js";
3
3
  import { CredentialReveal } from "./credential-reveal.js";
4
4
  import { QrCode } from "./qr-code.js";
@@ -15,6 +15,11 @@ import {
15
15
  CardAction,
16
16
  StatCard
17
17
  } from "./card.js";
18
+ import {
19
+ ServiceCatalogCta,
20
+ ServiceLauncherCard,
21
+ ServiceLauncherCardSkeleton
22
+ } from "./service-launcher-card.js";
18
23
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table.js";
19
24
  import { Descriptions } from "./descriptions.js";
20
25
  import { DataTable, flexRender } from "./data-table.js";
@@ -90,7 +95,11 @@ export {
90
95
  QrCode,
91
96
  ScrollArea,
92
97
  ScrollBar,
98
+ ServiceCatalogCta,
99
+ ServiceLauncherCard,
100
+ ServiceLauncherCardSkeleton,
93
101
  StatCard,
102
+ StatusBadge,
94
103
  Table,
95
104
  TableBody,
96
105
  TableCell,
@@ -1,24 +1,61 @@
1
1
  import * as React from "react";
2
+ import type { ListRowDensityProp } from "../../props/components/data-display.prop.js";
2
3
  /**
3
- * ListRow a single-line entity row (leading · title/description · trailing) for SHORT lists
4
- * inside a Card: active sessions, API tokens, linked accounts, passkeys, MFA factors, invitations.
4
+ * ListRow vertical/inline geometry `default` (the roomy entity row) or `compact` (the
5
+ * inline-actions row: avatar + title + small trailing Buttons on one line in a narrow card).
6
+ * A ListRow-local subset of the density vocabulary — it has no `comfortable` step.
7
+ */
8
+ export type ListRowDensity = ListRowDensityProp;
9
+ /**
10
+ * ListRow — a single-line entity row (indicator · leading · title/description · trailing) for
11
+ * SHORT lists inside a Card: active sessions, API tokens, linked accounts, passkeys, MFA factors,
12
+ * invitations, notifications.
5
13
  * Use it INSTEAD of a hand-rolled `<div className="flex items-center justify-between border-b …">`.
6
14
  * DataTable is too heavy for a 2–4 item list, and nesting a Card per row would be card-in-card —
7
15
  * ListRow is the in-between surface. Drop rows into a `<Card><CardContent flush>…` and they stack
8
16
  * with a quiet divider; the trailing slot holds the row's action (Button / DropdownMenu / Switch).
17
+ *
18
+ * Overflow (#224): the content column always shrinks below its intrinsic width
19
+ * (`min-inline-size: min(--list-row-body-min-width, 100%)`) and the trailing actions wrap onto
20
+ * their own line at narrow container widths — a long title plus two Buttons never widens the page
21
+ * root. `overflow` picks how the long content resolves: `truncate` (default, one line + ellipsis)
22
+ * or `wrap` (multi-line, `overflow-wrap: anywhere`).
23
+ *
24
+ * Density (#246): `density="compact"` is the compact inline-actions geometry — tighter block
25
+ * padding/gap and a LOWER body threshold (`--list-row-compact-*`), so an avatar, the title and one
26
+ * or two small trailing Buttons stay on one line inside a ~326px card column at 390px. It only
27
+ * lowers thresholds, so the #224 wrap contract still holds.
9
28
  */
10
29
  export interface ListRowProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
11
30
  /** Render element — `div` (default) or `li` when the parent is a `<ul>`/`<ol>`. */
12
31
  as?: "div" | "li";
13
32
  /** Leading slot — a decorative icon or an Avatar. Mark a purely decorative icon `aria-hidden`. */
14
33
  leading?: React.ReactNode;
15
- /** Primary line — rendered in medium weight; truncates to a single line. */
34
+ /** Primary line — rendered in medium weight. */
16
35
  title: React.ReactNode;
17
- /** Secondary line under the title (muted, xs); truncates to a single line. */
36
+ /** Secondary line under the title (muted, xs). */
18
37
  description?: React.ReactNode;
19
38
  /** Trailing slot — the row action(s): a Button / DropdownMenu trigger, a Badge, or a Switch. */
20
39
  trailing?: React.ReactNode;
21
40
  /** Cross-axis alignment of the columns — `center` (default) or `start` for multi-line content. */
22
41
  align?: "center" | "start";
42
+ /**
43
+ * How title/description resolve content too long for the row — `truncate` (default: one line
44
+ * with an ellipsis) or `wrap` (multi-line; long unbroken tokens break so the row never widens).
45
+ */
46
+ overflow?: "truncate" | "wrap";
47
+ /**
48
+ * Row geometry — `default` (roomy entity row) or `compact` (#246): tighter block padding and
49
+ * column gap plus a lower body threshold, so a leading Avatar, the title/description and one or
50
+ * two small trailing Buttons stay INLINE inside a narrow card (≈326px content) at 390px, and a
51
+ * history Badge + date stays on the title's line. Retune per theme with `--list-row-compact-*`.
52
+ */
53
+ density?: ListRowDensity;
54
+ /**
55
+ * Read/unread state — renders the indicator dot (with localized `sr-only` text, never colour
56
+ * alone) and the tokenized unread surface. OMIT the prop entirely for rows that have no read
57
+ * state; pass `false` for a read row so its title stays on the same optical axis as unread ones.
58
+ */
59
+ unread?: boolean;
23
60
  }
24
61
  export declare const ListRow: React.ForwardRefExoticComponent<ListRowProps & React.RefAttributes<HTMLDivElement>>;
@@ -1,23 +1,43 @@
1
+ "use client";
1
2
  import { jsx, jsxs } from "react/jsx-runtime";
2
3
  import * as React from "react";
4
+ import { useTranslation } from "../../i18n/use-translation.js";
3
5
  import { cn } from "../../lib/utils.js";
4
6
  import { Text } from "../general/typography.js";
5
7
  const ListRow = React.forwardRef(
6
- ({ as = "div", leading, title, description, trailing, align = "center", className, ...props }, ref) => {
8
+ ({
9
+ as = "div",
10
+ leading,
11
+ title,
12
+ description,
13
+ trailing,
14
+ align = "center",
15
+ overflow = "truncate",
16
+ density = "default",
17
+ unread,
18
+ className,
19
+ ...props
20
+ }, ref) => {
21
+ const { t } = useTranslation();
7
22
  const Comp = as;
23
+ const truncate = overflow !== "wrap";
8
24
  return /* @__PURE__ */ jsxs(
9
25
  Comp,
10
26
  {
11
27
  ref,
12
28
  "data-slot": "list-row",
13
29
  "data-align": align === "start" ? "start" : void 0,
30
+ "data-overflow": overflow === "wrap" ? "wrap" : void 0,
31
+ "data-density": density === "compact" ? "compact" : void 0,
32
+ "data-unread": unread === true ? "" : void 0,
14
33
  className: cn("ui-list-row", className),
15
34
  ...props,
16
35
  children: [
36
+ unread !== void 0 ? /* @__PURE__ */ jsx("span", { "data-slot": "list-row-indicator", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: unread ? t("dataDisplay.listRow.unread") : t("dataDisplay.listRow.read") }) }) : null,
17
37
  leading != null ? /* @__PURE__ */ jsx("span", { "data-slot": "list-row-leading", children: leading }) : null,
18
38
  /* @__PURE__ */ jsxs("span", { "data-slot": "list-row-body", children: [
19
- /* @__PURE__ */ jsx(Text, { weight: "medium", truncate: true, children: title }),
20
- description != null ? /* @__PURE__ */ jsx(Text, { size: "xs", tone: "muted", truncate: true, children: description }) : null
39
+ /* @__PURE__ */ jsx(Text, { weight: "medium", truncate, children: title }),
40
+ description != null ? /* @__PURE__ */ jsx(Text, { size: "xs", tone: "muted", truncate, children: description }) : null
21
41
  ] }),
22
42
  trailing != null ? /* @__PURE__ */ jsx("span", { "data-slot": "list-row-trailing", children: trailing }) : null
23
43
  ]
@@ -5,4 +5,4 @@ export type QrCodeProps = QrCodeProp & Omit<React.ComponentPropsWithoutRef<"svg"
5
5
  * Renders a QR code entirely in-process. The encoded value is never sent to a network service,
6
6
  * written to an element attribute, or included in accessible text.
7
7
  */
8
- export declare const QrCode: React.ForwardRefExoticComponent<QrCodeProp & Omit<Omit<React.SVGProps<SVGSVGElement>, "ref">, "style" | "children" | "role" | "type" | keyof QrCodeProp> & React.RefAttributes<SVGSVGElement>>;
8
+ export declare const QrCode: React.ForwardRefExoticComponent<QrCodeProp & Omit<Omit<React.SVGProps<SVGSVGElement>, "ref">, "style" | "role" | "children" | "type" | keyof QrCodeProp> & React.RefAttributes<SVGSVGElement>>;
@@ -0,0 +1,40 @@
1
+ import * as React from "react";
2
+ import type { LucideIcon } from "lucide-react";
3
+ import type { HeadingLevelProp, ToneProp } from "../../props/vocabulary/index.js";
4
+ export type ServiceLauncherStatusTone = Extract<ToneProp, "success" | "warning" | "destructive" | "info" | "neutral" | "muted">;
5
+ export interface ServiceLauncherCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
6
+ icon: LucideIcon;
7
+ title: React.ReactNode;
8
+ titleLevel?: HeadingLevelProp;
9
+ statusLabel?: React.ReactNode;
10
+ statusTone?: ServiceLauncherStatusTone;
11
+ description?: React.ReactNode;
12
+ metadata?: React.ReactNode;
13
+ action: React.ReactNode;
14
+ disabledReason?: React.ReactNode;
15
+ }
16
+ /**
17
+ * Token-owned launcher surface for an organization-scoped downstream service.
18
+ *
19
+ * Consumers supply real status, metadata and actions; access is NEVER inferred — the component
20
+ * derives no entitlement, no launch URL and no disabled state of its own. `statusLabel`/
21
+ * `statusTone` are rendered verbatim, and the action's `disabled` state is the consumer's Button
22
+ * prop. The only thing derived from a prop is presentational: supplying `disabledReason` marks
23
+ * the tile `data-unavailable` so the token layer can drop the medallion's brand wash.
24
+ *
25
+ * Layout is NOT owned here: place tiles in `ResponsiveGrid columns={{ sm: 1, md: 2, lg: 3 }}` for
26
+ * the canonical 3 → 2 → 1 launcher grid (the grid queries its own container, never the viewport).
27
+ */
28
+ export declare const ServiceLauncherCard: React.ForwardRefExoticComponent<ServiceLauncherCardProps & React.RefAttributes<HTMLDivElement>>;
29
+ export interface ServiceCatalogCtaProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
30
+ icon?: LucideIcon;
31
+ title: React.ReactNode;
32
+ action: React.ReactNode;
33
+ }
34
+ /** Dashed companion tile for the real catalog/add action beside launcher cards. */
35
+ export declare const ServiceCatalogCta: React.ForwardRefExoticComponent<ServiceCatalogCtaProps & React.RefAttributes<HTMLDivElement>>;
36
+ export interface ServiceLauncherCardSkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
37
+ label: string;
38
+ }
39
+ /** Shape-matched loading placeholder for a launcher card. */
40
+ export declare function ServiceLauncherCardSkeleton({ className, label, ...props }: ServiceLauncherCardSkeletonProps): React.JSX.Element;
@@ -0,0 +1,97 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Plus } from "lucide-react";
5
+ import { cn } from "../../lib/utils.js";
6
+ import { Badge } from "./badge.js";
7
+ import { Card } from "./card.js";
8
+ const ServiceLauncherCard = React.forwardRef(
9
+ ({
10
+ className,
11
+ icon: Icon,
12
+ title,
13
+ titleLevel = 2,
14
+ statusLabel,
15
+ statusTone = "neutral",
16
+ description,
17
+ metadata,
18
+ action,
19
+ disabledReason,
20
+ ...props
21
+ }, ref) => {
22
+ const Heading = `h${titleLevel}`;
23
+ return /* @__PURE__ */ jsxs(
24
+ Card,
25
+ {
26
+ ref,
27
+ density: "tight",
28
+ className: cn("ui-service-launcher-card", className),
29
+ "data-service-launcher": "",
30
+ "data-unavailable": disabledReason != null ? "" : void 0,
31
+ ...props,
32
+ children: [
33
+ /* @__PURE__ */ jsxs("div", { "data-slot": "service-launcher-heading", children: [
34
+ /* @__PURE__ */ jsx("span", { "data-slot": "service-launcher-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon, {}) }),
35
+ /* @__PURE__ */ jsx(Heading, { "data-slot": "service-launcher-title", children: title }),
36
+ statusLabel != null ? /* @__PURE__ */ jsx(Badge, { tone: statusTone, "data-slot": "service-launcher-status", children: statusLabel }) : null
37
+ ] }),
38
+ description != null ? /* @__PURE__ */ jsx("div", { "data-slot": "service-launcher-description", children: description }) : null,
39
+ metadata != null ? /* @__PURE__ */ jsx("div", { "data-slot": "service-launcher-metadata", children: metadata }) : null,
40
+ disabledReason != null ? /* @__PURE__ */ jsx("div", { "data-slot": "service-launcher-disabled-reason", children: disabledReason }) : null,
41
+ /* @__PURE__ */ jsx("div", { "data-slot": "service-launcher-action", children: action })
42
+ ]
43
+ }
44
+ );
45
+ }
46
+ );
47
+ ServiceLauncherCard.displayName = "ServiceLauncherCard";
48
+ const ServiceCatalogCta = React.forwardRef(
49
+ ({ className, icon: Icon = Plus, title, action, ...props }, ref) => /* @__PURE__ */ jsxs(
50
+ Card,
51
+ {
52
+ ref,
53
+ variant: "outline",
54
+ className: cn("ui-service-catalog-cta", className),
55
+ "data-service-catalog-cta": "",
56
+ ...props,
57
+ children: [
58
+ /* @__PURE__ */ jsx(Icon, { "data-slot": "service-catalog-icon", "aria-hidden": "true" }),
59
+ /* @__PURE__ */ jsx("div", { "data-slot": "service-catalog-title", children: title }),
60
+ /* @__PURE__ */ jsx("div", { "data-slot": "service-catalog-action", children: action })
61
+ ]
62
+ }
63
+ )
64
+ );
65
+ ServiceCatalogCta.displayName = "ServiceCatalogCta";
66
+ function ServiceLauncherCardSkeleton({
67
+ className,
68
+ label,
69
+ ...props
70
+ }) {
71
+ return /* @__PURE__ */ jsxs(
72
+ Card,
73
+ {
74
+ density: "tight",
75
+ className: cn("ui-service-launcher-card", className),
76
+ "data-service-launcher": "",
77
+ "aria-busy": "true",
78
+ ...props,
79
+ children: [
80
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: label }),
81
+ /* @__PURE__ */ jsxs("div", { "data-slot": "service-launcher-skeleton-heading", children: [
82
+ /* @__PURE__ */ jsx("span", { className: "ui-skeleton-block", "data-slot": "service-launcher-skeleton-icon" }),
83
+ /* @__PURE__ */ jsx("span", { className: "ui-skeleton-block", "data-slot": "service-launcher-skeleton-title" }),
84
+ /* @__PURE__ */ jsx("span", { className: "ui-skeleton-block", "data-slot": "service-launcher-skeleton-status" })
85
+ ] }),
86
+ /* @__PURE__ */ jsx("span", { className: "ui-skeleton-block", "data-slot": "service-launcher-skeleton-description" }),
87
+ /* @__PURE__ */ jsx("span", { className: "ui-skeleton-block", "data-slot": "service-launcher-skeleton-metadata" }),
88
+ /* @__PURE__ */ jsx("span", { className: "ui-skeleton-block", "data-slot": "service-launcher-skeleton-action" })
89
+ ]
90
+ }
91
+ );
92
+ }
93
+ export {
94
+ ServiceCatalogCta,
95
+ ServiceLauncherCard,
96
+ ServiceLauncherCardSkeleton
97
+ };
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import type { BreakpointProp, TableColumnPriorityProp, TablePresetProp } from "../../props/vocabulary/index.js";
2
3
  export type TableProps = React.HTMLAttributes<HTMLTableElement> & {
3
4
  /**
4
5
  * Whether the Table owns its own horizontal-scroll region (default `true`). When `true` a
@@ -8,6 +9,23 @@ export type TableProps = React.HTMLAttributes<HTMLTableElement> & {
8
9
  * avoids a redundant NESTED scroll container and a duplicate keyboard focus stop for one table.
9
10
  */
10
11
  scrollable?: boolean;
12
+ /**
13
+ * Named collection contract. `"default"` (the default) emits no attribute and keeps the plain
14
+ * table exactly as it is. `"action-collection"` is the canonical dense approval / action queue
15
+ * (gh#253): below `collapseBelow`, the desktop intrinsic column widths — the thing that pushes
16
+ * the last columns outside a 390px viewport — are replaced by the token-owned column PRIORITY
17
+ * measures (`--table-action-collection-*`) under `table-layout: fixed`, and cells wrap instead
18
+ * of forcing a horizontal scroll. Mark each column with `priority` on its `TableHead`/`TableCell`.
19
+ * The table keeps its real semantics: no `display` change, no role rewriting, no card swap, so
20
+ * header association, `aria-sort` and screen-reader table navigation are identical at every width.
21
+ */
22
+ preset?: TablePresetProp;
23
+ /**
24
+ * Step at which `preset="action-collection"` switches to the priority measures, measured against
25
+ * the TABLE's own container (not the viewport), so a table inside a rail collapses before the
26
+ * page does. Defaults to `"sm"` (40rem). Ignored while `preset` is `"default"`.
27
+ */
28
+ collapseBelow?: BreakpointProp;
11
29
  };
12
30
  export declare const Table: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableElement> & {
13
31
  /**
@@ -18,9 +36,36 @@ export declare const Table: React.ForwardRefExoticComponent<React.HTMLAttributes
18
36
  * avoids a redundant NESTED scroll container and a duplicate keyboard focus stop for one table.
19
37
  */
20
38
  scrollable?: boolean;
39
+ /**
40
+ * Named collection contract. `"default"` (the default) emits no attribute and keeps the plain
41
+ * table exactly as it is. `"action-collection"` is the canonical dense approval / action queue
42
+ * (gh#253): below `collapseBelow`, the desktop intrinsic column widths — the thing that pushes
43
+ * the last columns outside a 390px viewport — are replaced by the token-owned column PRIORITY
44
+ * measures (`--table-action-collection-*`) under `table-layout: fixed`, and cells wrap instead
45
+ * of forcing a horizontal scroll. Mark each column with `priority` on its `TableHead`/`TableCell`.
46
+ * The table keeps its real semantics: no `display` change, no role rewriting, no card swap, so
47
+ * header association, `aria-sort` and screen-reader table navigation are identical at every width.
48
+ */
49
+ preset?: TablePresetProp;
50
+ /**
51
+ * Step at which `preset="action-collection"` switches to the priority measures, measured against
52
+ * the TABLE's own container (not the viewport), so a table inside a rail collapses before the
53
+ * page does. Defaults to `"sm"` (40rem). Ignored while `preset` is `"default"`.
54
+ */
55
+ collapseBelow?: BreakpointProp;
21
56
  } & React.RefAttributes<HTMLTableElement>>;
22
57
  export declare const TableHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
23
58
  export declare const TableBody: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
24
59
  export declare const TableRow: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableRowElement> & React.RefAttributes<HTMLTableRowElement>>;
25
- export declare const TableHead: React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>;
26
- export declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>;
60
+ /**
61
+ * Column priority carried by BOTH the header cell and the body cells of a column. Read only by
62
+ * `Table preset="action-collection"` below its collapse step, where it selects the column's
63
+ * token-owned measure; unset columns take the remaining space. Emitted as `data-priority` only
64
+ * when supplied, so an ordinary table gains no attribute.
65
+ */
66
+ type TableCellPriority = {
67
+ priority?: TableColumnPriorityProp;
68
+ };
69
+ export declare const TableHead: React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & TableCellPriority & React.RefAttributes<HTMLTableCellElement>>;
70
+ export declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & TableCellPriority & React.RefAttributes<HTMLTableCellElement>>;
71
+ export {};
@@ -3,16 +3,23 @@ import * as React from "react";
3
3
  import { tableHeadHeightClass } from "../../lib/control-styles.js";
4
4
  import { cn } from "../../lib/utils.js";
5
5
  const Table = React.forwardRef(
6
- ({ className, scrollable = true, ...props }, ref) => (
6
+ ({ className, scrollable = true, preset = "default", collapseBelow = "sm", ...props }, ref) => (
7
7
  // A table wider than its container scrolls horizontally in this wrapper; keep it
8
8
  // keyboard-reachable so it can be scrolled without a pointer (WCAG 2.1.1 / axe
9
9
  // scrollable-region-focusable). No landmark role — avoids landmark-unique collisions.
10
10
  // When `scrollable` is false an ancestor owns the scroll region, so this is a bare
11
11
  // positioning box (no `overflow`, no tab stop) to avoid a redundant nested scroller.
12
+ // The preset adds ONE class (the container the collapse step is measured against) and the
13
+ // step attribute; with `preset="default"` neither is emitted, so the box is byte-identical.
12
14
  /* @__PURE__ */ jsx(
13
15
  "div",
14
16
  {
15
- className: scrollable ? "relative w-full overflow-auto" : "relative w-full",
17
+ className: cn(
18
+ scrollable ? "relative w-full overflow-auto" : "relative w-full",
19
+ preset !== "default" && "ui-table-collection"
20
+ ),
21
+ "data-preset": preset === "default" ? void 0 : preset,
22
+ "data-collapse-below": preset === "default" ? void 0 : collapseBelow,
16
23
  ...scrollable ? { tabIndex: 0 } : {},
17
24
  children: /* @__PURE__ */ jsx(
18
25
  "table",
@@ -44,9 +51,27 @@ const TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__
44
51
  }
45
52
  ));
46
53
  TableRow.displayName = "TableRow";
47
- const TableHead = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("th", { ref, "data-slot": "table-head", className: cn(tableHeadHeightClass, className), ...props }));
54
+ const TableHead = React.forwardRef(({ className, priority, ...props }, ref) => /* @__PURE__ */ jsx(
55
+ "th",
56
+ {
57
+ ref,
58
+ "data-slot": "table-head",
59
+ "data-priority": priority,
60
+ className: cn(tableHeadHeightClass, className),
61
+ ...props
62
+ }
63
+ ));
48
64
  TableHead.displayName = "TableHead";
49
- const TableCell = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("td", { ref, "data-slot": "table-cell", className: cn(className), ...props }));
65
+ const TableCell = React.forwardRef(({ className, priority, ...props }, ref) => /* @__PURE__ */ jsx(
66
+ "td",
67
+ {
68
+ ref,
69
+ "data-slot": "table-cell",
70
+ "data-priority": priority,
71
+ className: cn(className),
72
+ ...props
73
+ }
74
+ ));
50
75
  TableCell.displayName = "TableCell";
51
76
  export {
52
77
  Table,
@@ -0,0 +1,37 @@
1
+ import * as React from "react";
2
+ export type CommandPaletteItem = {
3
+ id: string;
4
+ label: React.ReactNode;
5
+ searchValue?: string;
6
+ meta?: React.ReactNode;
7
+ disabled?: boolean;
8
+ };
9
+ export type CommandPaletteGroup = {
10
+ id: string;
11
+ label: React.ReactNode;
12
+ items: CommandPaletteItem[];
13
+ };
14
+ export type CommandPaletteLabels = {
15
+ open: string;
16
+ title: string;
17
+ description: string;
18
+ placeholder: string;
19
+ empty: React.ReactNode;
20
+ loading?: React.ReactNode;
21
+ move?: React.ReactNode;
22
+ select?: React.ReactNode;
23
+ close?: React.ReactNode;
24
+ };
25
+ export type CommandPaletteProps = {
26
+ groups: CommandPaletteGroup[];
27
+ labels: CommandPaletteLabels;
28
+ onSelect: (item: CommandPaletteItem) => void;
29
+ open?: boolean;
30
+ defaultOpen?: boolean;
31
+ onOpenChange?: (open: boolean) => void;
32
+ loading?: boolean;
33
+ error?: React.ReactNode;
34
+ trigger?: React.ReactNode;
35
+ shortcut?: boolean;
36
+ };
37
+ export declare function CommandPalette({ groups, labels, onSelect, open: controlledOpen, defaultOpen, onOpenChange, loading, error, trigger, shortcut, }: CommandPaletteProps): React.JSX.Element;
@@ -0,0 +1,125 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Search } from "lucide-react";
5
+ import { Button } from "../general/button.js";
6
+ import { Dialog, DialogContent } from "../feedback/dialog.js";
7
+ import {
8
+ Command,
9
+ CommandEmpty,
10
+ CommandGroup,
11
+ CommandInput,
12
+ CommandItem,
13
+ CommandList
14
+ } from "./command.js";
15
+ function CommandPalette({
16
+ groups,
17
+ labels,
18
+ onSelect,
19
+ open: controlledOpen,
20
+ defaultOpen = false,
21
+ onOpenChange,
22
+ loading = false,
23
+ error,
24
+ trigger,
25
+ shortcut = true
26
+ }) {
27
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
28
+ const shortcutRestoreFocusRef = React.useRef(null);
29
+ const open = controlledOpen ?? uncontrolledOpen;
30
+ const setOpen = React.useCallback(
31
+ (next) => {
32
+ if (controlledOpen === void 0) {
33
+ setUncontrolledOpen(next);
34
+ }
35
+ onOpenChange?.(next);
36
+ },
37
+ [controlledOpen, onOpenChange]
38
+ );
39
+ React.useEffect(() => {
40
+ if (!shortcut) return;
41
+ const handleKeyDown = (event) => {
42
+ if (!event.isComposing && event.key.toLowerCase() === "k" && (event.metaKey || event.ctrlKey)) {
43
+ event.preventDefault();
44
+ if (!open && document.activeElement instanceof HTMLElement) {
45
+ shortcutRestoreFocusRef.current = document.activeElement;
46
+ }
47
+ setOpen(!open);
48
+ }
49
+ };
50
+ document.addEventListener("keydown", handleKeyDown);
51
+ return () => document.removeEventListener("keydown", handleKeyDown);
52
+ }, [open, setOpen, shortcut]);
53
+ const triggerNode = trigger ?? /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "ui-command-palette-trigger", children: [
54
+ /* @__PURE__ */ jsx(Search, { "aria-hidden": "true" }),
55
+ /* @__PURE__ */ jsx("span", { children: labels.open }),
56
+ /* @__PURE__ */ jsx("span", { className: "kbd", "aria-hidden": "true", children: "\u2318K" })
57
+ ] });
58
+ return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange: setOpen, children: [
59
+ /* @__PURE__ */ jsx(Dialog.Trigger, { asChild: true, children: triggerNode }),
60
+ /* @__PURE__ */ jsxs(
61
+ DialogContent,
62
+ {
63
+ className: "ui-command-palette",
64
+ showCloseButton: false,
65
+ "aria-modal": "true",
66
+ "aria-describedby": "ui-command-palette-description",
67
+ onCloseAutoFocus: (event) => {
68
+ const restoreTarget = shortcutRestoreFocusRef.current;
69
+ if (restoreTarget?.isConnected) {
70
+ event.preventDefault();
71
+ requestAnimationFrame(() => {
72
+ if (restoreTarget.isConnected) {
73
+ restoreTarget.focus({ preventScroll: true });
74
+ }
75
+ });
76
+ }
77
+ shortcutRestoreFocusRef.current = null;
78
+ },
79
+ children: [
80
+ /* @__PURE__ */ jsx(Dialog.Title, { className: "sr-only", children: labels.title }),
81
+ /* @__PURE__ */ jsx(Dialog.Description, { id: "ui-command-palette-description", className: "sr-only", children: labels.description }),
82
+ /* @__PURE__ */ jsxs(Command, { label: labels.title, children: [
83
+ /* @__PURE__ */ jsx(CommandInput, { autoFocus: true, placeholder: labels.placeholder, "aria-label": labels.placeholder }),
84
+ /* @__PURE__ */ jsx(CommandList, { "aria-busy": loading, children: loading ? /* @__PURE__ */ jsx("div", { className: "ui-command-palette-state", role: "status", children: labels.loading }) : error ? /* @__PURE__ */ jsx("div", { className: "ui-command-palette-state", role: "alert", children: error }) : /* @__PURE__ */ jsxs(Fragment, { children: [
85
+ /* @__PURE__ */ jsx(CommandEmpty, { children: labels.empty }),
86
+ groups.map((group) => /* @__PURE__ */ jsx(CommandGroup, { heading: group.label, children: group.items.map((item) => /* @__PURE__ */ jsxs(
87
+ CommandItem,
88
+ {
89
+ value: item.searchValue ?? `${item.id} ${String(item.label)}`,
90
+ disabled: item.disabled,
91
+ onSelect: () => {
92
+ setOpen(false);
93
+ onSelect(item);
94
+ },
95
+ children: [
96
+ /* @__PURE__ */ jsx("span", { className: "ui-command-palette-label", children: item.label }),
97
+ item.meta != null ? /* @__PURE__ */ jsx("span", { className: "ui-command-palette-meta", children: item.meta }) : null
98
+ ]
99
+ },
100
+ item.id
101
+ )) }, group.id))
102
+ ] }) })
103
+ ] }),
104
+ labels.move != null || labels.select != null || labels.close != null ? /* @__PURE__ */ jsxs("div", { className: "ui-command-palette-hints", "aria-hidden": "true", children: [
105
+ labels.move != null ? /* @__PURE__ */ jsxs("span", { children: [
106
+ "\u2191\u2193 ",
107
+ labels.move
108
+ ] }) : null,
109
+ labels.select != null ? /* @__PURE__ */ jsxs("span", { children: [
110
+ "\u21B5 ",
111
+ labels.select
112
+ ] }) : null,
113
+ labels.close != null ? /* @__PURE__ */ jsxs("span", { children: [
114
+ "esc ",
115
+ labels.close
116
+ ] }) : null
117
+ ] }) : null
118
+ ]
119
+ }
120
+ )
121
+ ] });
122
+ }
123
+ export {
124
+ CommandPalette
125
+ };
@@ -1,11 +1,11 @@
1
1
  import * as React from "react";
2
2
  export declare const Command: React.ForwardRefExoticComponent<Omit<{
3
3
  children?: React.ReactNode;
4
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
4
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
5
5
  ref?: React.Ref<HTMLDivElement>;
6
6
  } & {
7
7
  asChild?: boolean;
8
- }, keyof React.HTMLAttributes<HTMLDivElement> | "key" | "asChild"> & {
8
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
9
9
  label?: string;
10
10
  shouldFilter?: boolean;
11
11
  filter?: (value: string, search: string, keywords?: string[]) => number;
@@ -26,38 +26,38 @@ export declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pic
26
26
  } & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
27
27
  export declare const CommandList: React.ForwardRefExoticComponent<Omit<{
28
28
  children?: React.ReactNode;
29
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
29
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
30
30
  ref?: React.Ref<HTMLDivElement>;
31
31
  } & {
32
32
  asChild?: boolean;
33
- }, keyof React.HTMLAttributes<HTMLDivElement> | "key" | "asChild"> & {
33
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
34
34
  label?: string;
35
35
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
36
36
  export declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
37
37
  children?: React.ReactNode;
38
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
38
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
39
39
  ref?: React.Ref<HTMLDivElement>;
40
40
  } & {
41
41
  asChild?: boolean;
42
- }, keyof React.HTMLAttributes<HTMLDivElement> | "key" | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
42
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
43
43
  export declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
44
44
  children?: React.ReactNode;
45
- } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
45
+ } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
46
46
  ref?: React.Ref<HTMLDivElement>;
47
47
  } & {
48
48
  asChild?: boolean;
49
- }, keyof React.HTMLAttributes<HTMLDivElement> | "key" | "asChild">, "value" | "heading"> & {
49
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "value" | "heading"> & {
50
50
  heading?: React.ReactNode;
51
51
  value?: string;
52
52
  forceMount?: boolean;
53
53
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
54
54
  export declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
55
55
  children?: React.ReactNode;
56
- } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
56
+ } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
57
57
  ref?: React.Ref<HTMLDivElement>;
58
58
  } & {
59
59
  asChild?: boolean;
60
- }, keyof React.HTMLAttributes<HTMLDivElement> | "key" | "asChild">, "onSelect" | "value" | "disabled"> & {
60
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "value" | "disabled"> & {
61
61
  disabled?: boolean;
62
62
  onSelect?: (value: string) => void;
63
63
  value?: string;