@lerianstudio/sindarian-ui 1.2.0-beta.14 → 1.2.0-beta.15
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/form/radio-group-field/index.d.ts +1 -1
- package/dist/components/form/radio-group-field/index.d.ts.map +1 -1
- package/dist/components/form/radio-group-field/index.js +8 -1
- package/dist/components/ui/alert-dialog/index.d.ts.map +1 -1
- package/dist/components/ui/alert-dialog/index.js +1 -1
- package/dist/components/ui/copy-field/index.d.ts.map +1 -1
- package/dist/components/ui/copy-field/index.js +6 -1
- package/dist/components/ui/file-upload/index.d.ts.map +1 -1
- package/dist/components/ui/file-upload/index.js +8 -1
- package/dist/domain/delinquency-aging/aging-buckets.d.ts +22 -2
- package/dist/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
- package/dist/domain/delinquency-aging/aging-buckets.js +17 -4
- package/dist/domain/delinquency-aging/index.d.ts +17 -2
- package/dist/domain/delinquency-aging/index.d.ts.map +1 -1
- package/dist/domain/delinquency-aging/index.js +4 -2
- package/dist/domain/index.d.ts +2 -1
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/money-diff.d.ts +9 -4
- package/dist/domain/money-diff.d.ts.map +1 -1
- package/dist/domain/section-label/index.d.ts +3 -3
- package/dist/domain/section-label/index.d.ts.map +1 -1
- package/dist/domain/section-label/index.js +6 -2
- package/dist/domain/status-rail/index.d.ts.map +1 -1
- package/dist/domain/status-rail/index.js +9 -1
- package/dist/domain/threshold-gauge/index.d.ts.map +1 -1
- package/dist/domain/threshold-gauge/index.js +1 -1
- package/dist/enterprise/date-range-picker/index.d.ts.map +1 -1
- package/dist/enterprise/date-range-picker/index.js +28 -10
- package/dist/enterprise/search-input/index.d.ts.map +1 -1
- package/dist/enterprise/search-input/index.js +13 -6
- package/dist/enterprise/use-is-mobile.d.ts +13 -4
- package/dist/enterprise/use-is-mobile.d.ts.map +1 -1
- package/dist/enterprise/use-is-mobile.js +15 -6
- package/dist/esm/components/form/radio-group-field/index.d.ts +1 -1
- package/dist/esm/components/form/radio-group-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/radio-group-field/index.js +8 -1
- package/dist/esm/components/ui/alert-dialog/index.d.ts.map +1 -1
- package/dist/esm/components/ui/alert-dialog/index.js +1 -1
- package/dist/esm/components/ui/copy-field/index.d.ts.map +1 -1
- package/dist/esm/components/ui/copy-field/index.js +6 -1
- package/dist/esm/components/ui/file-upload/index.d.ts.map +1 -1
- package/dist/esm/components/ui/file-upload/index.js +8 -1
- package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts +22 -2
- package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
- package/dist/esm/domain/delinquency-aging/aging-buckets.js +17 -4
- package/dist/esm/domain/delinquency-aging/index.d.ts +17 -2
- package/dist/esm/domain/delinquency-aging/index.d.ts.map +1 -1
- package/dist/esm/domain/delinquency-aging/index.js +4 -2
- package/dist/esm/domain/index.d.ts +2 -1
- package/dist/esm/domain/index.d.ts.map +1 -1
- package/dist/esm/domain/money-diff.d.ts +9 -4
- package/dist/esm/domain/money-diff.d.ts.map +1 -1
- package/dist/esm/domain/section-label/index.d.ts +3 -3
- package/dist/esm/domain/section-label/index.d.ts.map +1 -1
- package/dist/esm/domain/section-label/index.js +6 -2
- package/dist/esm/domain/status-rail/index.d.ts.map +1 -1
- package/dist/esm/domain/status-rail/index.js +9 -1
- package/dist/esm/domain/threshold-gauge/index.d.ts.map +1 -1
- package/dist/esm/domain/threshold-gauge/index.js +1 -1
- package/dist/esm/enterprise/date-range-picker/index.d.ts.map +1 -1
- package/dist/esm/enterprise/date-range-picker/index.js +29 -11
- package/dist/esm/enterprise/search-input/index.d.ts.map +1 -1
- package/dist/esm/enterprise/search-input/index.js +13 -6
- package/dist/esm/enterprise/use-is-mobile.d.ts +13 -4
- package/dist/esm/enterprise/use-is-mobile.d.ts.map +1 -1
- package/dist/esm/enterprise/use-is-mobile.js +13 -5
- package/dist/esm/theme/theme-provider.d.ts.map +1 -1
- package/dist/esm/theme/theme-provider.js +15 -1
- package/dist/theme/theme-provider.d.ts.map +1 -1
- package/dist/theme/theme-provider.js +15 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/radio-group-field/index.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/radio-group-field/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAa5D,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,oCAAoC,CAAA;AAE3C,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,KAAK,uBAAuB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IAClE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IACb,OAAO,EAAE,qBAAqB,EAAE,CAAA;IAChC,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,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,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,0GAUlE,oBAAoB,CAAC,CAAC,CAAC,gCA4EzB,CAAA"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.RadioGroupField = void 0;
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_1 = require("react");
|
|
6
7
|
const form_1 = require("../../../components/ui/form");
|
|
7
8
|
const label_1 = require("../../../components/ui/label");
|
|
8
9
|
const radio_group_1 = require("../../../components/ui/radio-group");
|
|
@@ -12,6 +13,12 @@ const RadioGroupField = ({ control, name, options, label, description, tooltip,
|
|
|
12
13
|
// An empty or whitespace-only aria-label is worse than none: it names the
|
|
13
14
|
// control "". Drop it so the attribute never reaches the DOM.
|
|
14
15
|
const ariaLabel = ariaLabelProp?.trim() ? ariaLabelProp : undefined;
|
|
16
|
+
// `FormLabel` names its control through `htmlFor`, which only works on a
|
|
17
|
+
// labelable element — and the Radix radiogroup root is a plain div. So the
|
|
18
|
+
// visible label reached nobody: a screen-reader user landing on the group
|
|
19
|
+
// heard the options and no field name. The group points BACK at the label
|
|
20
|
+
// instead, via aria-labelledby on a stable generated id.
|
|
21
|
+
const labelId = (0, react_1.useId)();
|
|
15
22
|
// The type cannot rule out `label=""`, so this is the only signal a developer
|
|
16
23
|
// gets that the control shipped nameless.
|
|
17
24
|
if (process.env.NODE_ENV !== 'production' && !showLabel && !ariaLabel) {
|
|
@@ -21,7 +28,7 @@ const RadioGroupField = ({ control, name, options, label, description, tooltip,
|
|
|
21
28
|
// RadioGroup root is a plain div, so the ref goes on the first option a user
|
|
22
29
|
// could actually reach — a disabled radio is not focusable.
|
|
23
30
|
const focusTargetIndex = options.findIndex((option) => !option.disabled);
|
|
24
|
-
return ((0, jsx_runtime_1.jsx)(form_1.FormField, { control: control, name: name, render: ({ field }) => ((0, jsx_runtime_1.jsxs)(form_1.FormItem, { required: required, children: [showLabel && ((0, jsx_runtime_1.jsx)(form_1.FormLabel, { extra: tooltip ? (0, jsx_runtime_1.jsx)(form_1.FormTooltip, { children: tooltip }) : undefined, children: label })), (0, jsx_runtime_1.jsx)(form_1.FormControl, { children: (0, jsx_runtime_1.jsx)(radio_group_1.RadioGroup, { name: field.name, value: field.value ?? '', onValueChange: field.onChange, onBlur: field.onBlur, disabled: disabled, "aria-label": ariaLabel, className: "gap-2", children: options.map((option, index) => {
|
|
31
|
+
return ((0, jsx_runtime_1.jsx)(form_1.FormField, { control: control, name: name, render: ({ field }) => ((0, jsx_runtime_1.jsxs)(form_1.FormItem, { required: required, children: [showLabel && ((0, jsx_runtime_1.jsx)(form_1.FormLabel, { id: labelId, extra: tooltip ? (0, jsx_runtime_1.jsx)(form_1.FormTooltip, { children: tooltip }) : undefined, children: label })), (0, jsx_runtime_1.jsx)(form_1.FormControl, { children: (0, jsx_runtime_1.jsx)(radio_group_1.RadioGroup, { name: field.name, value: field.value ?? '', onValueChange: field.onChange, onBlur: field.onBlur, disabled: disabled, "aria-labelledby": showLabel ? labelId : undefined, "aria-label": showLabel ? undefined : ariaLabel, className: "gap-2", children: options.map((option, index) => {
|
|
25
32
|
const id = `${name}-${option.value}`;
|
|
26
33
|
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(radio_group_1.RadioGroupItem, { ref: index === focusTargetIndex ? field.ref : undefined, value: option.value, id: id, disabled: option.disabled }), (0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: id, className: "font-normal", children: option.label })] }, option.value));
|
|
27
34
|
}) }) }), (0, jsx_runtime_1.jsx)(form_1.FormMessage, {}), description && (0, jsx_runtime_1.jsx)(form_1.FormDescription, { children: description })] })) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/alert-dialog/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,oBAAoB,MAAM,8BAA8B,CAAA;AAKpE,iBAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,qBAExD;AAED,iBAAS,kBAAkB,CAAC,EAC1B,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,OAAO,CAAC,qBAI3D;AAED,iBAAS,iBAAiB,CAAC,EACzB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,qBAI1D;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,OAAO,CAAC,qBAQ3D;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,SAAS,EACT,UAAU,EACV,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,OAAO,CAAC,GAI1D,IAAI,CACF,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,EACxD,WAAW,GAAG,YAAY,CAC3B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/alert-dialog/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,oBAAoB,MAAM,8BAA8B,CAAA;AAKpE,iBAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,qBAExD;AAED,iBAAS,kBAAkB,CAAC,EAC1B,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,OAAO,CAAC,qBAI3D;AAED,iBAAS,iBAAiB,CAAC,EACzB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,qBAI1D;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,OAAO,CAAC,qBAQ3D;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,SAAS,EACT,UAAU,EACV,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,OAAO,CAAC,GAI1D,IAAI,CACF,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,EACxD,WAAW,GAAG,YAAY,CAC3B,qBAiBF;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ7B;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ7B;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,KAAK,CAAC,qBAQzD;AAED,iBAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,WAAW,CAAC,qBAQ/D;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,qBAQ1D;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,MAAM,CAAC,qBAQ1D;AAED,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EAClB,CAAA"}
|
|
@@ -62,7 +62,7 @@ function AlertDialogOverlay({ className, ...props }) {
|
|
|
62
62
|
return ((0, jsx_runtime_1.jsx)(AlertDialogPrimitive.Overlay, { "data-slot": "alert-dialog-overlay", className: (0, utils_1.cn)('dialog-overlay', className), ...props }));
|
|
63
63
|
}
|
|
64
64
|
function AlertDialogContent({ className, container, forceMount, ...props }) {
|
|
65
|
-
return ((0, jsx_runtime_1.jsxs)(AlertDialogPortal, { container: container, forceMount: forceMount, children: [(0, jsx_runtime_1.jsx)(AlertDialogOverlay, {}), (0, jsx_runtime_1.jsx)(AlertDialogPrimitive.Content, { "data-slot": "alert-dialog-content", className: (0, utils_1.cn)('dialog-content', className), ...props })] }));
|
|
65
|
+
return ((0, jsx_runtime_1.jsxs)(AlertDialogPortal, { container: container, forceMount: forceMount, children: [(0, jsx_runtime_1.jsx)(AlertDialogOverlay, { forceMount: forceMount }), (0, jsx_runtime_1.jsx)(AlertDialogPrimitive.Content, { "data-slot": "alert-dialog-content", className: (0, utils_1.cn)('dialog-content', className), forceMount: forceMount, ...props })] }));
|
|
66
66
|
}
|
|
67
67
|
function AlertDialogHeader({ className, ...props }) {
|
|
68
68
|
return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "alert-dialog-header", className: (0, utils_1.cn)('dialog-header', className), ...props }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/copy-field/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAmCD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,MAAc,EACd,WAAW,EACX,WAA0B,EAC1B,SAAwB,EACxB,UAA4B,EAC5B,mBAAmB,EACpB,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/copy-field/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAmCD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,MAAc,EACd,WAAW,EACX,WAA0B,EAC1B,SAAwB,EACxB,UAA4B,EAC5B,mBAAmB,EACpB,EAAE,cAAc,qBA6JhB"}
|
|
@@ -141,7 +141,12 @@ function CopyField({ value, label, masked = false, onCopyLabel, revealLabel = 'S
|
|
|
141
141
|
handleFallback();
|
|
142
142
|
}
|
|
143
143
|
};
|
|
144
|
-
return ((0, jsx_runtime_1.jsxs)("div", { "data-slot": "copy-field", className: "flex w-full flex-col gap-2", children: [label ? ((0, jsx_runtime_1.jsx)("label", { htmlFor: inputId, className: "text-muted-foreground text-sm font-semibold", children: label })) : null, (0, jsx_runtime_1.jsxs)("div", { "data-slot": "input-wrapper", className: "border-input-border focus-within:border-ring flex h-10 w-full cursor-text items-center gap-1 rounded-md border pr-1 pl-4 transition-[color,box-shadow]", children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, id: inputId, "data-slot": "input", "data-testid": "copy-field-input", type: showAsText ? 'text' : 'password', value: value, readOnly: true,
|
|
144
|
+
return ((0, jsx_runtime_1.jsxs)("div", { "data-slot": "copy-field", className: "flex w-full flex-col gap-2", children: [label ? ((0, jsx_runtime_1.jsx)("label", { htmlFor: inputId, className: "text-muted-foreground text-sm font-semibold", children: label })) : null, (0, jsx_runtime_1.jsxs)("div", { "data-slot": "input-wrapper", className: "border-input-border focus-within:border-ring flex h-10 w-full cursor-text items-center gap-1 rounded-md border pr-1 pl-4 transition-[color,box-shadow]", children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, id: inputId, "data-slot": "input", "data-testid": "copy-field-input", type: showAsText ? 'text' : 'password', value: value, readOnly: true,
|
|
145
|
+
// This field holds secrets: TOTP manual-entry secrets, recovery
|
|
146
|
+
// codes. While masked it renders as type="password", which invites
|
|
147
|
+
// browsers and password managers to autofill it or offer to SAVE its
|
|
148
|
+
// value, and spellcheck can ship the text to a remote service.
|
|
149
|
+
autoComplete: "off", spellCheck: false, "aria-label": label ? undefined : valueLabel,
|
|
145
150
|
// `min-w-0` lets this flex item shrink below its content width so a
|
|
146
151
|
// long value (e.g. a UUID recovery code) scrolls inside the field
|
|
147
152
|
// instead of overflowing its container. No `font-mono`: the value
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/file-upload/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3D,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAA;AAEvC,MAAM,MAAM,eAAe,GAAG;IAC5B,wGAAwG;IACxG,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0FAA0F;IAC1F,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iEAAiE;IACjE,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC/B,iGAAiG;IACjG,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI,CAAA;IACnD,gHAAgH;IAChH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,IAAI,CACN,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAEzC,MAAM,GACN,QAAQ,GACR,OAAO,GACP,UAAU,GACV,UAAU,GACV,UAAU,GACV,WAAW,GAEX,UAAU,CACb,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,eAAe,GAAG,IAAI,CASxB;AA8CD,eAAO,MAAM,UAAU;IAhGrB,wGAAwG;aAC/F,MAAM;IACf,0FAA0F;mBAC3E,MAAM;IACrB,iEAAiE;YACzD,gBAAgB,GAAG,IAAI;IAC/B,iGAAiG;cACvF,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI;IACnD,gHAAgH;cACtG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI;eAC/B,OAAO;SACb,MAAM;gBACC,MAAM;qBACD,OAAO;sBACN,OAAO;yBACJ,MAAM;mBACZ,MAAM;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/file-upload/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3D,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAA;AAEvC,MAAM,MAAM,eAAe,GAAG;IAC5B,wGAAwG;IACxG,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0FAA0F;IAC1F,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iEAAiE;IACjE,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC/B,iGAAiG;IACjG,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI,CAAA;IACnD,gHAAgH;IAChH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,IAAI,CACN,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAEzC,MAAM,GACN,QAAQ,GACR,OAAO,GACP,UAAU,GACV,UAAU,GACV,UAAU,GACV,WAAW,GAEX,UAAU,CACb,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,eAAe,GAAG,IAAI,CASxB;AA8CD,eAAO,MAAM,UAAU;IAhGrB,wGAAwG;aAC/F,MAAM;IACf,0FAA0F;mBAC3E,MAAM;IACrB,iEAAiE;YACzD,gBAAgB,GAAG,IAAI;IAC/B,iGAAiG;cACvF,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI;IACnD,gHAAgH;cACtG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI;eAC/B,OAAO;SACb,MAAM;gBACC,MAAM;qBACD,OAAO;sBACN,OAAO;yBACJ,MAAM;mBACZ,MAAM;6LA6RtB,CAAA"}
|
|
@@ -182,7 +182,14 @@ exports.FileUpload = React.forwardRef(function FileUpload({ accept, maxSizeBytes
|
|
|
182
182
|
reader.readAsText(file);
|
|
183
183
|
};
|
|
184
184
|
const onInputChange = (event) => {
|
|
185
|
-
|
|
185
|
+
const file = event.target.files?.[0];
|
|
186
|
+
// Release the FileList the moment it has been read. The browser fires
|
|
187
|
+
// `change` only when the selection DIFFERS from what the input already
|
|
188
|
+
// holds, so keeping it meant re-picking the same file after a host reset
|
|
189
|
+
// (or retrying a rejected one) was silently a no-op — the picker opened,
|
|
190
|
+
// the user chose the file, and nothing happened.
|
|
191
|
+
event.target.value = '';
|
|
192
|
+
handleFile(file);
|
|
186
193
|
};
|
|
187
194
|
const onDragOver = (event) => {
|
|
188
195
|
if (disabled)
|
|
@@ -6,6 +6,25 @@ export interface AgingBucket {
|
|
|
6
6
|
/** Money total for the band. Pass a decimal STRING for lossless sums. */
|
|
7
7
|
total: string | number;
|
|
8
8
|
}
|
|
9
|
+
export type AgingBand = 'current' | 'recent' | 'aging' | 'overdue';
|
|
10
|
+
/**
|
|
11
|
+
* Overrides for the fixed pt-BR copy. Every field is optional and defaults to
|
|
12
|
+
* the current value, so a consumer that passes nothing renders exactly as
|
|
13
|
+
* before. The band words in particular are the ACCESSIBLE severity cue (the
|
|
14
|
+
* sr-only text a screen reader announces), so a consumer running in another
|
|
15
|
+
* language needs them translatable, not just the digits `locale` already
|
|
16
|
+
* covers.
|
|
17
|
+
*/
|
|
18
|
+
export interface AgingBucketsLabels {
|
|
19
|
+
/** sr-only severity word per band. Merged shallowly over the pt-BR canon. */
|
|
20
|
+
bands?: Partial<Record<AgingBand, string>>;
|
|
21
|
+
/** Caption under the count column. Defaults to "Itens". */
|
|
22
|
+
count?: string;
|
|
23
|
+
/** Caption under the money column. Defaults to "Total". */
|
|
24
|
+
total?: string;
|
|
25
|
+
/** Label of the grand-total row. Defaults to "Total geral". */
|
|
26
|
+
grandTotal?: string;
|
|
27
|
+
}
|
|
9
28
|
export interface AgingBucketsProps {
|
|
10
29
|
/** Ordered current → oldest. Order carries meaning; not reordered internally. */
|
|
11
30
|
buckets: AgingBucket[];
|
|
@@ -15,9 +34,10 @@ export interface AgingBucketsProps {
|
|
|
15
34
|
locale?: string;
|
|
16
35
|
/** Render a money-math-exact grand total row across all buckets. */
|
|
17
36
|
showTotal?: boolean;
|
|
37
|
+
/** Override the fixed pt-BR copy. Omitted fields keep their defaults. */
|
|
38
|
+
labels?: AgingBucketsLabels;
|
|
18
39
|
className?: string;
|
|
19
40
|
}
|
|
20
|
-
export type AgingBand = 'current' | 'recent' | 'aging' | 'overdue';
|
|
21
41
|
/**
|
|
22
42
|
* Resolve a bucket's severity band from its ORDINAL POSITION, not its amount —
|
|
23
43
|
* the order is the information (older = worse). The first bucket is `current`;
|
|
@@ -33,5 +53,5 @@ export declare function bucketBand(index: number, count: number): AgingBand;
|
|
|
33
53
|
* grand total. Pure: the money-math third rail, unit-tested.
|
|
34
54
|
*/
|
|
35
55
|
export declare function sumBucketTotals(buckets: AgingBucket[], scale: number): string | null;
|
|
36
|
-
export declare function AgingBuckets({ buckets, currency, locale, showTotal, className }: AgingBucketsProps): import("react").JSX.Element;
|
|
56
|
+
export declare function AgingBuckets({ buckets, currency, locale, showTotal, labels, className }: AgingBucketsProps): import("react").JSX.Element;
|
|
37
57
|
//# sourceMappingURL=aging-buckets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aging-buckets.d.ts","sourceRoot":"","sources":["../../../src/domain/delinquency-aging/aging-buckets.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"aging-buckets.d.ts","sourceRoot":"","sources":["../../../src/domain/delinquency-aging/aging-buckets.tsx"],"names":[],"mappings":"AAyCA,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;AAElE;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAC1C,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,yEAAyE;IACzE,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA2BD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,WAAW,EAAE,EACtB,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAMf;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAiB,EACjB,MAAM,EACN,SAAS,EACV,EAAE,iBAAiB,+BAyGnB"}
|
|
@@ -27,7 +27,10 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
27
27
|
* grand total is shown it is summed through `money-math` integer minor units
|
|
28
28
|
* (BigInt, at the currency's CLDR scale) — never IEEE-754 — and rendered via
|
|
29
29
|
* `MoneyText`. A single unparseable bucket total poisons the sum to NO_VALUE
|
|
30
|
-
* rather than silently displaying a wrong number.
|
|
30
|
+
* rather than silently displaying a wrong number. The SAME currency scale that
|
|
31
|
+
* drives the sum is also the print scale handed to `MoneyText`, so the digits on
|
|
32
|
+
* screen are the digits that were summed — the printed total can never be a
|
|
33
|
+
* re-rounding of the computed one.
|
|
31
34
|
*
|
|
32
35
|
* Pure display: no directive, no interactivity, server-safe for RSC.
|
|
33
36
|
*/
|
|
@@ -86,12 +89,22 @@ function sumBucketTotals(buckets, scale) {
|
|
|
86
89
|
const total = (0, money_math_1.sumMinor)(buckets.map((b) => b.total), scale);
|
|
87
90
|
return total === null ? null : (0, money_math_1.minorToDecimal)(total, scale);
|
|
88
91
|
}
|
|
89
|
-
function AgingBuckets({ buckets, currency, locale, showTotal = false, className }) {
|
|
92
|
+
function AgingBuckets({ buckets, currency, locale, showTotal = false, labels, className }) {
|
|
93
|
+
const countLabel = labels?.count ?? 'Itens';
|
|
94
|
+
const totalLabel = labels?.total ?? 'Total';
|
|
95
|
+
const grandTotalLabel = labels?.grandTotal ?? 'Total geral';
|
|
96
|
+
// THIRD RAIL: one scale for BOTH the arithmetic and the print. `MoneyText`
|
|
97
|
+
// defaults to 2 fraction digits, so leaving it unset printed JPY (scale 0)
|
|
98
|
+
// with two decimals the currency does not have, and re-rounded the exact BHD
|
|
99
|
+
// (scale 3) grand total `1.005` to `1.01` — a printed total that disagreed
|
|
100
|
+
// with the total that was actually summed.
|
|
90
101
|
const scale = currency ? (0, money_math_1.minorDigitsOf)(currency) : 2;
|
|
91
102
|
const grandTotal = showTotal ? sumBucketTotals(buckets, scale) : null;
|
|
92
103
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex flex-col', className), children: [(0, jsx_runtime_1.jsx)("ul", { className: "flex flex-col", children: buckets.map((bucket, i) => {
|
|
93
104
|
const band = bucketBand(i, buckets.length);
|
|
94
105
|
const { Icon, tint, word } = BAND[band];
|
|
95
|
-
|
|
96
|
-
|
|
106
|
+
// Shallow merge: an unlisted band keeps its pt-BR default.
|
|
107
|
+
const bandWord = labels?.bands?.[band] ?? word;
|
|
108
|
+
return ((0, jsx_runtime_1.jsxs)("li", { className: "border-border flex items-center gap-3 border-b py-2.5 last:border-b-0", children: [(0, jsx_runtime_1.jsx)(Icon, { "aria-hidden": true, className: (0, utils_1.cn)('size-4 shrink-0', tint) }), (0, jsx_runtime_1.jsxs)("span", { className: "sr-only", children: [bandWord, ": "] }), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)(typography_1.LABEL_VOICE_CLASS, 'text-foreground min-w-0 flex-1 tracking-normal normal-case'), children: bucket.label }), (0, jsx_runtime_1.jsxs)("span", { className: "flex shrink-0 flex-col items-end leading-none", children: [(0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: "text-foreground", children: (0, format_1.formatCount)(bucket.count, locale) }), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)(typography_1.LABEL_VOICE_CLASS, 'mt-1'), children: countLabel })] }), (0, jsx_runtime_1.jsxs)("span", { className: "flex w-32 shrink-0 flex-col items-end leading-none sm:w-40", children: [(0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: (0, utils_1.cn)(band === 'overdue' && 'text-credit'), children: (0, jsx_runtime_1.jsx)(money_text_1.MoneyText, { amount: bucket.total, currency: currency, fractionDigits: scale, locale: locale, signColor: false }) }), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)(typography_1.LABEL_VOICE_CLASS, 'mt-1'), children: totalLabel })] })] }, `${bucket.label}-${i}`));
|
|
109
|
+
}) }), showTotal ? ((0, jsx_runtime_1.jsxs)("div", { className: "border-border flex items-center gap-3 border-t-2 pt-2.5", children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "size-4 shrink-0" }), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)(typography_1.LABEL_VOICE_CLASS, 'text-foreground min-w-0 flex-1'), children: grandTotalLabel }), (0, jsx_runtime_1.jsx)("span", { className: "w-32 shrink-0 text-right sm:w-40", children: grandTotal === null ? ((0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: "text-muted-foreground", children: format_1.NO_VALUE })) : ((0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: "text-foreground font-semibold", children: (0, jsx_runtime_1.jsx)(money_text_1.MoneyText, { amount: grandTotal, currency: currency, fractionDigits: scale, locale: locale, signColor: false }) })) })] })) : null] }));
|
|
97
110
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { GaugeBand } from '../threshold-gauge';
|
|
2
|
+
import type { AgingBucket, AgingBucketsLabels } from './aging-buckets';
|
|
3
|
+
export type { AgingBand, AgingBucketsLabels } from './aging-buckets';
|
|
2
4
|
/** A bucket in the aging schedule, plus the flag that marks it past due. The
|
|
3
5
|
* `overdue` flag is what the rate's NUMERATOR sums — the caller declares which
|
|
4
6
|
* bands count as delinquent (typically every band after "current"). */
|
|
@@ -40,6 +42,19 @@ export interface DelinquencyAgingProps {
|
|
|
40
42
|
locale?: string;
|
|
41
43
|
/** Quiet caption above the rate readout. Defaults to "Inadimplência". */
|
|
42
44
|
rateLabel?: string;
|
|
45
|
+
/** sr-only rate band word per band ("Saudável" / "Elevada" / "Em estresse").
|
|
46
|
+
* Merged shallowly; an unlisted band keeps its pt-BR default. This is the
|
|
47
|
+
* ACCESSIBLE band cue, so it has to be translatable — `locale` only reaches
|
|
48
|
+
* the digits. */
|
|
49
|
+
rateBandLabels?: Partial<Record<GaugeBand, string>>;
|
|
50
|
+
/** Readout when the portfolio is empty. Defaults to "sem carteira". */
|
|
51
|
+
emptyLabel?: string;
|
|
52
|
+
/** Readout when the rate cannot be determined. Defaults to "indeterminada". */
|
|
53
|
+
indeterminateLabel?: string;
|
|
54
|
+
/** Override the fixed pt-BR copy of the distribution below (band words, the
|
|
55
|
+
* count/money captions, the grand-total row). Omitted fields keep their
|
|
56
|
+
* defaults. */
|
|
57
|
+
bucketLabels?: AgingBucketsLabels;
|
|
43
58
|
/** Warn edge for the rate band (0..1 ratio). Crossing it strictly → elevated. */
|
|
44
59
|
warn?: number;
|
|
45
60
|
/** Breach edge for the rate band (0..1 ratio). Crossing it strictly → distressed. */
|
|
@@ -48,5 +63,5 @@ export interface DelinquencyAgingProps {
|
|
|
48
63
|
showTotal?: boolean;
|
|
49
64
|
className?: string;
|
|
50
65
|
}
|
|
51
|
-
export declare function DelinquencyAging({ buckets, currency, locale, rateLabel, warn, breach, showTotal, className }: DelinquencyAgingProps): import("react").JSX.Element;
|
|
66
|
+
export declare function DelinquencyAging({ buckets, currency, locale, rateLabel, rateBandLabels, emptyLabel, indeterminateLabel, bucketLabels, warn, breach, showTotal, className }: DelinquencyAgingProps): import("react").JSX.Element;
|
|
52
67
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/delinquency-aging/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/delinquency-aging/index.tsx"],"names":[],"mappings":"AAqDA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAKtE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAOpE;;wEAEwE;AACxE,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;oEACoE;AACpE,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iFAAiF;IACjF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,6EAA6E;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;0EAEsE;IACtE,aAAa,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,iBAAiB,EAAE,EAC5B,KAAK,EAAE,MAAM,GACZ,eAAe,CAuDjB;AAeD,MAAM,WAAW,qBAAqB;IACpC;yEACqE;IACrE,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;sBAGkB;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IACnD,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;oBAEgB;IAChB,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAA2B,EAC3B,cAAc,EACd,UAA2B,EAC3B,kBAAoC,EACpC,YAAY,EACZ,IAAW,EACX,MAAY,EACZ,SAAiB,EACjB,SAAS,EACV,EAAE,qBAAqB,+BAoEvB"}
|
|
@@ -129,7 +129,7 @@ const RATE_BAND = {
|
|
|
129
129
|
warn: { Icon: lucide_react_1.TriangleAlert, tint: 'text-system-alert', word: 'Elevada' },
|
|
130
130
|
breach: { Icon: lucide_react_1.AlertOctagon, tint: 'text-credit', word: 'Em estresse' }
|
|
131
131
|
};
|
|
132
|
-
function DelinquencyAging({ buckets, currency, locale, rateLabel = 'Inadimplência', warn = 0.05, breach = 0.1, showTotal = false, className }) {
|
|
132
|
+
function DelinquencyAging({ buckets, currency, locale, rateLabel = 'Inadimplência', rateBandLabels, emptyLabel = 'sem carteira', indeterminateLabel = 'indeterminada', bucketLabels, warn = 0.05, breach = 0.1, showTotal = false, className }) {
|
|
133
133
|
// THIRD RAIL: the rate scale and the two totals come from money-math, never
|
|
134
134
|
// float. The division below is of two exact BigInt-derived integers.
|
|
135
135
|
const scale = currency ? (0, money_math_1.minorDigitsOf)(currency) : 2;
|
|
@@ -143,9 +143,11 @@ function DelinquencyAging({ buckets, currency, locale, rateLabel = 'Inadimplênc
|
|
|
143
143
|
? (0, threshold_gauge_1.gaugeBand)(rate, { warn, breach }, 'higher-is-worse')
|
|
144
144
|
: 'low';
|
|
145
145
|
const { Icon, tint, word } = RATE_BAND[band];
|
|
146
|
+
// Shallow merge: an unlisted band keeps its pt-BR default.
|
|
147
|
+
const bandWord = rateBandLabels?.[band] ?? word;
|
|
146
148
|
const distressed = band === 'breach';
|
|
147
149
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex flex-col gap-4', className), children: [(0, jsx_runtime_1.jsxs)("header", { className: "flex items-baseline justify-between gap-3", children: [(0, jsx_runtime_1.jsx)(section_label_1.SectionLabel, { as: "span", children: rateLabel }), hasRate ? ((0, jsx_runtime_1.jsxs)("span", {
|
|
148
150
|
// A distressed rate is a credit alarm: announced the moment it
|
|
149
151
|
// crosses the band, so assistive tech does not lean on the tint.
|
|
150
|
-
role: distressed ? 'alert' : undefined, className: (0, utils_1.cn)('inline-flex items-center gap-1.5', tint), children: [(0, jsx_runtime_1.jsx)(Icon, { "aria-hidden": true, className: "size-4 shrink-0" }), (0, jsx_runtime_1.jsxs)("span", { className: "sr-only", children: [
|
|
152
|
+
role: distressed ? 'alert' : undefined, className: (0, utils_1.cn)('inline-flex items-center gap-1.5', tint), children: [(0, jsx_runtime_1.jsx)(Icon, { "aria-hidden": true, className: "size-4 shrink-0" }), (0, jsx_runtime_1.jsxs)("span", { className: "sr-only", children: [bandWord, ": "] }), (0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: tint, children: (0, format_1.formatPercent)(rate, { unit: 'ratio', locale }) })] })) : ((0, jsx_runtime_1.jsxs)("span", { className: "text-muted-foreground inline-flex items-center gap-1.5", children: [(0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)(typography_1.LABEL_VOICE_CLASS, 'tracking-normal normal-case'), children: indeterminate ? indeterminateLabel : emptyLabel }), (0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: "text-muted-foreground", children: format_1.NO_VALUE })] }))] }), (0, jsx_runtime_1.jsx)(aging_buckets_1.AgingBuckets, { buckets: buckets, currency: currency, locale: locale, showTotal: showTotal, labels: bucketLabels })] }));
|
|
151
153
|
}
|
package/dist/domain/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { NO_VALUE, formatCount, formatPercent, humanizeDurationMs, toPercentValue } from './format';
|
|
2
2
|
export type { FormatPercentOptions, PercentUnit } from './format';
|
|
3
3
|
export { moneyDiff } from './money-diff';
|
|
4
|
+
export type { MoneyDiffInput } from './money-diff';
|
|
4
5
|
export { MoneyText } from './money-text';
|
|
5
6
|
export type { MoneyTextProps } from './money-text';
|
|
6
7
|
export { FIGURE_CLASS, Figure } from './figure';
|
|
@@ -18,5 +19,5 @@ export type { StatusRailChip, StatusRailItem, StatusRailProps } from './status-r
|
|
|
18
19
|
export { ThresholdGauge, gaugeBand } from './threshold-gauge';
|
|
19
20
|
export type { GaugeBand, GaugeDirection, GaugeEdges, GaugeFormat, GaugeThresholds, ThresholdGaugeProps } from './threshold-gauge';
|
|
20
21
|
export { DelinquencyAging } from './delinquency-aging';
|
|
21
|
-
export type { DelinquencyAgingProps, DelinquencyBucket } from './delinquency-aging';
|
|
22
|
+
export type { AgingBand, AgingBucketsLabels, DelinquencyAgingProps, DelinquencyBucket } from './delinquency-aging';
|
|
22
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,cAAc,EACf,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEjE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,cAAc,EACf,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEjE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAC/C,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC/C,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE9D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACzD,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAExE,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAChC,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAErD,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1D,YAAY,EACV,cAAc,EACd,cAAc,EACd,eAAe,EAChB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7D,YAAY,EACV,SAAS,EACT,cAAc,EACd,UAAU,EACV,WAAW,EACX,eAAe,EACf,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,qBAAqB,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Amount } from './money-math';
|
|
2
|
-
/** The money-comparison contract: two sides, a currency, an optional tolerance.
|
|
3
|
-
type
|
|
2
|
+
/** The money-comparison contract: two sides, a currency, an optional tolerance.
|
|
3
|
+
* Exported so a consumer can name the argument type it is already passing. */
|
|
4
|
+
export type MoneyDiffInput = {
|
|
4
5
|
/** Left amount (canonical decimal string preferred for lossless math). */
|
|
5
6
|
left: Amount;
|
|
6
7
|
/** Right amount. The difference is left − right. */
|
|
@@ -12,12 +13,16 @@ type MoneyDiffInput = {
|
|
|
12
13
|
minorDigits?: number;
|
|
13
14
|
/** Absolute tolerance in MAJOR units. `|left − right| > tolerance` is a breach. */
|
|
14
15
|
tolerance?: Amount;
|
|
15
|
-
/** BCP 47 locale
|
|
16
|
+
/** BCP 47 locale. CURRENTLY UNUSED: `moneyDiff` returns `{ decimal, breach }`
|
|
17
|
+
* and formats nothing, so this value has no effect on the result. It stays in
|
|
18
|
+
* the contract because removing it would break every consumer that passes it
|
|
19
|
+
* (an object literal with an unknown member is an excess-property error), and
|
|
20
|
+
* because the formatting side of the pair — `MoneyText` — takes a locale of
|
|
21
|
+
* its own. Pass the locale THERE, at the point the figure is rendered. */
|
|
16
22
|
locale?: string;
|
|
17
23
|
};
|
|
18
24
|
export declare function moneyDiff(money: MoneyDiffInput): {
|
|
19
25
|
decimal: string | null;
|
|
20
26
|
breach: boolean;
|
|
21
27
|
};
|
|
22
|
-
export {};
|
|
23
28
|
//# sourceMappingURL=money-diff.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money-diff.d.ts","sourceRoot":"","sources":["../../src/domain/money-diff.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C
|
|
1
|
+
{"version":3,"file":"money-diff.d.ts","sourceRoot":"","sources":["../../src/domain/money-diff.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C;+EAC+E;AAC/E,MAAM,MAAM,cAAc,GAAG;IAC3B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAA;IACZ,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAA;IAChB;iFAC6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;+EAK2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG;IAChD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,MAAM,EAAE,OAAO,CAAA;CAChB,CA6BA"}
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
* Renders an `<h2>` by default (the ledger-sheet cell heading), but `as` lets
|
|
11
11
|
* it become a `<p>`/`<span>`/`<dt>` for captions and inline labels.
|
|
12
12
|
*/
|
|
13
|
-
import type { ElementType, ReactNode } from 'react';
|
|
13
|
+
import type { ElementType, HTMLAttributes, ReactNode } from 'react';
|
|
14
14
|
export type SectionLabelProps = {
|
|
15
15
|
children: ReactNode;
|
|
16
16
|
className?: string;
|
|
17
17
|
/** Render element. Defaults to `h2` (the ledger-sheet cell heading). */
|
|
18
18
|
as?: ElementType;
|
|
19
|
-
}
|
|
20
|
-
export declare function SectionLabel({ children, className, as: Tag }: SectionLabelProps): import("react").JSX.Element;
|
|
19
|
+
} & Omit<HTMLAttributes<HTMLElement>, 'children' | 'className'>;
|
|
20
|
+
export declare function SectionLabel({ children, className, as: Tag, ...rest }: SectionLabelProps): import("react").JSX.Element;
|
|
21
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/section-label/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/section-label/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKnE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wEAAwE;IACxE,EAAE,CAAC,EAAE,WAAW,CAAA;CACjB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC,CAAA;AAE/D,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,GAAU,EACd,GAAG,IAAI,EACR,EAAE,iBAAiB,+BAUnB"}
|
|
@@ -4,6 +4,10 @@ exports.SectionLabel = SectionLabel;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const typography_1 = require("../../lib/typography");
|
|
6
6
|
const utils_1 = require("../../lib/utils");
|
|
7
|
-
function SectionLabel({ children, className, as: Tag = 'h2' }) {
|
|
8
|
-
|
|
7
|
+
function SectionLabel({ children, className, as: Tag = 'h2', ...rest }) {
|
|
8
|
+
// The remaining element props reach the rendered tag, so a panel can point
|
|
9
|
+
// `aria-labelledby` at this heading via `id`, and tests can hang a `data-*`
|
|
10
|
+
// hook off it. Without the spread there was no way to reference the heading
|
|
11
|
+
// from its own container.
|
|
12
|
+
return ((0, jsx_runtime_1.jsx)(Tag, { className: (0, utils_1.cn)(typography_1.SECTION_LABEL_CLASS, className), ...rest, children: children }));
|
|
9
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/status-rail/index.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,MAAM,MAAM,cAAc,GAAG;IAC3B,uFAAuF;IACvF,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,uFAAuF;IACvF,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,KAAK,EAAE,SAAS,CAAA;IAChB,yEAAyE;IACzE,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,qEAAqE;IACrE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,qCAAqC;IACrC,KAAK,CAAC,EAAE,cAAc,EAAE,CAAA;IACxB,gCAAgC;IAChC,KAAK,CAAC,EAAE,cAAc,EAAE,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,KAAU,EACV,KAAU,EACV,SAAS,EACV,EAAE,eAAe,+
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/status-rail/index.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,MAAM,MAAM,cAAc,GAAG;IAC3B,uFAAuF;IACvF,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,uFAAuF;IACvF,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,KAAK,EAAE,SAAS,CAAA;IAChB,yEAAyE;IACzE,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,qEAAqE;IACrE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,qCAAqC;IACrC,KAAK,CAAC,EAAE,cAAc,EAAE,CAAA;IACxB,gCAAgC;IAChC,KAAK,CAAC,EAAE,cAAc,EAAE,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,KAAU,EACV,KAAU,EACV,SAAS,EACV,EAAE,eAAe,+BAwEjB;AAkBD,qFAAqF;AACrF,wBAAgB,GAAG,gCAMlB;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,gCAOxB"}
|
|
@@ -30,11 +30,19 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
30
30
|
const lucide_react_1 = require("lucide-react");
|
|
31
31
|
const utils_1 = require("../../lib/utils");
|
|
32
32
|
function StatusRail({ lead, items = [], chips = [], className }) {
|
|
33
|
+
// ONE test, used by both the lead span and the first item's separator. Two
|
|
34
|
+
// separate tests (`lead !== undefined && lead !== null` vs `lead != null`)
|
|
35
|
+
// agreed on null/undefined and diverged on a ReactNode that RENDERS NOTHING,
|
|
36
|
+
// which produced an empty lead span while the first item still got its
|
|
37
|
+
// leading dot — the rail opened with a stray `·`. React renders BOTH booleans
|
|
38
|
+
// as nothing, so `true` is as empty as `false`; the typeof check covers the
|
|
39
|
+
// pair rather than naming one of them.
|
|
40
|
+
const hasLead = lead != null && lead !== '' && typeof lead !== 'boolean';
|
|
33
41
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)(
|
|
34
42
|
// Recessed instrument strip: the page surface inside a hairline border
|
|
35
43
|
// whose top edge runs one step darker — light-from-above recession
|
|
36
44
|
// without any inner shadow.
|
|
37
|
-
'border-border border-t-foreground/10 bg-body-surface text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1.5 rounded-lg border px-4 py-2 font-mono text-xs tabular-nums', className), children: [
|
|
45
|
+
'border-border border-t-foreground/10 bg-body-surface text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1.5 rounded-lg border px-4 py-2 font-mono text-xs tabular-nums', className), children: [hasLead ? ((0, jsx_runtime_1.jsx)("span", { className: "text-foreground font-medium", children: lead })) : null, items.map((item, i) => ((0, jsx_runtime_1.jsx)(RailFragment, { hasLead: hasLead || i > 0, children: item.label != null ? ((0, jsx_runtime_1.jsxs)("span", { className: "flex items-center gap-1.5", children: [(0, jsx_runtime_1.jsx)("span", { className: "tracking-[0.08em] uppercase", children: item.label }), item.value] })) : ((0, jsx_runtime_1.jsx)("span", { className: "flex items-center gap-1.5", children: item.value })) }, item.id ?? i))), chips.length ? ((0, jsx_runtime_1.jsx)("span", { className: "ml-auto flex flex-wrap items-center gap-x-3 gap-y-1.5", children: chips.map((chip, i) => ((0, jsx_runtime_1.jsxs)("span", { className: "inline-flex items-center gap-1.5", children: [(0, jsx_runtime_1.jsx)("span", { className: "tracking-[0.08em] uppercase", children: chip.label }), (0, jsx_runtime_1.jsxs)("span", { className: (0, utils_1.cn)(
|
|
38
46
|
// Tiny mono token: raised a hair off the sunken tape by the
|
|
39
47
|
// card surface + whisper shadow.
|
|
40
48
|
'inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 shadow-sm', chip.alarm
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/threshold-gauge/index.tsx"],"names":[],"mappings":"AAiDA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEjD;gFACgF;AAChF,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAA;AAEjE;;gDAEgD;AAChD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;AAEjE;;;;wEAIwE;AACxE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAA;AAE/C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC;oEACgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb;;;;iDAI6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,qEAAqE;IACrE,SAAS,EAAE,cAAc,CAAA;IACzB,qDAAqD;IACrD,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;uCAImC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;0EAIsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAmCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,cAAc,GACxB,SAAS,CAUX;AA+CD,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,YAAY,EACZ,GAAO,EACP,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,MAAkB,EAClB,QAAQ,EACR,MAAM,EACN,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACV,EAAE,mBAAmB,+
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/threshold-gauge/index.tsx"],"names":[],"mappings":"AAiDA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEjD;gFACgF;AAChF,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAA;AAEjE;;gDAEgD;AAChD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;AAEjE;;;;wEAIwE;AACxE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAA;AAE/C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC;oEACgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb;;;;iDAI6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,qEAAqE;IACrE,SAAS,EAAE,cAAc,CAAA;IACzB,qDAAqD;IACrD,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;uCAImC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;0EAIsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAmCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,cAAc,GACxB,SAAS,CAUX;AA+CD,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,YAAY,EACZ,GAAO,EACP,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,SAAS,EACT,MAAkB,EAClB,QAAQ,EACR,MAAM,EACN,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACV,EAAE,mBAAmB,+BA8ErB"}
|
|
@@ -153,5 +153,5 @@ function ThresholdGauge({ value, displayValue, min = 0, max, warn, breach, edges
|
|
|
153
153
|
const valuePct = trackFraction(value, min, max) * 100;
|
|
154
154
|
const warnPct = trackFraction(warn, min, max) * 100;
|
|
155
155
|
const breachPct = trackFraction(breach, min, max) * 100;
|
|
156
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex flex-col gap-2', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline justify-between gap-3", children: [caption != null ? ((0, jsx_runtime_1.jsx)("span", { className: typography_1.LABEL_VOICE_CLASS, children: caption })) : ((0, jsx_runtime_1.jsx)("span", {})), (0, jsx_runtime_1.jsxs)("span", { className: (0, utils_1.cn)('inline-flex items-center gap-1.5', tint), children: [(0, jsx_runtime_1.jsx)(Icon, { "aria-hidden": true, className: "size-4 shrink-0" }), (0, jsx_runtime_1.jsxs)("span", { className: "sr-only", children: [word, ": "] }), (0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: tint, children: readout(displayValue ?? value, format, currency, locale) })] })] }), (0, jsx_runtime_1.jsxs)("div", { role: "meter", "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-label": meterName, className: "border-border bg-muted relative h-2 w-full overflow-hidden rounded-full border", children: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": true, className: (0, utils_1.cn)('absolute inset-y-0 left-0 rounded-full', BAND_FILL[band]), style: { width: `${valuePct}%` } }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "bg-system-alert absolute inset-y-0 w-px", style: { left: `${warnPct}%` } }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "bg-destructive absolute inset-y-0 w-px", style: { left: `${breachPct}%` } })] })] }));
|
|
156
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex flex-col gap-2', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline justify-between gap-3", children: [caption != null ? ((0, jsx_runtime_1.jsx)("span", { className: typography_1.LABEL_VOICE_CLASS, children: caption })) : ((0, jsx_runtime_1.jsx)("span", {})), (0, jsx_runtime_1.jsxs)("span", { className: (0, utils_1.cn)('inline-flex items-center gap-1.5', tint), children: [(0, jsx_runtime_1.jsx)(Icon, { "aria-hidden": true, className: "size-4 shrink-0" }), (0, jsx_runtime_1.jsxs)("span", { className: "sr-only", children: [word, ": "] }), (0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: tint, children: readout(displayValue ?? value, format, currency, locale) })] })] }), (0, jsx_runtime_1.jsxs)("div", { role: "meter", "aria-valuenow": Number.isFinite(value) ? value : undefined, "aria-valuemin": min, "aria-valuemax": max, "aria-label": meterName, className: "border-border bg-muted relative h-2 w-full overflow-hidden rounded-full border", children: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": true, className: (0, utils_1.cn)('absolute inset-y-0 left-0 rounded-full', BAND_FILL[band]), style: { width: `${valuePct}%` } }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "bg-system-alert absolute inset-y-0 w-px", style: { left: `${warnPct}%` } }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "bg-destructive absolute inset-y-0 w-px", style: { left: `${breachPct}%` } })] })] }));
|
|
157
157
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enterprise/date-range-picker/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enterprise/date-range-picker/index.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAUnD;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,cAAc,GAAG;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,cAAc,CAAA;IACrB,aAAa,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB,CAAA;AAkCD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,aAAa,EACb,MAAM,EACN,IAAI,EACJ,SAAS,EACT,OAAO,EACP,OAAe,EACf,OAAO,EACP,WAAwB,EACxB,SAA+B,EAC/B,UAAoB,EACpB,MAAa,EACd,EAAE,oBAAoB,+BAiHtB"}
|
|
@@ -4,14 +4,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.DateRangePicker = DateRangePicker;
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
6
|
/**
|
|
7
|
-
* DateRangePicker — a
|
|
7
|
+
* DateRangePicker — a two-segment popover range control.
|
|
8
8
|
*
|
|
9
|
-
* Two labelled mono trigger segments (from / to)
|
|
10
|
-
* react-day-picker range calendar
|
|
11
|
-
* strings (empty string = unset) so state shapes
|
|
12
|
-
* `date_to` stay untouched. The picker guarantees
|
|
13
|
-
* reorders inverted picks);
|
|
14
|
-
* external validation wiring
|
|
9
|
+
* Two labelled mono trigger segments (from / to) each open the SAME two-month
|
|
10
|
+
* react-day-picker range calendar over the same range selection. The external
|
|
11
|
+
* contract is plain YYYY-MM-DD strings (empty string = unset) so state shapes
|
|
12
|
+
* that speak `date_from`/`date_to` stay untouched. The picker guarantees
|
|
13
|
+
* from <= to (react-day-picker reorders inverted picks);
|
|
14
|
+
* aria-invalid/aria-describedby pass-throughs keep external validation wiring
|
|
15
|
+
* alive. i18n is via plain string/locale props.
|
|
16
|
+
*
|
|
17
|
+
* ONE POPOVER ROOT PER SEGMENT, deliberately. A single `Popover.Root` holds ONE
|
|
18
|
+
* trigger ref and ONE open state, so wrapping the whole two-button row in a
|
|
19
|
+
* single `PopoverTrigger asChild` put Radix's dialog attributes
|
|
20
|
+
* (`aria-haspopup`, `aria-expanded`, `aria-controls`) on a plain, non-focusable
|
|
21
|
+
* `div` — an aria-allowed-attr violation, two buttons advertising the same
|
|
22
|
+
* expanded state, and focus that Radix could drop on `document.body` when the
|
|
23
|
+
* popover closed. Each segment is now a real `PopoverTrigger` button: focusable,
|
|
24
|
+
* correctly named, and the element Radix returns focus to on dismissal.
|
|
15
25
|
*/
|
|
16
26
|
const react_1 = require("react");
|
|
17
27
|
const lucide_react_1 = require("lucide-react");
|
|
@@ -54,7 +64,11 @@ function toDayString(value) {
|
|
|
54
64
|
return `${year}-${month}-${day}`;
|
|
55
65
|
}
|
|
56
66
|
function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid = false, errorId, placeholder = 'Any date', ariaLabel = 'Select date range', clearLabel = 'Clear', locale = locale_1.enUS }) {
|
|
57
|
-
|
|
67
|
+
// Which segment's popover is open, if any. One root per segment means one open
|
|
68
|
+
// state per segment; holding the identity of the open one here keeps them
|
|
69
|
+
// mutually exclusive, so clicking "to" while "from" is open swaps the anchor
|
|
70
|
+
// instead of stacking two calendars.
|
|
71
|
+
const [openSegment, setOpenSegment] = (0, react_1.useState)(null);
|
|
58
72
|
const fromDate = parseDay(value.from);
|
|
59
73
|
const toDate = parseDay(value.to);
|
|
60
74
|
const selected = fromDate || toDate ? { from: fromDate, to: toDate } : undefined;
|
|
@@ -69,6 +83,10 @@ function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabe
|
|
|
69
83
|
});
|
|
70
84
|
};
|
|
71
85
|
const triggerClass = (0, utils_1.cn)('border-input bg-card hover:bg-secondary focus-visible:ring-ring flex h-9 items-center gap-2 rounded-md border px-3 text-left font-mono text-sm tabular-nums transition-colors duration-150 ease-out focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none sm:w-40', invalid && 'border-destructive');
|
|
72
|
-
|
|
73
|
-
|
|
86
|
+
// The one calendar, rendered inside whichever segment's popover is open. Both
|
|
87
|
+
// segments read and write the SAME range selection, so which one you opened
|
|
88
|
+
// changes only the anchor, never the state.
|
|
89
|
+
const calendar = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "range", numberOfMonths: 2, defaultMonth: fromDate ?? toDate ?? new Date(), selected: selected, onSelect: onSelect, locale: locale }), (0, jsx_runtime_1.jsx)("div", { className: "border-border flex items-center justify-end border-t px-3 py-2", children: (0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", variant: "plain", size: "small", disabled: !hasValue, onClick: () => onValueChange({ from: '', to: '' }), children: clearLabel }) })] }));
|
|
90
|
+
const renderSegment = (segment, id, label, dateValue) => ((0, jsx_runtime_1.jsxs)(popover_1.Popover, { open: openSegment === segment, onOpenChange: (next) => setOpenSegment(next ? segment : null), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: id, className: typography_1.SECTION_LABEL_CLASS, children: label }), (0, jsx_runtime_1.jsxs)(popover_1.PopoverTrigger, { type: "button", id: id, className: triggerClass, "aria-invalid": invalid || undefined, "aria-describedby": invalid ? errorId : undefined, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CalendarDays, { className: "text-muted-foreground size-4 shrink-0", "aria-hidden": true }), dateValue ? ((0, jsx_runtime_1.jsx)("span", { children: dateValue })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground font-sans", children: placeholder }))] })] }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { align: "start", className: "w-auto p-0", "aria-label": ariaLabel, children: calendar })] }, segment));
|
|
91
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end", children: [renderSegment('from', fromId, fromLabel, value.from), renderSegment('to', toId, toLabel, value.to)] }));
|
|
74
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enterprise/search-input/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,aAAa,EACb,UAAgB,EAChB,WAAuB,EACvB,YAAY,EAAE,SAAS,EACvB,UAA2B,EAC3B,QAAgB,EAChB,SAAS,EACT,EAAE,EACH,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enterprise/search-input/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,aAAa,EACb,UAAgB,EAChB,WAAuB,EACvB,YAAY,EAAE,SAAS,EACvB,UAA2B,EAC3B,QAAgB,EAChB,SAAS,EACT,EAAE,EACH,EAAE,gBAAgB,qBAsGlB"}
|
|
@@ -72,13 +72,20 @@ function SearchInput({ value, onValueChange, debounceMs = 250, placeholder = 'Se
|
|
|
72
72
|
// initial value is never mistaken for an echo of something we sent.
|
|
73
73
|
const lastEmitted = React.useRef(NO_PENDING_ECHO);
|
|
74
74
|
React.useEffect(() => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
const isEcho = lastEmitted.current === value;
|
|
76
|
+
// ANY external change consumes the token, echo or not. Consuming it only on
|
|
77
|
+
// a match left a DROPPED emission pending forever: emit "pix", the parent
|
|
78
|
+
// rejects it and holds "", the parent later sets "foo" (draft follows, token
|
|
79
|
+
// still holding "pix"), the parent then sets "pix" — read as our own echo,
|
|
80
|
+
// so the draft stayed on "foo" and the visible field disagreed with the
|
|
81
|
+
// controlled value. A later external change is proof the parent moved on,
|
|
82
|
+
// which invalidates any echo still outstanding.
|
|
83
|
+
lastEmitted.current = NO_PENDING_ECHO;
|
|
84
|
+
// A genuine echo must NOT reach the draft: the parent echoes one render
|
|
85
|
+
// later, by which time the user may have typed further, and syncing would
|
|
86
|
+
// rewind the field and swallow those keystrokes.
|
|
87
|
+
if (isEcho)
|
|
80
88
|
return;
|
|
81
|
-
}
|
|
82
89
|
setDraft(value);
|
|
83
90
|
}, [value]);
|
|
84
91
|
const clearTimer = React.useCallback(() => {
|