@godxjp/ui 18.8.0 → 18.10.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 (83) hide show
  1. package/LICENSE +202 -0
  2. package/dist/components/data-display/badge.d.ts +7 -0
  3. package/dist/components/data-display/badge.js +1 -1
  4. package/dist/components/data-display/card.d.ts +3 -27
  5. package/dist/components/data-display/card.js +1 -4
  6. package/dist/components/data-display/data-table.js +2 -2
  7. package/dist/components/data-display/index.d.ts +2 -0
  8. package/dist/components/data-display/index.js +2 -0
  9. package/dist/components/data-display/permission-matrix.d.ts +26 -0
  10. package/dist/components/data-display/permission-matrix.js +219 -0
  11. package/dist/components/data-display/table.d.ts +12 -0
  12. package/dist/components/data-entry/branch-scope-picker.d.ts +43 -0
  13. package/dist/components/data-entry/branch-scope-picker.js +200 -0
  14. package/dist/components/data-entry/command-palette.js +8 -1
  15. package/dist/components/data-entry/index.d.ts +2 -0
  16. package/dist/components/data-entry/index.js +2 -0
  17. package/dist/components/data-entry/input-otp.d.ts +1 -1
  18. package/dist/components/feedback/alert.d.ts +2 -20
  19. package/dist/components/feedback/alert.js +1 -11
  20. package/dist/components/feedback/banner.d.ts +21 -0
  21. package/dist/components/feedback/banner.js +15 -0
  22. package/dist/components/feedback/index.d.ts +4 -2
  23. package/dist/components/feedback/index.js +2 -2
  24. package/dist/components/general/typography.d.ts +1 -0
  25. package/dist/components/general/typography.js +32 -13
  26. package/dist/components/layout/auth-shell.d.ts +2 -2
  27. package/dist/components/layout/index.d.ts +2 -2
  28. package/dist/components/layout/index.js +2 -2
  29. package/dist/components/layout/page-container.d.ts +1 -1
  30. package/dist/components/layout/page-container.js +45 -19
  31. package/dist/components/layout/service-role-panel.d.ts +25 -0
  32. package/dist/components/layout/service-role-panel.js +206 -0
  33. package/dist/components/navigation/filter-bar.d.ts +2 -2
  34. package/dist/components/navigation/filter-bar.js +113 -34
  35. package/dist/components/navigation/index.d.ts +1 -1
  36. package/dist/components/navigation/steps.d.ts +2 -2
  37. package/dist/components/navigation/steps.js +2 -4
  38. package/dist/components/ui/avatar.d.ts +1 -1
  39. package/dist/components/ui/avatar.js +1 -2
  40. package/dist/components/ui/input-otp.d.ts +3 -15
  41. package/dist/components/ui/input-otp.js +1 -2
  42. package/dist/email/tokens.generated.d.ts +2 -2
  43. package/dist/email/tokens.generated.js +2 -2
  44. package/dist/i18n/messages/en.json +56 -4
  45. package/dist/i18n/messages/ja.json +51 -5
  46. package/dist/i18n/messages/vi.json +50 -4
  47. package/dist/props/components/data-display.prop.d.ts +66 -16
  48. package/dist/props/components/data-entry.prop.d.ts +54 -7
  49. package/dist/props/components/feedback.prop.d.ts +3 -3
  50. package/dist/props/components/general.prop.d.ts +8 -1
  51. package/dist/props/components/layout.prop.d.ts +75 -54
  52. package/dist/props/components/navigation.prop.d.ts +77 -59
  53. package/dist/props/registry.d.ts +273 -72
  54. package/dist/props/registry.js +361 -92
  55. package/dist/props/vocabulary/content.prop.d.ts +5 -0
  56. package/dist/props/vocabulary/index.d.ts +1 -1
  57. package/dist/props/vocabulary/interaction.prop.d.ts +4 -7
  58. package/dist/props/vocabulary/layout.prop.d.ts +2 -2
  59. package/dist/styles/alert-layout.css +15 -32
  60. package/dist/styles/badge-layout.css +5 -0
  61. package/dist/styles/card-layout.css +13 -49
  62. package/dist/styles/control.css +2 -12
  63. package/dist/styles/data-display-layout.css +0 -16
  64. package/dist/styles/layout.css +102 -108
  65. package/dist/styles/navigation-layout.css +3 -8
  66. package/dist/styles/shell-layout.css +17 -17
  67. package/dist/styles/table-layout.css +77 -2
  68. package/dist/styles/text-layout.css +13 -0
  69. package/dist/tokens/base.css +1 -0
  70. package/dist/tokens/components/badge.css +5 -0
  71. package/dist/tokens/components/banner.css +16 -0
  72. package/dist/tokens/components/card.css +0 -12
  73. package/dist/tokens/components/control.css +0 -16
  74. package/dist/tokens/components/data-display.css +0 -12
  75. package/dist/tokens/components/email.css +2 -8
  76. package/dist/tokens/components/feedback.css +0 -20
  77. package/dist/tokens/components/navigation.css +10 -34
  78. package/dist/tokens/components/shell.css +24 -36
  79. package/dist/tokens/components/table.css +41 -1
  80. package/dist/tokens/semantic/layout.css +5 -12
  81. package/package.json +15 -2
  82. package/dist/components/layout/page-header.d.ts +0 -22
  83. package/dist/components/layout/page-header.js +0 -89
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+ import type { ServiceRolePanelProp } from "../../props/components/layout.prop.js";
3
+ export type { ServiceRoleItemProp, ServiceRolePanelProp, ServiceRolePanelProp as ServiceRolePanelProps, } from "../../props/components/layout.prop.js";
4
+ /**
5
+ * ServiceRolePanel — the canonical role-collection ⇄ role-detail surface (gh#257 / DXS
6
+ * platform#311).
7
+ *
8
+ * A THIN formalized composition over `MasterDetail` (which owns ALL geometry: rail tracks, gap,
9
+ * stacking below the threshold — 1440/1024 two-track, 390 stacked list-then-detail) plus real
10
+ * primitives, exported because a consumer cannot import a docs page (the gh#251 lesson). What the
11
+ * panel adds is exactly the contract every service-role screen kept re-deriving:
12
+ *
13
+ * - **Selection** as the controlled triad (`value`/`defaultValue`/`onValueChange`, defaulting to
14
+ * the first role). Each role row is a real `Button` carrying `aria-current`, and selecting moves
15
+ * focus-target wiring through `MasterDetail`'s `detailId`/`tabIndex={-1}` detail region.
16
+ * - **Destructive confirmation built in**: `onDeleteRole`'s presence arms a per-role delete
17
+ * affordance behind the package `AlertDialog` (variant `destructive`); the handler fires only
18
+ * after the user confirms. Roles marked `locked` (system roles) never offer deletion and show a
19
+ * localized lock badge; `readOnly` hides every mutating affordance.
20
+ * - **Lifecycle states** mirror the DataTable #216 vocabulary and precedence:
21
+ * `loading` → `denied` → `error` → `empty` → content.
22
+ * - **Domain-neutral**: the roles and the detail surface (`children`, node or render-function) are
23
+ * consumer-supplied; no platform role or permission is encoded.
24
+ */
25
+ export declare const ServiceRolePanel: React.ForwardRefExoticComponent<ServiceRolePanelProp & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,206 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { AlertCircle, Lock, RefreshCw, ShieldAlert, Trash2 } from "lucide-react";
5
+ import { useTranslation } from "../../i18n/use-translation.js";
6
+ import { cn } from "../../lib/utils.js";
7
+ import { Badge } from "../data-display/badge.js";
8
+ import { EmptyState } from "../data-display/empty-state.js";
9
+ import { AlertDialog } from "../feedback/dialog.js";
10
+ import { SkeletonRows } from "../feedback/skeleton.js";
11
+ import { Button } from "../general/button.js";
12
+ import { Text } from "../general/typography.js";
13
+ import { MasterDetail } from "./master-detail.js";
14
+ const ServiceRolePanel = React.forwardRef(
15
+ function ServiceRolePanel2({
16
+ roles,
17
+ value: controlledValue,
18
+ defaultValue,
19
+ onValueChange,
20
+ children,
21
+ onDeleteRole,
22
+ readOnly = false,
23
+ loading = false,
24
+ empty,
25
+ error,
26
+ denied,
27
+ onRetry,
28
+ masterLabel,
29
+ detailLabel,
30
+ railWidth,
31
+ masterViewport,
32
+ collapseBelow,
33
+ id,
34
+ className
35
+ }, ref) {
36
+ const { t } = useTranslation();
37
+ const reactId = React.useId();
38
+ const rootId = id ?? `service-role-panel-${reactId}`;
39
+ const detailId = `${rootId}-detail`;
40
+ const [uncontrolled, setUncontrolled] = React.useState(
41
+ defaultValue ?? roles[0]?.id
42
+ );
43
+ const value = controlledValue ?? uncontrolled;
44
+ const selectedRole = roles.find((role) => role.id === value);
45
+ const select = (roleId) => {
46
+ if (controlledValue === void 0) setUncontrolled(roleId);
47
+ onValueChange?.(roleId);
48
+ };
49
+ const [pendingDelete, setPendingDelete] = React.useState(null);
50
+ const isDenied = denied !== void 0 && denied !== null && denied !== false;
51
+ const isError = error !== void 0 && error !== null && error !== false;
52
+ const deletable = typeof onDeleteRole === "function" && !readOnly;
53
+ const surface = (state) => /* @__PURE__ */ jsx(
54
+ "div",
55
+ {
56
+ ref,
57
+ id: rootId,
58
+ "data-slot": "service-role-panel",
59
+ className: cn("ui-service-role-panel", className),
60
+ children: state
61
+ }
62
+ );
63
+ if (loading) {
64
+ return surface(
65
+ /* @__PURE__ */ jsx("div", { "aria-busy": "true", "aria-label": t("layout.serviceRolePanel.loading"), role: "status", children: /* @__PURE__ */ jsx(SkeletonRows, { rows: 5, columns: 3 }) })
66
+ );
67
+ }
68
+ if (isDenied) {
69
+ return surface(
70
+ /* @__PURE__ */ jsx("div", { "aria-live": "polite", children: denied === true ? /* @__PURE__ */ jsx(
71
+ EmptyState,
72
+ {
73
+ icon: ShieldAlert,
74
+ tone: "warning",
75
+ variant: "section",
76
+ title: t("layout.serviceRolePanel.denied"),
77
+ description: t("layout.serviceRolePanel.deniedDescription"),
78
+ titleAs: "p"
79
+ }
80
+ ) : denied })
81
+ );
82
+ }
83
+ if (isError) {
84
+ return surface(
85
+ /* @__PURE__ */ jsx("div", { role: "alert", children: error === true ? /* @__PURE__ */ jsx(
86
+ EmptyState,
87
+ {
88
+ icon: AlertCircle,
89
+ tone: "destructive",
90
+ variant: "section",
91
+ title: t("layout.serviceRolePanel.error"),
92
+ description: t("layout.serviceRolePanel.errorDescription"),
93
+ titleAs: "p",
94
+ action: onRetry ? /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: onRetry, children: [
95
+ /* @__PURE__ */ jsx(RefreshCw, { "aria-hidden": "true" }),
96
+ t("common.retry")
97
+ ] }) : void 0
98
+ }
99
+ ) : error })
100
+ );
101
+ }
102
+ if (roles.length === 0) {
103
+ return surface(
104
+ /* @__PURE__ */ jsx("div", { "aria-live": "polite", children: empty ?? /* @__PURE__ */ jsx(
105
+ EmptyState,
106
+ {
107
+ variant: "section",
108
+ title: t("layout.serviceRolePanel.empty"),
109
+ description: t("layout.serviceRolePanel.emptyDescription"),
110
+ titleAs: "p"
111
+ }
112
+ ) })
113
+ );
114
+ }
115
+ const detail = typeof children === "function" ? children(selectedRole) : children ?? /* @__PURE__ */ jsx(
116
+ EmptyState,
117
+ {
118
+ variant: "compact",
119
+ title: t("layout.serviceRolePanel.noDetail"),
120
+ titleAs: "p"
121
+ }
122
+ );
123
+ return surface(
124
+ /* @__PURE__ */ jsxs(Fragment, { children: [
125
+ /* @__PURE__ */ jsx(
126
+ MasterDetail,
127
+ {
128
+ rail: "master",
129
+ railWidth,
130
+ masterViewport,
131
+ collapseBelow,
132
+ masterLabel: masterLabel ?? t("layout.serviceRolePanel.rolesLabel"),
133
+ detailLabel: detailLabel ?? t("layout.serviceRolePanel.detailLabel"),
134
+ detailId,
135
+ master: /* @__PURE__ */ jsx("ul", { className: "flex list-none flex-col gap-1", "data-slot": "service-role-panel-list", children: roles.map((role) => {
136
+ const selected = role.id === value;
137
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1", children: [
138
+ /* @__PURE__ */ jsx(
139
+ Button,
140
+ {
141
+ variant: selected ? "secondary" : "ghost",
142
+ className: "h-auto flex-1 justify-start py-2 text-start",
143
+ "aria-current": selected ? "true" : void 0,
144
+ "aria-controls": detailId,
145
+ onClick: () => select(role.id),
146
+ children: /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col items-start leading-tight", children: [
147
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex max-w-full items-center gap-1.5", children: [
148
+ /* @__PURE__ */ jsx(Text, { weight: "medium", className: "truncate", children: role.name }),
149
+ role.locked && /* @__PURE__ */ jsxs(Badge, { tone: "default", variant: "outline", children: [
150
+ /* @__PURE__ */ jsx(Lock, { "aria-hidden": "true" }),
151
+ t("layout.serviceRolePanel.locked")
152
+ ] })
153
+ ] }),
154
+ (role.description !== void 0 || role.memberCount !== void 0) && /* @__PURE__ */ jsx(Text, { size: "2xs", tone: "muted", className: "max-w-full truncate", children: [
155
+ role.description,
156
+ role.memberCount !== void 0 ? (
157
+ // `{count}` is Intl.NumberFormat-grouped by `interpolate`,
158
+ // pluralized by CLDR category — no hand-built formatting.
159
+ t("layout.serviceRolePanel.memberCount", {
160
+ count: role.memberCount
161
+ })
162
+ ) : void 0
163
+ ].filter((part) => part !== void 0).join(" \xB7 ") })
164
+ ] })
165
+ }
166
+ ),
167
+ deletable && !role.locked && /* @__PURE__ */ jsx(
168
+ Button,
169
+ {
170
+ variant: "ghost",
171
+ size: "icon-sm",
172
+ "aria-label": t("layout.serviceRolePanel.deleteRole", { role: role.name }),
173
+ onClick: () => setPendingDelete(role),
174
+ children: /* @__PURE__ */ jsx(Trash2, { "aria-hidden": "true" })
175
+ }
176
+ )
177
+ ] }, role.id);
178
+ }) }),
179
+ children: detail
180
+ }
181
+ ),
182
+ deletable && /* @__PURE__ */ jsx(
183
+ AlertDialog,
184
+ {
185
+ open: pendingDelete !== null,
186
+ onOpenChange: (open) => {
187
+ if (!open) setPendingDelete(null);
188
+ },
189
+ title: t("layout.serviceRolePanel.deleteTitle"),
190
+ description: pendingDelete ? t("layout.serviceRolePanel.deleteDescription", { role: pendingDelete.name }) : void 0,
191
+ confirmLabel: t("layout.serviceRolePanel.deleteConfirm"),
192
+ variant: "destructive",
193
+ onConfirm: () => {
194
+ if (pendingDelete) onDeleteRole?.(pendingDelete.id);
195
+ setPendingDelete(null);
196
+ }
197
+ }
198
+ )
199
+ ] })
200
+ );
201
+ }
202
+ );
203
+ ServiceRolePanel.displayName = "ServiceRolePanel";
204
+ export {
205
+ ServiceRolePanel
206
+ };
@@ -1,6 +1,6 @@
1
1
  import type { ToolbarGroupProp, ToolbarProp } from "../../props/components/navigation.prop.js";
