haze-ui 1.13.0 → 1.15.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 +54 -1
- package/dist/form/FormItem.js +33 -22
- package/dist/types/components/Alert/Alert.d.ts +2 -2
- package/dist/types/components/Banner/Banner.d.ts +2 -2
- package/dist/types/components/BottomSheet/BottomSheet.d.ts +2 -2
- package/dist/types/components/Carousel/Carousel.d.ts +2 -2
- package/dist/types/components/ChatInput/ChatInput.d.ts +2 -2
- package/dist/types/components/Checkbox/Checkbox.d.ts +2 -2
- package/dist/types/components/Collapsible/Collapsible.d.ts +2 -2
- package/dist/types/components/ColorPicker/ColorPicker.d.ts +2 -2
- package/dist/types/components/Combobox/Combobox.d.ts +3 -3
- package/dist/types/components/Command/Command.d.ts +2 -2
- package/dist/types/components/ConfirmDialog/ConfirmDialog.d.ts +2 -2
- package/dist/types/components/ContextMenu/ContextMenu.d.ts +2 -2
- package/dist/types/components/DateRangePicker/DateRangePicker.d.ts +3 -3
- package/dist/types/components/Datepicker/Datepicker.d.ts +3 -3
- package/dist/types/components/Dialog/Dialog.d.ts +2 -2
- package/dist/types/components/Disclosure/Disclosure.d.ts +2 -2
- package/dist/types/components/Drawer/Drawer.d.ts +2 -2
- package/dist/types/components/DropdownMenu/DropdownMenu.d.ts +2 -2
- package/dist/types/components/InlineEdit/InlineEdit.d.ts +2 -2
- package/dist/types/components/Input/Input.d.ts +2 -2
- package/dist/types/components/LogViewer/LogViewer.d.ts +2 -2
- package/dist/types/components/Menu/Menu.d.ts +2 -2
- package/dist/types/components/ModelPicker/ModelPicker.d.ts +2 -2
- package/dist/types/components/NumberInput/NumberInput.d.ts +2 -2
- package/dist/types/components/OTPInput/OTPInput.d.ts +2 -2
- package/dist/types/components/Pagination/Pagination.d.ts +2 -2
- package/dist/types/components/PasswordInput/PasswordInput.d.ts +2 -2
- package/dist/types/components/Popover/Popover.d.ts +2 -2
- package/dist/types/components/Radio/RadioGroup.d.ts +2 -2
- package/dist/types/components/Rating/Rating.d.ts +2 -2
- package/dist/types/components/Segmented/Segmented.d.ts +2 -2
- package/dist/types/components/Select/Select.d.ts +2 -2
- package/dist/types/components/Slider/Slider.d.ts +2 -2
- package/dist/types/components/Stepper/Stepper.d.ts +2 -2
- package/dist/types/components/Switch/Switch.d.ts +2 -2
- package/dist/types/components/Tabs/Tabs.d.ts +2 -2
- package/dist/types/components/TagInput/TagInput.d.ts +2 -2
- package/dist/types/components/Textarea/Textarea.d.ts +2 -2
- package/dist/types/components/TimePicker/TimePicker.d.ts +2 -2
- package/dist/types/components/Tooltip/Tooltip.d.ts +2 -2
- package/dist/types/components/Transfer/Transfer.d.ts +2 -2
- package/dist/types/components/Tree/types.d.ts +4 -4
- package/dist/types/form/FormItem.d.ts +70 -4
- package/dist/types/form/index.d.ts +1 -1
- package/dist/types/index.d.ts +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ views: controlled cores (`InputCore`, `SelectCore`, `SwitchCore`,
|
|
|
58
58
|
`TextareaCore`, `TagInputCore`, ...) take the plain `{value, onChange}`
|
|
59
59
|
pair with zero adapters, and `FormItem` wraps the hook's state in label,
|
|
60
60
|
error and aria wiring. The sugar components (`Input`, `Select`, ...)
|
|
61
|
-
keep their `Control<T> | T` API for standalone use outside forms.
|
|
61
|
+
keep their `ControlOrValue<T>` (`Control<T> | T`) API for standalone use outside forms.
|
|
62
62
|
|
|
63
63
|
### useField: field → {value, onChange}
|
|
64
64
|
|
|
@@ -154,6 +154,59 @@ render-prop are mutually exclusive.
|
|
|
154
154
|
- With a typed form, `validate`'s value argument is the field's actual
|
|
155
155
|
type (`PathValueOf<TValues, P>`), not `any`.
|
|
156
156
|
|
|
157
|
+
#### `input`: declarative binding for haze-ui cores (typed prop forwarding)
|
|
158
|
+
|
|
159
|
+
The ergonomic form for the controlled cores — pass the component and the
|
|
160
|
+
rest of the JSX goes straight to it, type-checked against its own props:
|
|
161
|
+
|
|
162
|
+
```jsx
|
|
163
|
+
<FormItem
|
|
164
|
+
form={form}
|
|
165
|
+
name="email"
|
|
166
|
+
label="Email"
|
|
167
|
+
input={InputCore}
|
|
168
|
+
placeholder="you@x.dev"
|
|
169
|
+
mode="onBlur"
|
|
170
|
+
validate={(v) => (v.includes('@') ? undefined : 'must be an email')}
|
|
171
|
+
/>
|
|
172
|
+
|
|
173
|
+
// JSX children forward too — a SelectCore's options:
|
|
174
|
+
<FormItem form={form} name="role" label="Role" input={SelectCore}>
|
|
175
|
+
<option value="admin">Admin</option>
|
|
176
|
+
<option value="viewer">Viewer</option>
|
|
177
|
+
</FormItem>
|
|
178
|
+
|
|
179
|
+
// checkbox-style controls keep the valueToProps adapter:
|
|
180
|
+
<FormItem
|
|
181
|
+
form={form}
|
|
182
|
+
name="subscribed"
|
|
183
|
+
label="Subscribe"
|
|
184
|
+
input={CheckboxCore}
|
|
185
|
+
valueToProps={(checked) => ({ checked })}
|
|
186
|
+
/>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`input` wires the same id/aria/`onBlur`/`onChange`/value contract as `as`
|
|
190
|
+
— every haze core (`InputCore`, `TextareaCore`, `SelectCore`,
|
|
191
|
+
`TagInputCore`, `CheckboxCore`, `SwitchCore`, …) speaks the plain
|
|
192
|
+
`{value, onChange}` pair, so the default adapters need nothing
|
|
193
|
+
(`TagInputCore`'s `onChange` already emits the next `string[]`; a
|
|
194
|
+
checkbox-style core pairs with `valueToProps`). The differences from
|
|
195
|
+
`as`:
|
|
196
|
+
|
|
197
|
+
- Forwarded props are **type-checked against the core's own props** —
|
|
198
|
+
`input={InputCore} size="xl"` is a compile error, while `asProps` is an
|
|
199
|
+
untyped bag.
|
|
200
|
+
- JSX **children** forward to the core (a `SelectCore`'s `<option>`s);
|
|
201
|
+
the render-prop children and `input` are mutually exclusive (a
|
|
202
|
+
render-prop next to `input` throws — it's a migration leftover).
|
|
203
|
+
- The wiring (`id`, `aria-invalid`, `aria-describedby`, `onBlur`,
|
|
204
|
+
`onChange`, `value`/`checked`) and FormItem's own prop names are
|
|
205
|
+
**reserved**: they are excluded from the forwarded type and always win
|
|
206
|
+
at runtime. A control prop that collides with one (e.g. CheckboxCore's
|
|
207
|
+
own `label`) is unreachable through `input` — use the render-prop or
|
|
208
|
+
`as`/`asProps` for it.
|
|
209
|
+
|
|
157
210
|
#### `mode`: per-field validation timing (react-f0rm ≥ 0.6)
|
|
158
211
|
|
|
159
212
|
Pass `mode` to validate one field on its own schedule instead of the
|
package/dist/form/FormItem.js
CHANGED
|
@@ -6,8 +6,8 @@ import { useId as r } from "react";
|
|
|
6
6
|
import { useField as i } from "react-f0rm";
|
|
7
7
|
//#region src/lib/form/FormItem.tsx
|
|
8
8
|
var a = "haze-FormItem__item", o = "haze-FormItem__labelText", s = "haze-FormItem__errorText";
|
|
9
|
-
function c({ form: c, name: l, label: u, validate: d, mode: f, validateDebounce: p, delayError: m, rules: h, className: g, renderError: _, as: v, asProps: y,
|
|
10
|
-
let
|
|
9
|
+
function c({ form: c, name: l, label: u, validate: d, mode: f, validateDebounce: p, delayError: m, rules: h, className: g, renderError: _, as: v, asProps: y, input: b, eventToValue: x, valueToProps: S, children: C, ...w }) {
|
|
10
|
+
let T = `haze-field-${r()}`, E = `${T}-error`, { value: D, onChange: O, onBlur: k, errors: A } = i({
|
|
11
11
|
form: c,
|
|
12
12
|
name: l,
|
|
13
13
|
validate: d,
|
|
@@ -15,37 +15,48 @@ function c({ form: c, name: l, label: u, validate: d, mode: f, validateDebounce:
|
|
|
15
15
|
validateDebounce: p,
|
|
16
16
|
delayError: m,
|
|
17
17
|
rules: h
|
|
18
|
-
}),
|
|
18
|
+
}), j = A.length > 0, M = x ?? ((e) => e);
|
|
19
|
+
if (b && typeof C == "function") throw Error("FormItem: `input` and the render-prop `children` are mutually exclusive — the input component is wired declaratively; remove the render-prop.");
|
|
20
|
+
let N = b;
|
|
19
21
|
return /* @__PURE__ */ n("div", {
|
|
20
22
|
className: e([a, g]),
|
|
21
23
|
children: [
|
|
22
24
|
u !== void 0 && /* @__PURE__ */ t("label", {
|
|
23
|
-
htmlFor:
|
|
25
|
+
htmlFor: T,
|
|
24
26
|
className: e(o),
|
|
25
27
|
children: u
|
|
26
28
|
}),
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"aria-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
N ? /* @__PURE__ */ t(N, {
|
|
30
|
+
...w,
|
|
31
|
+
id: T,
|
|
32
|
+
"aria-invalid": j || void 0,
|
|
33
|
+
"aria-describedby": j ? E : void 0,
|
|
34
|
+
onBlur: k,
|
|
35
|
+
onChange: (e) => O(M(e)),
|
|
36
|
+
...S ? S(D) : { value: D },
|
|
37
|
+
children: C
|
|
38
|
+
}) : v ? /* @__PURE__ */ t(v, {
|
|
39
|
+
id: T,
|
|
40
|
+
"aria-invalid": j || void 0,
|
|
41
|
+
"aria-describedby": j ? E : void 0,
|
|
42
|
+
onBlur: k,
|
|
43
|
+
onChange: (e) => O(M(e)),
|
|
33
44
|
...y,
|
|
34
|
-
...
|
|
35
|
-
}) :
|
|
36
|
-
id:
|
|
37
|
-
errorId:
|
|
38
|
-
invalid:
|
|
39
|
-
errors:
|
|
40
|
-
onBlur:
|
|
41
|
-
value:
|
|
42
|
-
onChange:
|
|
45
|
+
...S ? S(D) : { value: D }
|
|
46
|
+
}) : C({
|
|
47
|
+
id: T,
|
|
48
|
+
errorId: E,
|
|
49
|
+
invalid: j,
|
|
50
|
+
errors: A,
|
|
51
|
+
onBlur: k,
|
|
52
|
+
value: D,
|
|
53
|
+
onChange: O
|
|
43
54
|
}),
|
|
44
|
-
|
|
45
|
-
id:
|
|
55
|
+
j && /* @__PURE__ */ t("span", {
|
|
56
|
+
id: E,
|
|
46
57
|
role: "alert",
|
|
47
58
|
className: e(s),
|
|
48
|
-
children: _ ? _(
|
|
59
|
+
children: _ ? _(A[0].message, E) : A[0].message
|
|
49
60
|
})
|
|
50
61
|
]
|
|
51
62
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type AlertProps = {
|
|
4
|
-
visible?:
|
|
4
|
+
visible?: ControlOrValue<boolean>;
|
|
5
5
|
onClose?: () => void;
|
|
6
6
|
variant?: 'info' | 'success' | 'warning' | 'danger';
|
|
7
7
|
closable?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type BannerProps = {
|
|
4
|
-
visible?:
|
|
4
|
+
visible?: ControlOrValue<boolean>;
|
|
5
5
|
onClose?: () => void;
|
|
6
6
|
variant?: 'info' | 'success' | 'warning' | 'danger';
|
|
7
7
|
children: ReactNode;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type BottomSheetProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
onClose?: () => void;
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
className?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type CarouselProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<number>;
|
|
5
5
|
autoPlay?: boolean;
|
|
6
6
|
interval?: number;
|
|
7
7
|
className?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type ChatInputProps = {
|
|
3
|
-
value?:
|
|
3
|
+
value?: ControlOrValue<string>;
|
|
4
4
|
onSend?: (message: string) => void;
|
|
5
5
|
placeholder?: string;
|
|
6
6
|
disabled?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type CheckboxProps = {
|
|
4
|
-
checked?:
|
|
4
|
+
checked?: ControlOrValue<boolean>;
|
|
5
5
|
label?: ReactNode;
|
|
6
6
|
} & Omit<ComponentPropsWithoutRef<'input'>, 'checked' | 'type'>;
|
|
7
7
|
export default function Checkbox({ checked: checkedControl, className, label, onChange, ...rest }: CheckboxProps): import("react").JSX.Element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type CollapsibleProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
defaultOpen?: boolean;
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
className?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type ColorPickerProps = {
|
|
3
|
-
value?:
|
|
3
|
+
value?: ControlOrValue<string>;
|
|
4
4
|
presets?: string[];
|
|
5
5
|
onChange?: (color: string) => void;
|
|
6
6
|
className?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type ComboboxProps = {
|
|
3
|
-
value?:
|
|
4
|
-
open?:
|
|
3
|
+
value?: ControlOrValue<string>;
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
options: {
|
|
6
6
|
value: string;
|
|
7
7
|
label: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type CommandProps = {
|
|
4
|
-
query?:
|
|
4
|
+
query?: ControlOrValue<string>;
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
className?: string;
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type ConfirmDialogProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
onClose?: () => void;
|
|
6
6
|
onConfirm?: () => void;
|
|
7
7
|
onCancel?: () => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type ContextMenuProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
onOpenChange?: (open: boolean) => void;
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
className?: string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type DateRangePickerProps = {
|
|
4
|
-
startDate?:
|
|
5
|
-
endDate?:
|
|
4
|
+
startDate?: ControlOrValue<string>;
|
|
5
|
+
endDate?: ControlOrValue<string>;
|
|
6
6
|
onStartChange?: (value: string) => void;
|
|
7
7
|
onEndChange?: (value: string) => void;
|
|
8
8
|
separator?: ReactNode;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type DatepickerProps = {
|
|
3
|
-
value?:
|
|
4
|
-
open?:
|
|
3
|
+
value?: ControlOrValue<string>;
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
min?: string;
|
|
6
6
|
max?: string;
|
|
7
7
|
placeholder?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type DialogProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
onClose?: () => void;
|
|
6
6
|
/**
|
|
7
7
|
* 对话框标题:渲染为 h2 并以生成的 id 关联 dialog 的
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type DisclosureProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
summary: ReactNode;
|
|
6
6
|
className?: string;
|
|
7
7
|
children: ReactNode;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type DrawerProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
placement?: 'left' | 'right' | 'top' | 'bottom';
|
|
6
6
|
onClose?: () => void;
|
|
7
7
|
className?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type DropdownMenuProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
onOpenChange?: (open: boolean) => void;
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
className?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type InlineEditProps = {
|
|
3
|
-
value?:
|
|
3
|
+
value?: ControlOrValue<string>;
|
|
4
4
|
onChange?: (value: string) => void;
|
|
5
5
|
placeholder?: string;
|
|
6
6
|
disabled?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type InputProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<string>;
|
|
5
5
|
size?: 'sm' | 'md' | 'lg';
|
|
6
6
|
} & Omit<ComponentPropsWithoutRef<'input'>, 'value' | 'size'>;
|
|
7
7
|
export default function Input({ value: valueControl, size, className, onChange, ...rest }: InputProps): import("react").JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
3
3
|
type LogEntry = {
|
|
4
4
|
level: LogLevel;
|
|
@@ -7,7 +7,7 @@ type LogEntry = {
|
|
|
7
7
|
};
|
|
8
8
|
type LogViewerProps = {
|
|
9
9
|
logs: LogEntry[];
|
|
10
|
-
filter?:
|
|
10
|
+
filter?: ControlOrValue<LogLevel | null>;
|
|
11
11
|
className?: string;
|
|
12
12
|
};
|
|
13
13
|
export default function LogViewer({ logs, filter: filterControl, className }: LogViewerProps): import("react").JSX.Element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type MenuProps = {
|
|
4
|
-
open?:
|
|
4
|
+
open?: ControlOrValue<boolean>;
|
|
5
5
|
trigger?: ReactNode;
|
|
6
6
|
className?: string;
|
|
7
7
|
children: ReactNode;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type ModelOption = {
|
|
3
3
|
value: string;
|
|
4
4
|
label: string;
|
|
@@ -6,7 +6,7 @@ type ModelOption = {
|
|
|
6
6
|
contextLength?: string;
|
|
7
7
|
};
|
|
8
8
|
type ModelPickerProps = {
|
|
9
|
-
value?:
|
|
9
|
+
value?: ControlOrValue<string>;
|
|
10
10
|
onChange?: (value: string) => void;
|
|
11
11
|
options: ModelOption[];
|
|
12
12
|
disabled?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type NumberInputProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<number>;
|
|
5
5
|
min?: number;
|
|
6
6
|
max?: number;
|
|
7
7
|
step?: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type OTPInputProps = {
|
|
3
3
|
length?: number;
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<string>;
|
|
5
5
|
onChange?: (value: string) => void;
|
|
6
6
|
className?: string;
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type PaginationProps = {
|
|
4
|
-
page?:
|
|
4
|
+
page?: ControlOrValue<number>;
|
|
5
5
|
total: number;
|
|
6
6
|
pageSize?: number;
|
|
7
7
|
size?: 'sm' | 'md' | 'lg';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type PasswordInputProps = {
|
|
3
|
-
value?:
|
|
3
|
+
value?: ControlOrValue<string>;
|
|
4
4
|
onChange?: (value: string) => void;
|
|
5
5
|
placeholder?: string;
|
|
6
6
|
disabled?: boolean;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type PopoverProps = {
|
|
4
4
|
content: ReactNode;
|
|
5
|
-
open?:
|
|
5
|
+
open?: ControlOrValue<boolean>;
|
|
6
6
|
className?: string;
|
|
7
7
|
children: ReactNode;
|
|
8
8
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type RadioGroupProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<string>;
|
|
5
5
|
name?: string;
|
|
6
6
|
className?: string;
|
|
7
7
|
children: ReactNode;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type RatingProps = {
|
|
3
|
-
value?:
|
|
3
|
+
value?: ControlOrValue<number>;
|
|
4
4
|
count?: number;
|
|
5
5
|
allowHalf?: boolean;
|
|
6
6
|
onChange?: (value: number) => void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
import type { SegmentedOption } from './SegmentedCore';
|
|
3
3
|
type SegmentedProps = {
|
|
4
4
|
options: SegmentedOption[];
|
|
5
|
-
value?:
|
|
5
|
+
value?: ControlOrValue<string>;
|
|
6
6
|
onChange?: (value: string) => void;
|
|
7
7
|
size?: 'sm' | 'md' | 'lg';
|
|
8
8
|
className?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type SelectProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<string>;
|
|
5
5
|
size?: 'sm' | 'md' | 'lg';
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
} & Omit<ComponentPropsWithoutRef<'select'>, 'value' | 'size'>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type SliderProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<number>;
|
|
5
5
|
} & Omit<ComponentPropsWithoutRef<'input'>, 'type' | 'value'>;
|
|
6
6
|
export default function Slider({ value: valueControl, className, onChange, ...rest }: SliderProps): import("react").JSX.Element;
|
|
7
7
|
export type { SliderProps };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type StepperProps = {
|
|
4
|
-
activeStep?:
|
|
4
|
+
activeStep?: ControlOrValue<number>;
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
className?: string;
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type SwitchProps = {
|
|
4
|
-
checked?:
|
|
4
|
+
checked?: ControlOrValue<boolean>;
|
|
5
5
|
size?: 'sm' | 'md' | 'lg';
|
|
6
6
|
} & Omit<ComponentPropsWithoutRef<'button'>, 'type' | 'checked' | 'onChange'>;
|
|
7
7
|
export default function Switch({ checked: checkedControl, size, className, onClick, ...rest }: SwitchProps): import("react").JSX.Element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type TabsProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<string>;
|
|
5
5
|
className?: string;
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type TagInputProps = {
|
|
3
|
-
value?:
|
|
3
|
+
value?: ControlOrValue<string[]>;
|
|
4
4
|
onChange?: (value: string[]) => void;
|
|
5
5
|
placeholder?: string;
|
|
6
6
|
maxTags?: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type TextareaProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<string>;
|
|
5
5
|
size?: 'sm' | 'md' | 'lg';
|
|
6
6
|
} & Omit<ComponentPropsWithoutRef<'textarea'>, 'value'>;
|
|
7
7
|
export default function Textarea({ value: valueControl, size, className, onChange, ...rest }: TextareaProps): import("react").JSX.Element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type TimePickerProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: ControlOrValue<string>;
|
|
5
5
|
onChange?: (value: string) => void;
|
|
6
6
|
placeholder?: string;
|
|
7
7
|
className?: string;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
type TooltipProps = {
|
|
4
4
|
content: ReactNode;
|
|
5
5
|
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
6
6
|
/** Milliseconds of hover/focus before the tooltip appears. */
|
|
7
7
|
delay?: number;
|
|
8
|
-
open?:
|
|
8
|
+
open?: ControlOrValue<boolean>;
|
|
9
9
|
className?: string;
|
|
10
10
|
children: ReactNode;
|
|
11
11
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
2
2
|
type TransferItem = {
|
|
3
3
|
key: string;
|
|
4
4
|
title: string;
|
|
@@ -6,7 +6,7 @@ type TransferItem = {
|
|
|
6
6
|
};
|
|
7
7
|
type TransferProps = {
|
|
8
8
|
dataSource: TransferItem[];
|
|
9
|
-
targetKeys?:
|
|
9
|
+
targetKeys?: ControlOrValue<string[]>;
|
|
10
10
|
onChange?: (targetKeys: string[], direction: 'left' | 'right', moveKeys: string[]) => void;
|
|
11
11
|
className?: string;
|
|
12
12
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ControlOrValue } from 'react-use-control';
|
|
3
3
|
/**
|
|
4
4
|
* Tree 节点数据接口
|
|
5
5
|
*/
|
|
@@ -63,11 +63,11 @@ export type TreeProps = {
|
|
|
63
63
|
/** 自定义节点图标渲染 */
|
|
64
64
|
iconRender?: (node: TreeNodeData) => ReactNode;
|
|
65
65
|
/** (受控)展开的节点 */
|
|
66
|
-
expandedKeys?:
|
|
66
|
+
expandedKeys?: ControlOrValue<string[]>;
|
|
67
67
|
/** (受控)选中的节点 */
|
|
68
|
-
selectedKeys?:
|
|
68
|
+
selectedKeys?: ControlOrValue<string[]>;
|
|
69
69
|
/** (受控)复选的节点 */
|
|
70
|
-
checkedKeys?:
|
|
70
|
+
checkedKeys?: ControlOrValue<string[]>;
|
|
71
71
|
/** 自定义类名 */
|
|
72
72
|
className?: string;
|
|
73
73
|
/** 展开/收起回调 */
|
|
@@ -62,7 +62,10 @@ export type FormItemAsProps = {
|
|
|
62
62
|
* passing `{value}`. */
|
|
63
63
|
valueToProps?: (value: any) => Record<string, any>;
|
|
64
64
|
};
|
|
65
|
-
|
|
65
|
+
/** FormItem's own, non-polymorphic props — everything the item itself
|
|
66
|
+
* consumes regardless of how the control is bound (render-prop, `as`
|
|
67
|
+
* or `input`). */
|
|
68
|
+
export type FormItemOwnProps<TValues extends Record<string, any> = any, P extends FieldPath<TValues> | Name = Name> = {
|
|
66
69
|
form: FormInstance<TValues>;
|
|
67
70
|
name: P;
|
|
68
71
|
label?: ReactNode;
|
|
@@ -95,14 +98,56 @@ export type FormItemProps<TValues extends Record<string, any> = any, P extends F
|
|
|
95
98
|
/** Custom error renderer: when provided and the field has errors, the
|
|
96
99
|
* built-in error span renders `renderError(errors[0].message, errorId)`
|
|
97
100
|
* instead of the bare message. The span itself — id, `role='alert'`,
|
|
98
|
-
* styling — stays FormItem's, in
|
|
101
|
+
* styling — stays FormItem's, in every control-binding mode. */
|
|
99
102
|
renderError?: (error: string, id: string) => ReactNode;
|
|
100
103
|
className?: string;
|
|
101
|
-
}
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Props FormItem wires itself onto an `input`/`as` control — the bridge's
|
|
107
|
+
* own contract. Used to keep them out of `input`'s forwarded rest props
|
|
108
|
+
* (type level) and to document that they always win (runtime level):
|
|
109
|
+
* passing one anyway is a compile error, never a silent override.
|
|
110
|
+
*/
|
|
111
|
+
type FormItemWiredProps = {
|
|
112
|
+
id?: unknown;
|
|
113
|
+
onBlur?: unknown;
|
|
114
|
+
onChange?: unknown;
|
|
115
|
+
/** the value channel: `value` directly, or the prop `valueToProps`
|
|
116
|
+
* derives (e.g. `checked` for CheckboxCore) — either way FormItem's */
|
|
117
|
+
value?: unknown;
|
|
118
|
+
checked?: unknown;
|
|
119
|
+
'aria-invalid'?: unknown;
|
|
120
|
+
'aria-describedby'?: unknown;
|
|
121
|
+
};
|
|
122
|
+
export type FormItemProps<TValues extends Record<string, any> = any, P extends FieldPath<TValues> | Name = Name, TInputProps extends Record<string, any> = Record<never, never>> = FormItemOwnProps<TValues, P> & FormItemAsProps & {
|
|
123
|
+
/**
|
|
124
|
+
* Declarative binding for haze-ui cores: pass the component
|
|
125
|
+
* (`InputCore`, `TextareaCore`, `TagInputCore`, `SelectCore`,
|
|
126
|
+
* `CheckboxCore`, …) and FormItem wires `id`, `aria-invalid`,
|
|
127
|
+
* `aria-describedby`, `onBlur`, `onChange` and the value channel
|
|
128
|
+
* itself. Every other prop — and JSX children (a `SelectCore`'s
|
|
129
|
+
* `<option>`s) — is forwarded to the component, fully type-checked
|
|
130
|
+
* against its own props. Cores' `onChange` emits the next plain value
|
|
131
|
+
* (identity `eventToValue`); checkbox-style controls pair with
|
|
132
|
+
* `valueToProps={(checked) => ({checked})}`. Props FormItem owns or
|
|
133
|
+
* wires (label, className, id, aria-*, onBlur, onChange, value,
|
|
134
|
+
* checked, …) are reserved and cannot be forwarded — use the
|
|
135
|
+
* render-prop or `as`/`asProps` for a colliding control prop.
|
|
136
|
+
*/
|
|
137
|
+
input?: ComponentType<TInputProps>;
|
|
138
|
+
} & Omit<TInputProps, keyof FormItemOwnProps<TValues, P> | keyof FormItemAsProps | keyof FormItemWiredProps | 'input'> & ({
|
|
102
139
|
as: ComponentType<any>;
|
|
140
|
+
input?: never;
|
|
103
141
|
children?: never;
|
|
104
142
|
} | {
|
|
105
143
|
as?: undefined;
|
|
144
|
+
input: ComponentType<TInputProps>;
|
|
145
|
+
/** JSX children forward to the control (SelectCore's options);
|
|
146
|
+
* the render-prop form is mutually exclusive with `input`. */
|
|
147
|
+
children?: 'children' extends keyof TInputProps ? TInputProps['children'] : undefined;
|
|
148
|
+
} | {
|
|
149
|
+
as?: undefined;
|
|
150
|
+
input?: undefined;
|
|
106
151
|
children: (binding: FormItemBinding<TValues, P>) => ReactNode;
|
|
107
152
|
});
|
|
108
153
|
/**
|
|
@@ -141,8 +186,29 @@ export type FormItemProps<TValues extends Record<string, any> = any, P extends F
|
|
|
141
186
|
* value lands as `{value}` or, with `valueToProps`, whatever props the
|
|
142
187
|
* control wants (e.g. `{checked}` for CheckboxCore).
|
|
143
188
|
*
|
|
189
|
+
* The ergonomic form for haze-ui cores is `input`: the rest of the JSX
|
|
190
|
+
* props — and JSX children, e.g. a `SelectCore`'s `<option>`s — are
|
|
191
|
+
* forwarded to the component, type-checked against its own props
|
|
192
|
+
* (`input` and the render-prop children are mutually exclusive):
|
|
193
|
+
*
|
|
194
|
+
* ```tsx
|
|
195
|
+
* <FormItem
|
|
196
|
+
* form={form}
|
|
197
|
+
* name='email'
|
|
198
|
+
* input={InputCore}
|
|
199
|
+
* placeholder='Email'
|
|
200
|
+
* mode='onBlur'
|
|
201
|
+
* />
|
|
202
|
+
* ```
|
|
203
|
+
*
|
|
204
|
+
* The same wiring as `as` applies (id, aria, onBlur, onChange, value);
|
|
205
|
+
* wired and FormItem-owned prop names are reserved — a control prop that
|
|
206
|
+
* collides (CheckboxCore's `label`) needs the render-prop or
|
|
207
|
+
* `as`/`asProps` channel.
|
|
208
|
+
*
|
|
144
209
|
* When the field has errors, the first error's message is rendered into a
|
|
145
210
|
* `<span id={errorId} role='alert'>` next to the control; with no errors
|
|
146
211
|
* no extra element is rendered.
|
|
147
212
|
*/
|
|
148
|
-
export default function FormItem<TValues extends Record<string, any> = any, P extends FieldPath<TValues> | Name = Name>({ form, name, label, validate, mode, validateDebounce, delayError, rules, className, renderError, as: As, asProps, eventToValue, valueToProps, children }: FormItemProps<TValues, P>): import("react").JSX.Element;
|
|
213
|
+
export default function FormItem<TValues extends Record<string, any> = any, P extends FieldPath<TValues> | Name = Name, TInputProps extends Record<string, any> = Record<never, never>>({ form, name, label, validate, mode, validateDebounce, delayError, rules, className, renderError, as: As, asProps, input: Input, eventToValue, valueToProps, children, ...inputProps }: FormItemProps<TValues, P, TInputProps>): import("react").JSX.Element;
|
|
214
|
+
export {};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { default as FormItem } from './FormItem';
|
|
2
|
-
export type { FieldValidator, FormItemAsProps, FormItemBinding, FormItemProps } from './FormItem';
|
|
2
|
+
export type { FieldValidator, FormItemAsProps, FormItemBinding, FormItemOwnProps, FormItemProps } from './FormItem';
|
|
3
3
|
export type { FormInstance, PathValueOf } from 'react-f0rm';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -182,5 +182,6 @@ export type { DiffViewerProps, DiffLine } from './components/DiffViewer';
|
|
|
182
182
|
export { LogViewer } from './components/LogViewer';
|
|
183
183
|
export type { LogViewerProps, LogEntry, LogLevel } from './components/LogViewer';
|
|
184
184
|
export { FormItem } from './form';
|
|
185
|
-
export type { FieldValidator, FormItemAsProps, FormItemBinding, FormItemProps, FormInstance, PathValueOf, } from './form';
|
|
185
|
+
export type { FieldValidator, FormItemAsProps, FormItemBinding, FormItemOwnProps, FormItemProps, FormInstance, PathValueOf, } from './form';
|
|
186
186
|
export { useControl } from 'react-use-control';
|
|
187
|
+
export type { Control, ControlOrValue } from 'react-use-control';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "haze-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A React UI component library powered by react-use-control and Linaria",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"react-f0rm": ">=0.7.0 <0.9.0"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"react-use-control": "^1.
|
|
58
|
+
"react-use-control": "^1.5.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@babel/core": "^8.0.1",
|