@lerianstudio/sindarian-ui 1.3.0 → 1.4.0-beta.2

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 (160) hide show
  1. package/README.md +93 -12
  2. package/dist/components/card/account-card/index.d.ts.map +1 -1
  3. package/dist/components/card/account-card/index.js +2 -2
  4. package/dist/components/card/entity-card/index.d.ts.map +1 -1
  5. package/dist/components/card/entity-card/index.js +5 -1
  6. package/dist/components/dialog/confirmation-dialog/index.d.ts +10 -2
  7. package/dist/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
  8. package/dist/components/dialog/confirmation-dialog/index.js +72 -7
  9. package/dist/components/page-header/index.d.ts +14 -2
  10. package/dist/components/page-header/index.d.ts.map +1 -1
  11. package/dist/components/page-header/index.js +4 -4
  12. package/dist/components/ui/accordion/index.js +1 -1
  13. package/dist/components/ui/alert/index.d.ts +1 -1
  14. package/dist/components/ui/alert/styles.css +3 -3
  15. package/dist/components/ui/alert-dialog/index.d.ts +8 -2
  16. package/dist/components/ui/alert-dialog/index.d.ts.map +1 -1
  17. package/dist/components/ui/alert-dialog/index.js +4 -4
  18. package/dist/components/ui/autocomplete/index.d.ts +1 -1
  19. package/dist/components/ui/autocomplete/index.d.ts.map +1 -1
  20. package/dist/components/ui/autocomplete/index.js +42 -6
  21. package/dist/components/ui/badge/index.d.ts +10 -2
  22. package/dist/components/ui/badge/index.d.ts.map +1 -1
  23. package/dist/components/ui/badge/index.js +24 -4
  24. package/dist/components/ui/breadcrumb/styles.css +1 -1
  25. package/dist/components/ui/button/index.d.ts +2 -2
  26. package/dist/components/ui/button/index.d.ts.map +1 -1
  27. package/dist/components/ui/button/index.js +2 -1
  28. package/dist/components/ui/button/styles.css +17 -4
  29. package/dist/components/ui/card/index.d.ts +10 -2
  30. package/dist/components/ui/card/index.d.ts.map +1 -1
  31. package/dist/components/ui/card/index.js +2 -2
  32. package/dist/components/ui/command/index.js +1 -1
  33. package/dist/components/ui/dialog/styles.css +3 -3
  34. package/dist/components/ui/dropdown-menu/index.js +2 -2
  35. package/dist/components/ui/hover-card/index.js +1 -1
  36. package/dist/components/ui/input/adornment.d.ts +1 -1
  37. package/dist/components/ui/loading-button/index.js +1 -1
  38. package/dist/components/ui/multiple-select/index.js +1 -1
  39. package/dist/components/ui/otp-input/index.js +1 -1
  40. package/dist/components/ui/paper-collapsible/index.js +1 -1
  41. package/dist/components/ui/popover/index.js +1 -1
  42. package/dist/components/ui/select/styles.css +1 -1
  43. package/dist/components/ui/sheet/index.d.ts +1 -1
  44. package/dist/components/ui/sheet/index.js +2 -2
  45. package/dist/components/ui/sidebar/sidebar-expand-button.d.ts +5 -0
  46. package/dist/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
  47. package/dist/components/ui/sidebar/sidebar-expand-button.js +1 -1
  48. package/dist/components/ui/sidebar/sidebar-item-collapsible.js +1 -1
  49. package/dist/components/ui/skeleton/index.js +1 -1
  50. package/dist/components/ui/toast/toaster.d.ts +5 -0
  51. package/dist/components/ui/toast/toaster.d.ts.map +1 -1
  52. package/dist/components/ui/toast/toaster.js +6 -2
  53. package/dist/components/ui/tooltip/index.js +1 -1
  54. package/dist/domain/blotter/index.d.ts +7 -1
  55. package/dist/domain/blotter/index.d.ts.map +1 -1
  56. package/dist/domain/blotter/index.js +7 -3
  57. package/dist/domain/delinquency-aging/aging-buckets.d.ts +4 -1
  58. package/dist/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
  59. package/dist/domain/delinquency-aging/aging-buckets.js +7 -2
  60. package/dist/domain/delinquency-aging/index.d.ts +11 -1
  61. package/dist/domain/delinquency-aging/index.d.ts.map +1 -1
  62. package/dist/domain/delinquency-aging/index.js +7 -3
  63. package/dist/domain/figure/index.d.ts +13 -6
  64. package/dist/domain/figure/index.d.ts.map +1 -1
  65. package/dist/domain/figure/index.js +1 -0
  66. package/dist/domain/section-label/index.d.ts +7 -1
  67. package/dist/domain/section-label/index.d.ts.map +1 -1
  68. package/dist/domain/section-label/index.js +6 -2
  69. package/dist/enterprise/app-shell/index.d.ts +14 -0
  70. package/dist/enterprise/app-shell/index.d.ts.map +1 -1
  71. package/dist/enterprise/app-shell/index.js +2 -2
  72. package/dist/enterprise/data-table/index.d.ts +13 -1
  73. package/dist/enterprise/data-table/index.d.ts.map +1 -1
  74. package/dist/enterprise/data-table/index.js +7 -3
  75. package/dist/enterprise/search-input/index.d.ts +7 -1
  76. package/dist/enterprise/search-input/index.d.ts.map +1 -1
  77. package/dist/enterprise/search-input/index.js +2 -2
  78. package/dist/esm/components/card/account-card/index.d.ts.map +1 -1
  79. package/dist/esm/components/card/account-card/index.js +2 -2
  80. package/dist/esm/components/card/entity-card/index.d.ts.map +1 -1
  81. package/dist/esm/components/card/entity-card/index.js +5 -1
  82. package/dist/esm/components/dialog/confirmation-dialog/index.d.ts +10 -2
  83. package/dist/esm/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
  84. package/dist/esm/components/dialog/confirmation-dialog/index.js +39 -7
  85. package/dist/esm/components/page-header/index.d.ts +14 -2
  86. package/dist/esm/components/page-header/index.d.ts.map +1 -1
  87. package/dist/esm/components/page-header/index.js +4 -4
  88. package/dist/esm/components/ui/accordion/index.js +1 -1
  89. package/dist/esm/components/ui/alert/index.d.ts +1 -1
  90. package/dist/esm/components/ui/alert-dialog/index.d.ts +8 -2
  91. package/dist/esm/components/ui/alert-dialog/index.d.ts.map +1 -1
  92. package/dist/esm/components/ui/alert-dialog/index.js +4 -4
  93. package/dist/esm/components/ui/autocomplete/index.d.ts +1 -1
  94. package/dist/esm/components/ui/autocomplete/index.d.ts.map +1 -1
  95. package/dist/esm/components/ui/autocomplete/index.js +42 -6
  96. package/dist/esm/components/ui/badge/index.d.ts +10 -2
  97. package/dist/esm/components/ui/badge/index.d.ts.map +1 -1
  98. package/dist/esm/components/ui/badge/index.js +24 -4
  99. package/dist/esm/components/ui/button/index.d.ts +2 -2
  100. package/dist/esm/components/ui/button/index.d.ts.map +1 -1
  101. package/dist/esm/components/ui/button/index.js +2 -1
  102. package/dist/esm/components/ui/card/index.d.ts +10 -2
  103. package/dist/esm/components/ui/card/index.d.ts.map +1 -1
  104. package/dist/esm/components/ui/card/index.js +2 -2
  105. package/dist/esm/components/ui/command/index.js +1 -1
  106. package/dist/esm/components/ui/dropdown-menu/index.js +2 -2
  107. package/dist/esm/components/ui/hover-card/index.js +1 -1
  108. package/dist/esm/components/ui/input/adornment.d.ts +1 -1
  109. package/dist/esm/components/ui/loading-button/index.js +1 -1
  110. package/dist/esm/components/ui/multiple-select/index.js +1 -1
  111. package/dist/esm/components/ui/otp-input/index.js +1 -1
  112. package/dist/esm/components/ui/paper-collapsible/index.js +1 -1
  113. package/dist/esm/components/ui/popover/index.js +1 -1
  114. package/dist/esm/components/ui/sheet/index.d.ts +1 -1
  115. package/dist/esm/components/ui/sheet/index.js +2 -2
  116. package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts +5 -0
  117. package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
  118. package/dist/esm/components/ui/sidebar/sidebar-expand-button.js +1 -1
  119. package/dist/esm/components/ui/sidebar/sidebar-item-collapsible.js +1 -1
  120. package/dist/esm/components/ui/skeleton/index.js +1 -1
  121. package/dist/esm/components/ui/toast/toaster.d.ts +5 -0
  122. package/dist/esm/components/ui/toast/toaster.d.ts.map +1 -1
  123. package/dist/esm/components/ui/toast/toaster.js +6 -2
  124. package/dist/esm/components/ui/tooltip/index.js +1 -1
  125. package/dist/esm/domain/blotter/index.d.ts +7 -1
  126. package/dist/esm/domain/blotter/index.d.ts.map +1 -1
  127. package/dist/esm/domain/blotter/index.js +7 -3
  128. package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts +4 -1
  129. package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
  130. package/dist/esm/domain/delinquency-aging/aging-buckets.js +7 -2
  131. package/dist/esm/domain/delinquency-aging/index.d.ts +11 -1
  132. package/dist/esm/domain/delinquency-aging/index.d.ts.map +1 -1
  133. package/dist/esm/domain/delinquency-aging/index.js +7 -3
  134. package/dist/esm/domain/figure/index.d.ts +13 -6
  135. package/dist/esm/domain/figure/index.d.ts.map +1 -1
  136. package/dist/esm/domain/figure/index.js +1 -0
  137. package/dist/esm/domain/section-label/index.d.ts +7 -1
  138. package/dist/esm/domain/section-label/index.d.ts.map +1 -1
  139. package/dist/esm/domain/section-label/index.js +6 -2
  140. package/dist/esm/enterprise/app-shell/index.d.ts +14 -0
  141. package/dist/esm/enterprise/app-shell/index.d.ts.map +1 -1
  142. package/dist/esm/enterprise/app-shell/index.js +2 -2
  143. package/dist/esm/enterprise/data-table/index.d.ts +13 -1
  144. package/dist/esm/enterprise/data-table/index.d.ts.map +1 -1
  145. package/dist/esm/enterprise/data-table/index.js +8 -4
  146. package/dist/esm/enterprise/search-input/index.d.ts +7 -1
  147. package/dist/esm/enterprise/search-input/index.d.ts.map +1 -1
  148. package/dist/esm/enterprise/search-input/index.js +2 -2
  149. package/dist/esm/lib/utils.d.ts.map +1 -1
  150. package/dist/esm/lib/utils.js +27 -1
  151. package/dist/esm/theme/theme-provider.d.ts +8 -0
  152. package/dist/esm/theme/theme-provider.d.ts.map +1 -1
  153. package/dist/esm/theme/theme-provider.js +10 -0
  154. package/dist/globals.css +85 -58
  155. package/dist/lib/utils.d.ts.map +1 -1
  156. package/dist/lib/utils.js +27 -1
  157. package/dist/theme/theme-provider.d.ts +8 -0
  158. package/dist/theme/theme-provider.d.ts.map +1 -1
  159. package/dist/theme/theme-provider.js +11 -0
  160. package/package.json +1 -1
