@devalok/shilp-sutra 0.7.0 → 0.8.1
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/dist/composed/command-palette.d.ts.map +1 -1
- package/dist/composed/command-palette.js +84 -73
- package/dist/composed/extensions/emoji-suggestion.d.ts +2 -1
- package/dist/composed/extensions/emoji-suggestion.d.ts.map +1 -1
- package/dist/composed/extensions/emoji-suggestion.js +1 -1
- package/dist/composed/extensions/file-attachment.d.ts +2 -1
- package/dist/composed/extensions/file-attachment.d.ts.map +1 -1
- package/dist/composed/rich-text-editor.d.ts.map +1 -1
- package/dist/composed/rich-text-editor.js +173 -161
- package/dist/composed/status-badge.d.ts +11 -1
- package/dist/composed/status-badge.d.ts.map +1 -1
- package/dist/composed/status-badge.js +48 -20
- package/dist/hooks/use-color-mode.d.ts.map +1 -1
- package/dist/hooks/use-color-mode.js +8 -4
- package/dist/hooks/use-mobile.d.ts +5 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -1
- package/dist/node_modules/.pnpm/@emoji-mart_data@1.2.1/node_modules/@emoji-mart/data/sets/15/native.json.js +40141 -0
- package/dist/node_modules/.pnpm/@emoji-mart_react@1.1.1_emoji-mart@5.6.0_react@19.2.4/node_modules/@emoji-mart/react/dist/module.js +17 -0
- package/dist/node_modules/.pnpm/emoji-mart@5.6.0/node_modules/emoji-mart/dist/module.js +2958 -0
- package/dist/tailwind/index.cjs +2 -0
- package/dist/tailwind/preset.d.ts.map +1 -1
- package/dist/tailwind/preset.js +2 -0
- package/dist/tokens/semantic.css +3 -1
- package/dist/ui/alert.js +1 -1
- package/dist/ui/badge.js +2 -1
- package/dist/ui/banner.js +12 -12
- package/dist/ui/chip.d.ts.map +1 -1
- package/dist/ui/chip.js +1 -1
- package/dist/ui/color-input.d.ts.map +1 -1
- package/dist/ui/color-input.js +17 -16
- package/dist/ui/combobox.d.ts +20 -11
- package/dist/ui/combobox.d.ts.map +1 -1
- package/dist/ui/dialog.js +9 -9
- package/dist/ui/form.js +14 -35
- package/dist/ui/input.d.ts.map +1 -1
- package/dist/ui/input.js +12 -11
- package/dist/ui/number-input.d.ts.map +1 -1
- package/dist/ui/number-input.js +39 -35
- package/dist/ui/sheet.js +21 -21
- package/dist/ui/textarea.d.ts.map +1 -1
- package/dist/ui/textarea.js +30 -24
- package/dist/ui/toast.js +18 -18
- package/llms-full.txt +6 -4
- package/llms.txt +7 -1
- package/package.json +597 -592
- package/dist/_virtual/shilp-sutra.js +0 -5
- package/dist/_virtual/shilp-sutra2.js +0 -5
package/dist/ui/sheet.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as d, jsx as
|
|
3
|
-
import * as
|
|
4
|
-
import { Root as
|
|
2
|
+
import { jsxs as d, jsx as a } from "react/jsx-runtime";
|
|
3
|
+
import * as o from "react";
|
|
4
|
+
import { Root as x, Close as i, Portal as b, Trigger as y, Content as l, Description as n, Overlay as m, Title as c } from "../primitives/react-dialog.js";
|
|
5
5
|
import { cva as u } from "class-variance-authority";
|
|
6
6
|
import { IconX as N } from "@tabler/icons-react";
|
|
7
7
|
import { cn as r } from "./lib/utils.js";
|
|
8
|
-
const O =
|
|
8
|
+
const O = x, P = y, V = i, g = b, f = o.forwardRef(({ className: e, ...t }, s) => /* @__PURE__ */ a(
|
|
9
9
|
m,
|
|
10
10
|
{
|
|
11
11
|
className: r(
|
|
@@ -13,7 +13,7 @@ const O = b, P = y, V = i, g = x, f = s.forwardRef(({ className: e, ...t }, a) =
|
|
|
13
13
|
e
|
|
14
14
|
),
|
|
15
15
|
...t,
|
|
16
|
-
ref:
|
|
16
|
+
ref: s
|
|
17
17
|
}
|
|
18
18
|
));
|
|
19
19
|
f.displayName = m.displayName;
|
|
@@ -32,8 +32,8 @@ const v = u(
|
|
|
32
32
|
side: "right"
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
), w =
|
|
36
|
-
/* @__PURE__ */
|
|
35
|
+
), w = o.forwardRef(({ side: e = "right", className: t, children: s, ...p }, h) => /* @__PURE__ */ d(g, { children: [
|
|
36
|
+
/* @__PURE__ */ a(f, {}),
|
|
37
37
|
/* @__PURE__ */ d(
|
|
38
38
|
l,
|
|
39
39
|
{
|
|
@@ -41,21 +41,21 @@ const v = u(
|
|
|
41
41
|
className: r(v({ side: e }), t),
|
|
42
42
|
...p,
|
|
43
43
|
children: [
|
|
44
|
-
/* @__PURE__ */ d(i, { className: "absolute right-ds-05 top-ds-05 min-h-
|
|
45
|
-
/* @__PURE__ */
|
|
46
|
-
/* @__PURE__ */
|
|
44
|
+
/* @__PURE__ */ d(i, { className: "absolute right-ds-05 top-ds-05 min-h-ds-xs min-w-ds-xs flex items-center justify-center rounded-ds-sm text-icon-secondary transition-colors hover:text-icon-primary hover:bg-field focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus disabled:pointer-events-none", children: [
|
|
45
|
+
/* @__PURE__ */ a(N, { className: "h-ico-sm w-ico-sm" }),
|
|
46
|
+
/* @__PURE__ */ a("span", { className: "sr-only", children: "Close" })
|
|
47
47
|
] }),
|
|
48
|
-
|
|
48
|
+
s
|
|
49
49
|
]
|
|
50
50
|
}
|
|
51
51
|
)
|
|
52
52
|
] }));
|
|
53
53
|
w.displayName = l.displayName;
|
|
54
|
-
const S =
|
|
55
|
-
({ className: e, ...t },
|
|
54
|
+
const S = o.forwardRef(
|
|
55
|
+
({ className: e, ...t }, s) => /* @__PURE__ */ a(
|
|
56
56
|
"div",
|
|
57
57
|
{
|
|
58
|
-
ref:
|
|
58
|
+
ref: s,
|
|
59
59
|
className: r(
|
|
60
60
|
"flex flex-col space-y-ds-03 text-center sm:text-left",
|
|
61
61
|
e
|
|
@@ -65,11 +65,11 @@ const S = s.forwardRef(
|
|
|
65
65
|
)
|
|
66
66
|
);
|
|
67
67
|
S.displayName = "SheetHeader";
|
|
68
|
-
const R =
|
|
69
|
-
({ className: e, ...t },
|
|
68
|
+
const R = o.forwardRef(
|
|
69
|
+
({ className: e, ...t }, s) => /* @__PURE__ */ a(
|
|
70
70
|
"div",
|
|
71
71
|
{
|
|
72
|
-
ref:
|
|
72
|
+
ref: s,
|
|
73
73
|
className: r(
|
|
74
74
|
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-ds-03",
|
|
75
75
|
e
|
|
@@ -79,19 +79,19 @@ const R = s.forwardRef(
|
|
|
79
79
|
)
|
|
80
80
|
);
|
|
81
81
|
R.displayName = "SheetFooter";
|
|
82
|
-
const C =
|
|
82
|
+
const C = o.forwardRef(({ className: e, ...t }, s) => /* @__PURE__ */ a(
|
|
83
83
|
c,
|
|
84
84
|
{
|
|
85
|
-
ref:
|
|
85
|
+
ref: s,
|
|
86
86
|
className: r("text-ds-lg font-semibold text-text-primary", e),
|
|
87
87
|
...t
|
|
88
88
|
}
|
|
89
89
|
));
|
|
90
90
|
C.displayName = c.displayName;
|
|
91
|
-
const j =
|
|
91
|
+
const j = o.forwardRef(({ className: e, ...t }, s) => /* @__PURE__ */ a(
|
|
92
92
|
n,
|
|
93
93
|
{
|
|
94
|
-
ref:
|
|
94
|
+
ref: s,
|
|
95
95
|
className: r("text-ds-md text-text-secondary", e),
|
|
96
96
|
...t
|
|
97
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/ui/textarea.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/ui/textarea.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGzC,QAAA,MAAM,gBAAgB;;8EAsBrB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,EACrE,YAAY,CAAC,OAAO,gBAAgB,CAAC;IACvC,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,QAAA,MAAM,QAAQ,2FAyBb,CAAA;AAGD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAA"}
|
package/dist/ui/textarea.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
import * as
|
|
4
|
-
import { cva as
|
|
5
|
-
import { cn as
|
|
6
|
-
|
|
2
|
+
import { jsx as l } from "react/jsx-runtime";
|
|
3
|
+
import * as c from "react";
|
|
4
|
+
import { cva as b } from "class-variance-authority";
|
|
5
|
+
import { cn as u } from "./lib/utils.js";
|
|
6
|
+
import { useFormField as f } from "./form.js";
|
|
7
|
+
const m = b(
|
|
7
8
|
[
|
|
8
9
|
"flex w-full font-sans resize-y",
|
|
9
10
|
"bg-field text-text-primary",
|
|
@@ -25,25 +26,30 @@ const l = t(
|
|
|
25
26
|
},
|
|
26
27
|
defaultVariants: { size: "md" }
|
|
27
28
|
}
|
|
28
|
-
),
|
|
29
|
-
({ className:
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
29
|
+
), x = c.forwardRef(
|
|
30
|
+
({ className: s, state: a, size: o, ...i }, t) => {
|
|
31
|
+
const r = f(), e = a ?? (r.state === "helper" ? void 0 : r.state), d = i["aria-describedby"] ?? r.helperTextId, n = i["aria-required"] ?? r.required;
|
|
32
|
+
return /* @__PURE__ */ l(
|
|
33
|
+
"textarea",
|
|
34
|
+
{
|
|
35
|
+
"aria-invalid": e === "error" || void 0,
|
|
36
|
+
"aria-describedby": d,
|
|
37
|
+
"aria-required": n || void 0,
|
|
38
|
+
className: u(
|
|
39
|
+
m({ size: o }),
|
|
40
|
+
e === "error" && "border-border-error focus-visible:ring-error",
|
|
41
|
+
e === "warning" && "border-border-warning focus-visible:ring-warning",
|
|
42
|
+
e === "success" && "border-border-success focus-visible:ring-success",
|
|
43
|
+
s
|
|
44
|
+
),
|
|
45
|
+
ref: t,
|
|
46
|
+
...i
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
}
|
|
44
50
|
);
|
|
45
|
-
|
|
51
|
+
x.displayName = "Textarea";
|
|
46
52
|
export {
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
x as Textarea,
|
|
54
|
+
m as textareaVariants
|
|
49
55
|
};
|
package/dist/ui/toast.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
2
|
+
import { jsx as o } from "react/jsx-runtime";
|
|
3
3
|
import * as r from "react";
|
|
4
4
|
import { Provider as p, Root as i, Action as d, Close as n, Description as l, Title as c, Viewport as m } from "../primitives/react-toast.js";
|
|
5
5
|
import { cva as u } from "class-variance-authority";
|
|
6
|
-
import { IconX as
|
|
6
|
+
import { IconX as x } from "@tabler/icons-react";
|
|
7
7
|
import { cn as a } from "./lib/utils.js";
|
|
8
|
-
const C = p,
|
|
8
|
+
const C = p, b = r.forwardRef(({ className: e, ...t }, s) => /* @__PURE__ */ o(
|
|
9
9
|
m,
|
|
10
10
|
{
|
|
11
|
-
ref:
|
|
11
|
+
ref: s,
|
|
12
12
|
className: a(
|
|
13
13
|
"fixed top-0 z-toast flex max-h-screen w-full flex-col-reverse p-ds-05 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
|
14
14
|
e
|
|
@@ -16,7 +16,7 @@ const C = p, x = r.forwardRef(({ className: e, ...t }, o) => /* @__PURE__ */ s(
|
|
|
16
16
|
...t
|
|
17
17
|
}
|
|
18
18
|
));
|
|
19
|
-
|
|
19
|
+
b.displayName = m.displayName;
|
|
20
20
|
const v = u(
|
|
21
21
|
"group pointer-events-auto relative flex w-full items-center justify-between space-x-ds-03 overflow-hidden rounded-ds-md border p-ds-05 pr-ds-06 shadow-03 transition-all duration-moderate-02 data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
|
|
22
22
|
{
|
|
@@ -33,21 +33,21 @@ const v = u(
|
|
|
33
33
|
color: "neutral"
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
), w = r.forwardRef(({ className: e, color: t, ...
|
|
36
|
+
), w = r.forwardRef(({ className: e, color: t, ...s }, f) => /* @__PURE__ */ o(
|
|
37
37
|
i,
|
|
38
38
|
{
|
|
39
39
|
ref: f,
|
|
40
40
|
role: "status",
|
|
41
41
|
"aria-live": "polite",
|
|
42
42
|
className: a(v({ color: t }), e),
|
|
43
|
-
...
|
|
43
|
+
...s
|
|
44
44
|
}
|
|
45
45
|
));
|
|
46
46
|
w.displayName = i.displayName;
|
|
47
|
-
const y = r.forwardRef(({ className: e, ...t },
|
|
47
|
+
const y = r.forwardRef(({ className: e, ...t }, s) => /* @__PURE__ */ o(
|
|
48
48
|
d,
|
|
49
49
|
{
|
|
50
|
-
ref:
|
|
50
|
+
ref: s,
|
|
51
51
|
className: a(
|
|
52
52
|
"inline-flex h-ds-sm shrink-0 items-center justify-center rounded-ds-md border border-border bg-transparent px-ds-04 text-ds-md font-medium transition-colors hover:bg-layer-02 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-[0.38] group-[.destructive]:border-border-error group-[.destructive]:hover:bg-error-surface",
|
|
53
53
|
e
|
|
@@ -56,33 +56,33 @@ const y = r.forwardRef(({ className: e, ...t }, o) => /* @__PURE__ */ s(
|
|
|
56
56
|
}
|
|
57
57
|
));
|
|
58
58
|
y.displayName = d.displayName;
|
|
59
|
-
const g = r.forwardRef(({ className: e, ...t },
|
|
59
|
+
const g = r.forwardRef(({ className: e, ...t }, s) => /* @__PURE__ */ o(
|
|
60
60
|
n,
|
|
61
61
|
{
|
|
62
|
-
ref:
|
|
62
|
+
ref: s,
|
|
63
63
|
className: a(
|
|
64
|
-
"absolute right-ds-02 top-ds-02 min-h-
|
|
64
|
+
"absolute right-ds-02 top-ds-02 min-h-ds-xs min-w-ds-xs flex items-center justify-center rounded-ds-md p-ds-02 text-text-secondary opacity-70 transition-opacity hover:text-text-primary hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus",
|
|
65
65
|
e
|
|
66
66
|
),
|
|
67
67
|
"toast-close": "",
|
|
68
68
|
...t,
|
|
69
|
-
children: /* @__PURE__ */
|
|
69
|
+
children: /* @__PURE__ */ o(x, { className: "h-ico-sm w-ico-sm" })
|
|
70
70
|
}
|
|
71
71
|
));
|
|
72
72
|
g.displayName = n.displayName;
|
|
73
|
-
const N = r.forwardRef(({ className: e, ...t },
|
|
73
|
+
const N = r.forwardRef(({ className: e, ...t }, s) => /* @__PURE__ */ o(
|
|
74
74
|
c,
|
|
75
75
|
{
|
|
76
|
-
ref:
|
|
76
|
+
ref: s,
|
|
77
77
|
className: a("text-ds-md font-semibold [&+div]:text-ds-sm", e),
|
|
78
78
|
...t
|
|
79
79
|
}
|
|
80
80
|
));
|
|
81
81
|
N.displayName = c.displayName;
|
|
82
|
-
const h = r.forwardRef(({ className: e, ...t },
|
|
82
|
+
const h = r.forwardRef(({ className: e, ...t }, s) => /* @__PURE__ */ o(
|
|
83
83
|
l,
|
|
84
84
|
{
|
|
85
|
-
ref:
|
|
85
|
+
ref: s,
|
|
86
86
|
className: a("text-ds-md opacity-[0.9]", e),
|
|
87
87
|
...t
|
|
88
88
|
}
|
|
@@ -95,5 +95,5 @@ export {
|
|
|
95
95
|
h as ToastDescription,
|
|
96
96
|
C as ToastProvider,
|
|
97
97
|
N as ToastTitle,
|
|
98
|
-
|
|
98
|
+
b as ToastViewport
|
|
99
99
|
};
|
package/llms-full.txt
CHANGED
|
@@ -390,12 +390,12 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
390
390
|
- Server-safe: No
|
|
391
391
|
- Props:
|
|
392
392
|
options: ComboboxOption[] (REQUIRED) — { value: string, label: string, description?: string, icon?: ReactNode, disabled?: boolean }
|
|
393
|
-
|
|
394
|
-
|
|
393
|
+
DISCRIMINATED UNION — type depends on `multiple` flag:
|
|
394
|
+
Single (default): multiple?: false, value: string, onValueChange: (value: string) => void
|
|
395
|
+
Multiple: multiple: true, value: string[], onValueChange: (value: string[]) => void
|
|
395
396
|
placeholder: string (default: "Select...")
|
|
396
397
|
searchPlaceholder: string (default: "Search...")
|
|
397
398
|
emptyMessage: string (default: "No results found")
|
|
398
|
-
multiple: boolean (default: false)
|
|
399
399
|
disabled: boolean
|
|
400
400
|
triggerClassName: string
|
|
401
401
|
maxVisible: number (default: 6, max dropdown items before scroll)
|
|
@@ -405,7 +405,7 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
405
405
|
multiple
|
|
406
406
|
options={tagOptions}
|
|
407
407
|
value={selectedTags}
|
|
408
|
-
onValueChange={
|
|
408
|
+
onValueChange={setSelectedTags}
|
|
409
409
|
placeholder="Select tags..."
|
|
410
410
|
/>
|
|
411
411
|
- Gotchas:
|
|
@@ -593,6 +593,7 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
593
593
|
- Gotchas:
|
|
594
594
|
- HTML native "size" attribute is excluded — use CSS width instead
|
|
595
595
|
- state="error" sets aria-invalid automatically
|
|
596
|
+
- Inside FormField: auto-inherits state, aria-describedby, aria-required from context (explicit props override)
|
|
596
597
|
|
|
597
598
|
## InputOTP
|
|
598
599
|
- Import: @devalok/shilp-sutra/ui/input-otp
|
|
@@ -1134,6 +1135,7 @@ Note: getFormFieldA11y() was removed in favor of useFormField() hook.
|
|
|
1134
1135
|
- Example:
|
|
1135
1136
|
<Textarea size="lg" state="error" placeholder="Describe the issue..." />
|
|
1136
1137
|
- Gotchas: state="error" sets aria-invalid automatically; all sizes are vertically resizable
|
|
1138
|
+
- Inside FormField: auto-inherits state, aria-describedby, aria-required from context (explicit props override)
|
|
1137
1139
|
|
|
1138
1140
|
## Toast / Toaster
|
|
1139
1141
|
- Import: @devalok/shilp-sutra/ui/toast, @devalok/shilp-sutra/ui/toaster
|
package/llms.txt
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
> Built on the same primitives as shadcn/ui but with key API differences.
|
|
5
5
|
> Read this file BEFORE writing any UI code. Do NOT guess from shadcn/ui knowledge.
|
|
6
6
|
|
|
7
|
+
## BREAKING CHANGES (v0.8.0)
|
|
8
|
+
- Combobox: Now uses discriminated union. Single: `multiple?: false, value: string, onValueChange: (v: string) => void`. Multiple: `multiple: true, value: string[], onValueChange: (v: string[]) => void`. No more `v as string[]` casts.
|
|
9
|
+
- StatusBadge: Pass either `status` OR `color`, not both (discriminated union).
|
|
10
|
+
- Input/Textarea: Now auto-inherit state, aria-describedby, aria-required from FormField context. Explicit props override.
|
|
11
|
+
|
|
7
12
|
## Install & Setup
|
|
8
13
|
|
|
9
14
|
pnpm add @devalok/shilp-sutra
|
|
@@ -127,12 +132,13 @@ NOTIFICATION SELECTION GUIDE:
|
|
|
127
132
|
- FormField: state(helper|error|warning|success) > Label + Input + FormHelperText
|
|
128
133
|
- useFormField() hook returns { state, helperTextId, required } from FormField context
|
|
129
134
|
- Wire accessibility: const { state, helperTextId } = useFormField(); then aria-describedby={helperTextId}, aria-invalid={state === 'error'}
|
|
135
|
+
- Input/Textarea auto-wire from FormField context (no manual hookup needed). Explicit props override.
|
|
130
136
|
|
|
131
137
|
### Composed Components
|
|
132
138
|
- ConfirmDialog: open, onOpenChange, title, description, onConfirm + confirmText, cancelText, color(default|error), loading
|
|
133
139
|
- PageHeader: title, subtitle, breadcrumbs[], actions(ReactNode)
|
|
134
140
|
- AvatarGroup: users[], max(number), size(sm|md|lg), showTooltip
|
|
135
|
-
- StatusBadge: status(active|pending|approved|rejected|completed|blocked|cancelled|draft) color(success|warning|error|info|neutral) size(sm|md)
|
|
141
|
+
- StatusBadge: DISCRIMINATED UNION — pass status OR color, not both. status(active|pending|approved|rejected|completed|blocked|cancelled|draft) color(success|warning|error|info|neutral) size(sm|md)
|
|
136
142
|
- ContentCard: variant(default|outline|ghost) padding(default|compact|spacious|none)
|
|
137
143
|
- EmptyState: icon, title(required), description, action(ReactNode), compact
|
|
138
144
|
- PriorityIndicator: priority(LOW|MEDIUM|HIGH|URGENT) display(compact|full)
|