@xingxingmofashu/ui 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +8 -7
  2. package/dist/components/button.d.ts +1 -1
  3. package/dist/components/button.mjs +7 -2
  4. package/dist/components/card.d.ts +1 -1
  5. package/dist/components/checkbox-group.d.ts +41 -0
  6. package/dist/components/checkbox-group.mjs +223 -0
  7. package/dist/components/checkbox.d.ts +1 -1
  8. package/dist/components/checkbox.mjs +4 -0
  9. package/dist/components/field.d.ts +23 -0
  10. package/dist/components/field.mjs +62 -0
  11. package/dist/components/fieldset.d.ts +18 -0
  12. package/dist/components/fieldset.mjs +45 -0
  13. package/dist/components/form.d.ts +14 -0
  14. package/dist/components/form.mjs +21 -0
  15. package/dist/components/input.d.ts +1 -5
  16. package/dist/components/input.mjs +5 -35
  17. package/dist/components/menu.d.ts +8 -23
  18. package/dist/components/menu.mjs +11 -2
  19. package/dist/components/popover.d.ts +1 -12
  20. package/dist/components/radio-group.d.ts +1 -1
  21. package/dist/components/radio-group.mjs +7 -1
  22. package/dist/components/select.d.ts +1 -14
  23. package/dist/components/select.mjs +5 -3
  24. package/dist/components/slider.d.ts +2 -6
  25. package/dist/components/slider.mjs +4 -0
  26. package/dist/components/switch.mjs +3 -1
  27. package/dist/components/tabs.d.ts +1 -5
  28. package/dist/components/toggle-group.d.ts +1 -1
  29. package/dist/components/toggle-group.mjs +4 -0
  30. package/dist/components/toggle.d.ts +1 -1
  31. package/dist/components/toggle.mjs +4 -0
  32. package/dist/components/tooltip.d.ts +3 -18
  33. package/dist/components/tooltip.mjs +2 -2
  34. package/dist/index.d.ts +5 -1
  35. package/dist/index.mjs +6 -0
  36. package/dist/internal/fieldset.d.ts +8 -0
  37. package/dist/internal/fieldset.mjs +13 -0
  38. package/dist/theme/alert-dialog.mjs +2 -2
  39. package/dist/theme/card.mjs +1 -1
  40. package/dist/theme/checkbox-group.d.ts +41 -0
  41. package/dist/theme/checkbox-group.mjs +111 -0
  42. package/dist/theme/dialog.mjs +2 -2
  43. package/dist/theme/field.d.ts +25 -0
  44. package/dist/theme/field.mjs +66 -0
  45. package/dist/theme/fieldset.d.ts +5 -0
  46. package/dist/theme/fieldset.mjs +14 -0
  47. package/dist/theme/form.d.ts +4 -0
  48. package/dist/theme/form.mjs +6 -0
  49. package/dist/theme/input.d.ts +0 -2
  50. package/dist/theme/input.mjs +10 -10
  51. package/dist/theme/tabs.mjs +1 -1
  52. package/package.json +6 -3
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <picture>
2
- <source media="(prefers-color-scheme: dark)" srcset=".github/assets/surface-lab-dark.png">
3
- <source media="(prefers-color-scheme: light)" srcset=".github/assets/surface-lab-light.png">
4
- <img alt="The Liquid Glass Surface Lab panel showing glass components over the default image background in light mode." width="1024" src=".github/assets/surface-lab-light.png">
2
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/xingxingmofashu/ui/main/.github/assets/surface-lab-dark.png">
3
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/xingxingmofashu/ui/main/.github/assets/surface-lab-light.png">
4
+ <img alt="The Liquid Glass Surface Lab panel showing glass components over the default image background in light mode." width="1024" src="https://raw.githubusercontent.com/xingxingmofashu/ui/main/.github/assets/surface-lab-light.png">
5
5
  </picture>
6
6
 
7
7
  <div align="center">
@@ -14,15 +14,16 @@
14
14
 
15
15
  </div>
16
16
 
