@godxjp/ui 20.0.0 → 20.2.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 +8 -2
- package/dist/app/app-provider.js +37 -21
- package/dist/app/index.d.ts +2 -0
- package/dist/app/index.js +2 -0
- package/dist/app/storage.d.ts +17 -0
- package/dist/app/storage.js +28 -0
- package/dist/app/theme-axes.d.ts +2 -0
- package/dist/app/theme-axes.js +45 -0
- package/dist/components/charts/chart-cartesian.d.ts +2 -1
- package/dist/components/charts/chart-cartesian.js +52 -3
- package/dist/components/charts/chart-category-axis.d.ts +55 -0
- package/dist/components/charts/chart-category-axis.js +93 -0
- package/dist/components/charts/chart-frame.d.ts +10 -1
- package/dist/components/charts/chart-frame.js +19 -3
- package/dist/components/charts/compact-bar-trend.d.ts +1 -1
- package/dist/components/charts/compact-bar-trend.js +2 -0
- package/dist/components/charts/pie-chart.d.ts +1 -1
- package/dist/components/charts/pie-chart.js +12 -1
- package/dist/components/charts/recharts-peer.d.ts +49 -0
- package/dist/components/charts/recharts-peer.js +45 -0
- package/dist/components/data-display/card.d.ts +12 -1
- package/dist/components/data-display/card.js +22 -4
- package/dist/components/data-display/code-block.js +6 -2
- package/dist/components/data-display/data-table.d.ts +39 -4
- package/dist/components/data-display/data-table.js +802 -270
- package/dist/components/data-display/descriptions.d.ts +27 -6
- package/dist/components/data-display/descriptions.js +58 -17
- package/dist/components/data-display/index.d.ts +2 -0
- package/dist/components/data-display/index.js +2 -0
- package/dist/components/data-display/list-row.d.ts +10 -1
- package/dist/components/data-display/list-row.js +7 -1
- package/dist/components/data-display/popover.d.ts +9 -3
- package/dist/components/data-display/popover.js +65 -11
- package/dist/components/data-display/range-timeline.d.ts +38 -0
- package/dist/components/data-display/range-timeline.js +161 -0
- package/dist/components/data-display/scroll-area.js +13 -2
- package/dist/components/data-display/service-launcher-card.js +14 -12
- package/dist/components/data-display/table.d.ts +71 -3
- package/dist/components/data-display/table.js +56 -18
- package/dist/components/data-display/tree-list.js +4 -9
- package/dist/components/data-entry/calendar.d.ts +2 -2
- package/dist/components/data-entry/calendar.js +23 -3
- package/dist/components/data-entry/cascader.d.ts +1 -1
- package/dist/components/data-entry/cascader.js +188 -24
- package/dist/components/data-entry/color-picker.d.ts +1 -1
- package/dist/components/data-entry/color-picker.js +17 -5
- package/dist/components/data-entry/control-appearance.d.ts +64 -0
- package/dist/components/data-entry/control-appearance.js +39 -0
- package/dist/components/data-entry/control-surface.d.ts +61 -0
- package/dist/components/data-entry/control-surface.js +39 -0
- package/dist/components/data-entry/date-picker.d.ts +1 -1
- package/dist/components/data-entry/date-picker.js +344 -113
- package/dist/components/data-entry/date-range-picker.d.ts +1 -1
- package/dist/components/data-entry/date-range-picker.js +278 -140
- package/dist/components/data-entry/form-field.d.ts +1 -1
- package/dist/components/data-entry/form-field.js +39 -4
- package/dist/components/data-entry/form.d.ts +4 -0
- package/dist/components/data-entry/form.js +4 -2
- package/dist/components/data-entry/index.d.ts +7 -3
- package/dist/components/data-entry/index.js +10 -1
- package/dist/components/data-entry/input-otp.d.ts +1 -1
- package/dist/components/data-entry/input.d.ts +12 -34
- package/dist/components/data-entry/input.js +92 -24
- package/dist/components/data-entry/month-picker.d.ts +1 -1
- package/dist/components/data-entry/month-picker.js +47 -10
- package/dist/components/data-entry/month-range-picker.d.ts +1 -1
- package/dist/components/data-entry/month-range-picker.js +51 -11
- package/dist/components/data-entry/number-input.d.ts +7 -0
- package/dist/components/data-entry/number-input.js +147 -98
- package/dist/components/data-entry/password-input.d.ts +1 -1
- package/dist/components/data-entry/radio.d.ts +1 -1
- package/dist/components/data-entry/radio.js +61 -13
- package/dist/components/data-entry/search-input.d.ts +1 -1
- package/dist/components/data-entry/search-input.js +16 -2
- package/dist/components/data-entry/search-select.d.ts +2 -2
- package/dist/components/data-entry/search-select.js +209 -78
- package/dist/components/data-entry/select.d.ts +22 -4
- package/dist/components/data-entry/select.js +215 -163
- package/dist/components/data-entry/slider.d.ts +9 -1
- package/dist/components/data-entry/slider.js +87 -9
- package/dist/components/data-entry/switch.d.ts +3 -0
- package/dist/components/data-entry/switch.js +29 -3
- package/dist/components/data-entry/textarea.d.ts +14 -56
- package/dist/components/data-entry/textarea.js +80 -33
- package/dist/components/data-entry/time-picker.d.ts +2 -2
- package/dist/components/data-entry/time-picker.js +333 -109
- package/dist/components/data-entry/time-range-picker.d.ts +5 -0
- package/dist/components/data-entry/time-range-picker.js +89 -0
- package/dist/components/data-entry/transfer.d.ts +1 -1
- package/dist/components/data-entry/transfer.js +86 -28
- package/dist/components/data-entry/tree-select.d.ts +1 -1
- package/dist/components/data-entry/tree-select.js +201 -113
- package/dist/components/data-entry/tree-utils.js +7 -14
- package/dist/components/data-entry/upload-files.d.ts +2 -0
- package/dist/components/data-entry/upload-files.js +31 -0
- package/dist/components/data-entry/upload-request.d.ts +4 -0
- package/dist/components/data-entry/upload-request.js +53 -0
- package/dist/components/data-entry/upload-types.d.ts +28 -0
- package/dist/components/data-entry/upload-types.js +2 -0
- package/dist/components/data-entry/upload.d.ts +2 -2
- package/dist/components/data-entry/upload.js +475 -115
- package/dist/components/feedback/dialog.js +19 -19
- package/dist/components/feedback/sheet.js +3 -0
- package/dist/components/feedback/tooltip.js +3 -0
- package/dist/components/general/button.d.ts +2 -1
- package/dist/components/general/button.js +7 -1
- package/dist/components/general/index.d.ts +1 -0
- package/dist/components/general/index.js +2 -0
- package/dist/components/general/typography.d.ts +3 -0
- package/dist/components/general/typography.js +15 -1
- package/dist/components/general/visually-hidden.d.ts +3 -0
- package/dist/components/general/visually-hidden.js +9 -0
- package/dist/components/layout/app-launcher.d.ts +34 -0
- package/dist/components/layout/app-launcher.js +261 -0
- package/dist/components/layout/app-shell.d.ts +3 -1
- package/dist/components/layout/app-shell.js +34 -14
- package/dist/components/layout/auth-shell.d.ts +1 -1
- package/dist/components/layout/auth-shell.js +2 -0
- package/dist/components/layout/breadcrumb.d.ts +14 -2
- package/dist/components/layout/breadcrumb.js +46 -4
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +23 -2
- package/dist/components/layout/index.d.ts +3 -0
- package/dist/components/layout/index.js +5 -1
- package/dist/components/layout/org-switcher.js +20 -1
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +5 -3
- package/dist/components/layout/responsive-grid.d.ts +16 -2
- package/dist/components/layout/responsive-grid.js +29 -2
- package/dist/components/layout/sidebar.js +2 -1
- package/dist/components/layout/topbar-item.d.ts +3 -0
- package/dist/components/layout/topbar-item.js +18 -3
- package/dist/components/layout/topbar.d.ts +1 -1
- package/dist/components/layout/topbar.js +27 -6
- package/dist/components/navigation/dropdown-menu.d.ts +30 -2
- package/dist/components/navigation/dropdown-menu.js +73 -11
- package/dist/components/navigation/pagination.d.ts +2 -2
- package/dist/components/navigation/pagination.js +155 -83
- package/dist/components/navigation/steps.d.ts +2 -2
- package/dist/components/navigation/steps.js +29 -4
- package/dist/components/navigation/tabs.d.ts +5 -33
- package/dist/components/navigation/tabs.js +232 -64
- package/dist/components/ui/hover-card.js +3 -0
- package/dist/components/ui/input-otp.d.ts +26 -28
- package/dist/components/ui/input-otp.js +50 -7
- package/dist/components/ui/password-input.d.ts +36 -2
- package/dist/components/ui/password-input.js +27 -7
- package/dist/components/ui/rating.d.ts +25 -0
- package/dist/components/ui/rating.js +67 -27
- package/dist/components/ui/segmented.d.ts +9 -0
- package/dist/components/ui/segmented.js +17 -2
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/separator.js +13 -0
- package/dist/components/ui/tag-input.d.ts +45 -0
- package/dist/components/ui/tag-input.js +109 -27
- package/dist/form/form-context.d.ts +29 -0
- package/dist/form/form-context.js +44 -4
- package/dist/form/form-field-array.d.ts +22 -0
- package/dist/form/form-field-array.js +50 -0
- package/dist/form/form-field-control.d.ts +2 -1
- package/dist/form/form-field-control.js +116 -40
- package/dist/form/form-root.d.ts +2 -1
- package/dist/form/form-root.js +142 -23
- package/dist/form/index.d.ts +3 -1
- package/dist/form/index.js +12 -1
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +3 -1
- package/dist/i18n/messages/en.json +59 -6
- package/dist/i18n/messages/ja.json +59 -6
- package/dist/i18n/messages/vi.json +59 -6
- package/dist/i18n/translate.d.ts +19 -0
- package/dist/i18n/translate.js +24 -0
- package/dist/inertia/index.d.ts +20 -0
- package/dist/inertia/index.js +60 -1
- package/dist/lib/control-styles.d.ts +25 -3
- package/dist/lib/control-styles.js +9 -3
- package/dist/lib/datetime/picker-format.d.ts +8 -0
- package/dist/lib/datetime/picker-format.js +54 -0
- package/dist/lib/overlay-portal.d.ts +18 -0
- package/dist/lib/overlay-portal.js +17 -0
- package/dist/props/components/app.prop.d.ts +13 -2
- package/dist/props/components/charts.prop.d.ts +21 -0
- package/dist/props/components/data-display.prop.d.ts +55 -4
- package/dist/props/components/data-entry.prop.d.ts +687 -43
- package/dist/props/components/form.prop.d.ts +142 -4
- package/dist/props/components/general.prop.d.ts +30 -1
- package/dist/props/components/index.d.ts +2 -2
- package/dist/props/components/layout.prop.d.ts +255 -8
- package/dist/props/components/navigation.prop.d.ts +113 -3
- package/dist/props/registry.d.ts +376 -10
- package/dist/props/registry.js +493 -9
- package/dist/props/vocabulary/data.prop.d.ts +179 -1
- package/dist/props/vocabulary/index.d.ts +4 -4
- package/dist/props/vocabulary/interaction.prop.d.ts +51 -2
- package/dist/props/vocabulary/navigation.prop.d.ts +40 -0
- package/dist/props/vocabulary/shared.prop.d.ts +33 -0
- package/dist/styles/badge-layout.css +2 -1
- package/dist/styles/card-layout.css +36 -5
- package/dist/styles/chart-layout.css +17 -1
- package/dist/styles/control.css +520 -14
- package/dist/styles/data-display-layout.css +248 -7
- package/dist/styles/data-entry-layout.css +13 -0
- package/dist/styles/layout.css +221 -4
- package/dist/styles/navigation-layout.css +230 -1
- package/dist/styles/shell-layout.css +690 -21
- package/dist/styles/table-layout.css +95 -6
- package/dist/styles/text-layout.css +5 -0
- package/dist/tokens/base.css +1 -0
- package/dist/tokens/components/badge.css +1 -0
- package/dist/tokens/components/chart.css +6 -0
- package/dist/tokens/components/control.css +81 -3
- package/dist/tokens/components/data-display.css +9 -0
- package/dist/tokens/components/descriptions.css +11 -0
- package/dist/tokens/components/flex.css +8 -0
- package/dist/tokens/components/navigation.css +55 -0
- package/dist/tokens/components/shell.css +100 -5
- package/dist/tokens/components/table.css +14 -0
- package/dist/tokens/foundation.css +2 -0
- package/dist/tokens/semantic/layout.css +9 -0
- package/docs/CONSUMER-RULES.md +13 -0
- package/docs/DESIGN-AUTHORITY.md +43 -6
- package/docs/DEVELOPMENT.md +4 -3
- package/docs/FORMS.md +151 -6
- package/docs/FRAME-COVERAGE-REPORT.md +29 -16
- package/docs/README.md +1 -1
- package/docs/STANDARDS-vocabulary-tokens.md +1 -1
- package/docs/TESTING.md +15 -6
- package/docs/charts/cjk-category-axis.tsx +81 -0
- package/docs/data-display/card/index.tsx +22 -0
- package/docs/data-display/data-table/examples/antd-parity.tsx +257 -0
- package/docs/data-display/data-table/index.tsx +23 -0
- package/docs/data-display/descriptions.tsx +41 -0
- package/docs/data-display/list-row.tsx +6 -6
- package/docs/data-display/scroll-area.tsx +31 -25
- package/docs/data-display/table.tsx +104 -45
- package/docs/data-display/timeline.tsx +41 -0
- package/docs/data-entry/date-picker.tsx +85 -0
- package/docs/data-entry/date-range-picker.tsx +26 -0
- package/docs/data-entry/form-dynamic-fields.tsx +199 -0
- package/docs/data-entry/form.tsx +74 -4
- package/docs/data-entry/input-otp.tsx +24 -0
- package/docs/data-entry/input.tsx +46 -1
- package/docs/data-entry/month-range-picker.tsx +1 -1
- package/docs/data-entry/select.tsx +27 -0
- package/docs/data-entry/switch.tsx +41 -0
- package/docs/data-entry/textarea.tsx +38 -0
- package/docs/data-entry/time-picker.tsx +85 -1
- package/docs/data-entry/time-range-picker.tsx +55 -0
- package/docs/data-entry/transfer.tsx +17 -0
- package/docs/data-entry/upload.tsx +56 -12
- package/docs/feedback/tooltip.tsx +1 -1
- package/docs/general/activity.tsx +2 -2
- package/docs/general/button/index.tsx +14 -1
- package/docs/general/typography.tsx +14 -1
- package/docs/layout/app-launcher.tsx +195 -0
- package/docs/layout/app-shell-arrangements.tsx +5 -5
- package/docs/layout/app-shell.tsx +11 -0
- package/docs/layout/flex.tsx +50 -0
- package/docs/layout/responsive-grid.tsx +21 -1
- package/docs/layout/topbar.tsx +5 -9
- package/docs/navigation/app-setting-picker.tsx +11 -0
- package/docs/navigation/breadcrumb.tsx +48 -0
- package/docs/navigation/dropdown-menu.tsx +21 -0
- package/docs/navigation/pagination.tsx +52 -0
- package/docs/navigation/steps.tsx +37 -0
- package/docs/navigation/tabs.tsx +97 -1
- package/docs/query/button-refetch.tsx +1 -0
- package/docs/showcase/settings-security-mfa.tsx +3 -3
- package/package.json +24 -4
- package/scripts/_agent-setup.mjs +76 -9
- package/scripts/init-guinea-pig.mjs +26 -4
- package/scripts/ui-audit.mjs +243 -30
- package/scripts/visual-audit.mjs +45 -7
|
@@ -6,30 +6,50 @@ import { useTranslation } from "../../i18n/use-translation.js";
|
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
7
|
import { Input } from "../data-entry/input.js";
|
|
8
8
|
const PasswordInput = React.forwardRef(
|
|
9
|
-
({ className, ...props }, ref) => {
|
|
9
|
+
({ className, visibilityToggle = true, iconRender, suffix, trailingIcon, allowClear, ...props }, ref) => {
|
|
10
10
|
const { t } = useTranslation();
|
|
11
|
-
const
|
|
11
|
+
const controlledVisible = typeof visibilityToggle === "object" ? visibilityToggle.visible : void 0;
|
|
12
|
+
const onVisibleChange = typeof visibilityToggle === "object" ? visibilityToggle.onVisibleChange : void 0;
|
|
13
|
+
const showToggle = visibilityToggle !== false;
|
|
14
|
+
const [internalVisible, setInternalVisible] = React.useState(false);
|
|
15
|
+
const isVisibleControlled = controlledVisible !== void 0;
|
|
16
|
+
const visible = showToggle ? isVisibleControlled ? controlledVisible : internalVisible : false;
|
|
17
|
+
const setVisible = (next) => {
|
|
18
|
+
if (!isVisibleControlled) setInternalVisible(next);
|
|
19
|
+
onVisibleChange?.(next);
|
|
20
|
+
};
|
|
21
|
+
const toggleOwnsTrailing = showToggle;
|
|
22
|
+
if (toggleOwnsTrailing && process.env?.NODE_ENV !== "production" && (suffix != null || trailingIcon != null || allowClear)) {
|
|
23
|
+
console.warn(
|
|
24
|
+
"[godxjp-ui] PasswordInput: the reveal toggle owns the trailing slot, so `suffix` / `trailingIcon` / `allowClear` are ignored. Use `leadingIcon` (or `prefix`), or pass `visibilityToggle={false}` to hand the slot back."
|
|
25
|
+
);
|
|
26
|
+
}
|
|
12
27
|
return /* @__PURE__ */ jsxs("div", { className: "ui-password-input", "data-slot": "password-input", children: [
|
|
13
28
|
/* @__PURE__ */ jsx(
|
|
14
29
|
Input,
|
|
15
30
|
{
|
|
16
31
|
ref,
|
|
17
32
|
type: visible ? "text" : "password",
|
|
18
|
-
className: cn("ui-password-input-field", className),
|
|
33
|
+
className: cn(showToggle && "ui-password-input-field", className),
|
|
34
|
+
suffix: toggleOwnsTrailing ? void 0 : suffix,
|
|
35
|
+
trailingIcon: toggleOwnsTrailing ? void 0 : trailingIcon,
|
|
36
|
+
allowClear: toggleOwnsTrailing ? false : allowClear,
|
|
19
37
|
...props
|
|
20
38
|
}
|
|
21
39
|
),
|
|
22
|
-
/* @__PURE__ */ jsx(
|
|
40
|
+
showToggle ? /* @__PURE__ */ jsx(
|
|
23
41
|
"button",
|
|
24
42
|
{
|
|
25
43
|
type: "button",
|
|
26
44
|
className: "ui-password-input-toggle",
|
|
27
|
-
|
|
45
|
+
disabled: props.disabled,
|
|
46
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
47
|
+
onClick: () => setVisible(!visible),
|
|
28
48
|
"aria-label": visible ? t("ui.passwordInput.hide") : t("ui.passwordInput.show"),
|
|
29
49
|
"aria-pressed": visible,
|
|
30
|
-
children: visible ? /* @__PURE__ */ jsx(EyeOff, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Eye, { "aria-hidden": "true" })
|
|
50
|
+
children: iconRender ? iconRender(visible) : visible ? /* @__PURE__ */ jsx(EyeOff, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Eye, { "aria-hidden": "true" })
|
|
31
51
|
}
|
|
32
|
-
)
|
|
52
|
+
) : null
|
|
33
53
|
] });
|
|
34
54
|
}
|
|
35
55
|
);
|
|
@@ -3,7 +3,32 @@ export type RatingProps = {
|
|
|
3
3
|
value?: number;
|
|
4
4
|
defaultValue?: number;
|
|
5
5
|
onValueChange?: (value: number) => void;
|
|
6
|
+
/** Number of symbols. This library's older name for antd's `count`; both are accepted. */
|
|
6
7
|
max?: number;
|
|
8
|
+
/** antd `count` — number of symbols. Default 5. */
|
|
9
|
+
count?: number;
|
|
10
|
+
/**
|
|
11
|
+
* antd `allowHalf` — a symbol can be half-filled, so the scale is 0.5 … count in steps of 0.5.
|
|
12
|
+
* The keyboard steps by a half too, and each symbol becomes TWO hit areas (leading / trailing).
|
|
13
|
+
*/
|
|
14
|
+
allowHalf?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* antd `allowClear` — choosing the value that is already chosen clears it back to 0. On by
|
|
17
|
+
* default in antd; off here, because a rating inside a form is usually required and a silent
|
|
18
|
+
* reset on a second click reads as a lost answer.
|
|
19
|
+
*/
|
|
20
|
+
allowClear?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* antd `character` — what a symbol IS. A node for every symbol, or a function of the 1-based
|
|
23
|
+
* index for a scale whose symbols differ (A/B/C, 松竹梅, a heart for the top step).
|
|
24
|
+
*/
|
|
25
|
+
character?: React.ReactNode | ((index: number) => React.ReactNode);
|
|
26
|
+
/**
|
|
27
|
+
* antd `tooltips` — a label per step, in order. It is folded into each symbol's ACCESSIBLE NAME
|
|
28
|
+
* rather than shown only on hover: a `title` attribute is invisible to a keyboard and to touch,
|
|
29
|
+
* and the whole point of the prop is to say what "3 of 5" means.
|
|
30
|
+
*/
|
|
31
|
+
tooltips?: readonly string[];
|
|
7
32
|
readOnly?: boolean;
|
|
8
33
|
disabled?: boolean;
|
|
9
34
|
name?: string;
|
|
@@ -9,7 +9,12 @@ const Rating = React.forwardRef(
|
|
|
9
9
|
value,
|
|
10
10
|
defaultValue = 0,
|
|
11
11
|
onValueChange,
|
|
12
|
-
max
|
|
12
|
+
max,
|
|
13
|
+
count,
|
|
14
|
+
allowHalf = false,
|
|
15
|
+
allowClear = false,
|
|
16
|
+
character,
|
|
17
|
+
tooltips,
|
|
13
18
|
readOnly,
|
|
14
19
|
disabled,
|
|
15
20
|
name,
|
|
@@ -17,68 +22,103 @@ const Rating = React.forwardRef(
|
|
|
17
22
|
...rest
|
|
18
23
|
}, ref) => {
|
|
19
24
|
const { t } = useTranslation();
|
|
25
|
+
const symbols = count ?? max ?? 5;
|
|
20
26
|
const [internal, setInternal] = React.useState(defaultValue);
|
|
21
27
|
const current = value ?? internal;
|
|
22
28
|
const [hover, setHover] = React.useState(null);
|
|
23
29
|
const display = hover ?? current;
|
|
24
30
|
const interactive = !readOnly && !disabled;
|
|
31
|
+
const stepSize = allowHalf ? 0.5 : 1;
|
|
25
32
|
const select = (next) => {
|
|
26
33
|
if (!interactive) return;
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
const resolved = allowClear && next === current ? 0 : next;
|
|
35
|
+
if (value === void 0) setInternal(resolved);
|
|
36
|
+
onValueChange?.(resolved);
|
|
29
37
|
};
|
|
30
|
-
const focusableStar = current > 0 ? current : 1;
|
|
38
|
+
const focusableStar = current > 0 ? Math.ceil(current) : 1;
|
|
31
39
|
const onKeyDown = (e, star) => {
|
|
32
40
|
if (!interactive) return;
|
|
33
41
|
let next;
|
|
34
42
|
switch (e.key) {
|
|
35
43
|
case "ArrowRight":
|
|
36
44
|
case "ArrowUp":
|
|
37
|
-
next = Math.min(
|
|
45
|
+
next = Math.min(symbols, star + stepSize);
|
|
38
46
|
break;
|
|
39
47
|
case "ArrowLeft":
|
|
40
48
|
case "ArrowDown":
|
|
41
|
-
next = Math.max(
|
|
49
|
+
next = Math.max(stepSize, star - stepSize);
|
|
42
50
|
break;
|
|
43
51
|
case "Home":
|
|
44
|
-
next =
|
|
52
|
+
next = stepSize;
|
|
45
53
|
break;
|
|
46
54
|
case "End":
|
|
47
|
-
next =
|
|
55
|
+
next = symbols;
|
|
48
56
|
break;
|
|
49
57
|
default:
|
|
50
58
|
return;
|
|
51
59
|
}
|
|
52
60
|
e.preventDefault();
|
|
53
|
-
|
|
61
|
+
if (value === void 0) setInternal(next);
|
|
62
|
+
onValueChange?.(next);
|
|
63
|
+
};
|
|
64
|
+
const stepLabel = (star) => {
|
|
65
|
+
const tooltip = tooltips?.[star - 1];
|
|
66
|
+
const base = t("ui.rating.starLabel", { star, max: symbols });
|
|
67
|
+
return tooltip ? `${base}, ${tooltip}` : base;
|
|
54
68
|
};
|
|
69
|
+
const glyph = (star) => typeof character === "function" ? character(star) : character ?? /* @__PURE__ */ jsx(Star, { "aria-hidden": "true" });
|
|
55
70
|
return /* @__PURE__ */ jsxs(
|
|
56
71
|
"div",
|
|
57
72
|
{
|
|
58
73
|
ref,
|
|
59
74
|
role: "radiogroup",
|
|
60
75
|
"data-slot": "rating",
|
|
76
|
+
"data-allow-half": allowHalf ? "true" : void 0,
|
|
61
77
|
className: cn("ui-rating", className),
|
|
62
78
|
"aria-label": rest["aria-label"] ?? t("ui.rating.ariaLabel"),
|
|
63
79
|
children: [
|
|
64
|
-
Array.from({ length:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
Array.from({ length: symbols }, (_, i) => i + 1).map((star) => {
|
|
81
|
+
const symbol = /* @__PURE__ */ jsx(
|
|
82
|
+
"button",
|
|
83
|
+
{
|
|
84
|
+
type: "button",
|
|
85
|
+
role: "radio",
|
|
86
|
+
"aria-checked": current === star,
|
|
87
|
+
"aria-label": stepLabel(star),
|
|
88
|
+
disabled: disabled || readOnly,
|
|
89
|
+
tabIndex: interactive && star === focusableStar ? 0 : -1,
|
|
90
|
+
className: cn(
|
|
91
|
+
"ui-rating-star",
|
|
92
|
+
star <= display && "ui-rating-star-filled",
|
|
93
|
+
allowHalf && star - 0.5 === display && "ui-rating-star-half-filled"
|
|
94
|
+
),
|
|
95
|
+
onMouseEnter: () => interactive && setHover(star),
|
|
96
|
+
onMouseLeave: () => setHover(null),
|
|
97
|
+
onClick: () => select(star),
|
|
98
|
+
onKeyDown: (e) => onKeyDown(e, star),
|
|
99
|
+
children: glyph(star)
|
|
100
|
+
},
|
|
101
|
+
star
|
|
102
|
+
);
|
|
103
|
+
if (!allowHalf) return symbol;
|
|
104
|
+
return /* @__PURE__ */ jsxs("span", { "data-slot": "rating-symbol", className: "ui-rating-symbol", children: [
|
|
105
|
+
/* @__PURE__ */ jsx(
|
|
106
|
+
"button",
|
|
107
|
+
{
|
|
108
|
+
type: "button",
|
|
109
|
+
tabIndex: -1,
|
|
110
|
+
"aria-hidden": "true",
|
|
111
|
+
disabled: disabled || readOnly,
|
|
112
|
+
"data-slot": "rating-half",
|
|
113
|
+
className: "ui-rating-star-half",
|
|
114
|
+
onMouseEnter: () => interactive && setHover(star - 0.5),
|
|
115
|
+
onMouseLeave: () => setHover(null),
|
|
116
|
+
onClick: () => select(star - 0.5)
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
symbol
|
|
120
|
+
] }, star);
|
|
121
|
+
}),
|
|
82
122
|
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: current }) : null
|
|
83
123
|
]
|
|
84
124
|
}
|
|
@@ -18,6 +18,15 @@ export type SegmentedProp = {
|
|
|
18
18
|
/** Uncontrolled initial selection. */
|
|
19
19
|
defaultValue?: string;
|
|
20
20
|
onValueChange?: (value: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* antd `block` — stretch the bar to its container and share the width EQUALLY between the
|
|
23
|
+
* choices, so the selected pill does not resize as the label changes length.
|
|
24
|
+
*/
|
|
25
|
+
block?: boolean;
|
|
26
|
+
/** antd `vertical` — stack the choices in a column. Arrow keys follow the axis. */
|
|
27
|
+
vertical?: boolean;
|
|
28
|
+
/** Control height tier: `md` (default), `sm` or `lg` — the same tiers as every other control. */
|
|
29
|
+
size?: "sm" | "md" | "lg";
|
|
21
30
|
/** Disable the whole group. */
|
|
22
31
|
disabled?: boolean;
|
|
23
32
|
/** Form field name — submits the selected value with the form. */
|
|
@@ -3,15 +3,30 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
const Segmented = React.forwardRef(function Segmented2({
|
|
6
|
+
const Segmented = React.forwardRef(function Segmented2({
|
|
7
|
+
options,
|
|
8
|
+
value,
|
|
9
|
+
defaultValue,
|
|
10
|
+
onValueChange,
|
|
11
|
+
disabled,
|
|
12
|
+
block = false,
|
|
13
|
+
vertical = false,
|
|
14
|
+
size,
|
|
15
|
+
name,
|
|
16
|
+
id,
|
|
17
|
+
className,
|
|
18
|
+
...props
|
|
19
|
+
}, ref) {
|
|
7
20
|
return /* @__PURE__ */ jsx(
|
|
8
21
|
RadioGroupPrimitive.Root,
|
|
9
22
|
{
|
|
10
23
|
ref,
|
|
11
24
|
id,
|
|
12
25
|
"data-slot": "segmented",
|
|
26
|
+
"data-block": block ? "true" : void 0,
|
|
27
|
+
"data-size": size,
|
|
13
28
|
className: cn("ui-segmented", className),
|
|
14
|
-
orientation: "horizontal",
|
|
29
|
+
orientation: vertical ? "vertical" : "horizontal",
|
|
15
30
|
value,
|
|
16
31
|
defaultValue,
|
|
17
32
|
onValueChange,
|
|
@@ -12,6 +12,10 @@ export type { SeparatorProp, SeparatorProp as SeparatorProps, } from "../../prop
|
|
|
12
12
|
* the ref, and we decide what element carries them.
|
|
13
13
|
*/
|
|
14
14
|
export declare const Separator: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
15
|
+
labelSize?: "2xs" | "xs" | "sm" | "md";
|
|
16
|
+
space?: import("../../props/index.js").GapProp;
|
|
17
|
+
hideBelow?: import("../../props/index.js").BreakpointProp;
|
|
18
|
+
hideFrom?: import("../../props/index.js").BreakpointProp;
|
|
15
19
|
orientation?: import("../../props/index.js").OrientationProp;
|
|
16
20
|
label?: string;
|
|
17
21
|
labelAlign?: import("../../props/index.js").TextAlignProp;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { Separator as AriaSeparator } from "react-aria-components";
|
|
4
|
+
import { padStepToken } from "../../lib/variants.js";
|
|
4
5
|
import { cn } from "../../lib/utils.js";
|
|
5
6
|
const Separator = React.forwardRef(
|
|
6
7
|
({
|
|
7
8
|
className,
|
|
9
|
+
labelSize,
|
|
10
|
+
space,
|
|
11
|
+
hideBelow,
|
|
12
|
+
hideFrom,
|
|
13
|
+
style,
|
|
8
14
|
orientation = "horizontal",
|
|
9
15
|
decorative,
|
|
10
16
|
label,
|
|
@@ -28,6 +34,13 @@ const Separator = React.forwardRef(
|
|
|
28
34
|
ref,
|
|
29
35
|
elementType: "div",
|
|
30
36
|
"data-slot": "separator",
|
|
37
|
+
"data-label-size": labelSize,
|
|
38
|
+
"data-hide-below": hideBelow,
|
|
39
|
+
"data-hide-from": hideFrom,
|
|
40
|
+
style: {
|
|
41
|
+
...style,
|
|
42
|
+
...space === void 0 ? void 0 : { marginBlock: padStepToken(space) }
|
|
43
|
+
},
|
|
31
44
|
"data-orientation": orientation,
|
|
32
45
|
"data-tone": tone,
|
|
33
46
|
"data-labelled": labelled ? "" : void 0,
|
|
@@ -1,13 +1,58 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import type { AllowClearProp, ControlStatusProp, ControlVariantProp, MaxTagCountProp, MaxTagPlaceholderProp, SizeProp } from "../../props/vocabulary/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* TagInput is this library's answer to antd's `Select mode="tags"` — a free-text token field — so
|
|
5
|
+
* it takes the same token-level props antd puts on that mode.
|
|
6
|
+
*/
|
|
2
7
|
export type TagInputProps = {
|
|
3
8
|
value?: string[];
|
|
4
9
|
defaultValue?: string[];
|
|
5
10
|
onValueChange?: (tags: string[]) => void;
|
|
6
11
|
placeholder?: string;
|
|
7
12
|
disabled?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Read-only: the tags stay visible, selectable and submitted, but nothing can be added or
|
|
15
|
+
* removed — the draft field is read-only, the chip removers and the clear ✕ are withdrawn, and
|
|
16
|
+
* the container reports `aria-readonly`. Mirrors Select's readOnly contract (still focusable and
|
|
17
|
+
* still in the tab order, unlike `disabled`).
|
|
18
|
+
*/
|
|
19
|
+
readOnly?: boolean;
|
|
8
20
|
name?: string;
|
|
9
21
|
className?: string;
|
|
10
22
|
id?: string;
|
|
11
23
|
"aria-label"?: string;
|
|
24
|
+
/** Control height tier (antd `size`) — the shared `--control-height` ladder. */
|
|
25
|
+
size?: SizeProp;
|
|
26
|
+
/** Validation status (antd `status`). `error` also sets `aria-invalid`; `warning` recolours only. */
|
|
27
|
+
status?: ControlStatusProp;
|
|
28
|
+
/** Control surface (antd `variant`). Default `outlined`. */
|
|
29
|
+
variant?: ControlVariantProp;
|
|
30
|
+
/** Hard ceiling on how many tags may be held (antd `maxCount`). Further input is refused. */
|
|
31
|
+
maxCount?: number;
|
|
32
|
+
/**
|
|
33
|
+
* antd `allowClear` — a single ✕ that drops EVERY tag at once. Off by default (antd's own
|
|
34
|
+
* default for a tags field). The object form replaces the icon and/or the accessible label.
|
|
35
|
+
*/
|
|
36
|
+
allowClear?: AllowClearProp;
|
|
37
|
+
/** Fired after every tag is dropped through the ✕ (antd `onClear`). */
|
|
38
|
+
onClear?: () => void;
|
|
39
|
+
/** How many chips render before the rest collapse into the overflow node (antd `maxTagCount`). */
|
|
40
|
+
maxTagCount?: MaxTagCountProp;
|
|
41
|
+
/** The node standing in for what `maxTagCount` hid (antd `maxTagPlaceholder`). */
|
|
42
|
+
maxTagPlaceholder?: MaxTagPlaceholderProp;
|
|
43
|
+
/** Render one chip yourself (antd `tagRender`) — receives the value and an `onClose` remover. */
|
|
44
|
+
tagRender?: (props: {
|
|
45
|
+
value: string;
|
|
46
|
+
label: React.ReactNode;
|
|
47
|
+
onClose: () => void;
|
|
48
|
+
index: number;
|
|
49
|
+
disabled: boolean;
|
|
50
|
+
}) => React.ReactNode;
|
|
51
|
+
/**
|
|
52
|
+
* Characters that commit the draft into a tag (antd `tokenSeparators`). Default `[","]`; Enter
|
|
53
|
+
* always commits and is not a separator. Pasting a run containing a separator splits it into
|
|
54
|
+
* several tags, which is antd's behaviour and the reason the prop exists.
|
|
55
|
+
*/
|
|
56
|
+
tokenSeparators?: string[];
|
|
12
57
|
};
|
|
13
58
|
export declare const TagInput: React.ForwardRefExoticComponent<TagInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { X } from "lucide-react";
|
|
5
5
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import {
|
|
8
|
+
applyMaxTagCount,
|
|
9
|
+
controlSurfaceAttrs,
|
|
10
|
+
resolveAllowClear
|
|
11
|
+
} from "../data-entry/control-surface.js";
|
|
12
|
+
function escapeForCharClass(character) {
|
|
13
|
+
return character.replace(/[\\\]^-]/g, "\\$&");
|
|
14
|
+
}
|
|
7
15
|
const TagInput = React.forwardRef(
|
|
8
16
|
({
|
|
9
17
|
value,
|
|
@@ -11,10 +19,21 @@ const TagInput = React.forwardRef(
|
|
|
11
19
|
onValueChange,
|
|
12
20
|
placeholder,
|
|
13
21
|
disabled,
|
|
22
|
+
readOnly,
|
|
14
23
|
name,
|
|
15
24
|
className,
|
|
16
25
|
id,
|
|
17
|
-
"aria-label": ariaLabel
|
|
26
|
+
"aria-label": ariaLabel,
|
|
27
|
+
size,
|
|
28
|
+
status,
|
|
29
|
+
variant,
|
|
30
|
+
maxCount,
|
|
31
|
+
allowClear,
|
|
32
|
+
onClear,
|
|
33
|
+
maxTagCount,
|
|
34
|
+
maxTagPlaceholder,
|
|
35
|
+
tagRender,
|
|
36
|
+
tokenSeparators = [","]
|
|
18
37
|
}, ref) => {
|
|
19
38
|
const { t } = useTranslation();
|
|
20
39
|
const [internal, setInternal] = React.useState(defaultValue);
|
|
@@ -27,11 +46,25 @@ const TagInput = React.forwardRef(
|
|
|
27
46
|
const add = (raw) => {
|
|
28
47
|
const tag = raw.trim();
|
|
29
48
|
if (!tag || tags.includes(tag)) return;
|
|
49
|
+
if (maxCount !== void 0 && tags.length >= maxCount) return;
|
|
30
50
|
commit([...tags, tag]);
|
|
31
51
|
};
|
|
52
|
+
const addAll = (raw) => {
|
|
53
|
+
let next = [...tags];
|
|
54
|
+
const pieces = tokenSeparators.length ? raw.split(new RegExp(`[${tokenSeparators.map(escapeForCharClass).join("")}]`)) : [raw];
|
|
55
|
+
for (const piece of pieces) {
|
|
56
|
+
const tag = piece.trim();
|
|
57
|
+
if (!tag || next.includes(tag)) continue;
|
|
58
|
+
if (maxCount !== void 0 && next.length >= maxCount) break;
|
|
59
|
+
next = [...next, tag];
|
|
60
|
+
}
|
|
61
|
+
if (next.length !== tags.length) commit(next);
|
|
62
|
+
};
|
|
32
63
|
const removeAt = (i) => commit(tags.filter((_, idx) => idx !== i));
|
|
33
64
|
const onKeyDown = (e) => {
|
|
34
|
-
if (
|
|
65
|
+
if (readOnly) return;
|
|
66
|
+
if (e.nativeEvent.isComposing) return;
|
|
67
|
+
if (e.key === "Enter" || tokenSeparators.includes(e.key)) {
|
|
35
68
|
e.preventDefault();
|
|
36
69
|
add(draft);
|
|
37
70
|
setDraft("");
|
|
@@ -39,35 +72,63 @@ const TagInput = React.forwardRef(
|
|
|
39
72
|
removeAt(tags.length - 1);
|
|
40
73
|
}
|
|
41
74
|
};
|
|
75
|
+
const clearControl = resolveAllowClear(allowClear, false, t("common.clear"));
|
|
76
|
+
const showClear = clearControl.enabled && tags.length > 0 && !disabled && !readOnly;
|
|
77
|
+
const clearAll = () => {
|
|
78
|
+
commit([]);
|
|
79
|
+
onClear?.();
|
|
80
|
+
};
|
|
81
|
+
const chips = tags.map((tag, index) => ({ value: tag, label: tag, index }));
|
|
82
|
+
const {
|
|
83
|
+
visible: visibleChips,
|
|
84
|
+
omitted: omittedChips,
|
|
85
|
+
overflow
|
|
86
|
+
} = applyMaxTagCount(chips, maxTagCount, maxTagPlaceholder);
|
|
42
87
|
return /* @__PURE__ */ jsxs(
|
|
43
88
|
"div",
|
|
44
89
|
{
|
|
45
90
|
"data-slot": "tag-input",
|
|
46
91
|
"aria-disabled": disabled || void 0,
|
|
47
|
-
|
|
92
|
+
"aria-readonly": readOnly || void 0,
|
|
93
|
+
...controlSurfaceAttrs({ variant, status, size }),
|
|
94
|
+
"aria-invalid": status === "error" ? true : void 0,
|
|
95
|
+
className: cn(
|
|
96
|
+
"ui-tag-input ui-control-surface",
|
|
97
|
+
disabled && "ui-tag-input-disabled",
|
|
98
|
+
className
|
|
99
|
+
),
|
|
48
100
|
children: [
|
|
49
|
-
tags.length > 0 ? /* @__PURE__ */
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
101
|
+
tags.length > 0 ? /* @__PURE__ */ jsxs("ul", { role: "list", className: "ui-tag-input-list", "data-slot": "tag-input-list", children: [
|
|
102
|
+
visibleChips.map((chip) => /* @__PURE__ */ jsx(
|
|
103
|
+
"li",
|
|
104
|
+
{
|
|
105
|
+
role: "listitem",
|
|
106
|
+
className: "ui-tag-input-chip",
|
|
107
|
+
"data-slot": "tag-input-chip",
|
|
108
|
+
children: tagRender ? tagRender({
|
|
109
|
+
value: chip.value,
|
|
110
|
+
label: chip.label,
|
|
111
|
+
index: chip.index,
|
|
112
|
+
disabled: Boolean(disabled) || Boolean(readOnly),
|
|
113
|
+
onClose: () => removeAt(chip.index)
|
|
114
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
115
|
+
chip.value,
|
|
116
|
+
!disabled && !readOnly ? /* @__PURE__ */ jsx(
|
|
117
|
+
"button",
|
|
118
|
+
{
|
|
119
|
+
type: "button",
|
|
120
|
+
className: "ui-tag-input-remove",
|
|
121
|
+
"aria-label": t("ui.tagInput.removeTag", { tag: chip.value }),
|
|
122
|
+
onClick: () => removeAt(chip.index),
|
|
123
|
+
children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
|
|
124
|
+
}
|
|
125
|
+
) : null
|
|
126
|
+
] })
|
|
127
|
+
},
|
|
128
|
+
chip.value
|
|
129
|
+
)),
|
|
130
|
+
omittedChips.length > 0 ? /* @__PURE__ */ jsx("li", { role: "listitem", className: "ui-tag-input-chip", "data-slot": "tag-input-overflow", children: overflow ?? t("dataEntry.selection.overflow", { count: omittedChips.length }) }) : null
|
|
131
|
+
] }) : null,
|
|
71
132
|
/* @__PURE__ */ jsx(
|
|
72
133
|
"input",
|
|
73
134
|
{
|
|
@@ -76,12 +137,21 @@ const TagInput = React.forwardRef(
|
|
|
76
137
|
type: "text",
|
|
77
138
|
className: "ui-tag-input-field",
|
|
78
139
|
value: draft,
|
|
79
|
-
placeholder: tags.length === 0 ? placeholder : void 0,
|
|
140
|
+
placeholder: tags.length === 0 && !readOnly ? placeholder : void 0,
|
|
80
141
|
disabled,
|
|
142
|
+
readOnly,
|
|
81
143
|
"aria-label": ariaLabel ?? t("ui.tagInput.inputLabel"),
|
|
82
144
|
onChange: (e) => setDraft(e.target.value),
|
|
83
145
|
onKeyDown,
|
|
146
|
+
onPaste: (e) => {
|
|
147
|
+
const text = e.clipboardData.getData("text");
|
|
148
|
+
if (!tokenSeparators.some((separator) => text.includes(separator))) return;
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
addAll(text);
|
|
151
|
+
setDraft("");
|
|
152
|
+
},
|
|
84
153
|
onBlur: () => {
|
|
154
|
+
if (readOnly) return;
|
|
85
155
|
if (draft.trim()) {
|
|
86
156
|
add(draft);
|
|
87
157
|
setDraft("");
|
|
@@ -89,6 +159,18 @@ const TagInput = React.forwardRef(
|
|
|
89
159
|
}
|
|
90
160
|
}
|
|
91
161
|
),
|
|
162
|
+
showClear ? /* @__PURE__ */ jsx(
|
|
163
|
+
"button",
|
|
164
|
+
{
|
|
165
|
+
type: "button",
|
|
166
|
+
tabIndex: -1,
|
|
167
|
+
"aria-label": clearControl.label,
|
|
168
|
+
"data-slot": "tag-input-clear",
|
|
169
|
+
className: "ui-control-inline-affix-action ui-tag-input-clear",
|
|
170
|
+
onClick: clearAll,
|
|
171
|
+
children: clearControl.clearIcon ?? /* @__PURE__ */ jsx(X, { className: "ui-control-inline-affix-icon", "aria-hidden": "true" })
|
|
172
|
+
}
|
|
173
|
+
) : null,
|
|
92
174
|
/* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", "data-slot": "tag-input-status", children: t("ui.tagInput.tagCount", { count: tags.length }) }),
|
|
93
175
|
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: tags.join(",") }) : null
|
|
94
176
|
]
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Control, type FieldPath, type FieldValues, type UseFormReturn } from "react-hook-form";
|
|
1
2
|
import type { FormStateAdapter } from "../props/components/form.prop.js";
|
|
2
3
|
/**
|
|
3
4
|
* Context carrying a framework-agnostic {@link FormStateAdapter}. `FormRoot` provides it on the
|
|
@@ -7,11 +8,39 @@ import type { FormStateAdapter } from "../props/components/form.prop.js";
|
|
|
7
8
|
export declare const FormAdapterContext: import("react").Context<FormStateAdapter | null>;
|
|
8
9
|
/** Read the active form-state adapter, or `null` when `FormRoot` runs the react-hook-form path. */
|
|
9
10
|
export declare function useFormAdapter(): FormStateAdapter | null;
|
|
11
|
+
/** Form-wide options shared by BOTH paths — currently the antd-style form-level `disabled`. */
|
|
12
|
+
export interface FormOptionsContextValue {
|
|
13
|
+
disabled: boolean;
|
|
14
|
+
submitting?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Defaults to enabled so a `FormField`/`FormFieldControl` outside a `FormRoot` keeps working. */
|
|
17
|
+
export declare const FormOptionsContext: import("react").Context<FormOptionsContextValue>;
|
|
18
|
+
/**
|
|
19
|
+
* Whether the surrounding `FormRoot` disables its fields (`FormRoot disabled`). Read it for the
|
|
20
|
+
* action buttons, which are NOT fields and so are never disabled automatically.
|
|
21
|
+
*/
|
|
22
|
+
export declare function useFormDisabled(): boolean;
|
|
10
23
|
/**
|
|
11
24
|
* Whether the surrounding `FormRoot` is currently submitting — works for BOTH paths: the adapter's
|
|
12
25
|
* `isSubmitting` (e.g. Inertia's `processing`) or react-hook-form's `formState.isSubmitting`.
|
|
13
26
|
*/
|
|
14
27
|
export declare function useFormSubmitting(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The react-hook-form instance of the surrounding `FormRoot` (antd `Form.useFormInstance`) — for
|
|
30
|
+
* `setValue`/`trigger`/`getValues` deep inside a form without prop-drilling `form`. Throws on the
|
|
31
|
+
* adapter path, which has no RHF instance; use {@link useFormAdapter} there.
|
|
32
|
+
*/
|
|
33
|
+
export declare function useFormInstance<TFieldValues extends FieldValues = FieldValues>(): UseFormReturn<TFieldValues>;
|
|
34
|
+
export declare function getFallbackFormControl(): Control<FieldValues>;
|
|
35
|
+
/**
|
|
36
|
+
* Subscribe to a field's value (antd `Form.useWatch`) — the "show this section only when `plan`
|
|
37
|
+
* is `enterprise`" case, WITHOUT re-rendering the whole form. Omit `name` for every value.
|
|
38
|
+
* Works on both paths: react-hook-form's `useWatch`, or the adapter's `getValue`/`getValues`.
|
|
39
|
+
*
|
|
40
|
+
* Returns `unknown` — the same contract as `FormFieldControl`'s render-prop `value`. Narrow at the
|
|
41
|
+
* call site (`String(v ?? "")`, a Zod parse, a type guard).
|
|
42
|
+
*/
|
|
43
|
+
export declare function useFormWatch<TFieldValues extends FieldValues = FieldValues>(name?: FieldPath<TFieldValues>): unknown;
|
|
15
44
|
/**
|
|
16
45
|
* Normalise a control's change payload to a bare value. The `FormFieldControl` render-prop spreads
|
|
17
46
|
* `onChange` onto a control that may call it with a DOM `ChangeEvent` (native `<Input>`) OR a raw
|