@financedistrict/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.
Files changed (136) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +119 -0
  3. package/dist/Radio-BYWz1n7p.d.cts +32 -0
  4. package/dist/Radio-BYWz1n7p.d.ts +32 -0
  5. package/dist/SelectTrigger-By0iPBI3.d.cts +78 -0
  6. package/dist/SelectTrigger-By0iPBI3.d.ts +78 -0
  7. package/dist/accordion.cjs +322 -0
  8. package/dist/accordion.d.cts +156 -0
  9. package/dist/accordion.d.ts +156 -0
  10. package/dist/accordion.js +2 -0
  11. package/dist/apps-ui.umd.js +1 -0
  12. package/dist/button.cjs +366 -0
  13. package/dist/button.d.cts +52 -0
  14. package/dist/button.d.ts +52 -0
  15. package/dist/button.js +3 -0
  16. package/dist/checkbox.cjs +74 -0
  17. package/dist/checkbox.d.cts +63 -0
  18. package/dist/checkbox.d.ts +63 -0
  19. package/dist/checkbox.js +2 -0
  20. package/dist/chunk-3RU7JMFE.js +27 -0
  21. package/dist/chunk-5TWRK4NW.js +783 -0
  22. package/dist/chunk-7EOSDFS3.js +9 -0
  23. package/dist/chunk-AIQ4UOGK.js +142 -0
  24. package/dist/chunk-B3MMGTPV.js +200 -0
  25. package/dist/chunk-DAHQYLUI.js +146 -0
  26. package/dist/chunk-DGBXADSS.js +1 -0
  27. package/dist/chunk-E6KPNTWW.js +295 -0
  28. package/dist/chunk-EOAB6G2D.js +149 -0
  29. package/dist/chunk-FAOVKDVM.js +32 -0
  30. package/dist/chunk-FV76Z4Z2.js +78 -0
  31. package/dist/chunk-GLTLBUZ7.js +285 -0
  32. package/dist/chunk-GTZFV43T.js +154 -0
  33. package/dist/chunk-HRGZNL4A.js +88 -0
  34. package/dist/chunk-IEVN3J2F.js +98 -0
  35. package/dist/chunk-IRS3T6LF.js +352 -0
  36. package/dist/chunk-IYYHCQXG.js +146 -0
  37. package/dist/chunk-JIXW3455.js +89 -0
  38. package/dist/chunk-N4VAP2GB.js +77 -0
  39. package/dist/chunk-SJ2ZRYVV.js +167 -0
  40. package/dist/chunk-SNU4YXOR.js +66 -0
  41. package/dist/chunk-TT6JQATV.js +99 -0
  42. package/dist/chunk-UPQ3ZPCO.js +66 -0
  43. package/dist/chunk-UVUSVFOH.js +264 -0
  44. package/dist/chunk-WJFPGGJB.js +255 -0
  45. package/dist/chunk-WXEBQA7A.js +371 -0
  46. package/dist/chunk-Y2O4YYZQ.js +184 -0
  47. package/dist/cut-corner.cjs +111 -0
  48. package/dist/cut-corner.d.cts +49 -0
  49. package/dist/cut-corner.d.ts +49 -0
  50. package/dist/cut-corner.js +1 -0
  51. package/dist/dialog.cjs +441 -0
  52. package/dist/dialog.d.cts +240 -0
  53. package/dist/dialog.d.ts +240 -0
  54. package/dist/dialog.js +3 -0
  55. package/dist/feature-card.cjs +182 -0
  56. package/dist/feature-card.d.cts +54 -0
  57. package/dist/feature-card.d.ts +54 -0
  58. package/dist/feature-card.js +2 -0
  59. package/dist/filter.cjs +873 -0
  60. package/dist/filter.d.cts +129 -0
  61. package/dist/filter.d.ts +129 -0
  62. package/dist/filter.js +6 -0
  63. package/dist/index.cjs +4583 -0
  64. package/dist/index.d.cts +29 -0
  65. package/dist/index.d.ts +29 -0
  66. package/dist/index.js +27 -0
  67. package/dist/inline-select.cjs +856 -0
  68. package/dist/inline-select.d.cts +92 -0
  69. package/dist/inline-select.d.ts +92 -0
  70. package/dist/inline-select.js +6 -0
  71. package/dist/input.cjs +263 -0
  72. package/dist/input.d.cts +157 -0
  73. package/dist/input.d.ts +157 -0
  74. package/dist/input.js +4 -0
  75. package/dist/panel.cjs +185 -0
  76. package/dist/panel.d.cts +103 -0
  77. package/dist/panel.d.ts +103 -0
  78. package/dist/panel.js +2 -0
  79. package/dist/property-grid.cjs +110 -0
  80. package/dist/property-grid.d.cts +56 -0
  81. package/dist/property-grid.d.ts +56 -0
  82. package/dist/property-grid.js +2 -0
  83. package/dist/radio.cjs +74 -0
  84. package/dist/radio.d.cts +39 -0
  85. package/dist/radio.d.ts +39 -0
  86. package/dist/radio.js +2 -0
  87. package/dist/scrollbar.cjs +34 -0
  88. package/dist/scrollbar.d.cts +35 -0
  89. package/dist/scrollbar.d.ts +35 -0
  90. package/dist/scrollbar.js +1 -0
  91. package/dist/search-bar.cjs +408 -0
  92. package/dist/search-bar.d.cts +42 -0
  93. package/dist/search-bar.d.ts +42 -0
  94. package/dist/search-bar.js +4 -0
  95. package/dist/select.cjs +998 -0
  96. package/dist/select.d.cts +357 -0
  97. package/dist/select.d.ts +357 -0
  98. package/dist/select.js +5 -0
  99. package/dist/selectable-feature-card.cjs +159 -0
  100. package/dist/selectable-feature-card.d.cts +74 -0
  101. package/dist/selectable-feature-card.d.ts +74 -0
  102. package/dist/selectable-feature-card.js +3 -0
  103. package/dist/sidebar-item.cjs +175 -0
  104. package/dist/sidebar-item.d.cts +75 -0
  105. package/dist/sidebar-item.d.ts +75 -0
  106. package/dist/sidebar-item.js +2 -0
  107. package/dist/switch.cjs +86 -0
  108. package/dist/switch.d.cts +72 -0
  109. package/dist/switch.d.ts +72 -0
  110. package/dist/switch.js +2 -0
  111. package/dist/table-cell.cjs +196 -0
  112. package/dist/table-cell.d.cts +76 -0
  113. package/dist/table-cell.d.ts +76 -0
  114. package/dist/table-cell.js +2 -0
  115. package/dist/table-title.cjs +34 -0
  116. package/dist/table-title.d.cts +16 -0
  117. package/dist/table-title.d.ts +16 -0
  118. package/dist/table-title.js +2 -0
  119. package/dist/tabs.cjs +299 -0
  120. package/dist/tabs.d.cts +116 -0
  121. package/dist/tabs.d.ts +116 -0
  122. package/dist/tabs.js +2 -0
  123. package/dist/toast.cjs +87 -0
  124. package/dist/toast.d.cts +48 -0
  125. package/dist/toast.d.ts +48 -0
  126. package/dist/toast.js +2 -0
  127. package/dist/token-input.cjs +415 -0
  128. package/dist/token-input.d.cts +90 -0
  129. package/dist/token-input.d.ts +90 -0
  130. package/dist/token-input.js +3 -0
  131. package/dist/tooltip.cjs +384 -0
  132. package/dist/tooltip.d.cts +142 -0
  133. package/dist/tooltip.d.ts +142 -0
  134. package/dist/tooltip.js +2 -0
  135. package/package.json +200 -0
  136. package/src/fonts.css +33 -0
