@vaam-apps/ui 0.1.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.
- package/CHANGELOG.md +104 -0
- package/LICENSE +21 -0
- package/README.md +286 -0
- package/dist/components/data/code.d.ts +37 -0
- package/dist/components/data/code.d.ts.map +1 -0
- package/dist/components/data/code.js +37 -0
- package/dist/components/data/code.js.map +1 -0
- package/dist/components/data/copy-button.d.ts +39 -0
- package/dist/components/data/copy-button.d.ts.map +1 -0
- package/dist/components/data/copy-button.js +50 -0
- package/dist/components/data/copy-button.js.map +1 -0
- package/dist/components/data/detail-row.d.ts +69 -0
- package/dist/components/data/detail-row.d.ts.map +1 -0
- package/dist/components/data/detail-row.js +27 -0
- package/dist/components/data/detail-row.js.map +1 -0
- package/dist/components/data/id-display.d.ts +33 -0
- package/dist/components/data/id-display.d.ts.map +1 -0
- package/dist/components/data/id-display.js +25 -0
- package/dist/components/data/id-display.js.map +1 -0
- package/dist/components/data/masked-value.d.ts +47 -0
- package/dist/components/data/masked-value.d.ts.map +1 -0
- package/dist/components/data/masked-value.js +46 -0
- package/dist/components/data/masked-value.js.map +1 -0
- package/dist/components/data/money.d.ts +28 -0
- package/dist/components/data/money.d.ts.map +1 -0
- package/dist/components/data/money.js +22 -0
- package/dist/components/data/money.js.map +1 -0
- package/dist/components/data/phone-display.d.ts +45 -0
- package/dist/components/data/phone-display.d.ts.map +1 -0
- package/dist/components/data/phone-display.js +23 -0
- package/dist/components/data/phone-display.js.map +1 -0
- package/dist/components/data/stat-tile.d.ts +33 -0
- package/dist/components/data/stat-tile.d.ts.map +1 -0
- package/dist/components/data/stat-tile.js +18 -0
- package/dist/components/data/stat-tile.js.map +1 -0
- package/dist/components/data/timestamp-display.d.ts +14 -0
- package/dist/components/data/timestamp-display.d.ts.map +1 -0
- package/dist/components/data/timestamp-display.js +77 -0
- package/dist/components/data/timestamp-display.js.map +1 -0
- package/dist/components/patterns/inline-banner.d.ts +22 -0
- package/dist/components/patterns/inline-banner.d.ts.map +1 -0
- package/dist/components/patterns/inline-banner.js +11 -0
- package/dist/components/patterns/inline-banner.js.map +1 -0
- package/dist/components/patterns/inline-empty-state.d.ts +20 -0
- package/dist/components/patterns/inline-empty-state.d.ts.map +1 -0
- package/dist/components/patterns/inline-empty-state.js +11 -0
- package/dist/components/patterns/inline-empty-state.js.map +1 -0
- package/dist/components/patterns/live-row.d.ts +23 -0
- package/dist/components/patterns/live-row.d.ts.map +1 -0
- package/dist/components/patterns/live-row.js +48 -0
- package/dist/components/patterns/live-row.js.map +1 -0
- package/dist/components/patterns/payload-inspector.d.ts +25 -0
- package/dist/components/patterns/payload-inspector.d.ts.map +1 -0
- package/dist/components/patterns/payload-inspector.js +33 -0
- package/dist/components/patterns/payload-inspector.js.map +1 -0
- package/dist/components/patterns/route-skeleton.d.ts +15 -0
- package/dist/components/patterns/route-skeleton.d.ts.map +1 -0
- package/dist/components/patterns/route-skeleton.js +7 -0
- package/dist/components/patterns/route-skeleton.js.map +1 -0
- package/dist/components/patterns/screen-layout.d.ts +14 -0
- package/dist/components/patterns/screen-layout.d.ts.map +1 -0
- package/dist/components/patterns/screen-layout.js +11 -0
- package/dist/components/patterns/screen-layout.js.map +1 -0
- package/dist/components/patterns/stale-write-banner.d.ts +26 -0
- package/dist/components/patterns/stale-write-banner.d.ts.map +1 -0
- package/dist/components/patterns/stale-write-banner.js +28 -0
- package/dist/components/patterns/stale-write-banner.js.map +1 -0
- package/dist/components/patterns/state-timeline.d.ts +58 -0
- package/dist/components/patterns/state-timeline.d.ts.map +1 -0
- package/dist/components/patterns/state-timeline.js +103 -0
- package/dist/components/patterns/state-timeline.js.map +1 -0
- package/dist/components/primitives/badge.d.ts +27 -0
- package/dist/components/primitives/badge.d.ts.map +1 -0
- package/dist/components/primitives/badge.js +33 -0
- package/dist/components/primitives/badge.js.map +1 -0
- package/dist/components/primitives/button.d.ts +12 -0
- package/dist/components/primitives/button.d.ts.map +1 -0
- package/dist/components/primitives/button.js +42 -0
- package/dist/components/primitives/button.js.map +1 -0
- package/dist/components/primitives/calendar.d.ts +39 -0
- package/dist/components/primitives/calendar.d.ts.map +1 -0
- package/dist/components/primitives/calendar.js +102 -0
- package/dist/components/primitives/calendar.js.map +1 -0
- package/dist/components/primitives/card.d.ts +24 -0
- package/dist/components/primitives/card.d.ts.map +1 -0
- package/dist/components/primitives/card.js +28 -0
- package/dist/components/primitives/card.js.map +1 -0
- package/dist/components/primitives/checkbox.d.ts +42 -0
- package/dist/components/primitives/checkbox.d.ts.map +1 -0
- package/dist/components/primitives/checkbox.js +31 -0
- package/dist/components/primitives/checkbox.js.map +1 -0
- package/dist/components/primitives/chip-select.d.ts +38 -0
- package/dist/components/primitives/chip-select.d.ts.map +1 -0
- package/dist/components/primitives/chip-select.js +25 -0
- package/dist/components/primitives/chip-select.js.map +1 -0
- package/dist/components/primitives/command-menu.d.ts +54 -0
- package/dist/components/primitives/command-menu.d.ts.map +1 -0
- package/dist/components/primitives/command-menu.js +24 -0
- package/dist/components/primitives/command-menu.js.map +1 -0
- package/dist/components/primitives/confirm-dialog.d.ts +52 -0
- package/dist/components/primitives/confirm-dialog.d.ts.map +1 -0
- package/dist/components/primitives/confirm-dialog.js +30 -0
- package/dist/components/primitives/confirm-dialog.js.map +1 -0
- package/dist/components/primitives/date-picker.d.ts +68 -0
- package/dist/components/primitives/date-picker.d.ts.map +1 -0
- package/dist/components/primitives/date-picker.js +107 -0
- package/dist/components/primitives/date-picker.js.map +1 -0
- package/dist/components/primitives/dialog.d.ts +50 -0
- package/dist/components/primitives/dialog.d.ts.map +1 -0
- package/dist/components/primitives/dialog.js +90 -0
- package/dist/components/primitives/dialog.js.map +1 -0
- package/dist/components/primitives/drawer.d.ts +71 -0
- package/dist/components/primitives/drawer.d.ts.map +1 -0
- package/dist/components/primitives/drawer.js +93 -0
- package/dist/components/primitives/drawer.js.map +1 -0
- package/dist/components/primitives/dropdown-menu.d.ts +40 -0
- package/dist/components/primitives/dropdown-menu.d.ts.map +1 -0
- package/dist/components/primitives/dropdown-menu.js +53 -0
- package/dist/components/primitives/dropdown-menu.js.map +1 -0
- package/dist/components/primitives/form-field.d.ts +94 -0
- package/dist/components/primitives/form-field.d.ts.map +1 -0
- package/dist/components/primitives/form-field.js +27 -0
- package/dist/components/primitives/form-field.js.map +1 -0
- package/dist/components/primitives/inline-confirm.d.ts +62 -0
- package/dist/components/primitives/inline-confirm.d.ts.map +1 -0
- package/dist/components/primitives/inline-confirm.js +11 -0
- package/dist/components/primitives/inline-confirm.js.map +1 -0
- package/dist/components/primitives/input.d.ts +4 -0
- package/dist/components/primitives/input.d.ts.map +1 -0
- package/dist/components/primitives/input.js +13 -0
- package/dist/components/primitives/input.js.map +1 -0
- package/dist/components/primitives/label.d.ts +26 -0
- package/dist/components/primitives/label.d.ts.map +1 -0
- package/dist/components/primitives/label.js +33 -0
- package/dist/components/primitives/label.js.map +1 -0
- package/dist/components/primitives/pagination.d.ts +54 -0
- package/dist/components/primitives/pagination.d.ts.map +1 -0
- package/dist/components/primitives/pagination.js +31 -0
- package/dist/components/primitives/pagination.js.map +1 -0
- package/dist/components/primitives/popover.d.ts +12 -0
- package/dist/components/primitives/popover.d.ts.map +1 -0
- package/dist/components/primitives/popover.js +22 -0
- package/dist/components/primitives/popover.js.map +1 -0
- package/dist/components/primitives/progress.d.ts +25 -0
- package/dist/components/primitives/progress.d.ts.map +1 -0
- package/dist/components/primitives/progress.js +25 -0
- package/dist/components/primitives/progress.js.map +1 -0
- package/dist/components/primitives/radio-group.d.ts +47 -0
- package/dist/components/primitives/radio-group.d.ts.map +1 -0
- package/dist/components/primitives/radio-group.js +11 -0
- package/dist/components/primitives/radio-group.js.map +1 -0
- package/dist/components/primitives/select.d.ts +39 -0
- package/dist/components/primitives/select.d.ts.map +1 -0
- package/dist/components/primitives/select.js +142 -0
- package/dist/components/primitives/select.js.map +1 -0
- package/dist/components/primitives/separator.d.ts +9 -0
- package/dist/components/primitives/separator.d.ts.map +1 -0
- package/dist/components/primitives/separator.js +16 -0
- package/dist/components/primitives/separator.js.map +1 -0
- package/dist/components/primitives/side-nav.d.ts +65 -0
- package/dist/components/primitives/side-nav.d.ts.map +1 -0
- package/dist/components/primitives/side-nav.js +100 -0
- package/dist/components/primitives/side-nav.js.map +1 -0
- package/dist/components/primitives/skeleton.d.ts +22 -0
- package/dist/components/primitives/skeleton.d.ts.map +1 -0
- package/dist/components/primitives/skeleton.js +25 -0
- package/dist/components/primitives/skeleton.js.map +1 -0
- package/dist/components/primitives/spinner.d.ts +20 -0
- package/dist/components/primitives/spinner.d.ts.map +1 -0
- package/dist/components/primitives/spinner.js +21 -0
- package/dist/components/primitives/spinner.js.map +1 -0
- package/dist/components/primitives/switch.d.ts +29 -0
- package/dist/components/primitives/switch.d.ts.map +1 -0
- package/dist/components/primitives/switch.js +24 -0
- package/dist/components/primitives/switch.js.map +1 -0
- package/dist/components/primitives/table.d.ts +23 -0
- package/dist/components/primitives/table.d.ts.map +1 -0
- package/dist/components/primitives/table.js +81 -0
- package/dist/components/primitives/table.js.map +1 -0
- package/dist/components/primitives/tabs.d.ts +38 -0
- package/dist/components/primitives/tabs.d.ts.map +1 -0
- package/dist/components/primitives/tabs.js +84 -0
- package/dist/components/primitives/tabs.js.map +1 -0
- package/dist/components/primitives/textarea.d.ts +4 -0
- package/dist/components/primitives/textarea.d.ts.map +1 -0
- package/dist/components/primitives/textarea.js +11 -0
- package/dist/components/primitives/textarea.js.map +1 -0
- package/dist/components/primitives/toast.d.ts +24 -0
- package/dist/components/primitives/toast.d.ts.map +1 -0
- package/dist/components/primitives/toast.js +58 -0
- package/dist/components/primitives/toast.js.map +1 -0
- package/dist/components/primitives/tooltip.d.ts +30 -0
- package/dist/components/primitives/tooltip.d.ts.map +1 -0
- package/dist/components/primitives/tooltip.js +6 -0
- package/dist/components/primitives/tooltip.js.map +1 -0
- package/dist/components/status/state-chip.d.ts +53 -0
- package/dist/components/status/state-chip.d.ts.map +1 -0
- package/dist/components/status/state-chip.js +8 -0
- package/dist/components/status/state-chip.js.map +1 -0
- package/dist/components/status/state-mark.d.ts +21 -0
- package/dist/components/status/state-mark.d.ts.map +1 -0
- package/dist/components/status/state-mark.js +90 -0
- package/dist/components/status/state-mark.js.map +1 -0
- package/dist/components/status/status-pill.d.ts +62 -0
- package/dist/components/status/status-pill.d.ts.map +1 -0
- package/dist/components/status/status-pill.js +65 -0
- package/dist/components/status/status-pill.js.map +1 -0
- package/dist/components/status/status-tokens.d.ts +110 -0
- package/dist/components/status/status-tokens.d.ts.map +1 -0
- package/dist/components/status/status-tokens.js +102 -0
- package/dist/components/status/status-tokens.js.map +1 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cn.d.ts +11 -0
- package/dist/lib/cn.d.ts.map +1 -0
- package/dist/lib/cn.js +78 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/money.d.ts +73 -0
- package/dist/lib/money.d.ts.map +1 -0
- package/dist/lib/money.js +123 -0
- package/dist/lib/money.js.map +1 -0
- package/dist/lib/omit-undefined.d.ts +17 -0
- package/dist/lib/omit-undefined.d.ts.map +1 -0
- package/dist/lib/omit-undefined.js +24 -0
- package/dist/lib/omit-undefined.js.map +1 -0
- package/package.json +100 -0
- package/src/components/data/code.tsx +43 -0
- package/src/components/data/copy-button.tsx +97 -0
- package/src/components/data/detail-row.tsx +113 -0
- package/src/components/data/id-display.tsx +49 -0
- package/src/components/data/masked-value.tsx +96 -0
- package/src/components/data/money.tsx +46 -0
- package/src/components/data/phone-display.tsx +60 -0
- package/src/components/data/stat-tile.tsx +68 -0
- package/src/components/data/timestamp-display.tsx +106 -0
- package/src/components/patterns/inline-banner.tsx +60 -0
- package/src/components/patterns/inline-empty-state.tsx +45 -0
- package/src/components/patterns/live-row.tsx +75 -0
- package/src/components/patterns/payload-inspector.tsx +157 -0
- package/src/components/patterns/route-skeleton.tsx +77 -0
- package/src/components/patterns/screen-layout.tsx +44 -0
- package/src/components/patterns/stale-write-banner.tsx +44 -0
- package/src/components/patterns/state-timeline.tsx +229 -0
- package/src/components/primitives/badge.tsx +40 -0
- package/src/components/primitives/button.tsx +54 -0
- package/src/components/primitives/calendar.tsx +136 -0
- package/src/components/primitives/card.tsx +70 -0
- package/src/components/primitives/checkbox.tsx +101 -0
- package/src/components/primitives/chip-select.tsx +105 -0
- package/src/components/primitives/command-menu.tsx +92 -0
- package/src/components/primitives/confirm-dialog.tsx +109 -0
- package/src/components/primitives/date-picker.tsx +271 -0
- package/src/components/primitives/dialog.tsx +195 -0
- package/src/components/primitives/drawer.tsx +326 -0
- package/src/components/primitives/dropdown-menu.tsx +128 -0
- package/src/components/primitives/form-field.tsx +136 -0
- package/src/components/primitives/inline-confirm.tsx +118 -0
- package/src/components/primitives/input.tsx +21 -0
- package/src/components/primitives/label.tsx +43 -0
- package/src/components/primitives/pagination.tsx +110 -0
- package/src/components/primitives/popover.tsx +41 -0
- package/src/components/primitives/progress.tsx +66 -0
- package/src/components/primitives/radio-group.tsx +90 -0
- package/src/components/primitives/select.tsx +254 -0
- package/src/components/primitives/separator.tsx +49 -0
- package/src/components/primitives/side-nav.tsx +253 -0
- package/src/components/primitives/skeleton.tsx +25 -0
- package/src/components/primitives/spinner.tsx +39 -0
- package/src/components/primitives/switch.tsx +74 -0
- package/src/components/primitives/table.tsx +157 -0
- package/src/components/primitives/tabs.tsx +163 -0
- package/src/components/primitives/textarea.tsx +21 -0
- package/src/components/primitives/toast.tsx +117 -0
- package/src/components/primitives/tooltip.tsx +38 -0
- package/src/components/status/state-chip.tsx +70 -0
- package/src/components/status/state-mark.tsx +154 -0
- package/src/components/status/status-pill.tsx +153 -0
- package/src/components/status/status-tokens.ts +173 -0
- package/src/index.ts +96 -0
- package/src/lib/cn.ts +168 -0
- package/src/lib/money.ts +164 -0
- package/src/lib/omit-undefined.ts +25 -0
- package/src/styles/theme.css +381 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Menu, MenuButton, MenuItem, MenuItems, MenuSection, MenuSeparator, } from "@headlessui/react";
|
|
4
|
+
import { Check } from "lucide-react";
|
|
5
|
+
import { cn } from "../../lib/cn.js";
|
|
6
|
+
import { omitUndefined } from "../../lib/omit-undefined.js";
|
|
7
|
+
// D3: Radix `DropdownMenu` → Headless UI `Menu`/`MenuButton`/`MenuItems`/`MenuItem`.
|
|
8
|
+
export const DropdownMenu = Menu;
|
|
9
|
+
// `MenuButton` is natively polymorphic (`as`), replacing Radix's `asChild`
|
|
10
|
+
// pattern (D4's same call, applied to a trigger rather than `Button`
|
|
11
|
+
// itself): `<DropdownMenuTrigger as={Button} variant="secondary">…`.
|
|
12
|
+
export const DropdownMenuTrigger = MenuButton;
|
|
13
|
+
// `DropdownMenuGroup`/`DropdownMenuCheckboxItem` have zero call sites in
|
|
14
|
+
// this codebase today (grepped across `admin/` and `packages/ui`) — kept
|
|
15
|
+
// for API parity rather than dropped silently, mapped onto Headless UI's
|
|
16
|
+
// closest equivalents.
|
|
17
|
+
export const DropdownMenuGroup = MenuSection;
|
|
18
|
+
export function DropdownMenuSeparator({ className, ...props }) {
|
|
19
|
+
return _jsx(MenuSeparator, { className: cn("my-1 h-px bg-edge", className), ...props });
|
|
20
|
+
}
|
|
21
|
+
export function DropdownMenuContent({ className, ...props }) {
|
|
22
|
+
return (_jsx(MenuItems, { anchor: "bottom start", transition: true, className: cn("z-50 min-w-[180px] rounded-md border border-edge bg-surface-2 p-1 shadow-[var(--shadow-popover)] [--anchor-gap:4px] focus:outline-none", "origin-top transition duration-100 ease-out data-closed:scale-95 data-closed:opacity-0", className), ...props }));
|
|
23
|
+
}
|
|
24
|
+
export function DropdownMenuItem({ className, ...props }) {
|
|
25
|
+
return (_jsx(MenuItem, { as: "button", type: "button", className: cn("flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-body text-foreground outline-none", "data-focus:bg-surface-3", "data-disabled:pointer-events-none data-disabled:opacity-50", className), ...omitUndefined(props) }));
|
|
26
|
+
}
|
|
27
|
+
/** Unconsumed today (see module doc above) — caller controls `checked`
|
|
28
|
+
* itself, since Headless UI's `Menu` has no built-in checkbox-item state
|
|
29
|
+
* the way Radix's `DropdownMenuCheckboxItem` did. */
|
|
30
|
+
export function DropdownMenuCheckboxItem({ className, checked = false, children, ...props }) {
|
|
31
|
+
return (_jsxs(MenuItem, { as: "button", type: "button", role: "menuitemcheckbox", "aria-checked": checked, className: cn("flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-body text-foreground outline-none", "data-focus:bg-surface-3", className), ...omitUndefined(props), children: [_jsx("span", { className: "flex h-3.5 w-3.5 items-center justify-center", children: checked && _jsx(Check, { size: 14, strokeWidth: 1.5, "aria-hidden": "true" }) }), children] }));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* **Found live, not assumed**: Headless UI's own `MenuHeading` throws the
|
|
35
|
+
* identical "not inside a relevant parent" error `label.tsx`'s own module
|
|
36
|
+
* doc already found for the standalone `Label` — `MenuHeading` needs a
|
|
37
|
+
* `MenuSection` ancestor to supply that context (`MenuSection`'s own
|
|
38
|
+
* implementation calls `useLabels()` to *create* the provider; `MenuHeading`
|
|
39
|
+
* calls `useLabelContext()` to *consume* it), and every call site here
|
|
40
|
+
* (matching the original Radix `DropdownMenuLabel`'s own shape) renders a
|
|
41
|
+
* standalone label with no surrounding group. Radix's own `Label` was a
|
|
42
|
+
* plain, non-interactive `<div>` with no roving-focus/ARIA-grouping
|
|
43
|
+
* behaviour beyond being read as ordinary text inside the menu's
|
|
44
|
+
* accessible tree — so a plain `<div>` here loses nothing real and avoids
|
|
45
|
+
* a dependency this element doesn't actually need. Reproduced live: a real
|
|
46
|
+
* "Uncaught Error: You used a <Label /> component, but it is not inside a
|
|
47
|
+
* relevant parent" client-side exception, thrown the instant the gallery's
|
|
48
|
+
* demo menu opened, before this fix.
|
|
49
|
+
*/
|
|
50
|
+
export function DropdownMenuLabel({ className, ...props }) {
|
|
51
|
+
return (_jsx("div", { className: cn("px-2 py-1.5 text-micro text-muted-foreground tracking-[0.03em]", className), ...props }));
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=dropdown-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dropdown-menu.js","sourceRoot":"","sources":["../../../src/components/primitives/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,qFAAqF;AACrF,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AAEjC,2EAA2E;AAC3E,qEAAqE;AACrE,qEAAqE;AACrE,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAE9C,yEAAyE;AACzE,yEAAyE;AACzE,yEAAyE;AACzE,uBAAuB;AACvB,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE7C,MAAM,UAAU,qBAAqB,CAAC,EACpC,SAAS,EACT,GAAG,KAAK,EACuC;IAC/C,OAAO,KAAC,aAAa,IAAC,SAAS,EAAE,EAAE,CAAC,mBAAmB,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,EAClC,SAAS,EACT,GAAG,KAAK,EACmC;IAC3C,OAAO,CACL,KAAC,SAAS,IACR,MAAM,EAAC,cAAc,EACrB,UAAU,QACV,SAAS,EAAE,EAAE,CACX,wIAAwI,EACxI,wFAAwF,EACxF,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,SAAS,EACT,GAAG,KAAK,EACyC;IACjD,OAAO,CACL,KAAC,QAAQ,IACP,EAAE,EAAC,QAAQ,EACX,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,EAAE,CACX,uHAAuH,EACvH,yBAAyB,EACzB,4DAA4D,EAC5D,SAAS,CACV,KACG,aAAa,CAAC,KAAK,CAAC,GACxB,CACH,CAAC;AACJ,CAAC;AAED;;qDAEqD;AACrD,MAAM,UAAU,wBAAwB,CAAC,EACvC,SAAS,EACT,OAAO,GAAG,KAAK,EACf,QAAQ,EACR,GAAG,KAAK,EACiE;IACzE,OAAO,CACL,MAAC,QAAQ,IACP,EAAE,EAAC,QAAQ,EACX,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,kBAAkB,kBACT,OAAO,EACrB,SAAS,EAAE,EAAE,CACX,uHAAuH,EACvH,yBAAyB,EACzB,SAAS,CACV,KACG,aAAa,CAAC,KAAK,CAAC,aAExB,eAAM,SAAS,EAAC,8CAA8C,YAC3D,OAAO,IAAI,KAAC,KAAK,IAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,iBAAc,MAAM,GAAG,GAC/D,EACN,QAAQ,IACA,CACZ,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAwC;IAC7F,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CAAC,gEAAgE,EAAE,SAAS,CAAC,KACtF,KAAK,GACT,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A labelled form control with an optional validation error beneath it.
|
|
4
|
+
*
|
|
5
|
+
* This replaces the console's two most-duplicated class strings after the
|
|
6
|
+
* table-column ones:
|
|
7
|
+
*
|
|
8
|
+
* - `"flex flex-col gap-1.5"` — **80 occurrences**, every one of them
|
|
9
|
+
* wrapping exactly `<Label htmlFor>` + one control (+ sometimes an
|
|
10
|
+
* error paragraph).
|
|
11
|
+
* - `"text-caption text-state-danger-fg"` — **35 occurrences**, almost all
|
|
12
|
+
* of them that error paragraph.
|
|
13
|
+
*
|
|
14
|
+
* The shape was identical at every site, checked before this component was
|
|
15
|
+
* designed rather than assumed:
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <div className="flex flex-col gap-1.5">
|
|
19
|
+
* <Label htmlFor="record-msisdn">MSISDN</Label>
|
|
20
|
+
* <Input id="record-msisdn" {...form.register("msisdn")} />
|
|
21
|
+
* <p className="text-caption text-state-danger-fg">{errors.msisdn.message}</p>
|
|
22
|
+
* </div>
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* becomes
|
|
26
|
+
*
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <FormField label="MSISDN" htmlFor="record-msisdn" error={errors.msisdn?.message}>
|
|
29
|
+
* <Input id="record-msisdn" {...form.register("msisdn")} />
|
|
30
|
+
* </FormField>
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* **Why a semantic component and not a generic `<Stack gap="1.5">`.** A
|
|
34
|
+
* layout primitive parameterised by its own CSS is a `<div>` with extra
|
|
35
|
+
* steps — it moves the class from the call site into a prop at the call
|
|
36
|
+
* site, which is not factorisation. `FormField` instead names the *thing*
|
|
37
|
+
* (a labelled control with an error slot), so the spacing, the label
|
|
38
|
+
* treatment and the error treatment are one decision in one place, and a
|
|
39
|
+
* caller cannot get the error styling wrong by writing the `<p>` itself.
|
|
40
|
+
*
|
|
41
|
+
* `htmlFor` is required rather than optional. Several of the 80 sites had
|
|
42
|
+
* a `<Label>` with no `htmlFor` at all, which silently breaks
|
|
43
|
+
* click-to-focus and screen-reader association; making it required turns
|
|
44
|
+
* that into a compile error instead of an accessibility bug nobody
|
|
45
|
+
* notices.
|
|
46
|
+
*/
|
|
47
|
+
export interface FormFieldProps {
|
|
48
|
+
label: ReactNode;
|
|
49
|
+
/** The `id` of the control this labels. Required — see the module doc. */
|
|
50
|
+
htmlFor: string;
|
|
51
|
+
/** Validation message. `undefined` renders no error element at all. */
|
|
52
|
+
error?: string | undefined;
|
|
53
|
+
/** Help text rendered between the label and the control. */
|
|
54
|
+
hint?: ReactNode;
|
|
55
|
+
/**
|
|
56
|
+
* `"field"` (default) labels a single form control by `htmlFor`.
|
|
57
|
+
*
|
|
58
|
+
* `"group"` is for a `RadioGroup`/`ChipSelect`, where the control is a
|
|
59
|
+
* `role="radiogroup"`/`role="group"` wrapper rather than a labelable
|
|
60
|
+
* element. HTML's `for` only associates with labelable form controls, so
|
|
61
|
+
* pointing it at a `<div>` is invalid *and* dangling — which is exactly
|
|
62
|
+
* what the enum migration shipped: four `<Label for="…">` with no
|
|
63
|
+
* element carrying that id anywhere, found in review.
|
|
64
|
+
*
|
|
65
|
+
* In group mode no `for` is emitted; the label carries
|
|
66
|
+
* [`groupLabelId(htmlFor)`] instead, and the caller wires the group with
|
|
67
|
+
* `aria-labelledby={groupLabelId(htmlFor)}`. Both sides derive the id
|
|
68
|
+
* from the same function so they cannot drift.
|
|
69
|
+
*/
|
|
70
|
+
control?: "field" | "group";
|
|
71
|
+
children: ReactNode;
|
|
72
|
+
className?: string | undefined;
|
|
73
|
+
}
|
|
74
|
+
/** The id a `control="group"` FormField puts on its label, and the value a
|
|
75
|
+
* grouped control must pass as `aria-labelledby`. One function so the two
|
|
76
|
+
* sides cannot disagree. */
|
|
77
|
+
export declare function groupLabelId(htmlFor: string): string;
|
|
78
|
+
export declare function FormField({ label, htmlFor, error, hint, children, className, control, }: FormFieldProps): import("react").JSX.Element;
|
|
79
|
+
/**
|
|
80
|
+
* A validation message.
|
|
81
|
+
*
|
|
82
|
+
* Exported separately because a handful of the 35 sites are not inside a
|
|
83
|
+
* `FormField` — a form-level error above the submit button, or an error
|
|
84
|
+
* attached to a control group rather than one input. Those should still
|
|
85
|
+
* use the same treatment rather than re-inlining the class.
|
|
86
|
+
*
|
|
87
|
+
* `role="alert"` so the message is announced when it appears, which none
|
|
88
|
+
* of the 35 hand-rolled `<p>` elements did.
|
|
89
|
+
*/
|
|
90
|
+
export declare function FieldError({ children, className, }: {
|
|
91
|
+
children: ReactNode;
|
|
92
|
+
className?: string | undefined;
|
|
93
|
+
}): import("react").JSX.Element;
|
|
94
|
+
//# sourceMappingURL=form-field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-field.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/form-field.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,4DAA4D;IAC5D,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;4BAE4B;AAC5B,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,OAAO,EACP,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,OAAiB,GAClB,EAAE,cAAc,+BAkBhB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,+BAMA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { Label } from "./label.js";
|
|
4
|
+
/** The id a `control="group"` FormField puts on its label, and the value a
|
|
5
|
+
* grouped control must pass as `aria-labelledby`. One function so the two
|
|
6
|
+
* sides cannot disagree. */
|
|
7
|
+
export function groupLabelId(htmlFor) {
|
|
8
|
+
return `${htmlFor}-label`;
|
|
9
|
+
}
|
|
10
|
+
export function FormField({ label, htmlFor, error, hint, children, className, control = "field", }) {
|
|
11
|
+
return (_jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [control === "group" ? (_jsx("span", { id: groupLabelId(htmlFor), className: "font-medium text-body text-foreground", children: label })) : (_jsx(Label, { htmlFor: htmlFor, children: label })), hint !== undefined && _jsx("p", { className: "text-caption text-muted-foreground", children: hint }), children, error !== undefined && _jsx(FieldError, { children: error })] }));
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A validation message.
|
|
15
|
+
*
|
|
16
|
+
* Exported separately because a handful of the 35 sites are not inside a
|
|
17
|
+
* `FormField` — a form-level error above the submit button, or an error
|
|
18
|
+
* attached to a control group rather than one input. Those should still
|
|
19
|
+
* use the same treatment rather than re-inlining the class.
|
|
20
|
+
*
|
|
21
|
+
* `role="alert"` so the message is announced when it appears, which none
|
|
22
|
+
* of the 35 hand-rolled `<p>` elements did.
|
|
23
|
+
*/
|
|
24
|
+
export function FieldError({ children, className, }) {
|
|
25
|
+
return (_jsx("p", { role: "alert", className: cn("text-caption text-state-danger-fg", className), children: children }));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=form-field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-field.js","sourceRoot":"","sources":["../../../src/components/primitives/form-field.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AA2EhC;;4BAE4B;AAC5B,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,GAAG,OAAO,QAAQ,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,OAAO,EACP,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,OAAO,GAAG,OAAO,GACF;IACf,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,SAAS,CAAC,aACnD,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAIrB,eAAM,EAAE,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,SAAS,EAAC,uCAAuC,YAC/E,KAAK,GACD,CACR,CAAC,CAAC,CAAC,CACF,KAAC,KAAK,IAAC,OAAO,EAAE,OAAO,YAAG,KAAK,GAAS,CACzC,EACA,IAAI,KAAK,SAAS,IAAI,YAAG,SAAS,EAAC,oCAAoC,YAAE,IAAI,GAAK,EAClF,QAAQ,EACR,KAAK,KAAK,SAAS,IAAI,KAAC,UAAU,cAAE,KAAK,GAAc,IACpD,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,GAIV;IACC,OAAO,CACL,YAAG,IAAI,EAAC,OAAO,EAAC,SAAS,EAAE,EAAE,CAAC,mCAAmC,EAAE,SAAS,CAAC,YAC1E,QAAQ,GACP,CACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A confirmation rendered **inline**, inside the caller's own DOM subtree —
|
|
4
|
+
* never a portal, never a second `Dialog`/`FocusScope`. Exists specifically
|
|
5
|
+
* to replace a centered `Dialog` nested inside an open `QuickDetailDrawer` /
|
|
6
|
+
* `MoreDetailDrawer` (`vaul`), which is permanently broken: see
|
|
7
|
+
* `frontends/apps/admin/app/gallery/page.tsx`'s own
|
|
8
|
+
* `NestedDialogInDrawerRegression` writeup for the full root-cause
|
|
9
|
+
* investigation (`vaul`'s `Content` mounts a trapped, document-level
|
|
10
|
+
* `@radix-ui/react-focus-scope` `FocusScope` regardless of `dimmed`/`modal`,
|
|
11
|
+
* and Headless UI's `Dialog` always portals to its own sibling
|
|
12
|
+
* `#headlessui-portal-root` — so the trap yanks focus straight back out of
|
|
13
|
+
* the portal the instant it tries to move in, and the confirmation never
|
|
14
|
+
* becomes visible).
|
|
15
|
+
*
|
|
16
|
+
* Covers both destructive yes/no confirmations (`title`/`description`, no
|
|
17
|
+
* `children`) and a short form embedded in a confirmation step (`children`
|
|
18
|
+
* holds the field, e.g. sender-ids-screen.tsx's provider picker) — the two
|
|
19
|
+
* shapes this console actually needs, one component. A second, form-only
|
|
20
|
+
* component was considered and rejected: both shapes are "explain the
|
|
21
|
+
* consequence, then commit or back out," and forking that into two
|
|
22
|
+
* components would just be this file's own title/description/actions
|
|
23
|
+
* scaffold copy-pasted around a different middle section.
|
|
24
|
+
*
|
|
25
|
+
* The caller owns visibility: render this instead of the drawer's normal
|
|
26
|
+
* body content (and drop the drawer's own `footer` prop, since this
|
|
27
|
+
* component supplies its own Cancel/Confirm row) rather than layering it on
|
|
28
|
+
* top — there is no overlay, no absolute positioning, and no independent
|
|
29
|
+
* open/close transition to fight the drawer's own.
|
|
30
|
+
*/
|
|
31
|
+
export interface InlineConfirmProps {
|
|
32
|
+
/** The question being asked, e.g. "Delete this route?" or "Register {value}
|
|
33
|
+
* with a provider". Rendered as the panel's own heading — the drawer's
|
|
34
|
+
* `title` prop stays whatever record is being acted on; this is the
|
|
35
|
+
* action, not the record. */
|
|
36
|
+
title: ReactNode;
|
|
37
|
+
description?: ReactNode;
|
|
38
|
+
/** A field belonging to this confirmation, e.g. a provider `Select` — omit
|
|
39
|
+
* for a plain yes/no confirm. */
|
|
40
|
+
children?: ReactNode;
|
|
41
|
+
confirmLabel: string;
|
|
42
|
+
/** Shown on the confirm button while `pending` — defaults to `confirmLabel`
|
|
43
|
+
* with an ellipsis. */
|
|
44
|
+
pendingLabel?: string | undefined;
|
|
45
|
+
cancelLabel?: string;
|
|
46
|
+
onConfirm: () => void;
|
|
47
|
+
onCancel: () => void;
|
|
48
|
+
pending?: boolean;
|
|
49
|
+
/** Disables the confirm button independent of `pending`, e.g. no provider
|
|
50
|
+
* selected yet. */
|
|
51
|
+
confirmDisabled?: boolean;
|
|
52
|
+
/** Danger-hued confirm button + accent border, matching `Dialog`'s own
|
|
53
|
+
* "destructive action in the danger hue, never the primary hue"
|
|
54
|
+
* convention (console-redesign.md §1.7). Defaults `true` — every current
|
|
55
|
+
* call site is destructive; the one exception (sender-ids-screen.tsx's
|
|
56
|
+
* "register with a provider" form) passes `false`. */
|
|
57
|
+
destructive?: boolean;
|
|
58
|
+
error?: ReactNode;
|
|
59
|
+
className?: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function InlineConfirm({ title, description, children, confirmLabel, pendingLabel, cancelLabel, onConfirm, onCancel, pending, confirmDisabled, destructive, error, className, }: InlineConfirmProps): import("react").JSX.Element;
|
|
62
|
+
//# sourceMappingURL=inline-confirm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline-confirm.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/inline-confirm.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;iCAG6B;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;qCACiC;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB;2BACuB;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;uBACmB;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;0DAIsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,WAAsB,EACtB,SAAS,EACT,QAAQ,EACR,OAAe,EACf,eAAuB,EACvB,WAAkB,EAClB,KAAK,EACL,SAAS,GACV,EAAE,kBAAkB,+BAoCpB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
|
+
import { InlineBanner } from "../patterns/inline-banner.js";
|
|
5
|
+
import { Button } from "./button.js";
|
|
6
|
+
export function InlineConfirm({ title, description, children, confirmLabel, pendingLabel, cancelLabel = "Cancel", onConfirm, onCancel, pending = false, confirmDisabled = false, destructive = true, error, className, }) {
|
|
7
|
+
return (_jsxs("div", { className: cn("flex flex-col gap-4 rounded-sm border p-4", destructive
|
|
8
|
+
? "border-state-danger-border bg-state-danger-bg/30"
|
|
9
|
+
: "border-edge bg-surface-2", className), children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("h3", { className: "font-medium text-foreground text-title-sm", children: title }), description != null && _jsx("p", { className: "text-body text-muted-foreground", children: description })] }), children != null && _jsx("div", { className: "flex flex-col gap-4", children: children }), error != null && _jsx(InlineBanner, { variant: "danger", children: error }), _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", disabled: pending, onClick: onCancel, children: cancelLabel }), _jsx(Button, { type: "button", variant: destructive ? "destructive" : "primary", size: "sm", disabled: pending || confirmDisabled, onClick: onConfirm, children: pending ? (pendingLabel ?? `${confirmLabel}…`) : confirmLabel })] })] }));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=inline-confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline-confirm.js","sourceRoot":"","sources":["../../../src/components/primitives/inline-confirm.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AA8DlC,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,WAAW,GAAG,QAAQ,EACtB,SAAS,EACT,QAAQ,EACR,OAAO,GAAG,KAAK,EACf,eAAe,GAAG,KAAK,EACvB,WAAW,GAAG,IAAI,EAClB,KAAK,EACL,SAAS,GACU;IACnB,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,2CAA2C,EAC3C,WAAW;YACT,CAAC,CAAC,kDAAkD;YACpD,CAAC,CAAC,0BAA0B,EAC9B,SAAS,CACV,aAED,eAAK,SAAS,EAAC,qBAAqB,aAClC,aAAI,SAAS,EAAC,2CAA2C,YAAE,KAAK,GAAM,EACrE,WAAW,IAAI,IAAI,IAAI,YAAG,SAAS,EAAC,iCAAiC,YAAE,WAAW,GAAK,IACpF,EAEL,QAAQ,IAAI,IAAI,IAAI,cAAK,SAAS,EAAC,qBAAqB,YAAE,QAAQ,GAAO,EAEzE,KAAK,IAAI,IAAI,IAAI,KAAC,YAAY,IAAC,OAAO,EAAC,QAAQ,YAAE,KAAK,GAAgB,EAEvE,eAAK,SAAS,EAAC,qCAAqC,aAClD,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,EAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,YACjF,WAAW,GACL,EACT,KAAC,MAAM,IACL,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,EAChD,IAAI,EAAC,IAAI,EACT,QAAQ,EAAE,OAAO,IAAI,eAAe,EACpC,OAAO,EAAE,SAAS,YAEjB,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GACvD,IACL,IACF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { InputHTMLAttributes } from "react";
|
|
2
|
+
export type InputProps = InputHTMLAttributes<HTMLInputElement>;
|
|
3
|
+
export declare const Input: import("react").ForwardRefExoticComponent<InputProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
4
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAIjD,MAAM,MAAM,UAAU,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;AAS/D,eAAO,MAAM,KAAK,yGAMhB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
|
+
// D8: no explicit `rounded-*` class needed or added — daisyUI's own
|
|
5
|
+
// `.input` rule already sets every corner from `--radius-field`
|
|
6
|
+
// (confirmed by reading `daisyui/components/input.css` directly), and
|
|
7
|
+
// Phase 0 already rewrote that token to the new register. The class
|
|
8
|
+
// string here is unchanged from before the redesign; the rendered radius
|
|
9
|
+
// changed anyway, entirely from the token, with zero component code to
|
|
10
|
+
// touch — the intended effect of constraint 7 ("DaisyUI does the work").
|
|
11
|
+
export const Input = forwardRef(({ className, ...props }, ref) => (_jsx("input", { ref: ref, className: cn("input input-bordered w-full font-sans text-prose", className), ...props })));
|
|
12
|
+
Input.displayName = "Input";
|
|
13
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../../src/components/primitives/input.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAIlC,oEAAoE;AACpE,gEAAgE;AAChE,sEAAsE;AACtE,oEAAoE;AACpE,yEAAyE;AACzE,uEAAuE;AACvE,yEAAyE;AACzE,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAA+B,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAC9F,gBACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CAAC,kDAAkD,EAAE,SAAS,CAAC,KACxE,KAAK,GACT,CACH,CAAC,CAAC;AACH,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D3: ports from Radix `Label` to Headless UI's `Field`/`Label` composition.
|
|
3
|
+
*
|
|
4
|
+
* **Found live, not assumed:** Headless UI's own `Label` throws ("You used a
|
|
5
|
+
* `<Label />` component, but it is not inside a relevant parent") unless a
|
|
6
|
+
* `Field` ancestor exists to supply its context — unlike Radix's `Label`,
|
|
7
|
+
* which was a fully standalone `<label>` wrapper. None of this console's
|
|
8
|
+
* ~15 call sites wrap their `<Label htmlFor="x">…</Label>` +
|
|
9
|
+
* `<Input id="x">` pair in a `Field` (they associate the two explicitly via
|
|
10
|
+
* matching `htmlFor`/`id` instead, which needs no shared context at all),
|
|
11
|
+
* so porting to the bare Headless UI `Label` export would crash every one
|
|
12
|
+
* of them. Wrapping each call site in `<Field>` was considered and
|
|
13
|
+
* rejected — it would touch ~15 files outside this bucket's scope for no
|
|
14
|
+
* behavioural gain, since every call site already supplies its own
|
|
15
|
+
* `htmlFor`.
|
|
16
|
+
*
|
|
17
|
+
* Fixed here instead: `Label` supplies its own self-contained `Field`
|
|
18
|
+
* (`as={Fragment}`, so it adds no DOM node) around just the `Label` itself.
|
|
19
|
+
* This satisfies Headless UI's context requirement without requiring any
|
|
20
|
+
* caller to know `Field` exists, keeps the public API
|
|
21
|
+
* (`<Label htmlFor="x">…</Label>`) byte-identical to the Radix version, and
|
|
22
|
+
* still genuinely uses Headless UI's `Label` (constraint 6) rather than a
|
|
23
|
+
* hand-rolled `<label>`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const Label: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "ref"> & import("react").RefAttributes<HTMLLabelElement>>;
|
|
26
|
+
//# sourceMappingURL=label.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/label.tsx"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,KAAK,sNAUjB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Field, Label as HeadlessLabel } from "@headlessui/react";
|
|
4
|
+
import { Fragment, forwardRef } from "react";
|
|
5
|
+
import { cn } from "../../lib/cn.js";
|
|
6
|
+
import { omitUndefined } from "../../lib/omit-undefined.js";
|
|
7
|
+
/**
|
|
8
|
+
* D3: ports from Radix `Label` to Headless UI's `Field`/`Label` composition.
|
|
9
|
+
*
|
|
10
|
+
* **Found live, not assumed:** Headless UI's own `Label` throws ("You used a
|
|
11
|
+
* `<Label />` component, but it is not inside a relevant parent") unless a
|
|
12
|
+
* `Field` ancestor exists to supply its context — unlike Radix's `Label`,
|
|
13
|
+
* which was a fully standalone `<label>` wrapper. None of this console's
|
|
14
|
+
* ~15 call sites wrap their `<Label htmlFor="x">…</Label>` +
|
|
15
|
+
* `<Input id="x">` pair in a `Field` (they associate the two explicitly via
|
|
16
|
+
* matching `htmlFor`/`id` instead, which needs no shared context at all),
|
|
17
|
+
* so porting to the bare Headless UI `Label` export would crash every one
|
|
18
|
+
* of them. Wrapping each call site in `<Field>` was considered and
|
|
19
|
+
* rejected — it would touch ~15 files outside this bucket's scope for no
|
|
20
|
+
* behavioural gain, since every call site already supplies its own
|
|
21
|
+
* `htmlFor`.
|
|
22
|
+
*
|
|
23
|
+
* Fixed here instead: `Label` supplies its own self-contained `Field`
|
|
24
|
+
* (`as={Fragment}`, so it adds no DOM node) around just the `Label` itself.
|
|
25
|
+
* This satisfies Headless UI's context requirement without requiring any
|
|
26
|
+
* caller to know `Field` exists, keeps the public API
|
|
27
|
+
* (`<Label htmlFor="x">…</Label>`) byte-identical to the Radix version, and
|
|
28
|
+
* still genuinely uses Headless UI's `Label` (constraint 6) rather than a
|
|
29
|
+
* hand-rolled `<label>`.
|
|
30
|
+
*/
|
|
31
|
+
export const Label = forwardRef(({ className, ...props }, ref) => (_jsx(Field, { as: Fragment, children: _jsx(HeadlessLabel, { ref: ref, className: cn("text-body font-medium text-foreground", className), ...omitUndefined(props) }) })));
|
|
32
|
+
Label.displayName = "Label";
|
|
33
|
+
//# sourceMappingURL=label.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.js","sourceRoot":"","sources":["../../../src/components/primitives/label.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAC7B,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAChC,KAAC,KAAK,IAAC,EAAE,EAAE,QAAQ,YACjB,KAAC,aAAa,IACZ,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CAAC,uCAAuC,EAAE,SAAS,CAAC,KAC7D,aAAa,CAAC,KAAK,CAAC,GACxB,GACI,CACT,CACF,CAAC;AACF,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface PaginationProps {
|
|
3
|
+
onPrevious: (() => void) | undefined;
|
|
4
|
+
onNext: (() => void) | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* What the reader is looking at. Two honest shapes, and the choice is
|
|
7
|
+
* not cosmetic:
|
|
8
|
+
*
|
|
9
|
+
* - `{ kind: "offset", offset, pageSize, total }` — only when the API
|
|
10
|
+
* genuinely returns a total. Renders `1–25 of 340`.
|
|
11
|
+
* - `{ kind: "cursor", count }` — a keyset-paged API, which most
|
|
12
|
+
* event-shaped endpoints are, because counting a large table on every
|
|
13
|
+
* request is the expensive part. Renders `25 shown` and no page
|
|
14
|
+
* numbers, because there is no honest page number to render.
|
|
15
|
+
*
|
|
16
|
+
* Inventing a page count from a cursor API is the failure this type
|
|
17
|
+
* exists to prevent: it produces a "Page 3 of ?" that is wrong the
|
|
18
|
+
* moment a row is inserted.
|
|
19
|
+
*/
|
|
20
|
+
position: PaginationPosition;
|
|
21
|
+
/** Rendered between the counts and the buttons — a page-size select, a
|
|
22
|
+
* "Newest first" note. */
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
/**
|
|
25
|
+
* Overrides the landmark's accessible name.
|
|
26
|
+
*
|
|
27
|
+
* Needed whenever a screen shows more than one pager — a table with
|
|
28
|
+
* controls above and below is the usual case. Two `<nav>` landmarks
|
|
29
|
+
* with the same name is a real navigation defect, not a lint nit: a
|
|
30
|
+
* screen-reader user listing landmarks sees "Pagination, Pagination"
|
|
31
|
+
* and cannot tell which is which.
|
|
32
|
+
*/
|
|
33
|
+
label?: string | undefined;
|
|
34
|
+
className?: string | undefined;
|
|
35
|
+
}
|
|
36
|
+
export type PaginationPosition = {
|
|
37
|
+
kind: "offset";
|
|
38
|
+
offset: number;
|
|
39
|
+
pageSize: number;
|
|
40
|
+
total: number;
|
|
41
|
+
} | {
|
|
42
|
+
kind: "cursor";
|
|
43
|
+
count: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Previous/next paging with an honest position readout.
|
|
47
|
+
*
|
|
48
|
+
* Both callbacks are required but nullable: `undefined` disables that
|
|
49
|
+
* direction. Making them required-but-nullable rather than optional
|
|
50
|
+
* forces a caller to decide what the boundary is, instead of getting a
|
|
51
|
+
* silently dead button by omission.
|
|
52
|
+
*/
|
|
53
|
+
export declare function Pagination({ onPrevious, onNext, position, children, label, className, }: PaginationProps): import("react").JSX.Element;
|
|
54
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/pagination.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACrC,MAAM,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACjC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,EAAE,kBAAkB,CAAC;IAC7B;8BAC0B;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAatC;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,KAAoB,EACpB,SAAS,GACV,EAAE,eAAe,+BAqCjB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
import { Button } from "./button.js";
|
|
6
|
+
function positionLabel(position) {
|
|
7
|
+
if (position.kind === "cursor") {
|
|
8
|
+
return position.count === 0 ? "No results" : `${position.count} shown`;
|
|
9
|
+
}
|
|
10
|
+
const { offset, pageSize, total } = position;
|
|
11
|
+
if (total === 0)
|
|
12
|
+
return "No results";
|
|
13
|
+
const first = offset + 1;
|
|
14
|
+
const last = Math.min(offset + pageSize, total);
|
|
15
|
+
return `${first}–${last} of ${total}`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Previous/next paging with an honest position readout.
|
|
19
|
+
*
|
|
20
|
+
* Both callbacks are required but nullable: `undefined` disables that
|
|
21
|
+
* direction. Making them required-but-nullable rather than optional
|
|
22
|
+
* forces a caller to decide what the boundary is, instead of getting a
|
|
23
|
+
* silently dead button by omission.
|
|
24
|
+
*/
|
|
25
|
+
export function Pagination({ onPrevious, onNext, position, children, label = "Pagination", className, }) {
|
|
26
|
+
const atEnd = position.kind === "cursor"
|
|
27
|
+
? onNext === undefined
|
|
28
|
+
: position.offset + position.pageSize >= position.total;
|
|
29
|
+
return (_jsxs("nav", { "aria-label": label, className: cn("flex items-center justify-between gap-4 text-caption", className), children: [_jsx("p", { className: "font-mono text-subtle-foreground tabular-nums", children: positionLabel(position) }), _jsxs("div", { className: "flex items-center gap-2", children: [children, _jsxs(Button, { variant: "secondary", size: "sm", onClick: onPrevious, disabled: onPrevious === undefined, "aria-label": "Previous page", children: [_jsx(ChevronLeft, { size: 14, strokeWidth: 1.5 }), "Previous"] }), _jsxs(Button, { variant: "secondary", size: "sm", onClick: onNext, disabled: onNext === undefined || atEnd, "aria-label": "Next page", children: ["Next", _jsx(ChevronRight, { size: 14, strokeWidth: 1.5 })] })] })] }));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=pagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../../src/components/primitives/pagination.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAyClC,SAAS,aAAa,CAAC,QAA4B;IACjD,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,QAAQ,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,QAAQ,CAAC;IACzE,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAC7C,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,YAAY,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,GAAG,KAAK,IAAI,IAAI,OAAO,KAAK,EAAE,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,UAAU,EACV,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,KAAK,GAAG,YAAY,EACpB,SAAS,GACO;IAChB,MAAM,KAAK,GACT,QAAQ,CAAC,IAAI,KAAK,QAAQ;QACxB,CAAC,CAAC,MAAM,KAAK,SAAS;QACtB,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC;IAE5D,OAAO,CACL,6BACc,KAAK,EACjB,SAAS,EAAE,EAAE,CAAC,sDAAsD,EAAE,SAAS,CAAC,aAEhF,YAAG,SAAS,EAAC,+CAA+C,YAAE,aAAa,CAAC,QAAQ,CAAC,GAAK,EAC1F,eAAK,SAAS,EAAC,yBAAyB,aACrC,QAAQ,EACT,MAAC,MAAM,IACL,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,UAAU,KAAK,SAAS,gBACvB,eAAe,aAE1B,KAAC,WAAW,IAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,GAAI,gBAEpC,EACT,MAAC,MAAM,IACL,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,KAAK,SAAS,IAAI,KAAK,gBAC5B,WAAW,qBAGtB,KAAC,YAAY,IAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,GAAI,IACrC,IACL,IACF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PopoverPanel } from "@headlessui/react";
|
|
2
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
3
|
+
export declare const Popover: import("@headlessui/react")._internal_ComponentPopover & {
|
|
4
|
+
Button: import("@headlessui/react")._internal_ComponentPopoverButton;
|
|
5
|
+
Backdrop: import("@headlessui/react")._internal_ComponentPopoverBackdrop;
|
|
6
|
+
Overlay: import("@headlessui/react")._internal_ComponentPopoverBackdrop;
|
|
7
|
+
Panel: import("@headlessui/react")._internal_ComponentPopoverPanel;
|
|
8
|
+
Group: import("@headlessui/react")._internal_ComponentPopoverGroup;
|
|
9
|
+
};
|
|
10
|
+
export declare const PopoverTrigger: import("@headlessui/react")._internal_ComponentPopoverButton;
|
|
11
|
+
export declare function PopoverContent({ className, anchor, ...props }: ComponentPropsWithoutRef<typeof PopoverPanel>): import("react").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=popover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/popover.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA6C,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5F,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAQtD,eAAO,MAAM,OAAO;;;;;;CAAkB,CAAC;AAKvC,eAAO,MAAM,cAAc,8DAAgB,CAAC;AAO5C,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,MAAuB,EACvB,GAAG,KAAK,EACT,EAAE,wBAAwB,CAAC,OAAO,YAAY,CAAC,+BAa/C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Popover as HeadlessPopover, PopoverButton, PopoverPanel } from "@headlessui/react";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
// D3: Radix `Popover` → Headless UI `Popover`/`PopoverButton`/`PopoverPanel`.
|
|
6
|
+
// `Popover`/`PopoverButton` are used as-is — Headless UI's own `Popover` is
|
|
7
|
+
// already a fully self-contained open/close state machine (no separate
|
|
8
|
+
// "Root" plumbing needed the way `Dialog` needs one here, since Popover
|
|
9
|
+
// natively supports an in-place, uncontrolled trigger).
|
|
10
|
+
export const Popover = HeadlessPopover;
|
|
11
|
+
// `PopoverButton` is natively polymorphic (`as`), replacing Radix's
|
|
12
|
+
// `asChild` pattern (D4's same call, applied here to a trigger rather than
|
|
13
|
+
// `Button` itself): `<PopoverTrigger as={Button} variant="secondary">…`.
|
|
14
|
+
export const PopoverTrigger = PopoverButton;
|
|
15
|
+
// Radix also exported a standalone `Anchor` (a positioning reference
|
|
16
|
+
// distinct from the trigger) — unconsumed anywhere in this codebase, and
|
|
17
|
+
// Headless UI's own `anchor` prop on `PopoverPanel` (below) covers the same
|
|
18
|
+
// need without a separate element, so no replacement is exported.
|
|
19
|
+
export function PopoverContent({ className, anchor = "bottom start", ...props }) {
|
|
20
|
+
return (_jsx(PopoverPanel, { anchor: anchor, transition: true, className: cn("z-50 rounded-md border border-edge bg-surface-2 p-3 shadow-[var(--shadow-popover)] [--anchor-gap:6px] focus:outline-none", "origin-top transition duration-100 ease-out data-closed:scale-95 data-closed:opacity-0", className), ...props }));
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover.js","sourceRoot":"","sources":["../../../src/components/primitives/popover.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE5F,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAElC,8EAA8E;AAC9E,4EAA4E;AAC5E,uEAAuE;AACvE,wEAAwE;AACxE,wDAAwD;AACxD,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC;AAEvC,oEAAoE;AACpE,2EAA2E;AAC3E,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;AAE5C,qEAAqE;AACrE,yEAAyE;AACzE,4EAA4E;AAC5E,kEAAkE;AAElE,MAAM,UAAU,cAAc,CAAC,EAC7B,SAAS,EACT,MAAM,GAAG,cAAc,EACvB,GAAG,KAAK,EACsC;IAC9C,OAAO,CACL,KAAC,YAAY,IACX,MAAM,EAAE,MAAM,EACd,UAAU,QACV,SAAS,EAAE,EAAE,CACX,0HAA0H,EAC1H,wFAAwF,EACxF,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { StatusHue } from "../status/status-tokens.js";
|
|
2
|
+
export interface ProgressProps {
|
|
3
|
+
/** Completed units. Clamped into `[0, max]`. */
|
|
4
|
+
value: number;
|
|
5
|
+
max?: number;
|
|
6
|
+
/** `undefined` renders an indeterminate bar. */
|
|
7
|
+
tone?: StatusHue;
|
|
8
|
+
/** Accessible name, e.g. `"Retry budget used"`. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Show `3 / 5` beside the bar. */
|
|
11
|
+
showValue?: boolean;
|
|
12
|
+
className?: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A determinate progress bar for a *bounded, countable* quantity —
|
|
16
|
+
* attempts against a retry budget, rows processed, quota consumed.
|
|
17
|
+
*
|
|
18
|
+
* Not for an unbounded wait: a bar that creeps toward a value it cannot
|
|
19
|
+
* reach is a lie, and `Spinner` is the honest alternative. The `max` is
|
|
20
|
+
* required in spirit for that reason, and defaults to 100 only so a
|
|
21
|
+
* percentage — the one case where the bound is implied — needs no
|
|
22
|
+
* ceremony.
|
|
23
|
+
*/
|
|
24
|
+
export declare function Progress({ value, max, tone, label, showValue, className, }: ProgressProps): import("react").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/progress.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,GAAS,EACT,IAAgB,EAChB,KAAK,EACL,SAAiB,EACjB,SAAS,GACV,EAAE,aAAa,+BA+Bf"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { HUE_CLASSES } from "../status/status-tokens.js";
|
|
4
|
+
/**
|
|
5
|
+
* A determinate progress bar for a *bounded, countable* quantity —
|
|
6
|
+
* attempts against a retry budget, rows processed, quota consumed.
|
|
7
|
+
*
|
|
8
|
+
* Not for an unbounded wait: a bar that creeps toward a value it cannot
|
|
9
|
+
* reach is a lie, and `Spinner` is the honest alternative. The `max` is
|
|
10
|
+
* required in spirit for that reason, and defaults to 100 only so a
|
|
11
|
+
* percentage — the one case where the bound is implied — needs no
|
|
12
|
+
* ceremony.
|
|
13
|
+
*/
|
|
14
|
+
export function Progress({ value, max = 100, tone = "neutral", label, showValue = false, className, }) {
|
|
15
|
+
const safeMax = max <= 0 ? 1 : max;
|
|
16
|
+
const clamped = Math.min(Math.max(value, 0), safeMax);
|
|
17
|
+
const percent = (clamped / safeMax) * 100;
|
|
18
|
+
const hue = HUE_CLASSES[tone];
|
|
19
|
+
return (_jsxs("div", { className: cn("flex items-center gap-2", className), children: [_jsx("div", { role: "progressbar", "aria-label": label, "aria-valuenow": clamped, "aria-valuemin": 0, "aria-valuemax": safeMax, className: "h-1.5 min-w-0 flex-1 overflow-hidden rounded-full bg-surface-3", children: _jsx("div", {
|
|
20
|
+
// `currentColor` on a text-token class, so the fill tracks the
|
|
21
|
+
// same hue vocabulary every status surface uses rather than
|
|
22
|
+
// introducing a parallel set of bar colours.
|
|
23
|
+
className: cn("h-full rounded-full bg-current transition-[width] duration-300", hue.fg), style: { width: `${percent}%` } }) }), showValue && (_jsxs("span", { className: "shrink-0 font-mono text-caption text-subtle-foreground tabular-nums", children: [clamped, " / ", safeMax] }))] }));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../../../src/components/primitives/progress.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAElC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAetD;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,KAAK,EACL,GAAG,GAAG,GAAG,EACT,IAAI,GAAG,SAAS,EAChB,KAAK,EACL,SAAS,GAAG,KAAK,EACjB,SAAS,GACK;IACd,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,GAAG,CAAC;IAC1C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAE9B,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,SAAS,CAAC,aACtD,cACE,IAAI,EAAC,aAAa,gBACN,KAAK,mBACF,OAAO,mBACP,CAAC,mBACD,OAAO,EACtB,SAAS,EAAC,gEAAgE,YAE1E;oBACE,+DAA+D;oBAC/D,4DAA4D;oBAC5D,6CAA6C;oBAC7C,SAAS,EAAE,EAAE,CAAC,gEAAgE,EAAE,GAAG,CAAC,EAAE,CAAC,EACvF,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,OAAO,GAAG,EAAE,GAC/B,GACE,EACL,SAAS,IAAI,CACZ,gBAAM,SAAS,EAAC,qEAAqE,aAClF,OAAO,SAAK,OAAO,IACf,CACR,IACG,CACP,CAAC;AACJ,CAAC"}
|