2
- export type { FilterBarChipProp, FilterBarChipProp as FilterBarChipProps, FilterBarOverflowProp, ToolbarGroupProp, ToolbarGroupProp as ToolbarGroupProps, ToolbarGroupProp as FilterBarGroupProp, ToolbarGroupProp as FilterBarGroupProps, ToolbarProp, ToolbarProp as ToolbarProps, ToolbarProp as FilterBarProp, ToolbarProp as FilterBarProps, } from "../../props/components/navigation.prop.js";
3
- export declare function Toolbar({ onClear, hasActiveFilters, sticky, overflow, search, chips, onChipRemove, resultCount, actions, className, children, }: ToolbarProp): import("react").JSX.Element;
2
+ export type { FilterBarChipProp, FilterBarChipProp as FilterBarChipProps, FilterBarFilterProp, FilterBarFilterProp as FilterBarFilterProps, FilterBarOverflowProp, FilterBarSearchProp, FilterBarSearchProp as FilterBarSearchProps, ToolbarGroupProp, ToolbarGroupProp as ToolbarGroupProps, ToolbarGroupProp as FilterBarGroupProp, ToolbarGroupProp as FilterBarGroupProps, ToolbarProp, ToolbarProp as ToolbarProps, ToolbarProp as FilterBarProp, ToolbarProp as FilterBarProps, } from "../../props/components/navigation.prop.js";
3
+ export declare function Toolbar({ onClear, hasActiveFilters, sticky, overflow, search, filters, chips, onChipRemove, actions, resultCount, loading, disabled, error, className, children, }: ToolbarProp): import("react").JSX.Element;
4
4
  export declare function ToolbarGroup({ label, controlId, className, children }: ToolbarGroupProp): import("react").JSX.Element;