@@ -1,12 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Skeleton } from '../../components/ui/skeleton/index.js';
2
3
  import { LABEL_VOICE_CLASS } from '../../lib/typography.js';
3
4
  import { cn } from '../../lib/utils.js';
4
5
  export function Blotter({ children, className }) {
5
6
  return _jsx("dl", { className: cn('divide-border divide-y', className), children: children });
6
7
  }
7
- export function BlotterRow({ label, value, valueClassName, className, stacked = false }) {
8
+ export function BlotterRow({ label, value, valueClassName, className, stacked = false, loading = false }) {
9
+ // The skeleton stands in for the value slot's own shape: a full-width prose
10
+ // line when stacked, the mono figure's width when inline.
11
+ const shownValue = loading ? (_jsx(Skeleton, { className: cn('h-4', stacked ? 'w-full' : 'w-24') })) : (value);
8
12
  if (stacked) {
9
- return (_jsxs("div", { className: cn('hover:bg-body-surface space-y-1 px-2 py-2 transition-colors duration-150 ease-out', className), children: [_jsx("dt", { className: LABEL_VOICE_CLASS, children: label }), _jsx("dd", { className: cn('text-foreground text-sm break-words whitespace-pre-wrap', valueClassName), children: value })] }));
13
+ return (_jsxs("div", { "aria-busy": loading || undefined, className: cn('hover:bg-body-surface space-y-1 px-2 py-2 transition-colors duration-150 ease-out', className), children: [_jsx("dt", { className: LABEL_VOICE_CLASS, children: label }), _jsx("dd", { className: cn('text-foreground text-sm break-words whitespace-pre-wrap', valueClassName), children: shownValue })] }));
10
14
  }
11
- return (_jsxs("div", { className: cn('hover:bg-body-surface flex items-center justify-between gap-3 px-2 py-2 transition-colors duration-150 ease-out', className), children: [_jsx("dt", { className: LABEL_VOICE_CLASS, children: label }), _jsx("dd", { className: cn('font-mono text-sm font-medium tabular-nums', valueClassName), children: value })] }));
15
+ return (_jsxs("div", { "aria-busy": loading || undefined, className: cn('hover:bg-body-surface flex items-center justify-between gap-3 px-2 py-2 transition-colors duration-150 ease-out', className), children: [_jsx("dt", { className: LABEL_VOICE_CLASS, children: label }), _jsx("dd", { className: cn('font-mono text-sm font-medium tabular-nums', valueClassName), children: shownValue })] }));
12
16
  }
@@ -36,6 +36,9 @@ export interface AgingBucketsProps {
36
36
  showTotal?: boolean;
37
37
  /** Override the fixed pt-BR copy. Omitted fields keep their defaults. */
38
38
  labels?: AgingBucketsLabels;
39
+ /** Tint of the healthy (`current`) band: ambient green, or ink. Threaded in
40
+ * from `DelinquencyAging`; see the knob's doc there. Defaults to `success`. */
41
+ healthyTone?: 'success' | 'ink';
39
42
  className?: string;
40
43
  }
41
44
  /**
@@ -53,5 +56,5 @@ export declare function bucketBand(index: number, count: number): AgingBand;
53
56
  * grand total. Pure: the money-math third rail, unit-tested.
54
57
  */
55
58
  export declare function sumBucketTotals(buckets: AgingBucket[], scale: number): string | null;
56
- export declare function AgingBuckets({ buckets, currency, locale, showTotal, labels, className }: AgingBucketsProps): import("react").JSX.Element;
59
+ export declare function AgingBuckets({ buckets, currency, locale, showTotal, labels, healthyTone, className }: AgingBucketsProps): import("react").JSX.Element;
57
60
  //# 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":"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"}
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;oFACgF;IAChF,WAAW,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC/B,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,WAAuB,EACvB,SAAS,EACV,EAAE,iBAAiB,+BA+GnB"}
@@ -84,7 +84,7 @@ export function sumBucketTotals(buckets, scale) {
84
84
  const total = sumMinor(buckets.map((b) => b.total), scale);
85
85
  return total === null ? null : minorToDecimal(total, scale);
86
86
  }
87
- export function AgingBuckets({ buckets, currency, locale, showTotal = false, labels, className }) {
87
+ export function AgingBuckets({ buckets, currency, locale, showTotal = false, labels, healthyTone = 'success', className }) {
88
88
  const countLabel = labels?.count ?? 'Itens';
89
89
  const totalLabel = labels?.total ?? 'Total';
90
90
  const grandTotalLabel = labels?.grandTotal ?? 'Total geral';
@@ -97,7 +97,12 @@ export function AgingBuckets({ buckets, currency, locale, showTotal = false, lab
97
97
  const grandTotal = showTotal ? sumBucketTotals(buckets, scale) : null;
98
98
  return (_jsxs("div", { className: cn('flex flex-col', className), children: [_jsx("ul", { className: "flex flex-col", children: buckets.map((bucket, i) => {
99
99
  const band = bucketBand(i, buckets.length);
100
- const { Icon, tint, word } = BAND[band];
100
+ const { Icon, word } = BAND[band];
101
+ // `ink` retones ONLY the healthy band — the escalated bands keep their
102
+ // alert and credit-red tints, which are the whole point of the scale.
103
+ const tint = healthyTone === 'ink' && band === 'current'
104
+ ? 'text-foreground'
105
+ : BAND[band].tint;
101
106
  // Shallow merge: an unlisted band keeps its pt-BR default.
102
107
  const bandWord = labels?.bands?.[band] ?? word;
103
108
  return (_jsxs("li", { className: "border-border flex items-center gap-3 border-b py-2.5 last:border-b-0", children: [_jsx(Icon, { "aria-hidden": true, className: cn('size-4 shrink-0', tint) }), _jsxs("span", { className: "sr-only", children: [bandWord, ": "] }), _jsx("span", { className: cn(LABEL_VOICE_CLASS, 'text-foreground min-w-0 flex-1 tracking-normal normal-case'), children: bucket.label }), _jsxs("span", { className: "flex shrink-0 flex-col items-end leading-none", children: [_jsx(Figure, { size: "row", className: "text-foreground", children: formatCount(bucket.count, locale) }), _jsx("span", { className: cn(LABEL_VOICE_CLASS, 'mt-1'), children: countLabel })] }), _jsxs("span", { className: "flex w-32 shrink-0 flex-col items-end leading-none sm:w-40", children: [_jsx(Figure, { size: "row", className: cn(band === 'overdue' && 'text-credit'), children: _jsx(MoneyText, { amount: bucket.total, currency: currency, fractionDigits: scale, locale: locale, signColor: false }) }), _jsx("span", { className: cn(LABEL_VOICE_CLASS, 'mt-1'), children: totalLabel })] })] }, `${bucket.label}-${i}`));
@@ -65,7 +65,17 @@ export interface DelinquencyAgingProps {
65
65
  breach?: number;
66
66
  /** Render the money-math-exact grand total row under the distribution. */
67
67
  showTotal?: boolean;
68
+ /**
69
+ * Tint of the healthy band — the low delinquency rate AND the `current`
70
+ * aging bucket. `'success'` (default) is the ambient green; `'ink'` retones
71
+ * both to `text-foreground`, which is the Ledger canon for a healthy-but-
72
+ * nonzero book: green reads as "achievement", and a book merely not in
73
+ * arrears has achieved nothing. Scoped to the healthy band only — elevated,
74
+ * distressed and overdue keep their alert and credit-red tints, since the
75
+ * glyph + sr-only word (not the tint) are the load-bearing cue either way.
76
+ */
77
+ healthyTone?: 'success' | 'ink';
68
78
  className?: string;
69
79
  }
70
- export declare function DelinquencyAging({ buckets, currency, locale, rateLabel, rateBandLabels, emptyLabel, indeterminateLabel, bucketLabels, warn, breach, showTotal, className }: DelinquencyAgingProps): import("react").JSX.Element;
80
+ export declare function DelinquencyAging({ buckets, currency, locale, rateLabel, rateBandLabels, emptyLabel, indeterminateLabel, bucketLabels, warn, breach, showTotal, healthyTone, className }: DelinquencyAgingProps): import("react").JSX.Element;
71
81
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/delinquency-aging/index.tsx"],"names":[],"mappings":"AAoDA,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;AAoFD,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;;;mDAG+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;yEACqE;IACrE,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,+BAyEvB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/delinquency-aging/index.tsx"],"names":[],"mappings":"AAoDA,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;AAoFD,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;;;mDAG+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;yEACqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC/B,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,WAAuB,EACvB,SAAS,EACV,EAAE,qBAAqB,+BA+EvB"}
@@ -184,7 +184,7 @@ const RATE_BAND = {
184
184
  warn: { Icon: TriangleAlert, tint: 'text-system-alert', word: 'Elevada' },
185
185
  breach: { Icon: AlertOctagon, tint: 'text-credit', word: 'Em estresse' }
186
186
  };
187
- export function DelinquencyAging({ buckets, currency, locale, rateLabel = 'Inadimplência', rateBandLabels, emptyLabel = 'sem carteira', indeterminateLabel = 'indeterminada', bucketLabels, warn = 0.05, breach = 0.1, showTotal = false, className }) {
187
+ export function DelinquencyAging({ buckets, currency, locale, rateLabel = 'Inadimplência', rateBandLabels, emptyLabel = 'sem carteira', indeterminateLabel = 'indeterminada', bucketLabels, warn = 0.05, breach = 0.1, showTotal = false, healthyTone = 'success', className }) {
188
188
  // THIRD RAIL: the rate scale and the two totals come from money-math, never
189
189
  // float. The division below is of two exact BigInt-derived integers.
190
190
  const scale = currency ? minorDigitsOf(currency) : 2;
@@ -198,12 +198,16 @@ export function DelinquencyAging({ buckets, currency, locale, rateLabel = 'Inadi
198
198
  const band = hasRate && overdueMinor !== null && totalMinor !== null
199
199
  ? exactBand(overdueMinor, totalMinor, warn, breach)
200
200
  : 'low';
201
- const { Icon, tint, word } = RATE_BAND[band];
201
+ const { Icon, word } = RATE_BAND[band];
202
+ // `ink` retones ONLY the healthy band; `warn`/`breach` keep their alarm tints.
203
+ const tint = healthyTone === 'ink' && band === 'low'
204
+ ? 'text-foreground'
205
+ : RATE_BAND[band].tint;
202
206
  // Shallow merge: an unlisted band keeps its pt-BR default.
203
207
  const bandWord = rateBandLabels?.[band] ?? word;
204
208
  const distressed = band === 'breach';
205
209
  return (_jsxs("div", { className: cn('flex flex-col gap-4', className), children: [_jsxs("header", { className: "flex items-baseline justify-between gap-3", children: [_jsx(SectionLabel, { as: "span", children: rateLabel }), hasRate ? (_jsxs("span", {
206
210
  // A distressed rate is a credit alarm: announced the moment it
207
211
  // crosses the band, so assistive tech does not lean on the tint.
208
- role: distressed ? 'alert' : undefined, className: cn('inline-flex items-center gap-1.5', tint), children: [_jsx(Icon, { "aria-hidden": true, className: "size-4 shrink-0" }), _jsxs("span", { className: "sr-only", children: [bandWord, ": "] }), _jsx(Figure, { size: "row", className: tint, children: formatPercent(rate, { unit: 'ratio', locale }) })] })) : (_jsxs("span", { className: "text-muted-foreground inline-flex items-center gap-1.5", children: [_jsx("span", { className: cn(LABEL_VOICE_CLASS, 'tracking-normal normal-case'), children: indeterminate ? indeterminateLabel : emptyLabel }), _jsx(Figure, { size: "row", className: "text-muted-foreground", children: NO_VALUE })] }))] }), _jsx(AgingBuckets, { buckets: buckets, currency: currency, locale: locale, showTotal: showTotal, labels: bucketLabels })] }));
212
+ role: distressed ? 'alert' : undefined, className: cn('inline-flex items-center gap-1.5', tint), children: [_jsx(Icon, { "aria-hidden": true, className: "size-4 shrink-0" }), _jsxs("span", { className: "sr-only", children: [bandWord, ": "] }), _jsx(Figure, { size: "row", className: tint, children: formatPercent(rate, { unit: 'ratio', locale }) })] })) : (_jsxs("span", { className: "text-muted-foreground inline-flex items-center gap-1.5", children: [_jsx("span", { className: cn(LABEL_VOICE_CLASS, 'tracking-normal normal-case'), children: indeterminate ? indeterminateLabel : emptyLabel }), _jsx(Figure, { size: "row", className: "text-muted-foreground", children: NO_VALUE })] }))] }), _jsx(AgingBuckets, { buckets: buckets, currency: currency, locale: locale, showTotal: showTotal, labels: bucketLabels, healthyTone: healthyTone })] }));
209
213
  }
@@ -8,14 +8,21 @@
8
8
  * `FIGURE_CLASS` constants when composing className strings inline.
9
9
  *
10
10
  * Scale:
11
- * - hero : the dominant in-bar figure — text-4xl/5xl, semibold, tracking-tight
12
- * - panel : compliance / exposure — text-3xl, semibold, tracking-tight
13
- * - count : ledger count — text-2xl, semibold, tracking-tight
14
- * - row : inline / row figure — text-sm
15
- * - tick : ruler / micro figure — text-[10px], leading-none
11
+ * - hero : the dominant in-bar figure — text-4xl/5xl, semibold, tracking-tight
12
+ * - money-hero : hero-role MONEY figure — text-2xl/3xl, semibold, tracking-tight
13
+ * - panel : compliance / exposure — text-3xl, semibold, tracking-tight
14
+ * - count : ledger count — text-2xl, semibold, tracking-tight
15
+ * - row : inline / row figure — text-sm
16
+ * - tick : ruler / micro figure — text-[10px], leading-none
17
+ *
18
+ * `money-hero` is `hero`'s role at one step down the scale: a formatted BRL
19
+ * amount runs ~13 characters, which clips a three-column panel at 4xl/5xl, so
20
+ * consoles were hand-rolling `text-2xl lg:text-3xl` at the call site and losing
21
+ * the mono/tabular/weight invariants along the way. Same responsive shape as
22
+ * `hero`, same weight and tracking — only the two size steps differ.
16
23
  */
17
24
  import type { ElementType, ReactNode } from 'react';
18
- export type FigureSize = 'hero' | 'panel' | 'count' | 'row' | 'tick';
25
+ export type FigureSize = 'hero' | 'money-hero' | 'panel' | 'count' | 'row' | 'tick';
19
26
  /** Canonical class strings per figure size. The `tabular-nums` and `font-mono`
20
27
  * invariants live here so they can never be forgotten at a call site. */
21
28
  export declare const FIGURE_CLASS: Record<FigureSize, string>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/figure/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAInD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAA;AAEpE;0EAC0E;AAC1E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAMnD,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8EAA8E;IAC9E,EAAE,CAAC,EAAE,WAAW,CAAA;CACjB,CAAA;AAED,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,GAAY,EACjB,EAAE,WAAW,+BAEb"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/domain/figure/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAInD,MAAM,MAAM,UAAU,GACpB,MAAM,GAAG,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAA;AAE5D;0EAC0E;AAC1E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAQnD,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8EAA8E;IAC9E,EAAE,CAAC,EAAE,WAAW,CAAA;CACjB,CAAA;AAED,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,GAAY,EACjB,EAAE,WAAW,+BAEb"}
@@ -4,6 +4,7 @@ import { cn } from '../../lib/utils.js';
4
4
  * invariants live here so they can never be forgotten at a call site. */
5
5
  export const FIGURE_CLASS = {
6
6
  hero: 'font-mono text-4xl font-semibold tracking-tight tabular-nums lg:text-5xl',
7
+ 'money-hero': 'font-mono text-2xl font-semibold tracking-tight tabular-nums lg:text-3xl',
7
8
  panel: 'font-mono text-3xl font-semibold tracking-tight tabular-nums',
8
9
  count: 'font-mono text-2xl font-semibold tracking-tight tabular-nums',
9
10
  row: 'font-mono text-sm tabular-nums',
@@ -16,6 +16,12 @@ export type SectionLabelProps = {
16
16
  className?: string;
17
17
  /** Render element. Defaults to `h2` (the ledger-sheet cell heading). */
18
18
  as?: ElementType;
19
+ /**
20
+ * Rule the label as an entry-section head (hairline double border, `pb-2`)
21
+ * and stamp `data-variant="ruled"`. Mirrors `EmptyState.ruled`. Default off,
22
+ * so an unruled label renders exactly as before.
23
+ */
24
+ ruled?: boolean;
19
25
  } & Omit<HTMLAttributes<HTMLElement>, 'children' | 'className'>;
20
- export declare function SectionLabel({ children, className, as: Tag, ...rest }: SectionLabelProps): import("react").JSX.Element;
26
+ export declare function SectionLabel({ children, className, as: Tag, ruled, ...rest }: SectionLabelProps): import("react").JSX.Element;
21
27
  //# 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,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"}
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;AAUnE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wEAAwE;IACxE,EAAE,CAAC,EAAE,WAAW,CAAA;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,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,KAAa,EACb,GAAG,IAAI,EACR,EAAE,iBAAiB,+BAcnB"}
@@ -1,10 +1,14 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { SECTION_LABEL_CLASS } from '../../lib/typography.js';
3
3
  import { cn } from '../../lib/utils.js';
4
- export function SectionLabel({ children, className, as: Tag = 'h2', ...rest }) {
4
+ /** The entry-section head treatment: a hairline double rule under the label.
5
+ * `border-border`, NOT the register head's ink — this is the quieter of the two
6
+ * head rules. Pinned here because ~20 call sites were restating it. */
7
+ const RULED_CLASS = 'border-b-[3px] border-double border-border pb-2';
8
+ export function SectionLabel({ children, className, as: Tag = 'h2', ruled = false, ...rest }) {
5
9
  // The remaining element props reach the rendered tag, so a panel can point
6
10
  // `aria-labelledby` at this heading via `id`, and tests can hang a `data-*`
7
11
  // hook off it. Without the spread there was no way to reference the heading
8
12
  // from its own container.
9
- return (_jsx(Tag, { className: cn(SECTION_LABEL_CLASS, className), ...rest, children: children }));
13
+ return (_jsx(Tag, { ...rest, "data-variant": ruled ? 'ruled' : undefined, className: cn(SECTION_LABEL_CLASS, ruled && RULED_CLASS, className), children: children }));
10
14
  }
@@ -46,6 +46,20 @@ export type AppShellProps = {
46
46
  * inside <main> and are correctly page content, not a top-level landmark.
47
47
  */
48
48
  header?: React.ReactNode;
49
+ /**
50
+ * Accessible name for the <header> banner landmark, rendered as its
51
+ * `aria-label`. Omit it and the attribute is absent — the single banner is
52
+ * unambiguous on its own, so a name buys nothing and an unlocalized one costs
53
+ * clarity.
54
+ *
55
+ * Name it when the page carries MORE than one banner-role region (the shell's
56
+ * banner plus, say, an embedded app frame), because a screen-reader landmark
57
+ * list then shows two entries called "banner" with nothing to tell them
58
+ * apart. Also name it when an audit rule demands every landmark be named
59
+ * (`landmark-unique` / a house i18n-strict policy). Pass an ALREADY-TRANSLATED
60
+ * string — the shell does no i18n.
61
+ */
62
+ headerLabel?: string;
49
63
  children: React.ReactNode;
50
64
  className?: string;
51
65
  contentClassName?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/app-shell/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED,eAAO,MAAM,QAAQ,mFAgEpB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/app-shell/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED,eAAO,MAAM,QAAQ,mFAoEpB,CAAA"}
@@ -36,14 +36,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
36
36
  import * as React from 'react';
37
37
  import { SidebarProvider } from '../../components/ui/sidebar/index.js';
38
38
  import { cn } from '../../lib/utils.js';
39
- export const AppShell = React.forwardRef(function AppShell({ sidebar, header, children, className, contentClassName, skipToContentLabel }, ref) {
39
+ export const AppShell = React.forwardRef(function AppShell({ sidebar, header, headerLabel, children, className, contentClassName, skipToContentLabel }, ref) {
40
40
  // The content <main> id — wires the skip link to its target and gives the
41
41
  // <main> a stable, focusable anchor. Internal: no consumer-facing id prop.
42
42
  const mainId = React.useId();
43
43
  // sindarian-ui's SidebarProvider is context-only (it renders no DOM and
44
44
  // takes no className), so the shell owns the flex row itself and `className`
45
45
  // lands on it — the same element the legacy provider's className reached.
46
- return (_jsx(SidebarProvider, { children: _jsxs("div", { className: cn('flex h-svh w-full overflow-hidden', className), children: [skipToContentLabel ? (_jsx("a", { href: `#${mainId}`, className: "focus:bg-background focus:text-foreground sr-only focus:not-sr-only focus:absolute focus:z-50 focus:m-2 focus:rounded focus:px-3 focus:py-2 focus:shadow", children: skipToContentLabel })) : null, sidebar, _jsxs("div", { "data-slot": "sidebar-inset", className: "bg-background relative flex w-full min-w-0 flex-1 flex-col", children: [header ? (_jsx("header", { className: "border-border bg-background sticky top-0 z-10 flex items-center gap-3 border-b px-6 py-3", children: header })) : null, _jsx("main", { id: mainId, ref: ref, tabIndex: -1,
46
+ return (_jsx(SidebarProvider, { children: _jsxs("div", { className: cn('flex h-svh w-full overflow-hidden', className), children: [skipToContentLabel ? (_jsx("a", { href: `#${mainId}`, className: "focus:bg-background focus:text-foreground sr-only focus:not-sr-only focus:absolute focus:z-50 focus:m-2 focus:rounded focus:px-3 focus:py-2 focus:shadow", children: skipToContentLabel })) : null, sidebar, _jsxs("div", { "data-slot": "sidebar-inset", className: "bg-background relative flex w-full min-w-0 flex-1 flex-col", children: [header ? (_jsx("header", { "aria-label": headerLabel, className: "border-border bg-background sticky top-0 z-10 flex items-center gap-3 border-b px-6 py-3", children: header })) : null, _jsx("main", { id: mainId, ref: ref, tabIndex: -1,
47
47
  // min-h-0 lets this flex child shrink below its content height —
48
48
  // without it `flex-1` keeps min-height:auto and nothing scrolls.
49
49
  className: "min-h-0 flex-1 overflow-y-auto outline-none", children: _jsx("div", { className: cn('mx-auto w-full max-w-7xl px-6 py-8 lg:px-8', contentClassName), children: children }) })] })] }) }));
@@ -81,8 +81,20 @@ type DataTableBaseProps<TData> = {
81
81
  */
82
82
  rowHref?: (row: TData) => string;
83
83
  className?: string;
84
+ /**
85
+ * Extra classes merged onto every header cell, after the kit label voice —
86
+ * so a caller can override the voice's size/tracking/color for one table
87
+ * without restating the cluster. Per-column alignment stays `meta.numeric`.
88
+ */
89
+ headClassName?: string;
90
+ /**
91
+ * Footed-total row(s) rendered inside the kit `TableFooter` after the body.
92
+ * The caller supplies the row markup (`<tr><td>…</td></tr>`) so the footer
93
+ * can span, align and format its own figures. Omitted → no `tfoot`.
94
+ */
95
+ footer?: React.ReactNode;
84
96
  };
85
97
  export type DataTableProps<TData> = DataTableBaseProps<TData> & RowSelectionProps<TData>;
86
- export declare function DataTable<TData>({ columns, data, loading, skeletonRows, loadingLabel, empty, getRowId, flush, density, enableRowSelection, rowSelection, onRowSelectionChange, getRowSelectionLabel, onRowActivate, rowHref, className }: DataTableProps<TData>): import("react").JSX.Element;
98
+ export declare function DataTable<TData>({ columns, data, loading, skeletonRows, loadingLabel, empty, getRowId, flush, density, enableRowSelection, rowSelection, onRowSelectionChange, getRowSelectionLabel, onRowActivate, rowHref, className, headClassName, footer }: DataTableProps<TData>): import("react").JSX.Element;
87
99
  export {};
88
100
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/data-table/index.tsx"],"names":[],"mappings":"AAmCA,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,UAAU,EAEf,KAAK,OAAO,EACZ,KAAK,iBAAiB,EAEvB,MAAM,uBAAuB,CAAA;AAY9B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAEjE;;;;GAIG;AACH,OAAO,QAAQ,uBAAuB,CAAC;IAIrC,UAAU,UAAU,CAAC,KAAK,SAAS,OAAO,EAAE,MAAM;QAChD,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB;CACF;AAED;;;;;;;;GAQG;AACH,KAAK,iBAAiB,CAAC,KAAK,IACxB;IACE,kBAAkB,CAAC,EAAE,KAAK,CAAA;IAC1B,YAAY,CAAC,EAAE,KAAK,CAAA;IACpB,oBAAoB,CAAC,EAAE,KAAK,CAAA;IAC5B,oBAAoB,CAAC,EAAE,KAAK,CAAA;CAC7B,GACD;IACE,kBAAkB,EAAE,IAAI,CAAA;IACxB,kFAAkF;IAClF,YAAY,EAAE,iBAAiB,CAAA;IAC/B,4DAA4D;IAC5D,oBAAoB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACnD;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAA;CAC9C,CAAA;AAEL,KAAK,kBAAkB,CAAC,KAAK,IAAI;IAC/B,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAA;IACpC,IAAI,EAAE,KAAK,EAAE,CAAA;IACb,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAChD;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;IACnC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IACpC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,kBAAkB,CAAC,KAAK,CAAC,GAC3D,iBAAiB,CAAC,KAAK,CAAC,CAAA;AA4E1B,wBAAgB,SAAS,CAAC,KAAK,EAAE,EAC/B,OAAO,EACP,IAAI,EACJ,OAAe,EACf,YAAgB,EAChB,YAAmC,EACnC,KAAK,EACL,QAAQ,EACR,KAAa,EACb,OAAuB,EACvB,kBAA0B,EAC1B,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,OAAO,EACP,SAAS,EACV,EAAE,cAAc,CAAC,KAAK,CAAC,+BA+RvB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/data-table/index.tsx"],"names":[],"mappings":"AAsCA,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,UAAU,EAEf,KAAK,OAAO,EACZ,KAAK,iBAAiB,EAEvB,MAAM,uBAAuB,CAAA;AAc9B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAEjE;;;;GAIG;AACH,OAAO,QAAQ,uBAAuB,CAAC;IAIrC,UAAU,UAAU,CAAC,KAAK,SAAS,OAAO,EAAE,MAAM;QAChD,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB;CACF;AAED;;;;;;;;GAQG;AACH,KAAK,iBAAiB,CAAC,KAAK,IACxB;IACE,kBAAkB,CAAC,EAAE,KAAK,CAAA;IAC1B,YAAY,CAAC,EAAE,KAAK,CAAA;IACpB,oBAAoB,CAAC,EAAE,KAAK,CAAA;IAC5B,oBAAoB,CAAC,EAAE,KAAK,CAAA;CAC7B,GACD;IACE,kBAAkB,EAAE,IAAI,CAAA;IACxB,kFAAkF;IAClF,YAAY,EAAE,iBAAiB,CAAA;IAC/B,4DAA4D;IAC5D,oBAAoB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACnD;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAA;CAC9C,CAAA;AAEL,KAAK,kBAAkB,CAAC,KAAK,IAAI;IAC/B,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAA;IACpC,IAAI,EAAE,KAAK,EAAE,CAAA;IACb,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAChD;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;IACnC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IACpC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,kBAAkB,CAAC,KAAK,CAAC,GAC3D,iBAAiB,CAAC,KAAK,CAAC,CAAA;AA4E1B,wBAAgB,SAAS,CAAC,KAAK,EAAE,EAC/B,OAAO,EACP,IAAI,EACJ,OAAe,EACf,YAAgB,EAChB,YAAmC,EACnC,KAAK,EACL,QAAQ,EACR,KAAa,EACb,OAAuB,EACvB,kBAA0B,EAC1B,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,OAAO,EACP,SAAS,EACT,aAAa,EACb,MAAM,EACP,EAAE,cAAc,CAAC,KAAK,CAAC,+BAiSvB"}
@@ -10,6 +10,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  * - empty → EmptyState (data resolved, zero rows)
11
11
  * - data → semantic table rows; cells own any links/actions
12
12
  *
13
+ * Column heads speak the kit's LABEL_VOICE_CLASS; `headClassName` overrides it
14
+ * per table. An optional `footer` node renders in a `tfoot` for footed totals.
15
+ *
13
16
  * Columns are standard TanStack `ColumnDef<T>`; cells receive the row's
14
17
  * `original` value, so screens compose money / date / status cells directly in
15
18
  * their column `cell` renderers.
@@ -34,8 +37,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
34
37
  */
35
38
  import { useEffect, useMemo, useRef, useState } from 'react';
36
39
  import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
37
- import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../../components/ui/table/index.js';
40
+ import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from '../../components/ui/table/index.js';
38
41
  import { Skeleton } from '../../components/ui/skeleton/index.js';
42
+ import { LABEL_VOICE_CLASS } from '../../lib/typography.js';
39
43
  import { cn } from '../../lib/utils.js';
40
44
  import { EmptyState } from '../empty-state/index.js';
41
45
  const SELECTION_COLUMN_ID = '__select__';
@@ -75,7 +79,7 @@ function createSelectionColumn(getLabel) {
75
79
  cell: ({ row }) => _jsx(RowSelectionCheckbox, { row: row, getLabel: getLabel })
76
80
  };
77
81
  }
78
- export function DataTable({ columns, data, loading = false, skeletonRows = 8, loadingLabel = 'Loading table rows', empty, getRowId, flush = false, density = 'comfortable', enableRowSelection = false, rowSelection, onRowSelectionChange, getRowSelectionLabel, onRowActivate, rowHref, className }) {
82
+ export function DataTable({ columns, data, loading = false, skeletonRows = 8, loadingLabel = 'Loading table rows', empty, getRowId, flush = false, density = 'comfortable', enableRowSelection = false, rowSelection, onRowSelectionChange, getRowSelectionLabel, onRowActivate, rowHref, className, headClassName, footer }) {
79
83
  const tableColumns = useMemo(() => enableRowSelection
80
84
  ? [createSelectionColumn(getRowSelectionLabel), ...columns]
81
85
  : columns, [columns, enableRowSelection, getRowSelectionLabel]);
@@ -213,7 +217,7 @@ export function DataTable({ columns, data, loading = false, skeletonRows = 8, lo
213
217
  ? 'No rows'
214
218
  : `${rowCount} rows` }), _jsxs(Table, { "aria-busy": loading ? 'true' : undefined, children: [_jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => (_jsx(TableRow, { className: "hover:bg-transparent", children: headerGroup.headers.map((header) => {
215
219
  const numeric = header.column.columnDef.meta?.numeric;
216
- return (_jsx(TableHead, { align: numeric ? 'right' : undefined, className: cn('tracking-wide uppercase', headDensityClass, header.column.id === SELECTION_COLUMN_ID && 'w-10'), children: header.isPlaceholder
220
+ return (_jsx(TableHead, { align: numeric ? 'right' : undefined, className: cn(LABEL_VOICE_CLASS, headDensityClass, header.column.id === SELECTION_COLUMN_ID && 'w-10', headClassName), children: header.isPlaceholder
217
221
  ? null
218
222
  : flexRender(header.column.columnDef.header, header.getContext()) }, header.id));
219
223
  }) }, headerGroup.id))) }), _jsx(TableBody, { children: loading ? (Array.from({ length: skeletonRows }).map((_, rowIndex) => (_jsx(TableRow, { className: "hover:bg-transparent", children: Array.from({ length: colCount }).map((__, cellIndex) => (_jsx(TableCell, { className: cellDensityClass, children: _jsx(Skeleton, { className: "h-4 w-full max-w-[160px]" }) }, `skeleton-${rowIndex}-${cellIndex}`))) }, `skeleton-${rowIndex}`)))) : rowCount === 0 ? (_jsx(TableRow, { className: "hover:bg-transparent", children: _jsx(TableCell, { colSpan: colCount, className: "p-0", children: _jsx(EmptyState, { title: empty?.title ?? 'Nothing here yet', description: empty?.description, icon: empty?.icon, action: empty?.action,
@@ -238,5 +242,5 @@ export function DataTable({ columns, data, loading = false, skeletonRows = 8, lo
238
242
  ? 'selected'
239
243
  : undefined, children: row.getVisibleCells().map((cell) => (_jsx(TableCell, { className: cn(cell.column.columnDef.meta?.numeric && NUMERIC_CELL_CLASS, cellDensityClass, cell.column.id === SELECTION_COLUMN_ID && 'w-10'), onClick: cell.column.id === SELECTION_COLUMN_ID
240
244
  ? stopPropagation
241
- : undefined, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }, row.id)))) })] })] }));
245
+ : undefined, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }, row.id)))) }), footer ? _jsx(TableFooter, { children: footer }) : null] })] }));
242
246
  }
@@ -27,6 +27,12 @@ export type SearchInputProps = {
27
27
  disabled?: boolean;
28
28
  className?: string;
29
29
  id?: string;
30
+ /**
31
+ * Key events on the field, passed straight through. The component adds no
32
+ * Escape behaviour of its own: Escape-to-clear is a consumer gesture (some
33
+ * filter rows clear the field, others close a popover), so it owns it.
34
+ */
35
+ onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
30
36
  };
31
- export declare function SearchInput({ value, onValueChange, debounceMs, placeholder, 'aria-label': ariaLabel, clearLabel, disabled, className, id }: SearchInputProps): React.JSX.Element;
37
+ export declare function SearchInput({ value, onValueChange, debounceMs, placeholder, 'aria-label': ariaLabel, clearLabel, disabled, className, id, onKeyDown }: SearchInputProps): React.JSX.Element;
32
38
  //# sourceMappingURL=index.d.ts.map
@@ -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,qBAsGlB"}
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;IACX;;;;OAIG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,CAAA;CACzD,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,EACF,SAAS,EACV,EAAE,gBAAgB,qBAuGlB"}
@@ -23,7 +23,7 @@ import { cn } from '../../lib/utils.js';
23
23
  * string: any string sentinel is a value a parent could legitimately pass.
24
24
  */
25
25
  const NO_PENDING_ECHO = Symbol('no pending echo');
26
- export function SearchInput({ value, onValueChange, debounceMs = 250, placeholder = 'Search…', 'aria-label': ariaLabel, clearLabel = 'Clear search', disabled = false, className, id }) {
26
+ export function SearchInput({ value, onValueChange, debounceMs = 250, placeholder = 'Search…', 'aria-label': ariaLabel, clearLabel = 'Clear search', disabled = false, className, id, onKeyDown }) {
27
27
  // Local draft keeps typing instant; the controlled `value` is the source of
28
28
  // truth between edits. When the parent changes `value` out of band (reset,
29
29
  // programmatic set), the draft follows.
@@ -79,7 +79,7 @@ export function SearchInput({ value, onValueChange, debounceMs = 250, placeholde
79
79
  onValueChange('');
80
80
  };
81
81
  const hasValue = draft.length > 0;
82
- return (_jsx("div", { className: cn('relative w-full sm:w-64', className), children: _jsx(Input, { id: id, type: "search", role: "searchbox", value: draft, onChange: handleChange, placeholder: placeholder, "aria-label": ariaLabel ?? placeholder ?? 'Search', disabled: disabled,
82
+ return (_jsx("div", { className: cn('relative w-full sm:w-64', className), children: _jsx(Input, { id: id, type: "search", role: "searchbox", value: draft, onChange: handleChange, onKeyDown: onKeyDown, placeholder: placeholder, "aria-label": ariaLabel ?? placeholder ?? 'Search', disabled: disabled,
83
83
  // The native search clear glyph would duplicate our button.
84
84
  className: "[&::-webkit-search-cancel-button]:appearance-none", startAdornment: _jsx(InputAdornment, { position: "start", children: _jsx(Search, { "aria-hidden": true }) }), endAdornment: hasValue ? (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { type: "button", variant: "plain", size: "small", "aria-label": clearLabel, disabled: disabled, onClick: handleClear, className: "text-muted-foreground hover:text-foreground", children: _jsx(X, { className: "size-4", "aria-hidden": true }) }) })) : undefined }) }));
85
85
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAA;AAG5C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAA;AA8B5C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
@@ -1,5 +1,31 @@
1
1
  import { clsx } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
2
+ import { extendTailwindMerge } from 'tailwind-merge';
3
+ /**
4
+ * The kit's button variants are component classes in `@layer components`, not
5
+ * Tailwind utilities, so stock tailwind-merge has no group for them: it kept
6
+ * `button-primary button-destructive` together and let stylesheet source order
7
+ * pick the winner. Declaring the group makes the last one win, like every other
8
+ * conflict `cn` resolves.
9
+ *
10
+ * Variant classes only. `button-base`, `button-disabled`, `button-read-only`
11
+ * and `button-small` compose with a variant instead of conflicting with it, so
12
+ * they stay out of the group and are never merged away.
13
+ */
14
+ const twMerge = extendTailwindMerge({
15
+ extend: {
16
+ classGroups: {
17
+ 'sindarian-button-variant': [
18
+ 'button-plain',
19
+ 'button-primary',
20
+ 'button-secondary',
21
+ 'button-tertiary',
22
+ 'button-outline',
23
+ 'button-link',
24
+ 'button-destructive'
25
+ ]
26
+ }
27
+ }
28
+ });
3
29
  export function cn(...inputs) {
4
30
  return twMerge(clsx(inputs));
5
31
  }
@@ -34,5 +34,13 @@ export interface ThemeProviderProps {
34
34
  export declare function ThemeProvider({ children, storageKey, defaultTheme }: ThemeProviderProps): React.JSX.Element;
35
35
  /** Reads the theme context. Throws if used outside a ThemeProvider. */
36
36
  export declare function useTheme(): ThemeContextValue;
37
+ /**
38
+ * Reads the theme context without requiring a provider — `undefined` when
39
+ * there is none. For library components that should follow the theme when one
40
+ * exists but must not force every consumer to mount a ThemeProvider (Toaster).
41
+ * Not re-exported from the package barrel: consumers use `useTheme`, whose
42
+ * throw is the intended signal that the provider is missing.
43
+ */
44
+ export declare function useOptionalTheme(): ThemeContextValue | undefined;
37
45
  export {};
38
46
  //# sourceMappingURL=theme-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../../src/theme/theme-provider.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;AAgBzD,KAAK,iBAAiB,GAAG;IACvB,oEAAoE;IACpE,KAAK,EAAE,eAAe,CAAA;IACtB,yEAAyE;IACzE,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAA;IACzC,mDAAmD;IACnD,aAAa,EAAE,OAAO,GAAG,MAAM,CAAA;CAChC,CAAA;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iEAAiE;IACjE,YAAY,CAAC,EAAE,eAAe,CAAA;CAC/B;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,UAA8B,EAC9B,YAAuB,EACxB,EAAE,kBAAkB,qBAwFpB;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
1
+ {"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../../src/theme/theme-provider.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;AAgBzD,KAAK,iBAAiB,GAAG;IACvB,oEAAoE;IACpE,KAAK,EAAE,eAAe,CAAA;IACtB,yEAAyE;IACzE,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAA;IACzC,mDAAmD;IACnD,aAAa,EAAE,OAAO,GAAG,MAAM,CAAA;CAChC,CAAA;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iEAAiE;IACjE,YAAY,CAAC,EAAE,eAAe,CAAA;CAC/B;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,UAA8B,EAC9B,YAAuB,EACxB,EAAE,kBAAkB,qBAwFpB;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,GAAG,SAAS,CAEhE"}
@@ -110,3 +110,13 @@ export function useTheme() {
110
110
  }
111
111
  return context;
112
112
  }
113
+ /**
114
+ * Reads the theme context without requiring a provider — `undefined` when
115
+ * there is none. For library components that should follow the theme when one
116
+ * exists but must not force every consumer to mount a ThemeProvider (Toaster).
117
+ * Not re-exported from the package barrel: consumers use `useTheme`, whose
118
+ * throw is the intended signal that the provider is missing.
119
+ */
120
+ export function useOptionalTheme() {
121
+ return React.useContext(ThemeContext) ?? undefined;
122
+ }