@ashwa-io/ui 0.0.3 → 0.0.4
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/components/atomic/Checkbox/Checkbox.d.ts +11 -0
- package/dist/components/atomic/Checkbox/Checkbox.js +32 -0
- package/dist/components/atomic/Checkbox/index.d.ts +2 -0
- package/dist/components/atomic/ColorInput/ColorInput.d.ts +15 -0
- package/dist/components/atomic/ColorInput/ColorInput.js +44 -0
- package/dist/components/atomic/ColorInput/colorHex.js +8 -0
- package/dist/components/atomic/ColorInput/index.d.ts +2 -0
- package/dist/components/atomic/Select/Select.d.ts +18 -0
- package/dist/components/atomic/Select/Select.js +47 -0
- package/dist/components/atomic/Select/index.d.ts +2 -0
- package/dist/components/atomic/Switch/Switch.d.ts +11 -0
- package/dist/components/atomic/Switch/Switch.js +32 -0
- package/dist/components/atomic/Switch/index.d.ts +2 -0
- package/dist/components/atomic/TextArea/TextArea.d.ts +14 -0
- package/dist/components/atomic/TextArea/TextArea.js +35 -0
- package/dist/components/atomic/TextArea/index.d.ts +2 -0
- package/dist/components/atomic/TextInput/TextInput.d.ts +18 -0
- package/dist/components/atomic/TextInput/TextInput.js +42 -0
- package/dist/components/atomic/TextInput/index.d.ts +2 -0
- package/dist/components/layout/FormLayout/FormLayout.d.ts +9 -0
- package/dist/components/layout/FormLayout/FormLayout.js +15 -0
- package/dist/components/layout/FormLayout/index.d.ts +2 -0
- package/dist/components/molecule/FormField/FormField.d.ts +16 -0
- package/dist/components/molecule/FormField/FormField.js +47 -0
- package/dist/components/molecule/FormField/index.d.ts +2 -0
- package/dist/components/ui/checkbox.js +18 -0
- package/dist/components/ui/field.js +65 -0
- package/dist/components/ui/input.js +14 -0
- package/dist/components/ui/label.js +12 -0
- package/dist/components/ui/select.js +75 -0
- package/dist/components/ui/switch.js +18 -0
- package/dist/components/ui/textarea.js +12 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.js +9 -1
- package/dist/lib/types.d.ts +15 -1
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FieldBaseProps } from "../../../lib/types.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
export interface CheckboxProps extends FieldBaseProps {
|
|
4
|
+
value: boolean;
|
|
5
|
+
onChange: (value: boolean) => void;
|
|
6
|
+
onBlur?: () => void;
|
|
7
|
+
name?: string;
|
|
8
|
+
readOnly?: boolean;
|
|
9
|
+
ref?: React.Ref<HTMLElement>;
|
|
10
|
+
}
|
|
11
|
+
export declare const Checkbox: React.FC<CheckboxProps>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FormField } from "../../molecule/FormField/FormField.js";
|
|
2
|
+
import { Checkbox as Checkbox$1 } from "../../ui/checkbox.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
// src/components/atomic/Checkbox/Checkbox.tsx
|
|
5
|
+
const Checkbox = (props) => {
|
|
6
|
+
const { label, hideLabel, description, error, required, disabled, id, "data-testid": testId, value, onChange, onBlur, name, readOnly = false, ref } = props;
|
|
7
|
+
return /* @__PURE__ */ jsx(FormField, {
|
|
8
|
+
orientation: "horizontal",
|
|
9
|
+
label,
|
|
10
|
+
hideLabel,
|
|
11
|
+
description,
|
|
12
|
+
error,
|
|
13
|
+
required,
|
|
14
|
+
disabled,
|
|
15
|
+
id,
|
|
16
|
+
"data-testid": testId,
|
|
17
|
+
children: (control) => /* @__PURE__ */ jsx(Checkbox$1, {
|
|
18
|
+
ref,
|
|
19
|
+
id: control.id,
|
|
20
|
+
"aria-describedby": control["aria-describedby"],
|
|
21
|
+
"aria-invalid": control["aria-invalid"],
|
|
22
|
+
"aria-required": control["aria-required"],
|
|
23
|
+
disabled: control.disabled,
|
|
24
|
+
checked: value,
|
|
25
|
+
onCheckedChange: (checked) => onChange(checked),
|
|
26
|
+
onBlur,
|
|
27
|
+
name,
|
|
28
|
+
readOnly
|
|
29
|
+
})
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
export { Checkbox };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FieldBaseProps } from "../../../lib/types.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
export interface ColorInputProps extends FieldBaseProps {
|
|
4
|
+
/** 6-digit hex, e.g. '#1a73e8' (orgs.primaryColor), or the text being typed. */
|
|
5
|
+
value: string;
|
|
6
|
+
/**
|
|
7
|
+
* A valid 6-digit hex arrives normalized ('#1a73e8'); anything else arrives as typed, so the
|
|
8
|
+
* form's validation can flag it (e.g. `validate: v => /^#[0-9a-f]{6}$/.test(v) || '…'`).
|
|
9
|
+
*/
|
|
10
|
+
onChange: (value: string) => void;
|
|
11
|
+
onBlur?: () => void;
|
|
12
|
+
name?: string;
|
|
13
|
+
ref?: React.Ref<HTMLInputElement>;
|
|
14
|
+
}
|
|
15
|
+
export declare const ColorInput: React.FC<ColorInputProps>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { FormField } from "../../molecule/FormField/FormField.js";
|
|
2
|
+
import { Input } from "../../ui/input.js";
|
|
3
|
+
import { normalizeHex } from "./colorHex.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
// src/components/atomic/ColorInput/ColorInput.tsx
|
|
6
|
+
const ColorInput = (props) => {
|
|
7
|
+
const { label, hideLabel, description, error, required, disabled, id, "data-testid": testId, value, onChange, onBlur, name, ref } = props;
|
|
8
|
+
const handleText = (next) => onChange(normalizeHex(next) ?? next);
|
|
9
|
+
return /* @__PURE__ */ jsx(FormField, {
|
|
10
|
+
label,
|
|
11
|
+
hideLabel,
|
|
12
|
+
description,
|
|
13
|
+
error,
|
|
14
|
+
required,
|
|
15
|
+
disabled,
|
|
16
|
+
id,
|
|
17
|
+
"data-testid": testId,
|
|
18
|
+
children: (control) => /* @__PURE__ */ jsxs("div", {
|
|
19
|
+
className: "flex items-center gap-2",
|
|
20
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
21
|
+
type: "color",
|
|
22
|
+
"aria-label": `${label} picker`,
|
|
23
|
+
value: normalizeHex(value) ?? "#000000",
|
|
24
|
+
disabled: control.disabled,
|
|
25
|
+
onChange: (event) => handleText(event.target.value),
|
|
26
|
+
className: "border-input h-8 w-10 shrink-0 cursor-pointer rounded-lg border bg-transparent p-0.5 disabled:cursor-not-allowed disabled:opacity-50"
|
|
27
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
28
|
+
ref,
|
|
29
|
+
id: control.id,
|
|
30
|
+
"aria-describedby": control["aria-describedby"],
|
|
31
|
+
"aria-invalid": control["aria-invalid"],
|
|
32
|
+
"aria-required": control["aria-required"],
|
|
33
|
+
disabled: control.disabled,
|
|
34
|
+
name,
|
|
35
|
+
value,
|
|
36
|
+
spellCheck: false,
|
|
37
|
+
autoComplete: "off",
|
|
38
|
+
onChange: (event) => handleText(event.target.value),
|
|
39
|
+
onBlur
|
|
40
|
+
})]
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
export { ColorInput };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// src/components/atomic/ColorInput/colorHex.ts
|
|
2
|
+
const HEX6 = /^#?([0-9a-f]{6})$/i;
|
|
3
|
+
/** '#1A73E8' | '1a73e8' → '#1a73e8'; anything that is not 6 hex digits → null. */
|
|
4
|
+
const normalizeHex = (input) => {
|
|
5
|
+
const match = HEX6.exec(input.trim());
|
|
6
|
+
return match ? `#${match[1].toLowerCase()}` : null;
|
|
7
|
+
};
|
|
8
|
+
export { normalizeHex };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FieldBaseProps } from "../../../lib/types.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
export interface SelectOption {
|
|
4
|
+
value: string;
|
|
5
|
+
label: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface SelectProps extends FieldBaseProps {
|
|
9
|
+
options: SelectOption[];
|
|
10
|
+
/** null = nothing picked; the placeholder shows. */
|
|
11
|
+
value: string | null;
|
|
12
|
+
onChange: (value: string) => void;
|
|
13
|
+
onBlur?: () => void;
|
|
14
|
+
name?: string;
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
17
|
+
}
|
|
18
|
+
export declare const Select: React.FC<SelectProps>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { FormField } from "../../molecule/FormField/FormField.js";
|
|
2
|
+
import { Select as Select$1, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/select.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
// src/components/atomic/Select/Select.tsx
|
|
5
|
+
const LEFT_FIELD_REASONS = /* @__PURE__ */ new Set(["outside-press", "focus-out"]);
|
|
6
|
+
const Select = (props) => {
|
|
7
|
+
const { label, hideLabel, description, error, required, disabled, id, "data-testid": testId, options, value, onChange, onBlur, name, placeholder, ref } = props;
|
|
8
|
+
return /* @__PURE__ */ jsx(FormField, {
|
|
9
|
+
label,
|
|
10
|
+
hideLabel,
|
|
11
|
+
description,
|
|
12
|
+
error,
|
|
13
|
+
required,
|
|
14
|
+
disabled,
|
|
15
|
+
id,
|
|
16
|
+
"data-testid": testId,
|
|
17
|
+
children: (control) => /* @__PURE__ */ jsxs(Select$1, {
|
|
18
|
+
items: options,
|
|
19
|
+
value,
|
|
20
|
+
onValueChange: (next) => {
|
|
21
|
+
if (next !== null) onChange(next);
|
|
22
|
+
},
|
|
23
|
+
onOpenChange: (open, details) => {
|
|
24
|
+
if (!open && LEFT_FIELD_REASONS.has(details.reason)) onBlur?.();
|
|
25
|
+
},
|
|
26
|
+
name,
|
|
27
|
+
disabled: control.disabled,
|
|
28
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
29
|
+
ref,
|
|
30
|
+
id: control.id,
|
|
31
|
+
"aria-describedby": control["aria-describedby"],
|
|
32
|
+
"aria-invalid": control["aria-invalid"],
|
|
33
|
+
"aria-required": control["aria-required"],
|
|
34
|
+
onBlur: (event) => {
|
|
35
|
+
if (!event.relatedTarget?.closest("[data-slot=\"select-content\"]")) onBlur?.();
|
|
36
|
+
},
|
|
37
|
+
className: "w-full",
|
|
38
|
+
children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
|
|
39
|
+
}), /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
|
|
40
|
+
value: option.value,
|
|
41
|
+
disabled: option.disabled,
|
|
42
|
+
children: option.label
|
|
43
|
+
}, option.value)) })]
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
export { Select };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FieldBaseProps } from "../../../lib/types.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
export interface SwitchProps extends FieldBaseProps {
|
|
4
|
+
value: boolean;
|
|
5
|
+
onChange: (value: boolean) => void;
|
|
6
|
+
onBlur?: () => void;
|
|
7
|
+
name?: string;
|
|
8
|
+
readOnly?: boolean;
|
|
9
|
+
ref?: React.Ref<HTMLElement>;
|
|
10
|
+
}
|
|
11
|
+
export declare const Switch: React.FC<SwitchProps>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FormField } from "../../molecule/FormField/FormField.js";
|
|
2
|
+
import { Switch as Switch$1 } from "../../ui/switch.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
// src/components/atomic/Switch/Switch.tsx
|
|
5
|
+
const Switch = (props) => {
|
|
6
|
+
const { label, hideLabel, description, error, required, disabled, id, "data-testid": testId, value, onChange, onBlur, name, readOnly = false, ref } = props;
|
|
7
|
+
return /* @__PURE__ */ jsx(FormField, {
|
|
8
|
+
orientation: "horizontal",
|
|
9
|
+
label,
|
|
10
|
+
hideLabel,
|
|
11
|
+
description,
|
|
12
|
+
error,
|
|
13
|
+
required,
|
|
14
|
+
disabled,
|
|
15
|
+
id,
|
|
16
|
+
"data-testid": testId,
|
|
17
|
+
children: (control) => /* @__PURE__ */ jsx(Switch$1, {
|
|
18
|
+
ref,
|
|
19
|
+
id: control.id,
|
|
20
|
+
"aria-describedby": control["aria-describedby"],
|
|
21
|
+
"aria-invalid": control["aria-invalid"],
|
|
22
|
+
"aria-required": control["aria-required"],
|
|
23
|
+
disabled: control.disabled,
|
|
24
|
+
checked: value,
|
|
25
|
+
onCheckedChange: (checked) => onChange(checked),
|
|
26
|
+
onBlur,
|
|
27
|
+
name,
|
|
28
|
+
readOnly
|
|
29
|
+
})
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
export { Switch };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FieldBaseProps } from "../../../lib/types.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
export interface TextAreaProps extends FieldBaseProps {
|
|
4
|
+
value: string;
|
|
5
|
+
onChange: (value: string) => void;
|
|
6
|
+
onBlur?: () => void;
|
|
7
|
+
name?: string;
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
rows?: number;
|
|
10
|
+
maxLength?: number;
|
|
11
|
+
readOnly?: boolean;
|
|
12
|
+
ref?: React.Ref<HTMLTextAreaElement>;
|
|
13
|
+
}
|
|
14
|
+
export declare const TextArea: React.FC<TextAreaProps>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { FormField } from "../../molecule/FormField/FormField.js";
|
|
2
|
+
import { Textarea } from "../../ui/textarea.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
// src/components/atomic/TextArea/TextArea.tsx
|
|
5
|
+
const TextArea = (props) => {
|
|
6
|
+
const { label, hideLabel, description, error, required, disabled, id, "data-testid": testId, value, onChange, onBlur, name, placeholder, rows = 3, maxLength, readOnly = false, ref } = props;
|
|
7
|
+
return /* @__PURE__ */ jsx(FormField, {
|
|
8
|
+
label,
|
|
9
|
+
hideLabel,
|
|
10
|
+
description,
|
|
11
|
+
error,
|
|
12
|
+
required,
|
|
13
|
+
disabled,
|
|
14
|
+
id,
|
|
15
|
+
"data-testid": testId,
|
|
16
|
+
children: (control) => /* @__PURE__ */ jsx(Textarea, {
|
|
17
|
+
ref,
|
|
18
|
+
id: control.id,
|
|
19
|
+
"aria-describedby": control["aria-describedby"],
|
|
20
|
+
"aria-invalid": control["aria-invalid"],
|
|
21
|
+
"aria-required": control["aria-required"],
|
|
22
|
+
disabled: control.disabled,
|
|
23
|
+
name,
|
|
24
|
+
value,
|
|
25
|
+
placeholder,
|
|
26
|
+
rows,
|
|
27
|
+
maxLength,
|
|
28
|
+
readOnly,
|
|
29
|
+
onChange: (event) => onChange(event.target.value),
|
|
30
|
+
onBlur,
|
|
31
|
+
className: "field-sizing-fixed"
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
export { TextArea };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FieldBaseProps, IconComponent } from "../../../lib/types.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
export type TextInputType = 'text' | 'email' | 'password' | 'search' | 'tel' | 'url';
|
|
4
|
+
export interface TextInputProps extends FieldBaseProps {
|
|
5
|
+
value: string;
|
|
6
|
+
onChange: (value: string) => void;
|
|
7
|
+
onBlur?: () => void;
|
|
8
|
+
name?: string;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
type?: TextInputType;
|
|
11
|
+
/** Leading icon, decorative (aria-hidden). */
|
|
12
|
+
icon?: IconComponent;
|
|
13
|
+
readOnly?: boolean;
|
|
14
|
+
/** e.g. 'username', 'current-password' on login forms. */
|
|
15
|
+
autoComplete?: string;
|
|
16
|
+
ref?: React.Ref<HTMLInputElement>;
|
|
17
|
+
}
|
|
18
|
+
export declare const TextInput: React.FC<TextInputProps>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { FormField } from "../../molecule/FormField/FormField.js";
|
|
2
|
+
import { Input } from "../../ui/input.js";
|
|
3
|
+
import { cn } from "../../../lib/utils.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
// src/components/atomic/TextInput/TextInput.tsx
|
|
6
|
+
const TextInput = (props) => {
|
|
7
|
+
const { label, hideLabel, description, error, required, disabled, id, "data-testid": testId, value, onChange, onBlur, name, placeholder, type = "text", icon: Icon, readOnly = false, autoComplete, ref } = props;
|
|
8
|
+
return /* @__PURE__ */ jsx(FormField, {
|
|
9
|
+
label,
|
|
10
|
+
hideLabel,
|
|
11
|
+
description,
|
|
12
|
+
error,
|
|
13
|
+
required,
|
|
14
|
+
disabled,
|
|
15
|
+
id,
|
|
16
|
+
"data-testid": testId,
|
|
17
|
+
children: (control) => /* @__PURE__ */ jsxs("div", {
|
|
18
|
+
className: "relative",
|
|
19
|
+
children: [Icon && /* @__PURE__ */ jsx(Icon, {
|
|
20
|
+
"aria-hidden": true,
|
|
21
|
+
className: "text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2"
|
|
22
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
23
|
+
ref,
|
|
24
|
+
id: control.id,
|
|
25
|
+
"aria-describedby": control["aria-describedby"],
|
|
26
|
+
"aria-invalid": control["aria-invalid"],
|
|
27
|
+
"aria-required": control["aria-required"],
|
|
28
|
+
disabled: control.disabled,
|
|
29
|
+
type,
|
|
30
|
+
name,
|
|
31
|
+
value,
|
|
32
|
+
placeholder,
|
|
33
|
+
readOnly,
|
|
34
|
+
autoComplete,
|
|
35
|
+
onChange: (event) => onChange(event.target.value),
|
|
36
|
+
onBlur,
|
|
37
|
+
className: cn(Icon && "pl-8")
|
|
38
|
+
})]
|
|
39
|
+
})
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
export { TextInput };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type FormLayoutDirection = 'vertical' | 'horizontal';
|
|
3
|
+
export interface FormLayoutProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
/** horizontal: fields side by side in equal columns from sm up, stacked on phones. */
|
|
6
|
+
direction?: FormLayoutDirection;
|
|
7
|
+
'data-testid'?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const FormLayout: React.FC<FormLayoutProps>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
// src/components/layout/FormLayout/FormLayout.tsx
|
|
3
|
+
const DIRECTION = {
|
|
4
|
+
vertical: "flex flex-col gap-5",
|
|
5
|
+
horizontal: "grid gap-5 sm:auto-cols-fr sm:grid-flow-col"
|
|
6
|
+
};
|
|
7
|
+
const FormLayout = (props) => {
|
|
8
|
+
const { children, direction = "vertical", "data-testid": testId } = props;
|
|
9
|
+
return /* @__PURE__ */ jsx("div", {
|
|
10
|
+
"data-testid": testId,
|
|
11
|
+
className: DIRECTION[direction],
|
|
12
|
+
children
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
export { FormLayout };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FieldBaseProps } from "../../../lib/types.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
/** Wiring FormField hands to its control; pass each prop by name. */
|
|
4
|
+
export interface FormFieldControlProps {
|
|
5
|
+
id: string;
|
|
6
|
+
'aria-describedby'?: string;
|
|
7
|
+
'aria-invalid'?: true;
|
|
8
|
+
'aria-required'?: true;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface FormFieldProps extends FieldBaseProps {
|
|
12
|
+
children: (control: FormFieldControlProps) => React.ReactNode;
|
|
13
|
+
/** horizontal puts the label beside the control (checkbox, switch). */
|
|
14
|
+
orientation?: 'vertical' | 'horizontal';
|
|
15
|
+
}
|
|
16
|
+
export declare const FormField: React.FC<FormFieldProps>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Field, FieldContent, FieldDescription, FieldError, FieldLabel } from "../../ui/field.js";
|
|
2
|
+
import { cn } from "../../../lib/utils.js";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useId } from "react";
|
|
5
|
+
// src/components/molecule/FormField/FormField.tsx
|
|
6
|
+
const FormField = (props) => {
|
|
7
|
+
const { children, label, hideLabel = false, description, error, required = false, disabled = false, orientation = "vertical", id: idProp, "data-testid": testId } = props;
|
|
8
|
+
const generatedId = useId();
|
|
9
|
+
const id = idProp ?? generatedId;
|
|
10
|
+
const descriptionId = description ? `${id}-description` : void 0;
|
|
11
|
+
const errorId = error ? `${id}-error` : void 0;
|
|
12
|
+
const control = children({
|
|
13
|
+
id,
|
|
14
|
+
"aria-describedby": [descriptionId, errorId].filter(Boolean).join(" ") || void 0,
|
|
15
|
+
"aria-invalid": error ? true : void 0,
|
|
16
|
+
"aria-required": required ? true : void 0,
|
|
17
|
+
disabled
|
|
18
|
+
});
|
|
19
|
+
const labelNode = /* @__PURE__ */ jsxs(FieldLabel, {
|
|
20
|
+
htmlFor: id,
|
|
21
|
+
className: cn(hideLabel && "sr-only"),
|
|
22
|
+
children: [label, required && /* @__PURE__ */ jsx("span", {
|
|
23
|
+
"aria-hidden": true,
|
|
24
|
+
className: "text-destructive",
|
|
25
|
+
children: "*"
|
|
26
|
+
})]
|
|
27
|
+
});
|
|
28
|
+
const helpNodes = /* @__PURE__ */ jsxs(Fragment, { children: [description && /* @__PURE__ */ jsx(FieldDescription, {
|
|
29
|
+
id: descriptionId,
|
|
30
|
+
children: description
|
|
31
|
+
}), error && /* @__PURE__ */ jsx(FieldError, {
|
|
32
|
+
id: errorId,
|
|
33
|
+
children: error
|
|
34
|
+
})] });
|
|
35
|
+
return /* @__PURE__ */ jsx(Field, {
|
|
36
|
+
orientation,
|
|
37
|
+
"data-invalid": error ? true : void 0,
|
|
38
|
+
"data-disabled": disabled || void 0,
|
|
39
|
+
"data-testid": testId,
|
|
40
|
+
children: orientation === "horizontal" ? /* @__PURE__ */ jsxs(Fragment, { children: [control, /* @__PURE__ */ jsxs(FieldContent, { children: [labelNode, helpNodes] })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
41
|
+
labelNode,
|
|
42
|
+
control,
|
|
43
|
+
helpNodes
|
|
44
|
+
] })
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
export { FormField };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { cn } from "cn";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { CheckIcon } from "lucide-react";
|
|
4
|
+
import { Checkbox } from "@base-ui/react/checkbox";
|
|
5
|
+
// src/components/ui/checkbox.tsx
|
|
6
|
+
const Checkbox$1 = ({ className, ...props }) => {
|
|
7
|
+
return /* @__PURE__ */ jsx(Checkbox.Root, {
|
|
8
|
+
"data-slot": "checkbox",
|
|
9
|
+
className: cn("peer border-input group-has-[:focus-visible]/field-label:not-data-checked:border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border transition-colors outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3", className),
|
|
10
|
+
...props,
|
|
11
|
+
children: /* @__PURE__ */ jsx(Checkbox.Indicator, {
|
|
12
|
+
"data-slot": "checkbox-indicator",
|
|
13
|
+
className: "grid place-content-center text-current transition-none [&>svg]:size-3.5",
|
|
14
|
+
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
15
|
+
})
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
export { Checkbox$1 as Checkbox };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Label } from "./label.js";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
import { cn } from "cn";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
// src/components/ui/field.tsx
|
|
7
|
+
const fieldVariants = cva("group/field flex w-full gap-2 data-[invalid=true]:text-destructive", {
|
|
8
|
+
variants: { orientation: {
|
|
9
|
+
vertical: "flex-col *:w-full [&>.sr-only]:w-auto",
|
|
10
|
+
horizontal: "flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
|
11
|
+
responsive: "flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px"
|
|
12
|
+
} },
|
|
13
|
+
defaultVariants: { orientation: "vertical" }
|
|
14
|
+
});
|
|
15
|
+
const Field = ({ className, orientation = "vertical", ...props }) => {
|
|
16
|
+
return /* @__PURE__ */ jsx("div", {
|
|
17
|
+
role: "group",
|
|
18
|
+
"data-slot": "field",
|
|
19
|
+
"data-orientation": orientation,
|
|
20
|
+
className: cn(fieldVariants({ orientation }), className),
|
|
21
|
+
...props
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const FieldContent = ({ className, ...props }) => {
|
|
25
|
+
return /* @__PURE__ */ jsx("div", {
|
|
26
|
+
"data-slot": "field-content",
|
|
27
|
+
className: cn("group/field-content flex flex-1 flex-col gap-0.5 leading-snug", className),
|
|
28
|
+
...props
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
const FieldLabel = ({ className, ...props }) => {
|
|
32
|
+
return /* @__PURE__ */ jsx(Label, {
|
|
33
|
+
"data-slot": "field-label",
|
|
34
|
+
className: cn("group/field-label peer/field-label has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:not-has-[:disabled,[data-disabled]]:hover:bg-muted/50 has-[>[data-slot=field]]:has-[:focus-visible]:border-ring has-[>[data-slot=field]]:has-[:focus-visible]:ring-ring/50 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10 flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border has-[>[data-slot=field]]:has-[:focus-visible]:ring-3 *:data-[slot=field]:p-2.5", "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col", className),
|
|
35
|
+
...props
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const FieldDescription = ({ className, ...props }) => {
|
|
39
|
+
return /* @__PURE__ */ jsx("p", {
|
|
40
|
+
"data-slot": "field-description",
|
|
41
|
+
className: cn("text-muted-foreground text-left text-sm leading-normal font-normal group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5", "last:mt-0 nth-last-2:-mt-1", "[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", className),
|
|
42
|
+
...props
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
const FieldError = ({ className, children, errors, ...props }) => {
|
|
46
|
+
const content = useMemo(() => {
|
|
47
|
+
if (children) return children;
|
|
48
|
+
if (!errors?.length) return null;
|
|
49
|
+
const uniqueErrors = [...new Map(errors.map((error) => [error?.message, error])).values()];
|
|
50
|
+
if (uniqueErrors?.length == 1) return uniqueErrors[0]?.message;
|
|
51
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
52
|
+
className: "ml-4 flex list-disc flex-col gap-1",
|
|
53
|
+
children: uniqueErrors.map((error, index) => error?.message && /* @__PURE__ */ jsx("li", { children: error.message }, index))
|
|
54
|
+
});
|
|
55
|
+
}, [children, errors]);
|
|
56
|
+
if (!content) return null;
|
|
57
|
+
return /* @__PURE__ */ jsx("div", {
|
|
58
|
+
role: "alert",
|
|
59
|
+
"data-slot": "field-error",
|
|
60
|
+
className: cn("text-destructive text-sm font-normal", className),
|
|
61
|
+
...props,
|
|
62
|
+
children: content
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
export { Field, FieldContent, FieldDescription, FieldError, FieldLabel };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { cn } from "cn";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import "react";
|
|
4
|
+
import { Input } from "@base-ui/react/input";
|
|
5
|
+
// src/components/ui/input.tsx
|
|
6
|
+
const Input$1 = ({ className, type, ...props }) => {
|
|
7
|
+
return /* @__PURE__ */ jsx(Input, {
|
|
8
|
+
type,
|
|
9
|
+
"data-slot": "input",
|
|
10
|
+
className: cn("border-input file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 disabled:bg-input/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 h-8 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm", className),
|
|
11
|
+
...props
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
export { Input$1 as Input };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { cn } from "cn";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import "react";
|
|
4
|
+
// src/components/ui/label.tsx
|
|
5
|
+
const Label = ({ className, ...props }) => {
|
|
6
|
+
return /* @__PURE__ */ jsx("label", {
|
|
7
|
+
"data-slot": "label",
|
|
8
|
+
className: cn("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className),
|
|
9
|
+
...props
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
export { Label };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { cn } from "cn";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
4
|
+
import "react";
|
|
5
|
+
import { Select } from "@base-ui/react/select";
|
|
6
|
+
// src/components/ui/select.tsx
|
|
7
|
+
const Select$1 = Select.Root;
|
|
8
|
+
const SelectValue = ({ className, ...props }) => {
|
|
9
|
+
return /* @__PURE__ */ jsx(Select.Value, {
|
|
10
|
+
"data-slot": "select-value",
|
|
11
|
+
className: cn("flex flex-1 text-left", className),
|
|
12
|
+
...props
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
const SelectTrigger = ({ className, size = "default", children, ...props }) => {
|
|
16
|
+
return /* @__PURE__ */ jsxs(Select.Trigger, {
|
|
17
|
+
"data-slot": "select-trigger",
|
|
18
|
+
"data-size": size,
|
|
19
|
+
className: cn("border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 flex w-fit items-center justify-between gap-1.5 rounded-lg border bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
|
|
20
|
+
...props,
|
|
21
|
+
children: [children, /* @__PURE__ */ jsx(Select.Icon, { render: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "text-muted-foreground pointer-events-none size-4" }) })]
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const SelectContent = ({ className, children, side = "bottom", sideOffset = 4, align = "center", alignOffset = 0, alignItemWithTrigger = true, ...props }) => {
|
|
25
|
+
return /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsx(Select.Positioner, {
|
|
26
|
+
side,
|
|
27
|
+
sideOffset,
|
|
28
|
+
align,
|
|
29
|
+
alignOffset,
|
|
30
|
+
alignItemWithTrigger,
|
|
31
|
+
className: "isolate z-50",
|
|
32
|
+
children: /* @__PURE__ */ jsxs(Select.Popup, {
|
|
33
|
+
"data-slot": "select-content",
|
|
34
|
+
"data-align-trigger": alignItemWithTrigger,
|
|
35
|
+
className: cn("bg-popover text-popover-foreground ring-foreground/10 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg shadow-md ring-1 duration-100 data-[align-trigger=true]:animate-none", className),
|
|
36
|
+
...props,
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
39
|
+
/* @__PURE__ */ jsx(Select.List, { children }),
|
|
40
|
+
/* @__PURE__ */ jsx(SelectScrollDownButton, {})
|
|
41
|
+
]
|
|
42
|
+
})
|
|
43
|
+
}) });
|
|
44
|
+
};
|
|
45
|
+
const SelectItem = ({ className, children, ...props }) => {
|
|
46
|
+
return /* @__PURE__ */ jsxs(Select.Item, {
|
|
47
|
+
"data-slot": "select-item",
|
|
48
|
+
className: cn("focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className),
|
|
49
|
+
...props,
|
|
50
|
+
children: [/* @__PURE__ */ jsx(Select.ItemText, {
|
|
51
|
+
className: "flex flex-1 shrink-0 gap-2 whitespace-nowrap",
|
|
52
|
+
children
|
|
53
|
+
}), /* @__PURE__ */ jsx(Select.ItemIndicator, {
|
|
54
|
+
render: /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }),
|
|
55
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { className: "pointer-events-none" })
|
|
56
|
+
})]
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
const SelectScrollUpButton = ({ className, ...props }) => {
|
|
60
|
+
return /* @__PURE__ */ jsx(Select.ScrollUpArrow, {
|
|
61
|
+
"data-slot": "select-scroll-up-button",
|
|
62
|
+
className: cn("bg-popover top-0 z-10 flex w-full cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4", className),
|
|
63
|
+
...props,
|
|
64
|
+
children: /* @__PURE__ */ jsx(ChevronUpIcon, {})
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
const SelectScrollDownButton = ({ className, ...props }) => {
|
|
68
|
+
return /* @__PURE__ */ jsx(Select.ScrollDownArrow, {
|
|
69
|
+
"data-slot": "select-scroll-down-button",
|
|
70
|
+
className: cn("bg-popover bottom-0 z-10 flex w-full cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4", className),
|
|
71
|
+
...props,
|
|
72
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
export { Select$1 as Select, SelectContent, SelectItem, SelectScrollDownButton, SelectScrollUpButton, SelectTrigger, SelectValue };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "cn";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { Switch } from "@base-ui/react/switch";
|
|
5
|
+
// src/components/ui/switch.tsx
|
|
6
|
+
const Switch$1 = ({ className, size = "default", ...props }) => {
|
|
7
|
+
return /* @__PURE__ */ jsx(Switch.Root, {
|
|
8
|
+
"data-slot": "switch",
|
|
9
|
+
"data-size": size,
|
|
10
|
+
className: cn("peer group/switch focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none group-has-[:focus-visible]/field-label:border-transparent group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:ring-3 aria-invalid:ring-3 data-disabled:cursor-not-allowed data-disabled:opacity-50 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px]", className),
|
|
11
|
+
...props,
|
|
12
|
+
children: /* @__PURE__ */ jsx(Switch.Thumb, {
|
|
13
|
+
"data-slot": "switch-thumb",
|
|
14
|
+
className: "bg-background dark:data-checked:bg-primary-foreground dark:data-unchecked:bg-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0"
|
|
15
|
+
})
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
export { Switch$1 as Switch };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { cn } from "cn";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import "react";
|
|
4
|
+
// src/components/ui/textarea.tsx
|
|
5
|
+
const Textarea = ({ className, ...props }) => {
|
|
6
|
+
return /* @__PURE__ */ jsx("textarea", {
|
|
7
|
+
"data-slot": "textarea",
|
|
8
|
+
className: cn("border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 disabled:bg-input/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 flex field-sizing-content min-h-16 w-full rounded-lg border bg-transparent px-2.5 py-2 text-base transition-colors outline-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm", className),
|
|
9
|
+
...props
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
export { Textarea };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,19 +3,35 @@ import { Badge, BadgeProps } from "./components/atomic/Badge/Badge.js";
|
|
|
3
3
|
import "./components/atomic/Button/index.js";
|
|
4
4
|
import { ButtonVariant } from "./components/atomic/Button/buttonVariant.js";
|
|
5
5
|
import { Button, ButtonProps } from "./components/atomic/Button/Button.js";
|
|
6
|
+
import "./components/atomic/Checkbox/index.js";
|
|
7
|
+
import { Checkbox, CheckboxProps } from "./components/atomic/Checkbox/Checkbox.js";
|
|
8
|
+
import "./components/atomic/ColorInput/index.js";
|
|
9
|
+
import { ColorInput, ColorInputProps } from "./components/atomic/ColorInput/ColorInput.js";
|
|
6
10
|
import "./components/atomic/Divider/index.js";
|
|
7
11
|
import { Divider, DividerProps } from "./components/atomic/Divider/Divider.js";
|
|
8
12
|
import "./components/atomic/Heading/index.js";
|
|
9
13
|
import { Heading, HeadingLevel, HeadingProps } from "./components/atomic/Heading/Heading.js";
|
|
14
|
+
import "./components/atomic/Switch/index.js";
|
|
15
|
+
import { Switch, SwitchProps } from "./components/atomic/Switch/Switch.js";
|
|
10
16
|
import "./components/atomic/Text/index.js";
|
|
11
17
|
import { Text, TextProps, TextSize, TextTone, TextWeight } from "./components/atomic/Text/Text.js";
|
|
18
|
+
import "./components/atomic/TextArea/index.js";
|
|
19
|
+
import { TextArea, TextAreaProps } from "./components/atomic/TextArea/TextArea.js";
|
|
20
|
+
import "./components/atomic/TextInput/index.js";
|
|
21
|
+
import { TextInput, TextInputProps, TextInputType } from "./components/atomic/TextInput/TextInput.js";
|
|
12
22
|
import "./components/atomic/IconButton/index.js";
|
|
13
23
|
import { IconButton, IconButtonProps, IconButtonVariant } from "./components/atomic/IconButton/IconButton.js";
|
|
24
|
+
import "./components/atomic/Select/index.js";
|
|
25
|
+
import { Select, SelectOption, SelectProps } from "./components/atomic/Select/Select.js";
|
|
14
26
|
import "./components/atomic/Skeleton/index.js";
|
|
15
27
|
import { Skeleton, SkeletonProps, SkeletonShape } from "./components/atomic/Skeleton/Skeleton.js";
|
|
16
28
|
import "./components/atomic/Spinner/index.js";
|
|
17
29
|
import { Spinner, SpinnerProps } from "./components/atomic/Spinner/Spinner.js";
|
|
30
|
+
import "./components/layout/FormLayout/index.js";
|
|
31
|
+
import { FormLayout, FormLayoutDirection, FormLayoutProps } from "./components/layout/FormLayout/FormLayout.js";
|
|
32
|
+
import "./components/molecule/FormField/index.js";
|
|
33
|
+
import { FormField, FormFieldControlProps, FormFieldProps } from "./components/molecule/FormField/FormField.js";
|
|
18
34
|
import "./components/layout/Stack/index.js";
|
|
19
35
|
import { HStack, HStackProps, Stack, StackAlign, StackGap, StackJustify, StackProps, VStack, VStackProps } from "./components/layout/Stack/Stack.js";
|
|
20
|
-
import { IconComponent, Size, Tone } from "./lib/types.js";
|
|
21
|
-
export { Badge, type BadgeProps, Button, type ButtonProps, type ButtonVariant, Divider, type DividerProps, HStack, type HStackProps, Heading, type HeadingLevel, type HeadingProps, IconButton, type IconButtonProps, type IconButtonVariant, type IconComponent, type Size, Skeleton, type SkeletonProps, type SkeletonShape, Spinner, type SpinnerProps, Stack, type StackAlign, type StackGap, type StackJustify, type StackProps, Text, type TextProps, type TextSize, type TextTone, type TextWeight, type Tone, VStack, type VStackProps };
|
|
36
|
+
import { FieldBaseProps, IconComponent, Size, Tone } from "./lib/types.js";
|
|
37
|
+
export { Badge, type BadgeProps, Button, type ButtonProps, type ButtonVariant, Checkbox, type CheckboxProps, ColorInput, type ColorInputProps, Divider, type DividerProps, type FieldBaseProps, FormField, type FormFieldControlProps, type FormFieldProps, FormLayout, type FormLayoutDirection, type FormLayoutProps, HStack, type HStackProps, Heading, type HeadingLevel, type HeadingProps, IconButton, type IconButtonProps, type IconButtonVariant, type IconComponent, Select, type SelectOption, type SelectProps, type Size, Skeleton, type SkeletonProps, type SkeletonShape, Spinner, type SpinnerProps, Stack, type StackAlign, type StackGap, type StackJustify, type StackProps, Switch, type SwitchProps, Text, TextArea, type TextAreaProps, TextInput, type TextInputProps, type TextInputType, type TextProps, type TextSize, type TextTone, type TextWeight, type Tone, VStack, type VStackProps };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { Badge } from "./components/atomic/Badge/Badge.js";
|
|
2
2
|
import { Button } from "./components/atomic/Button/Button.js";
|
|
3
|
+
import { Checkbox } from "./components/atomic/Checkbox/Checkbox.js";
|
|
4
|
+
import { ColorInput } from "./components/atomic/ColorInput/ColorInput.js";
|
|
3
5
|
import { Divider } from "./components/atomic/Divider/Divider.js";
|
|
4
6
|
import { Heading } from "./components/atomic/Heading/Heading.js";
|
|
7
|
+
import { Switch } from "./components/atomic/Switch/Switch.js";
|
|
5
8
|
import { Text } from "./components/atomic/Text/Text.js";
|
|
9
|
+
import { TextArea } from "./components/atomic/TextArea/TextArea.js";
|
|
10
|
+
import { TextInput } from "./components/atomic/TextInput/TextInput.js";
|
|
6
11
|
import { IconButton } from "./components/atomic/IconButton/IconButton.js";
|
|
12
|
+
import { Select } from "./components/atomic/Select/Select.js";
|
|
7
13
|
import { Skeleton } from "./components/atomic/Skeleton/Skeleton.js";
|
|
8
14
|
import { Spinner } from "./components/atomic/Spinner/Spinner.js";
|
|
15
|
+
import { FormLayout } from "./components/layout/FormLayout/FormLayout.js";
|
|
16
|
+
import { FormField } from "./components/molecule/FormField/FormField.js";
|
|
9
17
|
import { HStack, Stack, VStack } from "./components/layout/Stack/Stack.js";
|
|
10
|
-
export { Badge, Button, Divider, HStack, Heading, IconButton, Skeleton, Spinner, Stack, Text, VStack };
|
|
18
|
+
export { Badge, Button, Checkbox, ColorInput, Divider, FormField, FormLayout, HStack, Heading, IconButton, Select, Skeleton, Spinner, Stack, Switch, Text, TextArea, TextInput, VStack };
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -7,4 +7,18 @@ export type IconComponent = React.ComponentType<{
|
|
|
7
7
|
className?: string;
|
|
8
8
|
'aria-hidden'?: boolean;
|
|
9
9
|
'data-icon'?: string;
|
|
10
|
-
}>;
|
|
10
|
+
}>;
|
|
11
|
+
/** Label, help and error props every form input shares (rendered by FormField). */
|
|
12
|
+
export interface FieldBaseProps {
|
|
13
|
+
/** Accessible name; always required, even when hidden. */
|
|
14
|
+
label: string;
|
|
15
|
+
/** Hides the label visually; screen readers still announce it. */
|
|
16
|
+
hideLabel?: boolean;
|
|
17
|
+
description?: string;
|
|
18
|
+
/** Message shown under the field; also sets aria-invalid. */
|
|
19
|
+
error?: string;
|
|
20
|
+
required?: boolean;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
id?: string;
|
|
23
|
+
'data-testid'?: string;
|
|
24
|
+
}
|
package/package.json
CHANGED