5
5
  /**
6
6
  * Canonical list-page filter strip.
@@ -4,6 +4,9 @@ import { useId } from "react";
4
4
  import { X } from "lucide-react";
5
5
  import { useTranslation } from "../../i18n/use-translation.js";
6
6
  import { Button } from "../general/button.js";
7
+ import { Badge } from "../data-display/badge.js";
8
+ import { SearchInput } from "../data-entry/search-input.js";
9
+ import { Select } from "../data-entry/select.js";
7
10
  import { cn } from "../../lib/utils.js";
8
11
  function Toolbar({
9
12
  onClear,
@@ -11,65 +14,141 @@ function Toolbar({
11
14
  sticky = false,
12
15
  overflow = "wrap",
13
16
  search,
17
+ filters,
14
18
  chips,
15
19
  onChipRemove,
16
- resultCount,
17
20
  actions,
21
+ resultCount,
22
+ loading,
23
+ disabled,
24
+ error,
18
25
  className,
19
26
  children
20
27
  }) {
21
28
  const { t } = useTranslation();
22
- const hasChips = chips != null && chips.length > 0;
29
+ const reactId = useId();
30
+ const hasModel = search !== void 0 || filters !== void 0 || chips !== void 0 || onChipRemove !== void 0 || actions !== void 0 || resultCount !== void 0 || loading !== void 0 || disabled !== void 0 || error !== void 0;
31
+ if (!hasModel) {
32
+ return /* @__PURE__ */ jsxs(
33
+ "div",
34
+ {
35
+ role: "toolbar",
36
+ "aria-label": t("navigation.toolbar.ariaLabel"),
37
+ "data-overflow": overflow,
38
+ className: cn("ui-toolbar", sticky && "ui-toolbar-sticky", className),
39
+ children: [
40
+ children,
41
+ onClear && hasActiveFilters && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: onClear, className: "ui-toolbar-clear", children: [
42
+ /* @__PURE__ */ jsx(X, { "aria-hidden": "true" }),
43
+ t("common.clearFilters")
44
+ ] })
45
+ ]
46
+ }
47
+ );
48
+ }
49
+ const showClear = Boolean(onClear && hasActiveFilters);
50
+ const showChips = Boolean(chips && chips.length > 0);
51
+ const showMeta = error != null || resultCount !== void 0;
23
52
  return /* @__PURE__ */ jsxs(
24
53
  "div",
25
54
  {
26
- role: "toolbar",
27
- "aria-label": t("navigation.toolbar.ariaLabel"),
28
- "data-overflow": overflow,
29
- className: cn("ui-toolbar", sticky && "ui-toolbar-sticky", className),
55
+ className: cn("ui-filter-bar", sticky && "ui-toolbar-sticky", className),
56
+ "data-loading": loading || void 0,
30
57
  children: [
31
- search != null && // A region, not a bare child, so the search control gets ONE measure
32
- // (--filter-bar-search-width) across every list page instead of whatever width the
33
- // caller's control happened to have.
34
- /* @__PURE__ */ jsx("div", { className: "ui-filter-bar-search", children: search }),
35
- children,
36
- hasChips && // `group` (not a second toolbar) — a toolbar may own a group, and the chips are a labelled
37
- // set of related controls rather than an independent toolbar competing for the same role.
38
- /* @__PURE__ */ jsx(
58
+ /* @__PURE__ */ jsxs(
59
+ "div",
60
+ {
61
+ role: "toolbar",
62
+ "aria-label": t("navigation.toolbar.ariaLabel"),
63
+ "aria-busy": loading || void 0,
64
+ "data-overflow": overflow,
65
+ className: "ui-toolbar",
66
+ children: [
67
+ search && /* @__PURE__ */ jsx(
68
+ SearchInput,
69
+ {
70
+ id: search.id,
71
+ className: "ui-filter-bar-search",
72
+ label: search.label,
73
+ ariaLabel: search.ariaLabel,
74
+ placeholder: search.placeholder,
75
+ value: search.value,
76
+ defaultValue: search.defaultValue,
77
+ onValueChange: search.onValueChange,
78
+ onSearch: search.onSearch,
79
+ disabled: disabled || search.disabled
80
+ }
81
+ ),
82
+ filters?.map((filter) => {
83
+ const controlId = `${reactId}-filter-${filter.value}`;
84
+ return /* @__PURE__ */ jsx(
85
+ ToolbarGroup,
86
+ {
87
+ label: filter.label,
88
+ controlId,
89
+ className: "ui-filter-bar-filter",
90
+ children: /* @__PURE__ */ jsx(
91
+ Select,
92
+ {
93
+ id: controlId,
94
+ options: filter.options,
95
+ value: filter.selected,
96
+ defaultValue: filter.defaultSelected,
97
+ onValueChange: (selected) => filter.onSelectedChange?.(selected),
98
+ placeholder: filter.placeholder,
99
+ disabled: disabled || filter.disabled
100
+ }
101
+ )
102
+ },
103
+ filter.value
104
+ );
105
+ }),
106
+ children,
107
+ (showClear || actions != null) && /* @__PURE__ */ jsxs("div", { className: "ui-filter-bar-end", children: [
108
+ showClear && /* @__PURE__ */ jsxs(
109
+ Button,
110
+ {
111
+ variant: "ghost",
112
+ size: "sm",
113
+ onClick: onClear,
114
+ disabled,
115
+ className: "ui-toolbar-clear",
116
+ children: [
117
+ /* @__PURE__ */ jsx(X, { "aria-hidden": "true" }),
118
+ t("common.clearFilters")
119
+ ]
120
+ }
121
+ ),
122
+ actions != null && /* @__PURE__ */ jsx("div", { className: "ui-filter-bar-actions", children: actions })
123
+ ] })
124
+ ]
125
+ }
126
+ ),
127
+ showChips && /* @__PURE__ */ jsx(
39
128
  "div",
40
129
  {
41
130
  role: "group",
42
131
  "aria-label": t("navigation.filterBar.appliedFilters"),
43
132
  className: "ui-filter-bar-chips",
44
133
  children: chips.map((chip) => /* @__PURE__ */ jsxs("span", { className: "ui-filter-bar-chip", children: [
45
- /* @__PURE__ */ jsx("span", { className: "ui-filter-bar-chip-label", children: chip.label }),
46
- (chip.onRemove || onChipRemove) && /* @__PURE__ */ jsx(
134
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", children: chip.label }),
135
+ onChipRemove && /* @__PURE__ */ jsx(
47
136
  Button,
48
137
  {
49
138
  variant: "ghost",
50
- size: "xs",
51
- className: "ui-filter-bar-chip-remove",
52
- "aria-label": t("navigation.filterBar.removeFilter", { label: chip.label }),
53
- onClick: () => {
54
- chip.onRemove?.();
55
- onChipRemove?.(chip.id);
56
- },
139
+ size: "icon-sm",
140
+ disabled: disabled || chip.disabled,
141
+ "aria-label": t("navigation.filterBar.removeFilter", {
142
+ label: typeof chip.label === "string" ? chip.label : chip.value
143
+ }),
144
+ onClick: () => onChipRemove(chip.value),
57
145
  children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
58
146
  }
59
147
  )
60
- ] }, chip.id))
148
+ ] }, chip.value))
61
149
  }
62
150
  ),
63
- resultCount !== void 0 && // The whole reason this is a prop rather than caller markup: a sighted user SEES the table
64
- // change, and a polite live region is what tells everyone else that filtering happened.
65
- // The number is grouped by `Intl.NumberFormat` and the noun selected by CLDR plural rules
66
- // for the active locale — never a hand-built "N items".
67
- /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", className: "ui-filter-bar-count", children: t("navigation.filterBar.resultCount", { count: resultCount }) }),
68
- onClear && hasActiveFilters && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: onClear, className: "ui-toolbar-clear", children: [
69
- /* @__PURE__ */ jsx(X, { "aria-hidden": "true" }),
70
- t("common.clearFilters")
71
- ] }),
72
- actions != null && /* @__PURE__ */ jsx("div", { className: "ui-filter-bar-actions", children: actions })
151
+ showMeta && /* @__PURE__ */ jsx("div", { className: "ui-filter-bar-meta", children: error != null ? /* @__PURE__ */ jsx("p", { role: "alert", className: "ui-filter-bar-error", children: error }) : /* @__PURE__ */ jsx("p", { role: "status", className: "ui-filter-bar-count", children: t("navigation.filterBar.resultCount", { count: resultCount }) }) })
73
152
  ]
