@andreyfedkovich/cozy-ui 0.8.0 → 0.9.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/CHANGELOG.md +8 -0
- package/README.md +85 -10
- package/dist-lib/index.d.ts +70 -24
- package/dist-lib/ui-library.cjs.js +12 -12
- package/dist-lib/ui-library.cjs.js.map +1 -1
- package/dist-lib/ui-library.es.js +3872 -3689
- package/dist-lib/ui-library.es.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
Формат основан на [Keep a Changelog](https://keepachangelog.com/).
|
|
4
4
|
Версии соответствуют [Semantic Versioning](https://semver.org/) и git-тегам `v*`.
|
|
5
5
|
|
|
6
|
+
## 0.9.0 - 2026-06-04
|
|
7
|
+
|
|
8
|
+
- **feat:** Единый контракт валидации полей — headless API: `FieldMeta`, `ShowErrorPolicy`, `resolveShowError`, `resolveFieldError`, `resolveFieldMessage`, `useFieldState`, `resolveValueChangeHandler`.
|
|
9
|
+
- **feat:** `Input`, `Textarea`, `Checkbox`, `Select`, `DialogSelect`, `TreeDialogSelect`, `Calendar` — пропсы `fieldMeta` и `showErrorPolicy`; явный `error` по-прежнему переопределяет meta. Дефолтная политика: `invalid && (touched || submitted || hasValue)`.
|
|
10
|
+
- **feat:** Общий A11y для полей — `aria-invalid`, `aria-describedby`, стабильные `id` через `useId()`, сообщение об ошибке с `role="alert"`.
|
|
11
|
+
- **feat:** Value picker’ы (`Select`, `DialogSelect`, `TreeDialogSelect`, `Calendar`) — канонический колбэк `onValueChange`; `onChange` оставлен как deprecated alias. На trigger добавлены `onBlur` / `onFocus` для интеграции с формами.
|
|
12
|
+
- **docs:** README — раздел Field validation, две семьи колбэков (native `onChange` vs picker `onValueChange`).
|
|
13
|
+
|
|
6
14
|
## 0.8.0 - 2026-06-02
|
|
7
15
|
|
|
8
16
|
- **feat:** Split published CSS into three entry points for Tailwind v3 host compatibility: `styles.css` (full bundle), `styles.modules.css` (SCSS modules only), and `styles.tailwind.css` (Tailwind v4 utilities). Existing `import "@andreyfedkovich/cozy-ui/styles.css"` is unchanged.
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ npm i @andreyfedkovich/cozy-ui
|
|
|
31
31
|
- [Design tokens](#design-tokens)
|
|
32
32
|
- [Component API](#component-api)
|
|
33
33
|
- [Layout & content](#layout--content) — `BaseBlock`, `Card`, `CollapsableBlock`, `Collapse`, `Carousel`, `EmptyComponent`, `Spinner`
|
|
34
|
-
- [Inputs & forms](#inputs--forms) — `Button`, `RadioGroupButton`, `Input`, `Textarea`, `Calendar`, `Checkbox`, `Select`, `DialogSelect`, `TreeDialogSelect`, `InputCaption`, `Label`
|
|
34
|
+
- [Inputs & forms](#inputs--forms) — field validation helpers, `Button`, `RadioGroupButton`, `Input`, `Textarea`, `Calendar`, `Checkbox`, `Select`, `DialogSelect`, `TreeDialogSelect`, `InputCaption`, `Label`
|
|
35
35
|
- [Navigation](#navigation) — `Tabs`, `TabsRounded`, `Stepper`
|
|
36
36
|
- [Overlays](#overlays) — `Popover`, `TooltipDark`, `TooltipLight`
|
|
37
37
|
- [Utility](#utility) — `Tag`, `CopyTextTrigger`
|
|
@@ -396,6 +396,59 @@ const [view, setView] = useState<"grid" | "list">("grid");
|
|
|
396
396
|
/>;
|
|
397
397
|
```
|
|
398
398
|
|
|
399
|
+
#### Field validation (headless)
|
|
400
|
+
|
|
401
|
+
Form state stays in your app (React Hook Form, TanStack Form, or `useState`). Cozy UI provides a shared **`FieldMeta`** contract and **`showErrorPolicy`** so all fields resolve “when to show the error” the same way.
|
|
402
|
+
|
|
403
|
+
| Export | Description |
|
|
404
|
+
| ------ | ----------- |
|
|
405
|
+
| `FieldMeta` | `touched`, `dirty`, `submitted`, `hasValue`, `invalid`, `errorMessage` |
|
|
406
|
+
| `ShowErrorPolicy` | `"default"` \| `"onBlur"` \| `"onSubmit"` \| `"always"` \| custom `(meta) => boolean` |
|
|
407
|
+
| `resolveShowError`, `resolveFieldError`, `resolveFieldMessage` | Pure functions (SSR-safe) |
|
|
408
|
+
| `useFieldState` | React hook wrapping the resolvers |
|
|
409
|
+
|
|
410
|
+
**Default policy:** `invalid && (touched || submitted || hasValue)`.
|
|
411
|
+
|
|
412
|
+
**Props on fields:** `error` (explicit override), `fieldMeta`, `showErrorPolicy`.
|
|
413
|
+
|
|
414
|
+
**Callback families:**
|
|
415
|
+
|
|
416
|
+
| Family | Components | Value callback | Focus |
|
|
417
|
+
| ------ | ---------- | -------------- | ----- |
|
|
418
|
+
| Native text | `Input`, `Textarea`, `Checkbox` | `onChange(event)` — DOM | `onBlur` / `onFocus` via `...rest` |
|
|
419
|
+
| Value picker | `Select`, `DialogSelect`, `TreeDialogSelect`, `Calendar` | **`onValueChange(value)`** (canonical); `onChange` deprecated alias | `onBlur` / `onFocus` on trigger |
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
import { Input, resolveFieldError } from "@andreyfedkovich/cozy-ui";
|
|
423
|
+
import { useState } from "react";
|
|
424
|
+
|
|
425
|
+
const [email, setEmail] = useState("");
|
|
426
|
+
const [touched, setTouched] = useState(false);
|
|
427
|
+
const [submitted, setSubmitted] = useState(false);
|
|
428
|
+
|
|
429
|
+
const meta = {
|
|
430
|
+
touched,
|
|
431
|
+
submitted,
|
|
432
|
+
hasValue: email.trim().length > 0,
|
|
433
|
+
invalid: !email.includes("@"),
|
|
434
|
+
errorMessage: "Enter a valid email.",
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
// Optional: resolve message before render
|
|
438
|
+
resolveFieldError(meta, "default");
|
|
439
|
+
|
|
440
|
+
<Input
|
|
441
|
+
label="Email"
|
|
442
|
+
value={email}
|
|
443
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
444
|
+
onBlur={() => setTouched(true)}
|
|
445
|
+
fieldMeta={meta}
|
|
446
|
+
showErrorPolicy="default"
|
|
447
|
+
/>;
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**React Hook Form (recipe):** use `register` on `Input`; use `Controller` on `Select` with `onValueChange={(opt) => field.onChange(opt)}`.
|
|
451
|
+
|
|
399
452
|
#### `Input`
|
|
400
453
|
|
|
401
454
|
Accessible text field with optional label and validation message for product forms.
|
|
@@ -405,7 +458,9 @@ Accessible text field with optional label and validation message for product for
|
|
|
405
458
|
| `label` | `ReactNode` | — | Field label above the input. |
|
|
406
459
|
| `tooltipContent` | `ReactNode` | — | Help tooltip on the «?» icon next to the label. |
|
|
407
460
|
| `tooltipPopperClassName` | `string` | — | Extra class for the tooltip popper. |
|
|
408
|
-
| `error` | `string \| null` | — | Validation message
|
|
461
|
+
| `error` | `string \| null` | — | Validation message (overrides `fieldMeta`). |
|
|
462
|
+
| `fieldMeta` | `FieldMeta` | — | Form meta for policy-based error display. |
|
|
463
|
+
| `showErrorPolicy` | `ShowErrorPolicy`| `"default"` | When to show `fieldMeta.errorMessage`. |
|
|
409
464
|
| `disabled` | `boolean` | `false` | Disabled state. |
|
|
410
465
|
| `className` | `string` | — | Wrapper class. |
|
|
411
466
|
| `inputClassName` | `string` | — | Native `<input>` class. |
|
|
@@ -477,9 +532,13 @@ Date picker field for forms. Value is stored as `yyyy-MM-dd` (or `null`); the tr
|
|
|
477
532
|
| `label` | `string` | — | Field label. |
|
|
478
533
|
| `required` | `boolean` | `false` | Appends ` *` to the label. |
|
|
479
534
|
| `value` | `string \| null` | — | Selected date as `yyyy-MM-dd`. |
|
|
480
|
-
| `
|
|
535
|
+
| `onValueChange` | `(value: string \| null) => void` | — | Called when the user picks or clears a date. |
|
|
536
|
+
| `onChange` | `(value: string \| null) => void` | — | **Deprecated.** Use `onValueChange`. |
|
|
537
|
+
| `onBlur` / `onFocus` | focus handlers | — | Forwarded to the trigger button. |
|
|
481
538
|
| `minDate` | `Date` | — | Earliest selectable day (inclusive, local calendar). |
|
|
482
|
-
| `error` | `string \| null` | — | Validation message
|
|
539
|
+
| `error` | `string \| null` | — | Validation message (overrides `fieldMeta`). |
|
|
540
|
+
| `fieldMeta` | `FieldMeta` | — | Form meta for policy-based error display. |
|
|
541
|
+
| `showErrorPolicy` | `ShowErrorPolicy` | `"default"` | When to show `fieldMeta.errorMessage`. |
|
|
483
542
|
| `disabled` | `boolean` | `false` | Disables the trigger. |
|
|
484
543
|
| `tooltipContent` | `ReactNode` | — | Help tooltip on the «i» icon next to the label. |
|
|
485
544
|
| `tooltipPopperClassName` | `string` | — | Extra class for the tooltip popper. |
|
|
@@ -500,14 +559,14 @@ const [startDate, setStartDate] = useState<string | null>(null);
|
|
|
500
559
|
label="Дата начала"
|
|
501
560
|
required
|
|
502
561
|
value={startDate}
|
|
503
|
-
|
|
562
|
+
onValueChange={setStartDate}
|
|
504
563
|
minDate={todayLocalDay()}
|
|
505
564
|
/>;
|
|
506
565
|
|
|
507
566
|
<Calendar
|
|
508
567
|
label="Дедлайн"
|
|
509
568
|
value={startDate}
|
|
510
|
-
|
|
569
|
+
onValueChange={setStartDate}
|
|
511
570
|
error="Укажите дату."
|
|
512
571
|
tooltipContent="Дата должна быть не раньше сегодня."
|
|
513
572
|
/>;
|
|
@@ -557,7 +616,10 @@ Powerful, virtualized-friendly select with `single` and `multiple` modes, search
|
|
|
557
616
|
| `mode` | `"single" \| "multiple"` | — | Selection mode. |
|
|
558
617
|
| `value` | `CustomOption \| CustomOption[]` | — | Current value. |
|
|
559
618
|
| `options` | `CustomOption[]` | — | Available options. |
|
|
560
|
-
| `
|
|
619
|
+
| `onValueChange` | `(option) => void` | — | Selection callback (canonical). |
|
|
620
|
+
| `onChange` | `(option) => void` | — | **Deprecated.** Use `onValueChange`. |
|
|
621
|
+
| `onBlur` / `onFocus` | focus handlers on trigger | — | For `touched` tracking. |
|
|
622
|
+
| `fieldMeta` / `showErrorPolicy` | see Field validation | — | Policy-based error display. |
|
|
561
623
|
| `onSearch` | `(value: string) => void` | — | Async search hook. |
|
|
562
624
|
| `template` | `"list" \| "table"` | `"list"` | Dropdown layout. |
|
|
563
625
|
| `columns` | `SelectColumn[]` | — | Required when `template="table"`. |
|
|
@@ -584,7 +646,7 @@ const [value, setValue] = useState<CustomOption<unknown, string> | null>(null);
|
|
|
584
646
|
placeholder="Pick one"
|
|
585
647
|
value={value}
|
|
586
648
|
options={options}
|
|
587
|
-
|
|
649
|
+
onValueChange={setValue}
|
|
588
650
|
/>;
|
|
589
651
|
```
|
|
590
652
|
|
|
@@ -609,7 +671,7 @@ import { DialogSelect } from "@andreyfedkovich/cozy-ui";
|
|
|
609
671
|
const { items, total } = await res.json();
|
|
610
672
|
return { options: items.map((p) => ({ value: p.id, label: p.name })), total };
|
|
611
673
|
}}
|
|
612
|
-
|
|
674
|
+
onValueChange={(opt) => console.log(opt)}
|
|
613
675
|
/>;
|
|
614
676
|
```
|
|
615
677
|
|
|
@@ -634,7 +696,7 @@ import { TreeDialogSelect } from "@andreyfedkovich/cozy-ui";
|
|
|
634
696
|
})}
|
|
635
697
|
searchNodes={async (search) => ({ matches: await searchTreeWithPath(search) })}
|
|
636
698
|
leafConfirmOnly
|
|
637
|
-
|
|
699
|
+
onValueChange={(node) => console.log(node)}
|
|
638
700
|
/>;
|
|
639
701
|
```
|
|
640
702
|
|
|
@@ -1100,6 +1162,19 @@ const [layout, setLayout] = useState<"agent" | "editor">("agent");
|
|
|
1100
1162
|
|
|
1101
1163
|
## Hooks & helpers
|
|
1102
1164
|
|
|
1165
|
+
### Field validation
|
|
1166
|
+
|
|
1167
|
+
```ts
|
|
1168
|
+
import {
|
|
1169
|
+
type FieldMeta,
|
|
1170
|
+
type ShowErrorPolicy,
|
|
1171
|
+
resolveFieldError,
|
|
1172
|
+
resolveFieldMessage,
|
|
1173
|
+
resolveShowError,
|
|
1174
|
+
useFieldState,
|
|
1175
|
+
} from "@andreyfedkovich/cozy-ui";
|
|
1176
|
+
```
|
|
1177
|
+
|
|
1103
1178
|
### `useMeasureElement`
|
|
1104
1179
|
|
|
1105
1180
|
Tracks the size of a DOM element via `ResizeObserver`.
|
package/dist-lib/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { default as FeedbackIcon } from './feedback.svg?react';
|
|
|
25
25
|
import { default as FileReloadIcon } from './fileReload.svg?react';
|
|
26
26
|
import { default as FileSync } from './fileSync.svg?react';
|
|
27
27
|
import { default as FilterIcon } from './filter.svg?react';
|
|
28
|
+
import { FocusEventHandler } from 'react';
|
|
28
29
|
import { default as FolderEditIcon } from './folderEdit.svg?react';
|
|
29
30
|
import { ForwardRefExoticComponent } from 'react';
|
|
30
31
|
import { default as GraduateIcon } from './graduate.svg?react';
|
|
@@ -137,17 +138,17 @@ declare type ButtonSize = "small" | "medium" | "large";
|
|
|
137
138
|
|
|
138
139
|
declare type ButtonVariant = "default" | "primary" | "secondary" | "text" | "link" | "danger";
|
|
139
140
|
|
|
140
|
-
export declare const Calendar: ({ label, required, value, onChange, minDate, error, disabled, tooltipContent, tooltipPopperClassName, className, }: CalendarProps) => JSX.Element;
|
|
141
|
+
export declare const Calendar: ({ label, required, value, onValueChange, onChange, minDate, error, fieldMeta, showErrorPolicy, disabled, onBlur, onFocus, tooltipContent, tooltipPopperClassName, className, }: CalendarProps) => JSX.Element;
|
|
141
142
|
|
|
142
|
-
export declare interface CalendarProps {
|
|
143
|
+
export declare interface CalendarProps extends ValueFieldCallbacks<string | null>, FieldValidationProps {
|
|
143
144
|
label: string;
|
|
144
145
|
required?: boolean;
|
|
145
146
|
value?: string | null;
|
|
146
|
-
onChange: (value: string | null) => void;
|
|
147
147
|
/** Нижняя граница выбора (включительно), локальный календарный день */
|
|
148
148
|
minDate?: Date;
|
|
149
|
-
error?: string | null;
|
|
150
149
|
disabled?: boolean;
|
|
150
|
+
onBlur?: FocusEventHandler<HTMLButtonElement>;
|
|
151
|
+
onFocus?: FocusEventHandler<HTMLButtonElement>;
|
|
151
152
|
/** Подсказка по наведению на иконку «?» справа от подписи */
|
|
152
153
|
tooltipContent?: ReactNode;
|
|
153
154
|
tooltipPopperClassName?: string;
|
|
@@ -203,9 +204,8 @@ export { ChatIcon }
|
|
|
203
204
|
|
|
204
205
|
export declare const Checkbox: ForwardRefExoticComponent<CheckboxProps & RefAttributes<HTMLInputElement>>;
|
|
205
206
|
|
|
206
|
-
export declare interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"
|
|
207
|
+
export declare interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type">, FieldValidationProps {
|
|
207
208
|
label?: ReactNode;
|
|
208
|
-
error?: string | null;
|
|
209
209
|
checkboxClassName?: string;
|
|
210
210
|
/** Подсказка по наведению на иконку «?» справа от подписи */
|
|
211
211
|
tooltipContent?: ReactNode;
|
|
@@ -387,8 +387,7 @@ export declare interface CustomOption<T, S = string> {
|
|
|
387
387
|
meta?: T;
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
declare type CustomSelectProps<T, S> = {
|
|
391
|
-
onChange?: (option: CustomOption<T, S>) => void;
|
|
390
|
+
declare type CustomSelectProps<T, S> = ValueFieldCallbacks<CustomOption<T, S>> & FieldValidationProps & {
|
|
392
391
|
options?: CustomOption<T, S>[];
|
|
393
392
|
placeholder: string;
|
|
394
393
|
dropdownRender?: (menu: ReactNode) => ReactNode;
|
|
@@ -416,7 +415,8 @@ declare type CustomSelectProps<T, S> = {
|
|
|
416
415
|
disabled?: boolean;
|
|
417
416
|
onClose?: () => void;
|
|
418
417
|
portalTarget?: Element;
|
|
419
|
-
|
|
418
|
+
onBlur?: default_2.FocusEventHandler<HTMLDivElement>;
|
|
419
|
+
onFocus?: default_2.FocusEventHandler<HTMLDivElement>;
|
|
420
420
|
template?: "list" | "table";
|
|
421
421
|
columns?: SelectColumn<T, S>[];
|
|
422
422
|
total?: number;
|
|
@@ -483,7 +483,7 @@ export declare interface DetailViewProps {
|
|
|
483
483
|
id?: string;
|
|
484
484
|
}
|
|
485
485
|
|
|
486
|
-
export declare const DialogSelect: <T, S extends string | number>({ value, placeholder, loadOptions, onChange, onClear, columns, label, tooltipContent, tooltipPopperClassName, title, searchPlaceholder, selectButtonText, closeButtonText, manualButtonText, onManualAdd, pageSize, debounceMs, disabled, error, className, inputClassName, selectedOptionRender, }: DialogSelectProps<T, S>) => JSX.Element;
|
|
486
|
+
export declare const DialogSelect: <T, S extends string | number>({ value, placeholder, loadOptions, onValueChange, onChange, onBlur, onFocus, onClear, columns, label, tooltipContent, tooltipPopperClassName, title, searchPlaceholder, selectButtonText, closeButtonText, manualButtonText, onManualAdd, pageSize, debounceMs, disabled, error, fieldMeta, showErrorPolicy, className, inputClassName, selectedOptionRender, }: DialogSelectProps<T, S>) => JSX.Element;
|
|
487
487
|
|
|
488
488
|
export declare type DialogSelectColumn<T, S extends string | number> = {
|
|
489
489
|
key: string;
|
|
@@ -492,12 +492,13 @@ export declare type DialogSelectColumn<T, S extends string | number> = {
|
|
|
492
492
|
render: (option: CustomOption<T, S>) => ReactNode;
|
|
493
493
|
};
|
|
494
494
|
|
|
495
|
-
export declare interface DialogSelectProps<T, S extends string | number> {
|
|
495
|
+
export declare interface DialogSelectProps<T, S extends string | number> extends ValueFieldCallbacks<CustomOption<T, S>>, FieldValidationProps {
|
|
496
496
|
value?: CustomOption<T, S> | null;
|
|
497
497
|
placeholder: string;
|
|
498
498
|
loadOptions: (params: LoadOptionsParams) => Promise<LoadOptionsResult<T, S>>;
|
|
499
|
-
onChange?: (option: CustomOption<T, S>) => void;
|
|
500
499
|
onClear?: () => void;
|
|
500
|
+
onBlur?: default_2.FocusEventHandler<HTMLDivElement>;
|
|
501
|
+
onFocus?: default_2.FocusEventHandler<HTMLDivElement>;
|
|
501
502
|
columns?: DialogSelectColumn<T, S>[];
|
|
502
503
|
label?: ReactNode;
|
|
503
504
|
/** Подсказка по наведению на иконку «?» справа от подписи */
|
|
@@ -512,7 +513,6 @@ export declare interface DialogSelectProps<T, S extends string | number> {
|
|
|
512
513
|
pageSize?: number;
|
|
513
514
|
debounceMs?: number;
|
|
514
515
|
disabled?: boolean;
|
|
515
|
-
error?: string | null;
|
|
516
516
|
className?: string;
|
|
517
517
|
inputClassName?: string;
|
|
518
518
|
selectedOptionRender?: (option: CustomOption<T, S>) => ReactNode;
|
|
@@ -562,8 +562,24 @@ declare interface FieldComponentProps extends Omit<DetailField, "value"> {
|
|
|
562
562
|
className?: string;
|
|
563
563
|
}
|
|
564
564
|
|
|
565
|
+
export declare type FieldMeta = {
|
|
566
|
+
touched?: boolean;
|
|
567
|
+
dirty?: boolean;
|
|
568
|
+
submitted?: boolean;
|
|
569
|
+
hasValue?: boolean;
|
|
570
|
+
invalid?: boolean;
|
|
571
|
+
errorMessage?: string | null;
|
|
572
|
+
};
|
|
573
|
+
|
|
565
574
|
declare const FieldRow: FC<FieldComponentProps>;
|
|
566
575
|
|
|
576
|
+
export declare type FieldValidationProps = {
|
|
577
|
+
/** Explicit error overrides {@link fieldMeta} + policy when set. */
|
|
578
|
+
error?: string | null;
|
|
579
|
+
fieldMeta?: FieldMeta;
|
|
580
|
+
showErrorPolicy?: ShowErrorPolicy;
|
|
581
|
+
};
|
|
582
|
+
|
|
567
583
|
export { FileReloadIcon }
|
|
568
584
|
|
|
569
585
|
export { FileSync }
|
|
@@ -610,7 +626,7 @@ export declare const Input: ForwardRefExoticComponent<InputProps & RefAttributes
|
|
|
610
626
|
|
|
611
627
|
export declare const InputCaption: React_2.FC<PropsWithChildren<InputCaptionProps>>;
|
|
612
628
|
|
|
613
|
-
declare interface InputCaptionProps {
|
|
629
|
+
declare interface InputCaptionProps extends React_2.HTMLAttributes<HTMLParagraphElement> {
|
|
614
630
|
isFullWidth?: boolean;
|
|
615
631
|
/** Visual tone. Defaults to `error` for backwards compatibility with validation messages. */
|
|
616
632
|
variant?: InputCaptionVariant;
|
|
@@ -620,15 +636,16 @@ declare interface InputCaptionProps {
|
|
|
620
636
|
|
|
621
637
|
export declare type InputCaptionVariant = "neutral" | "error" | "success";
|
|
622
638
|
|
|
623
|
-
export declare interface InputProps extends InputHTMLAttributes<HTMLInputElement
|
|
639
|
+
export declare interface InputProps extends InputHTMLAttributes<HTMLInputElement>, FieldValidationProps {
|
|
624
640
|
label?: ReactNode;
|
|
625
|
-
error?: string | null;
|
|
626
641
|
inputClassName?: string;
|
|
627
642
|
/** Подсказка по наведению на иконку «?» справа от подписи */
|
|
628
643
|
tooltipContent?: ReactNode;
|
|
629
644
|
tooltipPopperClassName?: string;
|
|
630
645
|
}
|
|
631
646
|
|
|
647
|
+
export declare function isFieldInvalid(meta: FieldMeta): boolean;
|
|
648
|
+
|
|
632
649
|
export { IslandIcon }
|
|
633
650
|
|
|
634
651
|
declare interface ItemComponentProps extends SettingsItem {
|
|
@@ -782,6 +799,21 @@ declare interface RadioGroupButtonProps<T extends string | number> {
|
|
|
782
799
|
|
|
783
800
|
export { ReloadIcon }
|
|
784
801
|
|
|
802
|
+
export declare function resolveFieldError(meta: FieldMeta | undefined, policy?: ShowErrorPolicy): string | null;
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Resolves the error message to display: explicit `error` wins over fieldMeta + policy.
|
|
806
|
+
*/
|
|
807
|
+
export declare function resolveFieldMessage(options: {
|
|
808
|
+
error?: string | null;
|
|
809
|
+
fieldMeta?: FieldMeta;
|
|
810
|
+
showErrorPolicy?: ShowErrorPolicy;
|
|
811
|
+
}): string | null;
|
|
812
|
+
|
|
813
|
+
export declare function resolveShowError(meta: FieldMeta | undefined, policy?: ShowErrorPolicy): boolean;
|
|
814
|
+
|
|
815
|
+
export declare function resolveValueChangeHandler<T>(callbacks: ValueFieldCallbacks<T>): ((value: T) => void) | undefined;
|
|
816
|
+
|
|
785
817
|
export { SchoolIcon }
|
|
786
818
|
|
|
787
819
|
export { SearchIcon }
|
|
@@ -798,7 +830,7 @@ declare interface SectionComponentProps extends Omit<DetailSection, "fields"> {
|
|
|
798
830
|
declare interface SectionProps extends SideNavSection {
|
|
799
831
|
}
|
|
800
832
|
|
|
801
|
-
export declare const Select: <T, S extends string | number>({ options, value, mode, placeholder, onChange, dropdownRender, optionRender, selectedOptionRender, dropdownIcon, tagRender, dropDownClassName, optionClassName, inputClassName, deleteIconClassName, onDelete, onClear, label, tooltipContent, tooltipPopperClassName, onSearch, searchClassName, searchPlaceholder, isLoading, disabled, onClose, portalTarget, error, template, columns, total, }: CustomSelectProps<T, S>) => JSX.Element;
|
|
833
|
+
export declare const Select: <T, S extends string | number>({ options, value, mode, placeholder, onValueChange, onChange, onBlur, onFocus, dropdownRender, optionRender, selectedOptionRender, dropdownIcon, tagRender, dropDownClassName, optionClassName, inputClassName, deleteIconClassName, onDelete, onClear, label, tooltipContent, tooltipPopperClassName, onSearch, searchClassName, searchPlaceholder, isLoading, disabled, onClose, portalTarget, error, fieldMeta, showErrorPolicy, template, columns, total, }: CustomSelectProps<T, S>) => JSX.Element;
|
|
802
834
|
|
|
803
835
|
export declare type SelectColumn<T, S> = {
|
|
804
836
|
key: string;
|
|
@@ -878,6 +910,8 @@ export declare interface SettingsViewProps {
|
|
|
878
910
|
id?: string;
|
|
879
911
|
}
|
|
880
912
|
|
|
913
|
+
export declare type ShowErrorPolicy = "default" | "onBlur" | "onSubmit" | "always" | ((meta: FieldMeta) => boolean);
|
|
914
|
+
|
|
881
915
|
export declare const SideNav: SideNavComponent;
|
|
882
916
|
|
|
883
917
|
declare type SideNavComponent = FC<SideNavProps> & {
|
|
@@ -1036,10 +1070,9 @@ export { TaskListIcon }
|
|
|
1036
1070
|
|
|
1037
1071
|
export declare const Textarea: ForwardRefExoticComponent<TextareaProps & RefAttributes<HTMLTextAreaElement>>;
|
|
1038
1072
|
|
|
1039
|
-
export declare interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement
|
|
1073
|
+
export declare interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement>, FieldValidationProps {
|
|
1040
1074
|
label?: ReactNode;
|
|
1041
|
-
error
|
|
1042
|
-
/** Neutral helper text under the textarea (hidden when `error` is set). */
|
|
1075
|
+
/** Neutral helper text under the textarea (hidden when error is shown). */
|
|
1043
1076
|
hint?: ReactNode;
|
|
1044
1077
|
hintVariant?: InputCaptionVariant;
|
|
1045
1078
|
textareaClassName?: string;
|
|
@@ -1098,7 +1131,7 @@ export declare type TooltipTrigger = "hover" | "click";
|
|
|
1098
1131
|
/** `yyyy-MM-dd` for API / form state */
|
|
1099
1132
|
export declare const toYmdString: (d: Date) => string;
|
|
1100
1133
|
|
|
1101
|
-
export declare const TreeDialogSelect: <T, S extends string | number>({ value, placeholder, loadChildren: loadChildrenProp, loadNodes, searchNodes, onChange, onClear, label, tooltipContent, tooltipPopperClassName, title, searchPlaceholder, selectButtonText, closeButtonText, confirmButtonText, debounceMs, disabled, error, className, inputClassName, selectedOptionRender, nodeRender, leafConfirmOnly, }: TreeDialogSelectProps<T, S>) => JSX.Element;
|
|
1134
|
+
export declare const TreeDialogSelect: <T, S extends string | number>({ value, placeholder, loadChildren: loadChildrenProp, loadNodes, searchNodes, onValueChange, onChange, onBlur, onFocus, onClear, label, tooltipContent, tooltipPopperClassName, title, searchPlaceholder, selectButtonText, closeButtonText, confirmButtonText, debounceMs, disabled, error, fieldMeta, showErrorPolicy, className, inputClassName, selectedOptionRender, nodeRender, leafConfirmOnly, }: TreeDialogSelectProps<T, S>) => JSX.Element;
|
|
1102
1135
|
|
|
1103
1136
|
/** Pass either {@link loadNodes} or {@link loadChildren} (deprecated alias). */
|
|
1104
1137
|
export declare type TreeDialogSelectProps<T, S extends string | number> = TreeDialogSelectShared<T, S> & ({
|
|
@@ -1109,12 +1142,13 @@ export declare type TreeDialogSelectProps<T, S extends string | number> = TreeDi
|
|
|
1109
1142
|
loadNodes?: TreeLoader<T, S>;
|
|
1110
1143
|
});
|
|
1111
1144
|
|
|
1112
|
-
declare interface TreeDialogSelectShared<T, S extends string | number> {
|
|
1145
|
+
declare interface TreeDialogSelectShared<T, S extends string | number> extends ValueFieldCallbacks<TreeNode<T, S>>, FieldValidationProps {
|
|
1113
1146
|
value?: TreeNode<T, S> | null;
|
|
1114
1147
|
placeholder: string;
|
|
1115
1148
|
searchNodes?: (search: string) => Promise<TreeSearchResult<T, S>>;
|
|
1116
|
-
onChange?: (node: TreeNode<T, S>) => void;
|
|
1117
1149
|
onClear?: () => void;
|
|
1150
|
+
onBlur?: default_2.FocusEventHandler<HTMLDivElement>;
|
|
1151
|
+
onFocus?: default_2.FocusEventHandler<HTMLDivElement>;
|
|
1118
1152
|
label?: ReactNode;
|
|
1119
1153
|
/** Подсказка по наведению на иконку «?» справа от подписи */
|
|
1120
1154
|
tooltipContent?: ReactNode;
|
|
@@ -1126,7 +1160,6 @@ declare interface TreeDialogSelectShared<T, S extends string | number> {
|
|
|
1126
1160
|
confirmButtonText?: string;
|
|
1127
1161
|
debounceMs?: number;
|
|
1128
1162
|
disabled?: boolean;
|
|
1129
|
-
error?: string | null;
|
|
1130
1163
|
className?: string;
|
|
1131
1164
|
inputClassName?: string;
|
|
1132
1165
|
selectedOptionRender?: (node: TreeNode<T, S>) => ReactNode;
|
|
@@ -1176,6 +1209,12 @@ declare interface UseDropdownPositionProps {
|
|
|
1176
1209
|
onAnchorFrame?: (placement: DropdownPosition) => void;
|
|
1177
1210
|
}
|
|
1178
1211
|
|
|
1212
|
+
export declare function useFieldState(fieldMeta: FieldMeta | undefined, policy?: ShowErrorPolicy, explicitError?: string | null): {
|
|
1213
|
+
showError: boolean;
|
|
1214
|
+
errorMessage: string | null;
|
|
1215
|
+
showErrorByPolicy: boolean;
|
|
1216
|
+
};
|
|
1217
|
+
|
|
1179
1218
|
export declare const useMeasureElement: (element?: HTMLElement | null) => {
|
|
1180
1219
|
height: number;
|
|
1181
1220
|
width: number;
|
|
@@ -1183,6 +1222,13 @@ export declare const useMeasureElement: (element?: HTMLElement | null) => {
|
|
|
1183
1222
|
|
|
1184
1223
|
export { UserSwitchIcon }
|
|
1185
1224
|
|
|
1225
|
+
/** Picker controls: canonical value callback + deprecated alias. */
|
|
1226
|
+
export declare type ValueFieldCallbacks<T> = {
|
|
1227
|
+
onValueChange?: (value: T) => void;
|
|
1228
|
+
/** @deprecated Use {@link onValueChange}. Removed in next major. */
|
|
1229
|
+
onChange?: (value: T) => void;
|
|
1230
|
+
};
|
|
1231
|
+
|
|
1186
1232
|
export { WalletIcon }
|
|
1187
1233
|
|
|
1188
1234
|
export { WarnIcon }
|