@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,184 @@
1
+ import { useSelectListbox, SelectListbox } from './chunk-5TWRK4NW.js';
2
+ import { cn } from './chunk-7EOSDFS3.js';
3
+ import * as React from 'react';
4
+ import { CaretDownIcon } from '@phosphor-icons/react';
5
+ import { cva } from 'class-variance-authority';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+
8
+ var inlineSelectVariants = cva(
9
+ [
10
+ // Inline text run: label + caret, 4px gap (Figma spacing/1), baseline-ish
11
+ // centered. `w-fit` so the ring hugs the content, not a full-width box.
12
+ "inline-flex w-fit items-center gap-1",
13
+ // Behaves as inline text — no field padding/background/border.
14
+ "cursor-pointer bg-transparent p-0 text-left align-middle",
15
+ "transition-colors",
16
+ // System focus ring (ADR-0010): momentary-control treatment, not a border
17
+ // recolor. Kill the default outline, then draw the 2px --focus ring with a
18
+ // 2px gap on :focus-visible only. `rounded-xs` matches the Figma ring.
19
+ "rounded-xs outline-none",
20
+ "focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus",
21
+ // Decorative svgs (caret / leading slot) never intercept the click and keep
22
+ // their explicit sizes.
23
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0"
24
+ ],
25
+ {
26
+ variants: {
27
+ variation: {
28
+ primary: "",
29
+ secondary: ""
30
+ },
31
+ disabled: {
32
+ // Muted + not-allowed, and the focus ring is suppressed (a disabled
33
+ // control is not focusable, but belt-and-braces if a consumer forces it).
34
+ true: "cursor-not-allowed focus-visible:outline-none",
35
+ false: ""
36
+ }
37
+ },
38
+ defaultVariants: {
39
+ variation: "primary",
40
+ disabled: false
41
+ }
42
+ }
43
+ );
44
+ function InlineSelectTrigger({
45
+ variation = "primary",
46
+ disabled = false,
47
+ displayText,
48
+ isPlaceholder,
49
+ open = false,
50
+ leadingSlot,
51
+ className,
52
+ ref,
53
+ ...props
54
+ }) {
55
+ const valueColor = variation === "secondary" ? "text-card-brand-secondary-foreground" : "text-card-primary-foreground";
56
+ const mutedColor = variation === "secondary" ? "text-card-brand-secondary-foreground-muted" : "text-card-primary-foreground-muted";
57
+ const labelColor = disabled || isPlaceholder ? mutedColor : valueColor;
58
+ return /* @__PURE__ */ jsxs(
59
+ "button",
60
+ {
61
+ type: "button",
62
+ ref,
63
+ role: "combobox",
64
+ "data-slot": "inline-select-trigger",
65
+ "data-variation": variation,
66
+ disabled,
67
+ className: cn(inlineSelectVariants({ variation, disabled }), className),
68
+ ...props,
69
+ children: [
70
+ leadingSlot != null && /* @__PURE__ */ jsx(
71
+ "span",
72
+ {
73
+ "data-slot": "inline-select-leading",
74
+ "aria-hidden": "true",
75
+ className: cn(
76
+ "flex items-center [&_svg:not([class*='size-'])]:size-4",
77
+ // The leading slot follows the caret/muted colour unless a real
78
+ // value is shown, then it follows the value colour (like the label).
79
+ labelColor
80
+ ),
81
+ children: leadingSlot
82
+ }
83
+ ),
84
+ /* @__PURE__ */ jsx(
85
+ "span",
86
+ {
87
+ "data-slot": "inline-select-value",
88
+ className: cn("body-03 truncate", labelColor),
89
+ children: displayText
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsx(
93
+ "span",
94
+ {
95
+ "data-slot": "inline-select-caret",
96
+ "aria-hidden": "true",
97
+ className: "flex items-center",
98
+ children: /* @__PURE__ */ jsx(
99
+ CaretDownIcon,
100
+ {
101
+ weight: "fill",
102
+ className: cn(
103
+ "size-3 transition-transform",
104
+ // Caret uses the muted variation colour (Figma resting state).
105
+ mutedColor,
106
+ open && "rotate-180"
107
+ )
108
+ }
109
+ )
110
+ }
111
+ )
112
+ ]
113
+ }
114
+ );
115
+ }
116
+ function InlineSelect({
117
+ options,
118
+ value: valueProp,
119
+ defaultValue,
120
+ onValueChange,
121
+ variation = "primary",
122
+ placeholder = "Select",
123
+ leadingSlot,
124
+ disabled,
125
+ name,
126
+ id: idProp,
127
+ className,
128
+ ref,
129
+ ...props
130
+ }) {
131
+ const generatedId = React.useId();
132
+ const id = idProp ?? generatedId;
133
+ const {
134
+ selected,
135
+ open,
136
+ setTriggerRef,
137
+ triggerProps,
138
+ listboxProps,
139
+ text,
140
+ isPlaceholder
141
+ } = useSelectListbox({
142
+ options,
143
+ // Normalize the single-select public value to the hook's array form.
144
+ value: valueProp,
145
+ defaultValue,
146
+ // The hook emits `string | string[]`; in single mode it is always a
147
+ // `string`, so narrow before handing it to the public single callback.
148
+ onValueChange: onValueChange ? (next) => onValueChange(Array.isArray(next) ? next[0] ?? "" : next) : void 0,
149
+ multiple: false,
150
+ disabled,
151
+ id,
152
+ ref,
153
+ placeholder
154
+ });
155
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
156
+ /* @__PURE__ */ jsx(
157
+ InlineSelectTrigger,
158
+ {
159
+ ref: setTriggerRef,
160
+ id,
161
+ variation,
162
+ open,
163
+ displayText: text,
164
+ isPlaceholder,
165
+ leadingSlot,
166
+ disabled,
167
+ className,
168
+ ...triggerProps,
169
+ ...props
170
+ }
171
+ ),
172
+ name != null && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: selected[0] ?? "" }),
173
+ open && /* @__PURE__ */ jsx(
174
+ SelectListbox,
175
+ {
176
+ ...listboxProps,
177
+ widthMode: "auto",
178
+ "aria-label": props["aria-label"]
179
+ }
180
+ )
181
+ ] });
182
+ }
183
+
184
+ export { InlineSelect, InlineSelectTrigger, inlineSelectVariants };
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ function _interopNamespace(e) {
6
+ if (e && e.__esModule) return e;
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
24
+
25
+ function buildCutPath({
26
+ W,
27
+ H,
28
+ cut,
29
+ rTR,
30
+ rBL,
31
+ rCut,
32
+ ox = 0,
33
+ oy = 0
34
+ }) {
35
+ const rCutSq = rCut / Math.SQRT2;
36
+ const x = (v) => v + ox;
37
+ const y = (v) => v + oy;
38
+ return [
39
+ `M ${x(cut + rCut)} ${y(0)}`,
40
+ `L ${x(W - rTR)} ${y(0)}`,
41
+ `Q ${x(W)} ${y(0)} ${x(W)} ${y(rTR)}`,
42
+ `L ${x(W)} ${y(H - cut - rCut)}`,
43
+ `Q ${x(W)} ${y(H - cut)} ${x(W - rCutSq)} ${y(H - cut + rCutSq)}`,
44
+ `L ${x(W - cut + rCutSq)} ${y(H - rCutSq)}`,
45
+ `Q ${x(W - cut)} ${y(H)} ${x(W - cut - rCut)} ${y(H)}`,
46
+ `L ${x(rBL)} ${y(H)}`,
47
+ `Q ${x(0)} ${y(H)} ${x(0)} ${y(H - rBL)}`,
48
+ `L ${x(0)} ${y(cut + rCut)}`,
49
+ `Q ${x(0)} ${y(cut)} ${x(rCutSq)} ${y(cut - rCutSq)}`,
50
+ `L ${x(cut - rCutSq)} ${y(rCutSq)}`,
51
+ `Q ${x(cut)} ${y(0)} ${x(cut + rCut)} ${y(0)}`,
52
+ `Z`
53
+ ].join(" ");
54
+ }
55
+ function useCutCornerClipPath(cut, {
56
+ radius = 2,
57
+ radiusCuts,
58
+ radiusTopRight,
59
+ radiusBottomLeft,
60
+ outset
61
+ } = {}) {
62
+ const ref = React__namespace.useRef(null);
63
+ const [clipPath, setClipPath] = React__namespace.useState();
64
+ const [pathD, setPathD] = React__namespace.useState();
65
+ const [outsetPathD, setOutsetPathD] = React__namespace.useState();
66
+ React__namespace.useLayoutEffect(() => {
67
+ const el = ref.current;
68
+ if (!el) return;
69
+ const rTR = radiusTopRight ?? radius;
70
+ const rBL = radiusBottomLeft ?? radius;
71
+ const rCut = radiusCuts ?? radius;
72
+ function compute(W, H) {
73
+ const d = buildCutPath({ W, H, cut, rTR, rBL, rCut });
74
+ setClipPath(`path('${d}')`);
75
+ setPathD(d);
76
+ if (outset != null) {
77
+ const g = outset;
78
+ setOutsetPathD(
79
+ buildCutPath({
80
+ W: W + 2 * g,
81
+ H: H + 2 * g,
82
+ cut: cut + (2 - Math.SQRT2) * g,
83
+ rTR: rTR + g,
84
+ rBL: rBL + g,
85
+ rCut: rCut + g,
86
+ ox: -g,
87
+ oy: -g
88
+ })
89
+ );
90
+ }
91
+ }
92
+ const initial = el.getBoundingClientRect();
93
+ compute(initial.width, initial.height);
94
+ const ro = new ResizeObserver((entries) => {
95
+ const box = entries[entries.length - 1]?.borderBoxSize?.[0];
96
+ if (box) {
97
+ compute(box.inlineSize, box.blockSize);
98
+ } else {
99
+ const rect = el.getBoundingClientRect();
100
+ compute(rect.width, rect.height);
101
+ }
102
+ });
103
+ ro.observe(el);
104
+ return () => ro.disconnect();
105
+ }, [cut, radius, radiusCuts, radiusTopRight, radiusBottomLeft, outset]);
106
+ return { ref, clipPath, pathD, outsetPathD };
107
+ }
108
+ var BUTTON_CUT = { cut: 8, radius: 2, radiusCuts: 0 };
109
+
110
+ exports.BUTTON_CUT = BUTTON_CUT;
111
+ exports.useCutCornerClipPath = useCutCornerClipPath;
@@ -0,0 +1,49 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Cut-corner geometry — ported from the FD marketing site (`fd-website`
5
+ * `useCutCornerClipPath`). Two diagonally-opposite corners (top-left and
6
+ * bottom-right) are chamfered; the other two are rounded 90° corners.
7
+ *
8
+ * The chamfer size and arc radii feed SVG path math, so the shape can't be
9
+ * expressed with CSS `border-radius` / `clip-path: polygon()` alone — the path
10
+ * depends on the measured pixel width/height. We therefore measure the element
11
+ * and recompute on resize.
12
+ *
13
+ * FD apps use SHARPER edges than the marketing site: the default arc radius is
14
+ * `2px` (Figma `radius/xs`) on every vertex, versus the site's softer `6/8px`.
15
+ */
16
+ interface UseCutCornerClipPathOptions {
17
+ /** Border-radius (px) applied to every vertex unless overridden below. */
18
+ radius?: number;
19
+ /** Radius override for the two diagonal chamfer arcs. */
20
+ radiusCuts?: number;
21
+ /** Radius override for the top-right 90° corner. */
22
+ radiusTopRight?: number;
23
+ /** Radius override for the bottom-left 90° corner. */
24
+ radiusBottomLeft?: number;
25
+ /**
26
+ * If set, also emit `outsetPathD` — the same shape expanded uniformly outward
27
+ * by this many px. Used to draw a focus ring that follows the cut-corner
28
+ * outline instead of a plain rounded rectangle.
29
+ */
30
+ outset?: number;
31
+ }
32
+ declare function useCutCornerClipPath<T extends HTMLElement = HTMLElement>(cut: number, { radius, radiusCuts, radiusTopRight, radiusBottomLeft, outset, }?: UseCutCornerClipPathOptions): {
33
+ ref: React.RefObject<T | null>;
34
+ clipPath: string | undefined;
35
+ pathD: string | undefined;
36
+ outsetPathD: string | undefined;
37
+ };
38
+ /**
39
+ * Fixed cut-corner preset for buttons (Figma `01. Buttons` → `cut-8px`):
40
+ * an 8px chamfer. The two diagonal cuts are sharp (`radiusCuts: 0`); the two
41
+ * square corners keep a subtle 2px arc. Same value for `sm` and `lg`.
42
+ */
43
+ declare const BUTTON_CUT: {
44
+ readonly cut: 8;
45
+ readonly radius: 2;
46
+ readonly radiusCuts: 0;
47
+ };
48
+
49
+ export { BUTTON_CUT, type UseCutCornerClipPathOptions, useCutCornerClipPath };
@@ -0,0 +1,49 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Cut-corner geometry — ported from the FD marketing site (`fd-website`
5
+ * `useCutCornerClipPath`). Two diagonally-opposite corners (top-left and
6
+ * bottom-right) are chamfered; the other two are rounded 90° corners.
7
+ *
8
+ * The chamfer size and arc radii feed SVG path math, so the shape can't be
9
+ * expressed with CSS `border-radius` / `clip-path: polygon()` alone — the path
10
+ * depends on the measured pixel width/height. We therefore measure the element
11
+ * and recompute on resize.
12
+ *
13
+ * FD apps use SHARPER edges than the marketing site: the default arc radius is
14
+ * `2px` (Figma `radius/xs`) on every vertex, versus the site's softer `6/8px`.
15
+ */
16
+ interface UseCutCornerClipPathOptions {
17
+ /** Border-radius (px) applied to every vertex unless overridden below. */
18
+ radius?: number;
19
+ /** Radius override for the two diagonal chamfer arcs. */
20
+ radiusCuts?: number;
21
+ /** Radius override for the top-right 90° corner. */
22
+ radiusTopRight?: number;
23
+ /** Radius override for the bottom-left 90° corner. */
24
+ radiusBottomLeft?: number;
25
+ /**
26
+ * If set, also emit `outsetPathD` — the same shape expanded uniformly outward
27
+ * by this many px. Used to draw a focus ring that follows the cut-corner
28
+ * outline instead of a plain rounded rectangle.
29
+ */
30
+ outset?: number;
31
+ }
32
+ declare function useCutCornerClipPath<T extends HTMLElement = HTMLElement>(cut: number, { radius, radiusCuts, radiusTopRight, radiusBottomLeft, outset, }?: UseCutCornerClipPathOptions): {
33
+ ref: React.RefObject<T | null>;
34
+ clipPath: string | undefined;
35
+ pathD: string | undefined;
36
+ outsetPathD: string | undefined;
37
+ };
38
+ /**
39
+ * Fixed cut-corner preset for buttons (Figma `01. Buttons` → `cut-8px`):
40
+ * an 8px chamfer. The two diagonal cuts are sharp (`radiusCuts: 0`); the two
41
+ * square corners keep a subtle 2px arc. Same value for `sm` and `lg`.
42
+ */
43
+ declare const BUTTON_CUT: {
44
+ readonly cut: 8;
45
+ readonly radius: 2;
46
+ readonly radiusCuts: 0;
47
+ };
48
+
49
+ export { BUTTON_CUT, type UseCutCornerClipPathOptions, useCutCornerClipPath };
@@ -0,0 +1 @@
1
+ export { BUTTON_CUT, useCutCornerClipPath } from './chunk-JIXW3455.js';