17
- `@xingxingmofashu/ui` is a collection of accessible, typed [React](https://react.dev)
17
+ `@xingxingmofashu/ui` is a collection of typed [React](https://react.dev)
18
18
  components with a Liquid Glass visual style, built with
19
19
  [Tailwind CSS](https://tailwindcss.com) and
20
20
  [Tailwind Variants](https://www.tailwind-variants.org). Glass surfaces, rim
21
21
  highlights, and inner shadows are drawn entirely with CSS.
22
22
 
23
- The package ships twenty-one components: Accordion, Alert Dialog, Button, Card,
24
- Checkbox, Dialog, Drawer, Input, Menu, Popover, Progress, Radio Group, Scroll
25
- Area, Select, Slider, Switch, Tabs, Toast, Toggle, Toggle Group, and Tooltip.
23
+ The package ships twenty-five components: Accordion, Alert Dialog, Button,
24
+ Card, Checkbox, Checkbox Group, Dialog, Drawer, Field, Fieldset, Form, Input,
25
+ Menu, Popover, Progress, Radio Group, Scroll Area, Select, Slider, Switch, Tabs,
26
+ Toast, Toggle, Toggle Group, and Tooltip.
26
27
 
27
28
  > [!NOTE]
28
29
  > Requires React 19, React DOM 19, Tailwind CSS 4, Node.js 22+, and an
@@ -18,6 +18,6 @@ interface ButtonProps extends Omit<UIButtonProps, "ref" | "style" | "className">
18
18
  /** Icon rendered after the label. */
19
19
  trailingIcon?: React.ReactNode;
20
20
  }
21
- declare function Button({ className, ui, children, label, leadingIcon, trailingIcon, size, ...props }: ButtonProps): React.JSX.Element;
21
+ declare function Button({ className, ui, children, label, leadingIcon, trailingIcon, size, disabled, ...props }: ButtonProps): React.JSX.Element;
22
22
  export { Button };
23
23
  export type { ButtonProps };
@@ -4,6 +4,7 @@ import {
4
4
  } from "@base-ui/react/button";
5
5
  import { cn } from "cn";
6
6
  import * as React from "react";
7
+ import { useFieldsetDisabled } from "../internal/fieldset.mjs";
7
8
  import theme from "../theme/button.mjs";
8
9
  function Button({
9
10
  className,
@@ -13,15 +14,19 @@ function Button({
13
14
  leadingIcon,
14
15
  trailingIcon,
15
16
  size,
17
+ disabled,
16
18
  ...props
17
19
  }) {
18
20
  const styles = theme({ size });
21
+ const fieldsetDisabled = useFieldsetDisabled(disabled);
22
+ const content = label || children;
19
23
  return /* @__PURE__ */ React.createElement(
20
24
  UIButton,
21
25
  {
22
26
  "data-slot": "root",
23
27
  className: cn(styles.root(), ui?.root, className),
24
- ...props
28
+ ...props,
29
+ disabled: fieldsetDisabled
25
30
  },
26
31
  /* @__PURE__ */ React.createElement("span", { "data-slot": "base", className: cn(styles.base(), ui?.base) }, /* @__PURE__ */ React.createElement(
27
32
  "span",
@@ -46,7 +51,7 @@ function Button({
46
51
  "aria-hidden": "true"
47
52
  },
48
53
  leadingIcon
49
- ) : null, /* @__PURE__ */ React.createElement("span", { "data-slot": "label", className: cn(styles.label(), ui?.label) }, label || children), trailingIcon ? /* @__PURE__ */ React.createElement(
54
+ ) : null, content ? /* @__PURE__ */ React.createElement("span", { "data-slot": "label", className: cn(styles.label(), ui?.label) }, content) : null, trailingIcon ? /* @__PURE__ */ React.createElement(
50
55
  "span",
51
56
  {
52
57
  "data-slot": "trailing-icon",
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { type ComponentConfig } from "../internal/tv";
3
3
  import theme from "../theme/card";
4
4
  type Card = ComponentConfig<typeof theme>;
5
- type CardProps = Omit<React.ComponentProps<"div">, "title"> & {
5
+ type CardProps = Omit<React.ComponentProps<"div">, "style" | "title"> & {
6
6
  /** Classes merged into the root element. */
7
7
  className?: string;
8
8
  /** Tailwind classes for internal slots, keyed by `data-slot`. */
@@ -0,0 +1,41 @@
1
+ import { Checkbox as UICheckbox } from "@base-ui/react/checkbox";
2
+ import { CheckboxGroup as UICheckboxGroup } from "@base-ui/react/checkbox-group";
3
+ import * as React from "react";
4
+ import { type VariantProps } from "tailwind-variants";
5
+ import { type ComponentConfig } from "../internal/tv";
6
+ import theme from "../theme/checkbox-group";
7
+ type CheckboxGroup = ComponentConfig<typeof theme>;
8
+ /** One entry in the group. */
9
+ type CheckboxGroupItemProps<Value extends string = string> = Omit<UICheckbox.Root.Props, "checked" | "defaultChecked" | "children" | "className" | "onCheckedChange" | "parent" | "style" | "value"> & {
10
+ /** Value that identifies the option in the group value. */
11
+ value: Value;
12
+ /** Visible label rendered next to the control. */
13
+ label?: React.ReactNode;
14
+ /** Supporting text rendered under the label. */
15
+ description?: React.ReactNode;
16
+ /** Tailwind classes merged into the entry root. */
17
+ className?: string;
18
+ /** Tailwind classes for control slots, keyed by `data-slot`. */
19
+ ui?: Partial<Pick<CheckboxGroup["slots"], "item" | "box" | "fill" | "glass" | "overlay" | "indicator" | "indicatorIcon" | "wrapper" | "itemLabel" | "itemDescription">>;
20
+ };
21
+ type CheckboxGroupProps<Value extends string = string> = Omit<UICheckboxGroup.Props, "allValues" | "children" | "className" | "defaultValue" | "onValueChange" | "style" | "value"> & VariantProps<typeof theme> & Pick<UICheckbox.Root.Props, "name" | "form" | "readOnly"> & {
22
+ /** Entries rendered by the group. */
23
+ items: readonly CheckboxGroupItemProps<Value>[];
24
+ /** Visible label for the group. */
25
+ label?: React.ReactNode;
26
+ /** Supporting text rendered under the group label. */
27
+ description?: React.ReactNode;
28
+ /** Controlled checked values. */
29
+ value?: readonly Value[];
30
+ /** Initial checked values when uncontrolled. */
31
+ defaultValue?: readonly Value[];
32
+ /** Called when a checkbox in the group is ticked or unticked. */
33
+ onValueChange?: (value: Value[], details: UICheckboxGroup.ChangeEventDetails) => void;
34
+ /** Tailwind classes merged into the group root. */
35
+ className?: string;
36
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
37
+ ui?: CheckboxGroup["slots"];
38
+ };
39
+ declare function CheckboxGroup<Value extends string = string>({ className, ui, size, items, label, description, name, form, readOnly, disabled, value, defaultValue, onValueChange, "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: CheckboxGroupProps<Value>): React.JSX.Element;
40
+ export { CheckboxGroup };
41
+ export type { CheckboxGroupItemProps, CheckboxGroupProps };
@@ -0,0 +1,223 @@
1
+ "use client";
2
+ import { Checkbox as UICheckbox } from "@base-ui/react/checkbox";
3
+ import { CheckboxGroup as UICheckboxGroup } from "@base-ui/react/checkbox-group";
4
+ import { cn } from "cn";
5
+ import * as React from "react";
6
+ import { mergeIds } from "../internal/aria.mjs";
7
+ import { useFieldsetDisabled } from "../internal/fieldset.mjs";
8
+ import theme from "../theme/checkbox-group.mjs";
9
+ import { CheckIcon } from "./icons/check.mjs";
10
+ import { DashIcon } from "./icons/dash.mjs";
11
+ function CheckboxGroup({
12
+ className,
13
+ ui,
14
+ size,
15
+ items,
16
+ label,
17
+ description,
18
+ name,
19
+ form,
20
+ readOnly,
21
+ disabled,
22
+ value,
23
+ defaultValue,
24
+ onValueChange,
25
+ "aria-describedby": ariaDescribedBy,
26
+ "aria-label": ariaLabel,
27
+ "aria-labelledby": ariaLabelledBy,
28
+ ...props
29
+ }) {
30
+ const styles = theme({ size });
31
+ const fieldsetDisabled = useFieldsetDisabled(disabled);
32
+ const labelId = React.useId();
33
+ const descriptionId = React.useId();
34
+ const labelledBy = ariaLabelledBy || (label && !ariaLabel ? labelId : void 0);
35
+ const hasName = Boolean(label || ariaLabel || labelledBy);
36
+ const describedBy = mergeIds(
37
+ ariaDescribedBy,
38
+ description && hasName ? descriptionId : void 0
39
+ );
40
+ function handleValueChange(next, details) {
41
+ onValueChange?.(next, details);
42
+ }
43
+ return /* @__PURE__ */ React.createElement(
44
+ UICheckboxGroup,
45
+ {
46
+ ...props,
47
+ "aria-describedby": describedBy,
48
+ "aria-label": ariaLabel,
49
+ ...labelledBy ? { "aria-labelledby": labelledBy } : {},
50
+ disabled: fieldsetDisabled,
51
+ value,
52
+ defaultValue,
53
+ onValueChange: handleValueChange,
54
+ "data-slot": "root",
55
+ className: cn(styles.root(), ui?.root, className)
56
+ },
57
+ label || description ? /* @__PURE__ */ React.createElement("div", { "data-slot": "header", className: cn(styles.header(), ui?.header) }, label ? /* @__PURE__ */ React.createElement(
58
+ "span",
59
+ {
60
+ id: labelId,
61
+ "data-slot": "label",
62
+ className: cn(styles.label(), ui?.label)
63
+ },
64
+ label
65
+ ) : null, description ? /* @__PURE__ */ React.createElement(
66
+ "span",
67
+ {
68
+ id: descriptionId,
69
+ "data-slot": "description",
70
+ className: cn(styles.description(), ui?.description)
71
+ },
72
+ description
73
+ ) : null) : null,
74
+ /* @__PURE__ */ React.createElement("div", { "data-slot": "items", className: cn(styles.items(), ui?.items) }, items.map((item) => /* @__PURE__ */ React.createElement(
75
+ CheckboxGroupItem,
76
+ {
77
+ key: item.value,
78
+ ...item,
79
+ name: item.name ?? name,
80
+ form: item.form ?? form,
81
+ readOnly: item.readOnly ?? readOnly,
82
+ ui: {
83
+ item: cn(ui?.item, item.ui?.item),
84
+ box: cn(ui?.box, item.ui?.box),
85
+ fill: cn(ui?.fill, item.ui?.fill),
86
+ glass: cn(ui?.glass, item.ui?.glass),
87
+ overlay: cn(ui?.overlay, item.ui?.overlay),
88
+ indicator: cn(ui?.indicator, item.ui?.indicator),
89
+ indicatorIcon: cn(
90
+ ui?.indicatorIcon,
91
+ item.ui?.indicatorIcon
92
+ ),
93
+ wrapper: cn(
94
+ styles.wrapper(),
95
+ ui?.wrapper,
96
+ item.ui?.wrapper
97
+ ),
98
+ itemLabel: cn(ui?.itemLabel, item.ui?.itemLabel),
99
+ itemDescription: cn(
100
+ ui?.itemDescription,
101
+ item.ui?.itemDescription
102
+ )
103
+ }
104
+ }
105
+ )))
106
+ );
107
+ }
108
+ function CheckboxGroupItem({
109
+ className,
110
+ ui,
111
+ label,
112
+ description,
113
+ value,
114
+ name,
115
+ form,
116
+ readOnly,
117
+ "aria-describedby": ariaDescribedBy,
118
+ "aria-label": ariaLabel,
119
+ "aria-labelledby": ariaLabelledBy,
120
+ ...props
121
+ }) {
122
+ const styles = theme();
123
+ const labelId = React.useId();
124
+ const descriptionId = React.useId();
125
+ const hasName = Boolean(label || ariaLabel || ariaLabelledBy);
126
+ const labelledBy = ariaLabelledBy || (label && !ariaLabel ? labelId : void 0);
127
+ const describedBy = mergeIds(
128
+ ariaDescribedBy,
129
+ description && hasName ? descriptionId : void 0
130
+ );
131
+ return /* @__PURE__ */ React.createElement(
132
+ UICheckbox.Root,
133
+ {
134
+ ...props,
135
+ value,
136
+ name,
137
+ form,
138
+ readOnly,
139
+ "aria-describedby": describedBy,
140
+ "aria-label": ariaLabel,
141
+ "aria-labelledby": labelledBy,
142
+ "data-slot": "item",
143
+ className: cn(styles.item(), ui?.item, className)
144
+ },
145
+ /* @__PURE__ */ React.createElement(
146
+ "span",
147
+ {
148
+ "data-slot": "box",
149
+ className: cn(styles.box(), ui?.box)
150
+ },
151
+ /* @__PURE__ */ React.createElement(
152
+ "span",
153
+ {
154
+ "aria-hidden": "true",
155
+ "data-slot": "fill",
156
+ className: cn(styles.fill(), ui?.fill)
157
+ }
158
+ ),
159
+ /* @__PURE__ */ React.createElement(
160
+ "span",
161
+ {
162
+ "aria-hidden": "true",
163
+ "data-slot": "glass",
164
+ className: cn(styles.glass(), ui?.glass)
165
+ },
166
+ /* @__PURE__ */ React.createElement(
167
+ "span",
168
+ {
169
+ "aria-hidden": "true",
170
+ "data-slot": "overlay",
171
+ className: cn(styles.overlay(), ui?.overlay)
172
+ }
173
+ )
174
+ ),
175
+ /* @__PURE__ */ React.createElement(
176
+ UICheckbox.Indicator,
177
+ {
178
+ keepMounted: true,
179
+ "aria-hidden": "true",
180
+ "data-slot": "indicator",
181
+ className: cn(styles.indicator(), ui?.indicator),
182
+ render: (indicatorProps, state) => /* @__PURE__ */ React.createElement("span", { ...indicatorProps }, /* @__PURE__ */ React.createElement(
183
+ "span",
184
+ {
185
+ "data-slot": "indicator-icon",
186
+ className: cn(styles.indicatorIcon(), ui?.indicatorIcon)
187
+ },
188
+ state.indeterminate ? /* @__PURE__ */ React.createElement(DashIcon, null) : /* @__PURE__ */ React.createElement(CheckIcon, null)
189
+ ))
190
+ }
191
+ )
192
+ ),
193
+ label || description ? /* @__PURE__ */ React.createElement(
194
+ "span",
195
+ {
196
+ "data-slot": "wrapper",
197
+ className: cn(styles.wrapper(), ui?.wrapper)
198
+ },
199
+ label ? /* @__PURE__ */ React.createElement(
200
+ "span",
201
+ {
202
+ id: labelId,
203
+ "data-slot": "item-label",
204
+ className: cn(styles.itemLabel(), ui?.itemLabel)
205
+ },
206
+ label
207
+ ) : null,
208
+ description ? /* @__PURE__ */ React.createElement(
209
+ "span",
210
+ {
211
+ id: descriptionId,
212
+ "data-slot": "item-description",
213
+ className: cn(
214
+ styles.itemDescription(),
215
+ ui?.itemDescription
216
+ )
217
+ },
218
+ description
219
+ ) : null
220
+ ) : null
221
+ );
222
+ }
223
+ export { CheckboxGroup };
@@ -16,6 +16,6 @@ interface CheckboxProps extends Omit<UICheckbox.Root.Props, "className" | "child
16
16
  /** Optional supporting text. */
17
17
  description?: React.ReactNode;
18
18
  }
19
- declare function Checkbox({ className, ui, label, description, size, indeterminate, "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: CheckboxProps): React.JSX.Element;
19
+ declare function Checkbox({ className, ui, label, description, size, disabled, indeterminate, "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: CheckboxProps): React.JSX.Element;
20
20
  export { Checkbox };
21
21
  export type { CheckboxProps };
@@ -3,6 +3,7 @@ import { Checkbox as UICheckbox } from "@base-ui/react/checkbox";
3
3
  import { cn } from "cn";
4
4
  import * as React from "react";
5
5
  import { mergeIds } from "../internal/aria.mjs";
6
+ import { useFieldsetDisabled } from "../internal/fieldset.mjs";
6
7
  import theme from "../theme/checkbox.mjs";
7
8
  import { CheckIcon } from "./icons/check.mjs";
8
9
  import { DashIcon } from "./icons/dash.mjs";
@@ -12,6 +13,7 @@ function Checkbox({
12
13
  label,
13
14
  description,
14
15
  size,
16
+ disabled,
15
17
  indeterminate = false,
16
18
  "aria-describedby": ariaDescribedBy,
17
19
  "aria-label": ariaLabel,
@@ -19,6 +21,7 @@ function Checkbox({
19
21
  ...props
20
22
  }) {
21
23
  const styles = theme({ size });
24
+ const fieldsetDisabled = useFieldsetDisabled(disabled);
22
25
  const labelId = React.useId();
23
26
  const descriptionId = React.useId();
24
27
  const hasName = Boolean(label || ariaLabel || ariaLabelledBy);
@@ -34,6 +37,7 @@ function Checkbox({
34
37
  "aria-describedby": describedBy,
35
38
  "aria-label": ariaLabel,
36
39
  "aria-labelledby": labelledBy,
40
+ disabled: fieldsetDisabled,
37
41
  indeterminate,
38
42
  "data-slot": "root",
39
43
  className: cn(styles.root(), ui?.root, className)
@@ -0,0 +1,23 @@
1
+ import { Field as UIField } from "@base-ui/react/field";
2
+ import * as React from "react";
3
+ import { type VariantProps } from "tailwind-variants";
4
+ import { type ComponentConfig } from "../internal/tv";
5
+ import theme from "../theme/field";
6
+ type Field = ComponentConfig<typeof theme>;
7
+ interface FieldProps extends Omit<UIField.Root.Props, "children" | "className" | "style">, VariantProps<typeof theme> {
8
+ /** Single Base UI control labelled and validated by the field. */
9
+ children: React.ReactElement;
10
+ /** Visible label associated with the control. */
11
+ label?: React.ReactNode;
12
+ /** Supporting text rendered under the control. */
13
+ description?: React.ReactNode;
14
+ /** Error message shown under the control. Accepts any React node. */
15
+ error?: React.ReactNode;
16
+ /** Tailwind classes merged into the field root. */
17
+ className?: string;
18
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
19
+ ui?: Field["slots"];
20
+ }
21
+ declare function Field({ children, className, ui, size, label, description, error, invalid, disabled, ...props }: FieldProps): React.JSX.Element;
22
+ export { Field };
23
+ export type { FieldProps };
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import { Field as UIField } from "@base-ui/react/field";
3
+ import { cn } from "cn";
4
+ import * as React from "react";
5
+ import theme from "../theme/field.mjs";
6
+ function FieldError({
7
+ error,
8
+ ui
9
+ }) {
10
+ const styles = theme();
11
+ return /* @__PURE__ */ React.createElement(
12
+ UIField.Error,
13
+ {
14
+ ...error ? { match: true, children: error } : {},
15
+ "data-slot": "error",
16
+ className: cn(styles.error(), ui?.error)
17
+ }
18
+ );
19
+ }
20
+ function Field({
21
+ children,
22
+ className,
23
+ ui,
24
+ size,
25
+ label,
26
+ description,
27
+ error,
28
+ invalid,
29
+ disabled,
30
+ ...props
31
+ }) {
32
+ const styles = theme({ size });
33
+ return /* @__PURE__ */ React.createElement(
34
+ UIField.Root,
35
+ {
36
+ ...props,
37
+ disabled,
38
+ invalid: invalid || (error ? true : void 0),
39
+ "data-slot": "root",
40
+ className: cn(styles.root(), ui?.root, className)
41
+ },
42
+ label ? /* @__PURE__ */ React.createElement(
43
+ UIField.Label,
44
+ {
45
+ "data-slot": "label",
46
+ className: cn(styles.label(), ui?.label)
47
+ },
48
+ label
49
+ ) : null,
50
+ children,
51
+ /* @__PURE__ */ React.createElement(FieldError, { error, ui }),
52
+ description ? /* @__PURE__ */ React.createElement(
53
+ UIField.Description,
54
+ {
55
+ "data-slot": "description",
56
+ className: cn(styles.description(), ui?.description)
57
+ },
58
+ description
59
+ ) : null
60
+ );
61
+ }
62
+ export { Field };
@@ -0,0 +1,18 @@
1
+ import { Fieldset as UIFieldset } from "@base-ui/react/fieldset";
2
+ import * as React from "react";
3
+ import { type ComponentConfig } from "../internal/tv";
4
+ import theme from "../theme/fieldset";
5
+ type Fieldset = ComponentConfig<typeof theme>;
6
+ interface FieldsetProps extends Omit<UIFieldset.Root.Props, "children" | "className" | "style"> {
7
+ /** Visible legend naming the group. */
8
+ legend?: React.ReactNode;
9
+ /** Fields and controls grouped by the fieldset. */
10
+ children: React.ReactNode;
11
+ /** Tailwind classes merged into the fieldset root. */
12
+ className?: string;
13
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
14
+ ui?: Fieldset["slots"];
15
+ }
16
+ declare function Fieldset({ children, legend, disabled, className, ui, "aria-labelledby": ariaLabelledBy, ...props }: FieldsetProps): React.JSX.Element;
17
+ export { Fieldset };
18
+ export type { FieldsetProps };
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { Fieldset as UIFieldset } from "@base-ui/react/fieldset";
3
+ import { cn } from "cn";
4
+ import * as React from "react";
5
+ import {
6
+ FieldsetDisabledProvider,
7
+ useFieldsetDisabled
8
+ } from "../internal/fieldset.mjs";
9
+ import theme from "../theme/fieldset.mjs";
10
+ function Fieldset({
11
+ children,
12
+ legend,
13
+ disabled = false,
14
+ className,
15
+ ui,
16
+ "aria-labelledby": ariaLabelledBy,
17
+ ...props
18
+ }) {
19
+ const styles = theme();
20
+ const legendId = React.useId();
21
+ const inheritedDisabled = useFieldsetDisabled();
22
+ const isDisabled = inheritedDisabled || disabled;
23
+ const labelledBy = ariaLabelledBy ?? (legend ? legendId : void 0);
24
+ return /* @__PURE__ */ React.createElement(FieldsetDisabledProvider, { disabled: isDisabled }, /* @__PURE__ */ React.createElement(
25
+ UIFieldset.Root,
26
+ {
27
+ ...props,
28
+ disabled: isDisabled,
29
+ ...labelledBy ? { "aria-labelledby": labelledBy } : {},
30
+ "data-slot": "root",
31
+ className: cn(styles.root(), ui?.root, className)
32
+ },
33
+ legend ? /* @__PURE__ */ React.createElement(
34
+ UIFieldset.Legend,
35
+ {
36
+ id: legendId,
37
+ "data-slot": "legend",
38
+ className: cn(styles.legend(), ui?.legend)
39
+ },
40
+ legend
41
+ ) : null,
42
+ children
43
+ ));
44
+ }
45
+ export { Fieldset };
@@ -0,0 +1,14 @@
1
+ import { Form as UIForm } from "@base-ui/react/form";
2
+ import * as React from "react";
3
+ import { type ComponentConfig } from "../internal/tv";
4
+ import theme from "../theme/form";
5
+ type Form = ComponentConfig<typeof theme>;
6
+ type FormProps<FormValues extends Record<string, any> = Record<string, any>> = Omit<UIForm.Props<FormValues>, "className" | "style"> & {
7
+ /** Tailwind classes merged into the form element. */
8
+ className?: string;
9
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
10
+ ui?: Form["slots"];
11
+ };
12
+ declare function Form<FormValues extends Record<string, any> = Record<string, any>>({ className, ui, ...props }: FormProps<FormValues>): React.JSX.Element;
13
+ export { Form };
14
+ export type { FormProps };
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { Form as UIForm } from "@base-ui/react/form";
3
+ import { cn } from "cn";
4
+ import * as React from "react";
5
+ import theme from "../theme/form.mjs";
6
+ function Form({
7
+ className,
8
+ ui,
9
+ ...props
10
+ }) {
11
+ const styles = theme();
12
+ return /* @__PURE__ */ React.createElement(
13
+ UIForm,
14
+ {
15
+ ...props,
16
+ "data-slot": "root",
17
+ className: cn(styles.root(), ui?.root, className)
18
+ }
19
+ );
20
+ }
21
+ export { Form };
@@ -9,15 +9,11 @@ interface InputProps extends Omit<UIInput.Props, "className" | "children" | "siz
9
9
  className?: string;
10
10
  /** Tailwind classes for internal slots, keyed by `data-slot`. */
11
11
  ui?: Input["slots"];
12
- /** Visible label associated with the input. */
13
- label?: React.ReactNode;
14
- /** Optional supporting text under the field. */
15
- description?: React.ReactNode;
16
12
  /** Icon rendered before the input. */
17
13
  leadingIcon?: React.ReactNode;
18
14
  /** Icon rendered after the input. */
19
15
  trailingIcon?: React.ReactNode;
20
16
  }
21
- declare function Input({ className, ui, label, description, leadingIcon, trailingIcon, size, id, disabled, "aria-describedby": ariaDescribedBy, ...props }: InputProps): React.JSX.Element;
17
+ declare function Input({ className, ui, leadingIcon, trailingIcon, size, disabled, ...props }: InputProps): React.JSX.Element;
22
18
  export { Input };
23
19
  export type { InputProps };