@api7/ui-components 0.4.0 → 0.6.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/README.md +221 -30
- package/dist/animations.css +12 -0
- package/dist/components/alert/alert.d.ts +0 -2
- package/dist/components/alert/alert.js +8 -9
- package/dist/components/avatar/avatar.d.ts +4 -6
- package/dist/components/avatar/avatar.js +7 -8
- package/dist/components/badge/badge.d.ts +0 -2
- package/dist/components/badge/badge.js +15 -16
- package/dist/components/button/button.d.ts +1 -4
- package/dist/components/button/button.js +15 -16
- package/dist/components/calendar/calendar.d.ts +1 -3
- package/dist/components/calendar/calendar.js +29 -30
- package/dist/components/checkbox/checkbox.d.ts +0 -2
- package/dist/components/checkbox/checkbox.js +4 -5
- package/dist/components/combobox/combobox.d.ts +0 -2
- package/dist/components/combobox/combobox.js +25 -25
- package/dist/components/data-table/data-table.d.ts +0 -2
- package/dist/components/data-table/data-table.js +8 -9
- package/dist/components/data-table/filter-header.d.ts +1 -3
- package/dist/components/data-table/filter-header.js +5 -6
- package/dist/components/data-table/sort-header.js +3 -4
- package/dist/components/date-picker/date-picker.d.ts +0 -2
- package/dist/components/date-picker/date-picker.js +15 -16
- package/dist/components/description-list/description-list.d.ts +24 -0
- package/dist/components/description-list/description-list.js +88 -0
- package/dist/components/dialog/dialog.d.ts +0 -2
- package/dist/components/dialog/dialog.js +12 -13
- package/dist/components/drawer/drawer.d.ts +0 -2
- package/dist/components/drawer/drawer.js +13 -14
- package/dist/components/empty/empty.d.ts +0 -2
- package/dist/components/empty/empty.js +9 -10
- package/dist/components/field/field.d.ts +0 -2
- package/dist/components/field/field.js +7 -8
- package/dist/components/field/labeled-field.d.ts +33 -0
- package/dist/components/field/labeled-field.js +67 -0
- package/dist/components/form/choice-fields.d.ts +1 -3
- package/dist/components/form/choice-fields.js +1 -2
- package/dist/components/form/date-fields.d.ts +0 -2
- package/dist/components/form/date-fields.js +2 -3
- package/dist/components/form/errors.d.ts +1 -3
- package/dist/components/form/errors.js +1 -2
- package/dist/components/form/form-context.d.ts +1 -3
- package/dist/components/form/form-context.js +1 -2
- package/dist/components/form/form-item.d.ts +6 -17
- package/dist/components/form/form-item.js +9 -58
- package/dist/components/form/form.d.ts +1 -3
- package/dist/components/form/form.js +1 -2
- package/dist/components/form/lazy-field-components.js +2 -3
- package/dist/components/form/submit-button.d.ts +1 -3
- package/dist/components/form/submit-button.js +1 -2
- package/dist/components/form/text-field.d.ts +1 -3
- package/dist/components/form/text-field.js +1 -2
- package/dist/components/form/toggle-fields.d.ts +1 -3
- package/dist/components/form/toggle-fields.js +30 -46
- package/dist/components/input/input.d.ts +0 -2
- package/dist/components/input/input.js +2 -3
- package/dist/components/input-group/input-group.d.ts +0 -2
- package/dist/components/input-group/input-group.js +12 -13
- package/dist/components/menu/menu.d.ts +14 -4
- package/dist/components/menu/menu.js +43 -31
- package/dist/components/number-field/number-field.d.ts +0 -2
- package/dist/components/number-field/number-field.js +8 -9
- package/dist/components/pagination/pagination.d.ts +1 -3
- package/dist/components/pagination/pagination.js +13 -14
- package/dist/components/popover/popover.d.ts +3 -3
- package/dist/components/popover/popover.js +14 -7
- package/dist/components/progress/progress.d.ts +17 -0
- package/dist/components/progress/progress.js +35 -0
- package/dist/components/radio-group/radio-group.d.ts +0 -2
- package/dist/components/radio-group/radio-group.js +4 -5
- package/dist/components/select/select.d.ts +0 -2
- package/dist/components/select/select.js +18 -18
- package/dist/components/separator/separator.d.ts +0 -2
- package/dist/components/separator/separator.js +2 -3
- package/dist/components/sidebar/sidebar.d.ts +0 -2
- package/dist/components/sidebar/sidebar.js +11 -12
- package/dist/components/skeleton/skeleton.d.ts +0 -2
- package/dist/components/skeleton/skeleton.js +2 -3
- package/dist/components/spinner/spinner.d.ts +12 -0
- package/dist/components/spinner/spinner.js +27 -0
- package/dist/components/switch/switch.d.ts +0 -2
- package/dist/components/switch/switch.js +3 -4
- package/dist/components/table/table.d.ts +0 -2
- package/dist/components/table/table.js +8 -9
- package/dist/components/tabs/tabs.d.ts +0 -2
- package/dist/components/tabs/tabs.js +5 -6
- package/dist/components/textarea/textarea.d.ts +0 -2
- package/dist/components/textarea/textarea.js +2 -3
- package/dist/components/toast/toast.d.ts +0 -2
- package/dist/components/toast/toast.js +19 -20
- package/dist/components/tooltip/tooltip.d.ts +0 -2
- package/dist/components/tooltip/tooltip.js +5 -4
- package/dist/config/config-provider.d.ts +1 -3
- package/dist/config/config-provider.js +1 -2
- package/dist/config/messages.d.ts +5 -3
- package/dist/config/messages.js +3 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +7 -3
- package/dist/lib/cn.js +5 -6
- package/dist/lib/control.js +4 -5
- package/dist/lib/popup.js +6 -6
- package/dist/theme.css +220 -0
- package/dist/tokens/contrast.d.ts +1 -3
- package/dist/tokens/contrast.js +1 -2
- package/dist/tokens/palette.d.ts +0 -2
- package/dist/tokens/palette.js +1 -2
- package/dist/tokens/scale.js +1 -2
- package/dist/tokens/semantic.d.ts +0 -2
- package/dist/tokens/semantic.js +0 -1
- package/dist/tokens/types.d.ts +1 -3
- package/dist/tokens/types.js +1 -2
- package/package.json +11 -9
- package/dist/styles.css +0 -2
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMessages } from "../../config/config-provider.js";
|
|
3
|
+
import { Field, FieldDescription, FieldError, FieldLabel, Fieldset, FieldsetLegend } from "./field.js";
|
|
4
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip/tooltip.js";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { InfoIcon } from "lucide-react";
|
|
7
|
+
// src/components/field/labeled-field.tsx
|
|
8
|
+
/** Appended inside a label so the accessible name reads "Name Optional". */
|
|
9
|
+
function OptionalMarker({ label }) {
|
|
10
|
+
const messages = useMessages();
|
|
11
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
12
|
+
className: "font-medium text-muted-foreground",
|
|
13
|
+
children: [" ", label ?? messages.form.optional]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** Info icon button next to a label; kept outside the label so clicking it does not focus the control. */
|
|
17
|
+
function LabelTooltip({ content, label }) {
|
|
18
|
+
const messages = useMessages();
|
|
19
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
20
|
+
render: /* @__PURE__ */ jsx("button", {
|
|
21
|
+
type: "button",
|
|
22
|
+
"aria-label": label ?? messages.form.moreInfo,
|
|
23
|
+
className: "inline-flex text-muted-foreground"
|
|
24
|
+
}),
|
|
25
|
+
children: /* @__PURE__ */ jsx(InfoIcon, { className: "size-3.5" })
|
|
26
|
+
}), /* @__PURE__ */ jsx(TooltipContent, { children: content })] });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A form row: label, optional marker, label tooltip, control, description and errors. It
|
|
30
|
+
* takes the field state as props, so any form library or plain React state can drive it.
|
|
31
|
+
*/
|
|
32
|
+
function LabeledField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, layout = "stacked", group = false, name, invalid = false, touched, dirty, errors = [], children }) {
|
|
33
|
+
const labelRow = label && /* @__PURE__ */ jsxs("div", {
|
|
34
|
+
className: "flex items-center gap-1",
|
|
35
|
+
children: [/* @__PURE__ */ jsxs(group ? FieldsetLegend : FieldLabel, { children: [label, optional && /* @__PURE__ */ jsx(OptionalMarker, { label: optionalLabel })] }), labelTooltip && /* @__PURE__ */ jsx(LabelTooltip, {
|
|
36
|
+
content: labelTooltip,
|
|
37
|
+
label: moreInfoLabel
|
|
38
|
+
})]
|
|
39
|
+
});
|
|
40
|
+
let body;
|
|
41
|
+
if (group) body = /* @__PURE__ */ jsxs(Fieldset, { children: [labelRow, children] });
|
|
42
|
+
else if (layout === "stacked") body = /* @__PURE__ */ jsxs(Fragment, { children: [labelRow, children] });
|
|
43
|
+
else body = /* @__PURE__ */ jsx("div", {
|
|
44
|
+
className: "flex flex-row items-center gap-2.5",
|
|
45
|
+
children: layout === "inline-end" ? /* @__PURE__ */ jsxs(Fragment, { children: [labelRow, children] }) : /* @__PURE__ */ jsxs(Fragment, { children: [children, labelRow] })
|
|
46
|
+
});
|
|
47
|
+
return /* @__PURE__ */ jsxs(Field, {
|
|
48
|
+
name,
|
|
49
|
+
invalid,
|
|
50
|
+
touched,
|
|
51
|
+
dirty,
|
|
52
|
+
className,
|
|
53
|
+
"data-slot": "form-item",
|
|
54
|
+
children: [
|
|
55
|
+
body,
|
|
56
|
+
description && /* @__PURE__ */ jsx(FieldDescription, { children: description }),
|
|
57
|
+
invalid && errors.length > 0 && /* @__PURE__ */ jsx(FieldError, {
|
|
58
|
+
match: true,
|
|
59
|
+
children: errors.map((message) => /* @__PURE__ */ jsx("span", {
|
|
60
|
+
className: "block",
|
|
61
|
+
children: message
|
|
62
|
+
}, message))
|
|
63
|
+
})
|
|
64
|
+
]
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export { LabeledField };
|
|
@@ -2,7 +2,6 @@ import { FormItemProps } from "./form-item.js";
|
|
|
2
2
|
import { NumberFieldProps } from "../number-field/number-field.js";
|
|
3
3
|
import { SelectProps } from "../select/select.js";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
|
-
//#region src/components/form/choice-fields.d.ts
|
|
6
5
|
export type NumberFieldFieldProps = Omit<FormItemProps, 'layout'> & Omit<NumberFieldProps, 'name' | 'value' | 'defaultValue' | 'onValueChange' | 'onBlur' | 'className'>;
|
|
7
6
|
export declare function FormNumberField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...numberFieldProps }: NumberFieldFieldProps): import("react").JSX.Element;
|
|
8
7
|
export type SelectFieldProps = Omit<FormItemProps, 'layout'> & Pick<SelectProps, 'items' | 'multiple' | 'clearable' | 'disabled' | 'readOnly'> & {
|
|
@@ -24,5 +23,4 @@ export interface ComboboxFieldProps<Item> extends Omit<FormItemProps, 'layout'>
|
|
|
24
23
|
itemToStringValue?: (item: Item) => string;
|
|
25
24
|
children?: (item: Item) => ReactNode;
|
|
26
25
|
}
|
|
27
|
-
export declare function ComboboxField<Item>({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, items, multiple, placeholder, disabled, itemToStringLabel, itemToStringValue, children }: ComboboxFieldProps<Item>): import("react").JSX.Element;
|
|
28
|
-
//#endregion
|
|
26
|
+
export declare function ComboboxField<Item>({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, items, multiple, placeholder, disabled, itemToStringLabel, itemToStringValue, children }: ComboboxFieldProps<Item>): import("react").JSX.Element;
|
|
@@ -6,7 +6,7 @@ import { useFieldContext } from "./form-context.js";
|
|
|
6
6
|
import { FormItem } from "./form-item.js";
|
|
7
7
|
import { useRef } from "react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
|
|
9
|
+
// src/components/form/choice-fields.tsx
|
|
10
10
|
function FormNumberField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...numberFieldProps }) {
|
|
11
11
|
const field = useFieldContext();
|
|
12
12
|
return /* @__PURE__ */ jsx(FormItem, {
|
|
@@ -119,5 +119,4 @@ function ComboboxField({ label, description, labelTooltip, optional, optionalLab
|
|
|
119
119
|
})
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
|
-
//#endregion
|
|
123
122
|
export { ComboboxField, FormNumberField, SelectField };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { FormItemProps } from "./form-item.js";
|
|
2
2
|
import { DatePickerProps, DateRangePickerProps } from "../date-picker/date-picker.js";
|
|
3
|
-
//#region src/components/form/date-fields.d.ts
|
|
4
3
|
type BoundPickerProps = 'value' | 'defaultValue' | 'onValueChange' | 'onOpenChange' | 'onBlur' | 'className';
|
|
5
4
|
export type DatePickerFieldProps = Omit<FormItemProps, 'layout'> & Omit<DatePickerProps, BoundPickerProps>;
|
|
6
5
|
export type DateRangePickerFieldProps = Omit<FormItemProps, 'layout'> & Omit<DateRangePickerProps, BoundPickerProps>;
|
|
@@ -8,5 +7,4 @@ export type DateRangePickerFieldProps = Omit<FormItemProps, 'layout'> & Omit<Dat
|
|
|
8
7
|
export declare function DatePickerField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...pickerProps }: DatePickerFieldProps): import("react").JSX.Element;
|
|
9
8
|
/** A DateRangePicker bound to the enclosing form field; the field value is a `DateRange` or `undefined`. */
|
|
10
9
|
export declare function DateRangePickerField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...pickerProps }: DateRangePickerFieldProps): import("react").JSX.Element;
|
|
11
|
-
//#endregion
|
|
12
10
|
export {};
|
|
@@ -4,11 +4,11 @@ import { useFieldContext } from "./form-context.js";
|
|
|
4
4
|
import { FormItem } from "./form-item.js";
|
|
5
5
|
import { Suspense, lazy, useRef } from "react";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
|
-
|
|
7
|
+
// src/components/form/date-fields.tsx
|
|
8
8
|
const DatePicker = lazy(() => import("../date-picker/date-picker.js").then((m) => ({ default: m.DatePicker })));
|
|
9
9
|
const DateRangePicker = lazy(() => import("../date-picker/date-picker.js").then((m) => ({ default: m.DateRangePicker })));
|
|
10
10
|
function PickerFallback() {
|
|
11
|
-
return /* @__PURE__ */ jsx(Skeleton, { className: "
|
|
11
|
+
return /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" });
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Tracks whether the calendar popover is open. Opening it moves focus off the trigger; that blur
|
|
@@ -73,5 +73,4 @@ function DateRangePickerField({ label, description, labelTooltip, optional, opti
|
|
|
73
73
|
})
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
|
-
//#endregion
|
|
77
76
|
export { DatePickerField, DateRangePickerField };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/components/form/errors.ts
|
|
2
2
|
function formatFieldErrors(errors) {
|
|
3
3
|
const messages = [];
|
|
4
4
|
for (const error of errors) {
|
|
@@ -7,5 +7,4 @@ function formatFieldErrors(errors) {
|
|
|
7
7
|
}
|
|
8
8
|
return messages;
|
|
9
9
|
}
|
|
10
|
-
//#endregion
|
|
11
10
|
export { formatFieldErrors };
|
|
@@ -1,3 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const fieldContext: import("react").Context<import("@tanstack/react-form").AnyFieldApi>, formContext: import("react").Context<import("@tanstack/react-form").AnyFormApi>, useFieldContext: <TData>() => import("@tanstack/react-form").FieldApi<any, string, TData, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>, useFormContext: () => import("@tanstack/react-form").ReactFormExtendedApi<Record<string, never>, any, any, any, any, any, any, any, any, any, any, any>;
|
|
3
|
-
//#endregion
|
|
1
|
+
export declare const fieldContext: import("react").Context<import("@tanstack/react-form").AnyFieldApi>, formContext: import("react").Context<import("@tanstack/react-form").AnyFormApi>, useFieldContext: <TData>() => import("@tanstack/react-form").FieldApi<any, string, TData, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>, useFormContext: () => import("@tanstack/react-form").ReactFormExtendedApi<Record<string, never>, any, any, any, any, any, any, any, any, any, any, any>;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createFormHookContexts } from "@tanstack/react-form";
|
|
3
|
-
|
|
3
|
+
// src/components/form/form-context.ts
|
|
4
4
|
const { fieldContext, formContext, useFieldContext, useFormContext } = createFormHookContexts();
|
|
5
|
-
//#endregion
|
|
6
5
|
export { fieldContext, formContext, useFieldContext, useFormContext };
|
|
@@ -1,18 +1,7 @@
|
|
|
1
|
+
import { LabeledFieldLayout, LabeledFieldProps } from "../field/labeled-field.js";
|
|
1
2
|
import { ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
export type
|
|
4
|
-
export interface FormItemProps {
|
|
5
|
-
label?: ReactNode;
|
|
6
|
-
description?: ReactNode;
|
|
7
|
-
/** Info icon next to the label that shows this content in a tooltip. */
|
|
8
|
-
labelTooltip?: ReactNode;
|
|
9
|
-
/** Appends the "Optional" marker to the label. */
|
|
10
|
-
optional?: boolean;
|
|
11
|
-
optionalLabel?: string;
|
|
12
|
-
moreInfoLabel?: string;
|
|
13
|
-
className?: string;
|
|
14
|
-
layout?: FormItemLayout;
|
|
15
|
-
}
|
|
3
|
+
export type FormItemLayout = LabeledFieldLayout;
|
|
4
|
+
export type FormItemProps = Pick<LabeledFieldProps, 'label' | 'description' | 'labelTooltip' | 'optional' | 'optionalLabel' | 'moreInfoLabel' | 'className' | 'layout'>;
|
|
16
5
|
/** Reads the bound field and returns what FormItem and controls need. */
|
|
17
6
|
export declare function useFieldState(): {
|
|
18
7
|
name: string;
|
|
@@ -21,7 +10,7 @@ export declare function useFieldState(): {
|
|
|
21
10
|
touched: boolean;
|
|
22
11
|
dirty: boolean;
|
|
23
12
|
};
|
|
24
|
-
|
|
13
|
+
/** LabeledField bound to the TanStack Form field around it. */
|
|
14
|
+
export declare function FormItem(props: FormItemProps & Pick<LabeledFieldProps, 'group'> & {
|
|
25
15
|
children: ReactNode;
|
|
26
|
-
}): import("react").JSX.Element;
|
|
27
|
-
//#endregion
|
|
16
|
+
}): import("react").JSX.Element;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { Field, FieldDescription, FieldError, FieldLabel } from "../field/field.js";
|
|
4
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip/tooltip.js";
|
|
2
|
+
import { LabeledField } from "../field/labeled-field.js";
|
|
5
3
|
import { useFieldContext } from "./form-context.js";
|
|
6
4
|
import { formatFieldErrors } from "./errors.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
//#region src/components/form/form-item.tsx
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
// src/components/form/form-item.tsx
|
|
10
7
|
/** Reads the bound field and returns what FormItem and controls need. */
|
|
11
8
|
function useFieldState() {
|
|
12
9
|
const field = useFieldContext();
|
|
@@ -20,57 +17,11 @@ function useFieldState() {
|
|
|
20
17
|
dirty: field.state.meta.isDirty
|
|
21
18
|
};
|
|
22
19
|
}
|
|
23
|
-
/**
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
children: [" ", label ?? messages.form.optional]
|
|
20
|
+
/** LabeledField bound to the TanStack Form field around it. */
|
|
21
|
+
function FormItem(props) {
|
|
22
|
+
return /* @__PURE__ */ jsx(LabeledField, {
|
|
23
|
+
...props,
|
|
24
|
+
...useFieldState()
|
|
29
25
|
});
|
|
30
26
|
}
|
|
31
|
-
|
|
32
|
-
function LabelTooltip({ content, label }) {
|
|
33
|
-
const messages = useMessages();
|
|
34
|
-
return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
35
|
-
render: /* @__PURE__ */ jsx("button", {
|
|
36
|
-
type: "button",
|
|
37
|
-
"aria-label": label ?? messages.form.moreInfo,
|
|
38
|
-
className: "asu:inline-flex asu:text-muted-foreground"
|
|
39
|
-
}),
|
|
40
|
-
children: /* @__PURE__ */ jsx(InfoIcon, { className: "asu:size-3.5" })
|
|
41
|
-
}), /* @__PURE__ */ jsx(TooltipContent, { children: content })] });
|
|
42
|
-
}
|
|
43
|
-
function FormItem({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, layout = "stacked", children }) {
|
|
44
|
-
const { name, invalid, errors, touched, dirty } = useFieldState();
|
|
45
|
-
const labelRow = label && /* @__PURE__ */ jsxs("div", {
|
|
46
|
-
className: "asu:flex asu:items-center asu:gap-1",
|
|
47
|
-
children: [/* @__PURE__ */ jsxs(FieldLabel, { children: [label, optional && /* @__PURE__ */ jsx(OptionalMarker, { label: optionalLabel })] }), labelTooltip && /* @__PURE__ */ jsx(LabelTooltip, {
|
|
48
|
-
content: labelTooltip,
|
|
49
|
-
label: moreInfoLabel
|
|
50
|
-
})]
|
|
51
|
-
});
|
|
52
|
-
return /* @__PURE__ */ jsxs(Field, {
|
|
53
|
-
name,
|
|
54
|
-
invalid,
|
|
55
|
-
touched,
|
|
56
|
-
dirty,
|
|
57
|
-
className,
|
|
58
|
-
"data-slot": "form-item",
|
|
59
|
-
children: [
|
|
60
|
-
layout === "stacked" ? /* @__PURE__ */ jsxs(Fragment, { children: [labelRow, children] }) : /* @__PURE__ */ jsx("div", {
|
|
61
|
-
className: "asu:flex asu:flex-row asu:items-center asu:gap-2.5",
|
|
62
|
-
children: layout === "inline-end" ? /* @__PURE__ */ jsxs(Fragment, { children: [labelRow, children] }) : /* @__PURE__ */ jsxs(Fragment, { children: [children, labelRow] })
|
|
63
|
-
}),
|
|
64
|
-
description && /* @__PURE__ */ jsx(FieldDescription, { children: description }),
|
|
65
|
-
invalid && /* @__PURE__ */ jsx(FieldError, {
|
|
66
|
-
match: true,
|
|
67
|
-
children: errors.map((message) => /* @__PURE__ */ jsx("span", {
|
|
68
|
-
className: "asu:block",
|
|
69
|
-
children: message
|
|
70
|
-
}, message))
|
|
71
|
-
})
|
|
72
|
-
]
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
//#endregion
|
|
76
|
-
export { FormItem, LabelTooltip, OptionalMarker, useFieldState };
|
|
27
|
+
export { FormItem, useFieldState };
|
|
@@ -3,7 +3,6 @@ import { DatePickerField, DateRangePickerField } from "./date-fields.js";
|
|
|
3
3
|
import { SubmitButton } from "./submit-button.js";
|
|
4
4
|
import { TextField, TextareaField } from "./text-field.js";
|
|
5
5
|
import { CheckboxField, RadioGroupField, SwitchField } from "./toggle-fields.js";
|
|
6
|
-
//#region src/components/form/form.d.ts
|
|
7
6
|
/**
|
|
8
7
|
* The field components registered with `useAppForm` by default. Extend them with your own
|
|
9
8
|
* fields by spreading this into a new `createFormHook` call:
|
|
@@ -118,5 +117,4 @@ export declare const useAppForm: <TFormData, TOnMount extends import("@tanstack/
|
|
|
118
117
|
SubmitButton: typeof SubmitButton;
|
|
119
118
|
}>;
|
|
120
119
|
fields: TFields;
|
|
121
|
-
}>) => ReturnType<import("react").FunctionComponent>;
|
|
122
|
-
//#endregion
|
|
120
|
+
}>) => ReturnType<import("react").FunctionComponent>;
|
|
@@ -6,7 +6,7 @@ import { SubmitButton } from "./submit-button.js";
|
|
|
6
6
|
import { TextField, TextareaField } from "./text-field.js";
|
|
7
7
|
import { CheckboxField, RadioGroupField, SwitchField } from "./toggle-fields.js";
|
|
8
8
|
import { createFormHook } from "@tanstack/react-form";
|
|
9
|
-
|
|
9
|
+
// src/components/form/form.ts
|
|
10
10
|
/**
|
|
11
11
|
* The field components registered with `useAppForm` by default. Extend them with your own
|
|
12
12
|
* fields by spreading this into a new `createFormHook` call:
|
|
@@ -42,5 +42,4 @@ const { useAppForm, withForm, withFieldGroup } = createFormHook({
|
|
|
42
42
|
fieldComponents,
|
|
43
43
|
formComponents
|
|
44
44
|
});
|
|
45
|
-
//#endregion
|
|
46
45
|
export { fieldComponents, formComponents, useAppForm, withFieldGroup, withForm };
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { Skeleton } from "../skeleton/skeleton.js";
|
|
3
3
|
import { Suspense, lazy } from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
|
|
5
|
+
// src/components/form/lazy-field-components.tsx
|
|
6
6
|
function loadOnDemand(load) {
|
|
7
7
|
const Lazy = lazy(load);
|
|
8
8
|
return function OnDemandField(props) {
|
|
9
9
|
return /* @__PURE__ */ jsx(Suspense, {
|
|
10
|
-
fallback: /* @__PURE__ */ jsx(Skeleton, { className: "
|
|
10
|
+
fallback: /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }),
|
|
11
11
|
children: /* @__PURE__ */ jsx(Lazy, { ...props })
|
|
12
12
|
});
|
|
13
13
|
};
|
|
@@ -15,5 +15,4 @@ function loadOnDemand(load) {
|
|
|
15
15
|
const LazySelectField = loadOnDemand(() => import("./choice-fields.js").then((m) => ({ default: m.SelectField })));
|
|
16
16
|
const LazyFormNumberField = loadOnDemand(() => import("./choice-fields.js").then((m) => ({ default: m.FormNumberField })));
|
|
17
17
|
const LazyComboboxField = loadOnDemand(() => import("./choice-fields.js").then((m) => ({ default: m.ComboboxField })));
|
|
18
|
-
//#endregion
|
|
19
18
|
export { LazyComboboxField, LazyFormNumberField, LazySelectField };
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import { ButtonProps } from "../button/button.js";
|
|
2
|
-
//#region src/components/form/submit-button.d.ts
|
|
3
2
|
export type SubmitButtonProps = Omit<ButtonProps, 'type' | 'loading'>;
|
|
4
|
-
export declare function SubmitButton(props: SubmitButtonProps): import("react").JSX.Element;
|
|
5
|
-
//#endregion
|
|
3
|
+
export declare function SubmitButton(props: SubmitButtonProps): import("react").JSX.Element;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Button } from "../button/button.js";
|
|
3
3
|
import { useFormContext } from "./form-context.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
|
|
5
|
+
// src/components/form/submit-button.tsx
|
|
6
6
|
function SubmitButton(props) {
|
|
7
7
|
const form = useFormContext();
|
|
8
8
|
return /* @__PURE__ */ jsx(form.Subscribe, {
|
|
@@ -15,5 +15,4 @@ function SubmitButton(props) {
|
|
|
15
15
|
})
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
|
-
//#endregion
|
|
19
18
|
export { SubmitButton };
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { FormItemProps } from "./form-item.js";
|
|
2
2
|
import { InputProps } from "../input/input.js";
|
|
3
3
|
import { TextareaProps } from "../textarea/textarea.js";
|
|
4
|
-
//#region src/components/form/text-field.d.ts
|
|
5
4
|
export type TextFieldProps = Omit<FormItemProps, 'layout'> & Omit<InputProps, 'name' | 'value' | 'defaultValue' | 'onValueChange' | 'onBlur' | 'className'>;
|
|
6
5
|
export declare function TextField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...inputProps }: TextFieldProps): import("react").JSX.Element;
|
|
7
6
|
export type TextareaFieldProps = Omit<FormItemProps, 'layout'> & Omit<TextareaProps, 'name' | 'value' | 'defaultValue' | 'onValueChange' | 'onBlur' | 'className'>;
|
|
8
|
-
export declare function TextareaField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...textareaProps }: TextareaFieldProps): import("react").JSX.Element;
|
|
9
|
-
//#endregion
|
|
7
|
+
export declare function TextareaField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...textareaProps }: TextareaFieldProps): import("react").JSX.Element;
|
|
@@ -4,7 +4,7 @@ import { Textarea } from "../textarea/textarea.js";
|
|
|
4
4
|
import { useFieldContext } from "./form-context.js";
|
|
5
5
|
import { FormItem } from "./form-item.js";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
|
-
|
|
7
|
+
// src/components/form/text-field.tsx
|
|
8
8
|
function TextField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...inputProps }) {
|
|
9
9
|
const field = useFieldContext();
|
|
10
10
|
return /* @__PURE__ */ jsx(FormItem, {
|
|
@@ -43,5 +43,4 @@ function TextareaField({ label, description, labelTooltip, optional, optionalLab
|
|
|
43
43
|
})
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
|
-
//#endregion
|
|
47
46
|
export { TextField, TextareaField };
|
|
@@ -2,7 +2,6 @@ import { FormItemProps } from "./form-item.js";
|
|
|
2
2
|
import { CheckboxProps } from "../checkbox/checkbox.js";
|
|
3
3
|
import { SwitchProps } from "../switch/switch.js";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
|
-
//#region src/components/form/toggle-fields.d.ts
|
|
6
5
|
export type CheckboxFieldProps = Omit<FormItemProps, 'layout'> & Omit<CheckboxProps, 'name' | 'checked' | 'defaultChecked' | 'onCheckedChange' | 'onBlur' | 'className'>;
|
|
7
6
|
export declare function CheckboxField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...checkboxProps }: CheckboxFieldProps): import("react").JSX.Element;
|
|
8
7
|
export type SwitchFieldProps = Omit<FormItemProps, 'layout'> & Omit<SwitchProps, 'name' | 'checked' | 'defaultChecked' | 'onCheckedChange' | 'onBlur' | 'className'>;
|
|
@@ -16,5 +15,4 @@ export type RadioGroupFieldProps = Omit<FormItemProps, 'layout'> & {
|
|
|
16
15
|
disabled?: boolean;
|
|
17
16
|
orientation?: 'horizontal' | 'vertical';
|
|
18
17
|
};
|
|
19
|
-
export declare function RadioGroupField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, options, disabled, orientation }: RadioGroupFieldProps): import("react").JSX.Element;
|
|
20
|
-
//#endregion
|
|
18
|
+
export declare function RadioGroupField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, options, disabled, orientation }: RadioGroupFieldProps): import("react").JSX.Element;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../lib/cn.js";
|
|
3
3
|
import { Checkbox } from "../checkbox/checkbox.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FieldLabel } from "../field/field.js";
|
|
5
5
|
import { RadioGroup, RadioGroupItem } from "../radio-group/radio-group.js";
|
|
6
6
|
import { Switch } from "../switch/switch.js";
|
|
7
7
|
import { useFieldContext } from "./form-context.js";
|
|
8
|
-
import { FormItem
|
|
8
|
+
import { FormItem } from "./form-item.js";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
import { Field } from "@base-ui/react/field";
|
|
11
|
-
|
|
11
|
+
// src/components/form/toggle-fields.tsx
|
|
12
12
|
function CheckboxField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, ...checkboxProps }) {
|
|
13
13
|
const field = useFieldContext();
|
|
14
14
|
return /* @__PURE__ */ jsx(FormItem, {
|
|
@@ -51,50 +51,34 @@ function SwitchField({ label, description, labelTooltip, optional, optionalLabel
|
|
|
51
51
|
}
|
|
52
52
|
function RadioGroupField({ label, description, labelTooltip, optional, optionalLabel, moreInfoLabel, className, options, disabled, orientation }) {
|
|
53
53
|
const field = useFieldContext();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
return /* @__PURE__ */ jsx(FormItem, {
|
|
55
|
+
label,
|
|
56
|
+
description,
|
|
57
|
+
labelTooltip,
|
|
58
|
+
optional,
|
|
59
|
+
optionalLabel,
|
|
60
|
+
moreInfoLabel,
|
|
60
61
|
className,
|
|
61
|
-
|
|
62
|
-
children:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
/* @__PURE__ */ jsx(RadioGroupItem, { value: option.value }),
|
|
82
|
-
" ",
|
|
83
|
-
option.label
|
|
84
|
-
]
|
|
85
|
-
})
|
|
86
|
-
}, option.value))
|
|
87
|
-
})] }),
|
|
88
|
-
description && /* @__PURE__ */ jsx(FieldDescription, { children: description }),
|
|
89
|
-
invalid && /* @__PURE__ */ jsx(FieldError, {
|
|
90
|
-
match: true,
|
|
91
|
-
children: errors.map((message) => /* @__PURE__ */ jsx("span", {
|
|
92
|
-
className: "asu:block",
|
|
93
|
-
children: message
|
|
94
|
-
}, message))
|
|
95
|
-
})
|
|
96
|
-
]
|
|
62
|
+
group: true,
|
|
63
|
+
children: /* @__PURE__ */ jsx(RadioGroup, {
|
|
64
|
+
value: field.state.value ?? null,
|
|
65
|
+
onValueChange: (value) => field.handleChange(value),
|
|
66
|
+
onBlur: field.handleBlur,
|
|
67
|
+
disabled,
|
|
68
|
+
"aria-orientation": orientation,
|
|
69
|
+
className: cn(orientation === "horizontal" && "flex-row flex-wrap gap-6"),
|
|
70
|
+
children: options.map((option) => /* @__PURE__ */ jsx(Field.Item, {
|
|
71
|
+
disabled: option.disabled,
|
|
72
|
+
children: /* @__PURE__ */ jsxs(FieldLabel, {
|
|
73
|
+
className: "font-normal",
|
|
74
|
+
children: [
|
|
75
|
+
/* @__PURE__ */ jsx(RadioGroupItem, { value: option.value }),
|
|
76
|
+
" ",
|
|
77
|
+
option.label
|
|
78
|
+
]
|
|
79
|
+
})
|
|
80
|
+
}, option.value))
|
|
81
|
+
})
|
|
97
82
|
});
|
|
98
83
|
}
|
|
99
|
-
//#endregion
|
|
100
84
|
export { CheckboxField, RadioGroupField, SwitchField };
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Input } from "@base-ui/react/input";
|
|
2
|
-
//#region src/components/input/input.d.ts
|
|
3
2
|
export type InputProps = Omit<Input.Props, 'className'> & {
|
|
4
3
|
className?: string;
|
|
5
4
|
};
|
|
6
5
|
declare function Input$1({ className, ...props }: InputProps): import("react").JSX.Element;
|
|
7
|
-
//#endregion
|
|
8
6
|
export { Input$1 as Input };
|
|
@@ -3,13 +3,12 @@ import { cn } from "../../lib/cn.js";
|
|
|
3
3
|
import { controlFocus, controlSurface } from "../../lib/control.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
import { Input } from "@base-ui/react/input";
|
|
6
|
-
|
|
6
|
+
// src/components/input/input.tsx
|
|
7
7
|
function Input$1({ className, ...props }) {
|
|
8
8
|
return /* @__PURE__ */ jsx(Input, {
|
|
9
|
-
className: cn(controlSurface, controlFocus, "
|
|
9
|
+
className: cn(controlSurface, controlFocus, "h-8 px-3 py-1", className),
|
|
10
10
|
...props,
|
|
11
11
|
"data-slot": "input"
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
|
-
//#endregion
|
|
15
14
|
export { Input$1 as Input };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ComponentProps } from "react";
|
|
2
|
-
//#region src/components/input-group/input-group.d.ts
|
|
3
2
|
export type InputGroupProps = ComponentProps<'div'>;
|
|
4
3
|
/** Joins an `Input` and a `Button` or an `InputGroupAddon` into one control: they touch, share one divider, and each keeps its own hover and focus. */
|
|
5
4
|
declare function InputGroup({ className, ...props }: InputGroupProps): import("react").JSX.Element;
|
|
@@ -9,5 +8,4 @@ export type InputGroupAddonProps = ComponentProps<'div'>;
|
|
|
9
8
|
* inside it loses its own surface and fills the block. It is drawn with a divider on the side that faces the field.
|
|
10
9
|
*/
|
|
11
10
|
declare function InputGroupAddon({ className, ...props }: InputGroupAddonProps): import("react").JSX.Element;
|
|
12
|
-
//#endregion
|
|
13
11
|
export { InputGroup, InputGroupAddon };
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../lib/cn.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
|
-
|
|
4
|
+
// src/components/input-group/input-group.tsx
|
|
5
5
|
const groupParts = [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
6
|
+
"isolate",
|
|
7
|
+
"[&>[data-slot]]:h-auto [&>[data-slot]]:rounded-none",
|
|
8
|
+
"[&>[data-slot]:first-child]:rounded-l-sm [&>[data-slot]:last-child]:rounded-r-sm [&>[data-slot]:not(:first-child)]:-ml-px",
|
|
9
|
+
"[&>[data-slot=input]]:relative [&>[data-slot=input]]:flex-1 [&>[data-slot=input]]:focus-visible:z-10",
|
|
10
|
+
"[&>[data-slot=button]]:focus-visible:relative [&>[data-slot=button]]:focus-visible:z-10",
|
|
11
|
+
"[&>[data-slot=input]+[data-slot][data-slot]]:border-l-transparent [&>[data-slot][data-slot]:has(+[data-slot=input])]:border-r-transparent",
|
|
12
|
+
"[&>[data-slot=input]:not(:focus-visible):not([aria-invalid=true]):has(+[data-slot=button]:is([data-variant=primary],[data-variant=secondary],[data-variant=destructive]))]:border-r-transparent [&>[data-slot=input]+[data-slot=button]:is([data-variant=primary],[data-variant=secondary],[data-variant=destructive])]:ml-0",
|
|
13
|
+
"[&>[data-slot=button]:is([data-variant=primary],[data-variant=secondary],[data-variant=destructive])+[data-slot=input]:not(:focus-visible):not([aria-invalid=true])]:border-l-transparent [&>[data-slot=button]:is([data-variant=primary],[data-variant=secondary],[data-variant=destructive])+[data-slot=input]]:ml-0",
|
|
14
|
+
"[&>[data-slot=input]+[data-slot=button][data-variant=outline]:focus-visible]:border-l-input [&>[data-slot=button][data-variant=outline]:focus-visible:has(+[data-slot=input])]:border-r-input"
|
|
15
15
|
].join(" ");
|
|
16
16
|
/** Joins an `Input` and a `Button` or an `InputGroupAddon` into one control: they touch, share one divider, and each keeps its own hover and focus. */
|
|
17
17
|
function InputGroup({ className, ...props }) {
|
|
18
18
|
return /* @__PURE__ */ jsx("div", {
|
|
19
|
-
className: cn("
|
|
19
|
+
className: cn("flex h-8 w-full items-stretch", groupParts, className),
|
|
20
20
|
...props,
|
|
21
21
|
"data-slot": "input-group"
|
|
22
22
|
});
|
|
@@ -27,10 +27,9 @@ function InputGroup({ className, ...props }) {
|
|
|
27
27
|
*/
|
|
28
28
|
function InputGroupAddon({ className, ...props }) {
|
|
29
29
|
return /* @__PURE__ */ jsx("div", {
|
|
30
|
-
className: cn("
|
|
30
|
+
className: cn("flex shrink-0 items-center border border-input bg-muted px-3 text-sm text-muted-foreground", "overflow-hidden [&_[data-slot=button]]:-mx-3 [&_[data-slot=button]]:h-full [&_[data-slot=button]]:rounded-none [&_[data-slot=button]]:border-0 [&_[data-slot=button]]:focus-visible:ring-inset [&_[data-slot=button]]:focus-visible:ring-ring [&_[data-slot=button]]:bg-transparent [&_[data-slot=button]]:text-foreground [&_[data-slot=button]]:hover:bg-accent", className),
|
|
31
31
|
...props,
|
|
32
32
|
"data-slot": "input-group-addon"
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
//#endregion
|
|
36
35
|
export { InputGroup, InputGroupAddon };
|