@@ -0,0 +1,240 @@
1
+ import * as React from 'react';
2
+ import * as class_variance_authority_types from 'class-variance-authority/types';
3
+
4
+ interface DialogRootProps {
5
+ /** Controlled open state. Pair with `onOpenChange`. Omit for uncontrolled. */
6
+ open?: boolean;
7
+ /** Initial open state when uncontrolled. Ignored if `open` is provided. */
8
+ defaultOpen?: boolean;
9
+ /** Called with the next open state from trigger/close/Escape/backdrop. */
10
+ onOpenChange?: (open: boolean) => void;
11
+ /**
12
+ * Whether Escape and a backdrop click dismiss the dialog. `false` forces the
13
+ * user through an explicit control (a footer button / the header X, which
14
+ * always close). Default `true`.
15
+ */
16
+ dismissable?: boolean;
17
+ children?: React.ReactNode;
18
+ }
19
+ /**
20
+ * State owner + context provider for the compound `Dialog`. Renders no DOM of
21
+ * its own. Controlled via `open`/`onOpenChange`, or uncontrolled via
22
+ * `defaultOpen`. Generates the `aria-labelledby`/`aria-describedby` ids that
23
+ * `Dialog.Header` and `Dialog.Content` share, so the wiring cannot drift.
24
+ */
25
+ declare function DialogRoot({ open: openProp, defaultOpen, onOpenChange, dismissable, children, }: DialogRootProps): React.JSX.Element;
26
+ interface TriggerLikeProps extends Omit<React.ComponentProps<"button">, "onClick"> {
27
+ /** Render the single child element as the root instead of a `<button>`. */
28
+ asChild?: boolean;
29
+ }
30
+ interface DialogTriggerProps extends TriggerLikeProps {
31
+ }
32
+ /**
33
+ * Optional button that opens the dialog. `asChild` adopts a passed element
34
+ * (e.g. `<Button>`). Wires `aria-haspopup="dialog"` + `aria-expanded`. Skip it
35
+ * for pure controlled usage.
36
+ */
37
+ declare function DialogTrigger({ asChild, ...props }: DialogTriggerProps): React.JSX.Element;
38
+ interface DialogCloseProps extends TriggerLikeProps {
39
+ }
40
+ /**
41
+ * Optional button that closes the dialog (e.g. wrapping a footer Cancel
42
+ * button). `asChild` adopts a passed element. Always closes, independent of
43
+ * `dismissable` (that only gates Escape + backdrop).
44
+ */
45
+ declare function DialogClose({ asChild, ...props }: DialogCloseProps): React.JSX.Element;
46
+ interface DialogContentProps extends React.ComponentProps<"div"> {
47
+ }
48
+ /**
49
+ * The portaled overlay layer — mounts via `createPortal` → `document.body`
50
+ * (escaping `overflow`/stacking ancestors, like `SelectListbox`) only while
51
+ * open. Renders the backdrop + the centred card, and owns the dialog semantics
52
+ * (`role="dialog"`, `aria-modal`, `aria-labelledby`/`aria-describedby`), the
53
+ * focus trap + return + scroll lock (`useFocusTrap`), Escape, and backdrop
54
+ * dismiss. Forwards `ref` to the card element.
55
+ */
56
+ declare function DialogContent({ className, children, ref, onKeyDown, ...props }: DialogContentProps): React.ReactPortal | null;
57
+ interface DialogHeaderProps extends Omit<React.ComponentProps<"div">, "title"> {
58
+ /**
59
+ * Decorative 32px icon (rendered `aria-hidden`). Hidden when omitted.
60
+ *
61
+ * **Rule: use a filled icon here.** The slot defaults Phosphor icons to
62
+ * `weight="fill"` via `IconContext`, so a plain `<SomeIcon />` renders filled
63
+ * with no per-call weight needed — matching the dialog's visual language. An
64
+ * explicit `weight` on the passed icon still wins, but line/regular weights are
65
+ * off-pattern for this slot. The top-right close (X) button is the sole
66
+ * exception and stays a regular-weight line icon.
67
+ */
68
+ icon?: React.ReactNode;
69
+ /** Title — becomes the dialog's `aria-labelledby` target (`display-04`). */
70
+ title: React.ReactNode;
71
+ /** Optional description — becomes `aria-describedby` (`body-03`, muted). */
72
+ description?: React.ReactNode;
73
+ /**
74
+ * Show the X close button, positioned against the card at 24px from its top and
75
+ * right (absolute — independent of the icon). Shown by **default**; pass
76
+ * `false` to hide it. Always closes, independent of `dismissable`.
77
+ */
78
+ showClose?: boolean;
79
+ }
80
+ /**
81
+ * Header block: an optional decorative icon, the title (registers the
82
+ * `aria-labelledby` id), an optional description (registers `aria-describedby`),
83
+ * and an optional X close button. Ids come from `Dialog.Root` context so the
84
+ * ARIA wiring stays in lock-step with `Dialog.Content`.
85
+ */
86
+ declare function DialogHeader({ icon, title, description, showClose, className, ref, ...props }: DialogHeaderProps): React.JSX.Element;
87
+ interface DialogBodyProps extends React.ComponentProps<"div"> {
88
+ }
89
+ /**
90
+ * Flexible content slot — inputs or any composition. Sizes to content and, in
91
+ * the card's bounded flex column, becomes the internal scroll region so the
92
+ * dialog never exceeds the viewport (custom scrollbar via `scrollbarVariants`).
93
+ */
94
+ declare function DialogBody({ className, children, ref, ...props }: DialogBodyProps): React.JSX.Element;
95
+ interface DialogFooterProps extends React.ComponentProps<"div"> {
96
+ }
97
+ /**
98
+ * Action-row slot — a full-width flex row (`gap-2`) whose children stretch to
99
+ * equal width (Figma's two-button layout). Apps pass `Button`s; a destructive
100
+ * dialog uses `Button variation="destructive"` here.
101
+ */
102
+ declare function DialogFooter({ className, children, ref, ...props }: DialogFooterProps): React.JSX.Element;
103
+ /**
104
+ * Compound modal dialog. Assemble from its namespaced parts:
105
+ *
106
+ * ```tsx
107
+ * <Dialog.Root open={open} onOpenChange={setOpen}>
108
+ * <Dialog.Trigger asChild><Button>Open</Button></Dialog.Trigger>
109
+ * <Dialog.Content>
110
+ * <Dialog.Header icon={<Icon />} title="Title" description="…" showClose />
111
+ * <Dialog.Body>{/* content *\/}</Dialog.Body>
112
+ * <Dialog.Footer>
113
+ * <Dialog.Close asChild><Button variation="secondary">Cancel</Button></Dialog.Close>
114
+ * <Button>Confirm</Button>
115
+ * </Dialog.Footer>
116
+ * </Dialog.Content>
117
+ * </Dialog.Root>
118
+ * ```
119
+ */
120
+ declare const Dialog: {
121
+ Root: typeof DialogRoot;
122
+ Trigger: typeof DialogTrigger;
123
+ Content: typeof DialogContent;
124
+ Header: typeof DialogHeader;
125
+ Body: typeof DialogBody;
126
+ Footer: typeof DialogFooter;
127
+ Close: typeof DialogClose;
128
+ };
129
+
130
+ /**
131
+ * All tabbable descendants of `container`, in DOM order.
132
+ *
133
+ * Deliberately does NOT filter by visibility (`offsetParent`/rects): jsdom
134
+ * performs no layout, so a visibility filter would drop every element under
135
+ * test. A modal's card rarely contains hidden-but-matching focusables, and the
136
+ * trap only ever cycles among what it returns, so the DOM-order set is
137
+ * sufficient. Kept pure (no React) so it is unit-testable in isolation.
138
+ */
139
+ declare function getFocusableElements(container: HTMLElement): HTMLElement[];
140
+ interface UseFocusTrapOptions {
141
+ /** Whether the trap is engaged (the dialog is open). */
142
+ active: boolean;
143
+ /** Ref to the element that focus is confined within (the dialog card). */
144
+ containerRef: React.RefObject<HTMLElement | null>;
145
+ }
146
+ /**
147
+ * Modal focus machinery for `Dialog.Content` — the piece ADR-0013 #2 explicitly
148
+ * deferred for `Select` (which kept focus on its trigger via
149
+ * `aria-activedescendant`). Dialog is a true modal, so on open it:
150
+ *
151
+ * 1. remembers the element that had focus (typically the trigger),
152
+ * 2. moves focus into the container (first focusable, else the container
153
+ * itself — give it `tabIndex={-1}` for that fallback),
154
+ * 3. locks body scroll, and
155
+ * 4. traps `Tab` / `Shift+Tab` so focus cycles within the container and cannot
156
+ * escape to the page behind the backdrop.
157
+ *
158
+ * On close/unmount it releases the scroll lock and restores focus to the
159
+ * remembered element. Dependency-free per ADR-0013 (no focus-trap library).
160
+ */
161
+ declare function useFocusTrap({ active, containerRef, }: UseFocusTrapOptions): void;
162
+
163
+ /**
164
+ * Dialog styling — the Figma `Dialog` card (nodes `4985:12074` / `4988:1882`)
165
+ * plus the overlay plumbing the library owns. Binds ONLY to the semantic token
166
+ * layer (never primitives, never the mode plumbing); theme switching is
167
+ * automatic via the `.dark` class, so no `dark:` variants are needed.
168
+ *
169
+ * Dialog is presentation-neutral: there is no `variation` prop (see the design
170
+ * spec / ADR-0022). The "basic" vs "destructive" Figma looks come entirely from
171
+ * the app-supplied header icon and footer `Button variation`, so these tables
172
+ * carry no variant axes — they are static class sets composed with `cn`.
173
+ */
174
+ /**
175
+ * The full-viewport backdrop. Fixed over everything, flex-centres the card, and
176
+ * paints the `--overlay` semantic token (a derived-alpha value, ADR-0005 — never
177
+ * an ad-hoc `bg-black/50`). `p-4` (1rem each side = 2rem total) reserves the
178
+ * viewport gutter the card's `max-w`/`max-h` calc subtract, so the card never
179
+ * touches an edge.
180
+ */
181
+ declare const dialogOverlayVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
182
+ /**
183
+ * The centred card. `w-[438px]` is the Figma-exact default width; there is no
184
+ * container token at 438px (closest is `--container-md` = 448px) and no width is
185
+ * expressible on the 4px spacing grid, so an arbitrary value is used
186
+ * deliberately (same posture as `scrollbarVariants`) and is `className`-
187
+ * overridable. `max-w`/`max-h` are viewport calcs (no token can express
188
+ * `100vw − gutter`) that keep the card inside the `p-4` overlay gutter; combined
189
+ * with the flex column below they let `Dialog.Body` scroll internally rather
190
+ * than let the card exceed the viewport.
191
+ */
192
+ declare const dialogContentVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
193
+ /**
194
+ * Header block: a stacked 32px decorative icon above the title/description
195
+ * column. `gap-4` (16px) between them, `items-start` left-aligns children.
196
+ * `shrink-0` keeps it fixed while the body scrolls. NOT `relative` on purpose —
197
+ * the close button positions against the card (`Dialog.Content`), so the header
198
+ * must not become the positioning anchor.
199
+ */
200
+ declare const dialogHeaderVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
201
+ /** Decorative 32px icon slot (`aria-hidden` on the element in `Dialog.Header`). */
202
+ declare const dialogHeaderIconVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
203
+ /**
204
+ * Title + description column: `gap-2` (8px) between the two, `w-full` so both
205
+ * span the header width. When the close X is shown on an icon-less header the
206
+ * component adds `pr-8` here so a long title clears the corner button (with an
207
+ * icon the title sits below the X, so no reservation is needed).
208
+ */
209
+ declare const dialogHeaderTextVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
210
+ /**
211
+ * The 16px muted X close button. Absolutely positioned against the card
212
+ * (`Dialog.Content` is the `relative` anchor) at `top-6 right-6` — always 24px
213
+ * from the card's top and right regardless of whether the header has an icon, so
214
+ * it never shifts with header content. Focus ring per ADR-0010.
215
+ */
216
+ declare const dialogCloseButtonVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
217
+ /**
218
+ * Body slot: sizes to content and, inside the card's bounded flex column,
219
+ * becomes the scroll region (`min-h-0 flex-1 overflow-y-auto`) so overflowing
220
+ * content scrolls internally and the dialog never exceeds the viewport. Custom
221
+ * scrollbar is composed in via `scrollbarVariants` in the component.
222
+ */
223
+ declare const dialogBodyVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
224
+ /**
225
+ * Footer action row: full width, `gap-2`, children stretched to equal width
226
+ * (Figma's two-button layout — each button is `flex: 1 0 0`). `shrink-0` keeps
227
+ * it pinned while the body scrolls.
228
+ *
229
+ * Two-level stretch: `[&>*]:flex-1` grows each direct child equally, but a cut-
230
+ * corner `Button` renders an `inline-block` wrapper span around its `<button>`,
231
+ * so the span fills the flex track while the inner button would stay content-
232
+ * width. `[&_button]:w-full` stretches that inner button to fill the track (a
233
+ * ghost button, which is the direct flex child, keeps its `flex:1 1 0%` basis).
234
+ * Targets the element, not `[data-slot=button]`, because a `Dialog.Close asChild`
235
+ * wrapper overrides the inner button's `data-slot` to `dialog-close`. The
236
+ * button's own `justify-center` then centers the label, matching Figma.
237
+ */
238
+ declare const dialogFooterVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
239
+
240
+ export { Dialog, DialogBody, type DialogBodyProps, DialogClose, type DialogCloseProps, DialogContent, type DialogContentProps, DialogFooter, type DialogFooterProps, DialogHeader, type DialogHeaderProps, DialogRoot, type DialogRootProps, DialogTrigger, type DialogTriggerProps, type UseFocusTrapOptions, dialogBodyVariants, dialogCloseButtonVariants, dialogContentVariants, dialogFooterVariants, dialogHeaderIconVariants, dialogHeaderTextVariants, dialogHeaderVariants, dialogOverlayVariants, getFocusableElements, useFocusTrap };
package/dist/dialog.js ADDED
@@ -0,0 +1,3 @@
1
+ export { Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTrigger, dialogBodyVariants, dialogCloseButtonVariants, dialogContentVariants, dialogFooterVariants, dialogHeaderIconVariants, dialogHeaderTextVariants, dialogHeaderVariants, dialogOverlayVariants, getFocusableElements, useFocusTrap } from './chunk-WXEBQA7A.js';
2
+ import './chunk-FAOVKDVM.js';
3
+ import './chunk-7EOSDFS3.js';
@@ -0,0 +1,182 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var react = require('@phosphor-icons/react');
5
+ var clsx = require('clsx');
6
+ var tailwindMerge = require('tailwind-merge');
7
+ var classVarianceAuthority = require('class-variance-authority');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
29
+
30
+ // src/feature-card/FeatureCard.tsx
31
+ function cn(...inputs) {
32
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
33
+ }
34
+ var featureCardVariants = classVarianceAuthority.cva(
35
+ "flex h-16 items-center gap-3 px-4 py-3 bg-card-background no-underline",
36
+ {
37
+ variants: {
38
+ interactive: {
39
+ true: [
40
+ "cursor-pointer transition-colors hover:bg-card-accent",
41
+ "outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus"
42
+ ],
43
+ false: ""
44
+ }
45
+ },
46
+ defaultVariants: { interactive: false }
47
+ }
48
+ );
49
+ var featureCardLeadingVariants = classVarianceAuthority.cva(
50
+ "flex shrink-0 items-center text-card-foreground [&_svg]:size-6 [&_svg]:shrink-0"
51
+ );
52
+ var featureCardTrailingVariants = classVarianceAuthority.cva(
53
+ "flex shrink-0 items-center text-card-foreground-muted [&_svg]:size-6 [&_svg]:shrink-0"
54
+ );
55
+ var featureCardTextVariants = classVarianceAuthority.cva("flex min-w-0 flex-1 flex-col");
56
+ var featureCardTitleRowVariants = classVarianceAuthority.cva(
57
+ "flex min-w-0 items-center gap-0.5"
58
+ );
59
+ var featureCardCaretVariants = classVarianceAuthority.cva(
60
+ "flex shrink-0 items-center text-card-foreground-muted [&_svg]:size-4 [&_svg]:shrink-0"
61
+ );
62
+ function setRef(ref, node) {
63
+ if (typeof ref === "function") ref(node);
64
+ else if (ref) ref.current = node;
65
+ }
66
+ function FeatureCard({
67
+ title,
68
+ subtitle,
69
+ leading,
70
+ trailing,
71
+ caret = true,
72
+ asChild = false,
73
+ href,
74
+ className,
75
+ children,
76
+ ref,
77
+ ...props
78
+ }) {
79
+ const interactive = asChild || href != null;
80
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
81
+ leading != null && /* @__PURE__ */ jsxRuntime.jsx(
82
+ "span",
83
+ {
84
+ "data-slot": "feature-card-leading",
85
+ "aria-hidden": "true",
86
+ className: featureCardLeadingVariants(),
87
+ children: leading
88
+ }
89
+ ),
90
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-slot": "feature-card-text", className: featureCardTextVariants(), children: [
91
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: featureCardTitleRowVariants(), children: [
92
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "body-02-medium truncate text-card-foreground", children: title }),
93
+ caret && /* @__PURE__ */ jsxRuntime.jsx(
94
+ "span",
95
+ {
96
+ "data-slot": "feature-card-caret",
97
+ "aria-hidden": "true",
98
+ className: featureCardCaretVariants(),
99
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.CaretRightIcon, {})
100
+ }
101
+ )
102
+ ] }),
103
+ subtitle != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "body-03 truncate text-card-foreground-muted", children: subtitle })
104
+ ] }),
105
+ trailing != null && /* @__PURE__ */ jsxRuntime.jsx(
106
+ "span",
107
+ {
108
+ "data-slot": "feature-card-trailing",
109
+ "aria-hidden": "true",
110
+ className: featureCardTrailingVariants(),
111
+ children: trailing
112
+ }
113
+ )
114
+ ] });
115
+ const rootClassName = cn(featureCardVariants({ interactive }), className);
116
+ if (asChild) {
117
+ if (!React__namespace.isValidElement(children)) {
118
+ throw new Error(
119
+ "FeatureCard: `asChild` requires a single React element child"
120
+ );
121
+ }
122
+ const child = children;
123
+ const childProps = child.props;
124
+ return React__namespace.cloneElement(
125
+ child,
126
+ {
127
+ ...props,
128
+ ...childProps,
129
+ "data-slot": "feature-card",
130
+ ref: (node) => {
131
+ setRef(ref, node);
132
+ setRef(childProps.ref, node);
133
+ },
134
+ className: cn(
135
+ rootClassName,
136
+ childProps.className
137
+ ),
138
+ onClick: (event) => {
139
+ props.onClick?.(event);
140
+ childProps.onClick?.(event);
141
+ },
142
+ style: {
143
+ ...props.style,
144
+ ...childProps.style
145
+ }
146
+ },
147
+ content,
148
+ childProps.children
149
+ );
150
+ }
151
+ if (href != null) {
152
+ return /* @__PURE__ */ jsxRuntime.jsx(
153
+ "a",
154
+ {
155
+ "data-slot": "feature-card",
156
+ href,
157
+ className: rootClassName,
158
+ ref,
159
+ ...props,
160
+ children: content
161
+ }
162
+ );
163
+ }
164
+ return /* @__PURE__ */ jsxRuntime.jsx(
165
+ "div",
166
+ {
167
+ "data-slot": "feature-card",
168
+ className: rootClassName,
169
+ ref,
170
+ ...props,
171
+ children: content
172
+ }
173
+ );
174
+ }
175
+
176
+ exports.FeatureCard = FeatureCard;
177
+ exports.featureCardCaretVariants = featureCardCaretVariants;
178
+ exports.featureCardLeadingVariants = featureCardLeadingVariants;
179
+ exports.featureCardTextVariants = featureCardTextVariants;
180
+ exports.featureCardTitleRowVariants = featureCardTitleRowVariants;
181
+ exports.featureCardTrailingVariants = featureCardTrailingVariants;
182
+ exports.featureCardVariants = featureCardVariants;
@@ -0,0 +1,54 @@
1
+ import * as React from 'react';
2
+ import * as class_variance_authority_types from 'class-variance-authority/types';
3
+
4
+ interface FeatureCardProps extends Omit<React.ComponentProps<"a">, "title" | "ref"> {
5
+ /** Title line (`body-02-medium`). Accessible name of an interactive card. */
6
+ title: React.ReactNode;
7
+ /** Optional subtitle line (`body-03`, muted). */
8
+ subtitle?: React.ReactNode;
9
+ /** Optional 24px leading icon slot (decorative, `aria-hidden`). */
10
+ leading?: React.ReactNode;
11
+ /** Optional 24px trailing icon slot (decorative, `aria-hidden`). */
12
+ trailing?: React.ReactNode;
13
+ /** Show the inline caret after the title. Default `true` (matches Figma). */
14
+ caret?: boolean;
15
+ /**
16
+ * Render the single element child as the root (a router `<Link>` / `<a>`),
17
+ * keeping all card styling. Requires exactly one valid element child.
18
+ */
19
+ asChild?: boolean;
20
+ /** Ref forwarded to the root element. */
21
+ ref?: React.Ref<HTMLElement>;
22
+ }
23
+ declare function FeatureCard({ title, subtitle, leading, trailing, caret, asChild, href, className, children, ref, ...props }: FeatureCardProps): React.JSX.Element;
24
+
25
+ /**
26
+ * FeatureCard styling — the Figma `feature-card` (node `4854:144741`). Binds
27
+ * ONLY to the `card-*` semantic token layer (never primitives / mode
28
+ * plumbing); theme switching is automatic via `.dark`, so no `dark:` variants.
29
+ *
30
+ * `feature-card` is a navigation card: the whole surface is the click target.
31
+ * The Figma `border-r` divider is NOT baked in — grouping/dividers are a
32
+ * consumer layout concern (a standalone card carries no stray border).
33
+ */
34
+ /**
35
+ * The card row. `h-16`=64px, `gap-3`=12px, `px-4`=16px, `py-3`=12px.
36
+ * `no-underline` strips the default `<a>` underline (the root may be an anchor
37
+ * or a cloned link). Interactive roots add hover accent + the ADR-0010 focus
38
+ * ring; a presentational root stays static.
39
+ */
40
+ declare const featureCardVariants: (props?: ({
41
+ interactive?: boolean | null | undefined;
42
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
43
+ /** Leading 24px decorative icon slot (`foreground`). */
44
+ declare const featureCardLeadingVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
45
+ /** Trailing 24px decorative icon slot (`foreground-muted`). */
46
+ declare const featureCardTrailingVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
47
+ /** Title + subtitle column. `min-w-0` + `flex-1` enable text truncation. */
48
+ declare const featureCardTextVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
49
+ /** Title + inline caret row. `gap-0.5`=2px; `min-w-0` lets the title truncate. */
50
+ declare const featureCardTitleRowVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
51
+ /** Inline 16px muted caret slot. */
52
+ declare const featureCardCaretVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
53
+
54
+ export { FeatureCard, type FeatureCardProps, featureCardCaretVariants, featureCardLeadingVariants, featureCardTextVariants, featureCardTitleRowVariants, featureCardTrailingVariants, featureCardVariants };
@@ -0,0 +1,54 @@
1
+ import * as React from 'react';
2
+ import * as class_variance_authority_types from 'class-variance-authority/types';
3
+
4
+ interface FeatureCardProps extends Omit<React.ComponentProps<"a">, "title" | "ref"> {
5
+ /** Title line (`body-02-medium`). Accessible name of an interactive card. */
6
+ title: React.ReactNode;
7
+ /** Optional subtitle line (`body-03`, muted). */
8
+ subtitle?: React.ReactNode;
9
+ /** Optional 24px leading icon slot (decorative, `aria-hidden`). */
10
+ leading?: React.ReactNode;
11
+ /** Optional 24px trailing icon slot (decorative, `aria-hidden`). */
12
+ trailing?: React.ReactNode;
13
+ /** Show the inline caret after the title. Default `true` (matches Figma). */
14
+ caret?: boolean;
15
+ /**
16
+ * Render the single element child as the root (a router `<Link>` / `<a>`),
17
+ * keeping all card styling. Requires exactly one valid element child.
18
+ */
19
+ asChild?: boolean;
20
+ /** Ref forwarded to the root element. */
21
+ ref?: React.Ref<HTMLElement>;
22
+ }
23
+ declare function FeatureCard({ title, subtitle, leading, trailing, caret, asChild, href, className, children, ref, ...props }: FeatureCardProps): React.JSX.Element;
24
+
25
+ /**
26
+ * FeatureCard styling — the Figma `feature-card` (node `4854:144741`). Binds
27
+ * ONLY to the `card-*` semantic token layer (never primitives / mode
28
+ * plumbing); theme switching is automatic via `.dark`, so no `dark:` variants.
29
+ *
30
+ * `feature-card` is a navigation card: the whole surface is the click target.
31
+ * The Figma `border-r` divider is NOT baked in — grouping/dividers are a
32
+ * consumer layout concern (a standalone card carries no stray border).
33
+ */
34
+ /**
35
+ * The card row. `h-16`=64px, `gap-3`=12px, `px-4`=16px, `py-3`=12px.
36
+ * `no-underline` strips the default `<a>` underline (the root may be an anchor
37
+ * or a cloned link). Interactive roots add hover accent + the ADR-0010 focus
38
+ * ring; a presentational root stays static.
39
+ */
40
+ declare const featureCardVariants: (props?: ({
41
+ interactive?: boolean | null | undefined;
42
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
43
+ /** Leading 24px decorative icon slot (`foreground`). */
44
+ declare const featureCardLeadingVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
45
+ /** Trailing 24px decorative icon slot (`foreground-muted`). */
46
+ declare const featureCardTrailingVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
47
+ /** Title + subtitle column. `min-w-0` + `flex-1` enable text truncation. */
48
+ declare const featureCardTextVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
49
+ /** Title + inline caret row. `gap-0.5`=2px; `min-w-0` lets the title truncate. */
50
+ declare const featureCardTitleRowVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
51
+ /** Inline 16px muted caret slot. */
52
+ declare const featureCardCaretVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
53
+
54
+ export { FeatureCard, type FeatureCardProps, featureCardCaretVariants, featureCardLeadingVariants, featureCardTextVariants, featureCardTitleRowVariants, featureCardTrailingVariants, featureCardVariants };
@@ -0,0 +1,2 @@
1
+ export { FeatureCard, featureCardCaretVariants, featureCardLeadingVariants, featureCardTextVariants, featureCardTitleRowVariants, featureCardTrailingVariants, featureCardVariants } from './chunk-EOAB6G2D.js';
2
+ import './chunk-7EOSDFS3.js';