@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.
Files changed (71) hide show
  1. package/dist/components/form/radio-group-field/index.d.ts +1 -1
  2. package/dist/components/form/radio-group-field/index.d.ts.map +1 -1
  3. package/dist/components/form/radio-group-field/index.js +8 -1
  4. package/dist/components/ui/alert-dialog/index.d.ts.map +1 -1
  5. package/dist/components/ui/alert-dialog/index.js +1 -1
  6. package/dist/components/ui/copy-field/index.d.ts.map +1 -1
  7. package/dist/components/ui/copy-field/index.js +6 -1
  8. package/dist/components/ui/file-upload/index.d.ts.map +1 -1
  9. package/dist/components/ui/file-upload/index.js +8 -1
  10. package/dist/domain/delinquency-aging/aging-buckets.d.ts +22 -2
  11. package/dist/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
  12. package/dist/domain/delinquency-aging/aging-buckets.js +17 -4
  13. package/dist/domain/delinquency-aging/index.d.ts +17 -2
  14. package/dist/domain/delinquency-aging/index.d.ts.map +1 -1
  15. package/dist/domain/delinquency-aging/index.js +4 -2
  16. package/dist/domain/index.d.ts +2 -1
  17. package/dist/domain/index.d.ts.map +1 -1
  18. package/dist/domain/money-diff.d.ts +9 -4
  19. package/dist/domain/money-diff.d.ts.map +1 -1
  20. package/dist/domain/section-label/index.d.ts +3 -3
  21. package/dist/domain/section-label/index.d.ts.map +1 -1
  22. package/dist/domain/section-label/index.js +6 -2
  23. package/dist/domain/status-rail/index.d.ts.map +1 -1
  24. package/dist/domain/status-rail/index.js +9 -1
  25. package/dist/domain/threshold-gauge/index.d.ts.map +1 -1
  26. package/dist/domain/threshold-gauge/index.js +1 -1
  27. package/dist/enterprise/date-range-picker/index.d.ts.map +1 -1
  28. package/dist/enterprise/date-range-picker/index.js +28 -10
  29. package/dist/enterprise/search-input/index.d.ts.map +1 -1
  30. package/dist/enterprise/search-input/index.js +13 -6
  31. package/dist/enterprise/use-is-mobile.d.ts +13 -4
  32. package/dist/enterprise/use-is-mobile.d.ts.map +1 -1
  33. package/dist/enterprise/use-is-mobile.js +15 -6
  34. package/dist/esm/components/form/radio-group-field/index.d.ts +1 -1
  35. package/dist/esm/components/form/radio-group-field/index.d.ts.map +1 -1
  36. package/dist/esm/components/form/radio-group-field/index.js +8 -1
  37. package/dist/esm/components/ui/alert-dialog/index.d.ts.map +1 -1
  38. package/dist/esm/components/ui/alert-dialog/index.js +1 -1
  39. package/dist/esm/components/ui/copy-field/index.d.ts.map +1 -1
  40. package/dist/esm/components/ui/copy-field/index.js +6 -1
  41. package/dist/esm/components/ui/file-upload/index.d.ts.map +1 -1
  42. package/dist/esm/components/ui/file-upload/index.js +8 -1
  43. package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts +22 -2
  44. package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
  45. package/dist/esm/domain/delinquency-aging/aging-buckets.js +17 -4
  46. package/dist/esm/domain/delinquency-aging/index.d.ts +17 -2
  47. package/dist/esm/domain/delinquency-aging/index.d.ts.map +1 -1
  48. package/dist/esm/domain/delinquency-aging/index.js +4 -2
  49. package/dist/esm/domain/index.d.ts +2 -1
  50. package/dist/esm/domain/index.d.ts.map +1 -1
  51. package/dist/esm/domain/money-diff.d.ts +9 -4
  52. package/dist/esm/domain/money-diff.d.ts.map +1 -1
  53. package/dist/esm/domain/section-label/index.d.ts +3 -3
  54. package/dist/esm/domain/section-label/index.d.ts.map +1 -1
  55. package/dist/esm/domain/section-label/index.js +6 -2
  56. package/dist/esm/domain/status-rail/index.d.ts.map +1 -1
  57. package/dist/esm/domain/status-rail/index.js +9 -1
  58. package/dist/esm/domain/threshold-gauge/index.d.ts.map +1 -1
  59. package/dist/esm/domain/threshold-gauge/index.js +1 -1
  60. package/dist/esm/enterprise/date-range-picker/index.d.ts.map +1 -1
  61. package/dist/esm/enterprise/date-range-picker/index.js +29 -11
  62. package/dist/esm/enterprise/search-input/index.d.ts.map +1 -1
  63. package/dist/esm/enterprise/search-input/index.js +13 -6
  64. package/dist/esm/enterprise/use-is-mobile.d.ts +13 -4
  65. package/dist/esm/enterprise/use-is-mobile.d.ts.map +1 -1
  66. package/dist/esm/enterprise/use-is-mobile.js +13 -5
  67. package/dist/esm/theme/theme-provider.d.ts.map +1 -1
  68. package/dist/esm/theme/theme-provider.js +15 -1
  69. package/dist/theme/theme-provider.d.ts.map +1 -1
  70. package/dist/theme/theme-provider.js +15 -1
  71. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import { type ReactNode } from 'react';
