@lerianstudio/sindarian-ui 2.0.0-beta.1 → 2.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/breadcrumb/index.d.ts.map +1 -1
- package/dist/components/breadcrumb/index.js +25 -1
- package/dist/components/card/account-card/index.js +5 -5
- package/dist/components/card/basic-card/index.d.ts.map +1 -1
- package/dist/components/card/basic-card/index.js +2 -2
- package/dist/components/card/entity-card/index.js +1 -1
- package/dist/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
- package/dist/components/dialog/confirmation-dialog/index.js +4 -1
- package/dist/components/entity-box/index.d.ts +18 -2
- package/dist/components/entity-box/index.d.ts.map +1 -1
- package/dist/components/entity-box/index.js +32 -4
- package/dist/components/form/file-upload-field/index.d.ts +11 -2
- package/dist/components/form/file-upload-field/index.d.ts.map +1 -1
- package/dist/components/form/file-upload-field/index.js +8 -3
- package/dist/components/form/input-field/index.d.ts +41 -2
- package/dist/components/form/input-field/index.d.ts.map +1 -1
- package/dist/components/form/input-field/index.js +73 -15
- package/dist/components/form/password-field/index.d.ts +5 -1
- package/dist/components/form/password-field/index.d.ts.map +1 -1
- package/dist/components/form/password-field/index.js +2 -2
- package/dist/components/form/select-field/index.d.ts +9 -1
- package/dist/components/form/select-field/index.d.ts.map +1 -1
- package/dist/components/form/select-field/index.js +2 -2
- package/dist/components/page-header/index.js +1 -1
- package/dist/components/table/id-table-cell.d.ts +5 -1
- package/dist/components/table/id-table-cell.d.ts.map +1 -1
- package/dist/components/table/id-table-cell.js +48 -6
- package/dist/components/ui/autocomplete/index.d.ts +24 -0
- package/dist/components/ui/autocomplete/index.d.ts.map +1 -1
- package/dist/components/ui/autocomplete/index.js +24 -0
- package/dist/components/ui/badge/index.d.ts +11 -7
- package/dist/components/ui/badge/index.d.ts.map +1 -1
- package/dist/components/ui/badge/index.js +20 -8
- package/dist/components/ui/button/styles.css +31 -1
- package/dist/components/ui/calendar/index.d.ts.map +1 -1
- package/dist/components/ui/calendar/index.js +7 -1
- package/dist/components/ui/copy-field/index.d.ts.map +1 -1
- package/dist/components/ui/copy-field/index.js +1 -1
- package/dist/components/ui/file-upload/index.d.ts +235 -9
- package/dist/components/ui/file-upload/index.d.ts.map +1 -1
- package/dist/components/ui/file-upload/index.js +354 -17
- package/dist/components/ui/form.d.ts +4 -0
- package/dist/components/ui/form.d.ts.map +1 -1
- package/dist/components/ui/form.js +48 -6
- package/dist/components/ui/input/styles.css +30 -2
- package/dist/components/ui/sheet/index.d.ts.map +1 -1
- package/dist/components/ui/sheet/index.js +2 -2
- package/dist/components/ui/sidebar/index.d.ts +1 -0
- package/dist/components/ui/sidebar/index.d.ts.map +1 -1
- package/dist/components/ui/sidebar/index.js +1 -0
- package/dist/components/ui/sidebar/sidebar-expand-button.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
- package/dist/components/ui/sidebar/sidebar-expand-button.js +15 -1
- package/dist/components/ui/sidebar/sidebar-item.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-item.d.ts.map +1 -1
- package/dist/components/ui/sidebar/sidebar-item.js +28 -4
- package/dist/components/ui/sidebar/sidebar-provider.d.ts +37 -0
- package/dist/components/ui/sidebar/sidebar-provider.d.ts.map +1 -1
- package/dist/components/ui/sidebar/sidebar-provider.js +125 -4
- package/dist/components/ui/sidebar/sidebar-root.d.ts +38 -1
- package/dist/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
- package/dist/components/ui/sidebar/sidebar-root.js +100 -5
- package/dist/components/ui/sidebar/sidebar-trigger.d.ts +18 -0
- package/dist/components/ui/sidebar/sidebar-trigger.d.ts.map +1 -0
- package/dist/components/ui/sidebar/sidebar-trigger.js +30 -0
- package/dist/components/ui/toggle-group/index.d.ts +1 -1
- package/dist/components/ui/toggle-group/index.d.ts.map +1 -1
- package/dist/components/ui/toggle-group/index.js +73 -4
- package/dist/esm/components/breadcrumb/index.d.ts.map +1 -1
- package/dist/esm/components/breadcrumb/index.js +25 -1
- package/dist/esm/components/card/account-card/index.js +5 -5
- package/dist/esm/components/card/basic-card/index.d.ts.map +1 -1
- package/dist/esm/components/card/basic-card/index.js +2 -2
- package/dist/esm/components/card/entity-card/index.js +1 -1
- package/dist/esm/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
- package/dist/esm/components/dialog/confirmation-dialog/index.js +4 -1
- package/dist/esm/components/entity-box/index.d.ts +18 -2
- package/dist/esm/components/entity-box/index.d.ts.map +1 -1
- package/dist/esm/components/entity-box/index.js +29 -4
- package/dist/esm/components/form/file-upload-field/index.d.ts +11 -2
- package/dist/esm/components/form/file-upload-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/file-upload-field/index.js +8 -3
- package/dist/esm/components/form/input-field/index.d.ts +41 -2
- package/dist/esm/components/form/input-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/input-field/index.js +73 -15
- package/dist/esm/components/form/password-field/index.d.ts +5 -1
- package/dist/esm/components/form/password-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/password-field/index.js +2 -2
- package/dist/esm/components/form/select-field/index.d.ts +9 -1
- package/dist/esm/components/form/select-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/select-field/index.js +2 -2
- package/dist/esm/components/page-header/index.js +1 -1
- package/dist/esm/components/table/id-table-cell.d.ts +5 -1
- package/dist/esm/components/table/id-table-cell.d.ts.map +1 -1
- package/dist/esm/components/table/id-table-cell.js +48 -3
- package/dist/esm/components/ui/autocomplete/index.d.ts +24 -0
- package/dist/esm/components/ui/autocomplete/index.d.ts.map +1 -1
- package/dist/esm/components/ui/autocomplete/index.js +24 -0
- package/dist/esm/components/ui/badge/index.d.ts +11 -7
- package/dist/esm/components/ui/badge/index.d.ts.map +1 -1
- package/dist/esm/components/ui/badge/index.js +20 -8
- package/dist/esm/components/ui/calendar/index.d.ts.map +1 -1
- package/dist/esm/components/ui/calendar/index.js +8 -2
- package/dist/esm/components/ui/copy-field/index.d.ts.map +1 -1
- package/dist/esm/components/ui/copy-field/index.js +1 -1
- package/dist/esm/components/ui/file-upload/index.d.ts +235 -9
- package/dist/esm/components/ui/file-upload/index.d.ts.map +1 -1
- package/dist/esm/components/ui/file-upload/index.js +353 -17
- package/dist/esm/components/ui/form.d.ts +4 -0
- package/dist/esm/components/ui/form.d.ts.map +1 -1
- package/dist/esm/components/ui/form.js +48 -6
- package/dist/esm/components/ui/sheet/index.d.ts.map +1 -1
- package/dist/esm/components/ui/sheet/index.js +2 -2
- package/dist/esm/components/ui/sidebar/index.d.ts +1 -0
- package/dist/esm/components/ui/sidebar/index.d.ts.map +1 -1
- package/dist/esm/components/ui/sidebar/index.js +1 -0
- package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts +1 -1
- package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
- package/dist/esm/components/ui/sidebar/sidebar-expand-button.js +15 -1
- package/dist/esm/components/ui/sidebar/sidebar-item.d.ts +1 -1
- package/dist/esm/components/ui/sidebar/sidebar-item.d.ts.map +1 -1
- package/dist/esm/components/ui/sidebar/sidebar-item.js +28 -4
- package/dist/esm/components/ui/sidebar/sidebar-provider.d.ts +37 -0
- package/dist/esm/components/ui/sidebar/sidebar-provider.d.ts.map +1 -1
- package/dist/esm/components/ui/sidebar/sidebar-provider.js +122 -1
- package/dist/esm/components/ui/sidebar/sidebar-root.d.ts +38 -1
- package/dist/esm/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
- package/dist/esm/components/ui/sidebar/sidebar-root.js +102 -7
- package/dist/esm/components/ui/sidebar/sidebar-trigger.d.ts +18 -0
- package/dist/esm/components/ui/sidebar/sidebar-trigger.d.ts.map +1 -0
- package/dist/esm/components/ui/sidebar/sidebar-trigger.js +26 -0
- package/dist/esm/components/ui/toggle-group/index.d.ts +1 -1
- package/dist/esm/components/ui/toggle-group/index.d.ts.map +1 -1
- package/dist/esm/components/ui/toggle-group/index.js +73 -4
- package/dist/globals.css +77 -31
- package/package.json +5 -3
|
@@ -63,12 +63,58 @@ const toggleVariants = (0, class_variance_authority_1.cva)("hover:bg-muted hover
|
|
|
63
63
|
size: 'default'
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
|
+
const ARROW_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
|
|
67
|
+
/**
|
|
68
|
+
* Is an arrow key down right now?
|
|
69
|
+
*
|
|
70
|
+
* This is how an item tells keyboard navigation apart from a pointer press or a
|
|
71
|
+
* programmatic focus, and it is the seam Radix uses for the same job in its own
|
|
72
|
+
* `RadioGroup`. It works because `RovingFocusGroup` defers the focus move to a
|
|
73
|
+
* `setTimeout`: the keydown has already bubbled to `document` and set the flag
|
|
74
|
+
* by the time the item receives `focus`.
|
|
75
|
+
*
|
|
76
|
+
* The distinction is not cosmetic. A pointer press focuses BEFORE the click
|
|
77
|
+
* lands, so selecting on every focus would turn one click into
|
|
78
|
+
* select-then-deselect and break mouse selection outright.
|
|
79
|
+
*
|
|
80
|
+
* Returns null when disabled, so `type="multiple"` carries no flag to read.
|
|
81
|
+
*/
|
|
82
|
+
function useArrowKeyPressed(enabled) {
|
|
83
|
+
const arrowKeyPressed = React.useRef(false);
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
if (!enabled)
|
|
86
|
+
return;
|
|
87
|
+
const onKeyDown = (event) => {
|
|
88
|
+
if (ARROW_KEYS.includes(event.key))
|
|
89
|
+
arrowKeyPressed.current = true;
|
|
90
|
+
};
|
|
91
|
+
const onKeyUp = () => {
|
|
92
|
+
arrowKeyPressed.current = false;
|
|
93
|
+
};
|
|
94
|
+
document.addEventListener('keydown', onKeyDown);
|
|
95
|
+
document.addEventListener('keyup', onKeyUp);
|
|
96
|
+
window.addEventListener('blur', onKeyUp);
|
|
97
|
+
return () => {
|
|
98
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
99
|
+
document.removeEventListener('keyup', onKeyUp);
|
|
100
|
+
window.removeEventListener('blur', onKeyUp);
|
|
101
|
+
// A group unmounted mid-keystroke never sees the keyup.
|
|
102
|
+
arrowKeyPressed.current = false;
|
|
103
|
+
};
|
|
104
|
+
}, [enabled]);
|
|
105
|
+
return enabled ? arrowKeyPressed : null;
|
|
106
|
+
}
|
|
66
107
|
const ToggleGroupContext = React.createContext({
|
|
67
108
|
size: 'default',
|
|
68
109
|
variant: 'default',
|
|
69
|
-
spacing: 0
|
|
110
|
+
spacing: 0,
|
|
111
|
+
arrowKeyPressed: null
|
|
70
112
|
});
|
|
71
113
|
function ToggleGroup({ className, variant, size, spacing = 0, children, style, ...props }) {
|
|
114
|
+
// Read, never destructured: `type` is the discriminant of the Radix props
|
|
115
|
+
// union, and pulling it out then spreading it back widens the union so the
|
|
116
|
+
// single/multiple props stop resolving.
|
|
117
|
+
const arrowKeyPressed = useArrowKeyPressed(props.type === 'single');
|
|
72
118
|
return ((0, jsx_runtime_1.jsx)(ToggleGroupPrimitive.Root, { "data-slot": "toggle-group", "data-variant": variant, "data-size": size, "data-spacing": spacing,
|
|
73
119
|
// Caller style first: `--gap` is ours and must survive, but everything
|
|
74
120
|
// else the caller passes has to reach the element.
|
|
@@ -76,12 +122,35 @@ function ToggleGroup({ className, variant, size, spacing = 0, children, style, .
|
|
|
76
122
|
// Legacy carried a `data-[spacing=default]:...:shadow-xs` rule here that
|
|
77
123
|
// never matched — `data-spacing` is always a number. Removed rather than
|
|
78
124
|
// activated, so the rendered pixels stay identical to sindarian-x.
|
|
79
|
-
'group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md', className), ...props, children: (0, jsx_runtime_1.jsx)(ToggleGroupContext.Provider, { value: { variant, size, spacing }, children: children }) }));
|
|
125
|
+
'group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md', className), ...props, children: (0, jsx_runtime_1.jsx)(ToggleGroupContext.Provider, { value: { variant, size, spacing, arrowKeyPressed }, children: children }) }));
|
|
80
126
|
}
|
|
81
|
-
function ToggleGroupItem({ className, children, variant, size, ...props }) {
|
|
127
|
+
function ToggleGroupItem({ className, children, variant, size, onFocus, ...props }) {
|
|
82
128
|
const context = React.useContext(ToggleGroupContext);
|
|
129
|
+
/**
|
|
130
|
+
* Selection follows focus, which is what `role="radio"` promises.
|
|
131
|
+
*
|
|
132
|
+
* With `type="single"` Radix puts the group on the ARIA radio pattern: the
|
|
133
|
+
* root is a `radiogroup`, each item a `radio` with `aria-checked`. Under that
|
|
134
|
+
* pattern an arrow key both moves focus and checks the item it lands on.
|
|
135
|
+
* Radix only moves focus, so a screen-reader operator used to arrow across
|
|
136
|
+
* "radio, not checked, 2 of 3" with nothing ever selected.
|
|
137
|
+
*
|
|
138
|
+
* `type="multiple"` is a `toolbar` of `aria-pressed` buttons and keeps its
|
|
139
|
+
* current behavior, where moving focus without pressing is correct: the flag
|
|
140
|
+
* is null there.
|
|
141
|
+
*
|
|
142
|
+
* Clicking the element rather than writing the value keeps a single
|
|
143
|
+
* activation path, so Radix's own toggle and any caller `onClick` both fire
|
|
144
|
+
* exactly as they do for a real click.
|
|
145
|
+
*/
|
|
146
|
+
const handleFocus = (event) => {
|
|
147
|
+
onFocus?.(event);
|
|
148
|
+
if (context.arrowKeyPressed?.current) {
|
|
149
|
+
event.currentTarget.click();
|
|
150
|
+
}
|
|
151
|
+
};
|
|
83
152
|
return ((0, jsx_runtime_1.jsx)(ToggleGroupPrimitive.Item, { "data-slot": "toggle-group-item", "data-variant": context.variant || variant, "data-size": context.size || size, "data-spacing": context.spacing, className: (0, utils_1.cn)(toggleVariants({
|
|
84
153
|
variant: context.variant || variant,
|
|
85
154
|
size: context.size || size
|
|
86
|
-
}), 'w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10', 'data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l', className), ...props, children: children }));
|
|
155
|
+
}), 'w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10', 'data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l', className), ...props, onFocus: handleFocus, children: children }));
|
|
87
156
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/breadcrumb/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,cAAc,EAAE,CAAA;CACxB,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,WAAW,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/breadcrumb/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,cAAc,EAAE,CAAA;CACxB,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,WAAW,eAAe,sBAmDpD,CAAA"}
|
|
@@ -2,5 +2,29 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { Breadcrumb as BaseBreadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '../../components/ui/breadcrumb/index.js';
|
|
4
4
|
export const Breadcrumb = ({ paths }) => {
|
|
5
|
-
|
|
5
|
+
const last = paths.length - 1;
|
|
6
|
+
return (_jsx(BaseBreadcrumb, { children: _jsx(BreadcrumbList, { children: paths.map((path, index) => {
|
|
7
|
+
/**
|
|
8
|
+
* ⛔ THE LAST CRUMB IS THE PAGE, whatever the caller passed.
|
|
9
|
+
*
|
|
10
|
+
* The page marker used to be a side effect of the caller omitting
|
|
11
|
+
* `href`, and nothing in `getBreadcrumbPaths` makes the last entry
|
|
12
|
+
* omit one. A trail whose final entry carried an href therefore had
|
|
13
|
+
* no `aria-current="page"` anywhere — a screen reader could not tell
|
|
14
|
+
* which of three links was the page being read — and the crumb was a
|
|
15
|
+
* live link back to the page the reader is already on.
|
|
16
|
+
*
|
|
17
|
+
* ⚠️ AND AN HREF-LESS ANCESTOR IS NOT A SWITCHED-OFF LINK. It used
|
|
18
|
+
* to reach `BreadcrumbPage` too, which hard-codes `role="link"
|
|
19
|
+
* aria-disabled="true"` — the right shape for the page you are ON,
|
|
20
|
+
* a destination that exists and simply is not navigable from here.
|
|
21
|
+
* An ancestor with no href is a grouping label: there is no page
|
|
22
|
+
* behind it, so "Settings, link, dimmed" told the reader a
|
|
23
|
+
* destination was unavailable to them rather than that it was never
|
|
24
|
+
* a destination, and inflated the link count of the trail. It is
|
|
25
|
+
* plain text now, and only the last crumb is the page.
|
|
26
|
+
*/
|
|
27
|
+
const isLast = index === last;
|
|
28
|
+
return (_jsxs(React.Fragment, { children: [_jsx(BreadcrumbItem, { children: path.href && !isLast ? (_jsx(BreadcrumbLink, { href: path.href, children: path.name })) : isLast ? (_jsx(BreadcrumbPage, { children: path.name })) : (_jsx("span", { className: "breadcrumb-page", children: path.name })) }), !isLast && _jsx(BreadcrumbSeparator, {})] }, index));
|
|
29
|
+
}) }) }));
|
|
6
30
|
};
|
|
@@ -23,7 +23,7 @@ export function AccountBalanceCardHeader({ className, ...props }) {
|
|
|
23
23
|
return (_jsx("div", { "data-slot": "account-balance-card-header", className: cn('flex flex-col', className), ...props }));
|
|
24
24
|
}
|
|
25
25
|
export function AccountBalanceCardTitle({ className, ...props }) {
|
|
26
|
-
return (_jsx("p", { "data-slot": "account-balance-card-title", className: cn('text-
|
|
26
|
+
return (_jsx("p", { "data-slot": "account-balance-card-title", className: cn('text-foreground text-lg font-bold', className), ...props }));
|
|
27
27
|
}
|
|
28
28
|
export function AccountBalanceCardDeleteButton({ className, ...props }) {
|
|
29
29
|
return (_jsx(IconButton, { variant: "outline", size: "small", rounded: true, "data-slot": "account-balance-card-delete-button", className: cn('absolute top-3 right-3', className), ...props, children: _jsx(Trash, { className: "text-muted-foreground h-4 w-4" }) }));
|
|
@@ -35,19 +35,19 @@ export function AccountBalanceCardLoading({ className, ...props }) {
|
|
|
35
35
|
return (_jsx(Skeleton, { "data-slot": "account-balance-card-loading", className: cn('bg-muted mt-3 h-3 w-full rounded-md', className), ...props }));
|
|
36
36
|
}
|
|
37
37
|
export function AccountBalanceCardEmpty({ className, ...props }) {
|
|
38
|
-
return (_jsx("p", { "data-slot": "account-balance-card-empty", className: cn('text-
|
|
38
|
+
return (_jsx("p", { "data-slot": "account-balance-card-empty", className: cn('text-muted-foreground mt-3 text-center text-sm font-normal', className), ...props }));
|
|
39
39
|
}
|
|
40
40
|
export function AccountBalanceCardInfo({ className, assetCode, value, children: _children, ref, ...props }) {
|
|
41
|
-
return (_jsxs("div", { ref: ref, "data-slot": "account-balance-card-info", className: cn('text-
|
|
41
|
+
return (_jsxs("div", { ref: ref, "data-slot": "account-balance-card-info", className: cn('text-muted-foreground mt-3 flex flex-row items-center justify-between text-sm font-normal', className), ...props, children: [_jsx("p", { children: assetCode }), _jsx("p", { children: value })] }));
|
|
42
42
|
}
|
|
43
43
|
export function AccountBalanceCardUpdateButton({ className: _className, loading, timestamp, loadingLabel = 'Updating...', updatedInLabel = 'Updated in', updatedLabel = 'Updated', onRefresh, children: _children, ref, ...props }) {
|
|
44
44
|
const _time = useTime({ interval: 1000 * 60 });
|
|
45
45
|
const updated = React.useMemo(() => {
|
|
46
46
|
return !dayjs(timestamp).isBefore(dayjs().subtract(1, 'minute'));
|
|
47
47
|
}, [_time, timestamp]);
|
|
48
|
-
return (_jsxs("div", { className: "mb-3 flex flex-row items-center justify-end gap-2", children: [_jsxs("p", { className: "text-
|
|
48
|
+
return (_jsxs("div", { className: "mb-3 flex flex-row items-center justify-end gap-2", children: [_jsxs("p", { className: "text-muted-foreground text-xs font-medium", children: [loading && loadingLabel, !loading && !updated && updatedInLabel, !loading && updated && updatedLabel] }), !loading && updated && (_jsx(CheckCircle2, { className: "text-system-success-h1a h-4 w-4" })), (!updated || loading) && (_jsx(Button, { ref: ref, variant: "link", "data-slot": "account-balance-card-update-button", className: "h-3 p-0", onClick: onRefresh, disabled: loading, ...props, children: _jsx(RefreshCw, { className: cn('size-4', { 'motion-safe:animate-spin': loading }) }) }))] }));
|
|
49
49
|
}
|
|
50
50
|
export function AccountBalanceCardTrigger({ className, openLabel, closeLabel, children: _children, ...props }) {
|
|
51
51
|
const { open } = React.useContext(AccountBalanceCardContext);
|
|
52
|
-
return (_jsx(CollapsibleTrigger, { asChild: true, children: _jsx(Button, { variant: "link", "data-slot": "account-balance-card-trigger", className: cn('text-
|
|
52
|
+
return (_jsx(CollapsibleTrigger, { asChild: true, children: _jsx(Button, { variant: "link", "data-slot": "account-balance-card-trigger", className: cn('text-muted-foreground h-4 p-0 text-xs', className), ...props, children: !open ? openLabel : closeLabel }) }));
|
|
53
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/card/basic-card/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAO7B;AAED,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,qBAO5B;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/card/basic-card/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAO7B;AAED,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,qBAO5B;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAU7B;AAED,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAE7B"}
|
|
@@ -4,10 +4,10 @@ export function BasicCard({ className, ...props }) {
|
|
|
4
4
|
return (_jsx("div", { className: cn('bg-card flex flex-col rounded-lg p-6', className), ...props }));
|
|
5
5
|
}
|
|
6
6
|
export function BasicCardTitle({ className, ...props }) {
|
|
7
|
-
return (_jsx("h2", { className: cn('text-
|
|
7
|
+
return (_jsx("h2", { className: cn('text-foreground mb-4 text-sm font-medium', className), ...props }));
|
|
8
8
|
}
|
|
9
9
|
export function BasicCardContent({ className, ...props }) {
|
|
10
|
-
return (_jsx("div", { className: cn('text-
|
|
10
|
+
return (_jsx("div", { className: cn('text-muted-foreground mb-6 text-sm font-medium', className), ...props }));
|
|
11
11
|
}
|
|
12
12
|
export function BasicCardAction({ className, ...props }) {
|
|
13
13
|
return _jsx("div", { className: cn('flex flex-col', className), ...props });
|
|
@@ -45,7 +45,7 @@ export function EntityCardDescription({ className, ...props }) {
|
|
|
45
45
|
return (_jsx("p", { "data-slot": "entity-card-description", className: cn('text-muted-foreground text-xs font-medium', className), ...props }));
|
|
46
46
|
}
|
|
47
47
|
export function EntityCardList({ className, ...props }) {
|
|
48
|
-
return (_jsx("ul", { "data-slot": "entity-card-list", className: cn('text-
|
|
48
|
+
return (_jsx("ul", { "data-slot": "entity-card-list", className: cn('text-muted-foreground mx-2 list-inside list-disc space-y-1 text-xs font-medium', className), ...props }));
|
|
49
49
|
}
|
|
50
50
|
export function EntityCardFooter({ className, children, ...props }) {
|
|
51
51
|
return (_jsxs("div", { "data-slot": "entity-card-footer", className: cn('text-muted-foreground flex flex-col gap-2 text-xs font-medium', className), ...props, children: [_jsx(Separator, {}), _jsx("div", { className: "[&>svg]:text-muted-foreground flex flex-row items-center gap-2 [&>svg]:size-4 [&>svg]:stroke-[1.5]", children: children })] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/dialog/confirmation-dialog/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAuD9B,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAA;IAC3D;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,KAAK,8BAA8B,GAC/B;IACE,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,CAAA;CACrB,GACD;IACE,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;yEACqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAEL,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,GACjE,8BAA8B,CAAA;AAEhC,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,KAAY,EACZ,WAAkB,EAClB,OAAmB,EACnB,OAAO,EACP,SAAoB,EACpB,QAAmB,EACnB,YAAY,EACZ,WAAW,EACX,YAAY,EACb,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/dialog/confirmation-dialog/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAuD9B,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAA;IAC3D;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,KAAK,8BAA8B,GAC/B;IACE,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,CAAA;CACrB,GACD;IACE,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;yEACqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAEL,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,GACjE,8BAA8B,CAAA;AAEhC,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,YAAY,EACZ,KAAY,EACZ,WAAkB,EAClB,OAAmB,EACnB,OAAO,EACP,SAAoB,EACpB,QAAmB,EACnB,YAAY,EACZ,WAAW,EACX,YAAY,EACb,EAAE,uBAAuB,qBAiGzB"}
|
|
@@ -53,5 +53,8 @@ export function ConfirmationDialog({ open, onOpenChange, title = null, descripti
|
|
|
53
53
|
if (busy) {
|
|
54
54
|
event.preventDefault();
|
|
55
55
|
}
|
|
56
|
-
}, children: [_jsxs(AlertDialogHeader, { className: "flex-row items-center", children: [_jsx(ConfirmationDialogIcon, { variant: variant }), _jsxs("div", { className: "flex flex-col gap-4", children: [title == null ||
|
|
56
|
+
}, children: [_jsxs(AlertDialogHeader, { className: "flex-row items-center", children: [_jsx(ConfirmationDialogIcon, { variant: variant }), _jsxs("div", { className: "flex flex-col gap-4", children: [title == null ||
|
|
57
|
+
title === false ||
|
|
58
|
+
title === true ||
|
|
59
|
+
title === '' ? (_jsx(AlertDialogTitle, { className: "sr-only", children: confirmLabel || 'Confirm' })) : (_jsx(AlertDialogTitle, { children: title })), description == null ? null : (_jsx(AlertDialogDescription, { children: description }))] })] }), pendingLabel ? (_jsx("span", { role: "status", className: "sr-only", children: busy ? pendingLabel : '' })) : null, _jsxs(AlertDialogFooter, { className: "gap-4", children: [_jsx(AlertDialogCancel, { asChild: true, variant: "secondary", children: _jsx(Button, { onClick: onCancel, disabled: busy, variant: "secondary", size: "small", children: cancelLabel ?? 'Cancel' }) }), _jsx(LoadingButton, { loading: busy, onClick: handleConfirm, variant: "primary", size: "small", "data-testid": "confirm", children: confirmLabel ?? 'Confirm' })] })] }) }));
|
|
57
60
|
}
|
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { CollapsibleContentProps, CollapsibleProps, CollapsibleTriggerProps } from '@radix-ui/react-collapsible';
|
|
3
3
|
declare function EntityBox({ className, children, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
4
|
-
declare function EntityBoxCollapsible({ className, ...props }: CollapsibleProps): React.JSX.Element;
|
|
5
|
-
|
|
4
|
+
declare function EntityBoxCollapsible({ className, open, defaultOpen, onOpenChange, ...props }: CollapsibleProps): React.JSX.Element;
|
|
5
|
+
export type EntityBoxCollapsibleTriggerProps = CollapsibleTriggerProps & {
|
|
6
|
+
/** Accessible name while the box is closed. */
|
|
7
|
+
expandLabel?: string;
|
|
8
|
+
/** Accessible name while the box is open. */
|
|
9
|
+
collapseLabel?: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* ⛔ THIS TRIGGER HAS NO TEXT NODE. It is a `Settings2` glyph inside a Button,
|
|
13
|
+
* so without an `aria-label` a screen reader announced "button" and nothing
|
|
14
|
+
* else (SC 4.1.2) — and this is the control that opens the filter panel on
|
|
15
|
+
* every console list page.
|
|
16
|
+
*
|
|
17
|
+
* The name describes the ACTION and Radix's `aria-expanded` carries the state,
|
|
18
|
+
* so the two halves do not repeat each other. English defaults because no
|
|
19
|
+
* consumer passes a label today; a translated console overrides both.
|
|
20
|
+
*/
|
|
21
|
+
declare function EntityBoxCollapsibleTrigger({ expandLabel, collapseLabel, 'aria-label': ariaLabel, ...props }: EntityBoxCollapsibleTriggerProps): React.JSX.Element;
|
|
6
22
|
declare function EntityBoxCollapsibleContent({ children, ...props }: CollapsibleContentProps): React.JSX.Element;
|
|
7
23
|
export interface EntityBoxHeaderProps extends React.ComponentProps<'div'> {
|
|
8
24
|
title: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/entity-box/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAczB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,uBAAuB,EACxB,MAAM,6BAA6B,CAAA;AAIpC,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAa7B;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/entity-box/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAczB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,uBAAuB,EACxB,MAAM,6BAA6B,CAAA;AAIpC,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAa7B;AAYD,iBAAS,oBAAoB,CAAC,EAC5B,SAAS,EACT,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,gBAAgB,qBAoBlB;AAED,MAAM,MAAM,gCAAgC,GAAG,uBAAuB,GAAG;IACvE,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED;;;;;;;;;GASG;AACH,iBAAS,2BAA2B,CAAC,EACnC,WAAsB,EACtB,aAA0B,EAC1B,YAAY,EAAE,SAAS,EACvB,GAAG,KAAK,EACT,EAAE,gCAAgC,qBAclC;AAED,iBAAS,2BAA2B,CAAC,EACnC,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,uBAAuB,qBAOzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACvE,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B;;;;;;;OAOG;IACH,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;CAC/B;AAED,iBAAS,oBAAoB,CAAC,EAC5B,KAAK,EACL,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,SAAS,EACT,EAAE,EAAE,OAAc,EAClB,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAkCtB;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAU7B;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAa7B;AAED,OAAO,EACL,SAAS,EACT,oBAAoB,EACpB,2BAA2B,EAC3B,2BAA2B,EAC3B,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EACjB,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
2
3
|
import { cn } from '../../lib/utils.js';
|
|
3
4
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip/index.js';
|
|
4
5
|
import { CircleHelp, Settings2 } from 'lucide-react';
|
|
@@ -8,11 +9,35 @@ import { Separator } from '../ui/separator/index.js';
|
|
|
8
9
|
function EntityBox({ className, children, ...props }) {
|
|
9
10
|
return (_jsx("div", { "data-slot": "entity-box", className: cn('shadow-entity-box bg-card mb-2 flex items-center justify-between rounded-lg p-6', className), ...props, children: children }));
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* The open state, republished for the trigger.
|
|
14
|
+
*
|
|
15
|
+
* Radix keeps it in a context it does not export, and the trigger one element
|
|
16
|
+
* down needs it to say what activating it will DO. Mirroring it here rather
|
|
17
|
+
* than forcing every consumer to lift the state: all ten console call sites
|
|
18
|
+
* render `<EntityBoxCollapsible>` uncontrolled.
|
|
19
|
+
*/
|
|
20
|
+
const EntityBoxCollapsibleContext = React.createContext(false);
|
|
21
|
+
function EntityBoxCollapsible({ className, open, defaultOpen, onOpenChange, ...props }) {
|
|
22
|
+
const [uncontrolled, setUncontrolled] = React.useState(defaultOpen ?? false);
|
|
23
|
+
return (_jsx(EntityBoxCollapsibleContext.Provider, { value: open ?? uncontrolled, children: _jsx(Collapsible, { className: cn('shadow-entity-box bg-card mb-2 flex flex-col rounded-lg', className), open: open, defaultOpen: defaultOpen, onOpenChange: (next) => {
|
|
24
|
+
setUncontrolled(next);
|
|
25
|
+
onOpenChange?.(next);
|
|
26
|
+
}, ...props }) }));
|
|
13
27
|
}
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
/**
|
|
29
|
+
* ⛔ THIS TRIGGER HAS NO TEXT NODE. It is a `Settings2` glyph inside a Button,
|
|
30
|
+
* so without an `aria-label` a screen reader announced "button" and nothing
|
|
31
|
+
* else (SC 4.1.2) — and this is the control that opens the filter panel on
|
|
32
|
+
* every console list page.
|
|
33
|
+
*
|
|
34
|
+
* The name describes the ACTION and Radix's `aria-expanded` carries the state,
|
|
35
|
+
* so the two halves do not repeat each other. English defaults because no
|
|
36
|
+
* consumer passes a label today; a translated console overrides both.
|
|
37
|
+
*/
|
|
38
|
+
function EntityBoxCollapsibleTrigger({ expandLabel = 'Expand', collapseLabel = 'Collapse', 'aria-label': ariaLabel, ...props }) {
|
|
39
|
+
const open = React.useContext(EntityBoxCollapsibleContext);
|
|
40
|
+
return (_jsx(CollapsibleTrigger, { ...props, asChild: true, children: _jsx(Button, { variant: "secondary", className: "h-[34px] w-[34px] p-2", "aria-label": ariaLabel ?? (open ? collapseLabel : expandLabel), children: _jsx(Settings2, { size: 16, "aria-hidden": true }) }) }));
|
|
16
41
|
}
|
|
17
42
|
function EntityBoxCollapsibleContent({ children, ...props }) {
|
|
18
43
|
return (_jsxs(CollapsibleContent, { ...props, children: [_jsx(Separator, { orientation: "horizontal" }), _jsx("div", { className: "grid w-full grid-cols-3 p-6", children: children })] }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { Control, FieldPathByValue, FieldValues } from 'react-hook-form';
|
|
3
|
-
import { type FileUploadResult } from '../../../components/ui/file-upload/index.js';
|
|
3
|
+
import { type FileUploadError, type FileUploadLabels, type FileUploadResult } from '../../../components/ui/file-upload/index.js';
|
|
4
4
|
import { type RenderableLabel } from '../../../components/form/renderable-label.js';
|
|
5
5
|
type FileUploadFieldOwnProps<T extends FieldValues = FieldValues> = {
|
|
6
6
|
control: Control<T>;
|
|
@@ -17,6 +17,15 @@ type FileUploadFieldOwnProps<T extends FieldValues = FieldValues> = {
|
|
|
17
17
|
maxSizeBytes?: number;
|
|
18
18
|
disabled?: boolean;
|
|
19
19
|
className?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Override the picker's user-visible copy. Threaded straight to FileUpload;
|
|
22
|
+
* omitted fields keep the English defaults. Note `labels.error` governs the
|
|
23
|
+
* PICKER's own size/type/read refusal only — resolver messages still come
|
|
24
|
+
* from the schema through FormMessage.
|
|
25
|
+
*/
|
|
26
|
+
labels?: FileUploadLabels;
|
|
27
|
+
/** Observe size, type, and read failures after the form value is cleared. */
|
|
28
|
+
onError?: (error: FileUploadError) => void;
|
|
20
29
|
/** Optional escape hatch to also observe the picked File/clear alongside the form's text value. */
|
|
21
30
|
onSelect?: (result: FileUploadResult | null) => void;
|
|
22
31
|
};
|
|
@@ -47,6 +56,6 @@ export type FileUploadFieldProps<T extends FieldValues = FieldValues> = FileUplo
|
|
|
47
56
|
* rejection; on resolver failure the FormMessage announces. Both surfaces are
|
|
48
57
|
* wired.
|
|
49
58
|
*/
|
|
50
|
-
export declare const FileUploadField: <T extends FieldValues = FieldValues>({ control, name, label, description, tooltip, required, accept, maxSizeBytes, disabled, className, onSelect, "aria-label": ariaLabelProp }: FileUploadFieldProps<T>) => import("react").JSX.Element;
|
|
59
|
+
export declare const FileUploadField: <T extends FieldValues = FieldValues>({ control, name, label, description, tooltip, required, accept, maxSizeBytes, disabled, className, labels, onError, onSelect, "aria-label": ariaLabelProp }: FileUploadFieldProps<T>) => import("react").JSX.Element;
|
|
51
60
|
export {};
|
|
52
61
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/file-upload-field/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAY,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAWxE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/file-upload-field/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAY,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAWxE,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACtB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,oCAAoC,CAAA;AAE3C,KAAK,uBAAuB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IAClE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB;;;;OAIG;IACH,IAAI,EAAE,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IAC7C,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAC1C,mGAAmG;IACnG,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI,CAAA;CACrD,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAClE,uBAAuB,CAAC,CAAC,CAAC,GACxB,CACI;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAC1C,CAAA;AAEL;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,6JAelE,oBAAoB,CAAC,CAAC,CAAC,gCAoFzB,CAAA"}
|
|
@@ -19,7 +19,7 @@ import { hasRenderableLabel } from '../../../components/form/renderable-label.js
|
|
|
19
19
|
* rejection; on resolver failure the FormMessage announces. Both surfaces are
|
|
20
20
|
* wired.
|
|
21
21
|
*/
|
|
22
|
-
export const FileUploadField = ({ control, name, label, description, tooltip, required, accept, maxSizeBytes, disabled, className, onSelect, 'aria-label': ariaLabelProp }) => {
|
|
22
|
+
export const FileUploadField = ({ control, name, label, description, tooltip, required, accept, maxSizeBytes, disabled, className, labels, onError, onSelect, 'aria-label': ariaLabelProp }) => {
|
|
23
23
|
const [localValue, setLocalValue] = useState(null);
|
|
24
24
|
const showLabel = hasRenderableLabel(label);
|
|
25
25
|
// An empty or whitespace-only aria-label is worse than none: it names the
|
|
@@ -51,10 +51,15 @@ export const FileUploadField = ({ control, name, label, description, tooltip, re
|
|
|
51
51
|
// value carries nothing else to tell them apart. Fix needs a reset epoch
|
|
52
52
|
// from react-hook-form, or a form value richer than the file text.
|
|
53
53
|
const shown = localValue && field.value === localValue.text ? localValue : null;
|
|
54
|
-
return (_jsxs(FormItem, { required: required, children: [showLabel && (_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : undefined, children: label })), _jsx(FormControl, { children: _jsx(FileUpload, { ref: field.ref, name: field.name, onBlur: field.onBlur, "aria-label": ariaLabel, accept: accept, maxSizeBytes: maxSizeBytes, disabled: disabled, className: className, value: shown, onSelect: (result) => {
|
|
54
|
+
return (_jsxs(FormItem, { required: required, children: [showLabel && (_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : undefined, children: label })), _jsx(FormControl, { children: _jsx(FileUpload, { ref: field.ref, name: field.name, onBlur: field.onBlur, "aria-label": ariaLabel, labels: labels, accept: accept, maxSizeBytes: maxSizeBytes, disabled: disabled, className: className, value: shown, onSelect: (result) => {
|
|
55
55
|
setLocalValue(result);
|
|
56
56
|
field.onChange(result?.text ?? '');
|
|
57
57
|
onSelect?.(result);
|
|
58
|
-
}, onError: () =>
|
|
58
|
+
}, onError: (error) => {
|
|
59
|
+
setLocalValue(null);
|
|
60
|
+
field.onChange('');
|
|
61
|
+
onSelect?.(null);
|
|
62
|
+
onError?.(error);
|
|
63
|
+
} }) }), _jsx(FormMessage, {}), description && _jsx(FormDescription, { children: description })] }));
|
|
59
64
|
} }));
|
|
60
65
|
};
|
|
@@ -1,9 +1,48 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type InputRef } from '../../../components/ui/input/index.js';
|
|
2
|
+
import { HTMLInputTypeAttribute, ReactNode, Ref } from 'react';
|
|
2
3
|
import { Control, FieldValues } from 'react-hook-form';
|
|
3
4
|
export type InputFieldProps<T extends FieldValues = FieldValues> = {
|
|
4
5
|
className?: string;
|
|
5
6
|
name: string;
|
|
6
7
|
type?: HTMLInputTypeAttribute;
|
|
8
|
+
/**
|
|
9
|
+
* Announce the field's own invalidity. Reaches the rendered control on BOTH
|
|
10
|
+
* branches, so a field with no `control` — and therefore no react-hook-form
|
|
11
|
+
* error state — can still tell a screen reader it is invalid.
|
|
12
|
+
*
|
|
13
|
+
* ORed with the form's error, never overriding it: `false` here cannot
|
|
14
|
+
* suppress a live resolver error. Nobody asked to mute a real validation
|
|
15
|
+
* failure, and on a financial console a muted one is a wrong number reaching
|
|
16
|
+
* a money path.
|
|
17
|
+
*
|
|
18
|
+
* TypeScript exempts hyphenated JSX attributes from excess-property
|
|
19
|
+
* checking, so passing this used to compile and then vanish.
|
|
20
|
+
*/
|
|
21
|
+
'aria-invalid'?: boolean;
|
|
22
|
+
/** Lower bound, forwarded to the single-line control on both branches. */
|
|
23
|
+
min?: number | string;
|
|
24
|
+
/** Upper bound, forwarded to the single-line control on both branches. */
|
|
25
|
+
max?: number | string;
|
|
26
|
+
/** Increment, forwarded to the single-line control on both branches. */
|
|
27
|
+
step?: number | string;
|
|
28
|
+
/** Character ceiling, forwarded on both branches (single-line and textarea). */
|
|
29
|
+
maxLength?: number;
|
|
30
|
+
/** Browser autofill hint. `"off"` is the one a money field usually wants. */
|
|
31
|
+
autoComplete?: React.HTMLInputAutoCompleteAttribute;
|
|
32
|
+
/** Virtual-keyboard hint, e.g. `"numeric"` or `"decimal"`. Both branches. */
|
|
33
|
+
inputMode?: React.HTMLAttributes<HTMLElement>['inputMode'];
|
|
34
|
+
/** Native validation regex. Single-line only — a textarea has no `pattern`. */
|
|
35
|
+
pattern?: string;
|
|
36
|
+
/** Focus the control on mount. React focuses the node rather than emitting an attribute. */
|
|
37
|
+
autoFocus?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Imperative handle on the rendered control: `focus()`/`blur()` on the
|
|
40
|
+
* single-line branch, the textarea node on the `textArea` branch (which
|
|
41
|
+
* satisfies the same shape). COMPOSED with react-hook-form's own ref when
|
|
42
|
+
* `control` is present, never replacing it — the form keeps the node it
|
|
43
|
+
* needs for `shouldFocusError`.
|
|
44
|
+
*/
|
|
45
|
+
ref?: Ref<InputRef>;
|
|
7
46
|
label?: ReactNode;
|
|
8
47
|
tooltip?: string;
|
|
9
48
|
labelExtra?: ReactNode;
|
|
@@ -32,5 +71,5 @@ export type InputFieldProps<T extends FieldValues = FieldValues> = {
|
|
|
32
71
|
'data-testid'?: string;
|
|
33
72
|
onChange?: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
34
73
|
};
|
|
35
|
-
export declare const InputField: <T extends FieldValues = FieldValues>({ className, type, label, tooltip, labelExtra, placeholder, description, startAdornment, endAdornment, required, readOnly, minHeight, maxHeight, textArea, defaultValue, value, onChange, ...others }: InputFieldProps<T>) => import("react").JSX.Element;
|
|
74
|
+
export declare const InputField: <T extends FieldValues = FieldValues>({ className, type, label, tooltip, labelExtra, placeholder, description, startAdornment, endAdornment, required, readOnly, minHeight, maxHeight, textArea, defaultValue, value, onChange, min, max, step, maxLength, autoComplete, inputMode, pattern, autoFocus, ref, "aria-invalid": ariaInvalid, ...others }: InputFieldProps<T>) => import("react").JSX.Element;
|
|
36
75
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/input-field/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/input-field/index.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,GAAG,EAAmB,MAAM,OAAO,CAAA;AAC/E,OAAO,EAAE,OAAO,EAAkB,WAAW,EAAQ,MAAM,iBAAiB,CAAA;AAE5E,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IACjE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,sBAAsB,CAAA;IAC7B;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,KAAK,CAAC,8BAA8B,CAAA;IACnD,6EAA6E;IAC7E,SAAS,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CAAA;IAC1D,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;IACnB,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,cAAc,CAAC,EAAE,SAAS,CAAA;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAA;IACxB;oDACgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACpB,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,CACT,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,KACzD,IAAI,CAAA;CACV,CAAA;AA4CD,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,iTA6B7D,eAAe,CAAC,CAAC,CAAC,gCAyHpB,CAAA"}
|
|
@@ -2,8 +2,59 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { AutosizeTextarea } from '../../../components/ui/autosize-textarea/index.js';
|
|
3
3
|
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, FormTooltip } from '../../../components/ui/form.js';
|
|
4
4
|
import { Input } from '../../../components/ui/input/index.js';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { useMemo, useRef } from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* Fan one node out to several refs. React hands a node to ONE ref, so a
|
|
8
|
+
* consumer ref and react-hook-form's `field.ref` cannot both be passed
|
|
9
|
+
* directly — one silently wins. Only used when the consumer actually supplied
|
|
10
|
+
* a ref, so a field without one keeps `field.ref`'s own identity and React
|
|
11
|
+
* never re-attaches it.
|
|
12
|
+
*/
|
|
13
|
+
function fanOutRef(...refs) {
|
|
14
|
+
return (node) => {
|
|
15
|
+
const cleanups = [];
|
|
16
|
+
for (const ref of refs) {
|
|
17
|
+
if (typeof ref === 'function') {
|
|
18
|
+
const cleanup = ref(node);
|
|
19
|
+
cleanups.push(typeof cleanup === 'function' ? cleanup : () => ref(null));
|
|
20
|
+
}
|
|
21
|
+
else if (ref) {
|
|
22
|
+
;
|
|
23
|
+
ref.current = node;
|
|
24
|
+
cleanups.push(() => {
|
|
25
|
+
;
|
|
26
|
+
ref.current = null;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return () => cleanups.forEach((cleanup) => cleanup());
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export const InputField = ({ className, type, label, tooltip, labelExtra, placeholder, description, startAdornment, endAdornment, required, readOnly, minHeight, maxHeight, textArea, defaultValue, value, onChange, min, max, step, maxLength, autoComplete, inputMode, pattern, autoFocus, ref, 'aria-invalid': ariaInvalid, ...others }) => {
|
|
34
|
+
// OR with the form's error, expressed through the Slot merge rather than by
|
|
35
|
+
// reading the form: FormControl already injects `aria-invalid={!!error}`, and
|
|
36
|
+
// a child prop only wins that merge when the KEY is present. So emit the key
|
|
37
|
+
// only for an explicit `true`, and let FormControl answer for every other
|
|
38
|
+
// case. `true || error` is true; `false || error` is whatever the form says,
|
|
39
|
+
// which is the whole point — an explicit `false` cannot mute a live error.
|
|
40
|
+
// With no `control` there is no error to OR against, so FormControl injects
|
|
41
|
+
// `false` and today's behaviour is unchanged.
|
|
42
|
+
const ariaInvalidProp = ariaInvalid ? { 'aria-invalid': true } : undefined;
|
|
43
|
+
const formRef = useRef(undefined);
|
|
44
|
+
const composedRef = useMemo(() => ref ? fanOutRef((node) => formRef.current?.(node), ref) : ref,
|
|
45
|
+
// `others.name` belongs here, and leaving it out is not a lint nit.
|
|
46
|
+
// react-hook-form hands a fresh `field.ref` for every name, and that ref
|
|
47
|
+
// only receives the element when React reattaches, which it does only when
|
|
48
|
+
// this callback's identity changes. Memoised on `ref` alone, one identity
|
|
49
|
+
// survived a name change, the new field never got its element, and
|
|
50
|
+
// `form.setFocus(newName)` then found nothing to focus and said nothing.
|
|
51
|
+
[ref, others.name]);
|
|
52
|
+
const renderItem = (binding) => (_jsxs(FormItem, { required: required, children: [label && (_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : labelExtra, children: label })), _jsx(FormControl, { children: textArea ? (_jsx(AutosizeTextarea, { className: className, placeholder: placeholder, readOnly: readOnly, minHeight: minHeight, maxHeight: maxHeight, maxLength: maxLength, autoComplete: autoComplete, inputMode: inputMode, autoFocus: autoFocus, "data-testid": others['data-testid'], ...ariaInvalidProp, ...binding })) : (_jsx(Input, { className: className, type: type, placeholder: placeholder, readOnly: readOnly, startAdornment: startAdornment, endAdornment: endAdornment,
|
|
53
|
+
// Bounds belong to the single-line control only: `min`/`max`/`step`
|
|
54
|
+
// mean nothing on a textarea and would render as invalid markup.
|
|
55
|
+
min: min, max: max, step: step, maxLength: maxLength, autoComplete: autoComplete, inputMode: inputMode,
|
|
56
|
+
// Single-line only: `<textarea pattern>` is not a thing.
|
|
57
|
+
pattern: pattern, autoFocus: autoFocus, "data-testid": others['data-testid'], ...ariaInvalidProp, ...binding })) }), _jsx(FormMessage, {}), description && _jsx(FormDescription, { children: description })] }));
|
|
7
58
|
if (!others.control) {
|
|
8
59
|
return renderItem({
|
|
9
60
|
name: others.name,
|
|
@@ -11,7 +62,10 @@ export const InputField = ({ className, type, label, tooltip, labelExtra, placeh
|
|
|
11
62
|
// Controlled when the caller holds the value, uncontrolled when it only
|
|
12
63
|
// seeds one — supplying both is what React warns about.
|
|
13
64
|
...(value !== undefined ? { value } : { defaultValue }),
|
|
14
|
-
onChange: (e) => onChange?.(e)
|
|
65
|
+
onChange: (e) => onChange?.(e),
|
|
66
|
+
// Nothing else claims the node on this branch, so the consumer ref goes
|
|
67
|
+
// straight through. Without it there was no node to focus at all.
|
|
68
|
+
ref: ref
|
|
15
69
|
});
|
|
16
70
|
}
|
|
17
71
|
return (_jsx(FormField, { ...others, name: others.name,
|
|
@@ -19,16 +73,20 @@ export const InputField = ({ className, type, label, tooltip, labelExtra, placeh
|
|
|
19
73
|
// value painted on the box only makes the field LOOK filled while the
|
|
20
74
|
// form still submits nothing for that name. Controller seeds its own
|
|
21
75
|
// state from this, so `field.value` carries the seed on both branches.
|
|
22
|
-
defaultValue: defaultValue, render: ({ field }) =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
field.
|
|
31
|
-
onChange
|
|
32
|
-
|
|
33
|
-
|
|
76
|
+
defaultValue: defaultValue, render: ({ field }) => {
|
|
77
|
+
formRef.current = field.ref;
|
|
78
|
+
return renderItem({
|
|
79
|
+
...field,
|
|
80
|
+
// Controlled from mount. react-hook-form hands `undefined` for any
|
|
81
|
+
// name the form declares no default for; React then mounts the box
|
|
82
|
+
// uncontrolled and flips it on the first keystroke, losing that
|
|
83
|
+
// character.
|
|
84
|
+
value: field.value ?? '',
|
|
85
|
+
onChange: (e) => {
|
|
86
|
+
field.onChange(e);
|
|
87
|
+
onChange?.(e);
|
|
88
|
+
},
|
|
89
|
+
ref: (ref ? composedRef : field.ref)
|
|
90
|
+
});
|
|
91
|
+
} }));
|
|
34
92
|
};
|
|
@@ -9,6 +9,10 @@ export type PasswordFieldProps<TFieldValues extends FieldValues = FieldValues, T
|
|
|
9
9
|
required?: boolean;
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
'data-testid'?: string;
|
|
12
|
+
/** Accessible name of the eye button while the password is hidden. */
|
|
13
|
+
showPasswordLabel?: string;
|
|
14
|
+
/** Accessible name of the eye button while the password is showing. */
|
|
15
|
+
hidePasswordLabel?: string;
|
|
12
16
|
};
|
|
13
|
-
export declare function PasswordField<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, label, tooltip, placeholder, control, required, disabled, 'data-testid': dataTestId }: PasswordFieldProps<TFieldValues, TName>): React.JSX.Element;
|
|
17
|
+
export declare function PasswordField<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, label, tooltip, placeholder, control, required, disabled, 'data-testid': dataTestId, showPasswordLabel, hidePasswordLabel }: PasswordFieldProps<TFieldValues, TName>): React.JSX.Element;
|
|
14
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/password-field/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAajE,MAAM,MAAM,kBAAkB,CAC5B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,IAC7D;IACF,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/password-field/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAajE,MAAM,MAAM,kBAAkB,CAC5B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,IAC7D;IACF,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,wBAAgB,aAAa,CAC3B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,EAC/D,EACA,IAAI,EACJ,KAAK,EACL,OAAO,EACP,WAAW,EACX,OAAO,EACP,QAAgB,EAChB,QAAgB,EAChB,aAAa,EAAE,UAAU,EACzB,iBAAmC,EACnC,iBAAmC,EACpC,EAAE,kBAAkB,CAAC,YAAY,EAAE,KAAK,CAAC,qBAuDzC"}
|
|
@@ -4,7 +4,7 @@ import { FormControl, FormField, FormItem, FormLabel, FormMessage, FormTooltip }
|
|
|
4
4
|
import { Input, InputAdornment } from '../../../components/ui/input/index.js';
|
|
5
5
|
import { Eye, EyeOff } from 'lucide-react';
|
|
6
6
|
import { IconButton } from '../../../components/ui/icon-button/index.js';
|
|
7
|
-
export function PasswordField({ name, label, tooltip, placeholder, control, required = false, disabled = false, 'data-testid': dataTestId }) {
|
|
7
|
+
export function PasswordField({ name, label, tooltip, placeholder, control, required = false, disabled = false, 'data-testid': dataTestId, showPasswordLabel = 'Show password', hidePasswordLabel = 'Hide password' }) {
|
|
8
8
|
const [show, setShow] = React.useState(false);
|
|
9
|
-
return (_jsx(FormField, { control: control, name: name, render: ({ field }) => (_jsxs(FormItem, { required: required, children: [_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : undefined, children: label }), _jsx(FormControl, { children: _jsx(Input, { ...field, type: show ? 'text' : 'password', placeholder: placeholder, endAdornment: _jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { type: "button", variant: "outline", rounded: true, onClick: () => setShow(!show), children: show ? _jsx(EyeOff, {}) : _jsx(Eye, {}) }) }), disabled: disabled, className: "pr-10", "data-testid": dataTestId }) }), _jsx(FormMessage, {})] })) }));
|
|
9
|
+
return (_jsx(FormField, { control: control, name: name, render: ({ field }) => (_jsxs(FormItem, { required: required, children: [_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : undefined, children: label }), _jsx(FormControl, { children: _jsx(Input, { ...field, type: show ? 'text' : 'password', placeholder: placeholder, endAdornment: _jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { type: "button", variant: "outline", rounded: true, "aria-label": show ? hidePasswordLabel : showPasswordLabel, onClick: () => setShow(!show), children: show ? _jsx(EyeOff, { "aria-hidden": true }) : _jsx(Eye, { "aria-hidden": true }) }) }), disabled: disabled, className: "pr-10", "data-testid": dataTestId }) }), _jsx(FormMessage, {})] })) }));
|
|
10
10
|
}
|