@gratiaos/ui 1.0.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/LICENSE +243 -0
- package/README.md +170 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useMissingScrew.d.ts +40 -0
- package/dist/hooks/useMissingScrew.d.ts.map +1 -0
- package/dist/hooks/useMissingScrew.js +76 -0
- package/dist/hooks/useMissingScrew.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/pad/Button.d.ts +10 -0
- package/dist/pad/Button.d.ts.map +1 -0
- package/dist/pad/Button.js +7 -0
- package/dist/pad/Button.js.map +1 -0
- package/dist/pad/Card.d.ts +8 -0
- package/dist/pad/Card.d.ts.map +1 -0
- package/dist/pad/Card.js +3 -0
- package/dist/pad/Card.js.map +1 -0
- package/dist/primitives/badge.d.ts +66 -0
- package/dist/primitives/badge.d.ts.map +1 -0
- package/dist/primitives/badge.js +23 -0
- package/dist/primitives/badge.js.map +1 -0
- package/dist/primitives/button.d.ts +60 -0
- package/dist/primitives/button.d.ts.map +1 -0
- package/dist/primitives/button.js +39 -0
- package/dist/primitives/button.js.map +1 -0
- package/dist/primitives/card.d.ts +54 -0
- package/dist/primitives/card.d.ts.map +1 -0
- package/dist/primitives/card.js +11 -0
- package/dist/primitives/card.js.map +1 -0
- package/dist/primitives/field.d.ts +107 -0
- package/dist/primitives/field.d.ts.map +1 -0
- package/dist/primitives/field.js +154 -0
- package/dist/primitives/field.js.map +1 -0
- package/dist/primitives/pill.d.ts +59 -0
- package/dist/primitives/pill.d.ts.map +1 -0
- package/dist/primitives/pill.js +26 -0
- package/dist/primitives/pill.js.map +1 -0
- package/dist/primitives/slot.d.ts +7 -0
- package/dist/primitives/slot.d.ts.map +1 -0
- package/dist/primitives/slot.js +9 -0
- package/dist/primitives/slot.js.map +1 -0
- package/dist/primitives/toast.d.ts +125 -0
- package/dist/primitives/toast.d.ts.map +1 -0
- package/dist/primitives/toast.js +462 -0
- package/dist/primitives/toast.js.map +1 -0
- package/package.json +87 -0
- package/styles/badge.css +175 -0
- package/styles/base.css +7 -0
- package/styles/button.css +257 -0
- package/styles/card.css +195 -0
- package/styles/field.css +195 -0
- package/styles/pad.css +140 -0
- package/styles/pill.css +167 -0
- package/styles/theme.css +492 -0
- package/styles/toast.css +286 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/pad/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,KAAK,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IACtD,EAAE,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;IACvB,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAEpC,CAAC"}
|
package/dist/pad/Card.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const Card = ({ as: Tag = 'section', padding = 'md', className = '', ...rest }) => (_jsx(Tag, { "data-ui": "pad-card", className: `pad-card ${padding === 'sm' ? 'p-3' : padding === 'lg' ? 'p-6' : 'p-4'} ${className}`, ...rest }));
|
|
3
|
+
//# sourceMappingURL=Card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/pad/Card.tsx"],"names":[],"mappings":";AAOA,MAAM,CAAC,MAAM,IAAI,GAAwB,CAAC,EAAE,EAAE,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,GAAG,IAAI,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,CAC7G,KAAC,GAAG,eAAS,UAAU,EAAC,SAAS,EAAE,YAAY,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,SAAS,EAAE,KAAM,IAAI,GAAI,CACxI,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Garden UI — Badge primitive (headless)
|
|
4
|
+
* --------------------------------------
|
|
5
|
+
* Whisper: "small truths, softly visible." 🌬️
|
|
6
|
+
*
|
|
7
|
+
* Purpose
|
|
8
|
+
* • Compact status/metadata label (denser than Pill, squarer radius).
|
|
9
|
+
* • Headless: emits data-attributes only; visuals live in styles/badge.css.
|
|
10
|
+
*
|
|
11
|
+
* Data API
|
|
12
|
+
* • [data-ui="badge"] — root hook
|
|
13
|
+
* • [data-variant="soft|solid|outline|subtle"]
|
|
14
|
+
* • [data-tone="subtle|accent|positive|warning|danger"]
|
|
15
|
+
* • [data-size="sm|md"] — default: sm
|
|
16
|
+
*
|
|
17
|
+
* A11y
|
|
18
|
+
* • Content is the accessible label; leading/trailing are aria-hidden.
|
|
19
|
+
* • When rendered as <button>, defaults type="button" (no accidental submits).
|
|
20
|
+
*
|
|
21
|
+
* Theming
|
|
22
|
+
* • Colors, borders, radius are defined in styles/badge.css via tokens.
|
|
23
|
+
*
|
|
24
|
+
* When to use
|
|
25
|
+
* • Inline facts (e.g., "Car", "Bridge", counts) where space is tight.
|
|
26
|
+
* • Use Pill when you want a rounder / more prominent chip.
|
|
27
|
+
*/
|
|
28
|
+
/** Visual tone (mapped by the skin). */
|
|
29
|
+
export type BadgeTone = 'subtle' | 'accent' | 'positive' | 'warning' | 'danger' | (string & {});
|
|
30
|
+
/** Visual weight (see skin for rendering). */
|
|
31
|
+
export type BadgeVariant = 'soft' | 'solid' | 'outline' | 'subtle' | (string & {});
|
|
32
|
+
/** Component size scale. Defaults to "sm". */
|
|
33
|
+
export type BadgeSize = 'sm' | 'md' | (string & {});
|
|
34
|
+
type BaseProps = {
|
|
35
|
+
/** Visual weight. Defaults to "soft". */
|
|
36
|
+
variant?: BadgeVariant;
|
|
37
|
+
/** Color tone. Defaults to "subtle". */
|
|
38
|
+
tone?: BadgeTone;
|
|
39
|
+
/** Component size. Defaults to "sm". */
|
|
40
|
+
size?: BadgeSize;
|
|
41
|
+
/** Optional leading adornment (icon, dot, avatar). */
|
|
42
|
+
leading?: React.ReactNode;
|
|
43
|
+
/** Optional trailing adornment (icon, counter, close). */
|
|
44
|
+
trailing?: React.ReactNode;
|
|
45
|
+
/** Additional class names forwarded to the root. */
|
|
46
|
+
className?: string;
|
|
47
|
+
/** Visible label/content (accessible name). */
|
|
48
|
+
children?: React.ReactNode;
|
|
49
|
+
};
|
|
50
|
+
/** Render as a different element. Defaults to span. */
|
|
51
|
+
type BadgeSpanProps = BaseProps & React.ComponentPropsWithoutRef<'span'> & {
|
|
52
|
+
as?: 'span';
|
|
53
|
+
};
|
|
54
|
+
/** Render as a button element. */
|
|
55
|
+
type BadgeButtonProps = BaseProps & React.ComponentPropsWithoutRef<'button'> & {
|
|
56
|
+
as: 'button';
|
|
57
|
+
};
|
|
58
|
+
/** Render as a link element. */
|
|
59
|
+
type BadgeAnchorProps = BaseProps & React.ComponentPropsWithoutRef<'a'> & {
|
|
60
|
+
as: 'a';
|
|
61
|
+
};
|
|
62
|
+
/** Discriminated union of supported render targets (defaults to <span>). */
|
|
63
|
+
type BadgeProps = BadgeSpanProps | BadgeButtonProps | BadgeAnchorProps;
|
|
64
|
+
export declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLElement>>;
|
|
65
|
+
export default Badge;
|
|
66
|
+
//# sourceMappingURL=badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../src/primitives/badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,wCAAwC;AACxC,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAChG,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AACnF,8CAA8C;AAC9C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAEpD,KAAK,SAAS,GAAG;IACf,yCAAyC;IACzC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,wCAAwC;IACxC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wCAAwC;IACxC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,sDAAsD;IACtD,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,uDAAuD;AACvD,KAAK,cAAc,GAAG,SAAS,GAAG,KAAK,CAAC,wBAAwB,CAAC,MAAM,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC3F,kCAAkC;AAClC,KAAK,gBAAgB,GAAG,SAAS,GAAG,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC,GAAG;IAAE,EAAE,EAAE,QAAQ,CAAA;CAAE,CAAC;AAChG,gCAAgC;AAChC,KAAK,gBAAgB,GAAG,SAAS,GAAG,KAAK,CAAC,wBAAwB,CAAC,GAAG,CAAC,GAAG;IAAE,EAAE,EAAE,GAAG,CAAA;CAAE,CAAC;AAEtF,4EAA4E;AAC5E,KAAK,UAAU,GAAG,cAAc,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAyBvE,eAAO,MAAM,KAAK,gFA+ChB,CAAC;AAIH,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
/** Compose visual slots and hide icons from assistive tech (text is the name). */
|
|
4
|
+
function renderContent(leading, trailing, children) {
|
|
5
|
+
return (_jsxs(_Fragment, { children: [leading ? (
|
|
6
|
+
// Presentational — hidden from AT since the text already conveys the label
|
|
7
|
+
_jsx("span", { "aria-hidden": "true", "data-slot": "icon leading", children: leading })) : null, children, trailing ? (_jsx("span", { "aria-hidden": "true", "data-slot": "icon trailing", children: trailing })) : null] }));
|
|
8
|
+
}
|
|
9
|
+
export const Badge = React.forwardRef((props, ref) => {
|
|
10
|
+
if (props.as === 'button') {
|
|
11
|
+
const { as, variant = 'soft', tone = 'subtle', size = 'sm', leading, trailing, className, type, children, ...rest } = props;
|
|
12
|
+
return (_jsx("button", { ref: ref, "data-ui": "badge", "data-variant": variant, "data-tone": tone, "data-size": size, className: className, type: type ?? 'button', ...rest, children: renderContent(leading, trailing, children) }));
|
|
13
|
+
}
|
|
14
|
+
if (props.as === 'a') {
|
|
15
|
+
const { as, variant = 'soft', tone = 'subtle', size = 'sm', leading, trailing, className, children, ...rest } = props;
|
|
16
|
+
return (_jsx("a", { ref: ref, "data-ui": "badge", "data-variant": variant, "data-tone": tone, "data-size": size, className: className, ...rest, children: renderContent(leading, trailing, children) }));
|
|
17
|
+
}
|
|
18
|
+
const { as, variant = 'soft', tone = 'subtle', size = 'sm', leading, trailing, className, children, ...rest } = props;
|
|
19
|
+
return (_jsx("span", { ref: ref, "data-ui": "badge", "data-variant": variant, "data-tone": tone, "data-size": size, className: className, ...rest, children: renderContent(leading, trailing, children) }));
|
|
20
|
+
});
|
|
21
|
+
Badge.displayName = 'Badge';
|
|
22
|
+
export default Badge;
|
|
23
|
+
//# sourceMappingURL=badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.js","sourceRoot":"","sources":["../../src/primitives/badge.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAkE/B,kFAAkF;AAClF,SAAS,aAAa,CAAC,OAAwB,EAAE,QAAyB,EAAE,QAAyB;IACnG,OAAO,CACL,8BACG,OAAO,CAAC,CAAC,CAAC;YACT,2EAA2E;YAC3E,8BAAkB,MAAM,eAAW,cAAc,YAC9C,OAAO,GACH,CACR,CAAC,CAAC,CAAC,IAAI,EACP,QAAQ,EACR,QAAQ,CAAC,CAAC,CAAC,CACV,8BAAkB,MAAM,eAAW,eAAe,YAC/C,QAAQ,GACJ,CACR,CAAC,CAAC,CAAC,IAAI,IACP,CACJ,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAA2B,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC7E,IAAI,KAAK,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QAC5H,OAAO,CACL,iBACE,GAAG,EAAE,GAAmC,aAChC,OAAO,kBACD,OAAO,eACV,IAAI,eACJ,IAAI,EACf,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,IAAI,IAAI,QAAQ,KAClB,IAAI,YACP,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,GACpC,CACV,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,EAAE,KAAK,GAAG,EAAE,CAAC;QACrB,MAAM,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QACtH,OAAO,CACL,YACE,GAAG,EAAE,GAAmC,aAChC,OAAO,kBACD,OAAO,eACV,IAAI,eACJ,IAAI,EACf,SAAS,EAAE,SAAS,KAChB,IAAI,YACP,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,GACzC,CACL,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACtH,OAAO,CACL,eACE,GAAG,EAAE,GAAiC,aAC9B,OAAO,kBACD,OAAO,eACV,IAAI,eACJ,IAAI,EACf,SAAS,EAAE,SAAS,KAChB,IAAI,YACP,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,GACtC,CACR,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC;AAE5B,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Garden UI — Button primitive (headless)
|
|
4
|
+
* ---------------------------------------
|
|
5
|
+
* Whisper: "action should feel grounded, never frantic." 🌬️
|
|
6
|
+
*
|
|
7
|
+
* Purpose
|
|
8
|
+
* • Accessible trigger for primary/secondary actions.
|
|
9
|
+
* • Headless: visuals live in styles/button.css; this file emits structure + data-attrs.
|
|
10
|
+
*
|
|
11
|
+
* Data API
|
|
12
|
+
* • [data-ui="button"] root
|
|
13
|
+
* • [data-variant="solid|outline|ghost|subtle"] [data-tone] [data-density]
|
|
14
|
+
* • [data-state="idle|loading|disabled"]
|
|
15
|
+
* • [data-loading-mode="inline|blocking"] (when loading)
|
|
16
|
+
* • [data-slot="icon leading|label|icon trailing|spinner|overlay"] parts for skins
|
|
17
|
+
*
|
|
18
|
+
* A11y
|
|
19
|
+
* • Native <button> covers keyboard/role by default.
|
|
20
|
+
* • When `asChild` renders a <span>, we emulate button behavior:
|
|
21
|
+
* role="button", tabIndex, Space/Enter→click and respect disabled/loading.
|
|
22
|
+
* • Spinner/overlay are presentational and marked `aria-hidden`.
|
|
23
|
+
*
|
|
24
|
+
* Theming
|
|
25
|
+
* • Skin reads tokens: --color-*, --radius-*, --shadow-*.
|
|
26
|
+
*
|
|
27
|
+
* Notes
|
|
28
|
+
* • “blocking” overlays the content for long ops; avoid overuse.
|
|
29
|
+
*/
|
|
30
|
+
/** Visual tone (mapped by the skin). */
|
|
31
|
+
export type ButtonTone = 'default' | 'accent' | 'positive' | 'warning' | 'danger';
|
|
32
|
+
/** Visual weight (see skin for rendering). */
|
|
33
|
+
export type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'subtle';
|
|
34
|
+
/** Vertical density (compact vs roomy). */
|
|
35
|
+
export type ButtonDensity = 'cozy' | 'snug';
|
|
36
|
+
/** Loading presentation. */
|
|
37
|
+
export type ButtonLoadingMode = 'inline' | 'blocking';
|
|
38
|
+
type ButtonOwnProps = {
|
|
39
|
+
/** Render as a span that mimics a button (role/keys). Defaults to false. */
|
|
40
|
+
asChild?: boolean;
|
|
41
|
+
/** Color tone. Defaults to "default". */
|
|
42
|
+
tone?: ButtonTone;
|
|
43
|
+
/** Visual weight. Defaults to "solid". */
|
|
44
|
+
variant?: ButtonVariant;
|
|
45
|
+
/** Vertical density. Defaults to "cozy". */
|
|
46
|
+
density?: ButtonDensity;
|
|
47
|
+
/** Show progress affordance. */
|
|
48
|
+
loading?: boolean;
|
|
49
|
+
/** Loading presentation: "inline" (default) or "blocking". */
|
|
50
|
+
loadingMode?: ButtonLoadingMode;
|
|
51
|
+
/** Optional leading adornment (icon). */
|
|
52
|
+
leadingIcon?: React.ReactNode;
|
|
53
|
+
/** Optional trailing adornment (icon). */
|
|
54
|
+
trailingIcon?: React.ReactNode;
|
|
55
|
+
};
|
|
56
|
+
/** Public props for Button (native button attrs + headless options). */
|
|
57
|
+
export type ButtonProps = ButtonOwnProps & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
58
|
+
export declare const Button: React.ForwardRefExoticComponent<ButtonOwnProps & React.ButtonHTMLAttributes<HTMLButtonElement> & React.RefAttributes<HTMLButtonElement>>;
|
|
59
|
+
export default Button;
|
|
60
|
+
//# sourceMappingURL=button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/primitives/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,wCAAwC;AACxC,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAClF,8CAA8C;AAC9C,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AACrE,2CAA2C;AAC3C,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAC5C,4BAA4B;AAC5B,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEtD,KAAK,cAAc,GAAG;IACpB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yCAAyC;IACzC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,yCAAyC;IACzC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,0CAA0C;IAC1C,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAChC,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAEzF,eAAO,MAAM,MAAM,0IAqGlB,CAAC;AAIF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
export const Button = React.forwardRef(({ asChild, tone = 'default', variant = 'solid', density = 'cozy', loading = false, loadingMode = 'inline', leadingIcon, trailingIcon, children, type, disabled, onClick, onKeyDown, ...rest }, ref) => {
|
|
4
|
+
const dataAttrs = {
|
|
5
|
+
'data-ui': 'button',
|
|
6
|
+
'data-tone': tone,
|
|
7
|
+
'data-variant': variant,
|
|
8
|
+
'data-density': density,
|
|
9
|
+
'data-state': loading ? 'loading' : disabled ? 'disabled' : 'idle',
|
|
10
|
+
'data-loading-mode': loading ? loadingMode : undefined,
|
|
11
|
+
};
|
|
12
|
+
const content = (_jsxs(_Fragment, { children: [leadingIcon ? (_jsx("span", { "data-slot": "icon leading", "aria-hidden": "true", children: leadingIcon })) : null, children != null ? _jsx("span", { "data-slot": "label", children: children }) : null, trailingIcon ? (_jsx("span", { "data-slot": "icon trailing", "aria-hidden": "true", children: trailingIcon })) : null, loading && loadingMode === 'inline' ? _jsx("span", { "data-slot": "spinner", "aria-hidden": "true" }) : null, loading && loadingMode === 'blocking' ? (_jsx("span", { "data-slot": "overlay", "aria-hidden": "true", children: _jsx("span", { "data-slot": "spinner" }) })) : null] }));
|
|
13
|
+
if (asChild) {
|
|
14
|
+
const handleClick = (e) => {
|
|
15
|
+
if (disabled || loading) {
|
|
16
|
+
e.preventDefault();
|
|
17
|
+
e.stopPropagation();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
onClick?.(e);
|
|
21
|
+
};
|
|
22
|
+
const handleKeyDown = (e) => {
|
|
23
|
+
onKeyDown?.(e);
|
|
24
|
+
if (e.defaultPrevented)
|
|
25
|
+
return;
|
|
26
|
+
if (disabled || loading)
|
|
27
|
+
return;
|
|
28
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
e.currentTarget.click();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return (_jsx("span", { ref: ref, role: "button", "aria-busy": loading || undefined, "aria-disabled": disabled || undefined, tabIndex: disabled ? -1 : 0, onClick: handleClick, onKeyDown: handleKeyDown, ...dataAttrs, ...rest, children: content }));
|
|
34
|
+
}
|
|
35
|
+
return (_jsx("button", { ref: ref, type: type ?? 'button', "aria-busy": loading || undefined, disabled: disabled, onClick: onClick, onKeyDown: onKeyDown, ...dataAttrs, ...rest, children: content }));
|
|
36
|
+
});
|
|
37
|
+
Button.displayName = 'Button';
|
|
38
|
+
export default Button;
|
|
39
|
+
//# sourceMappingURL=button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/primitives/button.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Garden UI — Card primitive (headless)
|
|
4
|
+
* -------------------------------------
|
|
5
|
+
* Whisper: "surfaces should invite, not insist." 🌬️
|
|
6
|
+
*
|
|
7
|
+
* Purpose
|
|
8
|
+
* • Lightweight surface wrapper for grouping content.
|
|
9
|
+
* • Headless by design — visuals come from tokens & optional skins.
|
|
10
|
+
*
|
|
11
|
+
* Data API (for skins)
|
|
12
|
+
* • [data-ui="card"]
|
|
13
|
+
* • [data-variant="plain|elev|glow|outline|inset|ghost|…"] — depth/outline semantics (extensible)
|
|
14
|
+
* • [data-padding="none|sm|md|lg"] — inner spacing
|
|
15
|
+
*
|
|
16
|
+
* A11y
|
|
17
|
+
* • Card is purely presentational; pass semantics via props (e.g., role="region", aria-labelledby).
|
|
18
|
+
* • No tabIndex by default; avoid using Card as an interactive control.
|
|
19
|
+
*
|
|
20
|
+
* Theming
|
|
21
|
+
* • Uses tokens: --color-surface, --color-elev, --color-border, --sheet-radius, --ring-accent.
|
|
22
|
+
* • Depth via utility `shadow-depth-*` (theme-controlled); glow uses an accent outline.
|
|
23
|
+
*
|
|
24
|
+
* When to use
|
|
25
|
+
* • As a neutral container in dashboards, pads, and panels.
|
|
26
|
+
* • Keep padding modest; compose layout with Stack/Grid instead of adding layout logic here.
|
|
27
|
+
*
|
|
28
|
+
* Notes
|
|
29
|
+
* • Variants are **pass‑through** to CSS skins; adding values here doesn't change visuals unless your skin targets them.
|
|
30
|
+
* • The type allows custom strings so downstream apps can trial variants without changing this file again.
|
|
31
|
+
*/
|
|
32
|
+
/** Visual depth/outline semantics (skin renders). */
|
|
33
|
+
type Variant = 'plain' | 'elev' | 'glow' | 'outline' | 'inset' | 'ghost' | (string & {});
|
|
34
|
+
/** Inner spacing scale for content. */
|
|
35
|
+
type Padding = 'none' | 'sm' | 'md' | 'lg';
|
|
36
|
+
export type CardProps<T extends React.ElementType = 'div'> = {
|
|
37
|
+
/** Render as a different element. Defaults to div. */
|
|
38
|
+
as?: T;
|
|
39
|
+
/** Visual depth/outline semantics. Defaults to "elev". */
|
|
40
|
+
variant?: Variant;
|
|
41
|
+
/** Inner spacing scale. Defaults to "md". */
|
|
42
|
+
padding?: Padding;
|
|
43
|
+
/** Additional class names forwarded to the root. */
|
|
44
|
+
className?: string;
|
|
45
|
+
/** Content inside the card (accessible name comes from content/aria props). */
|
|
46
|
+
children?: React.ReactNode;
|
|
47
|
+
} & Omit<React.ComponentPropsWithoutRef<T>, 'as' | 'children' | 'className'>;
|
|
48
|
+
export declare const Card: ((props: CardProps<any> & {
|
|
49
|
+
ref?: React.Ref<Element>;
|
|
50
|
+
}) => React.ReactElement | null) & {
|
|
51
|
+
displayName?: string;
|
|
52
|
+
};
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/primitives/card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,qDAAqD;AACrD,KAAK,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AACzF,uCAAuC;AACvC,KAAK,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,KAAK,IAAI;IAC3D,sDAAsD;IACtD,EAAE,CAAC,EAAE,CAAC,CAAC;IACP,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,UAAU,GAAG,WAAW,CAAC,CAAC;AAqB7E,eAAO,MAAM,IAAI,EAAuB,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;CAAE,KAAK,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG;IAC9H,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
const _Card = React.forwardRef(({ as, variant = 'elev', padding = 'md', className, children, ...rest }, ref) => {
|
|
4
|
+
const Comp = (as || 'div'); // polymorphic root
|
|
5
|
+
return (_jsx(Comp, { ref: ref, "data-ui": "card", "data-variant": variant, "data-padding": padding, className: className, ...rest, children: children }));
|
|
6
|
+
});
|
|
7
|
+
// Set displayName on the uncast component (avoids TS2339 after casting)
|
|
8
|
+
_Card.displayName = 'Card';
|
|
9
|
+
// Now cast to the polymorphic callable signature and export
|
|
10
|
+
export const Card = _Card;
|
|
11
|
+
//# sourceMappingURL=card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../../src/primitives/card.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAmD/B,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAC5B,CACE,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAgB,EACpF,GAAuB,EACvB,EAAE;IACF,MAAM,IAAI,GAAG,CAAC,EAAE,IAAI,KAAK,CAAsB,CAAC,CAAC,mBAAmB;IAEpE,OAAO,CACL,KAAC,IAAI,IAAC,GAAG,EAAE,GAAG,aAAU,MAAM,kBAAe,OAAO,kBAAgB,OAAO,EAAE,SAAS,EAAE,SAAS,KAAM,IAAI,YACxG,QAAQ,GACJ,CACR,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,wEAAwE;AACxE,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;AAE3B,4DAA4D;AAC5D,MAAM,CAAC,MAAM,IAAI,GAAG,KAEnB,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Garden UI — Field primitive (headless)
|
|
3
|
+
* -------------------------------------
|
|
4
|
+
* Whisper: "clarity first; comfort follows." 🌬️
|
|
5
|
+
*
|
|
6
|
+
* Purpose
|
|
7
|
+
* • A tiny accessibility wrapper that wires one control to its label & helper text.
|
|
8
|
+
* • Headless by design — visuals live in the skin (styles/field.css) via data‑attrs.
|
|
9
|
+
*
|
|
10
|
+
* Data API (for skins)
|
|
11
|
+
* • [data-ui="field"] — root wrapper
|
|
12
|
+
* • [data-state="valid|invalid"] — validation state
|
|
13
|
+
* • [data-disabled] on root when `disabled` is true
|
|
14
|
+
* • [data-tone="subtle|accent|positive|warning|danger"] — hint for skins
|
|
15
|
+
* • [data-part="label|control|error|description|hint|optional"]
|
|
16
|
+
* • [data-required] on label when `required` is true (skins style this calmly)
|
|
17
|
+
*
|
|
18
|
+
* A11y decisions
|
|
19
|
+
* • IDs: stable `controlId` from (prop.id || child.id || useId()).
|
|
20
|
+
* • `aria-describedby`: merges description + hint + error ids.
|
|
21
|
+
* • Errors: `role="alert"` only on the error node — no wrapper `aria-live` to avoid double reads.
|
|
22
|
+
* • Disabled: sets `aria-disabled` on the control and `data-disabled` on the wrapper.
|
|
23
|
+
* • Required: sets `aria-required` on control; we avoid noisy "(Optional)" by default.
|
|
24
|
+
*
|
|
25
|
+
* Children API
|
|
26
|
+
* • Element: <Field><input /></Field> — cloned with merged aria/id props.
|
|
27
|
+
* • Render fn: <Field>{(a) => <input {...a} />}</Field> — you render; we pass wiring.
|
|
28
|
+
*
|
|
29
|
+
* Dev notes / next
|
|
30
|
+
* • Docs: add README/Storybook examples (Basic, WithHint, WithError, RenderProp, Required).
|
|
31
|
+
* • Tests: describedby merge; required wiring; error flips data-state + aria-invalid; cloning preserves aria props.
|
|
32
|
+
* • DX: warn in dev when `children` is neither a function nor a valid element (implemented below).
|
|
33
|
+
* • Optional UX: default keeps "Optional" hidden; style required via label[data-required].
|
|
34
|
+
*/
|
|
35
|
+
import * as React from 'react';
|
|
36
|
+
export type Tone = 'accent' | 'positive' | 'warning' | 'danger' | 'subtle';
|
|
37
|
+
export type State = 'valid' | 'invalid';
|
|
38
|
+
type FieldRenderProps = {
|
|
39
|
+
id: string;
|
|
40
|
+
'aria-describedby'?: string;
|
|
41
|
+
'aria-invalid'?: true;
|
|
42
|
+
'aria-required'?: true;
|
|
43
|
+
'aria-disabled'?: true;
|
|
44
|
+
/** Convenience: many HTML controls accept `disabled`; renderers can spread it. */
|
|
45
|
+
disabled?: true;
|
|
46
|
+
};
|
|
47
|
+
type FieldChild = React.ReactNode | ((control: FieldRenderProps) => React.ReactNode);
|
|
48
|
+
export interface FieldProps {
|
|
49
|
+
/** Provide a stable id to wire label + messages. Defaults to an auto-generated id. */
|
|
50
|
+
id?: string;
|
|
51
|
+
/** Primary label rendered inside a <label>. */
|
|
52
|
+
label?: React.ReactNode;
|
|
53
|
+
/** Optional helper text shown beneath the control. */
|
|
54
|
+
description?: React.ReactNode;
|
|
55
|
+
/** Additional hint text (legacy alias for description). */
|
|
56
|
+
hint?: React.ReactNode;
|
|
57
|
+
/** Error message. When present the field is marked invalid. */
|
|
58
|
+
error?: React.ReactNode;
|
|
59
|
+
/** Mark control as required. Also sets aria-required. */
|
|
60
|
+
required?: boolean;
|
|
61
|
+
/** Custom copy for optional indicator (e.g. "Optional"). Set to null to hide. */
|
|
62
|
+
optionalText?: React.ReactNode;
|
|
63
|
+
/** Tone for styling hooks. */
|
|
64
|
+
tone?: Tone;
|
|
65
|
+
/** Rendered control element or render function receiving aria wiring. */
|
|
66
|
+
children: FieldChild;
|
|
67
|
+
/** Additional props spread onto the outer label. */
|
|
68
|
+
labelProps?: React.LabelHTMLAttributes<HTMLLabelElement>;
|
|
69
|
+
/** Optional class names applied to the outer wrapper. */
|
|
70
|
+
className?: string;
|
|
71
|
+
/** Disable the control and mark the field inert. Applies `data-disabled` on root. */
|
|
72
|
+
disabled?: boolean;
|
|
73
|
+
/** Extra ids to merge into `aria-describedby` (string or array). */
|
|
74
|
+
extraDescribedBy?: string | string[];
|
|
75
|
+
/** Hide the visual label while keeping it for screen readers (adds `sr-only`). */
|
|
76
|
+
labelVisuallyHidden?: boolean;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Field
|
|
80
|
+
*
|
|
81
|
+
* A lightweight accessibility wrapper that wires a label, helper messages, and
|
|
82
|
+
* error state to a single form control.
|
|
83
|
+
*
|
|
84
|
+
* ### ID strategy
|
|
85
|
+
* - Generates a stable id with `React.useId()`.
|
|
86
|
+
* - If the child element already provides an `id`, that wins.
|
|
87
|
+
* - You can also pass an explicit `id` prop to override both.
|
|
88
|
+
*
|
|
89
|
+
* The resolved control id is used to derive `-description`, `-hint`, and `-error`
|
|
90
|
+
* ids which are merged into `aria-describedby` as needed.
|
|
91
|
+
*
|
|
92
|
+
* ### Children API
|
|
93
|
+
* - **Element**: `<Field><input /></Field>` — The element is cloned and receives
|
|
94
|
+
* merged `id`, `aria-describedby`, `aria-invalid`, and `aria-required`.
|
|
95
|
+
* - **Render function**: `<Field>{(aria) => <input {...aria} />}</Field>` — You render
|
|
96
|
+
* the control yourself with the provided ARIA wiring (`id`, `aria-describedby`, etc.).
|
|
97
|
+
*
|
|
98
|
+
* ### Data attributes for skins
|
|
99
|
+
* - `data-ui="field"`, `data-state`, `data-tone`, and `data-part` markers on internal nodes.
|
|
100
|
+
*
|
|
101
|
+
* ### A11y rationale
|
|
102
|
+
* - Error messages use `role="alert"` for assertive announcements.
|
|
103
|
+
* - Wrapper does NOT set `aria-live` to avoid duplicate SR reads.
|
|
104
|
+
*/
|
|
105
|
+
export declare const Field: React.ForwardRefExoticComponent<FieldProps & React.RefAttributes<HTMLDivElement>>;
|
|
106
|
+
export {};
|
|
107
|
+
//# sourceMappingURL=field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../src/primitives/field.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,IAAI,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3E,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAExC,KAAK,gBAAgB,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,IAAI,CAAC;CACjB,CAAC;AAEF,KAAK,UAAU,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,OAAO,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;AAErF,MAAM,WAAW,UAAU;IACzB,sFAAsF;IACtF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,+CAA+C;IAC/C,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,2DAA2D;IAC3D,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,8BAA8B;IAC9B,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,yEAAyE;IACzE,QAAQ,EAAE,UAAU,CAAC;IACrB,oDAAoD;IACpD,UAAU,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IACzD,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACrC,kFAAkF;IAClF,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,KAAK,mFAqIhB,CAAC"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Garden UI — Field primitive (headless)
|
|
4
|
+
* -------------------------------------
|
|
5
|
+
* Whisper: "clarity first; comfort follows." 🌬️
|
|
6
|
+
*
|
|
7
|
+
* Purpose
|
|
8
|
+
* • A tiny accessibility wrapper that wires one control to its label & helper text.
|
|
9
|
+
* • Headless by design — visuals live in the skin (styles/field.css) via data‑attrs.
|
|
10
|
+
*
|
|
11
|
+
* Data API (for skins)
|
|
12
|
+
* • [data-ui="field"] — root wrapper
|
|
13
|
+
* • [data-state="valid|invalid"] — validation state
|
|
14
|
+
* • [data-disabled] on root when `disabled` is true
|
|
15
|
+
* • [data-tone="subtle|accent|positive|warning|danger"] — hint for skins
|
|
16
|
+
* • [data-part="label|control|error|description|hint|optional"]
|
|
17
|
+
* • [data-required] on label when `required` is true (skins style this calmly)
|
|
18
|
+
*
|
|
19
|
+
* A11y decisions
|
|
20
|
+
* • IDs: stable `controlId` from (prop.id || child.id || useId()).
|
|
21
|
+
* • `aria-describedby`: merges description + hint + error ids.
|
|
22
|
+
* • Errors: `role="alert"` only on the error node — no wrapper `aria-live` to avoid double reads.
|
|
23
|
+
* • Disabled: sets `aria-disabled` on the control and `data-disabled` on the wrapper.
|
|
24
|
+
* • Required: sets `aria-required` on control; we avoid noisy "(Optional)" by default.
|
|
25
|
+
*
|
|
26
|
+
* Children API
|
|
27
|
+
* • Element: <Field><input /></Field> — cloned with merged aria/id props.
|
|
28
|
+
* • Render fn: <Field>{(a) => <input {...a} />}</Field> — you render; we pass wiring.
|
|
29
|
+
*
|
|
30
|
+
* Dev notes / next
|
|
31
|
+
* • Docs: add README/Storybook examples (Basic, WithHint, WithError, RenderProp, Required).
|
|
32
|
+
* • Tests: describedby merge; required wiring; error flips data-state + aria-invalid; cloning preserves aria props.
|
|
33
|
+
* • DX: warn in dev when `children` is neither a function nor a valid element (implemented below).
|
|
34
|
+
* • Optional UX: default keeps "Optional" hidden; style required via label[data-required].
|
|
35
|
+
*/
|
|
36
|
+
import * as React from 'react';
|
|
37
|
+
const defaultOptionalText = null; // default: do not show optional text; mark required via CSS using [data-required]
|
|
38
|
+
// Join non-empty id parts into a single space-separated string for aria-describedby.
|
|
39
|
+
function joinIds(...parts) {
|
|
40
|
+
return parts.filter(Boolean).join(' ') || undefined;
|
|
41
|
+
}
|
|
42
|
+
function normalizeIds(ids) {
|
|
43
|
+
if (!ids)
|
|
44
|
+
return undefined;
|
|
45
|
+
return Array.isArray(ids) ? ids.filter(Boolean).join(' ') || undefined : ids || undefined;
|
|
46
|
+
}
|
|
47
|
+
// Narrow unknown to a string (safely) when reading potential child props.
|
|
48
|
+
function toString(value) {
|
|
49
|
+
return typeof value === 'string' ? value : undefined;
|
|
50
|
+
}
|
|
51
|
+
function hasAriaLabel(props) {
|
|
52
|
+
if (!props)
|
|
53
|
+
return false;
|
|
54
|
+
const a = props['aria-label'];
|
|
55
|
+
const b = props['aria-labelledby'];
|
|
56
|
+
return (typeof a === 'string' && a.trim().length > 0) || (typeof b === 'string' && b.trim().length > 0);
|
|
57
|
+
}
|
|
58
|
+
// Detect dev mode without importing Node types (works in browser ESM).
|
|
59
|
+
function isDevEnvironment() {
|
|
60
|
+
const globalProcess = globalThis.process;
|
|
61
|
+
const env = globalProcess && typeof globalProcess === 'object' ? globalProcess.env : undefined;
|
|
62
|
+
const mode = env && typeof env === 'object' && 'NODE_ENV' in env ? env.NODE_ENV : undefined;
|
|
63
|
+
return mode !== 'production';
|
|
64
|
+
}
|
|
65
|
+
// Tiny class join helper (no runtime deps).
|
|
66
|
+
/**
|
|
67
|
+
* Field
|
|
68
|
+
*
|
|
69
|
+
* A lightweight accessibility wrapper that wires a label, helper messages, and
|
|
70
|
+
* error state to a single form control.
|
|
71
|
+
*
|
|
72
|
+
* ### ID strategy
|
|
73
|
+
* - Generates a stable id with `React.useId()`.
|
|
74
|
+
* - If the child element already provides an `id`, that wins.
|
|
75
|
+
* - You can also pass an explicit `id` prop to override both.
|
|
76
|
+
*
|
|
77
|
+
* The resolved control id is used to derive `-description`, `-hint`, and `-error`
|
|
78
|
+
* ids which are merged into `aria-describedby` as needed.
|
|
79
|
+
*
|
|
80
|
+
* ### Children API
|
|
81
|
+
* - **Element**: `<Field><input /></Field>` — The element is cloned and receives
|
|
82
|
+
* merged `id`, `aria-describedby`, `aria-invalid`, and `aria-required`.
|
|
83
|
+
* - **Render function**: `<Field>{(aria) => <input {...aria} />}</Field>` — You render
|
|
84
|
+
* the control yourself with the provided ARIA wiring (`id`, `aria-describedby`, etc.).
|
|
85
|
+
*
|
|
86
|
+
* ### Data attributes for skins
|
|
87
|
+
* - `data-ui="field"`, `data-state`, `data-tone`, and `data-part` markers on internal nodes.
|
|
88
|
+
*
|
|
89
|
+
* ### A11y rationale
|
|
90
|
+
* - Error messages use `role="alert"` for assertive announcements.
|
|
91
|
+
* - Wrapper does NOT set `aria-live` to avoid duplicate SR reads.
|
|
92
|
+
*/
|
|
93
|
+
export const Field = React.forwardRef(function Field({ id: idProp, label, description, hint, error, required, optionalText = defaultOptionalText, tone, children, labelProps, className, disabled, extraDescribedBy, labelVisuallyHidden, }, ref) {
|
|
94
|
+
const generatedId = React.useId();
|
|
95
|
+
const childElement = React.isValidElement(children) ? children : null;
|
|
96
|
+
const childProps = childElement?.props ?? {};
|
|
97
|
+
const childId = toString(childProps.id);
|
|
98
|
+
const controlId = idProp ?? childId ?? generatedId;
|
|
99
|
+
const descriptionId = description ? `${controlId}-description` : undefined;
|
|
100
|
+
const hintId = hint ? `${controlId}-hint` : undefined;
|
|
101
|
+
const errorId = error ? `${controlId}-error` : undefined;
|
|
102
|
+
const computedTone = tone ?? (error ? 'danger' : 'subtle');
|
|
103
|
+
const controlRenderProps = {
|
|
104
|
+
id: controlId,
|
|
105
|
+
'aria-describedby': joinIds(descriptionId, hintId, errorId, normalizeIds(extraDescribedBy)),
|
|
106
|
+
'aria-invalid': error ? true : undefined,
|
|
107
|
+
'aria-required': required ? true : undefined,
|
|
108
|
+
'aria-disabled': disabled ? true : undefined,
|
|
109
|
+
disabled: disabled ? true : undefined,
|
|
110
|
+
};
|
|
111
|
+
let control;
|
|
112
|
+
if (isDevEnvironment()) {
|
|
113
|
+
const isFn = typeof children === 'function';
|
|
114
|
+
const isElement = !!childElement;
|
|
115
|
+
if (!isFn && !isElement) {
|
|
116
|
+
// Intentionally gentle — helps catch misuse without throwing.
|
|
117
|
+
// eslint-disable-next-line no-console
|
|
118
|
+
console.warn('[Field] `children` should be a React element or a render function. Received:', children);
|
|
119
|
+
}
|
|
120
|
+
const hasLabelNode = !!label;
|
|
121
|
+
const hasChildName = hasAriaLabel(childProps);
|
|
122
|
+
if (!hasLabelNode && !hasChildName) {
|
|
123
|
+
// eslint-disable-next-line no-console
|
|
124
|
+
console.warn('[Field] Accessible name missing: provide `label` or give the control `aria-label`/`aria-labelledby`.');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (typeof children === 'function') {
|
|
128
|
+
control = children(controlRenderProps);
|
|
129
|
+
}
|
|
130
|
+
else if (childElement) {
|
|
131
|
+
const mergedDescribedBy = joinIds(toString(childProps['aria-describedby']), descriptionId, hintId, errorId, normalizeIds(extraDescribedBy));
|
|
132
|
+
control = React.cloneElement(childElement, {
|
|
133
|
+
id: childProps.id ?? controlId,
|
|
134
|
+
'aria-describedby': mergedDescribedBy,
|
|
135
|
+
'aria-invalid': childProps['aria-invalid'] ?? (error ? true : undefined),
|
|
136
|
+
'aria-required': childProps['aria-required'] ?? (required ? true : undefined),
|
|
137
|
+
'aria-disabled': childProps['aria-disabled'] ?? (disabled ? true : undefined),
|
|
138
|
+
// @ts-ignore: not all elements accept `disabled`, that's OK — consumers control the tag.
|
|
139
|
+
disabled: childProps.disabled ?? (disabled ? true : undefined),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
control = children;
|
|
144
|
+
}
|
|
145
|
+
const state = error ? 'invalid' : 'valid';
|
|
146
|
+
const { className: labelClassName, ...restLabelProps } = labelProps ?? {};
|
|
147
|
+
const optionalIndicator = !required && optionalText != null ? (_jsx("span", { "data-part": "optional", "aria-hidden": "true", children: optionalText })) : null;
|
|
148
|
+
return (_jsxs("div", { ref: ref, "data-ui": "field", "data-state": state, "data-tone": computedTone, "data-disabled": disabled ? '' : undefined, className: className, children: [label ? (_jsxs("label", { htmlFor: controlId, "data-part": "label", "data-required": required ? '' : undefined, className: labelVisuallyHidden ? [labelClassName, 'sr-only'].filter(Boolean).join(' ') : labelClassName, ...restLabelProps, children: [_jsx("span", { children: label }), optionalIndicator] })) : null, _jsx("div", { "data-part": "control", children: control }), error ? (
|
|
149
|
+
// a11y: We use role="alert" on the error message for assertive announcement and
|
|
150
|
+
// do not set aria-live on the wrapper to avoid duplicate reads by screen readers.
|
|
151
|
+
_jsx("div", { id: errorId, "data-part": "error", role: "alert", children: error })) : null, description ? (_jsx("div", { id: descriptionId, "data-part": "description", children: description })) : null, hint ? (_jsx("div", { id: hintId, "data-part": "hint", children: hint })) : null] }));
|
|
152
|
+
});
|
|
153
|
+
Field.displayName = 'Field';
|
|
154
|
+
//# sourceMappingURL=field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.js","sourceRoot":"","sources":["../../src/primitives/field.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAiD/B,MAAM,mBAAmB,GAA2B,IAAI,CAAC,CAAC,kFAAkF;AAE5I,qFAAqF;AACrF,SAAS,OAAO,CAAC,GAAG,KAAgC;IAClD,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;AACtD,CAAC;AAED,SAAS,YAAY,CAAC,GAAuB;IAC3C,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC;AAC5F,CAAC;AAED,0EAA0E;AAC1E,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,YAAY,CAAC,KAA0C;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;IAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACnC,OAAO,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC1G,CAAC;AAED,uEAAuE;AACvE,SAAS,gBAAgB;IACvB,MAAM,aAAa,GAAI,UAA8D,CAAC,OAAO,CAAC;IAC9F,MAAM,GAAG,GAAG,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/F,MAAM,IAAI,GAAG,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,UAAU,IAAI,GAAG,CAAC,CAAC,CAAE,GAA+B,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACzH,OAAO,IAAI,KAAK,YAAY,CAAC;AAC/B,CAAC;AAED,4CAA4C;AAC5C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAA6B,SAAS,KAAK,CAC9E,EACE,EAAE,EAAE,MAAM,EACV,KAAK,EACL,WAAW,EACX,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,YAAY,GAAG,mBAAmB,EAClC,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,mBAAmB,GACpB,EACD,GAAG;IAEH,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IAElC,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,QAAwD,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvH,MAAM,UAAU,GAA4B,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC;IAEtE,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,MAAM,IAAI,OAAO,IAAI,WAAW,CAAC;IAEnD,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAEzD,MAAM,YAAY,GAAS,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAEjE,MAAM,kBAAkB,GAAqB;QAC3C,EAAE,EAAE,SAAS;QACb,kBAAkB,EAAE,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAC3F,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACxC,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC5C,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC5C,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;KACtC,CAAC;IAEF,IAAI,OAAwB,CAAC;IAE7B,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,OAAO,QAAQ,KAAK,UAAU,CAAC;QAC5C,MAAM,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC;QACjC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACxB,8DAA8D;YAC9D,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,8EAA8E,EAAE,QAAQ,CAAC,CAAC;QACzG,CAAC;QACD,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC;QAC7B,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,EAAE,CAAC;YACnC,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,sGAAsG,CAAC,CAAC;QACvH,CAAC;IACH,CAAC;IAED,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,OAAO,GAAI,QAAyD,CAAC,kBAAkB,CAAC,CAAC;IAC3F,CAAC;SAAM,IAAI,YAAY,EAAE,CAAC;QACxB,MAAM,iBAAiB,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAE5I,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE;YACzC,EAAE,EAAE,UAAU,CAAC,EAAE,IAAI,SAAS;YAC9B,kBAAkB,EAAE,iBAAiB;YACrC,cAAc,EAAE,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;YACxE,eAAe,EAAE,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;YAC7E,eAAe,EAAE,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;YAC7E,yFAAyF;YACzF,QAAQ,EAAG,UAAkB,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;SAC7C,CAAC,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,QAAQ,CAAC;IACrB,CAAC;IAED,MAAM,KAAK,GAAU,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;IAEjD,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,GAAG,UAAU,IAAK,EAAkD,CAAC;IAE3H,MAAM,iBAAiB,GACrB,CAAC,QAAQ,IAAI,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,CAClC,4BAAgB,UAAU,iBAAa,MAAM,YAC1C,YAAY,GACR,CACR,CAAC,CAAC,CAAC,IAAI,CAAC;IAEX,OAAO,CACL,eAAK,GAAG,EAAE,GAAG,aAAU,OAAO,gBAAa,KAAK,eAAa,YAAY,mBAAiB,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,aAOtI,KAAK,CAAC,CAAC,CAAC,CACP,iBACE,OAAO,EAAE,SAAS,eACR,OAAO,mBACF,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EACxC,SAAS,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,KACnG,cAAc,aAClB,yBAAO,KAAK,GAAQ,EACnB,iBAAiB,IACZ,CACT,CAAC,CAAC,CAAC,IAAI,EAER,2BAAe,SAAS,YAAE,OAAO,GAAO,EAEvC,KAAK,CAAC,CAAC,CAAC;YACP,gFAAgF;YAChF,kFAAkF;YAClF,cAAK,EAAE,EAAE,OAAO,eAAY,OAAO,EAAC,IAAI,EAAC,OAAO,YAC7C,KAAK,GACF,CACP,CAAC,CAAC,CAAC,IAAI,EAEP,WAAW,CAAC,CAAC,CAAC,CACb,cAAK,EAAE,EAAE,aAAa,eAAY,aAAa,YAC5C,WAAW,GACR,CACP,CAAC,CAAC,CAAC,IAAI,EAEP,IAAI,CAAC,CAAC,CAAC,CACN,cAAK,EAAE,EAAE,MAAM,eAAY,MAAM,YAC9B,IAAI,GACD,CACP,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC"}
|