2
2
  import { Control, FieldValues, Path } from 'react-hook-form';
3
3
  import { type RenderableLabel } from '../../../components/form/renderable-label';
4
4
  export type RadioGroupFieldOption = {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/radio-group-field/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,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,gCAkEzB,CAAA"}
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,qBAWF;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"}
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,qBAuJhB"}
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, "aria-label": label ? undefined : valueLabel,
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;6LAsRtB,CAAA"}
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
- handleFile(event.target.files?.[0]);
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":"AAsCA,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,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,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;AA2BlE;;;;;;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,SAAS,EACV,EAAE,iBAAiB,+BAwFnB"}
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
- 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: [word, ": "] }), (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: "Itens" })] }), (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, locale: locale, signColor: false }) }), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)(typography_1.LABEL_VOICE_CLASS, 'mt-1'), children: "Total" })] })] }, `${bucket.label}-${i}`));
96
- }) }), 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: "Total geral" }), (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, locale: locale, signColor: false }) })) })] })) : null] }));
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 { AgingBucket } from './aging-buckets';
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":"AAuDA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAOlD;;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,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,IAAW,EACX,MAAY,EACZ,SAAiB,EACjB,SAAS,EACV,EAAE,qBAAqB,+BAiEvB"}
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: [word, ": "] }), (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 ? 'indeterminada' : 'sem carteira' }), (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 })] }));
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
  }
@@ -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;AAExC,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,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,qBAAqB,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 MoneyDiffInput = {
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 for the money figure. */
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,mFAAmF;AACnF,KAAK,cAAc,GAAG;IACpB,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,0CAA0C;IAC1C,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"}
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;AAKnD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wEAAwE;IACxE,EAAE,CAAC,EAAE,WAAW,CAAA;CACjB,CAAA;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,GAAU,EACf,EAAE,iBAAiB,+BAEnB"}
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
- return (0, jsx_runtime_1.jsx)(Tag, { className: (0, utils_1.cn)(typography_1.SECTION_LABEL_CLASS, className), children: children });
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,+BA+DjB;AAkBD,qFAAqF;AACrF,wBAAgB,GAAG,gCAMlB;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,gCAOxB"}
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: [lead !== undefined && lead !== null ? ((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: lead != null || 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)(
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,+BAyErB"}
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":"AAaA,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,+BA0FtB"}
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 single popover range control.
7
+ * DateRangePicker — a two-segment popover range control.
8
8
  *
9
- * Two labelled mono trigger segments (from / to) share one two-month
10
- * react-day-picker range calendar. The external contract is plain YYYY-MM-DD
11
- * strings (empty string = unset) so state shapes that speak `date_from`/
12
- * `date_to` stay untouched. The picker guarantees from <= to (react-day-picker
13
- * reorders inverted picks); aria-invalid/aria-describedby pass-throughs keep
14
- * external validation wiring alive. i18n is via plain string/locale props.
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
- const [open, setOpen] = (0, react_1.useState)(false);
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
- const renderTrigger = (id, label, dateValue) => ((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)("button", { type: "button", id: id, className: triggerClass, "aria-haspopup": "dialog", "aria-expanded": open, "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 }))] })] }));
73
- return ((0, jsx_runtime_1.jsxs)(popover_1.Popover, { open: open, onOpenChange: setOpen, children: [(0, jsx_runtime_1.jsx)(popover_1.PopoverTrigger, { asChild: true, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end", children: [renderTrigger(fromId, fromLabel, value.from), renderTrigger(toId, toLabel, value.to)] }) }), (0, jsx_runtime_1.jsxs)(popover_1.PopoverContent, { align: "start", className: "w-auto p-0", "aria-label": ariaLabel, 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 }) })] })] }));
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,qBAgGlB"}
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
- if (lastEmitted.current === value) {
76
- // This is the echo of our own emission. Consume the token: a LATER
77
- // external change back to this same text (foo -> bar -> foo) is a real
78
- // change and must reach the draft.
79
- lastEmitted.current = NO_PENDING_ECHO;
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(() => {