74
153
  }
75
154
  );
@@ -5,7 +5,7 @@ export { Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarLabel
5
5
  export { NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, } from "./navigation-menu.js";
6
6
  export { Steps } from "./steps.js";
7
7
  export { FilterBar, FilterBarGroup, Toolbar, ToolbarGroup } from "./filter-bar.js";
8
- export type { FilterBarChipProp, FilterBarChipProps, FilterBarGroupProp, FilterBarGroupProps, FilterBarProp, FilterBarProps, ToolbarGroupProps, ToolbarProps, } from "./filter-bar.js";
8
+ export type { FilterBarChipProp, FilterBarChipProps, FilterBarFilterProp, FilterBarFilterProps, FilterBarGroupProp, FilterBarGroupProps, FilterBarOverflowProp, FilterBarProp, FilterBarProps, FilterBarSearchProp, FilterBarSearchProps, ToolbarGroupProps, ToolbarProps, } from "./filter-bar.js";
9
9
  export { AppSettingPicker } from "./app-setting-picker.js";
10
10
  export type { AppSettingPickerProp, AppSettingPickerProps, AppSettingKind, } from "./app-setting-picker.js";
11
11
  export type { BreadcrumbItemProp as BreadcrumbItem } from "../../props/vocabulary/navigation.prop.js";
@@ -1,4 +1,4 @@
1
1
  import * as React from "react";
2
2
  import type { StepsProp } from "../../props/components/navigation.prop.js";
3
- export type { StepsProp, StepsProp as StepsProps, StepItemProp, StepStatusProp, StepsSeparatorProp, } from "../../props/components/navigation.prop.js";
4
- export declare function Steps({ items, value: current, defaultValue, status: currentStatus, orientation, type, size, titlePlacement, separator, onValueChange, className, }: StepsProp): React.JSX.Element;
3
+ export type { StepsProp, StepsProp as StepsProps, StepItemProp, StepStatusProp, } from "../../props/components/navigation.prop.js";
4
+ export declare function Steps({ items, value: current, defaultValue, status: currentStatus, orientation, type, size, titlePlacement, onValueChange, className, }: StepsProp): React.JSX.Element;
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { ArrowRight, Check, ChevronRight, Circle, Loader2, X } from "lucide-react";
3
+ import { Check, ChevronRight, Circle, Loader2, X } from "lucide-react";
4
4
  import { useTranslation } from "../../i18n/use-translation.js";
5
5
  import { cn } from "../../lib/utils.js";
6
6
  import { controlIconClass } from "../../lib/control-styles.js";
@@ -61,7 +61,6 @@ function Steps({
61
61
  type = "default",
62
62
  size = "md",
63
63
  titlePlacement = "horizontal",
64
- separator = "chevron",
65
64
  onValueChange,
66
65
  className
67
66
  }) {
@@ -70,7 +69,6 @@ function Steps({
70
69
  const isVertical = orientation === "vertical";
71
70
  const compact = size === "sm";
72
71
  const inline = type === "inline";
73
- const SeparatorIcon = separator === "arrow" ? ArrowRight : ChevronRight;
74
72
  return /* @__PURE__ */ jsx(
75
73
  "ol",
76
74
  {
@@ -153,7 +151,7 @@ function Steps({
153
151
  }
154
152
  ) : /* @__PURE__ */ jsx("span", { className: stepClassName, children: stepInner }),
155
153
  inline && index < items.length - 1 ? /* @__PURE__ */ jsx(
156
- SeparatorIcon,
154
+ ChevronRight,
157
155
  {
158
156
  className: "ui-steps-inline-separator rtl:rotate-180",
159
157
  "aria-hidden": "true"
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
3
3
  import type { AvatarProp } from "../../props/components/data-display.prop.js";
4
- export declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & Pick<AvatarProp, "shape" | "appearance"> & React.RefAttributes<HTMLSpanElement>>;
4
+ export declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & Pick<AvatarProp, "shape"> & React.RefAttributes<HTMLSpanElement>>;
5
5
  export declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
6
6
  export declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
@@ -3,13 +3,12 @@ import { jsx } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
5
5
  import { cn } from "../../lib/utils.js";
6
- const Avatar = React.forwardRef(({ className, shape = "circle", appearance = "default", ...props }, ref) => /* @__PURE__ */ jsx(
6
+ const Avatar = React.forwardRef(({ className, shape = "circle", ...props }, ref) => /* @__PURE__ */ jsx(
7
7
  AvatarPrimitive.Root,
8
8
  {
9
9
  ref,
10
10
  "data-slot": "avatar",
11
11
  "data-shape": shape === "square" ? "square" : void 0,
12
- "data-appearance": appearance === "tinted" ? "tinted" : void 0,
13
12
  className: cn("ui-avatar", className),
14
13
  ...props
15
14
  }
@@ -1,15 +1,5 @@
1
1
  import * as React from "react";
2
- import type { InputOTPAlignProp } from "../../props/components/data-entry.prop.js";
3
- /**
4
- * InputOTP — the code-challenge field.
5
- *
6
- * `align` positions the whole row (groups + separators) on the main axis: `start` (default,
7
- * unchanged), `center` — the canonical auth challenge — or `end`. The attribute lands on the
8
- * hidden input because `input-otp` owns the container element; `.ui-otp-container` reads it back
9
- * through `:has()`, exactly as it already does for the invalid and disabled states. A service that
10
- * wants every code field centred sets `--otp-container-align` once instead.
11
- */
12
- export declare const InputOTP: React.ForwardRefExoticComponent<((Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
2
+ export declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
13
3
  value?: string;
14
4
  onChange?: (newValue: string) => unknown;
15
5
  maxLength: number;
@@ -35,10 +25,8 @@ export declare const InputOTP: React.ForwardRefExoticComponent<((Omit<Omit<React
35
25
  } & {
36
26
  render?: never;
37
27
  children: React.ReactNode;
38
- } & React.RefAttributes<HTMLInputElement>, "ref">) & {
39
- align?: InputOTPAlignProp;
40
- }) & React.RefAttributes<HTMLInputElement>>;
41
- export type { InputOTPAlignProp, InputOTPGroupAppearanceProp, InputOTPGroupProp, InputOTPGroupProp as InputOTPGroupProps, } from "../../props/components/data-entry.prop.js";
28
+ } & React.RefAttributes<HTMLInputElement>, "ref">) & React.RefAttributes<HTMLInputElement>>;
29
+ export type { InputOTPGroupAppearanceProp, InputOTPGroupProp, InputOTPGroupProp as InputOTPGroupProps, } from "../../props/components/data-entry.prop.js";
42
30
  export declare const InputOTPGroup: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
43
31
  appearance?: import("./input-otp.js").InputOTPGroupAppearanceProp;
44
32
  } & React.RefAttributes<HTMLDivElement>>;
@@ -4,12 +4,11 @@ import * as React from "react";
4
4
  import { OTPInput, OTPInputContext } from "input-otp";
5
5
  import { Minus } from "lucide-react";
6
6
  import { cn } from "../../lib/utils.js";
7
- const InputOTP = React.forwardRef(({ className, containerClassName, align, ...props }, ref) => /* @__PURE__ */ jsx(
7
+ const InputOTP = React.forwardRef(({ className, containerClassName, ...props }, ref) => /* @__PURE__ */ jsx(
8
8
  OTPInput,
9
9
  {
10
10
  ref,
11
11
  "data-slot": "input-otp",
12
- "data-align": align && align !== "start" ? align : void 0,
13
12
  containerClassName: cn("ui-otp-container", containerClassName),
14
13
  className: cn("ui-otp-input", className),
15
14
  ...props
@@ -146,8 +146,8 @@ export declare const EMAIL_GEOMETRY_SOURCE: {
146
146
  readonly "--email-heading-font-size": "17px";
147
147
  readonly "--email-heading-line-height": "1.7";
148
148
  readonly "--email-heading-font-weight": "500";
149
- readonly "--email-cta-height": "44px";
150
- readonly "--email-cta-line-height": "44px";
149
+ readonly "--email-cta-height": "36px";
150
+ readonly "--email-cta-line-height": "36px";
151
151
  readonly "--email-cta-padding-x": "16px";
152
152
  readonly "--email-cta-radius": "6px";
153
153
  readonly "--email-cta-font-size": "14px";
@@ -136,8 +136,8 @@ const EMAIL_GEOMETRY_SOURCE = {
136
136
  "--email-heading-font-size": "17px",
137
137
  "--email-heading-line-height": "1.7",
138
138
  "--email-heading-font-weight": "500",
139
- "--email-cta-height": "44px",
140
- "--email-cta-line-height": "44px",
139
+ "--email-cta-height": "36px",
140
+ "--email-cta-line-height": "36px",
141
141
  "--email-cta-padding-x": "16px",
142
142
  "--email-cta-radius": "6px",
143
143
  "--email-cta-font-size": "14px",