@alfadocs/ui-kit-debug 1.130.1 → 1.130.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 (179) hide show
  1. package/dist/_chunks/{actions-cell-renderer-DTaIQKp9.js → actions-cell-renderer-C-l_ppP6.js} +3 -3
  2. package/dist/_chunks/{actions-cell-renderer-DTaIQKp9.js.map → actions-cell-renderer-C-l_ppP6.js.map} +1 -1
  3. package/dist/_chunks/{alia-sidebar-BBxbMRmX.js → alia-sidebar-CK1zw_Bc.js} +2 -2
  4. package/dist/_chunks/{alia-sidebar-BBxbMRmX.js.map → alia-sidebar-CK1zw_Bc.js.map} +1 -1
  5. package/dist/_chunks/{anamnesis-summary-rows-CtcULkvc.js → anamnesis-summary-rows-CCNmkq55.js} +5 -5
  6. package/dist/_chunks/{anamnesis-summary-rows-CtcULkvc.js.map → anamnesis-summary-rows-CCNmkq55.js.map} +1 -1
  7. package/dist/_chunks/{appointment-card-vbUsDh70.js → appointment-card-OAOur8lH.js} +2 -2
  8. package/dist/_chunks/{appointment-card-vbUsDh70.js.map → appointment-card-OAOur8lH.js.map} +1 -1
  9. package/dist/_chunks/{appointment-peek-DdUhqfEi.js → appointment-peek-DZa6xyUb.js} +2 -2
  10. package/dist/_chunks/{appointment-peek-DdUhqfEi.js.map → appointment-peek-DZa6xyUb.js.map} +1 -1
  11. package/dist/_chunks/{appointment-timeline-B5pfBl-b.js → appointment-timeline-DQePqpyH.js} +3 -3
  12. package/dist/_chunks/{appointment-timeline-B5pfBl-b.js.map → appointment-timeline-DQePqpyH.js.map} +1 -1
  13. package/dist/_chunks/{appointment-tray-BhiXetjs.js → appointment-tray-DSFqO5Rm.js} +2 -2
  14. package/dist/_chunks/{appointment-tray-BhiXetjs.js.map → appointment-tray-DSFqO5Rm.js.map} +1 -1
  15. package/dist/_chunks/{balance-badge-cell-BtFge7Y6.js → balance-badge-cell-DTiMdnCZ.js} +4 -4
  16. package/dist/_chunks/{balance-badge-cell-BtFge7Y6.js.map → balance-badge-cell-DTiMdnCZ.js.map} +1 -1
  17. package/dist/_chunks/body-pointer-lock-CsOEDm1I.js +15 -0
  18. package/dist/_chunks/body-pointer-lock-CsOEDm1I.js.map +1 -0
  19. package/dist/_chunks/{button-group-B2MJo0Se.js → button-group-DuQuuulC.js} +2 -2
  20. package/dist/_chunks/{button-group-B2MJo0Se.js.map → button-group-DuQuuulC.js.map} +1 -1
  21. package/dist/_chunks/{calculator-dialog-BGX5XQCM.js → calculator-dialog-Cg3GjaRf.js} +2 -2
  22. package/dist/_chunks/{calculator-dialog-BGX5XQCM.js.map → calculator-dialog-Cg3GjaRf.js.map} +1 -1
  23. package/dist/_chunks/{calendar-DzR-vdJ5.js → calendar-BIoOeBTT.js} +103 -103
  24. package/dist/_chunks/{calendar-DzR-vdJ5.js.map → calendar-BIoOeBTT.js.map} +1 -1
  25. package/dist/_chunks/{calendar-appointment-editor-dialog-CXch4Pmu.js → calendar-appointment-editor-dialog-WW6V1SGh.js} +15 -15
  26. package/dist/_chunks/{calendar-appointment-editor-dialog-CXch4Pmu.js.map → calendar-appointment-editor-dialog-WW6V1SGh.js.map} +1 -1
  27. package/dist/_chunks/{care-plan-card-CwgkImOD.js → care-plan-card-DKScH9Ss.js} +2 -2
  28. package/dist/_chunks/{care-plan-card-CwgkImOD.js.map → care-plan-card-DKScH9Ss.js.map} +1 -1
  29. package/dist/_chunks/{care-plan-entry-card-cdojypxu.js → care-plan-entry-card-AG1y3nyW.js} +2 -2
  30. package/dist/_chunks/{care-plan-entry-card-cdojypxu.js.map → care-plan-entry-card-AG1y3nyW.js.map} +1 -1
  31. package/dist/_chunks/{chart-Aue_2dMb.js → chart-D0EeFWst.js} +2 -2
  32. package/dist/_chunks/{chart-Aue_2dMb.js.map → chart-D0EeFWst.js.map} +1 -1
  33. package/dist/_chunks/{dashboard-grid-CaxgaEgI.js → dashboard-grid-2uVXEe9e.js} +2 -2
  34. package/dist/_chunks/{dashboard-grid-CaxgaEgI.js.map → dashboard-grid-2uVXEe9e.js.map} +1 -1
  35. package/dist/_chunks/{data-table-BCfkcPti.js → data-table-FTV3uRjX.js} +3 -3
  36. package/dist/_chunks/{data-table-BCfkcPti.js.map → data-table-FTV3uRjX.js.map} +1 -1
  37. package/dist/_chunks/{default-tabs-BnB6FUEW.js → default-tabs-BryvhiHv.js} +4 -4
  38. package/dist/_chunks/{default-tabs-BnB6FUEW.js.map → default-tabs-BryvhiHv.js.map} +1 -1
  39. package/dist/_chunks/{dialog-CIUn5oLb.js → dialog-CVTxyR0v.js} +48 -47
  40. package/dist/_chunks/dialog-CVTxyR0v.js.map +1 -0
  41. package/dist/_chunks/{document-preview-BWDTCEHI.js → document-preview-_kQ9QvZV.js} +2 -2
  42. package/dist/_chunks/{document-preview-BWDTCEHI.js.map → document-preview-_kQ9QvZV.js.map} +1 -1
  43. package/dist/_chunks/{dropdown-menu-Dw6sgQwJ.js → dropdown-menu-DBWaW4pq.js} +92 -88
  44. package/dist/_chunks/dropdown-menu-DBWaW4pq.js.map +1 -0
  45. package/dist/_chunks/{editable-currency-cell-renderer-BlK-8A7b.js → editable-currency-cell-renderer-CZMQ5xRT.js} +2 -2
  46. package/dist/_chunks/{editable-currency-cell-renderer-BlK-8A7b.js.map → editable-currency-cell-renderer-CZMQ5xRT.js.map} +1 -1
  47. package/dist/_chunks/{face-scheme-Bt07zQJU.js → face-scheme-D_Y1StPl.js} +3 -3
  48. package/dist/_chunks/{face-scheme-Bt07zQJU.js.map → face-scheme-D_Y1StPl.js.map} +1 -1
  49. package/dist/_chunks/{file-manager-Dpwv0qs-.js → file-manager-Bzr5NK1t.js} +5 -5
  50. package/dist/_chunks/{file-manager-Dpwv0qs-.js.map → file-manager-Bzr5NK1t.js.map} +1 -1
  51. package/dist/_chunks/{header-settings-ZGvYAuKF.js → header-settings-Cu-MKOsO.js} +2 -2
  52. package/dist/_chunks/{header-settings-ZGvYAuKF.js.map → header-settings-Cu-MKOsO.js.map} +1 -1
  53. package/dist/_chunks/{heatmap-Ds5DJBUL.js → heatmap-C5gJin_F.js} +3 -3
  54. package/dist/_chunks/{heatmap-Ds5DJBUL.js.map → heatmap-C5gJin_F.js.map} +1 -1
  55. package/dist/_chunks/{help-me-write-templates-C28E_rOt.js → help-me-write-templates-DO6vJeP4.js} +2 -2
  56. package/dist/_chunks/{help-me-write-templates-C28E_rOt.js.map → help-me-write-templates-DO6vJeP4.js.map} +1 -1
  57. package/dist/_chunks/{icon-button-group-BKtkVZ1W.js → icon-button-group-SmkdVCNx.js} +2 -2
  58. package/dist/_chunks/{icon-button-group-BKtkVZ1W.js.map → icon-button-group-SmkdVCNx.js.map} +1 -1
  59. package/dist/_chunks/{invoice-upload-list-tJY7W1g_.js → invoice-upload-list-868v1oDe.js} +3 -3
  60. package/dist/_chunks/{invoice-upload-list-tJY7W1g_.js.map → invoice-upload-list-868v1oDe.js.map} +1 -1
  61. package/dist/_chunks/{link-cell-renderer-CC9VHU68.js → link-cell-renderer-D3JLPURZ.js} +2 -2
  62. package/dist/_chunks/{link-cell-renderer-CC9VHU68.js.map → link-cell-renderer-D3JLPURZ.js.map} +1 -1
  63. package/dist/_chunks/{marketplace-app-shell-D_HA8CKx.js → marketplace-app-shell-dMmxI6MT.js} +4 -4
  64. package/dist/_chunks/{marketplace-app-shell-D_HA8CKx.js.map → marketplace-app-shell-dMmxI6MT.js.map} +1 -1
  65. package/dist/_chunks/{muscle-scheme-DdIdm8Gw.js → muscle-scheme-BGJD62op.js} +2 -2
  66. package/dist/_chunks/{muscle-scheme-DdIdm8Gw.js.map → muscle-scheme-BGJD62op.js.map} +1 -1
  67. package/dist/_chunks/{notes-panel-DIY7eNsq.js → notes-panel-Cm-_pCRJ.js} +3 -3
  68. package/dist/_chunks/{notes-panel-DIY7eNsq.js.map → notes-panel-Cm-_pCRJ.js.map} +1 -1
  69. package/dist/_chunks/{parts-tGzYz0uG.js → parts-BOnDDU3E.js} +2 -2
  70. package/dist/_chunks/{parts-tGzYz0uG.js.map → parts-BOnDDU3E.js.map} +1 -1
  71. package/dist/_chunks/{patient-search-OAwFgOW3.js → patient-search-DBvLFArV.js} +2 -2
  72. package/dist/_chunks/{patient-search-OAwFgOW3.js.map → patient-search-DBvLFArV.js.map} +1 -1
  73. package/dist/_chunks/{practice-results-BDnZtbDM.js → practice-results-M5A9-X9y.js} +3 -3
  74. package/dist/_chunks/{practice-results-BDnZtbDM.js.map → practice-results-M5A9-X9y.js.map} +1 -1
  75. package/dist/_chunks/{public-header.agent-Db4wm6_S.js → public-header.agent-DaeDfLfy.js} +2 -2
  76. package/dist/_chunks/{public-header.agent-Db4wm6_S.js.map → public-header.agent-DaeDfLfy.js.map} +1 -1
  77. package/dist/_chunks/{radiograph-panel.agent-B-r3BoqU.js → radiograph-panel.agent-88VjqlG7.js} +2 -2
  78. package/dist/_chunks/{radiograph-panel.agent-B-r3BoqU.js.map → radiograph-panel.agent-88VjqlG7.js.map} +1 -1
  79. package/dist/_chunks/{rich-text-editor-TnX0SYdq.js → rich-text-editor-DjHL1b3E.js} +3 -3
  80. package/dist/_chunks/{rich-text-editor-TnX0SYdq.js.map → rich-text-editor-DjHL1b3E.js.map} +1 -1
  81. package/dist/_chunks/{row-actions-Dpf9CrCP.js → row-actions-BF2-uizV.js} +3 -3
  82. package/dist/_chunks/{row-actions-Dpf9CrCP.js.map → row-actions-BF2-uizV.js.map} +1 -1
  83. package/dist/_chunks/{sheet-uZZXaO_S.js → sheet-BdhYeQQT.js} +84 -72
  84. package/dist/_chunks/sheet-BdhYeQQT.js.map +1 -0
  85. package/dist/_chunks/{signature-request-DW2PSp66.js → signature-request-4pGq3YBe.js} +3 -3
  86. package/dist/_chunks/{signature-request-DW2PSp66.js.map → signature-request-4pGq3YBe.js.map} +1 -1
  87. package/dist/_chunks/{tab-bar-CF8R38Og.js → tab-bar-CeC2QOwB.js} +2 -2
  88. package/dist/_chunks/{tab-bar-CF8R38Og.js.map → tab-bar-CeC2QOwB.js.map} +1 -1
  89. package/dist/_chunks/{tabs-P4qFmxk5.js → tabs-CRIDBLP7.js} +2 -2
  90. package/dist/_chunks/{tabs-P4qFmxk5.js.map → tabs-CRIDBLP7.js.map} +1 -1
  91. package/dist/_chunks/{task-editor-CVRrDqpe.js → task-editor-BL2hHxNz.js} +3 -3
  92. package/dist/_chunks/{task-editor-CVRrDqpe.js.map → task-editor-BL2hHxNz.js.map} +1 -1
  93. package/dist/_chunks/{tasks-panel-DBSm3WjK.js → tasks-panel-BE3zaayj.js} +2 -2
  94. package/dist/_chunks/{tasks-panel-DBSm3WjK.js.map → tasks-panel-BE3zaayj.js.map} +1 -1
  95. package/dist/_chunks/{theme-toggle-CeKl8f_f.js → theme-toggle-BQDFxvVS.js} +3 -3
  96. package/dist/_chunks/{theme-toggle-CeKl8f_f.js.map → theme-toggle-BQDFxvVS.js.map} +1 -1
  97. package/dist/_chunks/{token-insert-menu-BrK5NQIq.js → token-insert-menu-BLtfMTJd.js} +2 -2
  98. package/dist/_chunks/{token-insert-menu-BrK5NQIq.js.map → token-insert-menu-BLtfMTJd.js.map} +1 -1
  99. package/dist/_chunks/{toolbar-CC-Ls_eC.js → toolbar-BK6S9PhI.js} +2 -2
  100. package/dist/_chunks/{toolbar-CC-Ls_eC.js.map → toolbar-BK6S9PhI.js.map} +1 -1
  101. package/dist/_chunks/{tooth-scheme-DHRxV2sE.js → tooth-scheme-BtnFgugP.js} +2 -2
  102. package/dist/_chunks/{tooth-scheme-DHRxV2sE.js.map → tooth-scheme-BtnFgugP.js.map} +1 -1
  103. package/dist/_chunks/{use-appointment-details-read-BrykoTOR.js → use-appointment-details-read-_b7FRB1x.js} +4 -4
  104. package/dist/_chunks/{use-appointment-details-read-BrykoTOR.js.map → use-appointment-details-read-_b7FRB1x.js.map} +1 -1
  105. package/dist/_chunks/{verify-identity-types-D_LdByCp.js → verify-identity-types-CxtrBXsZ.js} +2 -2
  106. package/dist/_chunks/{verify-identity-types-D_LdByCp.js.map → verify-identity-types-CxtrBXsZ.js.map} +1 -1
  107. package/dist/_chunks/{widget-picker-DrxJjEkv.js → widget-picker-D3T7e8a4.js} +2 -2
  108. package/dist/_chunks/{widget-picker-DrxJjEkv.js.map → widget-picker-D3T7e8a4.js.map} +1 -1
  109. package/dist/_chunks/{workflow-map-DCjkRuS_.js → workflow-map-DaZFP9SJ.js} +2 -2
  110. package/dist/_chunks/{workflow-map-DCjkRuS_.js.map → workflow-map-DaZFP9SJ.js.map} +1 -1
  111. package/dist/_chunks/{workflow-status-D0avpoeS.js → workflow-status-D1WgGVTP.js} +2 -2
  112. package/dist/_chunks/{workflow-status-D0avpoeS.js.map → workflow-status-D1WgGVTP.js.map} +1 -1
  113. package/dist/_chunks/{workflow-webhook-action-Cae02r_4.js → workflow-webhook-action-BsGSh3h9.js} +2 -2
  114. package/dist/_chunks/{workflow-webhook-action-Cae02r_4.js.map → workflow-webhook-action-BsGSh3h9.js.map} +1 -1
  115. package/dist/agent-catalog.json +1 -1
  116. package/dist/browser-support.js +1 -1
  117. package/dist/components/_shared/body-pointer-lock.d.ts +2 -0
  118. package/dist/components/_shared/body-pointer-lock.d.ts.map +1 -0
  119. package/dist/components/appointment-card/index.js +2 -2
  120. package/dist/components/appointment-details-panel/index.js +1 -1
  121. package/dist/components/appointment-peek/index.js +1 -1
  122. package/dist/components/appointment-timeline/index.js +1 -1
  123. package/dist/components/bill-table/index.js +1 -1
  124. package/dist/components/button-group/index.js +1 -1
  125. package/dist/components/calculator-dialog/index.js +1 -1
  126. package/dist/components/calendar/calendar.d.ts.map +1 -1
  127. package/dist/components/calendar/index.js +1 -1
  128. package/dist/components/care-plan-card/index.js +1 -1
  129. package/dist/components/care-plan-entry-card/index.js +1 -1
  130. package/dist/components/chart/index.js +1 -1
  131. package/dist/components/dashboard-grid/index.js +1 -1
  132. package/dist/components/data-grid/index.js +1 -1
  133. package/dist/components/data-table/index.js +4 -4
  134. package/dist/components/dialog/dialog.d.ts.map +1 -1
  135. package/dist/components/dialog/index.js +1 -1
  136. package/dist/components/document-preview/index.js +1 -1
  137. package/dist/components/dropdown-menu/dropdown-menu.d.ts.map +1 -1
  138. package/dist/components/dropdown-menu/index.js +1 -1
  139. package/dist/components/face-scheme/index.js +1 -1
  140. package/dist/components/file-manager/index.js +1 -1
  141. package/dist/components/header-settings/index.js +1 -1
  142. package/dist/components/heatmap/index.js +1 -1
  143. package/dist/components/icon-button-group/index.js +1 -1
  144. package/dist/components/invoice-upload-list/index.js +1 -1
  145. package/dist/components/muscle-scheme/index.js +1 -1
  146. package/dist/components/notes-panel/index.js +1 -1
  147. package/dist/components/patient-search/index.js +1 -1
  148. package/dist/components/patient-table/index.js +1 -1
  149. package/dist/components/practice-results/index.js +1 -1
  150. package/dist/components/public-header/index.js +1 -1
  151. package/dist/components/radiograph-panel/index.js +1 -1
  152. package/dist/components/rich-text-editor/index.js +1 -1
  153. package/dist/components/row-actions/index.js +1 -1
  154. package/dist/components/sheet/index.js +1 -1
  155. package/dist/components/sheet/sheet.d.ts.map +1 -1
  156. package/dist/components/skeleton-scheme/index.js +1 -1
  157. package/dist/components/tab-bar/index.js +1 -1
  158. package/dist/components/tabs/index.js +1 -1
  159. package/dist/components/task-editor/index.js +1 -1
  160. package/dist/components/tasks-panel/index.js +1 -1
  161. package/dist/components/theme-toggle/index.js +1 -1
  162. package/dist/components/token-insert-menu/index.js +1 -1
  163. package/dist/components/tooth-scheme/index.js +1 -1
  164. package/dist/components/widget-picker/index.js +1 -1
  165. package/dist/components/workflow/index.js +1 -1
  166. package/dist/components/workflow-status/index.js +1 -1
  167. package/dist/index.js +54 -54
  168. package/dist/patterns/alia-assistant/index.js +1 -1
  169. package/dist/patterns/anamnesis/index.js +1 -1
  170. package/dist/patterns/calendar/index.js +1 -1
  171. package/dist/patterns/help-me-write-templates/index.js +1 -1
  172. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  173. package/dist/patterns/signature-request/index.js +1 -1
  174. package/dist/patterns/verify-identity/index.js +1 -1
  175. package/dist/patterns/workflow-webhook-action/index.js +1 -1
  176. package/package.json +1 -1
  177. package/dist/_chunks/dialog-CIUn5oLb.js.map +0 -1
  178. package/dist/_chunks/dropdown-menu-Dw6sgQwJ.js.map +0 -1
  179. package/dist/_chunks/sheet-uZZXaO_S.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"default-tabs-BnB6FUEW.js","sources":["../../node_modules/lucide-react/dist/esm/icons/hand-coins.mjs","../../src/components/bill-table/bill-table.agent.ts","../../src/components/bill-table/bill-table.variants.ts","../../src/components/bill-table/types.ts","../../src/components/bill-table/model.ts","../../src/components/bill-table/status-maps.ts","../../src/components/bill-table/cells.tsx","../../src/components/bill-table/columns.tsx","../../src/components/bill-table/handle.ts","../../src/components/bill-table/row-actions.ts","../../src/components/bill-table/bill-table.tsx","../../src/components/bill-table/default-tabs.ts"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17\", key: \"geh8rc\" }],\n [\n \"path\",\n {\n d: \"m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9\",\n key: \"1fto5m\"\n }\n ],\n [\"path\", { d: \"m2 16 6 6\", key: \"1pfhp9\" }],\n [\"circle\", { cx: \"16\", cy: \"9\", r: \"2.9\", key: \"1n0dlu\" }],\n [\"circle\", { cx: \"6\", cy: \"5\", r: \"3\", key: \"151irh\" }]\n];\nconst HandCoins = createLucideIcon(\"hand-coins\", __iconNode);\n\nexport { __iconNode, HandCoins as default };\n//# sourceMappingURL=hand-coins.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter: BillTable. */\n/* */\n/* Works against the curated `BillTableHandle`: ids and kit shapes only, */\n/* never the DataGrid handle, a TanStack object, a row object or a DOM */\n/* node. It is the table's only agent surface: the DataGrid inside */\n/* registers none (`registerAgent={false}`). */\n/* */\n/* Safety: query actions stay `read` + `openWorld` (they change the view; */\n/* the host fetches). Column choices persist under `gridId` (`write`); */\n/* resetting them deletes the saved state (`destructive`). Downloading a */\n/* bill hands a document with patient data to the user's device (`phi`). */\n/* Opening a bill, or the warehouse dialog, changes nothing by itself */\n/* (`read` + `openWorld`). Edit, record payment, write off and delete are */\n/* UI-only in this phase. Agent state carries no PHI: a counterparty name */\n/* is read for companies only, a host's disabled text reads as `host`, */\n/* the quick search always reads `{ masked: true }`, and under privacy */\n/* mode the filters that can point at a person read `{ masked: true }`. */\n/* */\n/* Literal enums, not imports: the catalog build loads this file in plain */\n/* Node, where only type imports are erased (as data-grid.agent.ts). */\n/* A test should keep the literals equal to the BILL_* constants. */\n/* See src/docs/26-agent-readiness.mdx. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type {\n BillTableColumnId,\n BillTableFilterModel,\n BillTableHandle,\n BillTableSortEntry,\n} from './types';\n\nconst SORT_COLUMNS = ['number', 'date', 'counterparty', 'amount'] as const;\nconst DIRECTIONS = ['incoming', 'outgoing'] as const;\nconst PAYMENT = [\n 'paid',\n 'partiallyPaid',\n 'unpaid',\n 'overdue',\n 'writtenOff',\n 'noPaymentDue',\n] as const;\n/** Every SDI status but `notApplicable`, which is not a filter value. */\nconst SDI = [\n 'notSent',\n 'sending',\n 'pending',\n 'accepted',\n 'delivered',\n 'notDelivered',\n 'rejected',\n 'received',\n] as const;\nconst WAREHOUSE = ['notLoaded', 'toReview', 'loaded'] as const;\nconst TYPES = ['full', 'partial', 'credit', 'proforma', 'other'] as const;\nconst PAGE_SIZES = [25, 50, 100] as const;\nconst HIDEABLE_COLUMNS = [\n 'date',\n 'direction',\n 'counterparty',\n 'amount',\n 'paymentStatus',\n 'sdiStatus',\n 'warehouseStatus',\n] as const;\n\n/**\n * Filter keys whose values cannot point at a person: the column keys and\n * the platform's typed host keys. Under privacy mode every other key reads\n * `{ masked: true }`: `relation` and `personalAssistant` (they hold the id\n * of a patient, a company, an operator or a practice member) and any extra\n * key a host adds later, whose value the kit cannot vouch for.\n */\nconst NON_PERSONAL_FILTER_KEYS: ReadonlySet<string> = new Set([\n 'date',\n 'direction',\n 'amount',\n 'paymentStatus',\n 'sdiStatus',\n 'warehouseStatus',\n 'datePreset',\n 'type',\n 'number',\n 'prefix',\n 'withInsuranceNet',\n 'withVat',\n 'withTaxAtSource',\n 'withWelfareFundContribution',\n 'withUnpaidAmount',\n 'writtenOff',\n 'taxOfficeNotification',\n 'receivedFromSdi',\n 'sentToSdi',\n 'selfBill',\n 'liabilityDate',\n 'sdiEntryDate',\n 'relationType',\n 'insurance',\n]);\n\n/** What an agent sees in place of a value privacy mode hides. */\nconst MASKED = { masked: true } as const;\n\n/** Error codes the adapter throws (message prefix). The handle throws\n * `UNKNOWN_ROW`, `ACTION_UNAVAILABLE` and `ACTION_DISABLED` too. */\ntype BillTableAgentErrorCode =\n | 'UNKNOWN_ROW'\n | 'SORT_DISABLED'\n | 'COLUMN_MASKED'\n | 'UNKNOWN_FILTER'\n | 'UNKNOWN_COLUMN'\n | 'NOT_HIDEABLE'\n | 'SELECTION_DISABLED';\n\nfunction refuse(code: BillTableAgentErrorCode, detail: string): never {\n throw new Error(`${code}: ${detail}`);\n}\n\nfunction knownRow(handle: BillTableHandle, id: string): void {\n if (!handle.getRowIds().includes(id)) {\n refuse('UNKNOWN_ROW', `no bill \"${id}\" on the current page.`);\n }\n}\n\nconst set = (values: readonly string[]) => ({\n type: 'object',\n properties: {\n type: { const: 'set' },\n values: { type: 'array', items: { enum: [...values] } },\n },\n required: ['type', 'values'],\n additionalProperties: false,\n});\n\nconst dateRange = {\n type: 'object',\n properties: {\n type: { const: 'inRange' },\n dateFrom: { type: ['string', 'null'], format: 'date' },\n dateTo: { type: ['string', 'null'], format: 'date' },\n },\n required: ['type', 'dateFrom', 'dateTo'],\n additionalProperties: false,\n};\n\nconst yesNo = {\n type: 'boolean',\n description: 'true = yes, false = no; leave the key out for either.',\n};\n\n/** Every key `apply_filter` accepts. Unknown keys are refused, so a typo\n * never becomes a silent host key. `relation` and `personalAssistant` are\n * not offered: they take entity ids an agent has no safe way to learn. */\nconst FILTER_SCHEMA = {\n type: 'object',\n additionalProperties: false,\n properties: {\n date: dateRange,\n direction: set(DIRECTIONS),\n amount: {\n type: 'object',\n description: 'Amount in major units (12.50), as on the platform form.',\n properties: {\n type: {\n enum: ['inRange', 'greaterThanOrEqual', 'lessThanOrEqual', 'equals'],\n },\n filter: { type: 'number' },\n filterTo: { type: 'number' },\n },\n required: ['type'],\n additionalProperties: false,\n },\n paymentStatus: set(PAYMENT),\n sdiStatus: set(SDI),\n warehouseStatus: set(WAREHOUSE),\n datePreset: { enum: ['today', 'thisMonth', 'thisYear'] },\n type: set(TYPES),\n number: { type: 'string' },\n prefix: { type: 'string' },\n withInsuranceNet: yesNo,\n withVat: yesNo,\n withTaxAtSource: yesNo,\n withWelfareFundContribution: yesNo,\n withUnpaidAmount: yesNo,\n writtenOff: yesNo,\n taxOfficeNotification: yesNo,\n receivedFromSdi: yesNo,\n sentToSdi: yesNo,\n selfBill: yesNo,\n liabilityDate: dateRange,\n sdiEntryDate: dateRange,\n relationType: { enum: ['patient', 'company', 'operator'] },\n insurance: { type: 'string' },\n },\n} as const;\n\nconst FILTER_KEYS: ReadonlySet<string> = new Set(\n Object.keys(FILTER_SCHEMA.properties),\n);\n\n/** The filter model as an agent may read it (see NON_PERSONAL_FILTER_KEYS). */\nfunction readFilter(handle: BillTableHandle): Record<string, unknown> {\n const model: Record<string, unknown> = { ...handle.getFilter() };\n if (!handle.getFeatures().privacyMode) {\n return model;\n }\n const view: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(model)) {\n view[key] = NON_PERSONAL_FILTER_KEYS.has(key) ? value : MASKED;\n }\n return view;\n}\n\nconst ROW_ID_SCHEMA = {\n type: 'object',\n properties: { id: { type: 'string', description: 'A bill id (rows).' } },\n required: ['id'],\n additionalProperties: false,\n};\n\nexport const billTableAgent: AgentAdapter<BillTableHandle> = {\n id: 'bill-table',\n capabilities: [\n 'select_multiple',\n 'range_pick',\n 'filter',\n 'sort',\n 'paginate',\n 'view_change',\n 'scroll',\n // open_bill moves to the bill page (26 section 4: `navigate`).\n 'navigate',\n // load_into_warehouse opens the HTP-7311 dialog (`open`: a Dialog).\n // download_bill fits no capability exactly (a file request): the\n // agent-readiness-auditor rules on it.\n 'open',\n ],\n state: {\n features: {\n type: '{ selectable, privacyMode, showWarehouseStatus, sortableColumns, status }',\n descriptionKey: 'ui.agent.billTable.state.features',\n description:\n 'What this bill list can do now: selection, privacy mode, the warehouse column, sortable columns and loading status.',\n read: (handle) => handle.getFeatures(),\n },\n rows: {\n type: 'Array<{ id, number, type, date, direction, counterpartyKind, counterpartyName?, amountMinor, paymentStatus, sdiStatus, warehouseStatus, actions }>',\n descriptionKey: 'ui.agent.billTable.state.rows',\n description:\n 'The bills on the current page, amounts in hundredths. A counterparty name is given only for companies; patients and other people are never named.',\n read: (handle) => handle.getRowSummaries(),\n },\n selection: {\n type: 'string[]',\n descriptionKey: 'ui.agent.billTable.state.selection',\n description: 'Ids of the selected bills, on every page.',\n read: (handle) => handle.getSelection(),\n },\n sort: {\n type: 'Array<{ colId, sort }>',\n descriptionKey: 'ui.agent.billTable.state.sort',\n description:\n 'The active sort, as the server receives it. A counterparty sort is left out while privacy mode is on.',\n read: (handle) => handle.getQuery().sorting,\n },\n filter: {\n type: 'object',\n descriptionKey: 'ui.agent.billTable.state.filter',\n description:\n 'The active filters. Under privacy mode, filters that can point at a person read { masked: true }.',\n read: (handle) => readFilter(handle),\n },\n quickFilter: {\n type: \"'' | { masked: true }\",\n descriptionKey: 'ui.agent.billTable.state.quickFilter',\n description:\n 'Empty when no quick search is set; otherwise { masked: true }, since the text may be a name. Set it with set_quick_filter.',\n // Masked in both modes: a person's name typed here must not reach\n // agent state, privacy mode or not.\n read: (handle) => (handle.getQuickFilter() === '' ? '' : MASKED),\n },\n currentPage: {\n type: 'number',\n descriptionKey: 'ui.agent.billTable.state.currentPage',\n description: 'Zero-based page index.',\n read: (handle) => handle.getQuery().pagination.pageIndex,\n },\n pageSize: {\n type: 'number',\n descriptionKey: 'ui.agent.billTable.state.pageSize',\n description: 'Bills per page.',\n read: (handle) => handle.getQuery().pagination.pageSize,\n },\n pageCount: {\n type: 'number',\n descriptionKey: 'ui.agent.billTable.state.pageCount',\n description: 'Number of pages; -1 when the total is unknown.',\n read: (handle) => handle.getPageCount(),\n },\n rowCount: {\n type: 'number',\n descriptionKey: 'ui.agent.billTable.state.rowCount',\n description:\n 'Bills matching the filters, on every page; -1 when unknown.',\n read: (handle) => handle.getRowCount(),\n },\n columns: {\n type: 'Array<{ id, label, visible, canHide, sortable, masked }>',\n descriptionKey: 'ui.agent.billTable.state.columns',\n description: 'The columns, in display order.',\n read: (handle) => handle.getColumns(),\n },\n },\n actions: {\n select_rows: {\n safety: 'read',\n argsType: '{ ids: string[] }',\n argsSchema: {\n type: 'object',\n properties: { ids: { type: 'array', items: { type: 'string' } } },\n required: ['ids'],\n additionalProperties: false,\n },\n returns: 'string[]',\n idempotent: true,\n errors: ['SELECTION_DISABLED: the list is read-only.'],\n descriptionKey: 'ui.agent.billTable.actions.selectRows',\n description:\n 'Replace the selection with the given bill ids. Changing a filter or the search clears it.',\n invoke: (handle, args: { ids: string[] }) => {\n if (!handle.getFeatures().selectable) {\n refuse('SELECTION_DISABLED', 'this list has no selection.');\n }\n handle.setSelection(args.ids);\n return handle.getSelection();\n },\n },\n select_range: {\n safety: 'read',\n argsType: '{ fromId: string, toId: string }',\n argsSchema: {\n type: 'object',\n properties: { fromId: { type: 'string' }, toId: { type: 'string' } },\n required: ['fromId', 'toId'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: [\n 'SELECTION_DISABLED: the list is read-only.',\n 'UNKNOWN_ROW: fromId or toId is not on the current page.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.selectRange',\n description:\n 'Select every bill from fromId to toId on the current page, inclusive.',\n invoke: (handle, args: { fromId: string; toId: string }) => {\n if (!handle.getFeatures().selectable) {\n refuse('SELECTION_DISABLED', 'this list has no selection.');\n }\n knownRow(handle, args.fromId);\n knownRow(handle, args.toId);\n handle.selectRange(args.fromId, args.toId);\n },\n },\n clear_selection: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.clearSelection',\n description: 'Clear the selection on every page.',\n invoke: (handle) => handle.clearSelection(),\n },\n sort_by: {\n safety: 'read',\n openWorld: true,\n argsType:\n '{ colId: \"number\" | \"date\" | \"counterparty\" | \"amount\", sort: \"asc\" | \"desc\" }',\n argsSchema: {\n type: 'object',\n properties: {\n colId: { enum: [...SORT_COLUMNS] },\n sort: { enum: ['asc', 'desc'] },\n },\n required: ['colId', 'sort'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: [\n 'SORT_DISABLED: the server cannot sort this column (features.sortableColumns).',\n 'COLUMN_MASKED: counterparty cannot be sorted while privacy mode is on.',\n ],\n examples: [{ args: { colId: 'amount', sort: 'desc' } }],\n descriptionKey: 'ui.agent.billTable.actions.sortBy',\n description:\n 'Sort the bills by one column. The host fetches the first page again.',\n invoke: (handle, args: BillTableSortEntry) => {\n const features = handle.getFeatures();\n if (!features.sortableColumns.includes(args.colId)) {\n refuse('SORT_DISABLED', `column \"${args.colId}\" does not sort.`);\n }\n const column = handle.getColumns().find((c) => c.id === args.colId);\n if (column?.masked) {\n refuse('COLUMN_MASKED', `\"${args.colId}\" is hidden by privacy mode.`);\n }\n handle.setSort([{ colId: args.colId, sort: args.sort }]);\n },\n },\n apply_filter: {\n safety: 'read',\n openWorld: true,\n argsType: '{ model: BillTableFilterModel }',\n argsSchema: {\n type: 'object',\n properties: { model: FILTER_SCHEMA },\n required: ['model'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: [\n 'UNKNOWN_FILTER: a key is not a bill filter.',\n 'Changing filters clears the selection.',\n ],\n examples: [\n {\n args: {\n model: {\n sdiStatus: { type: 'set', values: ['received'] },\n warehouseStatus: { type: 'set', values: ['toReview'] },\n },\n },\n note: 'Bills from SDI that need a warehouse review.',\n },\n ],\n descriptionKey: 'ui.agent.billTable.actions.applyFilter',\n description:\n 'Replace the filters. The host fetches the first page again.',\n invoke: (handle, args: { model: BillTableFilterModel }) => {\n for (const key of Object.keys(args.model)) {\n if (!FILTER_KEYS.has(key)) {\n refuse('UNKNOWN_FILTER', `\"${key}\" is not a bill filter.`);\n }\n }\n handle.setFilter(args.model);\n },\n },\n set_quick_filter: {\n safety: 'read',\n openWorld: true,\n argsType: '{ text: string }',\n argsSchema: {\n type: 'object',\n properties: { text: { type: 'string' } },\n required: ['text'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: ['Changing the search clears the selection.'],\n descriptionKey: 'ui.agent.billTable.actions.setQuickFilter',\n description:\n 'Search by bill number, and by counterparty name unless privacy mode is on.',\n invoke: (handle, args: { text: string }) =>\n handle.setQuickFilter(args.text),\n },\n clear_filters: {\n safety: 'read',\n openWorld: true,\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.clearFilters',\n description: 'Remove every filter and the quick search.',\n invoke: (handle) => handle.clearFilters(),\n },\n go_to_page: {\n safety: 'read',\n openWorld: true,\n argsType: '{ pageIndex: number }',\n argsSchema: {\n type: 'object',\n properties: { pageIndex: { type: 'integer', minimum: 0 } },\n required: ['pageIndex'],\n additionalProperties: false,\n },\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.goToPage',\n description: 'Go to a zero-based page.',\n invoke: (handle, args: { pageIndex: number }) =>\n handle.goToPage(args.pageIndex),\n },\n set_page_size: {\n safety: 'read',\n openWorld: true,\n argsType: '{ size: 25 | 50 | 100 }',\n argsSchema: {\n type: 'object',\n properties: { size: { enum: [...PAGE_SIZES] } },\n required: ['size'],\n additionalProperties: false,\n },\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.setPageSize',\n description: 'Change how many bills show per page.',\n invoke: (handle, args: { size: number }) => handle.setPageSize(args.size),\n },\n scroll_to_row: {\n safety: 'read',\n argsType: '{ id: string }',\n argsSchema: ROW_ID_SCHEMA,\n idempotent: true,\n errors: ['UNKNOWN_ROW: the id is not on the current page.'],\n descriptionKey: 'ui.agent.billTable.actions.scrollToRow',\n description: 'Scroll a bill on the current page into view.',\n invoke: (handle, args: { id: string }) => {\n knownRow(handle, args.id);\n handle.scrollToRow(args.id);\n },\n },\n set_column_visibility: {\n safety: 'write',\n argsType: '{ id: string, visible: boolean }',\n argsSchema: {\n type: 'object',\n properties: {\n id: { enum: [...HIDEABLE_COLUMNS] },\n visible: { type: 'boolean' },\n },\n required: ['id', 'visible'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: [\n 'UNKNOWN_COLUMN: the column is not in this list (warehouseStatus needs the warehouse module).',\n 'NOT_HIDEABLE: number and actions always show.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.setColumnVisibility',\n description: 'Show or hide a column. The choice is saved for this list.',\n invoke: (handle, args: { id: BillTableColumnId; visible: boolean }) => {\n const column = handle.getColumns().find((c) => c.id === args.id);\n if (!column) refuse('UNKNOWN_COLUMN', `no column \"${args.id}\".`);\n if (!column.canHide) {\n refuse('NOT_HIDEABLE', `\"${args.id}\" always shows.`);\n }\n handle.setColumnVisible(args.id, args.visible);\n },\n },\n reset_columns: {\n safety: 'destructive',\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.resetColumns',\n description:\n 'Put every column back to its default and delete the column choices saved for this list.',\n invoke: (handle) => handle.resetColumns(),\n },\n get_row_actions: {\n safety: 'read',\n argsType: '{ id: string }',\n argsSchema: ROW_ID_SCHEMA,\n returns: 'Record<action, \"enabled\" | { disabled: reason }>',\n idempotent: true,\n errors: ['UNKNOWN_ROW: the id is not on the current page.'],\n descriptionKey: 'ui.agent.billTable.actions.getRowActions',\n description:\n 'Which actions one bill offers now, and why a disabled one is disabled.',\n // The agent-safe projection (reason codes, a host's text as `host`),\n // never `handle.getRowActions`, which carries the host's text.\n invoke: (handle, args: { id: string }) => {\n knownRow(handle, args.id);\n return (\n handle.getRowSummaries().find((row) => row.id === args.id)?.actions ??\n {}\n );\n },\n },\n open_bill: {\n safety: 'read',\n openWorld: true,\n argsType: '{ id: string }',\n argsSchema: ROW_ID_SCHEMA,\n errors: [\n 'UNKNOWN_ROW: the id is not on the current page.',\n 'ACTION_UNAVAILABLE: the bill offers no open action.',\n 'ACTION_DISABLED: followed by the reason code.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.openBill',\n description: 'Open one bill. The host shows its page.',\n invoke: (handle, args: { id: string }) => {\n knownRow(handle, args.id);\n handle.openBill(args.id);\n },\n },\n download_bill: {\n // A bill PDF or XML names the patient: a document with patient data\n // leaves the UI for the device (signature-request precedent, phi).\n safety: 'phi',\n openWorld: true,\n argsType: '{ id: string, format: \"pdf\" | \"xml\" }',\n argsSchema: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n format: { enum: ['pdf', 'xml'] },\n },\n required: ['id', 'format'],\n additionalProperties: false,\n },\n errors: [\n 'UNKNOWN_ROW: the id is not on the current page.',\n 'ACTION_UNAVAILABLE: the bill offers no download in this format.',\n 'ACTION_DISABLED: followed by the reason code.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.downloadBill',\n description: 'Download one bill as a PDF or an electronic invoice (XML).',\n invoke: (handle, args: { id: string; format: 'pdf' | 'xml' }) => {\n knownRow(handle, args.id);\n handle.downloadBill(args.id, args.format);\n },\n },\n load_into_warehouse: {\n // Opens the review dialog (or the upsell without the module);\n // nothing loads until the user confirms there.\n safety: 'read',\n openWorld: true,\n argsType: '{ id: string }',\n argsSchema: ROW_ID_SCHEMA,\n errors: [\n 'UNKNOWN_ROW: the id is not on the current page.',\n 'ACTION_UNAVAILABLE: not an incoming SDI bill.',\n 'ACTION_DISABLED: alreadyLoaded, when the bill is already in the warehouse.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.loadIntoWarehouse',\n description:\n \"Open the dialog that loads an incoming SDI bill's lines into the warehouse. Nothing loads until the user confirms.\",\n invoke: (handle, args: { id: string }) => {\n knownRow(handle, args.id);\n handle.loadIntoWarehouse(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'bill-table',\n description: 'Marks the element as a kit BillTable.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'gridId',\n description: 'Sourced from gridId (default accounting-bills).',\n },\n item: {\n attr: 'data-row-id',\n description:\n 'Opaque bill id on each row (DataGrid). Act through the handle, not the DOM.',\n },\n },\n};\n","/* -------------------------------------------------------------------- */\n/* BillTable: CVA for the root and the cells. Tokens only, logical */\n/* properties only. DataGrid owns the table chrome (borders, row size, */\n/* density, pins, sticky header and footer); these classes lay out what */\n/* sits inside one cell. */\n/* -------------------------------------------------------------------- */\n\nimport { cva } from 'class-variance-authority';\n\nimport { accessibleTargetBlockClass } from '../_shared/accessible-target';\n\n/** The BillTable root around the DataGrid frame. With `height: 'fill'`\n * the root is a flex column that fills its flex parent, so the grid\n * inside becomes the bounded scroll container (sticky header and footer,\n * virtualised rows). */\nexport const billTableVariants = cva('ds:w-full ds:min-w-0', {\n variants: {\n height: {\n auto: 'ds:block',\n fill: 'ds:flex ds:min-h-0 ds:flex-auto ds:flex-col',\n },\n },\n defaultVariants: { height: 'auto' },\n});\n\n/** Lines stacked in one cell (a value and its muted second line). */\nexport const cellStackVariants = cva(\n 'ds:flex ds:min-w-0 ds:flex-col ds:gap-[var(--spacing-2xs)]',\n {\n variants: {\n align: {\n start: 'ds:items-start',\n end: 'ds:items-end',\n },\n },\n defaultVariants: { align: 'start' },\n },\n);\n\n/** A muted second line (\"Credit note\", \"Due 4 Nov 2026\", \"Deleted\"). */\nexport const secondaryTextVariants = cva(\n 'type-meta ds:text-[color:var(--muted-foreground)]',\n);\n\n/** An icon beside its text, or a label beside an amount. */\nexport const inlineGroupVariants = cva(\n 'ds:inline-flex ds:min-w-0 ds:max-w-full ds:items-center ds:gap-[var(--spacing-xs)]',\n);\n\n/** The direction arrow. Mirrored in RTL: \"incoming\" points inward on\n * either reading direction. Decorative; the label is always visible. */\nexport const directionIconVariants = cva(\n 'ds:size-4 ds:shrink-0 ds:rtl:-scale-x-100',\n);\n\n/** One line of text that truncates; the full text stays in the DOM. */\nexport const truncatedTextVariants = cva(\n 'ds:block ds:min-w-0 ds:max-w-full ds:truncate',\n);\n\n/**\n * The bill number as the open control (kit Button, `intent=\"link\"`).\n *\n * Colour: the link intent paints `--primary`, which falls below 4.5:1 as\n * text on the dark page, so it is re-pointed at `--primary-readable`, as\n * the kit Link does. On a selected row the tint behind it is darker in the\n * dark theme (fuchsia-400 measures 4.46:1 there), so a selected row uses\n * the hover step, which passes on the tint: fuchsia-300 at 5.09:1 in dark,\n * violet-700 at 6.93:1 in light. AA in all four themes, plain or selected.\n *\n * Target: the link intent drops Button `sm`'s height, and `sm` hides its\n * 44 px hit area from 640 px up, which left a 21 px target in the main\n * control of each row. The `before:` hit area stays on at every width (it\n * grows the target, not the row), keyed on the Button's own marker so it\n * outranks `sm:before:hidden` whatever the CSS order (the DashboardGrid\n * precedent). In the accessible themes the box itself reaches the 48 px\n * floor, as DataGrid's own compact controls do.\n */\nexport const openButtonVariants = cva([\n 'ds:max-w-full ds:[--primary:var(--primary-readable)] ds:[--primary-hover:var(--primary-readable-hover)]',\n 'ds:[tr[data-selected]_&]:[--primary:var(--primary-readable-hover)]',\n 'ds:data-[component=button]:sm:before:block',\n accessibleTargetBlockClass,\n]);\n\n/** The bill number as plain text, when the host offers no `open`. */\nexport const numberTextVariants = cva('ds:font-medium');\n\n/** The totals breakdown inside the footer Popover, under its heading\n * and scope note. */\nexport const breakdownVariants = cva(\n 'ds:mt-[var(--spacing-sm)] ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]',\n);\n\n/** One direction's block in the breakdown: its heading and its sums. */\nexport const breakdownGroupVariants = cva(\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]',\n);\n\n/** One paragraph of the breakdown (a direction heading). */\nexport const breakdownTextVariants = cva('ds:m-0', {\n variants: {\n tone: {\n muted: 'ds:text-[color:var(--muted-foreground)]',\n strong:\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-x-[var(--spacing-sm)] ds:text-[color:var(--foreground)] ds:[font-weight:var(--font-weight-semibold)]',\n },\n },\n defaultVariants: { tone: 'muted' },\n});\n\n/** The breakdown's label and amount pairs. */\nexport const breakdownListVariants = cva(\n 'ds:m-0 ds:grid ds:grid-cols-[1fr_auto] ds:items-baseline ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-2xs)]',\n);\n\nexport const breakdownTermVariants = cva(\n 'ds:m-0 ds:text-[color:var(--muted-foreground)]',\n);\n\nexport const breakdownValueVariants = cva('ds:m-0 ds:text-end');\n","/* -------------------------------------------------------------------- */\n/* BillTable: public types (the Phase 2 contract). */\n/* */\n/* Rules this file keeps: */\n/* - No DataGrid internal and no TanStack type in a public type. Public */\n/* kit shapes (DataGridPagination, filter models) are reused. */\n/* - Only `BillRow.id` reaches the DOM (DataGrid `data-row-id`). */\n/* - Every field that mirrors the platform names its source on */\n/* alfadocs/platform origin/stable f039a606cf. */\n/* DB = src/Ic/MainBundle/Entity/DoctorBill.php */\n/* REPO = src/AlfaDocs/Infrastructure/Domain/Practice/Archive/Bill/ */\n/* DoctrineBillRepository.php */\n/* SEND = src/AlfaDocs/Domain/Practice/Archive/FatturazioneElettronica */\n/* /Sending/Bill/Bill.php */\n/* LIAB = src/AlfaDocs/Domain/Practice/Archive/Bill/Liability/ */\n/* Liability.php */\n/* CTRL = src/Ic/DcpBundle/Controller/DoctorBillController.php */\n/* FORM = src/Ic/DcpBundle/Form/Type/BillFilterType.php */\n/* */\n/* Copied from the reviewed draft */\n/* scratchpad/p2/contract/bill-table.ts; the implementer owns it from */\n/* here and keeps it in step with design-bill-table.md. */\n/* -------------------------------------------------------------------- */\n\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport type {\n DataGridChange,\n DataGridPagination,\n DataGridWriteOptions,\n} from '../data-grid/types';\nimport type {\n DateRangeFilterModel,\n NumberFilterModel,\n} from '../_shared/table-toolbar/seam';\nimport type { EmptyStateHeadingLevel } from '../empty-state';\n\n/* ================================================================== */\n/* Closed enums */\n/* ================================================================== */\n\n/** Platform: `DoctorBill::DIRECTION_*` (DB:37-38), field `direction`\n * (DB:1198). `incoming` = a bill the practice received (a cost);\n * `outgoing` = a bill the practice issued (revenue). */\nexport const BILL_DIRECTIONS = ['incoming', 'outgoing'] as const;\nexport type BillDirection = (typeof BILL_DIRECTIONS)[number];\n\n/** Platform: `DoctorBill::TYPE_*` (DB:40-44), field `type` (DB:854).\n * `credit` is a credit note. Incoming SDI credit notes carry their kind in\n * `documentType` (DB:282, `getDocumentType()` DB:2480); the conversion\n * maps TD04 to `credit` (`CreateRealBillForIncomingBillService.php:115`)\n * and refuses TD08 as unsupported (`:103-111`). */\nexport const BILL_TYPES = [\n 'full',\n 'partial',\n 'credit',\n 'proforma',\n 'other',\n] as const;\nexport type BillType = (typeof BILL_TYPES)[number];\n\n/**\n * Payment state of the bill. The platform has NO field for it: the host\n * derives it per row, on MAGNITUDES (a credit note's gross, paid and\n * unpaid amounts are negative, `DoctorBill.php:341-342`), first match wins:\n * 1. `noPaymentDue`: `type === 'proforma'` (DB:43; `isProformaOrWrittenOff()`\n * DB:2045 forces unpaid to 0).\n * 2. `writtenOff`: `writtenOff` true (DB:177).\n * 3. `paid`: `getUnpaidAmount()` (DB:806; SQL `unpaid_amount`, REPO:1033)\n * is 0.\n * 4. `overdue`: |unpaid| > 0 and at least one open liability is due\n * (`Liability::isDue()`, LIAB:205-208).\n * 5. `partiallyPaid`: |`getPaidAmount()`| (DB:791; SQL `paid_amount`) > 0.\n * 6. `unpaid`: anything else.\n * Direction-neutral on purpose: one label per state.\n */\nexport const BILL_PAYMENT_STATUSES = [\n 'paid',\n 'partiallyPaid',\n 'unpaid',\n 'overdue',\n 'writtenOff',\n 'noPaymentDue',\n] as const;\nexport type BillPaymentStatus = (typeof BILL_PAYMENT_STATUSES)[number];\n\n/**\n * SDI (Sistema di Interscambio) state. The platform has NO field on the\n * bill: the host derives it, first match wins:\n * - `received`: incoming and `fatturazioneElettronicaIncomingBillId` set\n * (DB:207).\n * - `notApplicable`: practice country is not `it`, or an incoming bill\n * neither from SDI nor a self-bill (`isAutoBill()` DB:2461). Renders an\n * empty cell.\n * - outgoing (and incoming self-bills), from the latest sending snapshot\n * `FatturazioneElettronica\\Sending\\Bill` (SEND) and its batch `Sending`\n * (`STATE_*`, Sending.php:28-30):\n * - `notSent`: no snapshot row for the bill.\n * - `sending`: batch state `todo` or `waiting_to_be_sent`.\n * - `pending`: `sent` true (SEND:22), `result` null (SEND:24).\n * - `rejected`: `result === 'rejected'` (SEND:32).\n * - `notDelivered`: accepted and `nonDeliveryNotificationIncomingMessageId`\n * set (SEND:28).\n * - `delivered`: accepted and `deliveryReceiptIncomingMessageId` set\n * (SEND:27).\n * - `accepted`: `result === 'accepted'` (SEND:31), no receipt yet.\n */\nexport const BILL_SDI_STATUSES = [\n 'notApplicable',\n 'notSent',\n 'sending',\n 'pending',\n 'accepted',\n 'delivered',\n 'notDelivered',\n 'rejected',\n 'received',\n] as const;\nexport type BillSdiStatus = (typeof BILL_SDI_STATUSES)[number];\n\n/**\n * Warehouse loading state of an incoming SDI bill. NO platform field yet:\n * HTP-7309 adds the invoice-line reference on stock movements, which is the\n * single source (HTP-7312: \"no second status store\").\n * - `loaded`: at least one line of the bill carries a reference.\n * - `toReview`: automatic loading ran and found an unmatched line, or it is\n * switched off (HTP-7313).\n * - `notLoaded`: an incoming SDI bill with neither.\n * `null` or absent: not an incoming SDI bill, or no module (HTP-7314).\n * Renders an empty cell.\n */\nexport const BILL_WAREHOUSE_STATUSES = [\n 'notLoaded',\n 'toReview',\n 'loaded',\n] as const;\nexport type BillWarehouseStatus = (typeof BILL_WAREHOUSE_STATUSES)[number];\n\n/**\n * Who the counterparty is, for privacy. Privacy mode hides `patient` and\n * `person`; `company` stays visible.\n * - `patient`: a care-plan bill, `doctorCarePlan` (DB:92) set.\n * - `person`: an individual who is not a patient: `doctorOperator`\n * (DB:1208), or no linked entity and a snapshot with\n * `counterpartFirstName`/`counterpartLastName` (DB:113, DB:118) and no\n * `counterpartCompanyName` (DB:108).\n * - `company`: `doctorCompany` (DB:1203; a supplier or lab), or a snapshot\n * with `counterpartCompanyName`. NOTE: DoctorCompany has no person flag,\n * so a sole trader stored as a company shows.\n */\nexport const BILL_COUNTERPARTY_KINDS = [\n 'patient',\n 'person',\n 'company',\n] as const;\nexport type BillCounterpartyKind = (typeof BILL_COUNTERPARTY_KINDS)[number];\n\n/* ================================================================== */\n/* Row actions */\n/* ================================================================== */\n\n/**\n * Every row action BillTable can offer, in menu order. The first four are\n * the brief's; the rest keep today's list working and render only when the\n * host makes them available (see `BillRow.actions`).\n * - `open`: `ic_dcp_doctor_bill_show` (CTRL:1162).\n * - `downloadPdf`: `ic_dcp_doctor_bill_download` (CTRL:1275).\n * - `downloadXml`: outgoing or self-bill (`canHaveFatturazioneElettronicaXml()`\n * DB:2507) or received from SDI.\n * - `loadIntoWarehouse`: opens the HTP-7311 dialog, or the HTP-7314 upsell\n * without the module. Not tied to `showWarehouseStatus`.\n * - `edit`, `recordPayment`, `writeOff`, `undoWriteOff`, `delete`: today's\n * edit, per-liability \"Incassa\"/\"Pagato\", \"Stralcia\", \"Non più stralciare\"\n * and \"Elimina\".\n */\nexport const BILL_ROW_ACTIONS = [\n 'open',\n 'downloadPdf',\n 'downloadXml',\n 'loadIntoWarehouse',\n 'edit',\n 'recordPayment',\n 'writeOff',\n 'undoWriteOff',\n 'delete',\n] as const;\nexport type BillRowActionId = (typeof BILL_ROW_ACTIONS)[number];\n\n/**\n * Kit-owned reasons, so the copy exists in 18 languages.\n * - `alreadyLoaded`: one-load rule (HTP-7309, HTP-7311).\n * - `sentToSdi`, `legalStorage`: `dcp.doctor_bill.list.can_not_edit_message`\n * (canEditOrDelete false, `BillListDTO.canEditOrDelete`).\n * - `paymentAutomation`: `...can_not_edit_or_delete_payment_automation`.\n * - `noPermission`: the user lacks `doctor_bill_edit` / `practice_bill_delete`.\n * - `inProgress`: the host is already running this action for the row.\n */\nexport const BILL_ACTION_DISABLED_REASONS = [\n 'alreadyLoaded',\n 'sentToSdi',\n 'legalStorage',\n 'paymentAutomation',\n 'noPermission',\n 'inProgress',\n] as const;\nexport type BillActionDisabledReason =\n (typeof BILL_ACTION_DISABLED_REASONS)[number];\n\n/**\n * `'enabled'`, or disabled with a kit reason or a host text (translated\n * by the host). An action absent from the map is not shown.\n *\n * Don't name a person in the host text (nor in `error.description` or\n * `extraFilterLabels`): use a kit reason code where one fits. The kit\n * cannot tell whether a text names someone, so under privacy mode every\n * host text reads as kit copy, and agent reads carry only the code\n * `'host'`, never the text.\n */\nexport type BillRowActionState =\n | 'enabled'\n | { disabled: BillActionDisabledReason }\n | { disabled: { text: string } };\n\nexport type BillRowActionMap = Partial<\n Record<BillRowActionId, BillRowActionState>\n>;\n\n/** An action's state as an agent reads it: a host's own disabled text is\n * reduced to the code `'host'`, whatever privacy mode says, since it may\n * name a person. */\nexport type BillRowActionSummaryState =\n | 'enabled'\n | { disabled: BillActionDisabledReason | 'host' };\n\nexport type BillRowActionSummaryMap = Partial<\n Record<BillRowActionId, BillRowActionSummaryState>\n>;\n\n/* ================================================================== */\n/* Row */\n/* ================================================================== */\n\nexport interface BillCounterparty {\n kind: BillCounterpartyKind;\n /**\n * The linked entity's name as the list shows it today: the patient of\n * `doctorCarePlan` (DB:92), `doctorCompany.name` (DB:1203,\n * DoctorCompany.php:20) or the `doctorOperator` (DB:1208). Fallback for a\n * bill with no linked entity: `getRelevantCounterpartName()` (DB:2099).\n * NOT the SDI sending snapshot. Masked under privacy mode unless `kind`\n * is `company`.\n */\n name: string;\n /** The linked entity is soft-deleted (`DoctorCompany.deleted`,\n * DoctorCompany.php:94; list.html.twig:100-112 appends \"(cancellato)\"). */\n deleted?: boolean;\n}\n\nexport interface BillRow {\n /** `DoctorBill.id` (DB:82), as a string. The only field in the DOM. */\n id: string;\n /** `getNumberPrefixAndNumber()` (DB:1687): `incomingNumber` (DB:1617)\n * for incoming, `outgoingNumberPrefix` (DB:1607) + `outgoingNumber`\n * (DB:1612) for outgoing. Plain text, never masked: it names the row. */\n number: string;\n /** `DoctorBill.type` (DB:854). */\n type: BillType;\n /** `DoctorBill.date` (DB:72) as a calendar day `YYYY-MM-DD`. */\n date: string;\n /** `DoctorBill.direction` (DB:1198). */\n direction: BillDirection;\n /** `null` when the bill has no counterparty at all. */\n counterparty: BillCounterparty | null;\n /**\n * `getGross()` (DB:773; SQL alias `gross`, REPO:1018) in minor units:\n * the host sends `(int) round($gross * 100)` from PHP. Exact here only\n * because SQL already rounds `gross` to 2 places (REPO:1016-1018);\n * FatturaPA line values (up to 8 places) travel as decimal strings\n * instead (BillLineTable). Never parsed from a float string in the\n * browser. Sign as stored: negative for a credit note\n * (`DoctorBill::setNet` asserts net <= 0 for credit bills,\n * `DoctorBill.php:341-342`). The cell uses Money's default tone, so a\n * credit note reads as a minus sign, not an alarm. In the table's\n * `currency`. The amount FILTER is in major units (see\n * `BillTableFilterModel.amount`).\n */\n amountMinor: number;\n paymentStatus: BillPaymentStatus;\n /** Earliest open liability date (`DoctorBill.liabilities` DB:952,\n * `Liability.date`), `YYYY-MM-DD`; shown under `unpaid`,\n * `partiallyPaid` and `overdue` only. */\n nextDueDate?: string | null;\n sdiStatus: BillSdiStatus;\n /** See `BillWarehouseStatus`. Read only when `showWarehouseStatus`. */\n warehouseStatus?: BillWarehouseStatus | null;\n /** Per-row availability; absent action = hidden. `open` should always be\n * present (the bill number is the open control). */\n actions: BillRowActionMap;\n}\n\n/* ================================================================== */\n/* Totals */\n/* ================================================================== */\n\n/**\n * Sums over every bill that matches the query (all pages) for ONE\n * direction. Same sums as today (CTRL:289-297, GeneralManager.php:193-232),\n * split by direction because today's single sum adds costs and revenue\n * together. Minor units, `(int) round($sum * 100)` on the server (exact:\n * every summand is already at 2 places). Signed: credit notes count\n * negative, as stored.\n */\nexport interface BillDirectionTotals {\n /** Bills counted (`count($rows)`, GeneralManager.php:199-203). */\n count: number;\n /** Sum of SQL `gross` (REPO:1018). */\n grossMinor: number;\n /** Sum of `db.net` (DB:67). */\n netMinor: number;\n /** Sum of `db.vat` (DB:747). */\n vatMinor: number;\n /** Sum of `db.tax_at_source` (DB:1419). */\n taxAtSourceMinor: number;\n /** Sum of SQL `paid_amount` (REPO:1032). */\n paidMinor: number;\n /** Sum of SQL `unpaid_amount` (REPO:1033). */\n unpaidMinor: number;\n}\n\n/** A direction with no matching bill is `null` or absent and gets no line. */\nexport interface BillTableTotals {\n incoming?: BillDirectionTotals | null;\n outgoing?: BillDirectionTotals | null;\n}\n\n/* ================================================================== */\n/* Columns, sorting, filters, query */\n/* ================================================================== */\n\nexport const BILL_TABLE_COLUMNS = [\n 'number',\n 'date',\n 'direction',\n 'counterparty',\n 'amount',\n 'paymentStatus',\n 'sdiStatus',\n 'warehouseStatus',\n 'actions',\n] as const;\nexport type BillTableColumnId = (typeof BILL_TABLE_COLUMNS)[number];\n\n/** Columns the server can sort. Default: all four. */\nexport const BILL_TABLE_SORT_COLUMNS = [\n 'number',\n 'date',\n 'counterparty',\n 'amount',\n] as const;\nexport type BillTableSortColumn = (typeof BILL_TABLE_SORT_COLUMNS)[number];\n\nexport interface BillTableSortEntry {\n colId: BillTableSortColumn;\n sort: 'asc' | 'desc';\n}\n\n/** A set filter whose values are one of BillTable's enums. Assignable to\n * the kit `SelectFilterModel`. */\nexport interface BillSetFilter<TValue extends string> {\n type: 'set';\n values: TValue[];\n}\n\n/** Relative periods the server resolves on each request, so a saved tab\n * \"This year\" stays right next year. Replaces CTRL:160-163's fixed\n * `date_from`. */\nexport type BillDatePreset = 'today' | 'thisMonth' | 'thisYear';\n\n/**\n * Every filter BillTable carries. Column keys are evaluated by the server\n * from the column filters in the header; host keys are written by the\n * platform's own advanced-filter panel (`toolbarStart`) and are never\n * evaluated by the kit. Chips show a host key's label only, never its value.\n * A type alias (not an interface) so it is assignable to\n * `DataGridFilterModel`.\n */\nexport type BillTableFilterModel = {\n /* ---- column keys ---- */\n /** FORM `date_from`/`date_to`. */\n date?: DateRangeFilterModel;\n /** FORM `direction`. */\n direction?: BillSetFilter<BillDirection>;\n /** FORM `amount_from`/`amount_to` (`inRange`, either bound). MAJOR units\n * as typed (12.50), like the platform form. Note the unit differs from\n * `BillRow.amountMinor` (minor units): the server converts. */\n amount?: NumberFilterModel;\n /** New: needs the derived status in SQL. */\n paymentStatus?: BillSetFilter<BillPaymentStatus>;\n /** New: needs the derived status in SQL. */\n sdiStatus?: BillSetFilter<BillSdiStatus>;\n /** New (HTP-7312). Ignored by the server without the module. */\n warehouseStatus?: BillSetFilter<BillWarehouseStatus>;\n\n /* ---- host keys (the platform form, FORM:27-243) ---- */\n datePreset?: BillDatePreset;\n /** FORM `type` (multi). */\n type?: BillSetFilter<BillType>;\n /** FORM `number` (exact). Shares its id with the `number` column, so\n * DataGrid reads it as that column's key: its chip is named by the\n * column, not by `filterLabels` (a bill number is not personal data). */\n number?: string;\n /** FORM `prefix` (exact). */\n prefix?: string;\n /** FORM yes/no fields: `true` = yes, `false` = no, absent = any. */\n withInsuranceNet?: boolean;\n withVat?: boolean;\n withTaxAtSource?: boolean;\n withWelfareFundContribution?: boolean;\n withUnpaidAmount?: boolean;\n writtenOff?: boolean;\n /** FORM `tax_office_notification`. */\n taxOfficeNotification?: boolean;\n /** FORM `fatturazione_elettronica_incoming_bill`. */\n receivedFromSdi?: boolean;\n /** FORM `fatturazione_elettronica_sending_bill` (accepted by SDI,\n * CTRL:189-211). */\n sentToSdi?: boolean;\n /** FORM `self_bill`. */\n selfBill?: boolean;\n /** FORM `with_liability_from`/`_to`. */\n liabilityDate?: DateRangeFilterModel;\n /** FORM `sdi_entry_date_from`/`_to`. */\n sdiEntryDate?: DateRangeFilterModel;\n /** FORM `relation_type`. */\n relationType?: 'patient' | 'company' | 'operator';\n /** FORM `relation`: an entity id, never a name. */\n relation?: { type: 'patient' | 'company' | 'operator'; id: string };\n /** FORM `insurance`: an insurer key or `'none'`. */\n insurance?: string;\n /** FORM `personal_assistant`: a practice member id. */\n personalAssistant?: string;\n};\n\nexport type BillTableHostFilterKey = Exclude<\n keyof BillTableFilterModel,\n BillTableColumnId\n>;\n\n/** The query a host holds and feeds back (controlled). */\nexport interface BillTableQueryState {\n /** Default `[{ colId: 'date', sort: 'desc' }]` (CTRL:180-183). */\n sorting: BillTableSortEntry[];\n filters: BillTableFilterModel;\n /** Matches the bill number and, unless `privacyMode`, the counterparty\n * name. New on the platform (no free-text search today). */\n quickFilter: string;\n /** Zero-based. Default `{ pageIndex: 0, pageSize: 25 }`. */\n pagination: DataGridPagination;\n}\n\n/** What `onQueryChange` reports: the state plus the privacy flag, so the\n * server searches bill numbers only while names are hidden. */\nexport interface BillTableQuery extends BillTableQueryState {\n privacyMode: boolean;\n}\n\n/* ================================================================== */\n/* Callbacks */\n/* ================================================================== */\n\n/** Who triggered a row action: a person in the table, or the handle (an\n * agent). The platform can keep agent calls out of its analytics. */\nexport type BillActionSource = 'user' | 'api';\n\nexport interface BillActionContext {\n source: BillActionSource;\n}\n\n/** HTP-7312 analytics: `bill_warehouse_load_clicked { warehouse_status }`. */\nexport interface BillLoadContext extends BillActionContext {\n /** The row's status, or `null` (not computed without the module). */\n warehouseStatus: BillWarehouseStatus | null;\n}\n\nexport type BillDownloadFormat = 'pdf' | 'xml';\n\n/** List downloads that apply the current query to EVERY matching bill\n * (index.html.twig:91-131, IndexPage.js:29-34). Labels are kit copy. */\nexport const BILL_LIST_DOWNLOADS = [\n 'csv',\n 'csvDetailed',\n 'pdfZip',\n 'pdfSingle',\n 'xmlOutgoingZip',\n 'xmlIncomingZip',\n] as const;\nexport type BillListDownloadKind = (typeof BILL_LIST_DOWNLOADS)[number];\n\n/* ================================================================== */\n/* Props */\n/* ================================================================== */\n\nexport interface BillTableProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'children' | 'dir' | 'onChange'\n> {\n /* ===== data (server mode, always) ===== */\n\n /** The current page only. */\n rows: readonly BillRow[];\n /** Bills matching the query, all pages. `-1` = unknown. */\n rowCount: number;\n /** ISO 4217, for every amount (`current_doctor_address().currency`,\n * list.html.twig:2). Default `'EUR'`. */\n currency?: string;\n /** Server sums, all pages. Absent or `null`: no totals row (the user\n * lacks `practice_see_total_values`, index.html.twig:309-311). */\n totals?: BillTableTotals | null;\n\n /* ===== query (sorting, filters, quick search, paging) ===== */\n\n /** Controlled. Pair with `onQueryChange`. */\n query?: BillTableQueryState;\n /** Uncontrolled seed. */\n defaultQuery?: Partial<BillTableQueryState>;\n /** The single fetch trigger. Never fires on mount; fires once per change\n * of sorting, filters, quick search, page or page size (a sort, filter or\n * search change resets the page to 0), whatever the source (the UI, the\n * handle, a DataGridTabs switch, a new controlled `query`), and once when\n * `privacyMode` changes while a quick search or a counterparty sort is\n * active. That last emission is DataGrid's (the query carries the\n * effective sort: a counterparty sort is paused, not sent, while names\n * are hidden, and comes back when privacy mode turns off); BillTable only\n * adds `privacyMode` to it and never emits on its own. A controlled host\n * stores what this reports and passes it back as `query`. */\n onQueryChange?: (query: BillTableQuery) => void;\n /** Columns the server can sort. Default all of\n * `BILL_TABLE_SORT_COLUMNS`. */\n sortableColumns?: readonly BillTableSortColumn[];\n /** Default `[25, 50, 100]`. */\n pageSizeOptions?: readonly number[];\n\n /* ===== selection ===== */\n\n /** Checkbox column and bulk actions. Default `true`; `false` for a\n * read-only list. */\n selectable?: boolean;\n /** Controlled ids, every page. Survives paging and sorting; cleared when\n * filters or quick search change (DataGrid\n * `clearSelectionOnFilterChange`, always on). */\n selection?: readonly string[];\n defaultSelection?: readonly string[];\n onSelectionChange?: (ids: string[]) => void;\n\n /* ===== columns ===== */\n\n /** Adds the warehouse status column (HTP-7314: practices with the\n * module). Does not affect the `loadIntoWarehouse` action. */\n showWarehouseStatus?: boolean;\n /** BillTable's `data-component-id` and agent instance id, and the inner\n * DataGrid's column-state storage key. Default `'accounting-bills'`.\n * The inner DataGrid gets `registerAgent={false}`, so only\n * `billTableAgent` registers under this id. */\n gridId?: string;\n /** Default `true`. */\n persistColumnState?: boolean;\n\n /* ===== row actions (the host does the work; the kit never fetches) ===== */\n\n onOpen: (row: BillRow, context: BillActionContext) => void;\n onDownload?: (\n row: BillRow,\n format: BillDownloadFormat,\n context: BillActionContext,\n ) => void;\n onLoadIntoWarehouse?: (row: BillRow, context: BillLoadContext) => void;\n onEdit?: (row: BillRow, context: BillActionContext) => void;\n onRecordPayment?: (row: BillRow, context: BillActionContext) => void;\n /** `revert` true = \"Undo write-off\". */\n onWriteOff?: (\n row: BillRow,\n revert: boolean,\n context: BillActionContext,\n ) => void;\n /** The host confirms (AlertDialog) before deleting. */\n onDelete?: (row: BillRow, context: BillActionContext) => void;\n\n /* ===== bulk and list actions ===== */\n\n /** Shows \"Download PDFs\" and \"Download XML files\" for the selection. */\n onBulkDownload?: (ids: string[], format: BillDownloadFormat) => void;\n /** List downloads offered in the toolbar's download menu, in this order.\n * Default none. */\n listDownloads?: readonly BillListDownloadKind[];\n onListDownload?: (kind: BillListDownloadKind, query: BillTableQuery) => void;\n /** Shows the toolbar Refresh button. */\n onRefresh?: () => void;\n\n /* ===== toolbar ===== */\n\n /** Host content at the start of the filter bar: the platform's\n * \"Show advanced filters\" trigger, whose panel writes host keys through\n * the controlled `query` or `handle.setFilter`. */\n toolbarStart?: ReactNode;\n /** Chip labels for extra host keys the platform adds later (translated\n * by the host). Kit keys already have kit labels. Don't name a person\n * in a label. */\n extraFilterLabels?: Record<string, string>;\n\n /* ===== states ===== */\n\n /** Default `'ready'`. */\n status?: 'ready' | 'loading' | 'error';\n /** Overrides `ui.billTable.error.*`; `onRetry` shows \"Try again\".\n * Don't name a person in the title or description. */\n error?: { title?: string; description?: string; onRetry?: () => void };\n /** First-use action (\"Add bill\"); omitted when the user cannot create. */\n onCreateBill?: () => void;\n /** Heading level for the empty and error states. Default 3. */\n headingLevel?: EmptyStateHeadingLevel;\n\n /* ===== privacy and layout ===== */\n\n /** Masks patient and person names; companies stay visible. Default\n * `false`. */\n privacyMode?: boolean;\n /** Default `t('billTable.caption')`, \"Bills\". */\n caption?: string;\n /** Default `'default'`. */\n density?: 'default' | 'compact';\n /** `'fill'`: BillTable fills a flex column parent and its grid becomes\n * the bounded scroll container, so the header and the totals row stay\n * in view and a page above 100 rows is virtualised. Give the parent a\n * bounded block size. Default `'auto'` (the grid grows with its rows). */\n height?: 'auto' | 'fill';\n}\n\n/* ================================================================== */\n/* Handle */\n/* ================================================================== */\n\nexport interface BillTableFeatureInfo {\n selectable: boolean;\n privacyMode: boolean;\n showWarehouseStatus: boolean;\n sortableColumns: BillTableSortColumn[];\n status: 'ready' | 'loading' | 'error';\n}\n\nexport interface BillTableColumnInfo {\n id: BillTableColumnId;\n /** Plain, translated name. */\n label: string;\n visible: boolean;\n canHide: boolean;\n sortable: boolean;\n /** Masked by privacy mode (counterparty while `privacyMode`). */\n masked: boolean;\n}\n\n/**\n * One bill as an agent may read it (state slot `rows`). The counterparty\n * name is present only for `company`; patients and other people are never\n * named here, whatever `privacyMode` says (agent state carries no PHI,\n * `src/agent/types.ts:76-80`).\n */\nexport interface BillRowSummary {\n id: string;\n number: string;\n type: BillType;\n date: string;\n direction: BillDirection;\n counterpartyKind: BillCounterpartyKind | null;\n counterpartyName?: string;\n amountMinor: number;\n paymentStatus: BillPaymentStatus;\n sdiStatus: BillSdiStatus;\n warehouseStatus: BillWarehouseStatus | null;\n /** Reason codes only: a host's own text reads as `'host'`. */\n actions: BillRowActionSummaryMap;\n}\n\n/** Who caused a change, as DataGrid reports it. */\nexport type BillTableChange = DataGridChange;\n\n/**\n * Curated handle (`ref`). Ids and kit shapes only: no DataGrid handle, no\n * TanStack object, no row object, no DOM node. Reads go to the live grid,\n * so a read straight after a write is fresh.\n *\n * Saved views: wrap BillTable in `DataGridTabs`. The DataGrid inside\n * registers itself with the tabs through context, so no `getTable` is\n * needed. This handle is not a `DataGridTabsSeam` (the seam also needs\n * `applyView`, `isPrivacyMode` and DataGrid's full column info), so do not\n * pass it as `getTable`.\n */\nexport interface BillTableHandle {\n getFeatures(): BillTableFeatureInfo;\n\n /* ---- query ---- */\n /** The effective query, as `onQueryChange` reports it (a paused\n * counterparty sort left out under privacy mode). */\n getQuery(): BillTableQuery;\n /** Refused (no-op, DEV warning) for a column outside `sortableColumns`\n * or masked by privacy mode. The server sorts by one column: only the\n * first entry is used. */\n setSort(model: readonly BillTableSortEntry[]): void;\n /** Every filter the table holds: column models and host keys, a filter\n * paused by privacy mode included. */\n getFilter(): BillTableFilterModel;\n setFilter(model: BillTableFilterModel, options?: DataGridWriteOptions): void;\n getQuickFilter(): string;\n setQuickFilter(text: string, options?: DataGridWriteOptions): void;\n clearFilters(): void;\n goToPage(pageIndex: number): void;\n setPageSize(size: number): void;\n /** `-1` when the total is unknown. */\n getPageCount(): number;\n getRowCount(): number;\n /** The current page, display order. */\n getRowIds(): string[];\n\n /* ---- selection ---- */\n getSelection(): string[];\n setSelection(ids: readonly string[]): void;\n selectRange(fromId: string, toId: string): void;\n clearSelection(): void;\n\n /* ---- columns ---- */\n getColumns(): BillTableColumnInfo[];\n setColumnVisible(id: BillTableColumnId, visible: boolean): void;\n resetColumns(): void;\n\n /* ---- focus ---- */\n scrollToRow(id: string): void;\n /** Focus the row's control in `columnId` (`number` = the open button,\n * `actions` = the menu button). Default `number`. */\n focusRow(id: string, columnId?: 'number' | 'actions'): void;\n\n /* ---- rows (agent-safe projection, current page) ---- */\n /** Never a patient's or person's name; see `BillRowSummary`. */\n getRowSummaries(): BillRowSummary[];\n\n /* ---- row actions (same callbacks as the UI, source 'api') ---- */\n /** The actions the table offers for the row: entries of `row.actions`\n * whose callback is set (`open` always has one). Under privacy mode\n * every host's own disabled text reads as kit copy, whatever the\n * counterparty. For the host; agents read `getRowSummaries()`, which\n * carries reason codes only. Throws `UNKNOWN_ROW`. */\n getRowActions(id: string): BillRowActionMap;\n /** Throws `UNKNOWN_ROW`, `ACTION_UNAVAILABLE` (absent from the row's map,\n * or no callback) or `ACTION_DISABLED: <reason>`, where the reason is the\n * kit code or `host` (never a host's text). */\n openBill(id: string): void;\n downloadBill(id: string, format: BillDownloadFormat): void;\n loadIntoWarehouse(id: string): void;\n\n /* ---- change feed ---- */\n subscribe(listener: (change: BillTableChange) => void): () => void;\n}\n\n/* ================================================================== */\n/* Default saved views (DataGridTabs) */\n/* ================================================================== */\n\n/** Stable tab ids (developer constants; emitted as `data-tab-id`). */\nexport const BILL_TABLE_DEFAULT_TAB_IDS = [\n 'bills-this-year',\n 'bills-all',\n 'bills-incoming',\n 'bills-outgoing',\n 'bills-to-pay',\n 'bills-to-collect',\n 'bills-to-load',\n] as const;\nexport type BillTableDefaultTabId = (typeof BILL_TABLE_DEFAULT_TAB_IDS)[number];\n","/* -------------------------------------------------------------------- */\n/* BillTable: pure helpers shared by the component, the handle and the */\n/* agent projection. No React, no translation. */\n/* */\n/* Money rule (money.mdx, \"Money from the platform\"): every amount here */\n/* is an integer in hundredths, as the platform sends it. The kit never */\n/* adds, subtracts or rounds a bill amount or a total, and never turns */\n/* one into a float by division: display goes through Money's exact */\n/* `scale` path, export through the `./decimal` helpers. */\n/* -------------------------------------------------------------------- */\n\nimport { decimalToNumber } from '../_shared/decimal';\nimport { formatLocale } from '../_shared/intl-locale';\nimport type { DataGridSortEntry } from '../data-grid/types';\nimport {\n BILL_ROW_ACTIONS,\n BILL_TABLE_SORT_COLUMNS,\n type BillActionContext,\n type BillActionDisabledReason,\n type BillRow,\n type BillRowActionId,\n type BillRowActionMap,\n type BillRowActionState,\n type BillRowActionSummaryMap,\n type BillRowSummary,\n type BillTableProps,\n type BillTableSortColumn,\n type BillTableSortEntry,\n} from './types';\n\n/* ================================================================== */\n/* Constants */\n/* ================================================================== */\n\n/** Default `gridId`: BillTable's agent instance id and the inner\n * DataGrid's column-state storage key. */\nexport const BILL_TABLE_DEFAULT_GRID_ID = 'accounting-bills';\n\n/** The platform's default order (`DoctorBillController.php:180-183`). */\nexport const BILL_TABLE_DEFAULT_SORT: readonly BillTableSortEntry[] = [\n { colId: 'date', sort: 'desc' },\n];\n\n/** Page sizes the pager offers. The largest equals DataGrid's\n * virtualisation threshold, so a page keeps every row in the DOM. */\nexport const BILL_TABLE_PAGE_SIZE_OPTIONS: readonly number[] = [25, 50, 100];\n\n/**\n * Decimal places of every amount BillTable receives: `BillRow.amountMinor`\n * and the `BillDirectionTotals` sums are `(int) round($x * 100)` from PHP\n * (exact, because SQL already rounds gross to 2 places,\n * `DoctrineBillRepository.php:1016-1018`). Money gets it as `scale`, so the\n * integer is formatted with integer arithmetic and never divided as a float.\n */\nexport const BILL_AMOUNT_SCALE = 2;\n\n/** Context of a row action a person started in the table. */\nexport const USER_ACTION: BillActionContext = { source: 'user' };\n\n/** Context of a row action started through the handle (an agent). */\nexport const API_ACTION: BillActionContext = { source: 'api' };\n\n/* ================================================================== */\n/* Rows */\n/* ================================================================== */\n\n/**\n * Does privacy mode hide this row's counterparty? Patients and other\n * people are hidden; companies (suppliers, labs) stay visible; a bill\n * with no counterparty has nothing to hide. Michael's privacy decision\n * (4 Nov 2026); also the counterparty column's `appliesTo`.\n */\nexport function isPersonCounterparty(row: BillRow): boolean {\n return row.counterparty !== null && row.counterparty.kind !== 'company';\n}\n\n/**\n * The amount as a number in major units, for CSV, XLSX and PDF. Built from\n * the integer with the exact decimal helpers (`12345` gives `123.45`), so\n * the number is the nearest double to the decimal and no division happens.\n * `null` for a value that is not a safe integer or that a double cannot\n * give back exactly (beyond 15 significant digits): the cell exports empty\n * rather than a wrong figure.\n */\nexport function amountForExport(amountMinor: number): number | null {\n if (!Number.isSafeInteger(amountMinor)) return null;\n return decimalToNumber({ units: amountMinor, scale: BILL_AMOUNT_SCALE });\n}\n\n/* Building an `Intl.DateTimeFormat` costs far more than using one, and a\n page repeats the same locale in every row. */\nconst dayFormatters = new Map<string, Intl.DateTimeFormat>();\nconst CALENDAR_DAY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\n/**\n * A calendar day `YYYY-MM-DD` in the UI language, medium style (\"4 Nov\n * 2026\" in British English). Read and formatted in UTC, so the day never\n * moves with the viewer's time zone. Any other text is returned as given.\n */\nexport function formatCalendarDay(day: string, language: string): string {\n const match = CALENDAR_DAY.exec(day);\n if (!match) return day;\n const [, year, month, date] = match;\n const instant = new Date(\n Date.UTC(Number(year), Number(month) - 1, Number(date)),\n );\n if (Number.isNaN(instant.getTime())) return day;\n const locale = formatLocale(language);\n let formatter = dayFormatters.get(locale);\n if (!formatter) {\n formatter = new Intl.DateTimeFormat(locale, {\n dateStyle: 'medium',\n timeZone: 'UTC',\n });\n dayFormatters.set(locale, formatter);\n }\n return formatter.format(instant);\n}\n\n/* ================================================================== */\n/* Sorting */\n/* ================================================================== */\n\nconst SORT_COLUMNS: ReadonlySet<string> = new Set(BILL_TABLE_SORT_COLUMNS);\n\nexport function isBillTableSortColumn(\n colId: string,\n): colId is BillTableSortColumn {\n return SORT_COLUMNS.has(colId);\n}\n\n/** DataGrid sort entries as BillTable's typed entries. Only sortable bill\n * columns can be in a DataGrid sort; anything else is left out. */\nexport function toBillSortEntries(\n entries: readonly DataGridSortEntry[],\n): BillTableSortEntry[] {\n const out: BillTableSortEntry[] = [];\n for (const entry of entries) {\n if (isBillTableSortColumn(entry.colId)) {\n out.push({ colId: entry.colId, sort: entry.sort });\n }\n }\n return out;\n}\n\n/** A stable text for comparing two sorts. */\nexport function sortKey(entries: readonly DataGridSortEntry[]): string {\n return entries.map((entry) => `${entry.colId}:${entry.sort}`).join('|');\n}\n\n/**\n * What the last `onQueryChange` reported: the effective sort it carried,\n * and the sort the grid itself held at that moment.\n */\nexport interface BillSortEcho {\n key: string;\n raw: readonly BillTableSortEntry[];\n}\n\n/**\n * The sorting to hand the inner DataGrid when the host controls `query`.\n *\n * Under privacy mode `onQueryChange` reports the EFFECTIVE sort: a\n * counterparty sort is paused, so it is left out. A host that stores that\n * query and passes it back would erase the paused entry, which then could\n * not come back when privacy mode turns off, and the grid would report the\n * same query a second time. So while the host's sorting is exactly what\n * BillTable last reported, the grid keeps the sort it holds itself. Any\n * other sorting is a host decision and wins.\n */\nexport function resolveControlledSorting(\n hostSorting: readonly BillTableSortEntry[],\n echo: BillSortEcho | null,\n): readonly BillTableSortEntry[] {\n if (echo && sortKey(hostSorting) === echo.key) return echo.raw;\n return hostSorting;\n}\n\n/* ================================================================== */\n/* Row actions */\n/* ================================================================== */\n\n/** The host callbacks behind the row actions. */\nexport type BillTableCallbacks = Pick<\n BillTableProps,\n | 'onOpen'\n | 'onDownload'\n | 'onLoadIntoWarehouse'\n | 'onEdit'\n | 'onRecordPayment'\n | 'onWriteOff'\n | 'onDelete'\n>;\n\n/** The callback each action needs: an action shows only when the row's\n * map lists it AND this callback is set. */\nexport const BILL_ACTION_CALLBACK: Readonly<\n Record<BillRowActionId, keyof BillTableCallbacks>\n> = {\n open: 'onOpen',\n downloadPdf: 'onDownload',\n downloadXml: 'onDownload',\n loadIntoWarehouse: 'onLoadIntoWarehouse',\n edit: 'onEdit',\n recordPayment: 'onRecordPayment',\n writeOff: 'onWriteOff',\n undoWriteOff: 'onWriteOff',\n delete: 'onDelete',\n};\n\nexport function hasActionCallback(\n callbacks: BillTableCallbacks,\n action: BillRowActionId,\n): boolean {\n return typeof callbacks[BILL_ACTION_CALLBACK[action]] === 'function';\n}\n\n/** The kit reason code of a disabled action, or `'host'` for a host's own\n * text. Never the host text itself: it may name a person. */\nexport function disabledReasonCode(\n state: Exclude<BillRowActionState, 'enabled'>,\n): BillActionDisabledReason | 'host' {\n return typeof state.disabled === 'string' ? state.disabled : 'host';\n}\n\n/**\n * The actions the table offers for one row, as the HOST reads them:\n * entries of `row.actions` whose callback is set, in menu order. Under\n * privacy mode every host's own disabled text gives way to\n * `hiddenReasonText` (kit copy), whatever the counterparty kind: the kit\n * cannot tell whether a text names someone. Kit reason codes stay. Agents\n * never read this; they read `summariseActions`.\n */\nexport function offeredActions(\n row: BillRow,\n callbacks: BillTableCallbacks,\n privacyMode: boolean,\n hiddenReasonText: string,\n): BillRowActionMap {\n const offered: BillRowActionMap = {};\n for (const action of BILL_ROW_ACTIONS) {\n const state = row.actions[action];\n if (state === undefined || !hasActionCallback(callbacks, action)) continue;\n offered[action] =\n privacyMode && state !== 'enabled' && typeof state.disabled !== 'string'\n ? { disabled: { text: hiddenReasonText } }\n : state;\n }\n return offered;\n}\n\n/**\n * The actions the table offers for one row, as an AGENT reads them: the\n * same entries as `offeredActions`, with every disabled reason as its code.\n * A host's own text is always `'host'`, privacy mode or not, since it may\n * name a person (agent state carries no PHI, `src/agent/types.ts`).\n */\nexport function summariseActions(\n row: BillRow,\n callbacks: BillTableCallbacks,\n): BillRowActionSummaryMap {\n const offered: BillRowActionSummaryMap = {};\n for (const action of BILL_ROW_ACTIONS) {\n const state = row.actions[action];\n if (state === undefined || !hasActionCallback(callbacks, action)) continue;\n offered[action] =\n state === 'enabled' ? 'enabled' : { disabled: disabledReasonCode(state) };\n }\n return offered;\n}\n\n/**\n * One bill as an agent may read it. The counterparty name is given for a\n * company only: a patient's or another person's name is never in agent\n * state, privacy mode or not (`src/agent/types.ts`, state slots carry no\n * PHI). Disabled reasons are codes only, never a host's text.\n */\nexport function summariseBillRow(\n row: BillRow,\n callbacks: BillTableCallbacks,\n): BillRowSummary {\n const summary: BillRowSummary = {\n id: row.id,\n number: row.number,\n type: row.type,\n date: row.date,\n direction: row.direction,\n counterpartyKind: row.counterparty?.kind ?? null,\n amountMinor: row.amountMinor,\n paymentStatus: row.paymentStatus,\n sdiStatus: row.sdiStatus,\n warehouseStatus: row.warehouseStatus ?? null,\n actions: summariseActions(row, callbacks),\n };\n if (row.counterparty?.kind === 'company') {\n summary.counterpartyName = row.counterparty.name;\n }\n return summary;\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: closed enums to badge variant and copy. */\n/* */\n/* One map per enum. Every key is a literal string and the maps are */\n/* `as const`, so `t(MAP[value].key, MAP[value].en)` resolves to the */\n/* finite set of keys for the i18n inventory check, and the English */\n/* default sits next to its key. Badge colours are Michael's decisions */\n/* (4 Nov 2026) and design-bill-table.md section 1.2. */\n/* -------------------------------------------------------------------- */\n\nimport type {\n BillActionDisabledReason,\n BillDirection,\n BillListDownloadKind,\n BillPaymentStatus,\n BillRowActionId,\n BillSdiStatus,\n BillType,\n BillWarehouseStatus,\n} from './types';\n\n/** The Badge variants BillTable uses. */\nexport type BillBadgeVariant =\n | 'neutral'\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\ninterface BillCopy {\n readonly key: string;\n readonly en: string;\n}\n\ninterface BillStatusCopy extends BillCopy {\n readonly variant: BillBadgeVariant;\n}\n\n/** Every row action but `open`: the bill number is the open control, so\n * `open` is never a menu item. */\nexport type BillMenuActionId = Exclude<BillRowActionId, 'open'>;\n\n/** Payment status. `unpaid` is warning because the platform paints \"Da\n * incassare / Da pagare\" `text-warning` today; `overdue` is error. */\nexport const BILL_PAYMENT_STATUS_COPY = {\n paid: { key: 'billTable.paymentStatus.paid', en: 'Paid', variant: 'success' },\n partiallyPaid: {\n key: 'billTable.paymentStatus.partiallyPaid',\n en: 'Partly paid',\n variant: 'warning',\n },\n unpaid: {\n key: 'billTable.paymentStatus.unpaid',\n en: 'Unpaid',\n variant: 'warning',\n },\n overdue: {\n key: 'billTable.paymentStatus.overdue',\n en: 'Overdue',\n variant: 'error',\n },\n writtenOff: {\n key: 'billTable.paymentStatus.writtenOff',\n en: 'Written off',\n variant: 'neutral',\n },\n noPaymentDue: {\n key: 'billTable.paymentStatus.noPaymentDue',\n en: 'No payment due',\n variant: 'neutral',\n },\n} as const satisfies Record<BillPaymentStatus, BillStatusCopy>;\n\n/** SDI status. `notApplicable` has no entry: it renders an empty cell and\n * is not a filter option. `notDelivered` is warning, not error: the\n * invoice is legally issued and needs a follow-up, not a resend. */\nexport const BILL_SDI_STATUS_COPY = {\n notSent: {\n key: 'billTable.sdiStatus.notSent',\n en: 'Not sent',\n variant: 'neutral',\n },\n sending: {\n key: 'billTable.sdiStatus.sending',\n en: 'Sending',\n variant: 'info',\n },\n pending: {\n key: 'billTable.sdiStatus.pending',\n en: 'Awaiting SDI',\n variant: 'warning',\n },\n accepted: {\n key: 'billTable.sdiStatus.accepted',\n en: 'Accepted',\n variant: 'success',\n },\n delivered: {\n key: 'billTable.sdiStatus.delivered',\n en: 'Delivered',\n variant: 'success',\n },\n notDelivered: {\n key: 'billTable.sdiStatus.notDelivered',\n en: 'Not delivered',\n variant: 'warning',\n },\n rejected: {\n key: 'billTable.sdiStatus.rejected',\n en: 'Rejected',\n variant: 'error',\n },\n received: {\n key: 'billTable.sdiStatus.received',\n en: 'Received from SDI',\n variant: 'info',\n },\n} as const satisfies Record<\n Exclude<BillSdiStatus, 'notApplicable'>,\n BillStatusCopy\n>;\n\n/** Warehouse status: Not loaded neutral, To review warning, Loaded success\n * (Michael, 4 Nov 2026). */\nexport const BILL_WAREHOUSE_STATUS_COPY = {\n notLoaded: {\n key: 'billTable.warehouseStatus.notLoaded',\n en: 'Not loaded',\n variant: 'neutral',\n },\n toReview: {\n key: 'billTable.warehouseStatus.toReview',\n en: 'To review',\n variant: 'warning',\n },\n loaded: {\n key: 'billTable.warehouseStatus.loaded',\n en: 'Loaded',\n variant: 'success',\n },\n} as const satisfies Record<BillWarehouseStatus, BillStatusCopy>;\n\nexport const BILL_DIRECTION_COPY = {\n incoming: { key: 'billTable.direction.incoming', en: 'Incoming' },\n outgoing: { key: 'billTable.direction.outgoing', en: 'Outgoing' },\n} as const satisfies Record<BillDirection, BillCopy>;\n\n/** The muted line under the bill number. A final bill (`full`) shows no\n * line, so it has no entry. */\nexport const BILL_TYPE_COPY = {\n partial: { key: 'billTable.type.partial', en: 'Deposit' },\n credit: { key: 'billTable.type.credit', en: 'Credit note' },\n proforma: { key: 'billTable.type.proforma', en: 'Pro forma' },\n other: { key: 'billTable.type.other', en: 'Other document' },\n} as const satisfies Record<Exclude<BillType, 'full'>, BillCopy>;\n\n/** Row-menu items, in menu order (design section 3.6). */\nexport const BILL_ACTION_COPY = {\n downloadPdf: { key: 'billTable.action.downloadPdf', en: 'Download PDF' },\n downloadXml: { key: 'billTable.action.downloadXml', en: 'Download XML' },\n loadIntoWarehouse: {\n key: 'billTable.action.loadIntoWarehouse',\n en: 'Load into warehouse',\n },\n edit: { key: 'billTable.action.edit', en: 'Edit' },\n recordPayment: {\n key: 'billTable.action.recordPayment',\n en: 'Record payment',\n },\n writeOff: {\n key: 'billTable.action.writeOff',\n en: 'Write off the unpaid amount',\n },\n undoWriteOff: { key: 'billTable.action.undoWriteOff', en: 'Undo write-off' },\n delete: { key: 'billTable.action.delete', en: 'Delete' },\n} as const satisfies Record<BillMenuActionId, BillCopy>;\n\n/** Kit-owned reasons for a disabled action, so the copy exists in every\n * language. */\nexport const BILL_DISABLED_REASON_COPY = {\n alreadyLoaded: {\n key: 'billTable.disabledReason.alreadyLoaded',\n en: 'This bill is already in the warehouse.',\n },\n sentToSdi: {\n key: 'billTable.disabledReason.sentToSdi',\n en: 'This bill was sent to SDI, so it cannot be changed.',\n },\n legalStorage: {\n key: 'billTable.disabledReason.legalStorage',\n en: 'This bill is in legal storage, so it cannot be changed.',\n },\n paymentAutomation: {\n key: 'billTable.disabledReason.paymentAutomation',\n en: 'This bill has automatic payments, so it cannot be changed.',\n },\n noPermission: {\n key: 'billTable.disabledReason.noPermission',\n en: 'You do not have permission to do this.',\n },\n inProgress: {\n key: 'billTable.disabledReason.inProgress',\n en: 'Already in progress.',\n },\n} as const satisfies Record<BillActionDisabledReason, BillCopy>;\n\n/** List downloads in the toolbar's download menu. */\nexport const BILL_LIST_DOWNLOAD_COPY = {\n csv: { key: 'billTable.export.csv', en: 'CSV' },\n csvDetailed: {\n key: 'billTable.export.csvDetailed',\n en: 'CSV with treatments',\n },\n pdfZip: { key: 'billTable.export.pdfZip', en: 'ZIP with one PDF per bill' },\n pdfSingle: { key: 'billTable.export.pdfSingle', en: 'One PDF' },\n xmlOutgoingZip: {\n key: 'billTable.export.xmlOutgoingZip',\n en: 'ZIP of sent electronic invoices (XML)',\n },\n xmlIncomingZip: {\n key: 'billTable.export.xmlIncomingZip',\n en: 'ZIP of electronic invoices received from SDI (XML)',\n },\n} as const satisfies Record<BillListDownloadKind, BillCopy>;\n","/* -------------------------------------------------------------------- */\n/* BillTable: what each cell and footer cell shows. */\n/* */\n/* Always rendered inside the BillTable root, which carries the bounding */\n/* marker, through its DataGrid, which renders the table sections and the */\n/* cells around them. Kit leaves only (Badge, Money, Button, IconButton, */\n/* InfoTip, Popover, VisuallyHidden); no row datum goes into an */\n/* attribute: names are text, */\n/* and controls are named by reference. */\n/* -------------------------------------------------------------------- */\n\nimport { useId } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { ArrowDownLeft, ArrowUpRight, Info } from 'lucide-react';\n\nimport { Badge } from '../badge/badge';\nimport { Button } from '../button/button';\nimport { IconButton } from '../button/icon-button';\nimport { InfoTip } from '../info-tip/info-tip';\nimport { Money } from '../money/money';\nimport { Popover } from '../popover/popover';\nimport { VisuallyHidden } from '../visually-hidden/visually-hidden';\nimport { accessibleTargetSquareClass } from '../_shared/accessible-target';\nimport { formatNumber } from '../_shared/format-number';\nimport {\n breakdownGroupVariants,\n breakdownListVariants,\n breakdownTermVariants,\n breakdownTextVariants,\n breakdownValueVariants,\n breakdownVariants,\n cellStackVariants,\n directionIconVariants,\n inlineGroupVariants,\n numberTextVariants,\n openButtonVariants,\n secondaryTextVariants,\n truncatedTextVariants,\n} from './bill-table.variants';\nimport { BILL_AMOUNT_SCALE, formatCalendarDay } from './model';\nimport {\n BILL_DIRECTION_COPY,\n BILL_DISABLED_REASON_COPY,\n BILL_PAYMENT_STATUS_COPY,\n BILL_SDI_STATUS_COPY,\n BILL_TYPE_COPY,\n BILL_WAREHOUSE_STATUS_COPY,\n type BillBadgeVariant,\n} from './status-maps';\nimport {\n BILL_DIRECTIONS,\n type BillCounterparty,\n type BillDirection,\n type BillPaymentStatus,\n type BillRow,\n type BillSdiStatus,\n type BillTableTotals,\n type BillWarehouseStatus,\n} from './types';\n\n/* ================================================================== */\n/* Number: the row header and the open control */\n/* ================================================================== */\n\nexport interface OpenBillCellProps {\n row: BillRow;\n /** Id of the static hidden \"Open bill\" text the table renders once. */\n openHintId: string;\n onOpen: (row: BillRow) => void;\n /** Privacy mode is on: a host's own disabled text gives way to kit copy,\n * whatever the counterparty (the kit cannot tell whether it names\n * someone). */\n hideHostText: boolean;\n}\n\n/**\n * The bill number. It names the row (the column is the row header) and is\n * the open control: a link-styled kit Button whose accessible name is the\n * visible number, so the row reads \"A12\", with the static \"Open bill\" as\n * its description. With no `open` in the row's map it is plain text. A\n * disabled `open` stays focusable and adds its reason to the description.\n * Non-final bills show their type on a muted second line.\n */\nexport function OpenBillCell({\n row,\n openHintId,\n onOpen,\n hideHostText,\n}: OpenBillCellProps) {\n const { t } = useTranslation('ui');\n const reasonId = useId();\n const state = row.actions.open;\n\n let typeLine: string | null = null;\n if (row.type !== 'full') {\n const copy = BILL_TYPE_COPY[row.type];\n typeLine = t(copy.key, copy.en);\n }\n\n let reason: string | null = null;\n if (state !== undefined && state !== 'enabled') {\n if (typeof state.disabled === 'string') {\n const copy = BILL_DISABLED_REASON_COPY[state.disabled];\n reason = t(copy.key, copy.en);\n } else {\n reason = hideHostText\n ? t(\n 'billTable.disabledReason.privacyHidden',\n 'Not available (reason hidden in privacy mode)',\n )\n : state.disabled.text;\n }\n }\n\n return (\n <span className={cellStackVariants()}>\n {state === undefined ? (\n <span className={numberTextVariants()}>{row.number}</span>\n ) : (\n <Button\n intent=\"link\"\n size=\"sm\"\n className={openButtonVariants()}\n aria-describedby={reason ? `${openHintId} ${reasonId}` : openHintId}\n // Not the HTML attribute: the button stays a Tab stop, so its\n // reason can be reached. The click guard below refuses it.\n aria-disabled={reason ? true : undefined}\n onClick={(event) => {\n if (reason) {\n event.preventDefault();\n return;\n }\n onOpen(row);\n }}\n >\n {row.number}\n </Button>\n )}\n {reason ? (\n <span hidden id={reasonId}>\n {reason}\n </span>\n ) : null}\n {typeLine ? (\n <span className={secondaryTextVariants()}>{typeLine}</span>\n ) : null}\n </span>\n );\n}\n\n/* ================================================================== */\n/* Date, direction, counterparty */\n/* ================================================================== */\n\n/** A calendar day in the UI language, read in UTC so it never shifts. */\nexport function CalendarDayCell({ day }: { day: string }) {\n const { i18n } = useTranslation('ui');\n return <span>{formatCalendarDay(day, i18n.language)}</span>;\n}\n\n/** The direction arrow, decorative (the label is always beside it). */\nexport function DirectionIcon({ direction }: { direction: BillDirection }) {\n const Icon = direction === 'incoming' ? ArrowDownLeft : ArrowUpRight;\n return <Icon aria-hidden=\"true\" className={directionIconVariants()} />;\n}\n\n/** Arrow and visible label: \"Incoming\" or \"Outgoing\". */\nexport function DirectionLabel({ direction }: { direction: BillDirection }) {\n const { t } = useTranslation('ui');\n const copy = BILL_DIRECTION_COPY[direction];\n return (\n <span className={inlineGroupVariants()}>\n <DirectionIcon direction={direction} />\n <span>{t(copy.key, copy.en)}</span>\n </span>\n );\n}\n\n/**\n * The counterparty's name, in its own text direction and truncated with\n * the full text in the DOM; a muted \"Deleted\" line for a deleted entity.\n * Never rendered for a masked cell: under privacy mode DataGrid shows the\n * mask for patients and people instead of calling the column's `cell`.\n */\nexport function CounterpartyCell({\n counterparty,\n}: {\n counterparty: BillCounterparty | null;\n}) {\n const { t } = useTranslation('ui');\n if (counterparty === null) {\n return (\n <span className={secondaryTextVariants()}>\n {t('billTable.counterparty.none', 'No counterparty')}\n </span>\n );\n }\n return (\n <span className={cellStackVariants()}>\n <span dir=\"auto\" className={truncatedTextVariants()}>\n {counterparty.name}\n </span>\n {counterparty.deleted ? (\n <span className={secondaryTextVariants()}>\n {t('billTable.counterparty.deleted', 'Deleted')}\n </span>\n ) : null}\n </span>\n );\n}\n\n/**\n * An amount in hundredths, in the table currency. Money's default tone: a\n * credit note is negative as stored and reads as a minus sign, not as an\n * alarm. `scale` keeps Money on its exact integer path.\n */\nexport function AmountCell({\n amountMinor,\n currency,\n}: {\n amountMinor: number;\n currency: string;\n}) {\n return (\n <Money\n size=\"sm\"\n value={amountMinor}\n currency={currency}\n scale={BILL_AMOUNT_SCALE}\n />\n );\n}\n\n/* ================================================================== */\n/* Statuses */\n/* ================================================================== */\n\n/** A status as text with a decorative dot: never colour alone. */\nfunction StatusBadge({\n label,\n variant,\n}: {\n label: string;\n variant: BillBadgeVariant;\n}) {\n return (\n <Badge size=\"sm\" variant={variant} withDot>\n {label}\n </Badge>\n );\n}\n\n/** Statuses that still have money to settle: they show the next due day. */\nconst DUE_STATUSES = new Set<BillPaymentStatus>([\n 'unpaid',\n 'partiallyPaid',\n 'overdue',\n]);\n\nexport function PaymentStatusCell({\n status,\n nextDueDate,\n}: {\n status: BillPaymentStatus;\n nextDueDate: string | null;\n}) {\n const { t, i18n } = useTranslation('ui');\n const copy = BILL_PAYMENT_STATUS_COPY[status];\n return (\n <span className={cellStackVariants()}>\n <StatusBadge label={t(copy.key, copy.en)} variant={copy.variant} />\n {nextDueDate && DUE_STATUSES.has(status) ? (\n <span className={secondaryTextVariants()}>\n {t('billTable.paymentStatus.due', 'Due {{date}}', {\n date: formatCalendarDay(nextDueDate, i18n.language),\n })}\n </span>\n ) : null}\n </span>\n );\n}\n\n/** Empty for `notApplicable` (not an Italian electronic invoice). */\nexport function SdiStatusCell({ status }: { status: BillSdiStatus }) {\n const { t } = useTranslation('ui');\n if (status === 'notApplicable') return null;\n const copy = BILL_SDI_STATUS_COPY[status];\n return <StatusBadge label={t(copy.key, copy.en)} variant={copy.variant} />;\n}\n\n/** Empty for `null` (not an incoming SDI bill, or no warehouse module). */\nexport function WarehouseStatusCell({\n status,\n}: {\n status: BillWarehouseStatus | null;\n}) {\n const { t } = useTranslation('ui');\n if (status === null) return null;\n const copy = BILL_WAREHOUSE_STATUS_COPY[status];\n return <StatusBadge label={t(copy.key, copy.en)} variant={copy.variant} />;\n}\n\n/** The InfoTip beside the \"SDI status\" header, outside its sort button. */\nexport function SdiHeaderTip() {\n const { t } = useTranslation('ui');\n return (\n <InfoTip\n size=\"sm\"\n content={t(\n 'billTable.sdiHelp',\n 'SDI is the Italian exchange system for electronic invoices.',\n )}\n />\n );\n}\n\n/* ================================================================== */\n/* Totals row */\n/* ================================================================== */\n\n/** One label and amount pair of the breakdown. */\nfunction BreakdownEntry({\n label,\n value,\n currency,\n}: {\n label: string;\n value: number;\n currency: string;\n}) {\n return (\n <>\n <dt className={breakdownTermVariants()}>{label}</dt>\n <dd className={breakdownValueVariants()}>\n <Money\n size=\"sm\"\n value={value}\n currency={currency}\n scale={BILL_AMOUNT_SCALE}\n />\n </dd>\n </>\n );\n}\n\n/** Today's six sums and the count, per present direction, as given by the\n * server. The kit adds, subtracts and rounds nothing. */\nfunction TotalsBreakdown({\n totals,\n currency,\n}: {\n totals: BillTableTotals;\n currency: string;\n}) {\n const { t, i18n } = useTranslation('ui');\n return (\n <div className={breakdownVariants()}>\n {BILL_DIRECTIONS.map((direction) => {\n const sums = totals[direction];\n if (!sums) return null;\n return (\n <div key={direction} className={breakdownGroupVariants()}>\n <p className={breakdownTextVariants({ tone: 'strong' })}>\n <DirectionLabel direction={direction} />\n <span>\n {t('billTable.totals.count', '{{formatted}} bills', {\n count: sums.count,\n formatted: formatNumber(sums.count, i18n.language),\n })}\n </span>\n </p>\n <dl className={breakdownListVariants()}>\n <BreakdownEntry\n label={t('billTable.totals.gross', 'Gross')}\n value={sums.grossMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.net', 'Net')}\n value={sums.netMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.vat', 'VAT')}\n value={sums.vatMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.taxAtSource', 'Withholding tax')}\n value={sums.taxAtSourceMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.paid', 'Paid')}\n value={sums.paidMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.unpaid', 'Unpaid')}\n value={sums.unpaidMinor}\n currency={currency}\n />\n </dl>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * The totals row header (`<th scope=\"row\">`): \"Total\" and a \"Totals\n * breakdown\" button that opens a kit Popover in click mode: a dialog\n * named by its heading, with the scope note as its description and every\n * sum per direction. Focus moves into the dialog on open, so a screen\n * reader user reaches the sums; Escape closes it and returns focus to the\n * button. The table does not widen.\n */\nexport function TotalsHeaderCell({\n totals,\n currency,\n}: {\n totals: BillTableTotals;\n currency: string;\n}) {\n const { t } = useTranslation('ui');\n const breakdown = t('billTable.totals.breakdown', 'Totals breakdown');\n return (\n <span className={inlineGroupVariants()}>\n <span>{t('dataTable.totalRow', 'Total')}</span>\n <Popover>\n <Popover.Trigger asChild>\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={<Info aria-hidden=\"true\" />}\n aria-label={breakdown}\n className={accessibleTargetSquareClass}\n />\n </Popover.Trigger>\n <Popover.Content side=\"top\" align=\"start\" size=\"md\">\n <Popover.Heading>{breakdown}</Popover.Heading>\n <Popover.Description>\n {t(\n 'billTable.totals.scope',\n 'Every bill that matches the filters, on all pages.',\n )}\n </Popover.Description>\n <TotalsBreakdown totals={totals} currency={currency} />\n </Popover.Content>\n </Popover>\n </span>\n );\n}\n\n/**\n * One line per present direction, as the server gave it (all pages, never\n * mixed: a sum of costs and revenue means nothing). The amount column\n * shows the gross with the direction label; the payment column shows what\n * is still unpaid, its direction named for screen readers and drawn by the\n * same arrow as the amount line beside it.\n */\nexport function DirectionTotalsCell({\n totals,\n field,\n currency,\n}: {\n totals: BillTableTotals;\n field: 'grossMinor' | 'unpaidMinor';\n currency: string;\n}) {\n const { t } = useTranslation('ui');\n return (\n <span\n className={cellStackVariants({\n align: field === 'grossMinor' ? 'end' : 'start',\n })}\n >\n {BILL_DIRECTIONS.map((direction) => {\n const sums = totals[direction];\n if (!sums) return null;\n const copy = BILL_DIRECTION_COPY[direction];\n const directionText = t(copy.key, copy.en);\n return (\n <span key={direction} className={inlineGroupVariants()}>\n <DirectionIcon direction={direction} />\n {field === 'grossMinor' ? (\n <span>{directionText}</span>\n ) : (\n <>\n <VisuallyHidden>{directionText}</VisuallyHidden>\n <span>{t('billTable.totals.unpaid', 'Unpaid')}</span>\n </>\n )}\n <Money\n size=\"sm\"\n value={sums[field]}\n currency={currency}\n scale={BILL_AMOUNT_SCALE}\n />\n </span>\n );\n })}\n </span>\n );\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: the column definitions on the DataGrid column API. */\n/* */\n/* Reading copy: design-bill-table.md section 2. Widths are the initial */\n/* px (`size` puts the grid in fixed layout); tiers show a column from */\n/* 640, 900 or 1,200 px of grid width, and a user's own choice in */\n/* ColumnToggle always wins. Every cell renders inside the BillTable root */\n/* through its DataGrid; only `row.id` reaches the DOM (`data-row-id`). */\n/* -------------------------------------------------------------------- */\n\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { DataGridColumn, DataGridOption } from '../data-grid/types';\nimport type { NumberFilterOperator } from '../_shared/table-toolbar/seam';\nimport { RowActions, type RowActionDef } from '../row-actions/row-actions';\nimport { VisuallyHidden } from '../visually-hidden/visually-hidden';\nimport {\n AmountCell,\n CalendarDayCell,\n CounterpartyCell,\n DirectionLabel,\n DirectionTotalsCell,\n OpenBillCell,\n PaymentStatusCell,\n SdiHeaderTip,\n SdiStatusCell,\n TotalsHeaderCell,\n WarehouseStatusCell,\n} from './cells';\nimport { amountForExport, isPersonCounterparty } from './model';\nimport {\n BILL_DIRECTION_COPY,\n BILL_PAYMENT_STATUS_COPY,\n BILL_SDI_STATUS_COPY,\n BILL_WAREHOUSE_STATUS_COPY,\n} from './status-maps';\nimport {\n BILL_DIRECTIONS,\n BILL_PAYMENT_STATUSES,\n BILL_SDI_STATUSES,\n BILL_WAREHOUSE_STATUSES,\n type BillDirection,\n type BillPaymentStatus,\n type BillRow,\n type BillSdiStatus,\n type BillTableSortColumn,\n type BillTableTotals,\n type BillWarehouseStatus,\n} from './types';\n\n/** The amount filter's conditions; `inRange` first, as the platform form\n * (`amount_from` / `amount_to`). Bounds are major units, as typed. */\nconst AMOUNT_FILTER_OPERATORS: readonly NumberFilterOperator[] = [\n 'inRange',\n 'greaterThanOrEqual',\n 'lessThanOrEqual',\n 'equals',\n];\n\ntype BillSdiFilterStatus = Exclude<BillSdiStatus, 'notApplicable'>;\n\n/** SDI filter values: every status but `notApplicable`, which renders an\n * empty cell and is not something to filter by. */\nconst SDI_FILTER_STATUSES: readonly BillSdiFilterStatus[] =\n BILL_SDI_STATUSES.filter(\n (status): status is BillSdiFilterStatus => status !== 'notApplicable',\n );\n\nexport interface UseBillTableColumnsOptions {\n /** ISO 4217, for every amount and the amount filter. */\n currency: string;\n showWarehouseStatus: boolean;\n sortableColumns: readonly BillTableSortColumn[];\n /** Absent: no totals row (no column gets a footer). */\n totals: BillTableTotals | null;\n privacyMode: boolean;\n /** Id of the static hidden \"Open bill\" text. */\n openHintId: string;\n /** Stable; calls the host's `onOpen` with `source: 'user'`. */\n onOpenRow: (row: BillRow) => void;\n /** Stable kit RowActions definitions (`useBillRowActions`). */\n rowActions: readonly RowActionDef<BillRow>[];\n}\n\n/** BillTable's DataGrid columns, rebuilt only when an input changes. */\nexport function useBillTableColumns({\n currency,\n showWarehouseStatus,\n sortableColumns,\n totals,\n privacyMode,\n openHintId,\n onOpenRow,\n rowActions,\n}: UseBillTableColumnsOptions): DataGridColumn<BillRow>[] {\n const { t } = useTranslation('ui');\n // A host may pass a new array each render; the set of columns is what\n // matters.\n const sortableKey = sortableColumns.join('|');\n\n return useMemo(() => {\n const sortable = new Set(sortableKey.split('|'));\n\n const directionLabel = (direction: BillDirection): string => {\n const copy = BILL_DIRECTION_COPY[direction];\n return t(copy.key, copy.en);\n };\n const paymentLabel = (status: BillPaymentStatus): string => {\n const copy = BILL_PAYMENT_STATUS_COPY[status];\n return t(copy.key, copy.en);\n };\n const sdiLabel = (status: BillSdiFilterStatus): string => {\n const copy = BILL_SDI_STATUS_COPY[status];\n return t(copy.key, copy.en);\n };\n const warehouseLabel = (status: BillWarehouseStatus): string => {\n const copy = BILL_WAREHOUSE_STATUS_COPY[status];\n return t(copy.key, copy.en);\n };\n // Select filters in server mode need their options (a page cannot\n // derive them). Values are the enum values, never labels.\n const options = <TValue extends string>(\n values: readonly TValue[],\n label: (value: TValue) => string,\n ): DataGridOption[] =>\n values.map((value) => ({ value, label: label(value) }));\n\n const actionsLabel = t('dataTable.actions', 'Actions');\n\n const columns: DataGridColumn<BillRow>[] = [\n {\n id: 'number',\n header: t('billTable.column.number', 'Number'),\n // The number names the row: `<th scope=\"row\">`, \"Select A12\",\n // \"Actions, A12\". Pinned at the inline start, always shown.\n rowHeader: true,\n pin: 'start',\n hideable: false,\n reorderable: false,\n pinnable: false,\n size: 136,\n minSize: 112,\n value: (row) => row.number,\n exportValue: (row) => row.number,\n sort: sortable.has('number') ? 'text' : undefined,\n cell: (row) => (\n <OpenBillCell\n row={row}\n openHintId={openHintId}\n onOpen={onOpenRow}\n hideHostText={privacyMode}\n />\n ),\n footer: totals ? (\n <TotalsHeaderCell totals={totals} currency={currency} />\n ) : undefined,\n },\n {\n id: 'date',\n header: t('billTable.column.date', 'Date'),\n size: 120,\n responsiveTier: 1,\n // A calendar day `YYYY-MM-DD`; DataGrid formats it for export.\n value: (row) => row.date,\n sort: sortable.has('date') ? 'date' : undefined,\n sortDescFirst: true,\n // One request per range: the server filters on Apply.\n filter: { kind: 'dateRange', commitMode: 'apply' },\n search: false,\n cell: (row) => <CalendarDayCell day={row.date} />,\n },\n {\n id: 'direction',\n header: t('billTable.column.direction', 'Direction'),\n size: 132,\n responsiveTier: 1,\n value: (row) => row.direction,\n exportValue: (row) => directionLabel(row.direction),\n filter: {\n kind: 'select',\n options: options(BILL_DIRECTIONS, directionLabel),\n },\n search: false,\n cell: (row) => <DirectionLabel direction={row.direction} />,\n },\n {\n id: 'counterparty',\n header: t('billTable.column.counterparty', 'Counterparty'),\n size: 240,\n minSize: 160,\n value: (row) => row.counterparty?.name ?? null,\n // Off while privacy mode is on: the whole column leaves sorting and\n // the server query (DataGrid's whole-column privacy rule).\n sort: sortable.has('counterparty') ? 'text' : undefined,\n // Patients and other people are masked; companies stay visible.\n privacy: { mode: 'mask', appliesTo: isPersonCounterparty },\n cell: (row) => <CounterpartyCell counterparty={row.counterparty} />,\n },\n {\n id: 'amount',\n header: t('billTable.column.amount', 'Amount'),\n align: 'end',\n size: 136,\n value: (row) => row.amountMinor,\n exportValue: (row) => amountForExport(row.amountMinor),\n sort: sortable.has('amount') ? 'number' : undefined,\n sortDescFirst: true,\n // A currency NumberInput in the table currency. Bounds are MAJOR\n // units as typed (12.50), like the platform's amount_from/_to;\n // the server converts. Rows carry minor units.\n filter: {\n kind: 'number',\n mode: 'currency',\n currency,\n operators: AMOUNT_FILTER_OPERATORS,\n defaultOperator: 'inRange',\n },\n search: false,\n cell: (row) => (\n <AmountCell amountMinor={row.amountMinor} currency={currency} />\n ),\n footer: totals ? (\n <DirectionTotalsCell\n totals={totals}\n field=\"grossMinor\"\n currency={currency}\n />\n ) : undefined,\n },\n {\n id: 'paymentStatus',\n header: t('billTable.column.paymentStatus', 'Payment status'),\n size: 168,\n responsiveTier: 2,\n value: (row) => row.paymentStatus,\n exportValue: (row) => paymentLabel(row.paymentStatus),\n filter: {\n kind: 'select',\n options: options(BILL_PAYMENT_STATUSES, paymentLabel),\n },\n search: false,\n cell: (row) => (\n <PaymentStatusCell\n status={row.paymentStatus}\n nextDueDate={row.nextDueDate ?? null}\n />\n ),\n footer: totals ? (\n <DirectionTotalsCell\n totals={totals}\n field=\"unpaidMinor\"\n currency={currency}\n />\n ) : undefined,\n },\n {\n id: 'sdiStatus',\n header: t('billTable.column.sdiStatus', 'SDI status'),\n headerTip: <SdiHeaderTip />,\n size: 168,\n responsiveTier: 3,\n value: (row) =>\n row.sdiStatus === 'notApplicable' ? null : row.sdiStatus,\n exportValue: (row) =>\n row.sdiStatus === 'notApplicable' ? '' : sdiLabel(row.sdiStatus),\n filter: {\n kind: 'select',\n options: options(SDI_FILTER_STATUSES, sdiLabel),\n },\n search: false,\n cell: (row) => <SdiStatusCell status={row.sdiStatus} />,\n },\n ];\n\n if (showWarehouseStatus) {\n columns.push({\n id: 'warehouseStatus',\n header: t('billTable.column.warehouseStatus', 'Warehouse status'),\n size: 152,\n responsiveTier: 2,\n value: (row) => row.warehouseStatus ?? null,\n exportValue: (row) =>\n row.warehouseStatus ? warehouseLabel(row.warehouseStatus) : '',\n filter: {\n kind: 'select',\n options: options(BILL_WAREHOUSE_STATUSES, warehouseLabel),\n },\n search: false,\n cell: (row) => (\n <WarehouseStatusCell status={row.warehouseStatus ?? null} />\n ),\n });\n }\n\n columns.push({\n id: 'actions',\n header: <VisuallyHidden>{actionsLabel}</VisuallyHidden>,\n headerLabel: actionsLabel,\n pin: 'end',\n size: 64,\n hideable: false,\n reorderable: false,\n pinnable: false,\n resizable: false,\n exportable: false,\n printable: false,\n search: false,\n // Kit RowActions, menu only: one \"More actions\" button per row, the\n // group named by reference (\"Actions, A12\"), never by row data in an\n // attribute. A row that offers no menu item renders no button.\n cell: (row, context) => (\n <RowActions\n row={row}\n actions={rowActions}\n maxInline={0}\n aria-labelledby={context.inputLabelledBy}\n />\n ),\n });\n\n return columns;\n }, [\n t,\n currency,\n showWarehouseStatus,\n sortableKey,\n totals,\n privacyMode,\n openHintId,\n onOpenRow,\n rowActions,\n ]);\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: the curated handle (`ref`). */\n/* */\n/* Built over the inner DataGrid's handle and the props of the last */\n/* render. It hands out ids and kit shapes only: never the DataGrid */\n/* handle, a TanStack object, a row object or a DOM node. Reads go to the */\n/* live grid, so a read straight after a write is fresh (DataGrid's */\n/* freshness rule). Row actions call the same host callbacks as the UI, */\n/* with `source: 'api'`, after the same availability checks; a refused */\n/* call throws an Error whose message starts with its code. */\n/* -------------------------------------------------------------------- */\n\nimport { isDevelopment } from '../_shared/is-development';\nimport {\n DATA_GRID_DEFAULT_PAGE_SIZE,\n type DataGridHandle,\n} from '../data-grid/types';\nimport {\n API_ACTION,\n disabledReasonCode,\n hasActionCallback,\n offeredActions,\n summariseBillRow,\n toBillSortEntries,\n type BillTableCallbacks,\n} from './model';\nimport {\n BILL_TABLE_COLUMNS,\n type BillDownloadFormat,\n type BillRow,\n type BillRowActionId,\n type BillTableColumnId,\n type BillTableColumnInfo,\n type BillTableFeatureInfo,\n type BillTableFilterModel,\n type BillTableHandle,\n type BillTableQuery,\n} from './types';\n\n/** What the handle reads from the last render. */\nexport interface BillTableLive {\n /** The current page. */\n rows: readonly BillRow[];\n callbacks: BillTableCallbacks;\n features: BillTableFeatureInfo;\n /** Kit copy that stands in for every host's own disabled text under\n * privacy mode (host reads only; agent reads carry codes). */\n hiddenReasonText: string;\n}\n\ntype BillTableHandleErrorCode =\n | 'UNKNOWN_ROW'\n | 'ACTION_UNAVAILABLE'\n | 'ACTION_DISABLED';\n\nfunction refuse(code: BillTableHandleErrorCode, detail: string): never {\n throw new Error(`${code}: ${detail}`);\n}\n\nfunction warn(message: string): void {\n if (isDevelopment()) console.warn(`[BillTable] ${message}`);\n}\n\nconst COLUMN_IDS: ReadonlySet<string> = new Set(BILL_TABLE_COLUMNS);\n\nfunction isBillTableColumnId(id: string): id is BillTableColumnId {\n return COLUMN_IDS.has(id);\n}\n\n/** Ids of the columns privacy mode masks right now (the counterparty\n * while `privacyMode` is on). */\nfunction maskedColumnIds(grid: DataGridHandle): Set<string> {\n return new Set(\n grid\n .getColumns()\n .filter((column) => column.masked === true)\n .map((column) => column.id),\n );\n}\n\nexport function createBillTableHandle(\n gridRef: { readonly current: DataGridHandle | null },\n liveRef: { readonly current: BillTableLive },\n): BillTableHandle {\n const grid = (): DataGridHandle | null => gridRef.current;\n const live = (): BillTableLive => liveRef.current;\n\n function findRow(id: string): BillRow {\n const row = live().rows.find((candidate) => candidate.id === id);\n return row ?? refuse('UNKNOWN_ROW', `no bill \"${id}\" on the current page.`);\n }\n\n /** The row and callbacks for an action the row offers and allows. */\n function prepare(\n id: string,\n action: BillRowActionId,\n ): { row: BillRow; callbacks: BillTableCallbacks } {\n const row = findRow(id);\n const { callbacks } = live();\n const state = row.actions[action];\n if (state === undefined || !hasActionCallback(callbacks, action)) {\n refuse('ACTION_UNAVAILABLE', `bill \"${id}\" does not offer ${action}.`);\n }\n if (state !== 'enabled') {\n // The kit reason code, or `host`: never a host's text, which may\n // name a person.\n refuse('ACTION_DISABLED', disabledReasonCode(state));\n }\n return { row, callbacks };\n }\n\n return {\n getFeatures() {\n const { features } = live();\n return { ...features, sortableColumns: [...features.sortableColumns] };\n },\n\n /* ---- query ---- */\n\n getQuery(): BillTableQuery {\n const handle = grid();\n const { privacyMode } = live().features;\n if (!handle) {\n return {\n sorting: [],\n filters: {},\n quickFilter: '',\n pagination: { pageIndex: 0, pageSize: DATA_GRID_DEFAULT_PAGE_SIZE },\n privacyMode,\n };\n }\n // The effective query, as `onQueryChange` reports it: a masked\n // column's sort entries and filter keys are paused, not sent.\n const masked = maskedColumnIds(handle);\n const filters: Record<string, unknown> = { ...handle.getFilter() };\n for (const key of Object.keys(filters)) {\n if (masked.has(key)) delete filters[key];\n }\n return {\n sorting: toBillSortEntries(\n handle.getSort().filter((entry) => !masked.has(entry.colId)),\n ),\n filters: filters as BillTableFilterModel,\n quickFilter: handle.getQuickFilter(),\n pagination: {\n pageIndex: handle.getCurrentPage(),\n pageSize: handle.getPageSize(),\n },\n privacyMode,\n };\n },\n\n setSort(model) {\n const handle = grid();\n if (!handle) return;\n const { sortableColumns } = live().features;\n const masked = maskedColumnIds(handle);\n for (const entry of model) {\n if (!sortableColumns.includes(entry.colId)) {\n warn(`setSort: the server does not sort \"${entry.colId}\".`);\n return;\n }\n if (masked.has(entry.colId)) {\n warn(`setSort: \"${entry.colId}\" is hidden by privacy mode.`);\n return;\n }\n }\n if (model.length > 1) {\n warn('setSort: the server sorts by one column; the first one is used.');\n }\n handle.setSort(model.slice(0, 1));\n },\n\n getFilter() {\n return { ...(grid()?.getFilter() ?? {}) } as BillTableFilterModel;\n },\n\n setFilter(model, options) {\n grid()?.setFilter(model, options);\n },\n\n getQuickFilter() {\n return grid()?.getQuickFilter() ?? '';\n },\n\n setQuickFilter(text, options) {\n grid()?.setQuickFilter(text, options);\n },\n\n clearFilters() {\n grid()?.clearFilters();\n },\n\n goToPage(pageIndex) {\n grid()?.goToPage(pageIndex);\n },\n\n setPageSize(size) {\n grid()?.setPageSize(size);\n },\n\n getPageCount() {\n return grid()?.getPageCount() ?? 0;\n },\n\n getRowCount() {\n return grid()?.getRowCount() ?? 0;\n },\n\n getRowIds() {\n return grid()?.getRowIds() ?? live().rows.map((row) => row.id);\n },\n\n /* ---- selection ---- */\n\n getSelection() {\n return grid()?.getSelection() ?? [];\n },\n\n setSelection(ids) {\n grid()?.setSelection(ids);\n },\n\n selectRange(fromId, toId) {\n grid()?.selectRange(fromId, toId);\n },\n\n clearSelection() {\n grid()?.clearSelection();\n },\n\n /* ---- columns ---- */\n\n getColumns() {\n const handle = grid();\n if (!handle) return [];\n const { privacyMode } = live().features;\n const columns: BillTableColumnInfo[] = [];\n for (const column of handle.getColumns()) {\n if (!isBillTableColumnId(column.id)) continue;\n columns.push({\n id: column.id,\n label: column.label,\n visible: column.visible,\n canHide: column.canHide,\n sortable: column.sortable,\n // DataGrid reports `masked`; a missing value counts as masked\n // for the counterparty while privacy mode is on.\n masked:\n column.masked ?? (privacyMode && column.id === 'counterparty'),\n });\n }\n return columns;\n },\n\n setColumnVisible(id, visible) {\n grid()?.setColumnVisible(id, visible);\n },\n\n resetColumns() {\n grid()?.resetColumnState();\n },\n\n /* ---- focus ---- */\n\n scrollToRow(id) {\n grid()?.scrollToRow(id);\n },\n\n focusRow(id, columnId = 'number') {\n grid()?.focusRow(id, columnId);\n },\n\n /* ---- rows (agent-safe projection) ---- */\n\n getRowSummaries() {\n const { rows, callbacks } = live();\n return rows.map((row) => summariseBillRow(row, callbacks));\n },\n\n /* ---- row actions ---- */\n\n getRowActions(id) {\n const row = findRow(id);\n const { callbacks, features, hiddenReasonText } = live();\n return offeredActions(\n row,\n callbacks,\n features.privacyMode,\n hiddenReasonText,\n );\n },\n\n openBill(id) {\n const { row, callbacks } = prepare(id, 'open');\n callbacks.onOpen(row, API_ACTION);\n },\n\n downloadBill(id, format: BillDownloadFormat) {\n if (format !== 'pdf' && format !== 'xml') {\n refuse('ACTION_UNAVAILABLE', `unknown format \"${String(format)}\".`);\n }\n const { row, callbacks } = prepare(\n id,\n format === 'xml' ? 'downloadXml' : 'downloadPdf',\n );\n callbacks.onDownload?.(row, format, API_ACTION);\n },\n\n loadIntoWarehouse(id) {\n const { row, callbacks } = prepare(id, 'loadIntoWarehouse');\n callbacks.onLoadIntoWarehouse?.(row, {\n ...API_ACTION,\n warehouseStatus: row.warehouseStatus ?? null,\n });\n },\n\n /* ---- change feed ---- */\n\n subscribe(listener) {\n return grid()?.subscribe(listener) ?? (() => {});\n },\n };\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: the row menu as kit RowActions definitions. */\n/* */\n/* The actions column is the kit `RowActions` leaf with `maxInline={0}`: */\n/* one \"More actions\" button per row (one Tab stop), its menu in this */\n/* order (design section 3.6): downloads, warehouse, bill actions, then */\n/* delete in the destructive style, with a separator between the groups */\n/* (RowActions `section`). `open` is never here: the bill */\n/* number opens the bill. An action shows when the row's map lists it AND */\n/* its callback is set; a disabled one stays focusable in the menu and */\n/* shows its reason as the item's second line. BillTable composes nothing */\n/* of its own around RowActions. */\n/* -------------------------------------------------------------------- */\n\nimport { createElement, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n CircleOff,\n FileCode,\n FileText,\n HandCoins,\n PackagePlus,\n Pencil,\n Trash2,\n Undo2,\n type LucideIcon,\n} from 'lucide-react';\n\nimport type { RowActionDef } from '../row-actions/row-actions';\nimport { USER_ACTION, type BillTableCallbacks } from './model';\nimport {\n BILL_ACTION_COPY,\n BILL_DISABLED_REASON_COPY,\n type BillMenuActionId,\n} from './status-maps';\nimport type { BillRow } from './types';\n\n/** Design 3.6 menu groups. Developer constants, never row data. */\nconst BILL_ACTION_SECTION: Record<BillMenuActionId, string> = {\n downloadPdf: 'downloads',\n downloadXml: 'downloads',\n loadIntoWarehouse: 'warehouse',\n edit: 'bill',\n recordPayment: 'bill',\n writeOff: 'bill',\n undoWriteOff: 'bill',\n delete: 'delete',\n};\n\n/** Which optional callbacks the host passed. Each one adds its items. */\nexport interface BillRowActionAvailability {\n download: boolean;\n loadIntoWarehouse: boolean;\n edit: boolean;\n recordPayment: boolean;\n writeOff: boolean;\n delete: boolean;\n}\n\nexport interface UseBillRowActionsOptions {\n /** The host callbacks as of the last render, read when an item runs, so\n * a host's inline functions never rebuild the menu. */\n callbacksRef: { readonly current: BillTableCallbacks };\n available: BillRowActionAvailability;\n /** Under privacy mode every host's own disabled text gives way to kit\n * copy, whatever the counterparty: the kit cannot tell whether a text\n * names someone. */\n privacyMode: boolean;\n}\n\n/** The RowActions definitions for every row of the table. */\nexport function useBillRowActions({\n callbacksRef,\n available,\n privacyMode,\n}: UseBillRowActionsOptions): RowActionDef<BillRow>[] {\n const { t } = useTranslation('ui');\n const {\n download,\n loadIntoWarehouse,\n edit,\n recordPayment,\n writeOff,\n delete: remove,\n } = available;\n\n return useMemo(() => {\n const hiddenReason = t(\n 'billTable.disabledReason.privacyHidden',\n 'Not available (reason hidden in privacy mode)',\n );\n\n /** The translated reason of a disabled item, or `undefined`. */\n const reasonFor = (\n row: BillRow,\n action: BillMenuActionId,\n ): string | undefined => {\n const state = row.actions[action];\n if (state === undefined || state === 'enabled') return undefined;\n if (typeof state.disabled === 'string') {\n const copy = BILL_DISABLED_REASON_COPY[state.disabled];\n return t(copy.key, copy.en);\n }\n return privacyMode ? hiddenReason : state.disabled.text;\n };\n\n const item = (\n action: BillMenuActionId,\n icon: LucideIcon,\n run: (row: BillRow) => void,\n variant: 'default' | 'destructive' = 'default',\n ): RowActionDef<BillRow> => {\n const copy = BILL_ACTION_COPY[action];\n return {\n // Developer constant: React key and `data-action-id`, never row data.\n id: action,\n // Design 3.6 menu group: the menu draws a separator between groups.\n section: BILL_ACTION_SECTION[action],\n icon: createElement(icon, { 'aria-hidden': true }),\n label: t(copy.key, copy.en),\n onClick: run,\n variant,\n hidden: (row) => row.actions[action] === undefined,\n disabled: (row) => {\n const state = row.actions[action];\n return state !== undefined && state !== 'enabled';\n },\n disabledReason: (row) => reasonFor(row, action),\n };\n };\n\n const callbacks = () => callbacksRef.current;\n const items: RowActionDef<BillRow>[] = [];\n if (download) {\n items.push(\n item('downloadPdf', FileText, (row) =>\n callbacks().onDownload?.(row, 'pdf', USER_ACTION),\n ),\n item('downloadXml', FileCode, (row) =>\n callbacks().onDownload?.(row, 'xml', USER_ACTION),\n ),\n );\n }\n if (loadIntoWarehouse) {\n items.push(\n item('loadIntoWarehouse', PackagePlus, (row) =>\n callbacks().onLoadIntoWarehouse?.(row, {\n ...USER_ACTION,\n // HTP-7312 analytics: `bill_warehouse_load_clicked\n // { warehouse_status }`; `null` without the module.\n warehouseStatus: row.warehouseStatus ?? null,\n }),\n ),\n );\n }\n if (edit) {\n items.push(\n item('edit', Pencil, (row) => callbacks().onEdit?.(row, USER_ACTION)),\n );\n }\n if (recordPayment) {\n items.push(\n item('recordPayment', HandCoins, (row) =>\n callbacks().onRecordPayment?.(row, USER_ACTION),\n ),\n );\n }\n if (writeOff) {\n items.push(\n item('writeOff', CircleOff, (row) =>\n callbacks().onWriteOff?.(row, false, USER_ACTION),\n ),\n item('undoWriteOff', Undo2, (row) =>\n callbacks().onWriteOff?.(row, true, USER_ACTION),\n ),\n );\n }\n if (remove) {\n items.push(\n item(\n 'delete',\n Trash2,\n (row) => callbacks().onDelete?.(row, USER_ACTION),\n 'destructive',\n ),\n );\n }\n return items;\n }, [\n t,\n callbacksRef,\n download,\n loadIntoWarehouse,\n edit,\n recordPayment,\n writeOff,\n remove,\n privacyMode,\n ]);\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: the Accounting bills list (HTP-7312) on the kit DataGrid. */\n/* */\n/* Server mode only: the host owns the query and fetches; the kit */\n/* renders, reports one `onQueryChange` per change and never fetches. */\n/* Composes DataGrid (columns, pager, EmptyState, totals row), */\n/* DataGridToolbar parts and the kit RowActions leaf. Privacy mode hides */\n/* people (patient and person counterparties); companies stay visible. */\n/* One agent surface per table: `billTableAgent` over the curated handle; */\n/* the inner DataGrid registers none (`registerAgent={false}`). */\n/* Design: design-bill-table.md (Phase 2), decisions D1 to D20. */\n/* -------------------------------------------------------------------- */\n\nimport {\n forwardRef,\n useCallback,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { FileCode, FileText } from 'lucide-react';\n\nimport { useAgentRegistration } from '../../agent';\nimport { DataGrid } from '../data-grid/data-grid';\nimport { DataGridToolbar } from '../data-grid/toolbar';\nimport type { DataGridHandle, DataGridQuery } from '../data-grid/types';\nimport { IconButtonGroup } from '../icon-button-group/icon-button-group';\nimport { billTableAgent } from './bill-table.agent';\nimport { billTableVariants } from './bill-table.variants';\nimport { useBillTableColumns } from './columns';\nimport { createBillTableHandle, type BillTableLive } from './handle';\nimport {\n BILL_TABLE_DEFAULT_GRID_ID,\n BILL_TABLE_DEFAULT_SORT,\n BILL_TABLE_PAGE_SIZE_OPTIONS,\n USER_ACTION,\n resolveControlledSorting,\n sortKey,\n toBillSortEntries,\n type BillSortEcho,\n type BillTableCallbacks,\n} from './model';\nimport { useBillRowActions } from './row-actions';\nimport { BILL_DIRECTION_COPY, BILL_LIST_DOWNLOAD_COPY } from './status-maps';\nimport {\n BILL_DIRECTIONS,\n BILL_TABLE_SORT_COLUMNS,\n type BillListDownloadKind,\n type BillRow,\n type BillTableFilterModel,\n type BillTableHandle,\n type BillTableHostFilterKey,\n type BillTableProps,\n} from './types';\n\nexport type { BillTableProps, BillTableHandle } from './types';\n\nconst NO_LIST_DOWNLOADS: readonly BillListDownloadKind[] = [];\n\nconst getBillRowId = (row: BillRow): string => row.id;\n\n/** The bill number names the row: \"Select A12\", \"Actions, A12\". It is not\n * personal data, so it names the row under privacy mode too. */\nconst getBillRowLabel = (row: BillRow): string => row.number;\n\n/**\n * The Accounting bills list. Pass one page of `rows`, the total\n * `rowCount` and either a controlled `query` or a `defaultQuery`; fetch on\n * `onQueryChange`. `ref` gives the curated `BillTableHandle`.\n *\n * Saved views: wrap it in `DataGridTabs` (with `useBillTableDefaultTabs`\n * for the suggested views). The DataGrid inside registers itself with the\n * tabs through context, so the tabs need no `getTable`.\n */\nexport const BillTable = forwardRef<BillTableHandle, BillTableProps>(\n function BillTable(props, ref) {\n const {\n /* data */\n rows,\n rowCount,\n currency = 'EUR',\n totals = null,\n /* query */\n query,\n defaultQuery,\n onQueryChange,\n sortableColumns = BILL_TABLE_SORT_COLUMNS,\n pageSizeOptions = BILL_TABLE_PAGE_SIZE_OPTIONS,\n /* selection */\n selectable = true,\n selection,\n defaultSelection,\n onSelectionChange,\n /* columns */\n showWarehouseStatus = false,\n gridId = BILL_TABLE_DEFAULT_GRID_ID,\n persistColumnState = true,\n /* row actions */\n onOpen,\n onDownload,\n onLoadIntoWarehouse,\n onEdit,\n onRecordPayment,\n onWriteOff,\n onDelete,\n /* bulk and list actions */\n onBulkDownload,\n listDownloads = NO_LIST_DOWNLOADS,\n onListDownload,\n onRefresh,\n /* toolbar */\n toolbarStart,\n extraFilterLabels,\n /* states */\n status = 'ready',\n error,\n onCreateBill,\n headingLevel,\n /* privacy and layout */\n privacyMode = false,\n caption,\n density = 'default',\n height = 'auto',\n /* DOM: naming goes to the grid's scroll region */\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n ...rest\n } = props;\n\n const { t } = useTranslation('ui');\n const openHintId = useId();\n const gridRef = useRef<DataGridHandle | null>(null);\n\n /* ---------------- what the handle and the menu read ---------------- */\n\n const callbacks: BillTableCallbacks = {\n onOpen,\n onDownload,\n onLoadIntoWarehouse,\n onEdit,\n onRecordPayment,\n onWriteOff,\n onDelete,\n };\n // Read when an action runs, so a host's inline functions never rebuild\n // the columns or the menu.\n const callbacksRef = useRef(callbacks);\n callbacksRef.current = callbacks;\n\n const hiddenReasonText = t(\n 'billTable.disabledReason.privacyHidden',\n 'Not available (reason hidden in privacy mode)',\n );\n const live: BillTableLive = {\n rows,\n callbacks,\n features: {\n selectable,\n privacyMode,\n showWarehouseStatus,\n sortableColumns: [...sortableColumns],\n status,\n },\n hiddenReasonText,\n };\n const liveRef = useRef(live);\n liveRef.current = live;\n\n /* ---------------- curated handle and agent ---------------- */\n\n const [handle] = useState(() => createBillTableHandle(gridRef, liveRef));\n useImperativeHandle(ref, () => handle, [handle]);\n // `gridId` is the instance id. The DataGrid inside gets\n // `registerAgent={false}`, so one table exposes one agent surface.\n useAgentRegistration(billTableAgent, handle, gridId);\n\n /* ---------------- query ---------------- */\n\n // What the last `onQueryChange` carried, for `resolveControlledSorting`.\n const echoRef = useRef<BillSortEcho | null>(null);\n\n // DataGrid reports the effective query: under privacy mode a paused\n // counterparty sort is left out (DG-6), and DataGrid itself emits once\n // when privacy mode changes the query. BillTable adds `privacyMode` to\n // that call and never emits on its own.\n const handleQueryChange = (next: DataGridQuery) => {\n const sorting = toBillSortEntries(next.sorting);\n echoRef.current = {\n key: sortKey(sorting),\n raw: toBillSortEntries(gridRef.current?.getSort() ?? next.sorting),\n };\n onQueryChange?.({\n sorting,\n // Column models and host keys; DataGrid evaluates none of them in\n // server mode and passes the host's keys through as written.\n filters: next.filters as BillTableFilterModel,\n quickFilter: next.quickFilter,\n pagination: { ...next.pagination },\n privacyMode,\n });\n };\n const controlledSorting = query\n ? resolveControlledSorting(query.sorting, echoRef.current)\n : undefined;\n\n const pageSizeKey = pageSizeOptions.join(',');\n const paginationConfig = useMemo(\n () => ({\n pageSizeOptions:\n pageSizeKey === ''\n ? BILL_TABLE_PAGE_SIZE_OPTIONS\n : pageSizeKey.split(',').map(Number),\n }),\n [pageSizeKey],\n );\n\n // Chip labels for the platform's advanced filters (host keys). A chip\n // shows a host key's label only, never its value.\n const filterLabels = useMemo(() => {\n const kitLabels: Record<BillTableHostFilterKey | 'number', string> = {\n datePreset: t('billTable.filter.datePreset', 'Period'),\n type: t('billTable.filter.type', 'Type'),\n number: t('billTable.filter.number', 'Number'),\n prefix: t('billTable.filter.prefix', 'Prefix'),\n withInsuranceNet: t(\n 'billTable.filter.withInsuranceNet',\n 'Insurer amount',\n ),\n withVat: t('billTable.filter.withVat', 'VAT'),\n withTaxAtSource: t(\n 'billTable.filter.withTaxAtSource',\n 'Withholding tax',\n ),\n withWelfareFundContribution: t(\n 'billTable.filter.withWelfareFundContribution',\n 'Welfare fund contribution',\n ),\n withUnpaidAmount: t(\n 'billTable.filter.withUnpaidAmount',\n 'Amount still to pay',\n ),\n writtenOff: t('billTable.filter.writtenOff', 'Written off'),\n taxOfficeNotification: t(\n 'billTable.filter.taxOfficeNotification',\n 'Consent to send to Sistema TS',\n ),\n receivedFromSdi: t(\n 'billTable.filter.receivedFromSdi',\n 'Received from SDI',\n ),\n sentToSdi: t('billTable.filter.sentToSdi', 'Sent to SDI'),\n selfBill: t('billTable.filter.selfBill', 'Self-billing'),\n liabilityDate: t('billTable.filter.liabilityDate', 'Due date'),\n sdiEntryDate: t(\n 'billTable.filter.sdiEntryDate',\n 'Date received by SDI',\n ),\n relationType: t('billTable.filter.relationType', 'Counterparty type'),\n relation: t('billTable.filter.relation', 'Counterparty'),\n insurance: t('billTable.filter.insurance', 'Insurer'),\n personalAssistant: t(\n 'billTable.filter.personalAssistant',\n 'Personal assistant',\n ),\n };\n return { ...kitLabels, ...extraFilterLabels };\n }, [t, extraFilterLabels]);\n\n /* ---------------- columns ---------------- */\n\n const rowActions = useBillRowActions({\n callbacksRef,\n available: {\n download: Boolean(onDownload),\n loadIntoWarehouse: Boolean(onLoadIntoWarehouse),\n edit: Boolean(onEdit),\n recordPayment: Boolean(onRecordPayment),\n writeOff: Boolean(onWriteOff),\n delete: Boolean(onDelete),\n },\n privacyMode,\n });\n const onOpenRow = useCallback((row: BillRow) => {\n callbacksRef.current.onOpen(row, USER_ACTION);\n }, []);\n const columns = useBillTableColumns({\n currency,\n showWarehouseStatus,\n sortableColumns,\n totals,\n privacyMode,\n openHintId,\n onOpenRow,\n rowActions,\n });\n\n /* ---------------- toolbar ---------------- */\n\n const directionPills = BILL_DIRECTIONS.map((direction) => {\n const copy = BILL_DIRECTION_COPY[direction];\n return { value: direction, label: t(copy.key, copy.en) };\n });\n\n const toolbar = (\n <DataGridToolbar>\n <DataGridToolbar.FilterBar>\n {toolbarStart}\n <DataGridToolbar.QuickSearch\n placeholder={\n privacyMode\n ? t('billTable.search.placeholderPrivate', 'Search by number')\n : t(\n 'billTable.search.placeholder',\n 'Search by number or counterparty',\n )\n }\n />\n <DataGridToolbar.FacetFilter\n field=\"direction\"\n label={t('billTable.column.direction', 'Direction')}\n options={[\n { value: null, label: t('dataTable.selectFilter.all', 'All') },\n ...directionPills,\n ]}\n />\n <DataGridToolbar.FilterChips />\n </DataGridToolbar.FilterBar>\n <DataGridToolbar.Actions>\n {selectable && onBulkDownload ? (\n <>\n <DataGridToolbar.BulkAction\n label={t('billTable.bulk.downloadPdf', 'Download PDFs')}\n icon={<FileText aria-hidden=\"true\" />}\n onAction={({ selectedRowIds }) =>\n onBulkDownload([...selectedRowIds], 'pdf')\n }\n />\n <DataGridToolbar.BulkAction\n label={t('billTable.bulk.downloadXml', 'Download XML files')}\n icon={<FileCode aria-hidden=\"true\" />}\n onAction={({ selectedRowIds }) =>\n onBulkDownload([...selectedRowIds], 'xml')\n }\n />\n </>\n ) : null}\n <IconButtonGroup\n aria-label={t('dataTable.tableActions', 'Table actions')}\n >\n {listDownloads.length > 0 && onListDownload ? (\n // Today's list downloads apply the query to every matching\n // bill on the server; DataGrid's built-in CSV, Excel and PDF\n // would export one page, so only custom items are offered.\n <DataGridToolbar.ExportMenu\n label={t('billTable.export.menu', 'Download list')}\n >\n {listDownloads.map((kind) => {\n const copy = BILL_LIST_DOWNLOAD_COPY[kind];\n return (\n <DataGridToolbar.ExportMenu.Item\n key={kind}\n format=\"custom\"\n label={t(copy.key, copy.en)}\n onExport={() => onListDownload(kind, handle.getQuery())}\n />\n );\n })}\n </DataGridToolbar.ExportMenu>\n ) : null}\n {onRefresh ? (\n <DataGridToolbar.Refresh onRefresh={onRefresh} />\n ) : null}\n <DataGridToolbar.ColumnToggle />\n </IconButtonGroup>\n </DataGridToolbar.Actions>\n </DataGridToolbar>\n );\n\n /* ---------------- render ---------------- */\n\n return (\n <div\n data-component=\"bill-table\"\n data-component-id={gridId}\n className={billTableVariants({ height, className })}\n {...rest}\n >\n {/* The open button's description, once for every row: its name\n is the visible bill number, so the row header reads \"A12\". */}\n <span hidden id={openHintId}>\n {t('billTable.open', 'Open bill')}\n </span>\n <DataGrid<BillRow>\n ref={gridRef}\n columns={columns}\n rows={rows}\n getRowId={getBillRowId}\n caption={caption ?? t('billTable.caption', 'Bills')}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n /* identity: storage key only; BillTable is the agent surface */\n gridId={gridId}\n registerAgent={false}\n persistColumnState={persistColumnState}\n /* server mode: the host fetches on onQueryChange */\n dataMode=\"server\"\n rowCount={rowCount}\n sorting={controlledSorting}\n defaultSorting={defaultQuery?.sorting ?? BILL_TABLE_DEFAULT_SORT}\n filters={query?.filters}\n defaultFilters={defaultQuery?.filters}\n quickFilter={query?.quickFilter}\n defaultQuickFilter={defaultQuery?.quickFilter}\n page={query?.pagination}\n defaultPage={defaultQuery?.pagination}\n onQueryChange={handleQueryChange}\n filterLabels={filterLabels}\n /* the server sorts by one column */\n multiSort={false}\n maxSortLevels={1}\n pagination={paginationConfig}\n /* selection survives paging; a new filter or search clears it */\n selectionMode={selectable ? 'multiple' : 'none'}\n rowSelection={selection}\n defaultRowSelection={defaultSelection}\n onRowSelectionChange={onSelectionChange}\n selectAllScope=\"page\"\n rangeSelection\n clearSelectionOnFilterChange\n /* columns */\n columnResizing\n responsiveColumns\n getRowLabel={getBillRowLabel}\n rowLabelPrivacySafe\n /* states */\n status={status}\n error={{\n title:\n error?.title ??\n t('billTable.error.title', 'The bills could not be loaded'),\n description: error?.description,\n onRetry: error?.onRetry,\n headingLevel,\n }}\n empty={{\n title: t('billTable.empty.title', 'No bills yet'),\n description: t(\n 'billTable.empty.description',\n 'Bills you create, or receive from SDI, appear here.',\n ),\n action: onCreateBill\n ? {\n label: t('billTable.empty.action', 'Add bill'),\n onClick: onCreateBill,\n }\n : undefined,\n headingLevel,\n noResultsTitle: t(\n 'billTable.empty.noResultsTitle',\n 'No bills match your filters',\n ),\n }}\n toolbar={toolbar}\n density={density}\n height={height}\n privacyMode={privacyMode}\n />\n </div>\n );\n },\n);\n\nBillTable.displayName = 'BillTable';\n","/* -------------------------------------------------------------------- */\n/* BillTable: suggested saved views for DataGridTabs. */\n/* */\n/* The host wraps BillTable in DataGridTabs (composition): the DataGrid */\n/* inside BillTable registers itself with the tabs through context, so no */\n/* `getTable` is needed, and a tab switch reaches the host as one */\n/* `onQueryChange` with the whole restored view. Persistence stays with */\n/* the platform. A hook, not a factory that takes `t`: the labels are */\n/* translated here, from the `ui` namespace. */\n/* -------------------------------------------------------------------- */\n\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { DataGridSavedTab } from '../data-grid-tabs/types';\nimport type {\n BillDirection,\n BillPaymentStatus,\n BillSdiStatus,\n BillTableDefaultTabId,\n BillTableFilterModel,\n BillWarehouseStatus,\n} from './types';\n\nexport interface BillTableDefaultTabsOptions {\n /** Adds \"To load into warehouse\": practices with the warehouse module\n * (HTP-7314). Default `false`. */\n withWarehouse?: boolean;\n}\n\n/** A default tab: a stable developer id and a typed bill filter model. */\ninterface BillTableDefaultTab extends DataGridSavedTab {\n id: BillTableDefaultTabId;\n filterModel: BillTableFilterModel;\n}\n\nconst INCOMING: BillDirection[] = ['incoming'];\nconst OUTGOING: BillDirection[] = ['outgoing'];\n/** Money still to settle: the \"To pay\" and \"To collect\" views. */\nconst OPEN_PAYMENT: BillPaymentStatus[] = [\n 'unpaid',\n 'partiallyPaid',\n 'overdue',\n];\nconst FROM_SDI: BillSdiStatus[] = ['received'];\nconst TO_LOAD: BillWarehouseStatus[] = ['notLoaded', 'toReview'];\n\n/**\n * The kit's suggested saved views, for `DataGridTabs` `defaultTabs`:\n * This year (the default, locked), All (locked), Incoming, Outgoing, To pay,\n * To collect and, with the warehouse module, To load into warehouse.\n *\n * \"This year\" is the host key `datePreset: 'thisYear'`, which the server\n * resolves on every request, so a saved \"This year\" is still right next\n * year. Labels are kit copy, translated when the tabs are created; every\n * tab is marked `userNamed: false`, so the labels stay readable under\n * privacy mode (no label holds a name). Seed the host's first query from\n * the active tab's `filterModel`, so mounting the tabs costs no extra\n * request.\n */\nexport function useBillTableDefaultTabs({\n withWarehouse = false,\n}: BillTableDefaultTabsOptions = {}): DataGridSavedTab[] {\n const { t } = useTranslation('ui');\n return useMemo(() => {\n const tabs: BillTableDefaultTab[] = [\n {\n id: 'bills-this-year',\n label: t('billTable.tabs.thisYear', 'This year'),\n filterModel: { datePreset: 'thisYear' },\n locked: true,\n userNamed: false,\n },\n {\n id: 'bills-all',\n label: t('billTable.tabs.all', 'All'),\n filterModel: {},\n locked: true,\n userNamed: false,\n },\n {\n id: 'bills-incoming',\n label: t('billTable.tabs.incoming', 'Incoming'),\n filterModel: { direction: { type: 'set', values: [...INCOMING] } },\n userNamed: false,\n },\n {\n id: 'bills-outgoing',\n label: t('billTable.tabs.outgoing', 'Outgoing'),\n filterModel: { direction: { type: 'set', values: [...OUTGOING] } },\n userNamed: false,\n },\n {\n id: 'bills-to-pay',\n label: t('billTable.tabs.toPay', 'To pay'),\n filterModel: {\n direction: { type: 'set', values: [...INCOMING] },\n paymentStatus: { type: 'set', values: [...OPEN_PAYMENT] },\n },\n userNamed: false,\n },\n {\n id: 'bills-to-collect',\n label: t('billTable.tabs.toCollect', 'To collect'),\n filterModel: {\n direction: { type: 'set', values: [...OUTGOING] },\n paymentStatus: { type: 'set', values: [...OPEN_PAYMENT] },\n },\n userNamed: false,\n },\n ];\n if (withWarehouse) {\n tabs.push({\n id: 'bills-to-load',\n label: t('billTable.tabs.toLoad', 'To load into warehouse'),\n filterModel: {\n sdiStatus: { type: 'set', values: [...FROM_SDI] },\n warehouseStatus: { type: 'set', values: [...TO_LOAD] },\n },\n userNamed: false,\n });\n }\n return tabs;\n }, [t, withWarehouse]);\n}\n"],"names":["__iconNode","HandCoins","createLucideIcon","SORT_COLUMNS","DIRECTIONS","PAYMENT","SDI","WAREHOUSE","TYPES","PAGE_SIZES","HIDEABLE_COLUMNS","NON_PERSONAL_FILTER_KEYS","MASKED","refuse","code","detail","knownRow","handle","id","set","values","dateRange","yesNo","FILTER_SCHEMA","FILTER_KEYS","readFilter","model","view","key","value","ROW_ID_SCHEMA","billTableAgent","args","column","c","_a","row","billTableVariants","cva","cellStackVariants","secondaryTextVariants","inlineGroupVariants","directionIconVariants","truncatedTextVariants","openButtonVariants","accessibleTargetBlockClass","numberTextVariants","breakdownVariants","breakdownGroupVariants","breakdownTextVariants","breakdownListVariants","breakdownTermVariants","breakdownValueVariants","BILL_DIRECTIONS","BILL_TYPES","BILL_PAYMENT_STATUSES","BILL_SDI_STATUSES","BILL_WAREHOUSE_STATUSES","BILL_COUNTERPARTY_KINDS","BILL_ROW_ACTIONS","BILL_ACTION_DISABLED_REASONS","BILL_TABLE_COLUMNS","BILL_TABLE_SORT_COLUMNS","BILL_LIST_DOWNLOADS","BILL_TABLE_DEFAULT_TAB_IDS","BILL_TABLE_DEFAULT_GRID_ID","BILL_TABLE_DEFAULT_SORT","BILL_TABLE_PAGE_SIZE_OPTIONS","BILL_AMOUNT_SCALE","USER_ACTION","API_ACTION","isPersonCounterparty","amountForExport","amountMinor","decimalToNumber","dayFormatters","CALENDAR_DAY","formatCalendarDay","day","language","match","year","month","date","instant","locale","formatLocale","formatter","isBillTableSortColumn","colId","toBillSortEntries","entries","out","entry","sortKey","resolveControlledSorting","hostSorting","echo","BILL_ACTION_CALLBACK","hasActionCallback","callbacks","action","disabledReasonCode","state","offeredActions","privacyMode","hiddenReasonText","offered","summariseActions","summariseBillRow","summary","_b","BILL_PAYMENT_STATUS_COPY","BILL_SDI_STATUS_COPY","BILL_WAREHOUSE_STATUS_COPY","BILL_DIRECTION_COPY","BILL_TYPE_COPY","BILL_ACTION_COPY","BILL_DISABLED_REASON_COPY","BILL_LIST_DOWNLOAD_COPY","OpenBillCell","openHintId","onOpen","hideHostText","t","useTranslation","reasonId","useId","typeLine","copy","reason","jsxs","jsx","Button","event","CalendarDayCell","i18n","DirectionIcon","direction","ArrowDownLeft","ArrowUpRight","DirectionLabel","CounterpartyCell","counterparty","AmountCell","currency","Money","StatusBadge","label","variant","Badge","DUE_STATUSES","PaymentStatusCell","status","nextDueDate","SdiStatusCell","WarehouseStatusCell","SdiHeaderTip","InfoTip","BreakdownEntry","Fragment","TotalsBreakdown","totals","sums","formatNumber","TotalsHeaderCell","breakdown","Popover","IconButton","Info","accessibleTargetSquareClass","DirectionTotalsCell","field","directionText","VisuallyHidden","AMOUNT_FILTER_OPERATORS","SDI_FILTER_STATUSES","useBillTableColumns","showWarehouseStatus","sortableColumns","onOpenRow","rowActions","sortableKey","useMemo","sortable","directionLabel","paymentLabel","sdiLabel","warehouseLabel","options","actionsLabel","columns","context","RowActions","warn","message","isDevelopment","COLUMN_IDS","isBillTableColumnId","maskedColumnIds","grid","createBillTableHandle","gridRef","liveRef","live","findRow","candidate","prepare","features","DATA_GRID_DEFAULT_PAGE_SIZE","masked","filters","text","pageIndex","size","ids","fromId","toId","visible","columnId","rows","format","listener","BILL_ACTION_SECTION","useBillRowActions","callbacksRef","available","download","loadIntoWarehouse","edit","recordPayment","writeOff","remove","hiddenReason","reasonFor","item","icon","run","createElement","items","FileText","FileCode","PackagePlus","Pencil","CircleOff","Undo2","Trash2","NO_LIST_DOWNLOADS","getBillRowId","getBillRowLabel","BillTable","forwardRef","props","ref","rowCount","query","defaultQuery","onQueryChange","pageSizeOptions","selectable","selection","defaultSelection","onSelectionChange","gridId","persistColumnState","onDownload","onLoadIntoWarehouse","onEdit","onRecordPayment","onWriteOff","onDelete","onBulkDownload","listDownloads","onListDownload","onRefresh","toolbarStart","extraFilterLabels","error","onCreateBill","headingLevel","caption","density","height","className","ariaLabel","ariaLabelledBy","ariaDescribedBy","rest","useRef","useState","useImperativeHandle","useAgentRegistration","echoRef","handleQueryChange","next","sorting","controlledSorting","pageSizeKey","paginationConfig","filterLabels","useCallback","directionPills","toolbar","DataGridToolbar","selectedRowIds","IconButtonGroup","kind","DataGrid","INCOMING","OUTGOING","OPEN_PAYMENT","FROM_SDI","TO_LOAD","useBillTableDefaultTabs","withWarehouse","tabs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,KAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,GAAG,oDAAoD,KAAK,SAAQ,CAAE;AAAA,EACjF;AAAA,IACE;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,KAAK;AAAA,IACX;AAAA,EACA;AAAA,EACE,CAAC,QAAQ,EAAE,GAAG,aAAa,KAAK,SAAQ,CAAE;AAAA,EAC1C,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,KAAK,GAAG,OAAO,KAAK,UAAU;AAAA,EACzD,CAAC,UAAU,EAAE,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,KAAK,SAAQ,CAAE;AACxD,GACMC,KAAYC,GAAiB,cAAcF,EAAU,GCWrDG,KAAe,CAAC,UAAU,QAAQ,gBAAgB,QAAQ,GAC1DC,KAAa,CAAC,YAAY,UAAU,GACpCC,KAAU;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEMC,KAAM;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACMC,KAAY,CAAC,aAAa,YAAY,QAAQ,GAC9CC,KAAQ,CAAC,QAAQ,WAAW,UAAU,YAAY,OAAO,GACzDC,KAAa,CAAC,IAAI,IAAI,GAAG,GACzBC,KAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASMC,yBAAoD,IAAI;AAAA,EAC5D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC,GAGKC,KAAS,EAAE,QAAQ,GAAA;AAazB,SAASC,EAAOC,GAA+BC,GAAuB;AACpE,QAAM,IAAI,MAAM,GAAGD,CAAI,KAAKC,CAAM,EAAE;AACtC;AAEA,SAASC,EAASC,GAAyBC,GAAkB;AAC3D,EAAKD,EAAO,UAAA,EAAY,SAASC,CAAE,KACjCL,EAAO,eAAe,YAAYK,CAAE,wBAAwB;AAEhE;AAEA,MAAMC,IAAM,CAACC,OAA+B;AAAA,EAC1C,MAAM;AAAA,EACN,YAAY;AAAA,IACV,MAAM,EAAE,OAAO,MAAA;AAAA,IACf,QAAQ,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,CAAC,GAAGA,CAAM,EAAA,EAAE;AAAA,EAAE;AAAA,EAExD,UAAU,CAAC,QAAQ,QAAQ;AAAA,EAC3B,sBAAsB;AACxB,IAEMC,KAAY;AAAA,EAChB,MAAM;AAAA,EACN,YAAY;AAAA,IACV,MAAM,EAAE,OAAO,UAAA;AAAA,IACf,UAAU,EAAE,MAAM,CAAC,UAAU,MAAM,GAAG,QAAQ,OAAA;AAAA,IAC9C,QAAQ,EAAE,MAAM,CAAC,UAAU,MAAM,GAAG,QAAQ,OAAA;AAAA,EAAO;AAAA,EAErD,UAAU,CAAC,QAAQ,YAAY,QAAQ;AAAA,EACvC,sBAAsB;AACxB,GAEMC,IAAQ;AAAA,EACZ,MAAM;AAAA,EACN,aAAa;AACf,GAKMC,KAAgB;AAAA,EACpB,MAAM;AAAA,EACN,sBAAsB;AAAA,EACtB,YAAY;AAAA,IACV,MAAMF;AAAA,IACN,WAAWF,EAAIf,EAAU;AAAA,IACzB,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,aAAa;AAAA,MACb,YAAY;AAAA,QACV,MAAM;AAAA,UACJ,MAAM,CAAC,WAAW,sBAAsB,mBAAmB,QAAQ;AAAA,QAAA;AAAA,QAErE,QAAQ,EAAE,MAAM,SAAA;AAAA,QAChB,UAAU,EAAE,MAAM,SAAA;AAAA,MAAS;AAAA,MAE7B,UAAU,CAAC,MAAM;AAAA,MACjB,sBAAsB;AAAA,IAAA;AAAA,IAExB,eAAee,EAAId,EAAO;AAAA,IAC1B,WAAWc,EAAIb,EAAG;AAAA,IAClB,iBAAiBa,EAAIZ,EAAS;AAAA,IAC9B,YAAY,EAAE,MAAM,CAAC,SAAS,aAAa,UAAU,EAAA;AAAA,IACrD,MAAMY,EAAIX,EAAK;AAAA,IACf,QAAQ,EAAE,MAAM,SAAA;AAAA,IAChB,QAAQ,EAAE,MAAM,SAAA;AAAA,IAChB,kBAAkBc;AAAA,IAClB,SAASA;AAAA,IACT,iBAAiBA;AAAA,IACjB,6BAA6BA;AAAA,IAC7B,kBAAkBA;AAAA,IAClB,YAAYA;AAAA,IACZ,uBAAuBA;AAAA,IACvB,iBAAiBA;AAAA,IACjB,WAAWA;AAAA,IACX,UAAUA;AAAA,IACV,eAAeD;AAAA,IACf,cAAcA;AAAA,IACd,cAAc,EAAE,MAAM,CAAC,WAAW,WAAW,UAAU,EAAA;AAAA,IACvD,WAAW,EAAE,MAAM,SAAA;AAAA,EAAS;AAEhC,GAEMG,KAAmC,IAAI;AAAA,EAC3C,OAAO,KAAKD,GAAc,UAAU;AACtC;AAGA,SAASE,GAAWR,GAAkD;AACpE,QAAMS,IAAiC,EAAE,GAAGT,EAAO,YAAU;AAC7D,MAAI,CAACA,EAAO,YAAA,EAAc;AACxB,WAAOS;AAET,QAAMC,IAAgC,CAAA;AACtC,aAAW,CAACC,GAAKC,CAAK,KAAK,OAAO,QAAQH,CAAK;AAC7C,IAAAC,EAAKC,CAAG,IAAIjB,GAAyB,IAAIiB,CAAG,IAAIC,IAAQjB;AAE1D,SAAOe;AACT;AAEA,MAAMG,IAAgB;AAAA,EACpB,MAAM;AAAA,EACN,YAAY,EAAE,IAAI,EAAE,MAAM,UAAU,aAAa,sBAAoB;AAAA,EACrE,UAAU,CAAC,IAAI;AAAA,EACf,sBAAsB;AACxB,GAEaC,KAAgD;AAAA,EAC3D,IAAI;AAAA,EACJ,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA,EAAA;AAAA,EAEF,OAAO;AAAA,IACL,UAAU;AAAA,MACR,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACd,MAAWA,EAAO,YAAA;AAAA,IAAY;AAAA,IAEvC,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWA,EAAO,gBAAA;AAAA,IAAgB;AAAA,IAE3C,WAAW;AAAA,MACT,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,aAAA;AAAA,IAAa;AAAA,IAExC,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWA,EAAO,WAAW;AAAA,IAAA;AAAA,IAEtC,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWQ,GAAWR,CAAM;AAAA,IAAA;AAAA,IAErC,aAAa;AAAA,MACX,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA;AAAA;AAAA,MAGF,MAAM,CAACA,MAAYA,EAAO,eAAA,MAAqB,KAAK,KAAKL;AAAA,IAAA;AAAA,IAE3D,aAAa;AAAA,MACX,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACK,MAAWA,EAAO,SAAA,EAAW,WAAW;AAAA,IAAA;AAAA,IAEjD,UAAU;AAAA,MACR,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,SAAA,EAAW,WAAW;AAAA,IAAA;AAAA,IAEjD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,aAAA;AAAA,IAAa;AAAA,IAExC,UAAU;AAAA,MACR,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWA,EAAO,YAAA;AAAA,IAAY;AAAA,IAEvC,SAAS;AAAA,MACP,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,WAAA;AAAA,IAAW;AAAA,EACtC;AAAA,EAEF,SAAS;AAAA,IACP,aAAa;AAAA,MACX,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAA,IAAW;AAAA,QAC9D,UAAU,CAAC,KAAK;AAAA,QAChB,sBAAsB;AAAA,MAAA;AAAA,MAExB,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,QAAQ,CAAC,4CAA4C;AAAA,MACrD,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACA,GAAQe,OACVf,EAAO,YAAA,EAAc,cACxBJ,EAAO,sBAAsB,6BAA6B,GAE5DI,EAAO,aAAae,EAAK,GAAG,GACrBf,EAAO,aAAA;AAAA,IAChB;AAAA,IAEF,cAAc;AAAA,MACZ,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAA,GAAY,MAAM,EAAE,MAAM,WAAS;AAAA,QACjE,UAAU,CAAC,UAAU,MAAM;AAAA,QAC3B,sBAAsB;AAAA,MAAA;AAAA,MAExB,YAAY;AAAA,MACZ,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACA,GAAQe,MAA2C;AAC1D,QAAKf,EAAO,YAAA,EAAc,cACxBJ,EAAO,sBAAsB,6BAA6B,GAE5DG,EAASC,GAAQe,EAAK,MAAM,GAC5BhB,EAASC,GAAQe,EAAK,IAAI,GAC1Bf,EAAO,YAAYe,EAAK,QAAQA,EAAK,IAAI;AAAA,MAC3C;AAAA,IAAA;AAAA,IAEF,iBAAiB;AAAA,MACf,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACf,MAAWA,EAAO,eAAA;AAAA,IAAe;AAAA,IAE5C,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UACE;AAAA,MACF,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,OAAO,EAAE,MAAM,CAAC,GAAGd,EAAY,EAAA;AAAA,UAC/B,MAAM,EAAE,MAAM,CAAC,OAAO,MAAM,EAAA;AAAA,QAAE;AAAA,QAEhC,UAAU,CAAC,SAAS,MAAM;AAAA,QAC1B,sBAAsB;AAAA,MAAA;AAAA,MAExB,YAAY;AAAA,MACZ,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,UAAU,MAAM,OAAA,GAAU;AAAA,MACtD,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACc,GAAQe,MAA6B;AAE5C,QADiBf,EAAO,YAAA,EACV,gBAAgB,SAASe,EAAK,KAAK,KAC/CnB,EAAO,iBAAiB,WAAWmB,EAAK,KAAK,kBAAkB;AAEjE,cAAMC,IAAShB,EAAO,WAAA,EAAa,KAAK,CAAC,MAAM,EAAE,OAAOe,EAAK,KAAK;AAClE,QAAIC,KAAA,QAAAA,EAAQ,UACVpB,EAAO,iBAAiB,IAAImB,EAAK,KAAK,8BAA8B,GAEtEf,EAAO,QAAQ,CAAC,EAAE,OAAOe,EAAK,OAAO,MAAMA,EAAK,KAAA,CAAM,CAAC;AAAA,MACzD;AAAA,IAAA;AAAA,IAEF,cAAc;AAAA,MACZ,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY,EAAE,OAAOT,GAAA;AAAA,QACrB,UAAU,CAAC,OAAO;AAAA,QAClB,sBAAsB;AAAA,MAAA;AAAA,MAExB,YAAY;AAAA,MACZ,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,UAAU;AAAA,QACR;AAAA,UACE,MAAM;AAAA,YACJ,OAAO;AAAA,cACL,WAAW,EAAE,MAAM,OAAO,QAAQ,CAAC,UAAU,EAAA;AAAA,cAC7C,iBAAiB,EAAE,MAAM,OAAO,QAAQ,CAAC,UAAU,EAAA;AAAA,YAAE;AAAA,UACvD;AAAA,UAEF,MAAM;AAAA,QAAA;AAAA,MACR;AAAA,MAEF,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACN,GAAQe,MAA0C;AACzD,mBAAWJ,KAAO,OAAO,KAAKI,EAAK,KAAK;AACtC,UAAKR,GAAY,IAAII,CAAG,KACtBf,EAAO,kBAAkB,IAAIe,CAAG,yBAAyB;AAG7D,QAAAX,EAAO,UAAUe,EAAK,KAAK;AAAA,MAC7B;AAAA,IAAA;AAAA,IAEF,kBAAkB;AAAA,MAChB,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY,EAAE,MAAM,EAAE,MAAM,WAAS;AAAA,QACrC,UAAU,CAAC,MAAM;AAAA,QACjB,sBAAsB;AAAA,MAAA;AAAA,MAExB,YAAY;AAAA,MACZ,QAAQ,CAAC,2CAA2C;AAAA,MACpD,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACf,GAAQe,MACff,EAAO,eAAee,EAAK,IAAI;AAAA,IAAA;AAAA,IAEnC,eAAe;AAAA,MACb,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACf,MAAWA,EAAO,aAAA;AAAA,IAAa;AAAA,IAE1C,YAAY;AAAA,MACV,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,SAAS,IAAE;AAAA,QACvD,UAAU,CAAC,WAAW;AAAA,QACtB,sBAAsB;AAAA,MAAA;AAAA,MAExB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACA,GAAQe,MACff,EAAO,SAASe,EAAK,SAAS;AAAA,IAAA;AAAA,IAElC,eAAe;AAAA,MACb,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,GAAGvB,EAAU,IAAE;AAAA,QAC5C,UAAU,CAAC,MAAM;AAAA,QACjB,sBAAsB;AAAA,MAAA;AAAA,MAExB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACQ,GAAQe,MAA2Bf,EAAO,YAAYe,EAAK,IAAI;AAAA,IAAA;AAAA,IAE1E,eAAe;AAAA,MACb,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAYF;AAAA,MACZ,YAAY;AAAA,MACZ,QAAQ,CAAC,iDAAiD;AAAA,MAC1D,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACb,GAAQe,MAAyB;AACxC,QAAAhB,EAASC,GAAQe,EAAK,EAAE,GACxBf,EAAO,YAAYe,EAAK,EAAE;AAAA,MAC5B;AAAA,IAAA;AAAA,IAEF,uBAAuB;AAAA,MACrB,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,IAAI,EAAE,MAAM,CAAC,GAAGtB,EAAgB,EAAA;AAAA,UAChC,SAAS,EAAE,MAAM,UAAA;AAAA,QAAU;AAAA,QAE7B,UAAU,CAAC,MAAM,SAAS;AAAA,QAC1B,sBAAsB;AAAA,MAAA;AAAA,MAExB,YAAY;AAAA,MACZ,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACO,GAAQe,MAAsD;AACrE,cAAMC,IAAShB,EAAO,WAAA,EAAa,KAAK,CAACiB,MAAMA,EAAE,OAAOF,EAAK,EAAE;AAC/D,QAAKC,KAAQpB,EAAO,kBAAkB,cAAcmB,EAAK,EAAE,IAAI,GAC1DC,EAAO,WACVpB,EAAO,gBAAgB,IAAImB,EAAK,EAAE,iBAAiB,GAErDf,EAAO,iBAAiBe,EAAK,IAAIA,EAAK,OAAO;AAAA,MAC/C;AAAA,IAAA;AAAA,IAEF,eAAe;AAAA,MACb,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACf,MAAWA,EAAO,aAAA;AAAA,IAAa;AAAA,IAE1C,iBAAiB;AAAA,MACf,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAYa;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,QAAQ,CAAC,iDAAiD;AAAA,MAC1D,gBAAgB;AAAA,MAChB,aACE;AAAA;AAAA;AAAA,MAGF,QAAQ,CAACb,GAAQe,MAAyB;;AACxC,eAAAhB,EAASC,GAAQe,EAAK,EAAE,KAEtBG,IAAAlB,EAAO,kBAAkB,KAAK,CAACmB,MAAQA,EAAI,OAAOJ,EAAK,EAAE,MAAzD,gBAAAG,EAA4D,YAC5D,CAAA;AAAA,MAEJ;AAAA,IAAA;AAAA,IAEF,WAAW;AAAA,MACT,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAYL;AAAA,MACZ,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACb,GAAQe,MAAyB;AACxC,QAAAhB,EAASC,GAAQe,EAAK,EAAE,GACxBf,EAAO,SAASe,EAAK,EAAE;AAAA,MACzB;AAAA,IAAA;AAAA,IAEF,eAAe;AAAA;AAAA;AAAA,MAGb,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,IAAI,EAAE,MAAM,SAAA;AAAA,UACZ,QAAQ,EAAE,MAAM,CAAC,OAAO,KAAK,EAAA;AAAA,QAAE;AAAA,QAEjC,UAAU,CAAC,MAAM,QAAQ;AAAA,QACzB,sBAAsB;AAAA,MAAA;AAAA,MAExB,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACf,GAAQe,MAAgD;AAC/D,QAAAhB,EAASC,GAAQe,EAAK,EAAE,GACxBf,EAAO,aAAae,EAAK,IAAIA,EAAK,MAAM;AAAA,MAC1C;AAAA,IAAA;AAAA,IAEF,qBAAqB;AAAA;AAAA;AAAA,MAGnB,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAYF;AAAA,MACZ,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACb,GAAQe,MAAyB;AACxC,QAAAhB,EAASC,GAAQe,EAAK,EAAE,GACxBf,EAAO,kBAAkBe,EAAK,EAAE;AAAA,MAClC;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,aAAa;AAAA,IAAA;AAAA,IAEf,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aACE;AAAA,IAAA;AAAA,EACJ;AAEJ,GC7nBaK,KAAoBC,EAAI,wBAAwB;AAAA,EAC3D,UAAU;AAAA,IACR,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IAAA;AAAA,EACR;AAAA,EAEF,iBAAiB,EAAE,QAAQ,OAAA;AAC7B,CAAC,GAGYC,IAAoBD;AAAA,EAC/B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,OAAO;AAAA,QACL,OAAO;AAAA,QACP,KAAK;AAAA,MAAA;AAAA,IACP;AAAA,IAEF,iBAAiB,EAAE,OAAO,QAAA;AAAA,EAAQ;AAEtC,GAGaE,IAAwBF;AAAA,EACnC;AACF,GAGaG,KAAsBH;AAAA,EACjC;AACF,GAIaI,KAAwBJ;AAAA,EACnC;AACF,GAGaK,KAAwBL;AAAA,EACnC;AACF,GAoBaM,KAAqBN,EAAI;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACAO;AACF,CAAC,GAGYC,KAAqBR,EAAI,gBAAgB,GAIzCS,KAAoBT;AAAA,EAC/B;AACF,GAGaU,KAAyBV;AAAA,EACpC;AACF,GAGaW,KAAwBX,EAAI,UAAU;AAAA,EACjD,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,QACE;AAAA,IAAA;AAAA,EACJ;AAAA,EAEF,iBAAiB,EAAE,MAAM,QAAA;AAC3B,CAAC,GAGYY,KAAwBZ;AAAA,EACnC;AACF,GAEaa,KAAwBb;AAAA,EACnC;AACF,GAEac,KAAyBd,EAAI,oBAAoB,GC7EjDe,IAAkB,CAAC,YAAY,UAAU,GAQzCC,KAAa;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAkBaC,KAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAwBaC,KAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAcaC,KAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAeaC,KAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAqBaC,KAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAYaC,KAA+B;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAuIaC,KAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAIaC,KAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAkIaC,KAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GA+QaC,KAA6B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GCjuBaC,KAA6B,oBAG7BC,KAAyD;AAAA,EACpE,EAAE,OAAO,QAAQ,MAAM,OAAA;AACzB,GAIaC,KAAkD,CAAC,IAAI,IAAI,GAAG,GAS9DC,IAAoB,GAGpBC,IAAiC,EAAE,QAAQ,OAAA,GAG3CC,KAAgC,EAAE,QAAQ,MAAA;AAYhD,SAASC,GAAqBnC,GAAuB;AAC1D,SAAOA,EAAI,iBAAiB,QAAQA,EAAI,aAAa,SAAS;AAChE;AAUO,SAASoC,GAAgBC,GAAoC;AAClE,SAAK,OAAO,cAAcA,CAAW,IAC9BC,GAAgB,EAAE,OAAOD,GAAa,OAAOL,GAAmB,IADxB;AAEjD;AAIA,MAAMO,yBAAoB,IAAA,GACpBC,KAAe;AAOd,SAASC,GAAkBC,GAAaC,GAA0B;AACvE,QAAMC,IAAQJ,GAAa,KAAKE,CAAG;AACnC,MAAI,CAACE,EAAO,QAAOF;AACnB,QAAM,GAAGG,GAAMC,GAAOC,CAAI,IAAIH,GACxBI,IAAU,IAAI;AAAA,IAClB,KAAK,IAAI,OAAOH,CAAI,GAAG,OAAOC,CAAK,IAAI,GAAG,OAAOC,CAAI,CAAC;AAAA,EAAA;AAExD,MAAI,OAAO,MAAMC,EAAQ,QAAA,CAAS,EAAG,QAAON;AAC5C,QAAMO,IAASC,GAAaP,CAAQ;AACpC,MAAIQ,IAAYZ,GAAc,IAAIU,CAAM;AACxC,SAAKE,MACHA,IAAY,IAAI,KAAK,eAAeF,GAAQ;AAAA,IAC1C,WAAW;AAAA,IACX,UAAU;AAAA,EAAA,CACX,GACDV,GAAc,IAAIU,GAAQE,CAAS,IAE9BA,EAAU,OAAOH,CAAO;AACjC;AAMA,MAAMjF,KAAoC,IAAI,IAAI2D,EAAuB;AAElE,SAAS0B,GACdC,GAC8B;AAC9B,SAAOtF,GAAa,IAAIsF,CAAK;AAC/B;AAIO,SAASC,GACdC,GACsB;AACtB,QAAMC,IAA4B,CAAA;AAClC,aAAWC,KAASF;AAClB,IAAIH,GAAsBK,EAAM,KAAK,KACnCD,EAAI,KAAK,EAAE,OAAOC,EAAM,OAAO,MAAMA,EAAM,MAAM;AAGrD,SAAOD;AACT;AAGO,SAASE,GAAQH,GAA+C;AACrE,SAAOA,EAAQ,IAAI,CAACE,MAAU,GAAGA,EAAM,KAAK,IAAIA,EAAM,IAAI,EAAE,EAAE,KAAK,GAAG;AACxE;AAsBO,SAASE,GACdC,GACAC,GAC+B;AAC/B,SAAIA,KAAQH,GAAQE,CAAW,MAAMC,EAAK,MAAYA,EAAK,MACpDD;AACT;AAoBO,MAAME,KAET;AAAA,EACF,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,MAAM;AAAA,EACN,eAAe;AAAA,EACf,UAAU;AAAA,EACV,cAAc;AAAA,EACd,QAAQ;AACV;AAEO,SAASC,GACdC,GACAC,GACS;AACT,SAAO,OAAOD,EAAUF,GAAqBG,CAAM,CAAC,KAAM;AAC5D;AAIO,SAASC,GACdC,GACmC;AACnC,SAAO,OAAOA,EAAM,YAAa,WAAWA,EAAM,WAAW;AAC/D;AAUO,SAASC,GACdpE,GACAgE,GACAK,GACAC,GACkB;AAClB,QAAMC,IAA4B,CAAA;AAClC,aAAWN,KAAU1C,IAAkB;AACrC,UAAM4C,IAAQnE,EAAI,QAAQiE,CAAM;AAChC,IAAIE,MAAU,UAAa,CAACJ,GAAkBC,GAAWC,CAAM,MAC/DM,EAAQN,CAAM,IACZI,KAAeF,MAAU,aAAa,OAAOA,EAAM,YAAa,WAC5D,EAAE,UAAU,EAAE,MAAMG,EAAA,MACpBH;AAAA,EACR;AACA,SAAOI;AACT;AAQO,SAASC,GACdxE,GACAgE,GACyB;AACzB,QAAMO,IAAmC,CAAA;AACzC,aAAWN,KAAU1C,IAAkB;AACrC,UAAM4C,IAAQnE,EAAI,QAAQiE,CAAM;AAChC,IAAIE,MAAU,UAAa,CAACJ,GAAkBC,GAAWC,CAAM,MAC/DM,EAAQN,CAAM,IACZE,MAAU,YAAY,YAAY,EAAE,UAAUD,GAAmBC,CAAK,EAAA;AAAA,EAC1E;AACA,SAAOI;AACT;AAQO,SAASE,GACdzE,GACAgE,GACgB;;AAChB,QAAMU,IAA0B;AAAA,IAC9B,IAAI1E,EAAI;AAAA,IACR,QAAQA,EAAI;AAAA,IACZ,MAAMA,EAAI;AAAA,IACV,MAAMA,EAAI;AAAA,IACV,WAAWA,EAAI;AAAA,IACf,oBAAkBD,IAAAC,EAAI,iBAAJ,gBAAAD,EAAkB,SAAQ;AAAA,IAC5C,aAAaC,EAAI;AAAA,IACjB,eAAeA,EAAI;AAAA,IACnB,WAAWA,EAAI;AAAA,IACf,iBAAiBA,EAAI,mBAAmB;AAAA,IACxC,SAASwE,GAAiBxE,GAAKgE,CAAS;AAAA,EAAA;AAE1C,WAAIW,IAAA3E,EAAI,iBAAJ,gBAAA2E,EAAkB,UAAS,cAC7BD,EAAQ,mBAAmB1E,EAAI,aAAa,OAEvC0E;AACT;AC9PO,MAAME,KAA2B;AAAA,EACtC,MAAM,EAAE,KAAK,gCAAgC,IAAI,QAAQ,SAAS,UAAA;AAAA,EAClE,eAAe;AAAA,IACb,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,QAAQ;AAAA,IACN,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,SAAS;AAAA,IACP,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,YAAY;AAAA,IACV,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,cAAc;AAAA,IACZ,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAEb,GAKaC,KAAuB;AAAA,EAClC,SAAS;AAAA,IACP,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,SAAS;AAAA,IACP,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,SAAS;AAAA,IACP,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,UAAU;AAAA,IACR,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,WAAW;AAAA,IACT,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,cAAc;AAAA,IACZ,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,UAAU;AAAA,IACR,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,UAAU;AAAA,IACR,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAEb,GAOaC,KAA6B;AAAA,EACxC,WAAW;AAAA,IACT,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,UAAU;AAAA,IACR,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAAA,EAEX,QAAQ;AAAA,IACN,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,EAAA;AAEb,GAEaC,IAAsB;AAAA,EACjC,UAAU,EAAE,KAAK,gCAAgC,IAAI,WAAA;AAAA,EACrD,UAAU,EAAE,KAAK,gCAAgC,IAAI,WAAA;AACvD,GAIaC,KAAiB;AAAA,EAC5B,SAAS,EAAE,KAAK,0BAA0B,IAAI,UAAA;AAAA,EAC9C,QAAQ,EAAE,KAAK,yBAAyB,IAAI,cAAA;AAAA,EAC5C,UAAU,EAAE,KAAK,2BAA2B,IAAI,YAAA;AAAA,EAChD,OAAO,EAAE,KAAK,wBAAwB,IAAI,iBAAA;AAC5C,GAGaC,KAAmB;AAAA,EAC9B,aAAa,EAAE,KAAK,gCAAgC,IAAI,eAAA;AAAA,EACxD,aAAa,EAAE,KAAK,gCAAgC,IAAI,eAAA;AAAA,EACxD,mBAAmB;AAAA,IACjB,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,MAAM,EAAE,KAAK,yBAAyB,IAAI,OAAA;AAAA,EAC1C,eAAe;AAAA,IACb,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,UAAU;AAAA,IACR,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,cAAc,EAAE,KAAK,iCAAiC,IAAI,iBAAA;AAAA,EAC1D,QAAQ,EAAE,KAAK,2BAA2B,IAAI,SAAA;AAChD,GAIaC,KAA4B;AAAA,EACvC,eAAe;AAAA,IACb,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,WAAW;AAAA,IACT,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,cAAc;AAAA,IACZ,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,mBAAmB;AAAA,IACjB,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,cAAc;AAAA,IACZ,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,YAAY;AAAA,IACV,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAER,GAGaC,KAA0B;AAAA,EACrC,KAAK,EAAE,KAAK,wBAAwB,IAAI,MAAA;AAAA,EACxC,aAAa;AAAA,IACX,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,QAAQ,EAAE,KAAK,2BAA2B,IAAI,4BAAA;AAAA,EAC9C,WAAW,EAAE,KAAK,8BAA8B,IAAI,UAAA;AAAA,EACpD,gBAAgB;AAAA,IACd,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAAA,EAEN,gBAAgB;AAAA,IACd,KAAK;AAAA,IACL,IAAI;AAAA,EAAA;AAER;AC5IO,SAASC,GAAa;AAAA,EAC3B,KAAApF;AAAA,EACA,YAAAqF;AAAA,EACA,QAAAC;AAAA,EACA,cAAAC;AACF,GAAsB;AACpB,QAAM,EAAE,GAAAC,EAAA,IAAMC,EAAe,IAAI,GAC3BC,IAAWC,GAAA,GACXxB,IAAQnE,EAAI,QAAQ;AAE1B,MAAI4F,IAA0B;AAC9B,MAAI5F,EAAI,SAAS,QAAQ;AACvB,UAAM6F,IAAOb,GAAehF,EAAI,IAAI;AACpC,IAAA4F,IAAWJ,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,EAChC;AAEA,MAAIC,IAAwB;AAC5B,MAAI3B,MAAU,UAAaA,MAAU;AACnC,QAAI,OAAOA,EAAM,YAAa,UAAU;AACtC,YAAM0B,IAAOX,GAA0Bf,EAAM,QAAQ;AACrD,MAAA2B,IAASN,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,IAC9B;AACE,MAAAC,IAASP,IACLC;AAAA,QACE;AAAA,QACA;AAAA,MAAA,IAEFrB,EAAM,SAAS;AAIvB,SACE,gBAAA4B,EAAC,QAAA,EAAK,WAAW5F,EAAA,GACd,UAAA;AAAA,IAAAgE,MAAU,2BACR,QAAA,EAAK,WAAWzD,MAAuB,UAAAV,EAAI,QAAO,IAEnD,gBAAAgG;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,QAAO;AAAA,QACP,MAAK;AAAA,QACL,WAAWzF,GAAA;AAAA,QACX,oBAAkBsF,IAAS,GAAGT,CAAU,IAAIK,CAAQ,KAAKL;AAAA,QAGzD,iBAAeS,IAAS,KAAO;AAAA,QAC/B,SAAS,CAACI,MAAU;AAClB,cAAIJ,GAAQ;AACV,YAAAI,EAAM,eAAA;AACN;AAAA,UACF;AACA,UAAAZ,EAAOtF,CAAG;AAAA,QACZ;AAAA,QAEC,UAAAA,EAAI;AAAA,MAAA;AAAA,IAAA;AAAA,IAGR8F,sBACE,QAAA,EAAK,QAAM,IAAC,IAAIJ,GACd,aACH,IACE;AAAA,IACHE,IACC,gBAAAI,EAAC,QAAA,EAAK,WAAW5F,KAA0B,aAAS,IAClD;AAAA,EAAA,GACN;AAEJ;AAOO,SAAS+F,GAAgB,EAAE,KAAAzD,KAAwB;AACxD,QAAM,EAAE,MAAA0D,EAAA,IAASX,EAAe,IAAI;AACpC,2BAAQ,QAAA,EAAM,UAAAhD,GAAkBC,GAAK0D,EAAK,QAAQ,GAAE;AACtD;AAGO,SAASC,GAAc,EAAE,WAAAC,KAA2C;AAEzE,2BADaA,MAAc,aAAaC,KAAgBC,IAChD,EAAK,eAAY,QAAO,WAAWlG,MAAyB;AACtE;AAGO,SAASmG,GAAe,EAAE,WAAAH,KAA2C;AAC1E,QAAM,EAAE,EAAA,IAAMb,EAAe,IAAI,GAC3BI,IAAOd,EAAoBuB,CAAS;AAC1C,SACE,gBAAAP,EAAC,QAAA,EAAK,WAAW1F,GAAA,GACf,UAAA;AAAA,IAAA,gBAAA2F,EAACK,MAAc,WAAAC,GAAsB;AAAA,sBACpC,QAAA,EAAM,UAAA,EAAET,EAAK,KAAKA,EAAK,EAAE,EAAA,CAAE;AAAA,EAAA,GAC9B;AAEJ;AAQO,SAASa,GAAiB;AAAA,EAC/B,cAAAC;AACF,GAEG;AACD,QAAM,EAAE,EAAA,IAAMlB,EAAe,IAAI;AACjC,SAAIkB,MAAiB,OAEjB,gBAAAX,EAAC,UAAK,WAAW5F,EAAA,GACd,UAAA,EAAE,+BAA+B,iBAAiB,GACrD,IAIF,gBAAA2F,EAAC,QAAA,EAAK,WAAW5F,EAAA,GACf,UAAA;AAAA,IAAA,gBAAA6F,EAAC,UAAK,KAAI,QAAO,WAAWzF,GAAA,GACzB,YAAa,MAChB;AAAA,IACCoG,EAAa,UACZ,gBAAAX,EAAC,QAAA,EAAK,WAAW5F,KACd,UAAA,EAAE,kCAAkC,SAAS,EAAA,CAChD,IACE;AAAA,EAAA,GACN;AAEJ;AAOO,SAASwG,GAAW;AAAA,EACzB,aAAAvE;AAAA,EACA,UAAAwE;AACF,GAGG;AACD,SACE,gBAAAb;AAAA,IAACc;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,OAAOzE;AAAA,MACP,UAAAwE;AAAA,MACA,OAAO7E;AAAA,IAAA;AAAA,EAAA;AAGb;AAOA,SAAS+E,GAAY;AAAA,EACnB,OAAAC;AAAA,EACA,SAAAC;AACF,GAGG;AACD,2BACGC,IAAA,EAAM,MAAK,MAAK,SAAAD,GAAkB,SAAO,IACvC,UAAAD,GACH;AAEJ;AAGA,MAAMG,yBAAmB,IAAuB;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAASC,GAAkB;AAAA,EAChC,QAAAC;AAAA,EACA,aAAAC;AACF,GAGG;AACD,QAAM,EAAE,GAAA9B,GAAG,MAAAY,MAASX,EAAe,IAAI,GACjCI,IAAOjB,GAAyByC,CAAM;AAC5C,SACE,gBAAAtB,EAAC,QAAA,EAAK,WAAW5F,EAAA,GACf,UAAA;AAAA,IAAA,gBAAA6F,EAACe,IAAA,EAAY,OAAOvB,EAAEK,EAAK,KAAKA,EAAK,EAAE,GAAG,SAASA,EAAK,QAAA,CAAS;AAAA,IAChEyB,KAAeH,GAAa,IAAIE,CAAM,IACrC,gBAAArB,EAAC,QAAA,EAAK,WAAW5F,EAAA,GACd,UAAAoF,EAAE,+BAA+B,gBAAgB;AAAA,MAChD,MAAM/C,GAAkB6E,GAAalB,EAAK,QAAQ;AAAA,IAAA,CACnD,GACH,IACE;AAAA,EAAA,GACN;AAEJ;AAGO,SAASmB,GAAc,EAAE,QAAAF,KAAqC;AACnE,QAAM,EAAE,EAAA,IAAM5B,EAAe,IAAI;AACjC,MAAI4B,MAAW,gBAAiB,QAAO;AACvC,QAAMxB,IAAOhB,GAAqBwC,CAAM;AACxC,SAAO,gBAAArB,EAACe,IAAA,EAAY,OAAO,EAAElB,EAAK,KAAKA,EAAK,EAAE,GAAG,SAASA,EAAK,QAAA,CAAS;AAC1E;AAGO,SAAS2B,GAAoB;AAAA,EAClC,QAAAH;AACF,GAEG;AACD,QAAM,EAAE,EAAA,IAAM5B,EAAe,IAAI;AACjC,MAAI4B,MAAW,KAAM,QAAO;AAC5B,QAAMxB,IAAOf,GAA2BuC,CAAM;AAC9C,SAAO,gBAAArB,EAACe,IAAA,EAAY,OAAO,EAAElB,EAAK,KAAKA,EAAK,EAAE,GAAG,SAASA,EAAK,QAAA,CAAS;AAC1E;AAGO,SAAS4B,KAAe;AAC7B,QAAM,EAAE,GAAAjC,EAAA,IAAMC,EAAe,IAAI;AACjC,SACE,gBAAAO;AAAA,IAAC0B;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAASlC;AAAA,QACP;AAAA,QACA;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAGN;AAOA,SAASmC,EAAe;AAAA,EACtB,OAAAX;AAAA,EACA,OAAAvH;AAAA,EACA,UAAAoH;AACF,GAIG;AACD,SACE,gBAAAd,EAAA6B,IAAA,EACE,UAAA;AAAA,IAAA,gBAAA5B,EAAC,MAAA,EAAG,WAAWjF,GAAA,GAA0B,UAAAiG,GAAM;AAAA,IAC/C,gBAAAhB,EAAC,MAAA,EAAG,WAAWhF,GAAA,GACb,UAAA,gBAAAgF;AAAA,MAACc;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAArH;AAAA,QACA,UAAAoH;AAAA,QACA,OAAO7E;AAAA,MAAA;AAAA,IAAA,EACT,CACF;AAAA,EAAA,GACF;AAEJ;AAIA,SAAS6F,GAAgB;AAAA,EACvB,QAAAC;AAAA,EACA,UAAAjB;AACF,GAGG;AACD,QAAM,EAAE,GAAArB,GAAG,MAAAY,MAASX,EAAe,IAAI;AACvC,SACE,gBAAAO,EAAC,SAAI,WAAWrF,MACb,UAAAM,EAAgB,IAAI,CAACqF,MAAc;AAClC,UAAMyB,IAAOD,EAAOxB,CAAS;AAC7B,WAAKyB,IAEH,gBAAAhC,EAAC,OAAA,EAAoB,WAAWnF,GAAA,GAC9B,UAAA;AAAA,MAAA,gBAAAmF,EAAC,OAAE,WAAWlF,GAAsB,EAAE,MAAM,UAAU,GACpD,UAAA;AAAA,QAAA,gBAAAmF,EAACS,MAAe,WAAAH,GAAsB;AAAA,QACtC,gBAAAN,EAAC,QAAA,EACE,UAAAR,EAAE,0BAA0B,uBAAuB;AAAA,UAClD,OAAOuC,EAAK;AAAA,UACZ,WAAWC,GAAaD,EAAK,OAAO3B,EAAK,QAAQ;AAAA,QAAA,CAClD,EAAA,CACH;AAAA,MAAA,GACF;AAAA,MACA,gBAAAL,EAAC,MAAA,EAAG,WAAWjF,GAAA,GACb,UAAA;AAAA,QAAA,gBAAAkF;AAAA,UAAC2B;AAAA,UAAA;AAAA,YACC,OAAOnC,EAAE,0BAA0B,OAAO;AAAA,YAC1C,OAAOuC,EAAK;AAAA,YACZ,UAAAlB;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF,gBAAAb;AAAA,UAAC2B;AAAA,UAAA;AAAA,YACC,OAAOnC,EAAE,wBAAwB,KAAK;AAAA,YACtC,OAAOuC,EAAK;AAAA,YACZ,UAAAlB;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF,gBAAAb;AAAA,UAAC2B;AAAA,UAAA;AAAA,YACC,OAAOnC,EAAE,wBAAwB,KAAK;AAAA,YACtC,OAAOuC,EAAK;AAAA,YACZ,UAAAlB;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF,gBAAAb;AAAA,UAAC2B;AAAA,UAAA;AAAA,YACC,OAAOnC,EAAE,gCAAgC,iBAAiB;AAAA,YAC1D,OAAOuC,EAAK;AAAA,YACZ,UAAAlB;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF,gBAAAb;AAAA,UAAC2B;AAAA,UAAA;AAAA,YACC,OAAOnC,EAAE,yBAAyB,MAAM;AAAA,YACxC,OAAOuC,EAAK;AAAA,YACZ,UAAAlB;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF,gBAAAb;AAAA,UAAC2B;AAAA,UAAA;AAAA,YACC,OAAOnC,EAAE,2BAA2B,QAAQ;AAAA,YAC5C,OAAOuC,EAAK;AAAA,YACZ,UAAAlB;AAAA,UAAA;AAAA,QAAA;AAAA,MACF,EAAA,CACF;AAAA,IAAA,EAAA,GAzCQP,CA0CV,IA5CgB;AAAA,EA8CpB,CAAC,EAAA,CACH;AAEJ;AAUO,SAAS2B,GAAiB;AAAA,EAC/B,QAAAH;AAAA,EACA,UAAAjB;AACF,GAGG;AACD,QAAM,EAAE,GAAArB,EAAA,IAAMC,EAAe,IAAI,GAC3ByC,IAAY1C,EAAE,8BAA8B,kBAAkB;AACpE,SACE,gBAAAO,EAAC,QAAA,EAAK,WAAW1F,GAAA,GACf,UAAA;AAAA,IAAA,gBAAA2F,EAAC,QAAA,EAAM,UAAAR,EAAE,sBAAsB,OAAO,GAAE;AAAA,sBACvC2C,GAAA,EACC,UAAA;AAAA,MAAA,gBAAAnC,EAACmC,EAAQ,SAAR,EAAgB,SAAO,IACtB,UAAA,gBAAAnC;AAAA,QAACoC;AAAA,QAAA;AAAA,UACC,QAAO;AAAA,UACP,MAAK;AAAA,UACL,MAAM,gBAAApC,EAACqC,IAAA,EAAK,eAAY,OAAA,CAAO;AAAA,UAC/B,cAAYH;AAAA,UACZ,WAAWI;AAAA,QAAA;AAAA,MAAA,GAEf;AAAA,MACA,gBAAAvC,EAACoC,EAAQ,SAAR,EAAgB,MAAK,OAAM,OAAM,SAAQ,MAAK,MAC7C,UAAA;AAAA,QAAA,gBAAAnC,EAACmC,EAAQ,SAAR,EAAiB,UAAAD,EAAA,CAAU;AAAA,QAC5B,gBAAAlC,EAACmC,EAAQ,aAAR,EACE,UAAA3C;AAAA,UACC;AAAA,UACA;AAAA,QAAA,GAEJ;AAAA,QACA,gBAAAQ,EAAC6B,IAAA,EAAgB,QAAAC,GAAgB,UAAAjB,EAAA,CAAoB;AAAA,MAAA,EAAA,CACvD;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AASO,SAAS0B,GAAoB;AAAA,EAClC,QAAAT;AAAA,EACA,OAAAU;AAAA,EACA,UAAA3B;AACF,GAIG;AACD,QAAM,EAAE,GAAArB,EAAA,IAAMC,EAAe,IAAI;AACjC,SACE,gBAAAO;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW7F,EAAkB;AAAA,QAC3B,OAAOqI,MAAU,eAAe,QAAQ;AAAA,MAAA,CACzC;AAAA,MAEA,UAAAvH,EAAgB,IAAI,CAACqF,MAAc;AAClC,cAAMyB,IAAOD,EAAOxB,CAAS;AAC7B,YAAI,CAACyB,EAAM,QAAO;AAClB,cAAMlC,IAAOd,EAAoBuB,CAAS,GACpCmC,IAAgBjD,EAAEK,EAAK,KAAKA,EAAK,EAAE;AACzC,eACE,gBAAAE,EAAC,QAAA,EAAqB,WAAW1F,GAAA,GAC/B,UAAA;AAAA,UAAA,gBAAA2F,EAACK,MAAc,WAAAC,GAAsB;AAAA,UACpCkC,MAAU,eACT,gBAAAxC,EAAC,QAAA,EAAM,UAAAyC,EAAA,CAAc,IAErB,gBAAA1C,EAAA6B,IAAA,EACE,UAAA;AAAA,YAAA,gBAAA5B,EAAC0C,MAAgB,UAAAD,EAAA,CAAc;AAAA,YAC/B,gBAAAzC,EAAC,QAAA,EAAM,UAAAR,EAAE,2BAA2B,QAAQ,EAAA,CAAE;AAAA,UAAA,GAChD;AAAA,UAEF,gBAAAQ;AAAA,YAACc;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAOiB,EAAKS,CAAK;AAAA,cACjB,UAAA3B;AAAA,cACA,OAAO7E;AAAA,YAAA;AAAA,UAAA;AAAA,QACT,EAAA,GAfSsE,CAgBX;AAAA,MAEJ,CAAC;AAAA,IAAA;AAAA,EAAA;AAGP;ACpcA,MAAMqC,KAA2D;AAAA,EAC/D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMMC,KACJxH,GAAkB;AAAA,EAChB,CAACiG,MAA0CA,MAAW;AACxD;AAmBK,SAASwB,GAAoB;AAAA,EAClC,UAAAhC;AAAA,EACA,qBAAAiC;AAAA,EACA,iBAAAC;AAAA,EACA,QAAAjB;AAAA,EACA,aAAAzD;AAAA,EACA,YAAAgB;AAAA,EACA,WAAA2D;AAAA,EACA,YAAAC;AACF,GAA0D;AACxD,QAAM,EAAE,GAAAzD,EAAA,IAAMC,EAAe,IAAI,GAG3ByD,IAAcH,EAAgB,KAAK,GAAG;AAE5C,SAAOI,EAAQ,MAAM;AACnB,UAAMC,IAAW,IAAI,IAAIF,EAAY,MAAM,GAAG,CAAC,GAEzCG,IAAiB,CAAC/C,MAAqC;AAC3D,YAAMT,IAAOd,EAAoBuB,CAAS;AAC1C,aAAOd,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,IAC5B,GACMyD,IAAe,CAACjC,MAAsC;AAC1D,YAAMxB,IAAOjB,GAAyByC,CAAM;AAC5C,aAAO7B,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,IAC5B,GACM0D,IAAW,CAAClC,MAAwC;AACxD,YAAMxB,IAAOhB,GAAqBwC,CAAM;AACxC,aAAO7B,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,IAC5B,GACM2D,IAAiB,CAACnC,MAAwC;AAC9D,YAAMxB,IAAOf,GAA2BuC,CAAM;AAC9C,aAAO7B,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,IAC5B,GAGM4D,IAAU,CACdzK,GACAgI,MAEAhI,EAAO,IAAI,CAACS,OAAW,EAAE,OAAAA,GAAO,OAAOuH,EAAMvH,CAAK,IAAI,GAElDiK,IAAelE,EAAE,qBAAqB,SAAS,GAE/CmE,IAAqC;AAAA,MACzC;AAAA,QACE,IAAI;AAAA,QACJ,QAAQnE,EAAE,2BAA2B,QAAQ;AAAA;AAAA;AAAA,QAG7C,WAAW;AAAA,QACX,KAAK;AAAA,QACL,UAAU;AAAA,QACV,aAAa;AAAA,QACb,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO,CAACxF,MAAQA,EAAI;AAAA,QACpB,aAAa,CAACA,MAAQA,EAAI;AAAA,QAC1B,MAAMoJ,EAAS,IAAI,QAAQ,IAAI,SAAS;AAAA,QACxC,MAAM,CAACpJ,MACL,gBAAAgG;AAAA,UAACZ;AAAA,UAAA;AAAA,YACC,KAAApF;AAAA,YACA,YAAAqF;AAAA,YACA,QAAQ2D;AAAA,YACR,cAAc3E;AAAA,UAAA;AAAA,QAAA;AAAA,QAGlB,QAAQyD,IACN,gBAAA9B,EAACiC,IAAA,EAAiB,QAAAH,GAAgB,UAAAjB,GAAoB,IACpD;AAAA,MAAA;AAAA,MAEN;AAAA,QACE,IAAI;AAAA,QACJ,QAAQrB,EAAE,yBAAyB,MAAM;AAAA,QACzC,MAAM;AAAA,QACN,gBAAgB;AAAA;AAAA,QAEhB,OAAO,CAACxF,MAAQA,EAAI;AAAA,QACpB,MAAMoJ,EAAS,IAAI,MAAM,IAAI,SAAS;AAAA,QACtC,eAAe;AAAA;AAAA,QAEf,QAAQ,EAAE,MAAM,aAAa,YAAY,QAAA;AAAA,QACzC,QAAQ;AAAA,QACR,MAAM,CAACpJ,wBAASmG,IAAA,EAAgB,KAAKnG,EAAI,KAAA,CAAM;AAAA,MAAA;AAAA,MAEjD;AAAA,QACE,IAAI;AAAA,QACJ,QAAQwF,EAAE,8BAA8B,WAAW;AAAA,QACnD,MAAM;AAAA,QACN,gBAAgB;AAAA,QAChB,OAAO,CAACxF,MAAQA,EAAI;AAAA,QACpB,aAAa,CAACA,MAAQqJ,EAAerJ,EAAI,SAAS;AAAA,QAClD,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,SAASyJ,EAAQxI,GAAiBoI,CAAc;AAAA,QAAA;AAAA,QAElD,QAAQ;AAAA,QACR,MAAM,CAACrJ,wBAASyG,IAAA,EAAe,WAAWzG,EAAI,UAAA,CAAW;AAAA,MAAA;AAAA,MAE3D;AAAA,QACE,IAAI;AAAA,QACJ,QAAQwF,EAAE,iCAAiC,cAAc;AAAA,QACzD,MAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO,CAACxF,MAAA;;AAAQ,mBAAAD,IAAAC,EAAI,iBAAJ,gBAAAD,EAAkB,SAAQ;AAAA;AAAA;AAAA;AAAA,QAG1C,MAAMqJ,EAAS,IAAI,cAAc,IAAI,SAAS;AAAA;AAAA,QAE9C,SAAS,EAAE,MAAM,QAAQ,WAAWjH,GAAA;AAAA,QACpC,MAAM,CAACnC,wBAAS0G,IAAA,EAAiB,cAAc1G,EAAI,aAAA,CAAc;AAAA,MAAA;AAAA,MAEnE;AAAA,QACE,IAAI;AAAA,QACJ,QAAQwF,EAAE,2BAA2B,QAAQ;AAAA,QAC7C,OAAO;AAAA,QACP,MAAM;AAAA,QACN,OAAO,CAACxF,MAAQA,EAAI;AAAA,QACpB,aAAa,CAACA,MAAQoC,GAAgBpC,EAAI,WAAW;AAAA,QACrD,MAAMoJ,EAAS,IAAI,QAAQ,IAAI,WAAW;AAAA,QAC1C,eAAe;AAAA;AAAA;AAAA;AAAA,QAIf,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,UAAAvC;AAAA,UACA,WAAW8B;AAAA,UACX,iBAAiB;AAAA,QAAA;AAAA,QAEnB,QAAQ;AAAA,QACR,MAAM,CAAC3I,MACL,gBAAAgG,EAACY,MAAW,aAAa5G,EAAI,aAAa,UAAA6G,GAAoB;AAAA,QAEhE,QAAQiB,IACN,gBAAA9B;AAAA,UAACuC;AAAA,UAAA;AAAA,YACC,QAAAT;AAAA,YACA,OAAM;AAAA,YACN,UAAAjB;AAAA,UAAA;AAAA,QAAA,IAEA;AAAA,MAAA;AAAA,MAEN;AAAA,QACE,IAAI;AAAA,QACJ,QAAQrB,EAAE,kCAAkC,gBAAgB;AAAA,QAC5D,MAAM;AAAA,QACN,gBAAgB;AAAA,QAChB,OAAO,CAACxF,MAAQA,EAAI;AAAA,QACpB,aAAa,CAACA,MAAQsJ,EAAatJ,EAAI,aAAa;AAAA,QACpD,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,SAASyJ,EAAQtI,IAAuBmI,CAAY;AAAA,QAAA;AAAA,QAEtD,QAAQ;AAAA,QACR,MAAM,CAACtJ,MACL,gBAAAgG;AAAA,UAACoB;AAAA,UAAA;AAAA,YACC,QAAQpH,EAAI;AAAA,YACZ,aAAaA,EAAI,eAAe;AAAA,UAAA;AAAA,QAAA;AAAA,QAGpC,QAAQ8H,IACN,gBAAA9B;AAAA,UAACuC;AAAA,UAAA;AAAA,YACC,QAAAT;AAAA,YACA,OAAM;AAAA,YACN,UAAAjB;AAAA,UAAA;AAAA,QAAA,IAEA;AAAA,MAAA;AAAA,MAEN;AAAA,QACE,IAAI;AAAA,QACJ,QAAQrB,EAAE,8BAA8B,YAAY;AAAA,QACpD,6BAAYiC,IAAA,EAAa;AAAA,QACzB,MAAM;AAAA,QACN,gBAAgB;AAAA,QAChB,OAAO,CAACzH,MACNA,EAAI,cAAc,kBAAkB,OAAOA,EAAI;AAAA,QACjD,aAAa,CAACA,MACZA,EAAI,cAAc,kBAAkB,KAAKuJ,EAASvJ,EAAI,SAAS;AAAA,QACjE,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,SAASyJ,EAAQb,IAAqBW,CAAQ;AAAA,QAAA;AAAA,QAEhD,QAAQ;AAAA,QACR,MAAM,CAACvJ,wBAASuH,IAAA,EAAc,QAAQvH,EAAI,UAAA,CAAW;AAAA,MAAA;AAAA,IACvD;AAGF,WAAI8I,KACFa,EAAQ,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,QAAQnE,EAAE,oCAAoC,kBAAkB;AAAA,MAChE,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,OAAO,CAACxF,MAAQA,EAAI,mBAAmB;AAAA,MACvC,aAAa,CAACA,MACZA,EAAI,kBAAkBwJ,EAAexJ,EAAI,eAAe,IAAI;AAAA,MAC9D,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,SAASyJ,EAAQpI,IAAyBmI,CAAc;AAAA,MAAA;AAAA,MAE1D,QAAQ;AAAA,MACR,MAAM,CAACxJ,MACL,gBAAAgG,EAACwB,MAAoB,QAAQxH,EAAI,mBAAmB,KAAA,CAAM;AAAA,IAAA,CAE7D,GAGH2J,EAAQ,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,QAAQ,gBAAA3D,EAAC0C,IAAA,EAAgB,UAAAgB,EAAA,CAAa;AAAA,MACtC,aAAaA;AAAA,MACb,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,MACb,UAAU;AAAA,MACV,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,QAAQ;AAAA;AAAA;AAAA;AAAA,MAIR,MAAM,CAAC1J,GAAK4J,MACV,gBAAA5D;AAAA,QAAC6D;AAAA,QAAA;AAAA,UACC,KAAA7J;AAAA,UACA,SAASiJ;AAAA,UACT,WAAW;AAAA,UACX,mBAAiBW,EAAQ;AAAA,QAAA;AAAA,MAAA;AAAA,IAC3B,CAEH,GAEMD;AAAA,EACT,GAAG;AAAA,IACDnE;AAAA,IACAqB;AAAA,IACAiC;AAAA,IACAI;AAAA,IACApB;AAAA,IACAzD;AAAA,IACAgB;AAAA,IACA2D;AAAA,IACAC;AAAA,EAAA,CACD;AACH;ACtRA,SAASxK,EAAOC,GAAgCC,GAAuB;AACrE,QAAM,IAAI,MAAM,GAAGD,CAAI,KAAKC,CAAM,EAAE;AACtC;AAEA,SAASmL,GAAKC,GAAuB;AACnC,EAAIC,QAAiB,QAAQ,KAAK,eAAeD,CAAO,EAAE;AAC5D;AAEA,MAAME,KAAkC,IAAI,IAAIxI,EAAkB;AAElE,SAASyI,GAAoBpL,GAAqC;AAChE,SAAOmL,GAAW,IAAInL,CAAE;AAC1B;AAIA,SAASqL,GAAgBC,GAAmC;AAC1D,SAAO,IAAI;AAAA,IACTA,EACG,WAAA,EACA,OAAO,CAACvK,MAAWA,EAAO,WAAW,EAAI,EACzC,IAAI,CAACA,MAAWA,EAAO,EAAE;AAAA,EAAA;AAEhC;AAEO,SAASwK,GACdC,GACAC,GACiB;AACjB,QAAMH,IAAO,MAA6BE,EAAQ,SAC5CE,IAAO,MAAqBD,EAAQ;AAE1C,WAASE,EAAQ3L,GAAqB;AAEpC,WADY0L,IAAO,KAAK,KAAK,CAACE,MAAcA,EAAU,OAAO5L,CAAE,KACjDL,EAAO,eAAe,YAAYK,CAAE,wBAAwB;AAAA,EAC5E;AAGA,WAAS6L,EACP7L,GACAmF,GACiD;AACjD,UAAMjE,IAAMyK,EAAQ3L,CAAE,GAChB,EAAE,WAAAkF,EAAA,IAAcwG,EAAA,GAChBrG,IAAQnE,EAAI,QAAQiE,CAAM;AAChC,YAAIE,MAAU,UAAa,CAACJ,GAAkBC,GAAWC,CAAM,MAC7DxF,EAAO,sBAAsB,SAASK,CAAE,oBAAoBmF,CAAM,GAAG,GAEnEE,MAAU,aAGZ1F,EAAO,mBAAmByF,GAAmBC,CAAK,CAAC,GAE9C,EAAE,KAAAnE,GAAK,WAAAgE,EAAA;AAAA,EAChB;AAEA,SAAO;AAAA,IACL,cAAc;AACZ,YAAM,EAAE,UAAA4G,EAAA,IAAaJ,EAAA;AACrB,aAAO,EAAE,GAAGI,GAAU,iBAAiB,CAAC,GAAGA,EAAS,eAAe,EAAA;AAAA,IACrE;AAAA;AAAA,IAIA,WAA2B;AACzB,YAAM/L,IAASuL,EAAA,GACT,EAAE,aAAA/F,EAAA,IAAgBmG,EAAA,EAAO;AAC/B,UAAI,CAAC3L;AACH,eAAO;AAAA,UACL,SAAS,CAAA;AAAA,UACT,SAAS,CAAA;AAAA,UACT,aAAa;AAAA,UACb,YAAY,EAAE,WAAW,GAAG,UAAUgM,GAAA;AAAA,UACtC,aAAAxG;AAAA,QAAA;AAKJ,YAAMyG,IAASX,GAAgBtL,CAAM,GAC/BkM,IAAmC,EAAE,GAAGlM,EAAO,YAAU;AAC/D,iBAAWW,KAAO,OAAO,KAAKuL,CAAO;AACnC,QAAID,EAAO,IAAItL,CAAG,KAAG,OAAOuL,EAAQvL,CAAG;AAEzC,aAAO;AAAA,QACL,SAAS8D;AAAA,UACPzE,EAAO,UAAU,OAAO,CAAC4E,MAAU,CAACqH,EAAO,IAAIrH,EAAM,KAAK,CAAC;AAAA,QAAA;AAAA,QAE7D,SAAAsH;AAAA,QACA,aAAalM,EAAO,eAAA;AAAA,QACpB,YAAY;AAAA,UACV,WAAWA,EAAO,eAAA;AAAA,UAClB,UAAUA,EAAO,YAAA;AAAA,QAAY;AAAA,QAE/B,aAAAwF;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,QAAQ/E,GAAO;AACb,YAAMT,IAASuL,EAAA;AACf,UAAI,CAACvL,EAAQ;AACb,YAAM,EAAE,iBAAAkK,EAAA,IAAoByB,EAAA,EAAO,UAC7BM,IAASX,GAAgBtL,CAAM;AACrC,iBAAW4E,KAASnE,GAAO;AACzB,YAAI,CAACyJ,EAAgB,SAAStF,EAAM,KAAK,GAAG;AAC1C,UAAAqG,GAAK,sCAAsCrG,EAAM,KAAK,IAAI;AAC1D;AAAA,QACF;AACA,YAAIqH,EAAO,IAAIrH,EAAM,KAAK,GAAG;AAC3B,UAAAqG,GAAK,aAAarG,EAAM,KAAK,8BAA8B;AAC3D;AAAA,QACF;AAAA,MACF;AACA,MAAInE,EAAM,SAAS,KACjBwK,GAAK,iEAAiE,GAExEjL,EAAO,QAAQS,EAAM,MAAM,GAAG,CAAC,CAAC;AAAA,IAClC;AAAA,IAEA,YAAY;;AACV,aAAO,EAAE,KAAIS,IAAAqK,EAAA,MAAA,gBAAArK,EAAQ,gBAAe,CAAA,EAAC;AAAA,IACvC;AAAA,IAEA,UAAUT,GAAOmK,GAAS;;AACxB,OAAA1J,IAAAqK,QAAA,QAAArK,EAAQ,UAAUT,GAAOmK;AAAA,IAC3B;AAAA,IAEA,iBAAiB;;AACf,eAAO1J,IAAAqK,EAAA,MAAA,gBAAArK,EAAQ,qBAAoB;AAAA,IACrC;AAAA,IAEA,eAAeiL,GAAMvB,GAAS;;AAC5B,OAAA1J,IAAAqK,QAAA,QAAArK,EAAQ,eAAeiL,GAAMvB;AAAA,IAC/B;AAAA,IAEA,eAAe;;AACb,OAAA1J,IAAAqK,EAAA,MAAA,QAAArK,EAAQ;AAAA,IACV;AAAA,IAEA,SAASkL,GAAW;;AAClB,OAAAlL,IAAAqK,EAAA,MAAA,QAAArK,EAAQ,SAASkL;AAAA,IACnB;AAAA,IAEA,YAAYC,GAAM;;AAChB,OAAAnL,IAAAqK,EAAA,MAAA,QAAArK,EAAQ,YAAYmL;AAAA,IACtB;AAAA,IAEA,eAAe;;AACb,eAAOnL,IAAAqK,EAAA,MAAA,gBAAArK,EAAQ,mBAAkB;AAAA,IACnC;AAAA,IAEA,cAAc;;AACZ,eAAOA,IAAAqK,EAAA,MAAA,gBAAArK,EAAQ,kBAAiB;AAAA,IAClC;AAAA,IAEA,YAAY;;AACV,eAAOA,IAAAqK,EAAA,MAAA,gBAAArK,EAAQ,gBAAeyK,EAAA,EAAO,KAAK,IAAI,CAACxK,MAAQA,EAAI,EAAE;AAAA,IAC/D;AAAA;AAAA,IAIA,eAAe;;AACb,eAAOD,IAAAqK,EAAA,MAAA,gBAAArK,EAAQ,mBAAkB,CAAA;AAAA,IACnC;AAAA,IAEA,aAAaoL,GAAK;;AAChB,OAAApL,IAAAqK,EAAA,MAAA,QAAArK,EAAQ,aAAaoL;AAAA,IACvB;AAAA,IAEA,YAAYC,GAAQC,GAAM;;AACxB,OAAAtL,IAAAqK,QAAA,QAAArK,EAAQ,YAAYqL,GAAQC;AAAA,IAC9B;AAAA,IAEA,iBAAiB;;AACf,OAAAtL,IAAAqK,EAAA,MAAA,QAAArK,EAAQ;AAAA,IACV;AAAA;AAAA,IAIA,aAAa;AACX,YAAMlB,IAASuL,EAAA;AACf,UAAI,CAACvL,EAAQ,QAAO,CAAA;AACpB,YAAM,EAAE,aAAAwF,EAAA,IAAgBmG,EAAA,EAAO,UACzBb,IAAiC,CAAA;AACvC,iBAAW9J,KAAUhB,EAAO;AAC1B,QAAKqL,GAAoBrK,EAAO,EAAE,KAClC8J,EAAQ,KAAK;AAAA,UACX,IAAI9J,EAAO;AAAA,UACX,OAAOA,EAAO;AAAA,UACd,SAASA,EAAO;AAAA,UAChB,SAASA,EAAO;AAAA,UAChB,UAAUA,EAAO;AAAA;AAAA;AAAA,UAGjB,QACEA,EAAO,WAAWwE,KAAexE,EAAO,OAAO;AAAA,QAAA,CAClD;AAEH,aAAO8J;AAAA,IACT;AAAA,IAEA,iBAAiB7K,GAAIwM,GAAS;;AAC5B,OAAAvL,IAAAqK,QAAA,QAAArK,EAAQ,iBAAiBjB,GAAIwM;AAAA,IAC/B;AAAA,IAEA,eAAe;;AACb,OAAAvL,IAAAqK,EAAA,MAAA,QAAArK,EAAQ;AAAA,IACV;AAAA;AAAA,IAIA,YAAYjB,GAAI;;AACd,OAAAiB,IAAAqK,EAAA,MAAA,QAAArK,EAAQ,YAAYjB;AAAA,IACtB;AAAA,IAEA,SAASA,GAAIyM,IAAW,UAAU;;AAChC,OAAAxL,IAAAqK,QAAA,QAAArK,EAAQ,SAASjB,GAAIyM;AAAA,IACvB;AAAA;AAAA,IAIA,kBAAkB;AAChB,YAAM,EAAE,MAAAC,GAAM,WAAAxH,EAAA,IAAcwG,EAAA;AAC5B,aAAOgB,EAAK,IAAI,CAACxL,MAAQyE,GAAiBzE,GAAKgE,CAAS,CAAC;AAAA,IAC3D;AAAA;AAAA,IAIA,cAAclF,GAAI;AAChB,YAAMkB,IAAMyK,EAAQ3L,CAAE,GAChB,EAAE,WAAAkF,GAAW,UAAA4G,GAAU,kBAAAtG,EAAA,IAAqBkG,EAAA;AAClD,aAAOpG;AAAA,QACLpE;AAAA,QACAgE;AAAA,QACA4G,EAAS;AAAA,QACTtG;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,SAASxF,GAAI;AACX,YAAM,EAAE,KAAAkB,GAAK,WAAAgE,EAAA,IAAc2G,EAAQ7L,GAAI,MAAM;AAC7C,MAAAkF,EAAU,OAAOhE,GAAKkC,EAAU;AAAA,IAClC;AAAA,IAEA,aAAapD,GAAI2M,GAA4B;;AAC3C,MAAIA,MAAW,SAASA,MAAW,SACjChN,EAAO,sBAAsB,mBAAmB,OAAOgN,CAAM,CAAC,IAAI;AAEpE,YAAM,EAAE,KAAAzL,GAAK,WAAAgE,EAAA,IAAc2G;AAAA,QACzB7L;AAAA,QACA2M,MAAW,QAAQ,gBAAgB;AAAA,MAAA;AAErC,OAAA1L,IAAAiE,EAAU,eAAV,QAAAjE,EAAA,KAAAiE,GAAuBhE,GAAKyL,GAAQvJ;AAAA,IACtC;AAAA,IAEA,kBAAkBpD,GAAI;;AACpB,YAAM,EAAE,KAAAkB,GAAK,WAAAgE,EAAA,IAAc2G,EAAQ7L,GAAI,mBAAmB;AAC1D,OAAAiB,IAAAiE,EAAU,wBAAV,QAAAjE,EAAA,KAAAiE,GAAgChE,GAAK;AAAA,QACnC,GAAGkC;AAAA,QACH,iBAAiBlC,EAAI,mBAAmB;AAAA,MAAA;AAAA,IAE5C;AAAA;AAAA,IAIA,UAAU0L,GAAU;;AAClB,eAAO3L,IAAAqK,EAAA,MAAA,gBAAArK,EAAQ,UAAU2L,QAAc,MAAM;AAAA,MAAC;AAAA,IAChD;AAAA,EAAA;AAEJ;AC7RA,MAAMC,KAAwD;AAAA,EAC5D,aAAa;AAAA,EACb,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,MAAM;AAAA,EACN,eAAe;AAAA,EACf,UAAU;AAAA,EACV,cAAc;AAAA,EACd,QAAQ;AACV;AAwBO,SAASC,GAAkB;AAAA,EAChC,cAAAC;AAAA,EACA,WAAAC;AAAA,EACA,aAAAzH;AACF,GAAsD;AACpD,QAAM,EAAE,GAAAmB,EAAA,IAAMC,EAAe,IAAI,GAC3B;AAAA,IACJ,UAAAsG;AAAA,IACA,mBAAAC;AAAA,IACA,MAAAC;AAAA,IACA,eAAAC;AAAA,IACA,UAAAC;AAAA,IACA,QAAQC;AAAA,EAAA,IACNN;AAEJ,SAAO3C,EAAQ,MAAM;AACnB,UAAMkD,IAAe7G;AAAA,MACnB;AAAA,MACA;AAAA,IAAA,GAII8G,IAAY,CAChBtM,GACAiE,MACuB;AACvB,YAAME,IAAQnE,EAAI,QAAQiE,CAAM;AAChC,UAAI,EAAAE,MAAU,UAAaA,MAAU,YACrC;AAAA,YAAI,OAAOA,EAAM,YAAa,UAAU;AACtC,gBAAM0B,IAAOX,GAA0Bf,EAAM,QAAQ;AACrD,iBAAOqB,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,QAC5B;AACA,eAAOxB,IAAcgI,IAAelI,EAAM,SAAS;AAAA;AAAA,IACrD,GAEMoI,IAAO,CACXtI,GACAuI,GACAC,GACAxF,IAAqC,cACX;AAC1B,YAAMpB,IAAOZ,GAAiBhB,CAAM;AACpC,aAAO;AAAA;AAAA,QAEL,IAAIA;AAAA;AAAA,QAEJ,SAAS0H,GAAoB1H,CAAM;AAAA,QACnC,MAAMyI,GAAcF,GAAM,EAAE,eAAe,IAAM;AAAA,QACjD,OAAOhH,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,QAC1B,SAAS4G;AAAA,QACT,SAAAxF;AAAA,QACA,QAAQ,CAACjH,MAAQA,EAAI,QAAQiE,CAAM,MAAM;AAAA,QACzC,UAAU,CAACjE,MAAQ;AACjB,gBAAMmE,IAAQnE,EAAI,QAAQiE,CAAM;AAChC,iBAAOE,MAAU,UAAaA,MAAU;AAAA,QAC1C;AAAA,QACA,gBAAgB,CAACnE,MAAQsM,EAAUtM,GAAKiE,CAAM;AAAA,MAAA;AAAA,IAElD,GAEMD,IAAY,MAAM6H,EAAa,SAC/Bc,IAAiC,CAAA;AACvC,WAAIZ,KACFY,EAAM;AAAA,MACJJ;AAAA,QAAK;AAAA,QAAeK;AAAA,QAAU,CAAC5M,MAAA;;AAC7B,kBAAA2E,KAAA5E,IAAAiE,EAAA,GAAY,eAAZ,gBAAAW,EAAA,KAAA5E,GAAyBC,GAAK,OAAOiC;AAAA;AAAA,MAAW;AAAA,MAElDsK;AAAA,QAAK;AAAA,QAAeM;AAAA,QAAU,CAAC7M,MAAA;;AAC7B,kBAAA2E,KAAA5E,IAAAiE,EAAA,GAAY,eAAZ,gBAAAW,EAAA,KAAA5E,GAAyBC,GAAK,OAAOiC;AAAA;AAAA,MAAW;AAAA,IAClD,GAGA+J,KACFW,EAAM;AAAA,MACJJ;AAAA,QAAK;AAAA,QAAqBO;AAAA,QAAa,CAAC9M,MAAA;;AACtC,kBAAA2E,KAAA5E,IAAAiE,KAAY,wBAAZ,gBAAAW,EAAA,KAAA5E,GAAkCC,GAAK;AAAA,YACrC,GAAGiC;AAAA;AAAA;AAAA,YAGH,iBAAiBjC,EAAI,mBAAmB;AAAA,UAAA;AAAA;AAAA,MACzC;AAAA,IACH,GAGAiM,KACFU,EAAM;AAAA,MACJJ,EAAK,QAAQQ,IAAQ,CAAC/M,MAAA;;AAAQ,gBAAA2E,KAAA5E,IAAAiE,KAAY,WAAZ,gBAAAW,EAAA,KAAA5E,GAAqBC,GAAKiC;AAAA,OAAY;AAAA,IAAA,GAGpEiK,KACFS,EAAM;AAAA,MACJJ;AAAA,QAAK;AAAA,QAAiB1O;AAAA,QAAW,CAACmC,MAAA;;AAChC,kBAAA2E,KAAA5E,IAAAiE,EAAA,GAAY,oBAAZ,gBAAAW,EAAA,KAAA5E,GAA8BC,GAAKiC;AAAA;AAAA,MAAW;AAAA,IAChD,GAGAkK,KACFQ,EAAM;AAAA,MACJJ;AAAA,QAAK;AAAA,QAAYS;AAAA,QAAW,CAAChN,MAAA;;AAC3B,kBAAA2E,KAAA5E,IAAAiE,EAAA,GAAY,eAAZ,gBAAAW,EAAA,KAAA5E,GAAyBC,GAAK,IAAOiC;AAAA;AAAA,MAAW;AAAA,MAElDsK;AAAA,QAAK;AAAA,QAAgBU;AAAA,QAAO,CAACjN,MAAA;;AAC3B,kBAAA2E,KAAA5E,IAAAiE,EAAA,GAAY,eAAZ,gBAAAW,EAAA,KAAA5E,GAAyBC,GAAK,IAAMiC;AAAA;AAAA,MAAW;AAAA,IACjD,GAGAmK,KACFO,EAAM;AAAA,MACJJ;AAAA,QACE;AAAA,QACAW;AAAA,QACA,CAAClN,MAAA;;AAAQ,kBAAA2E,KAAA5E,IAAAiE,EAAA,GAAY,aAAZ,gBAAAW,EAAA,KAAA5E,GAAuBC,GAAKiC;AAAA;AAAA,QACrC;AAAA,MAAA;AAAA,IACF,GAGG0K;AAAA,EACT,GAAG;AAAA,IACDnH;AAAA,IACAqG;AAAA,IACAE;AAAA,IACAC;AAAA,IACAC;AAAA,IACAC;AAAA,IACAC;AAAA,IACAC;AAAA,IACA/H;AAAA,EAAA,CACD;AACH;AC3IA,MAAM8I,KAAqD,CAAA,GAErDC,KAAe,CAACpN,MAAyBA,EAAI,IAI7CqN,KAAkB,CAACrN,MAAyBA,EAAI,QAWzCsN,KAAYC;AAAA,EACvB,SAAmBC,GAAOC,GAAK;AAC7B,UAAM;AAAA;AAAA,MAEJ,MAAAjC;AAAA,MACA,UAAAkC;AAAA,MACA,UAAA7G,IAAW;AAAA,MACX,QAAAiB,IAAS;AAAA;AAAA,MAET,OAAA6F;AAAA,MACA,cAAAC;AAAA,MACA,eAAAC;AAAA,MACA,iBAAA9E,IAAkBrH;AAAA,MAClB,iBAAAoM,IAAkB/L;AAAA;AAAA,MAElB,YAAAgM,IAAa;AAAA,MACb,WAAAC;AAAA,MACA,kBAAAC;AAAA,MACA,mBAAAC;AAAA;AAAA,MAEA,qBAAApF,IAAsB;AAAA,MACtB,QAAAqF,IAAStM;AAAA,MACT,oBAAAuM,IAAqB;AAAA;AAAA,MAErB,QAAA9I;AAAA,MACA,YAAA+I;AAAA,MACA,qBAAAC;AAAA,MACA,QAAAC;AAAA,MACA,iBAAAC;AAAA,MACA,YAAAC;AAAA,MACA,UAAAC;AAAA;AAAA,MAEA,gBAAAC;AAAA,MACA,eAAAC,KAAgBzB;AAAA,MAChB,gBAAA0B;AAAA,MACA,WAAAC;AAAA;AAAA,MAEA,cAAAC;AAAA,MACA,mBAAAC;AAAA;AAAA,MAEA,QAAA3H,KAAS;AAAA,MACT,OAAA4H;AAAA,MACA,cAAAC;AAAA,MACA,cAAAC;AAAA;AAAA,MAEA,aAAA9K,IAAc;AAAA,MACd,SAAA+K;AAAA,MACA,SAAAC,KAAU;AAAA,MACV,QAAAC,KAAS;AAAA;AAAA,MAET,WAAAC;AAAA,MACA,cAAcC;AAAA,MACd,mBAAmBC;AAAA,MACnB,oBAAoBC;AAAA,MACpB,GAAGC;AAAA,IAAA,IACDnC,GAEE,EAAE,GAAAhI,EAAA,IAAMC,EAAe,IAAI,GAC3BJ,KAAaM,GAAA,GACb2E,IAAUsF,EAA8B,IAAI,GAI5C5L,IAAgC;AAAA,MACpC,QAAAsB;AAAA,MACA,YAAA+I;AAAA,MACA,qBAAAC;AAAA,MACA,QAAAC;AAAA,MACA,iBAAAC;AAAA,MACA,YAAAC;AAAA,MACA,UAAAC;AAAA,IAAA,GAII7C,IAAe+D,EAAO5L,CAAS;AACrC,IAAA6H,EAAa,UAAU7H;AAEvB,UAAMM,KAAmBkB;AAAA,MACvB;AAAA,MACA;AAAA,IAAA,GAEIgF,KAAsB;AAAA,MAC1B,MAAAgB;AAAA,MACA,WAAAxH;AAAA,MACA,UAAU;AAAA,QACR,YAAA+J;AAAA,QACA,aAAA1J;AAAA,QACA,qBAAAyE;AAAA,QACA,iBAAiB,CAAC,GAAGC,CAAe;AAAA,QACpC,QAAA1B;AAAA,MAAA;AAAA,MAEF,kBAAA/C;AAAA,IAAA,GAEIiG,KAAUqF,EAAOpF,EAAI;AAC3B,IAAAD,GAAQ,UAAUC;AAIlB,UAAM,CAAC3L,CAAM,IAAIgR,GAAS,MAAMxF,GAAsBC,GAASC,EAAO,CAAC;AACvE,IAAAuF,GAAoBrC,GAAK,MAAM5O,GAAQ,CAACA,CAAM,CAAC,GAG/CkR,GAAqBpQ,IAAgBd,GAAQsP,CAAM;AAKnD,UAAM6B,KAAUJ,EAA4B,IAAI,GAM1CK,KAAoB,CAACC,MAAwB;;AACjD,YAAMC,IAAU7M,GAAkB4M,EAAK,OAAO;AAC9C,MAAAF,GAAQ,UAAU;AAAA,QAChB,KAAKtM,GAAQyM,CAAO;AAAA,QACpB,KAAK7M,KAAkBvD,KAAAuK,EAAQ,YAAR,gBAAAvK,GAAiB,cAAamQ,EAAK,OAAO;AAAA,MAAA,GAEnErC,KAAA,QAAAA,EAAgB;AAAA,QACd,SAAAsC;AAAA;AAAA;AAAA,QAGA,SAASD,EAAK;AAAA,QACd,aAAaA,EAAK;AAAA,QAClB,YAAY,EAAE,GAAGA,EAAK,WAAA;AAAA,QACtB,aAAA7L;AAAA,MAAA;AAAA,IAEJ,GACM+L,KAAoBzC,IACtBhK,GAAyBgK,EAAM,SAASqC,GAAQ,OAAO,IACvD,QAEEK,IAAcvC,EAAgB,KAAK,GAAG,GACtCwC,KAAmBnH;AAAA,MACvB,OAAO;AAAA,QACL,iBACEkH,MAAgB,KACZtO,KACAsO,EAAY,MAAM,GAAG,EAAE,IAAI,MAAM;AAAA,MAAA;AAAA,MAEzC,CAACA,CAAW;AAAA,IAAA,GAKRE,KAAepH,EAAQ,OA+CpB,EAAE,GA9C4D;AAAA,MACnE,YAAY3D,EAAE,+BAA+B,QAAQ;AAAA,MACrD,MAAMA,EAAE,yBAAyB,MAAM;AAAA,MACvC,QAAQA,EAAE,2BAA2B,QAAQ;AAAA,MAC7C,QAAQA,EAAE,2BAA2B,QAAQ;AAAA,MAC7C,kBAAkBA;AAAA,QAChB;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAASA,EAAE,4BAA4B,KAAK;AAAA,MAC5C,iBAAiBA;AAAA,QACf;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,6BAA6BA;AAAA,QAC3B;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,kBAAkBA;AAAA,QAChB;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,YAAYA,EAAE,+BAA+B,aAAa;AAAA,MAC1D,uBAAuBA;AAAA,QACrB;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,iBAAiBA;AAAA,QACf;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,WAAWA,EAAE,8BAA8B,aAAa;AAAA,MACxD,UAAUA,EAAE,6BAA6B,cAAc;AAAA,MACvD,eAAeA,EAAE,kCAAkC,UAAU;AAAA,MAC7D,cAAcA;AAAA,QACZ;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,cAAcA,EAAE,iCAAiC,mBAAmB;AAAA,MACpE,UAAUA,EAAE,6BAA6B,cAAc;AAAA,MACvD,WAAWA,EAAE,8BAA8B,SAAS;AAAA,MACpD,mBAAmBA;AAAA,QACjB;AAAA,QACA;AAAA,MAAA;AAAA,IACF,GAEqB,GAAGwJ,GAAA,IACzB,CAACxJ,GAAGwJ,EAAiB,CAAC,GAInB/F,KAAa2C,GAAkB;AAAA,MACnC,cAAAC;AAAA,MACA,WAAW;AAAA,QACT,UAAU,EAAQwC;AAAA,QAClB,mBAAmB,EAAQC;AAAA,QAC3B,MAAM,EAAQC;AAAA,QACd,eAAe,EAAQC;AAAA,QACvB,UAAU,EAAQC;AAAA,QAClB,QAAQ,EAAQC;AAAA,MAAQ;AAAA,MAE1B,aAAArK;AAAA,IAAA,CACD,GACK2E,KAAYwH,GAAY,CAACxQ,MAAiB;AAC9C,MAAA6L,EAAa,QAAQ,OAAO7L,GAAKiC,CAAW;AAAA,IAC9C,GAAG,CAAA,CAAE,GACC0H,KAAUd,GAAoB;AAAA,MAClC,UAAAhC;AAAA,MACA,qBAAAiC;AAAA,MACA,iBAAAC;AAAA,MACA,QAAAjB;AAAA,MACA,aAAAzD;AAAA,MACA,YAAAgB;AAAA,MACA,WAAA2D;AAAA,MACA,YAAAC;AAAA,IAAA,CACD,GAIKwH,KAAiBxP,EAAgB,IAAI,CAACqF,MAAc;AACxD,YAAMT,IAAOd,EAAoBuB,CAAS;AAC1C,aAAO,EAAE,OAAOA,GAAW,OAAOd,EAAEK,EAAK,KAAKA,EAAK,EAAE,EAAA;AAAA,IACvD,CAAC,GAEK6K,uBACHC,GAAA,EACC,UAAA;AAAA,MAAA,gBAAA5K,EAAC4K,EAAgB,WAAhB,EACE,UAAA;AAAA,QAAA5B;AAAA,QACD,gBAAA/I;AAAA,UAAC2K,EAAgB;AAAA,UAAhB;AAAA,YACC,aACEtM,IACImB,EAAE,uCAAuC,kBAAkB,IAC3DA;AAAA,cACE;AAAA,cACA;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,QAGR,gBAAAQ;AAAA,UAAC2K,EAAgB;AAAA,UAAhB;AAAA,YACC,OAAM;AAAA,YACN,OAAOnL,EAAE,8BAA8B,WAAW;AAAA,YAClD,SAAS;AAAA,cACP,EAAE,OAAO,MAAM,OAAOA,EAAE,8BAA8B,KAAK,EAAA;AAAA,cAC3D,GAAGiL;AAAA,YAAA;AAAA,UACL;AAAA,QAAA;AAAA,QAEF,gBAAAzK,EAAC2K,EAAgB,aAAhB,CAAA,CAA4B;AAAA,MAAA,GAC/B;AAAA,MACA,gBAAA5K,EAAC4K,EAAgB,SAAhB,EACE,UAAA;AAAA,QAAA5C,KAAcY,IACb,gBAAA5I,EAAA6B,IAAA,EACE,UAAA;AAAA,UAAA,gBAAA5B;AAAA,YAAC2K,EAAgB;AAAA,YAAhB;AAAA,cACC,OAAOnL,EAAE,8BAA8B,eAAe;AAAA,cACtD,MAAM,gBAAAQ,EAAC4G,IAAA,EAAS,eAAY,OAAA,CAAO;AAAA,cACnC,UAAU,CAAC,EAAE,gBAAAgE,EAAA,MACXjC,EAAe,CAAC,GAAGiC,CAAc,GAAG,KAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAG7C,gBAAA5K;AAAA,YAAC2K,EAAgB;AAAA,YAAhB;AAAA,cACC,OAAOnL,EAAE,8BAA8B,oBAAoB;AAAA,cAC3D,MAAM,gBAAAQ,EAAC6G,IAAA,EAAS,eAAY,OAAA,CAAO;AAAA,cACnC,UAAU,CAAC,EAAE,gBAAA+D,EAAA,MACXjC,EAAe,CAAC,GAAGiC,CAAc,GAAG,KAAK;AAAA,YAAA;AAAA,UAAA;AAAA,QAE7C,EAAA,CACF,IACE;AAAA,QACJ,gBAAA7K;AAAA,UAAC8K;AAAA,UAAA;AAAA,YACC,cAAYrL,EAAE,0BAA0B,eAAe;AAAA,YAEtD,UAAA;AAAA,cAAAoJ,GAAc,SAAS,KAAKC;AAAA;AAAA;AAAA;AAAA,gBAI3B,gBAAA7I;AAAA,kBAAC2K,EAAgB;AAAA,kBAAhB;AAAA,oBACC,OAAOnL,EAAE,yBAAyB,eAAe;AAAA,oBAEhD,UAAAoJ,GAAc,IAAI,CAACkC,MAAS;AAC3B,4BAAMjL,IAAOV,GAAwB2L,CAAI;AACzC,6BACE,gBAAA9K;AAAA,wBAAC2K,EAAgB,WAAW;AAAA,wBAA3B;AAAA,0BAEC,QAAO;AAAA,0BACP,OAAOnL,EAAEK,EAAK,KAAKA,EAAK,EAAE;AAAA,0BAC1B,UAAU,MAAMgJ,GAAeiC,GAAMjS,EAAO,UAAU;AAAA,wBAAA;AAAA,wBAHjDiS;AAAA,sBAAA;AAAA,oBAMX,CAAC;AAAA,kBAAA;AAAA,gBAAA;AAAA,kBAED;AAAA,cACHhC,KACC,gBAAA9I,EAAC2K,EAAgB,SAAhB,EAAwB,WAAA7B,IAAsB,IAC7C;AAAA,cACJ,gBAAA9I,EAAC2K,EAAgB,cAAhB,CAAA,CAA6B;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAChC,EAAA,CACF;AAAA,IAAA,GACF;AAKF,WACE,gBAAA5K;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,kBAAe;AAAA,QACf,qBAAmBoI;AAAA,QACnB,WAAWlO,GAAkB,EAAE,QAAAqP,IAAQ,WAAAC,IAAW;AAAA,QACjD,GAAGI;AAAA,QAIJ,UAAA;AAAA,UAAA,gBAAA3J,EAAC,QAAA,EAAK,QAAM,IAAC,IAAIX,IACd,UAAAG,EAAE,kBAAkB,WAAW,EAAA,CAClC;AAAA,UACA,gBAAAQ;AAAA,YAAC+K;AAAA,YAAA;AAAA,cACC,KAAKzG;AAAA,cACL,SAAAX;AAAA,cACA,MAAA6B;AAAA,cACA,UAAU4B;AAAA,cACV,SAASgC,MAAW5J,EAAE,qBAAqB,OAAO;AAAA,cAClD,cAAYgK;AAAA,cACZ,mBAAiBC;AAAA,cACjB,oBAAkBC;AAAA,cAElB,QAAAvB;AAAA,cACA,eAAe;AAAA,cACf,oBAAAC;AAAA,cAEA,UAAS;AAAA,cACT,UAAAV;AAAA,cACA,SAAS0C;AAAA,cACT,iBAAgBxC,KAAA,gBAAAA,EAAc,YAAW9L;AAAA,cACzC,SAAS6L,KAAA,gBAAAA,EAAO;AAAA,cAChB,gBAAgBC,KAAA,gBAAAA,EAAc;AAAA,cAC9B,aAAaD,KAAA,gBAAAA,EAAO;AAAA,cACpB,oBAAoBC,KAAA,gBAAAA,EAAc;AAAA,cAClC,MAAMD,KAAA,gBAAAA,EAAO;AAAA,cACb,aAAaC,KAAA,gBAAAA,EAAc;AAAA,cAC3B,eAAeqC;AAAA,cACf,cAAAM;AAAA,cAEA,WAAW;AAAA,cACX,eAAe;AAAA,cACf,YAAYD;AAAA,cAEZ,eAAevC,IAAa,aAAa;AAAA,cACzC,cAAcC;AAAA,cACd,qBAAqBC;AAAA,cACrB,sBAAsBC;AAAA,cACtB,gBAAe;AAAA,cACf,gBAAc;AAAA,cACd,8BAA4B;AAAA,cAE5B,gBAAc;AAAA,cACd,mBAAiB;AAAA,cACjB,aAAab;AAAA,cACb,qBAAmB;AAAA,cAEnB,QAAAhG;AAAA,cACA,OAAO;AAAA,gBACL,QACE4H,KAAA,gBAAAA,EAAO,UACPzJ,EAAE,yBAAyB,+BAA+B;AAAA,gBAC5D,aAAayJ,KAAA,gBAAAA,EAAO;AAAA,gBACpB,SAASA,KAAA,gBAAAA,EAAO;AAAA,gBAChB,cAAAE;AAAA,cAAA;AAAA,cAEF,OAAO;AAAA,gBACL,OAAO3J,EAAE,yBAAyB,cAAc;AAAA,gBAChD,aAAaA;AAAA,kBACX;AAAA,kBACA;AAAA,gBAAA;AAAA,gBAEF,QAAQ0J,KACJ;AAAA,kBACE,OAAO1J,EAAE,0BAA0B,UAAU;AAAA,kBAC7C,SAAS0J;AAAA,gBAAA,IAEX;AAAA,gBACJ,cAAAC;AAAA,gBACA,gBAAgB3J;AAAA,kBACd;AAAA,kBACA;AAAA,gBAAA;AAAA,cACF;AAAA,cAEF,SAAAkL;AAAA,cACA,SAAArB;AAAA,cACA,QAAAC;AAAA,cACA,aAAAjL;AAAA,YAAA;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEAiJ,GAAU,cAAc;AC1bxB,MAAM0D,KAA4B,CAAC,UAAU,GACvCC,KAA4B,CAAC,UAAU,GAEvCC,KAAoC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,GACMC,KAA4B,CAAC,UAAU,GACvCC,KAAiC,CAAC,aAAa,UAAU;AAexD,SAASC,GAAwB;AAAA,EACtC,eAAAC,IAAgB;AAClB,IAAiC,IAAwB;AACvD,QAAM,EAAE,EAAA,IAAM7L,EAAe,IAAI;AACjC,SAAO0D,EAAQ,MAAM;AACnB,UAAMoI,IAA8B;AAAA,MAClC;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,2BAA2B,WAAW;AAAA,QAC/C,aAAa,EAAE,YAAY,WAAA;AAAA,QAC3B,QAAQ;AAAA,QACR,WAAW;AAAA,MAAA;AAAA,MAEb;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,sBAAsB,KAAK;AAAA,QACpC,aAAa,CAAA;AAAA,QACb,QAAQ;AAAA,QACR,WAAW;AAAA,MAAA;AAAA,MAEb;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,2BAA2B,UAAU;AAAA,QAC9C,aAAa,EAAE,WAAW,EAAE,MAAM,OAAO,QAAQ,CAAC,GAAGP,EAAQ,IAAE;AAAA,QAC/D,WAAW;AAAA,MAAA;AAAA,MAEb;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,2BAA2B,UAAU;AAAA,QAC9C,aAAa,EAAE,WAAW,EAAE,MAAM,OAAO,QAAQ,CAAC,GAAGC,EAAQ,IAAE;AAAA,QAC/D,WAAW;AAAA,MAAA;AAAA,MAEb;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,wBAAwB,QAAQ;AAAA,QACzC,aAAa;AAAA,UACX,WAAW,EAAE,MAAM,OAAO,QAAQ,CAAC,GAAGD,EAAQ,EAAA;AAAA,UAC9C,eAAe,EAAE,MAAM,OAAO,QAAQ,CAAC,GAAGE,EAAY,EAAA;AAAA,QAAE;AAAA,QAE1D,WAAW;AAAA,MAAA;AAAA,MAEb;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,4BAA4B,YAAY;AAAA,QACjD,aAAa;AAAA,UACX,WAAW,EAAE,MAAM,OAAO,QAAQ,CAAC,GAAGD,EAAQ,EAAA;AAAA,UAC9C,eAAe,EAAE,MAAM,OAAO,QAAQ,CAAC,GAAGC,EAAY,EAAA;AAAA,QAAE;AAAA,QAE1D,WAAW;AAAA,MAAA;AAAA,IACb;AAEF,WAAII,KACFC,EAAK,KAAK;AAAA,MACR,IAAI;AAAA,MACJ,OAAO,EAAE,yBAAyB,wBAAwB;AAAA,MAC1D,aAAa;AAAA,QACX,WAAW,EAAE,MAAM,OAAO,QAAQ,CAAC,GAAGJ,EAAQ,EAAA;AAAA,QAC9C,iBAAiB,EAAE,MAAM,OAAO,QAAQ,CAAC,GAAGC,EAAO,EAAA;AAAA,MAAE;AAAA,MAEvD,WAAW;AAAA,IAAA,CACZ,GAEIG;AAAA,EACT,GAAG,CAAC,GAAGD,CAAa,CAAC;AACvB;","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"default-tabs-BryvhiHv.js","sources":["../../node_modules/lucide-react/dist/esm/icons/hand-coins.mjs","../../src/components/bill-table/bill-table.agent.ts","../../src/components/bill-table/bill-table.variants.ts","../../src/components/bill-table/types.ts","../../src/components/bill-table/model.ts","../../src/components/bill-table/status-maps.ts","../../src/components/bill-table/cells.tsx","../../src/components/bill-table/columns.tsx","../../src/components/bill-table/handle.ts","../../src/components/bill-table/row-actions.ts","../../src/components/bill-table/bill-table.tsx","../../src/components/bill-table/default-tabs.ts"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17\", key: \"geh8rc\" }],\n [\n \"path\",\n {\n d: \"m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9\",\n key: \"1fto5m\"\n }\n ],\n [\"path\", { d: \"m2 16 6 6\", key: \"1pfhp9\" }],\n [\"circle\", { cx: \"16\", cy: \"9\", r: \"2.9\", key: \"1n0dlu\" }],\n [\"circle\", { cx: \"6\", cy: \"5\", r: \"3\", key: \"151irh\" }]\n];\nconst HandCoins = createLucideIcon(\"hand-coins\", __iconNode);\n\nexport { __iconNode, HandCoins as default };\n//# sourceMappingURL=hand-coins.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter: BillTable. */\n/* */\n/* Works against the curated `BillTableHandle`: ids and kit shapes only, */\n/* never the DataGrid handle, a TanStack object, a row object or a DOM */\n/* node. It is the table's only agent surface: the DataGrid inside */\n/* registers none (`registerAgent={false}`). */\n/* */\n/* Safety: query actions stay `read` + `openWorld` (they change the view; */\n/* the host fetches). Column choices persist under `gridId` (`write`); */\n/* resetting them deletes the saved state (`destructive`). Downloading a */\n/* bill hands a document with patient data to the user's device (`phi`). */\n/* Opening a bill, or the warehouse dialog, changes nothing by itself */\n/* (`read` + `openWorld`). Edit, record payment, write off and delete are */\n/* UI-only in this phase. Agent state carries no PHI: a counterparty name */\n/* is read for companies only, a host's disabled text reads as `host`, */\n/* the quick search always reads `{ masked: true }`, and under privacy */\n/* mode the filters that can point at a person read `{ masked: true }`. */\n/* */\n/* Literal enums, not imports: the catalog build loads this file in plain */\n/* Node, where only type imports are erased (as data-grid.agent.ts). */\n/* A test should keep the literals equal to the BILL_* constants. */\n/* See src/docs/26-agent-readiness.mdx. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type {\n BillTableColumnId,\n BillTableFilterModel,\n BillTableHandle,\n BillTableSortEntry,\n} from './types';\n\nconst SORT_COLUMNS = ['number', 'date', 'counterparty', 'amount'] as const;\nconst DIRECTIONS = ['incoming', 'outgoing'] as const;\nconst PAYMENT = [\n 'paid',\n 'partiallyPaid',\n 'unpaid',\n 'overdue',\n 'writtenOff',\n 'noPaymentDue',\n] as const;\n/** Every SDI status but `notApplicable`, which is not a filter value. */\nconst SDI = [\n 'notSent',\n 'sending',\n 'pending',\n 'accepted',\n 'delivered',\n 'notDelivered',\n 'rejected',\n 'received',\n] as const;\nconst WAREHOUSE = ['notLoaded', 'toReview', 'loaded'] as const;\nconst TYPES = ['full', 'partial', 'credit', 'proforma', 'other'] as const;\nconst PAGE_SIZES = [25, 50, 100] as const;\nconst HIDEABLE_COLUMNS = [\n 'date',\n 'direction',\n 'counterparty',\n 'amount',\n 'paymentStatus',\n 'sdiStatus',\n 'warehouseStatus',\n] as const;\n\n/**\n * Filter keys whose values cannot point at a person: the column keys and\n * the platform's typed host keys. Under privacy mode every other key reads\n * `{ masked: true }`: `relation` and `personalAssistant` (they hold the id\n * of a patient, a company, an operator or a practice member) and any extra\n * key a host adds later, whose value the kit cannot vouch for.\n */\nconst NON_PERSONAL_FILTER_KEYS: ReadonlySet<string> = new Set([\n 'date',\n 'direction',\n 'amount',\n 'paymentStatus',\n 'sdiStatus',\n 'warehouseStatus',\n 'datePreset',\n 'type',\n 'number',\n 'prefix',\n 'withInsuranceNet',\n 'withVat',\n 'withTaxAtSource',\n 'withWelfareFundContribution',\n 'withUnpaidAmount',\n 'writtenOff',\n 'taxOfficeNotification',\n 'receivedFromSdi',\n 'sentToSdi',\n 'selfBill',\n 'liabilityDate',\n 'sdiEntryDate',\n 'relationType',\n 'insurance',\n]);\n\n/** What an agent sees in place of a value privacy mode hides. */\nconst MASKED = { masked: true } as const;\n\n/** Error codes the adapter throws (message prefix). The handle throws\n * `UNKNOWN_ROW`, `ACTION_UNAVAILABLE` and `ACTION_DISABLED` too. */\ntype BillTableAgentErrorCode =\n | 'UNKNOWN_ROW'\n | 'SORT_DISABLED'\n | 'COLUMN_MASKED'\n | 'UNKNOWN_FILTER'\n | 'UNKNOWN_COLUMN'\n | 'NOT_HIDEABLE'\n | 'SELECTION_DISABLED';\n\nfunction refuse(code: BillTableAgentErrorCode, detail: string): never {\n throw new Error(`${code}: ${detail}`);\n}\n\nfunction knownRow(handle: BillTableHandle, id: string): void {\n if (!handle.getRowIds().includes(id)) {\n refuse('UNKNOWN_ROW', `no bill \"${id}\" on the current page.`);\n }\n}\n\nconst set = (values: readonly string[]) => ({\n type: 'object',\n properties: {\n type: { const: 'set' },\n values: { type: 'array', items: { enum: [...values] } },\n },\n required: ['type', 'values'],\n additionalProperties: false,\n});\n\nconst dateRange = {\n type: 'object',\n properties: {\n type: { const: 'inRange' },\n dateFrom: { type: ['string', 'null'], format: 'date' },\n dateTo: { type: ['string', 'null'], format: 'date' },\n },\n required: ['type', 'dateFrom', 'dateTo'],\n additionalProperties: false,\n};\n\nconst yesNo = {\n type: 'boolean',\n description: 'true = yes, false = no; leave the key out for either.',\n};\n\n/** Every key `apply_filter` accepts. Unknown keys are refused, so a typo\n * never becomes a silent host key. `relation` and `personalAssistant` are\n * not offered: they take entity ids an agent has no safe way to learn. */\nconst FILTER_SCHEMA = {\n type: 'object',\n additionalProperties: false,\n properties: {\n date: dateRange,\n direction: set(DIRECTIONS),\n amount: {\n type: 'object',\n description: 'Amount in major units (12.50), as on the platform form.',\n properties: {\n type: {\n enum: ['inRange', 'greaterThanOrEqual', 'lessThanOrEqual', 'equals'],\n },\n filter: { type: 'number' },\n filterTo: { type: 'number' },\n },\n required: ['type'],\n additionalProperties: false,\n },\n paymentStatus: set(PAYMENT),\n sdiStatus: set(SDI),\n warehouseStatus: set(WAREHOUSE),\n datePreset: { enum: ['today', 'thisMonth', 'thisYear'] },\n type: set(TYPES),\n number: { type: 'string' },\n prefix: { type: 'string' },\n withInsuranceNet: yesNo,\n withVat: yesNo,\n withTaxAtSource: yesNo,\n withWelfareFundContribution: yesNo,\n withUnpaidAmount: yesNo,\n writtenOff: yesNo,\n taxOfficeNotification: yesNo,\n receivedFromSdi: yesNo,\n sentToSdi: yesNo,\n selfBill: yesNo,\n liabilityDate: dateRange,\n sdiEntryDate: dateRange,\n relationType: { enum: ['patient', 'company', 'operator'] },\n insurance: { type: 'string' },\n },\n} as const;\n\nconst FILTER_KEYS: ReadonlySet<string> = new Set(\n Object.keys(FILTER_SCHEMA.properties),\n);\n\n/** The filter model as an agent may read it (see NON_PERSONAL_FILTER_KEYS). */\nfunction readFilter(handle: BillTableHandle): Record<string, unknown> {\n const model: Record<string, unknown> = { ...handle.getFilter() };\n if (!handle.getFeatures().privacyMode) {\n return model;\n }\n const view: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(model)) {\n view[key] = NON_PERSONAL_FILTER_KEYS.has(key) ? value : MASKED;\n }\n return view;\n}\n\nconst ROW_ID_SCHEMA = {\n type: 'object',\n properties: { id: { type: 'string', description: 'A bill id (rows).' } },\n required: ['id'],\n additionalProperties: false,\n};\n\nexport const billTableAgent: AgentAdapter<BillTableHandle> = {\n id: 'bill-table',\n capabilities: [\n 'select_multiple',\n 'range_pick',\n 'filter',\n 'sort',\n 'paginate',\n 'view_change',\n 'scroll',\n // open_bill moves to the bill page (26 section 4: `navigate`).\n 'navigate',\n // load_into_warehouse opens the HTP-7311 dialog (`open`: a Dialog).\n // download_bill fits no capability exactly (a file request): the\n // agent-readiness-auditor rules on it.\n 'open',\n ],\n state: {\n features: {\n type: '{ selectable, privacyMode, showWarehouseStatus, sortableColumns, status }',\n descriptionKey: 'ui.agent.billTable.state.features',\n description:\n 'What this bill list can do now: selection, privacy mode, the warehouse column, sortable columns and loading status.',\n read: (handle) => handle.getFeatures(),\n },\n rows: {\n type: 'Array<{ id, number, type, date, direction, counterpartyKind, counterpartyName?, amountMinor, paymentStatus, sdiStatus, warehouseStatus, actions }>',\n descriptionKey: 'ui.agent.billTable.state.rows',\n description:\n 'The bills on the current page, amounts in hundredths. A counterparty name is given only for companies; patients and other people are never named.',\n read: (handle) => handle.getRowSummaries(),\n },\n selection: {\n type: 'string[]',\n descriptionKey: 'ui.agent.billTable.state.selection',\n description: 'Ids of the selected bills, on every page.',\n read: (handle) => handle.getSelection(),\n },\n sort: {\n type: 'Array<{ colId, sort }>',\n descriptionKey: 'ui.agent.billTable.state.sort',\n description:\n 'The active sort, as the server receives it. A counterparty sort is left out while privacy mode is on.',\n read: (handle) => handle.getQuery().sorting,\n },\n filter: {\n type: 'object',\n descriptionKey: 'ui.agent.billTable.state.filter',\n description:\n 'The active filters. Under privacy mode, filters that can point at a person read { masked: true }.',\n read: (handle) => readFilter(handle),\n },\n quickFilter: {\n type: \"'' | { masked: true }\",\n descriptionKey: 'ui.agent.billTable.state.quickFilter',\n description:\n 'Empty when no quick search is set; otherwise { masked: true }, since the text may be a name. Set it with set_quick_filter.',\n // Masked in both modes: a person's name typed here must not reach\n // agent state, privacy mode or not.\n read: (handle) => (handle.getQuickFilter() === '' ? '' : MASKED),\n },\n currentPage: {\n type: 'number',\n descriptionKey: 'ui.agent.billTable.state.currentPage',\n description: 'Zero-based page index.',\n read: (handle) => handle.getQuery().pagination.pageIndex,\n },\n pageSize: {\n type: 'number',\n descriptionKey: 'ui.agent.billTable.state.pageSize',\n description: 'Bills per page.',\n read: (handle) => handle.getQuery().pagination.pageSize,\n },\n pageCount: {\n type: 'number',\n descriptionKey: 'ui.agent.billTable.state.pageCount',\n description: 'Number of pages; -1 when the total is unknown.',\n read: (handle) => handle.getPageCount(),\n },\n rowCount: {\n type: 'number',\n descriptionKey: 'ui.agent.billTable.state.rowCount',\n description:\n 'Bills matching the filters, on every page; -1 when unknown.',\n read: (handle) => handle.getRowCount(),\n },\n columns: {\n type: 'Array<{ id, label, visible, canHide, sortable, masked }>',\n descriptionKey: 'ui.agent.billTable.state.columns',\n description: 'The columns, in display order.',\n read: (handle) => handle.getColumns(),\n },\n },\n actions: {\n select_rows: {\n safety: 'read',\n argsType: '{ ids: string[] }',\n argsSchema: {\n type: 'object',\n properties: { ids: { type: 'array', items: { type: 'string' } } },\n required: ['ids'],\n additionalProperties: false,\n },\n returns: 'string[]',\n idempotent: true,\n errors: ['SELECTION_DISABLED: the list is read-only.'],\n descriptionKey: 'ui.agent.billTable.actions.selectRows',\n description:\n 'Replace the selection with the given bill ids. Changing a filter or the search clears it.',\n invoke: (handle, args: { ids: string[] }) => {\n if (!handle.getFeatures().selectable) {\n refuse('SELECTION_DISABLED', 'this list has no selection.');\n }\n handle.setSelection(args.ids);\n return handle.getSelection();\n },\n },\n select_range: {\n safety: 'read',\n argsType: '{ fromId: string, toId: string }',\n argsSchema: {\n type: 'object',\n properties: { fromId: { type: 'string' }, toId: { type: 'string' } },\n required: ['fromId', 'toId'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: [\n 'SELECTION_DISABLED: the list is read-only.',\n 'UNKNOWN_ROW: fromId or toId is not on the current page.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.selectRange',\n description:\n 'Select every bill from fromId to toId on the current page, inclusive.',\n invoke: (handle, args: { fromId: string; toId: string }) => {\n if (!handle.getFeatures().selectable) {\n refuse('SELECTION_DISABLED', 'this list has no selection.');\n }\n knownRow(handle, args.fromId);\n knownRow(handle, args.toId);\n handle.selectRange(args.fromId, args.toId);\n },\n },\n clear_selection: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.clearSelection',\n description: 'Clear the selection on every page.',\n invoke: (handle) => handle.clearSelection(),\n },\n sort_by: {\n safety: 'read',\n openWorld: true,\n argsType:\n '{ colId: \"number\" | \"date\" | \"counterparty\" | \"amount\", sort: \"asc\" | \"desc\" }',\n argsSchema: {\n type: 'object',\n properties: {\n colId: { enum: [...SORT_COLUMNS] },\n sort: { enum: ['asc', 'desc'] },\n },\n required: ['colId', 'sort'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: [\n 'SORT_DISABLED: the server cannot sort this column (features.sortableColumns).',\n 'COLUMN_MASKED: counterparty cannot be sorted while privacy mode is on.',\n ],\n examples: [{ args: { colId: 'amount', sort: 'desc' } }],\n descriptionKey: 'ui.agent.billTable.actions.sortBy',\n description:\n 'Sort the bills by one column. The host fetches the first page again.',\n invoke: (handle, args: BillTableSortEntry) => {\n const features = handle.getFeatures();\n if (!features.sortableColumns.includes(args.colId)) {\n refuse('SORT_DISABLED', `column \"${args.colId}\" does not sort.`);\n }\n const column = handle.getColumns().find((c) => c.id === args.colId);\n if (column?.masked) {\n refuse('COLUMN_MASKED', `\"${args.colId}\" is hidden by privacy mode.`);\n }\n handle.setSort([{ colId: args.colId, sort: args.sort }]);\n },\n },\n apply_filter: {\n safety: 'read',\n openWorld: true,\n argsType: '{ model: BillTableFilterModel }',\n argsSchema: {\n type: 'object',\n properties: { model: FILTER_SCHEMA },\n required: ['model'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: [\n 'UNKNOWN_FILTER: a key is not a bill filter.',\n 'Changing filters clears the selection.',\n ],\n examples: [\n {\n args: {\n model: {\n sdiStatus: { type: 'set', values: ['received'] },\n warehouseStatus: { type: 'set', values: ['toReview'] },\n },\n },\n note: 'Bills from SDI that need a warehouse review.',\n },\n ],\n descriptionKey: 'ui.agent.billTable.actions.applyFilter',\n description:\n 'Replace the filters. The host fetches the first page again.',\n invoke: (handle, args: { model: BillTableFilterModel }) => {\n for (const key of Object.keys(args.model)) {\n if (!FILTER_KEYS.has(key)) {\n refuse('UNKNOWN_FILTER', `\"${key}\" is not a bill filter.`);\n }\n }\n handle.setFilter(args.model);\n },\n },\n set_quick_filter: {\n safety: 'read',\n openWorld: true,\n argsType: '{ text: string }',\n argsSchema: {\n type: 'object',\n properties: { text: { type: 'string' } },\n required: ['text'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: ['Changing the search clears the selection.'],\n descriptionKey: 'ui.agent.billTable.actions.setQuickFilter',\n description:\n 'Search by bill number, and by counterparty name unless privacy mode is on.',\n invoke: (handle, args: { text: string }) =>\n handle.setQuickFilter(args.text),\n },\n clear_filters: {\n safety: 'read',\n openWorld: true,\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.clearFilters',\n description: 'Remove every filter and the quick search.',\n invoke: (handle) => handle.clearFilters(),\n },\n go_to_page: {\n safety: 'read',\n openWorld: true,\n argsType: '{ pageIndex: number }',\n argsSchema: {\n type: 'object',\n properties: { pageIndex: { type: 'integer', minimum: 0 } },\n required: ['pageIndex'],\n additionalProperties: false,\n },\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.goToPage',\n description: 'Go to a zero-based page.',\n invoke: (handle, args: { pageIndex: number }) =>\n handle.goToPage(args.pageIndex),\n },\n set_page_size: {\n safety: 'read',\n openWorld: true,\n argsType: '{ size: 25 | 50 | 100 }',\n argsSchema: {\n type: 'object',\n properties: { size: { enum: [...PAGE_SIZES] } },\n required: ['size'],\n additionalProperties: false,\n },\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.setPageSize',\n description: 'Change how many bills show per page.',\n invoke: (handle, args: { size: number }) => handle.setPageSize(args.size),\n },\n scroll_to_row: {\n safety: 'read',\n argsType: '{ id: string }',\n argsSchema: ROW_ID_SCHEMA,\n idempotent: true,\n errors: ['UNKNOWN_ROW: the id is not on the current page.'],\n descriptionKey: 'ui.agent.billTable.actions.scrollToRow',\n description: 'Scroll a bill on the current page into view.',\n invoke: (handle, args: { id: string }) => {\n knownRow(handle, args.id);\n handle.scrollToRow(args.id);\n },\n },\n set_column_visibility: {\n safety: 'write',\n argsType: '{ id: string, visible: boolean }',\n argsSchema: {\n type: 'object',\n properties: {\n id: { enum: [...HIDEABLE_COLUMNS] },\n visible: { type: 'boolean' },\n },\n required: ['id', 'visible'],\n additionalProperties: false,\n },\n idempotent: true,\n errors: [\n 'UNKNOWN_COLUMN: the column is not in this list (warehouseStatus needs the warehouse module).',\n 'NOT_HIDEABLE: number and actions always show.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.setColumnVisibility',\n description: 'Show or hide a column. The choice is saved for this list.',\n invoke: (handle, args: { id: BillTableColumnId; visible: boolean }) => {\n const column = handle.getColumns().find((c) => c.id === args.id);\n if (!column) refuse('UNKNOWN_COLUMN', `no column \"${args.id}\".`);\n if (!column.canHide) {\n refuse('NOT_HIDEABLE', `\"${args.id}\" always shows.`);\n }\n handle.setColumnVisible(args.id, args.visible);\n },\n },\n reset_columns: {\n safety: 'destructive',\n idempotent: true,\n descriptionKey: 'ui.agent.billTable.actions.resetColumns',\n description:\n 'Put every column back to its default and delete the column choices saved for this list.',\n invoke: (handle) => handle.resetColumns(),\n },\n get_row_actions: {\n safety: 'read',\n argsType: '{ id: string }',\n argsSchema: ROW_ID_SCHEMA,\n returns: 'Record<action, \"enabled\" | { disabled: reason }>',\n idempotent: true,\n errors: ['UNKNOWN_ROW: the id is not on the current page.'],\n descriptionKey: 'ui.agent.billTable.actions.getRowActions',\n description:\n 'Which actions one bill offers now, and why a disabled one is disabled.',\n // The agent-safe projection (reason codes, a host's text as `host`),\n // never `handle.getRowActions`, which carries the host's text.\n invoke: (handle, args: { id: string }) => {\n knownRow(handle, args.id);\n return (\n handle.getRowSummaries().find((row) => row.id === args.id)?.actions ??\n {}\n );\n },\n },\n open_bill: {\n safety: 'read',\n openWorld: true,\n argsType: '{ id: string }',\n argsSchema: ROW_ID_SCHEMA,\n errors: [\n 'UNKNOWN_ROW: the id is not on the current page.',\n 'ACTION_UNAVAILABLE: the bill offers no open action.',\n 'ACTION_DISABLED: followed by the reason code.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.openBill',\n description: 'Open one bill. The host shows its page.',\n invoke: (handle, args: { id: string }) => {\n knownRow(handle, args.id);\n handle.openBill(args.id);\n },\n },\n download_bill: {\n // A bill PDF or XML names the patient: a document with patient data\n // leaves the UI for the device (signature-request precedent, phi).\n safety: 'phi',\n openWorld: true,\n argsType: '{ id: string, format: \"pdf\" | \"xml\" }',\n argsSchema: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n format: { enum: ['pdf', 'xml'] },\n },\n required: ['id', 'format'],\n additionalProperties: false,\n },\n errors: [\n 'UNKNOWN_ROW: the id is not on the current page.',\n 'ACTION_UNAVAILABLE: the bill offers no download in this format.',\n 'ACTION_DISABLED: followed by the reason code.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.downloadBill',\n description: 'Download one bill as a PDF or an electronic invoice (XML).',\n invoke: (handle, args: { id: string; format: 'pdf' | 'xml' }) => {\n knownRow(handle, args.id);\n handle.downloadBill(args.id, args.format);\n },\n },\n load_into_warehouse: {\n // Opens the review dialog (or the upsell without the module);\n // nothing loads until the user confirms there.\n safety: 'read',\n openWorld: true,\n argsType: '{ id: string }',\n argsSchema: ROW_ID_SCHEMA,\n errors: [\n 'UNKNOWN_ROW: the id is not on the current page.',\n 'ACTION_UNAVAILABLE: not an incoming SDI bill.',\n 'ACTION_DISABLED: alreadyLoaded, when the bill is already in the warehouse.',\n ],\n descriptionKey: 'ui.agent.billTable.actions.loadIntoWarehouse',\n description:\n \"Open the dialog that loads an incoming SDI bill's lines into the warehouse. Nothing loads until the user confirms.\",\n invoke: (handle, args: { id: string }) => {\n knownRow(handle, args.id);\n handle.loadIntoWarehouse(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'bill-table',\n description: 'Marks the element as a kit BillTable.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'gridId',\n description: 'Sourced from gridId (default accounting-bills).',\n },\n item: {\n attr: 'data-row-id',\n description:\n 'Opaque bill id on each row (DataGrid). Act through the handle, not the DOM.',\n },\n },\n};\n","/* -------------------------------------------------------------------- */\n/* BillTable: CVA for the root and the cells. Tokens only, logical */\n/* properties only. DataGrid owns the table chrome (borders, row size, */\n/* density, pins, sticky header and footer); these classes lay out what */\n/* sits inside one cell. */\n/* -------------------------------------------------------------------- */\n\nimport { cva } from 'class-variance-authority';\n\nimport { accessibleTargetBlockClass } from '../_shared/accessible-target';\n\n/** The BillTable root around the DataGrid frame. With `height: 'fill'`\n * the root is a flex column that fills its flex parent, so the grid\n * inside becomes the bounded scroll container (sticky header and footer,\n * virtualised rows). */\nexport const billTableVariants = cva('ds:w-full ds:min-w-0', {\n variants: {\n height: {\n auto: 'ds:block',\n fill: 'ds:flex ds:min-h-0 ds:flex-auto ds:flex-col',\n },\n },\n defaultVariants: { height: 'auto' },\n});\n\n/** Lines stacked in one cell (a value and its muted second line). */\nexport const cellStackVariants = cva(\n 'ds:flex ds:min-w-0 ds:flex-col ds:gap-[var(--spacing-2xs)]',\n {\n variants: {\n align: {\n start: 'ds:items-start',\n end: 'ds:items-end',\n },\n },\n defaultVariants: { align: 'start' },\n },\n);\n\n/** A muted second line (\"Credit note\", \"Due 4 Nov 2026\", \"Deleted\"). */\nexport const secondaryTextVariants = cva(\n 'type-meta ds:text-[color:var(--muted-foreground)]',\n);\n\n/** An icon beside its text, or a label beside an amount. */\nexport const inlineGroupVariants = cva(\n 'ds:inline-flex ds:min-w-0 ds:max-w-full ds:items-center ds:gap-[var(--spacing-xs)]',\n);\n\n/** The direction arrow. Mirrored in RTL: \"incoming\" points inward on\n * either reading direction. Decorative; the label is always visible. */\nexport const directionIconVariants = cva(\n 'ds:size-4 ds:shrink-0 ds:rtl:-scale-x-100',\n);\n\n/** One line of text that truncates; the full text stays in the DOM. */\nexport const truncatedTextVariants = cva(\n 'ds:block ds:min-w-0 ds:max-w-full ds:truncate',\n);\n\n/**\n * The bill number as the open control (kit Button, `intent=\"link\"`).\n *\n * Colour: the link intent paints `--primary`, which falls below 4.5:1 as\n * text on the dark page, so it is re-pointed at `--primary-readable`, as\n * the kit Link does. On a selected row the tint behind it is darker in the\n * dark theme (fuchsia-400 measures 4.46:1 there), so a selected row uses\n * the hover step, which passes on the tint: fuchsia-300 at 5.09:1 in dark,\n * violet-700 at 6.93:1 in light. AA in all four themes, plain or selected.\n *\n * Target: the link intent drops Button `sm`'s height, and `sm` hides its\n * 44 px hit area from 640 px up, which left a 21 px target in the main\n * control of each row. The `before:` hit area stays on at every width (it\n * grows the target, not the row), keyed on the Button's own marker so it\n * outranks `sm:before:hidden` whatever the CSS order (the DashboardGrid\n * precedent). In the accessible themes the box itself reaches the 48 px\n * floor, as DataGrid's own compact controls do.\n */\nexport const openButtonVariants = cva([\n 'ds:max-w-full ds:[--primary:var(--primary-readable)] ds:[--primary-hover:var(--primary-readable-hover)]',\n 'ds:[tr[data-selected]_&]:[--primary:var(--primary-readable-hover)]',\n 'ds:data-[component=button]:sm:before:block',\n accessibleTargetBlockClass,\n]);\n\n/** The bill number as plain text, when the host offers no `open`. */\nexport const numberTextVariants = cva('ds:font-medium');\n\n/** The totals breakdown inside the footer Popover, under its heading\n * and scope note. */\nexport const breakdownVariants = cva(\n 'ds:mt-[var(--spacing-sm)] ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]',\n);\n\n/** One direction's block in the breakdown: its heading and its sums. */\nexport const breakdownGroupVariants = cva(\n 'ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]',\n);\n\n/** One paragraph of the breakdown (a direction heading). */\nexport const breakdownTextVariants = cva('ds:m-0', {\n variants: {\n tone: {\n muted: 'ds:text-[color:var(--muted-foreground)]',\n strong:\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-x-[var(--spacing-sm)] ds:text-[color:var(--foreground)] ds:[font-weight:var(--font-weight-semibold)]',\n },\n },\n defaultVariants: { tone: 'muted' },\n});\n\n/** The breakdown's label and amount pairs. */\nexport const breakdownListVariants = cva(\n 'ds:m-0 ds:grid ds:grid-cols-[1fr_auto] ds:items-baseline ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-2xs)]',\n);\n\nexport const breakdownTermVariants = cva(\n 'ds:m-0 ds:text-[color:var(--muted-foreground)]',\n);\n\nexport const breakdownValueVariants = cva('ds:m-0 ds:text-end');\n","/* -------------------------------------------------------------------- */\n/* BillTable: public types (the Phase 2 contract). */\n/* */\n/* Rules this file keeps: */\n/* - No DataGrid internal and no TanStack type in a public type. Public */\n/* kit shapes (DataGridPagination, filter models) are reused. */\n/* - Only `BillRow.id` reaches the DOM (DataGrid `data-row-id`). */\n/* - Every field that mirrors the platform names its source on */\n/* alfadocs/platform origin/stable f039a606cf. */\n/* DB = src/Ic/MainBundle/Entity/DoctorBill.php */\n/* REPO = src/AlfaDocs/Infrastructure/Domain/Practice/Archive/Bill/ */\n/* DoctrineBillRepository.php */\n/* SEND = src/AlfaDocs/Domain/Practice/Archive/FatturazioneElettronica */\n/* /Sending/Bill/Bill.php */\n/* LIAB = src/AlfaDocs/Domain/Practice/Archive/Bill/Liability/ */\n/* Liability.php */\n/* CTRL = src/Ic/DcpBundle/Controller/DoctorBillController.php */\n/* FORM = src/Ic/DcpBundle/Form/Type/BillFilterType.php */\n/* */\n/* Copied from the reviewed draft */\n/* scratchpad/p2/contract/bill-table.ts; the implementer owns it from */\n/* here and keeps it in step with design-bill-table.md. */\n/* -------------------------------------------------------------------- */\n\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport type {\n DataGridChange,\n DataGridPagination,\n DataGridWriteOptions,\n} from '../data-grid/types';\nimport type {\n DateRangeFilterModel,\n NumberFilterModel,\n} from '../_shared/table-toolbar/seam';\nimport type { EmptyStateHeadingLevel } from '../empty-state';\n\n/* ================================================================== */\n/* Closed enums */\n/* ================================================================== */\n\n/** Platform: `DoctorBill::DIRECTION_*` (DB:37-38), field `direction`\n * (DB:1198). `incoming` = a bill the practice received (a cost);\n * `outgoing` = a bill the practice issued (revenue). */\nexport const BILL_DIRECTIONS = ['incoming', 'outgoing'] as const;\nexport type BillDirection = (typeof BILL_DIRECTIONS)[number];\n\n/** Platform: `DoctorBill::TYPE_*` (DB:40-44), field `type` (DB:854).\n * `credit` is a credit note. Incoming SDI credit notes carry their kind in\n * `documentType` (DB:282, `getDocumentType()` DB:2480); the conversion\n * maps TD04 to `credit` (`CreateRealBillForIncomingBillService.php:115`)\n * and refuses TD08 as unsupported (`:103-111`). */\nexport const BILL_TYPES = [\n 'full',\n 'partial',\n 'credit',\n 'proforma',\n 'other',\n] as const;\nexport type BillType = (typeof BILL_TYPES)[number];\n\n/**\n * Payment state of the bill. The platform has NO field for it: the host\n * derives it per row, on MAGNITUDES (a credit note's gross, paid and\n * unpaid amounts are negative, `DoctorBill.php:341-342`), first match wins:\n * 1. `noPaymentDue`: `type === 'proforma'` (DB:43; `isProformaOrWrittenOff()`\n * DB:2045 forces unpaid to 0).\n * 2. `writtenOff`: `writtenOff` true (DB:177).\n * 3. `paid`: `getUnpaidAmount()` (DB:806; SQL `unpaid_amount`, REPO:1033)\n * is 0.\n * 4. `overdue`: |unpaid| > 0 and at least one open liability is due\n * (`Liability::isDue()`, LIAB:205-208).\n * 5. `partiallyPaid`: |`getPaidAmount()`| (DB:791; SQL `paid_amount`) > 0.\n * 6. `unpaid`: anything else.\n * Direction-neutral on purpose: one label per state.\n */\nexport const BILL_PAYMENT_STATUSES = [\n 'paid',\n 'partiallyPaid',\n 'unpaid',\n 'overdue',\n 'writtenOff',\n 'noPaymentDue',\n] as const;\nexport type BillPaymentStatus = (typeof BILL_PAYMENT_STATUSES)[number];\n\n/**\n * SDI (Sistema di Interscambio) state. The platform has NO field on the\n * bill: the host derives it, first match wins:\n * - `received`: incoming and `fatturazioneElettronicaIncomingBillId` set\n * (DB:207).\n * - `notApplicable`: practice country is not `it`, or an incoming bill\n * neither from SDI nor a self-bill (`isAutoBill()` DB:2461). Renders an\n * empty cell.\n * - outgoing (and incoming self-bills), from the latest sending snapshot\n * `FatturazioneElettronica\\Sending\\Bill` (SEND) and its batch `Sending`\n * (`STATE_*`, Sending.php:28-30):\n * - `notSent`: no snapshot row for the bill.\n * - `sending`: batch state `todo` or `waiting_to_be_sent`.\n * - `pending`: `sent` true (SEND:22), `result` null (SEND:24).\n * - `rejected`: `result === 'rejected'` (SEND:32).\n * - `notDelivered`: accepted and `nonDeliveryNotificationIncomingMessageId`\n * set (SEND:28).\n * - `delivered`: accepted and `deliveryReceiptIncomingMessageId` set\n * (SEND:27).\n * - `accepted`: `result === 'accepted'` (SEND:31), no receipt yet.\n */\nexport const BILL_SDI_STATUSES = [\n 'notApplicable',\n 'notSent',\n 'sending',\n 'pending',\n 'accepted',\n 'delivered',\n 'notDelivered',\n 'rejected',\n 'received',\n] as const;\nexport type BillSdiStatus = (typeof BILL_SDI_STATUSES)[number];\n\n/**\n * Warehouse loading state of an incoming SDI bill. NO platform field yet:\n * HTP-7309 adds the invoice-line reference on stock movements, which is the\n * single source (HTP-7312: \"no second status store\").\n * - `loaded`: at least one line of the bill carries a reference.\n * - `toReview`: automatic loading ran and found an unmatched line, or it is\n * switched off (HTP-7313).\n * - `notLoaded`: an incoming SDI bill with neither.\n * `null` or absent: not an incoming SDI bill, or no module (HTP-7314).\n * Renders an empty cell.\n */\nexport const BILL_WAREHOUSE_STATUSES = [\n 'notLoaded',\n 'toReview',\n 'loaded',\n] as const;\nexport type BillWarehouseStatus = (typeof BILL_WAREHOUSE_STATUSES)[number];\n\n/**\n * Who the counterparty is, for privacy. Privacy mode hides `patient` and\n * `person`; `company` stays visible.\n * - `patient`: a care-plan bill, `doctorCarePlan` (DB:92) set.\n * - `person`: an individual who is not a patient: `doctorOperator`\n * (DB:1208), or no linked entity and a snapshot with\n * `counterpartFirstName`/`counterpartLastName` (DB:113, DB:118) and no\n * `counterpartCompanyName` (DB:108).\n * - `company`: `doctorCompany` (DB:1203; a supplier or lab), or a snapshot\n * with `counterpartCompanyName`. NOTE: DoctorCompany has no person flag,\n * so a sole trader stored as a company shows.\n */\nexport const BILL_COUNTERPARTY_KINDS = [\n 'patient',\n 'person',\n 'company',\n] as const;\nexport type BillCounterpartyKind = (typeof BILL_COUNTERPARTY_KINDS)[number];\n\n/* ================================================================== */\n/* Row actions */\n/* ================================================================== */\n\n/**\n * Every row action BillTable can offer, in menu order. The first four are\n * the brief's; the rest keep today's list working and render only when the\n * host makes them available (see `BillRow.actions`).\n * - `open`: `ic_dcp_doctor_bill_show` (CTRL:1162).\n * - `downloadPdf`: `ic_dcp_doctor_bill_download` (CTRL:1275).\n * - `downloadXml`: outgoing or self-bill (`canHaveFatturazioneElettronicaXml()`\n * DB:2507) or received from SDI.\n * - `loadIntoWarehouse`: opens the HTP-7311 dialog, or the HTP-7314 upsell\n * without the module. Not tied to `showWarehouseStatus`.\n * - `edit`, `recordPayment`, `writeOff`, `undoWriteOff`, `delete`: today's\n * edit, per-liability \"Incassa\"/\"Pagato\", \"Stralcia\", \"Non più stralciare\"\n * and \"Elimina\".\n */\nexport const BILL_ROW_ACTIONS = [\n 'open',\n 'downloadPdf',\n 'downloadXml',\n 'loadIntoWarehouse',\n 'edit',\n 'recordPayment',\n 'writeOff',\n 'undoWriteOff',\n 'delete',\n] as const;\nexport type BillRowActionId = (typeof BILL_ROW_ACTIONS)[number];\n\n/**\n * Kit-owned reasons, so the copy exists in 18 languages.\n * - `alreadyLoaded`: one-load rule (HTP-7309, HTP-7311).\n * - `sentToSdi`, `legalStorage`: `dcp.doctor_bill.list.can_not_edit_message`\n * (canEditOrDelete false, `BillListDTO.canEditOrDelete`).\n * - `paymentAutomation`: `...can_not_edit_or_delete_payment_automation`.\n * - `noPermission`: the user lacks `doctor_bill_edit` / `practice_bill_delete`.\n * - `inProgress`: the host is already running this action for the row.\n */\nexport const BILL_ACTION_DISABLED_REASONS = [\n 'alreadyLoaded',\n 'sentToSdi',\n 'legalStorage',\n 'paymentAutomation',\n 'noPermission',\n 'inProgress',\n] as const;\nexport type BillActionDisabledReason =\n (typeof BILL_ACTION_DISABLED_REASONS)[number];\n\n/**\n * `'enabled'`, or disabled with a kit reason or a host text (translated\n * by the host). An action absent from the map is not shown.\n *\n * Don't name a person in the host text (nor in `error.description` or\n * `extraFilterLabels`): use a kit reason code where one fits. The kit\n * cannot tell whether a text names someone, so under privacy mode every\n * host text reads as kit copy, and agent reads carry only the code\n * `'host'`, never the text.\n */\nexport type BillRowActionState =\n | 'enabled'\n | { disabled: BillActionDisabledReason }\n | { disabled: { text: string } };\n\nexport type BillRowActionMap = Partial<\n Record<BillRowActionId, BillRowActionState>\n>;\n\n/** An action's state as an agent reads it: a host's own disabled text is\n * reduced to the code `'host'`, whatever privacy mode says, since it may\n * name a person. */\nexport type BillRowActionSummaryState =\n | 'enabled'\n | { disabled: BillActionDisabledReason | 'host' };\n\nexport type BillRowActionSummaryMap = Partial<\n Record<BillRowActionId, BillRowActionSummaryState>\n>;\n\n/* ================================================================== */\n/* Row */\n/* ================================================================== */\n\nexport interface BillCounterparty {\n kind: BillCounterpartyKind;\n /**\n * The linked entity's name as the list shows it today: the patient of\n * `doctorCarePlan` (DB:92), `doctorCompany.name` (DB:1203,\n * DoctorCompany.php:20) or the `doctorOperator` (DB:1208). Fallback for a\n * bill with no linked entity: `getRelevantCounterpartName()` (DB:2099).\n * NOT the SDI sending snapshot. Masked under privacy mode unless `kind`\n * is `company`.\n */\n name: string;\n /** The linked entity is soft-deleted (`DoctorCompany.deleted`,\n * DoctorCompany.php:94; list.html.twig:100-112 appends \"(cancellato)\"). */\n deleted?: boolean;\n}\n\nexport interface BillRow {\n /** `DoctorBill.id` (DB:82), as a string. The only field in the DOM. */\n id: string;\n /** `getNumberPrefixAndNumber()` (DB:1687): `incomingNumber` (DB:1617)\n * for incoming, `outgoingNumberPrefix` (DB:1607) + `outgoingNumber`\n * (DB:1612) for outgoing. Plain text, never masked: it names the row. */\n number: string;\n /** `DoctorBill.type` (DB:854). */\n type: BillType;\n /** `DoctorBill.date` (DB:72) as a calendar day `YYYY-MM-DD`. */\n date: string;\n /** `DoctorBill.direction` (DB:1198). */\n direction: BillDirection;\n /** `null` when the bill has no counterparty at all. */\n counterparty: BillCounterparty | null;\n /**\n * `getGross()` (DB:773; SQL alias `gross`, REPO:1018) in minor units:\n * the host sends `(int) round($gross * 100)` from PHP. Exact here only\n * because SQL already rounds `gross` to 2 places (REPO:1016-1018);\n * FatturaPA line values (up to 8 places) travel as decimal strings\n * instead (BillLineTable). Never parsed from a float string in the\n * browser. Sign as stored: negative for a credit note\n * (`DoctorBill::setNet` asserts net <= 0 for credit bills,\n * `DoctorBill.php:341-342`). The cell uses Money's default tone, so a\n * credit note reads as a minus sign, not an alarm. In the table's\n * `currency`. The amount FILTER is in major units (see\n * `BillTableFilterModel.amount`).\n */\n amountMinor: number;\n paymentStatus: BillPaymentStatus;\n /** Earliest open liability date (`DoctorBill.liabilities` DB:952,\n * `Liability.date`), `YYYY-MM-DD`; shown under `unpaid`,\n * `partiallyPaid` and `overdue` only. */\n nextDueDate?: string | null;\n sdiStatus: BillSdiStatus;\n /** See `BillWarehouseStatus`. Read only when `showWarehouseStatus`. */\n warehouseStatus?: BillWarehouseStatus | null;\n /** Per-row availability; absent action = hidden. `open` should always be\n * present (the bill number is the open control). */\n actions: BillRowActionMap;\n}\n\n/* ================================================================== */\n/* Totals */\n/* ================================================================== */\n\n/**\n * Sums over every bill that matches the query (all pages) for ONE\n * direction. Same sums as today (CTRL:289-297, GeneralManager.php:193-232),\n * split by direction because today's single sum adds costs and revenue\n * together. Minor units, `(int) round($sum * 100)` on the server (exact:\n * every summand is already at 2 places). Signed: credit notes count\n * negative, as stored.\n */\nexport interface BillDirectionTotals {\n /** Bills counted (`count($rows)`, GeneralManager.php:199-203). */\n count: number;\n /** Sum of SQL `gross` (REPO:1018). */\n grossMinor: number;\n /** Sum of `db.net` (DB:67). */\n netMinor: number;\n /** Sum of `db.vat` (DB:747). */\n vatMinor: number;\n /** Sum of `db.tax_at_source` (DB:1419). */\n taxAtSourceMinor: number;\n /** Sum of SQL `paid_amount` (REPO:1032). */\n paidMinor: number;\n /** Sum of SQL `unpaid_amount` (REPO:1033). */\n unpaidMinor: number;\n}\n\n/** A direction with no matching bill is `null` or absent and gets no line. */\nexport interface BillTableTotals {\n incoming?: BillDirectionTotals | null;\n outgoing?: BillDirectionTotals | null;\n}\n\n/* ================================================================== */\n/* Columns, sorting, filters, query */\n/* ================================================================== */\n\nexport const BILL_TABLE_COLUMNS = [\n 'number',\n 'date',\n 'direction',\n 'counterparty',\n 'amount',\n 'paymentStatus',\n 'sdiStatus',\n 'warehouseStatus',\n 'actions',\n] as const;\nexport type BillTableColumnId = (typeof BILL_TABLE_COLUMNS)[number];\n\n/** Columns the server can sort. Default: all four. */\nexport const BILL_TABLE_SORT_COLUMNS = [\n 'number',\n 'date',\n 'counterparty',\n 'amount',\n] as const;\nexport type BillTableSortColumn = (typeof BILL_TABLE_SORT_COLUMNS)[number];\n\nexport interface BillTableSortEntry {\n colId: BillTableSortColumn;\n sort: 'asc' | 'desc';\n}\n\n/** A set filter whose values are one of BillTable's enums. Assignable to\n * the kit `SelectFilterModel`. */\nexport interface BillSetFilter<TValue extends string> {\n type: 'set';\n values: TValue[];\n}\n\n/** Relative periods the server resolves on each request, so a saved tab\n * \"This year\" stays right next year. Replaces CTRL:160-163's fixed\n * `date_from`. */\nexport type BillDatePreset = 'today' | 'thisMonth' | 'thisYear';\n\n/**\n * Every filter BillTable carries. Column keys are evaluated by the server\n * from the column filters in the header; host keys are written by the\n * platform's own advanced-filter panel (`toolbarStart`) and are never\n * evaluated by the kit. Chips show a host key's label only, never its value.\n * A type alias (not an interface) so it is assignable to\n * `DataGridFilterModel`.\n */\nexport type BillTableFilterModel = {\n /* ---- column keys ---- */\n /** FORM `date_from`/`date_to`. */\n date?: DateRangeFilterModel;\n /** FORM `direction`. */\n direction?: BillSetFilter<BillDirection>;\n /** FORM `amount_from`/`amount_to` (`inRange`, either bound). MAJOR units\n * as typed (12.50), like the platform form. Note the unit differs from\n * `BillRow.amountMinor` (minor units): the server converts. */\n amount?: NumberFilterModel;\n /** New: needs the derived status in SQL. */\n paymentStatus?: BillSetFilter<BillPaymentStatus>;\n /** New: needs the derived status in SQL. */\n sdiStatus?: BillSetFilter<BillSdiStatus>;\n /** New (HTP-7312). Ignored by the server without the module. */\n warehouseStatus?: BillSetFilter<BillWarehouseStatus>;\n\n /* ---- host keys (the platform form, FORM:27-243) ---- */\n datePreset?: BillDatePreset;\n /** FORM `type` (multi). */\n type?: BillSetFilter<BillType>;\n /** FORM `number` (exact). Shares its id with the `number` column, so\n * DataGrid reads it as that column's key: its chip is named by the\n * column, not by `filterLabels` (a bill number is not personal data). */\n number?: string;\n /** FORM `prefix` (exact). */\n prefix?: string;\n /** FORM yes/no fields: `true` = yes, `false` = no, absent = any. */\n withInsuranceNet?: boolean;\n withVat?: boolean;\n withTaxAtSource?: boolean;\n withWelfareFundContribution?: boolean;\n withUnpaidAmount?: boolean;\n writtenOff?: boolean;\n /** FORM `tax_office_notification`. */\n taxOfficeNotification?: boolean;\n /** FORM `fatturazione_elettronica_incoming_bill`. */\n receivedFromSdi?: boolean;\n /** FORM `fatturazione_elettronica_sending_bill` (accepted by SDI,\n * CTRL:189-211). */\n sentToSdi?: boolean;\n /** FORM `self_bill`. */\n selfBill?: boolean;\n /** FORM `with_liability_from`/`_to`. */\n liabilityDate?: DateRangeFilterModel;\n /** FORM `sdi_entry_date_from`/`_to`. */\n sdiEntryDate?: DateRangeFilterModel;\n /** FORM `relation_type`. */\n relationType?: 'patient' | 'company' | 'operator';\n /** FORM `relation`: an entity id, never a name. */\n relation?: { type: 'patient' | 'company' | 'operator'; id: string };\n /** FORM `insurance`: an insurer key or `'none'`. */\n insurance?: string;\n /** FORM `personal_assistant`: a practice member id. */\n personalAssistant?: string;\n};\n\nexport type BillTableHostFilterKey = Exclude<\n keyof BillTableFilterModel,\n BillTableColumnId\n>;\n\n/** The query a host holds and feeds back (controlled). */\nexport interface BillTableQueryState {\n /** Default `[{ colId: 'date', sort: 'desc' }]` (CTRL:180-183). */\n sorting: BillTableSortEntry[];\n filters: BillTableFilterModel;\n /** Matches the bill number and, unless `privacyMode`, the counterparty\n * name. New on the platform (no free-text search today). */\n quickFilter: string;\n /** Zero-based. Default `{ pageIndex: 0, pageSize: 25 }`. */\n pagination: DataGridPagination;\n}\n\n/** What `onQueryChange` reports: the state plus the privacy flag, so the\n * server searches bill numbers only while names are hidden. */\nexport interface BillTableQuery extends BillTableQueryState {\n privacyMode: boolean;\n}\n\n/* ================================================================== */\n/* Callbacks */\n/* ================================================================== */\n\n/** Who triggered a row action: a person in the table, or the handle (an\n * agent). The platform can keep agent calls out of its analytics. */\nexport type BillActionSource = 'user' | 'api';\n\nexport interface BillActionContext {\n source: BillActionSource;\n}\n\n/** HTP-7312 analytics: `bill_warehouse_load_clicked { warehouse_status }`. */\nexport interface BillLoadContext extends BillActionContext {\n /** The row's status, or `null` (not computed without the module). */\n warehouseStatus: BillWarehouseStatus | null;\n}\n\nexport type BillDownloadFormat = 'pdf' | 'xml';\n\n/** List downloads that apply the current query to EVERY matching bill\n * (index.html.twig:91-131, IndexPage.js:29-34). Labels are kit copy. */\nexport const BILL_LIST_DOWNLOADS = [\n 'csv',\n 'csvDetailed',\n 'pdfZip',\n 'pdfSingle',\n 'xmlOutgoingZip',\n 'xmlIncomingZip',\n] as const;\nexport type BillListDownloadKind = (typeof BILL_LIST_DOWNLOADS)[number];\n\n/* ================================================================== */\n/* Props */\n/* ================================================================== */\n\nexport interface BillTableProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'children' | 'dir' | 'onChange'\n> {\n /* ===== data (server mode, always) ===== */\n\n /** The current page only. */\n rows: readonly BillRow[];\n /** Bills matching the query, all pages. `-1` = unknown. */\n rowCount: number;\n /** ISO 4217, for every amount (`current_doctor_address().currency`,\n * list.html.twig:2). Default `'EUR'`. */\n currency?: string;\n /** Server sums, all pages. Absent or `null`: no totals row (the user\n * lacks `practice_see_total_values`, index.html.twig:309-311). */\n totals?: BillTableTotals | null;\n\n /* ===== query (sorting, filters, quick search, paging) ===== */\n\n /** Controlled. Pair with `onQueryChange`. */\n query?: BillTableQueryState;\n /** Uncontrolled seed. */\n defaultQuery?: Partial<BillTableQueryState>;\n /** The single fetch trigger. Never fires on mount; fires once per change\n * of sorting, filters, quick search, page or page size (a sort, filter or\n * search change resets the page to 0), whatever the source (the UI, the\n * handle, a DataGridTabs switch, a new controlled `query`), and once when\n * `privacyMode` changes while a quick search or a counterparty sort is\n * active. That last emission is DataGrid's (the query carries the\n * effective sort: a counterparty sort is paused, not sent, while names\n * are hidden, and comes back when privacy mode turns off); BillTable only\n * adds `privacyMode` to it and never emits on its own. A controlled host\n * stores what this reports and passes it back as `query`. */\n onQueryChange?: (query: BillTableQuery) => void;\n /** Columns the server can sort. Default all of\n * `BILL_TABLE_SORT_COLUMNS`. */\n sortableColumns?: readonly BillTableSortColumn[];\n /** Default `[25, 50, 100]`. */\n pageSizeOptions?: readonly number[];\n\n /* ===== selection ===== */\n\n /** Checkbox column and bulk actions. Default `true`; `false` for a\n * read-only list. */\n selectable?: boolean;\n /** Controlled ids, every page. Survives paging and sorting; cleared when\n * filters or quick search change (DataGrid\n * `clearSelectionOnFilterChange`, always on). */\n selection?: readonly string[];\n defaultSelection?: readonly string[];\n onSelectionChange?: (ids: string[]) => void;\n\n /* ===== columns ===== */\n\n /** Adds the warehouse status column (HTP-7314: practices with the\n * module). Does not affect the `loadIntoWarehouse` action. */\n showWarehouseStatus?: boolean;\n /** BillTable's `data-component-id` and agent instance id, and the inner\n * DataGrid's column-state storage key. Default `'accounting-bills'`.\n * The inner DataGrid gets `registerAgent={false}`, so only\n * `billTableAgent` registers under this id. */\n gridId?: string;\n /** Default `true`. */\n persistColumnState?: boolean;\n\n /* ===== row actions (the host does the work; the kit never fetches) ===== */\n\n onOpen: (row: BillRow, context: BillActionContext) => void;\n onDownload?: (\n row: BillRow,\n format: BillDownloadFormat,\n context: BillActionContext,\n ) => void;\n onLoadIntoWarehouse?: (row: BillRow, context: BillLoadContext) => void;\n onEdit?: (row: BillRow, context: BillActionContext) => void;\n onRecordPayment?: (row: BillRow, context: BillActionContext) => void;\n /** `revert` true = \"Undo write-off\". */\n onWriteOff?: (\n row: BillRow,\n revert: boolean,\n context: BillActionContext,\n ) => void;\n /** The host confirms (AlertDialog) before deleting. */\n onDelete?: (row: BillRow, context: BillActionContext) => void;\n\n /* ===== bulk and list actions ===== */\n\n /** Shows \"Download PDFs\" and \"Download XML files\" for the selection. */\n onBulkDownload?: (ids: string[], format: BillDownloadFormat) => void;\n /** List downloads offered in the toolbar's download menu, in this order.\n * Default none. */\n listDownloads?: readonly BillListDownloadKind[];\n onListDownload?: (kind: BillListDownloadKind, query: BillTableQuery) => void;\n /** Shows the toolbar Refresh button. */\n onRefresh?: () => void;\n\n /* ===== toolbar ===== */\n\n /** Host content at the start of the filter bar: the platform's\n * \"Show advanced filters\" trigger, whose panel writes host keys through\n * the controlled `query` or `handle.setFilter`. */\n toolbarStart?: ReactNode;\n /** Chip labels for extra host keys the platform adds later (translated\n * by the host). Kit keys already have kit labels. Don't name a person\n * in a label. */\n extraFilterLabels?: Record<string, string>;\n\n /* ===== states ===== */\n\n /** Default `'ready'`. */\n status?: 'ready' | 'loading' | 'error';\n /** Overrides `ui.billTable.error.*`; `onRetry` shows \"Try again\".\n * Don't name a person in the title or description. */\n error?: { title?: string; description?: string; onRetry?: () => void };\n /** First-use action (\"Add bill\"); omitted when the user cannot create. */\n onCreateBill?: () => void;\n /** Heading level for the empty and error states. Default 3. */\n headingLevel?: EmptyStateHeadingLevel;\n\n /* ===== privacy and layout ===== */\n\n /** Masks patient and person names; companies stay visible. Default\n * `false`. */\n privacyMode?: boolean;\n /** Default `t('billTable.caption')`, \"Bills\". */\n caption?: string;\n /** Default `'default'`. */\n density?: 'default' | 'compact';\n /** `'fill'`: BillTable fills a flex column parent and its grid becomes\n * the bounded scroll container, so the header and the totals row stay\n * in view and a page above 100 rows is virtualised. Give the parent a\n * bounded block size. Default `'auto'` (the grid grows with its rows). */\n height?: 'auto' | 'fill';\n}\n\n/* ================================================================== */\n/* Handle */\n/* ================================================================== */\n\nexport interface BillTableFeatureInfo {\n selectable: boolean;\n privacyMode: boolean;\n showWarehouseStatus: boolean;\n sortableColumns: BillTableSortColumn[];\n status: 'ready' | 'loading' | 'error';\n}\n\nexport interface BillTableColumnInfo {\n id: BillTableColumnId;\n /** Plain, translated name. */\n label: string;\n visible: boolean;\n canHide: boolean;\n sortable: boolean;\n /** Masked by privacy mode (counterparty while `privacyMode`). */\n masked: boolean;\n}\n\n/**\n * One bill as an agent may read it (state slot `rows`). The counterparty\n * name is present only for `company`; patients and other people are never\n * named here, whatever `privacyMode` says (agent state carries no PHI,\n * `src/agent/types.ts:76-80`).\n */\nexport interface BillRowSummary {\n id: string;\n number: string;\n type: BillType;\n date: string;\n direction: BillDirection;\n counterpartyKind: BillCounterpartyKind | null;\n counterpartyName?: string;\n amountMinor: number;\n paymentStatus: BillPaymentStatus;\n sdiStatus: BillSdiStatus;\n warehouseStatus: BillWarehouseStatus | null;\n /** Reason codes only: a host's own text reads as `'host'`. */\n actions: BillRowActionSummaryMap;\n}\n\n/** Who caused a change, as DataGrid reports it. */\nexport type BillTableChange = DataGridChange;\n\n/**\n * Curated handle (`ref`). Ids and kit shapes only: no DataGrid handle, no\n * TanStack object, no row object, no DOM node. Reads go to the live grid,\n * so a read straight after a write is fresh.\n *\n * Saved views: wrap BillTable in `DataGridTabs`. The DataGrid inside\n * registers itself with the tabs through context, so no `getTable` is\n * needed. This handle is not a `DataGridTabsSeam` (the seam also needs\n * `applyView`, `isPrivacyMode` and DataGrid's full column info), so do not\n * pass it as `getTable`.\n */\nexport interface BillTableHandle {\n getFeatures(): BillTableFeatureInfo;\n\n /* ---- query ---- */\n /** The effective query, as `onQueryChange` reports it (a paused\n * counterparty sort left out under privacy mode). */\n getQuery(): BillTableQuery;\n /** Refused (no-op, DEV warning) for a column outside `sortableColumns`\n * or masked by privacy mode. The server sorts by one column: only the\n * first entry is used. */\n setSort(model: readonly BillTableSortEntry[]): void;\n /** Every filter the table holds: column models and host keys, a filter\n * paused by privacy mode included. */\n getFilter(): BillTableFilterModel;\n setFilter(model: BillTableFilterModel, options?: DataGridWriteOptions): void;\n getQuickFilter(): string;\n setQuickFilter(text: string, options?: DataGridWriteOptions): void;\n clearFilters(): void;\n goToPage(pageIndex: number): void;\n setPageSize(size: number): void;\n /** `-1` when the total is unknown. */\n getPageCount(): number;\n getRowCount(): number;\n /** The current page, display order. */\n getRowIds(): string[];\n\n /* ---- selection ---- */\n getSelection(): string[];\n setSelection(ids: readonly string[]): void;\n selectRange(fromId: string, toId: string): void;\n clearSelection(): void;\n\n /* ---- columns ---- */\n getColumns(): BillTableColumnInfo[];\n setColumnVisible(id: BillTableColumnId, visible: boolean): void;\n resetColumns(): void;\n\n /* ---- focus ---- */\n scrollToRow(id: string): void;\n /** Focus the row's control in `columnId` (`number` = the open button,\n * `actions` = the menu button). Default `number`. */\n focusRow(id: string, columnId?: 'number' | 'actions'): void;\n\n /* ---- rows (agent-safe projection, current page) ---- */\n /** Never a patient's or person's name; see `BillRowSummary`. */\n getRowSummaries(): BillRowSummary[];\n\n /* ---- row actions (same callbacks as the UI, source 'api') ---- */\n /** The actions the table offers for the row: entries of `row.actions`\n * whose callback is set (`open` always has one). Under privacy mode\n * every host's own disabled text reads as kit copy, whatever the\n * counterparty. For the host; agents read `getRowSummaries()`, which\n * carries reason codes only. Throws `UNKNOWN_ROW`. */\n getRowActions(id: string): BillRowActionMap;\n /** Throws `UNKNOWN_ROW`, `ACTION_UNAVAILABLE` (absent from the row's map,\n * or no callback) or `ACTION_DISABLED: <reason>`, where the reason is the\n * kit code or `host` (never a host's text). */\n openBill(id: string): void;\n downloadBill(id: string, format: BillDownloadFormat): void;\n loadIntoWarehouse(id: string): void;\n\n /* ---- change feed ---- */\n subscribe(listener: (change: BillTableChange) => void): () => void;\n}\n\n/* ================================================================== */\n/* Default saved views (DataGridTabs) */\n/* ================================================================== */\n\n/** Stable tab ids (developer constants; emitted as `data-tab-id`). */\nexport const BILL_TABLE_DEFAULT_TAB_IDS = [\n 'bills-this-year',\n 'bills-all',\n 'bills-incoming',\n 'bills-outgoing',\n 'bills-to-pay',\n 'bills-to-collect',\n 'bills-to-load',\n] as const;\nexport type BillTableDefaultTabId = (typeof BILL_TABLE_DEFAULT_TAB_IDS)[number];\n","/* -------------------------------------------------------------------- */\n/* BillTable: pure helpers shared by the component, the handle and the */\n/* agent projection. No React, no translation. */\n/* */\n/* Money rule (money.mdx, \"Money from the platform\"): every amount here */\n/* is an integer in hundredths, as the platform sends it. The kit never */\n/* adds, subtracts or rounds a bill amount or a total, and never turns */\n/* one into a float by division: display goes through Money's exact */\n/* `scale` path, export through the `./decimal` helpers. */\n/* -------------------------------------------------------------------- */\n\nimport { decimalToNumber } from '../_shared/decimal';\nimport { formatLocale } from '../_shared/intl-locale';\nimport type { DataGridSortEntry } from '../data-grid/types';\nimport {\n BILL_ROW_ACTIONS,\n BILL_TABLE_SORT_COLUMNS,\n type BillActionContext,\n type BillActionDisabledReason,\n type BillRow,\n type BillRowActionId,\n type BillRowActionMap,\n type BillRowActionState,\n type BillRowActionSummaryMap,\n type BillRowSummary,\n type BillTableProps,\n type BillTableSortColumn,\n type BillTableSortEntry,\n} from './types';\n\n/* ================================================================== */\n/* Constants */\n/* ================================================================== */\n\n/** Default `gridId`: BillTable's agent instance id and the inner\n * DataGrid's column-state storage key. */\nexport const BILL_TABLE_DEFAULT_GRID_ID = 'accounting-bills';\n\n/** The platform's default order (`DoctorBillController.php:180-183`). */\nexport const BILL_TABLE_DEFAULT_SORT: readonly BillTableSortEntry[] = [\n { colId: 'date', sort: 'desc' },\n];\n\n/** Page sizes the pager offers. The largest equals DataGrid's\n * virtualisation threshold, so a page keeps every row in the DOM. */\nexport const BILL_TABLE_PAGE_SIZE_OPTIONS: readonly number[] = [25, 50, 100];\n\n/**\n * Decimal places of every amount BillTable receives: `BillRow.amountMinor`\n * and the `BillDirectionTotals` sums are `(int) round($x * 100)` from PHP\n * (exact, because SQL already rounds gross to 2 places,\n * `DoctrineBillRepository.php:1016-1018`). Money gets it as `scale`, so the\n * integer is formatted with integer arithmetic and never divided as a float.\n */\nexport const BILL_AMOUNT_SCALE = 2;\n\n/** Context of a row action a person started in the table. */\nexport const USER_ACTION: BillActionContext = { source: 'user' };\n\n/** Context of a row action started through the handle (an agent). */\nexport const API_ACTION: BillActionContext = { source: 'api' };\n\n/* ================================================================== */\n/* Rows */\n/* ================================================================== */\n\n/**\n * Does privacy mode hide this row's counterparty? Patients and other\n * people are hidden; companies (suppliers, labs) stay visible; a bill\n * with no counterparty has nothing to hide. Michael's privacy decision\n * (4 Nov 2026); also the counterparty column's `appliesTo`.\n */\nexport function isPersonCounterparty(row: BillRow): boolean {\n return row.counterparty !== null && row.counterparty.kind !== 'company';\n}\n\n/**\n * The amount as a number in major units, for CSV, XLSX and PDF. Built from\n * the integer with the exact decimal helpers (`12345` gives `123.45`), so\n * the number is the nearest double to the decimal and no division happens.\n * `null` for a value that is not a safe integer or that a double cannot\n * give back exactly (beyond 15 significant digits): the cell exports empty\n * rather than a wrong figure.\n */\nexport function amountForExport(amountMinor: number): number | null {\n if (!Number.isSafeInteger(amountMinor)) return null;\n return decimalToNumber({ units: amountMinor, scale: BILL_AMOUNT_SCALE });\n}\n\n/* Building an `Intl.DateTimeFormat` costs far more than using one, and a\n page repeats the same locale in every row. */\nconst dayFormatters = new Map<string, Intl.DateTimeFormat>();\nconst CALENDAR_DAY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\n/**\n * A calendar day `YYYY-MM-DD` in the UI language, medium style (\"4 Nov\n * 2026\" in British English). Read and formatted in UTC, so the day never\n * moves with the viewer's time zone. Any other text is returned as given.\n */\nexport function formatCalendarDay(day: string, language: string): string {\n const match = CALENDAR_DAY.exec(day);\n if (!match) return day;\n const [, year, month, date] = match;\n const instant = new Date(\n Date.UTC(Number(year), Number(month) - 1, Number(date)),\n );\n if (Number.isNaN(instant.getTime())) return day;\n const locale = formatLocale(language);\n let formatter = dayFormatters.get(locale);\n if (!formatter) {\n formatter = new Intl.DateTimeFormat(locale, {\n dateStyle: 'medium',\n timeZone: 'UTC',\n });\n dayFormatters.set(locale, formatter);\n }\n return formatter.format(instant);\n}\n\n/* ================================================================== */\n/* Sorting */\n/* ================================================================== */\n\nconst SORT_COLUMNS: ReadonlySet<string> = new Set(BILL_TABLE_SORT_COLUMNS);\n\nexport function isBillTableSortColumn(\n colId: string,\n): colId is BillTableSortColumn {\n return SORT_COLUMNS.has(colId);\n}\n\n/** DataGrid sort entries as BillTable's typed entries. Only sortable bill\n * columns can be in a DataGrid sort; anything else is left out. */\nexport function toBillSortEntries(\n entries: readonly DataGridSortEntry[],\n): BillTableSortEntry[] {\n const out: BillTableSortEntry[] = [];\n for (const entry of entries) {\n if (isBillTableSortColumn(entry.colId)) {\n out.push({ colId: entry.colId, sort: entry.sort });\n }\n }\n return out;\n}\n\n/** A stable text for comparing two sorts. */\nexport function sortKey(entries: readonly DataGridSortEntry[]): string {\n return entries.map((entry) => `${entry.colId}:${entry.sort}`).join('|');\n}\n\n/**\n * What the last `onQueryChange` reported: the effective sort it carried,\n * and the sort the grid itself held at that moment.\n */\nexport interface BillSortEcho {\n key: string;\n raw: readonly BillTableSortEntry[];\n}\n\n/**\n * The sorting to hand the inner DataGrid when the host controls `query`.\n *\n * Under privacy mode `onQueryChange` reports the EFFECTIVE sort: a\n * counterparty sort is paused, so it is left out. A host that stores that\n * query and passes it back would erase the paused entry, which then could\n * not come back when privacy mode turns off, and the grid would report the\n * same query a second time. So while the host's sorting is exactly what\n * BillTable last reported, the grid keeps the sort it holds itself. Any\n * other sorting is a host decision and wins.\n */\nexport function resolveControlledSorting(\n hostSorting: readonly BillTableSortEntry[],\n echo: BillSortEcho | null,\n): readonly BillTableSortEntry[] {\n if (echo && sortKey(hostSorting) === echo.key) return echo.raw;\n return hostSorting;\n}\n\n/* ================================================================== */\n/* Row actions */\n/* ================================================================== */\n\n/** The host callbacks behind the row actions. */\nexport type BillTableCallbacks = Pick<\n BillTableProps,\n | 'onOpen'\n | 'onDownload'\n | 'onLoadIntoWarehouse'\n | 'onEdit'\n | 'onRecordPayment'\n | 'onWriteOff'\n | 'onDelete'\n>;\n\n/** The callback each action needs: an action shows only when the row's\n * map lists it AND this callback is set. */\nexport const BILL_ACTION_CALLBACK: Readonly<\n Record<BillRowActionId, keyof BillTableCallbacks>\n> = {\n open: 'onOpen',\n downloadPdf: 'onDownload',\n downloadXml: 'onDownload',\n loadIntoWarehouse: 'onLoadIntoWarehouse',\n edit: 'onEdit',\n recordPayment: 'onRecordPayment',\n writeOff: 'onWriteOff',\n undoWriteOff: 'onWriteOff',\n delete: 'onDelete',\n};\n\nexport function hasActionCallback(\n callbacks: BillTableCallbacks,\n action: BillRowActionId,\n): boolean {\n return typeof callbacks[BILL_ACTION_CALLBACK[action]] === 'function';\n}\n\n/** The kit reason code of a disabled action, or `'host'` for a host's own\n * text. Never the host text itself: it may name a person. */\nexport function disabledReasonCode(\n state: Exclude<BillRowActionState, 'enabled'>,\n): BillActionDisabledReason | 'host' {\n return typeof state.disabled === 'string' ? state.disabled : 'host';\n}\n\n/**\n * The actions the table offers for one row, as the HOST reads them:\n * entries of `row.actions` whose callback is set, in menu order. Under\n * privacy mode every host's own disabled text gives way to\n * `hiddenReasonText` (kit copy), whatever the counterparty kind: the kit\n * cannot tell whether a text names someone. Kit reason codes stay. Agents\n * never read this; they read `summariseActions`.\n */\nexport function offeredActions(\n row: BillRow,\n callbacks: BillTableCallbacks,\n privacyMode: boolean,\n hiddenReasonText: string,\n): BillRowActionMap {\n const offered: BillRowActionMap = {};\n for (const action of BILL_ROW_ACTIONS) {\n const state = row.actions[action];\n if (state === undefined || !hasActionCallback(callbacks, action)) continue;\n offered[action] =\n privacyMode && state !== 'enabled' && typeof state.disabled !== 'string'\n ? { disabled: { text: hiddenReasonText } }\n : state;\n }\n return offered;\n}\n\n/**\n * The actions the table offers for one row, as an AGENT reads them: the\n * same entries as `offeredActions`, with every disabled reason as its code.\n * A host's own text is always `'host'`, privacy mode or not, since it may\n * name a person (agent state carries no PHI, `src/agent/types.ts`).\n */\nexport function summariseActions(\n row: BillRow,\n callbacks: BillTableCallbacks,\n): BillRowActionSummaryMap {\n const offered: BillRowActionSummaryMap = {};\n for (const action of BILL_ROW_ACTIONS) {\n const state = row.actions[action];\n if (state === undefined || !hasActionCallback(callbacks, action)) continue;\n offered[action] =\n state === 'enabled' ? 'enabled' : { disabled: disabledReasonCode(state) };\n }\n return offered;\n}\n\n/**\n * One bill as an agent may read it. The counterparty name is given for a\n * company only: a patient's or another person's name is never in agent\n * state, privacy mode or not (`src/agent/types.ts`, state slots carry no\n * PHI). Disabled reasons are codes only, never a host's text.\n */\nexport function summariseBillRow(\n row: BillRow,\n callbacks: BillTableCallbacks,\n): BillRowSummary {\n const summary: BillRowSummary = {\n id: row.id,\n number: row.number,\n type: row.type,\n date: row.date,\n direction: row.direction,\n counterpartyKind: row.counterparty?.kind ?? null,\n amountMinor: row.amountMinor,\n paymentStatus: row.paymentStatus,\n sdiStatus: row.sdiStatus,\n warehouseStatus: row.warehouseStatus ?? null,\n actions: summariseActions(row, callbacks),\n };\n if (row.counterparty?.kind === 'company') {\n summary.counterpartyName = row.counterparty.name;\n }\n return summary;\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: closed enums to badge variant and copy. */\n/* */\n/* One map per enum. Every key is a literal string and the maps are */\n/* `as const`, so `t(MAP[value].key, MAP[value].en)` resolves to the */\n/* finite set of keys for the i18n inventory check, and the English */\n/* default sits next to its key. Badge colours are Michael's decisions */\n/* (4 Nov 2026) and design-bill-table.md section 1.2. */\n/* -------------------------------------------------------------------- */\n\nimport type {\n BillActionDisabledReason,\n BillDirection,\n BillListDownloadKind,\n BillPaymentStatus,\n BillRowActionId,\n BillSdiStatus,\n BillType,\n BillWarehouseStatus,\n} from './types';\n\n/** The Badge variants BillTable uses. */\nexport type BillBadgeVariant =\n | 'neutral'\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\ninterface BillCopy {\n readonly key: string;\n readonly en: string;\n}\n\ninterface BillStatusCopy extends BillCopy {\n readonly variant: BillBadgeVariant;\n}\n\n/** Every row action but `open`: the bill number is the open control, so\n * `open` is never a menu item. */\nexport type BillMenuActionId = Exclude<BillRowActionId, 'open'>;\n\n/** Payment status. `unpaid` is warning because the platform paints \"Da\n * incassare / Da pagare\" `text-warning` today; `overdue` is error. */\nexport const BILL_PAYMENT_STATUS_COPY = {\n paid: { key: 'billTable.paymentStatus.paid', en: 'Paid', variant: 'success' },\n partiallyPaid: {\n key: 'billTable.paymentStatus.partiallyPaid',\n en: 'Partly paid',\n variant: 'warning',\n },\n unpaid: {\n key: 'billTable.paymentStatus.unpaid',\n en: 'Unpaid',\n variant: 'warning',\n },\n overdue: {\n key: 'billTable.paymentStatus.overdue',\n en: 'Overdue',\n variant: 'error',\n },\n writtenOff: {\n key: 'billTable.paymentStatus.writtenOff',\n en: 'Written off',\n variant: 'neutral',\n },\n noPaymentDue: {\n key: 'billTable.paymentStatus.noPaymentDue',\n en: 'No payment due',\n variant: 'neutral',\n },\n} as const satisfies Record<BillPaymentStatus, BillStatusCopy>;\n\n/** SDI status. `notApplicable` has no entry: it renders an empty cell and\n * is not a filter option. `notDelivered` is warning, not error: the\n * invoice is legally issued and needs a follow-up, not a resend. */\nexport const BILL_SDI_STATUS_COPY = {\n notSent: {\n key: 'billTable.sdiStatus.notSent',\n en: 'Not sent',\n variant: 'neutral',\n },\n sending: {\n key: 'billTable.sdiStatus.sending',\n en: 'Sending',\n variant: 'info',\n },\n pending: {\n key: 'billTable.sdiStatus.pending',\n en: 'Awaiting SDI',\n variant: 'warning',\n },\n accepted: {\n key: 'billTable.sdiStatus.accepted',\n en: 'Accepted',\n variant: 'success',\n },\n delivered: {\n key: 'billTable.sdiStatus.delivered',\n en: 'Delivered',\n variant: 'success',\n },\n notDelivered: {\n key: 'billTable.sdiStatus.notDelivered',\n en: 'Not delivered',\n variant: 'warning',\n },\n rejected: {\n key: 'billTable.sdiStatus.rejected',\n en: 'Rejected',\n variant: 'error',\n },\n received: {\n key: 'billTable.sdiStatus.received',\n en: 'Received from SDI',\n variant: 'info',\n },\n} as const satisfies Record<\n Exclude<BillSdiStatus, 'notApplicable'>,\n BillStatusCopy\n>;\n\n/** Warehouse status: Not loaded neutral, To review warning, Loaded success\n * (Michael, 4 Nov 2026). */\nexport const BILL_WAREHOUSE_STATUS_COPY = {\n notLoaded: {\n key: 'billTable.warehouseStatus.notLoaded',\n en: 'Not loaded',\n variant: 'neutral',\n },\n toReview: {\n key: 'billTable.warehouseStatus.toReview',\n en: 'To review',\n variant: 'warning',\n },\n loaded: {\n key: 'billTable.warehouseStatus.loaded',\n en: 'Loaded',\n variant: 'success',\n },\n} as const satisfies Record<BillWarehouseStatus, BillStatusCopy>;\n\nexport const BILL_DIRECTION_COPY = {\n incoming: { key: 'billTable.direction.incoming', en: 'Incoming' },\n outgoing: { key: 'billTable.direction.outgoing', en: 'Outgoing' },\n} as const satisfies Record<BillDirection, BillCopy>;\n\n/** The muted line under the bill number. A final bill (`full`) shows no\n * line, so it has no entry. */\nexport const BILL_TYPE_COPY = {\n partial: { key: 'billTable.type.partial', en: 'Deposit' },\n credit: { key: 'billTable.type.credit', en: 'Credit note' },\n proforma: { key: 'billTable.type.proforma', en: 'Pro forma' },\n other: { key: 'billTable.type.other', en: 'Other document' },\n} as const satisfies Record<Exclude<BillType, 'full'>, BillCopy>;\n\n/** Row-menu items, in menu order (design section 3.6). */\nexport const BILL_ACTION_COPY = {\n downloadPdf: { key: 'billTable.action.downloadPdf', en: 'Download PDF' },\n downloadXml: { key: 'billTable.action.downloadXml', en: 'Download XML' },\n loadIntoWarehouse: {\n key: 'billTable.action.loadIntoWarehouse',\n en: 'Load into warehouse',\n },\n edit: { key: 'billTable.action.edit', en: 'Edit' },\n recordPayment: {\n key: 'billTable.action.recordPayment',\n en: 'Record payment',\n },\n writeOff: {\n key: 'billTable.action.writeOff',\n en: 'Write off the unpaid amount',\n },\n undoWriteOff: { key: 'billTable.action.undoWriteOff', en: 'Undo write-off' },\n delete: { key: 'billTable.action.delete', en: 'Delete' },\n} as const satisfies Record<BillMenuActionId, BillCopy>;\n\n/** Kit-owned reasons for a disabled action, so the copy exists in every\n * language. */\nexport const BILL_DISABLED_REASON_COPY = {\n alreadyLoaded: {\n key: 'billTable.disabledReason.alreadyLoaded',\n en: 'This bill is already in the warehouse.',\n },\n sentToSdi: {\n key: 'billTable.disabledReason.sentToSdi',\n en: 'This bill was sent to SDI, so it cannot be changed.',\n },\n legalStorage: {\n key: 'billTable.disabledReason.legalStorage',\n en: 'This bill is in legal storage, so it cannot be changed.',\n },\n paymentAutomation: {\n key: 'billTable.disabledReason.paymentAutomation',\n en: 'This bill has automatic payments, so it cannot be changed.',\n },\n noPermission: {\n key: 'billTable.disabledReason.noPermission',\n en: 'You do not have permission to do this.',\n },\n inProgress: {\n key: 'billTable.disabledReason.inProgress',\n en: 'Already in progress.',\n },\n} as const satisfies Record<BillActionDisabledReason, BillCopy>;\n\n/** List downloads in the toolbar's download menu. */\nexport const BILL_LIST_DOWNLOAD_COPY = {\n csv: { key: 'billTable.export.csv', en: 'CSV' },\n csvDetailed: {\n key: 'billTable.export.csvDetailed',\n en: 'CSV with treatments',\n },\n pdfZip: { key: 'billTable.export.pdfZip', en: 'ZIP with one PDF per bill' },\n pdfSingle: { key: 'billTable.export.pdfSingle', en: 'One PDF' },\n xmlOutgoingZip: {\n key: 'billTable.export.xmlOutgoingZip',\n en: 'ZIP of sent electronic invoices (XML)',\n },\n xmlIncomingZip: {\n key: 'billTable.export.xmlIncomingZip',\n en: 'ZIP of electronic invoices received from SDI (XML)',\n },\n} as const satisfies Record<BillListDownloadKind, BillCopy>;\n","/* -------------------------------------------------------------------- */\n/* BillTable: what each cell and footer cell shows. */\n/* */\n/* Always rendered inside the BillTable root, which carries the bounding */\n/* marker, through its DataGrid, which renders the table sections and the */\n/* cells around them. Kit leaves only (Badge, Money, Button, IconButton, */\n/* InfoTip, Popover, VisuallyHidden); no row datum goes into an */\n/* attribute: names are text, */\n/* and controls are named by reference. */\n/* -------------------------------------------------------------------- */\n\nimport { useId } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { ArrowDownLeft, ArrowUpRight, Info } from 'lucide-react';\n\nimport { Badge } from '../badge/badge';\nimport { Button } from '../button/button';\nimport { IconButton } from '../button/icon-button';\nimport { InfoTip } from '../info-tip/info-tip';\nimport { Money } from '../money/money';\nimport { Popover } from '../popover/popover';\nimport { VisuallyHidden } from '../visually-hidden/visually-hidden';\nimport { accessibleTargetSquareClass } from '../_shared/accessible-target';\nimport { formatNumber } from '../_shared/format-number';\nimport {\n breakdownGroupVariants,\n breakdownListVariants,\n breakdownTermVariants,\n breakdownTextVariants,\n breakdownValueVariants,\n breakdownVariants,\n cellStackVariants,\n directionIconVariants,\n inlineGroupVariants,\n numberTextVariants,\n openButtonVariants,\n secondaryTextVariants,\n truncatedTextVariants,\n} from './bill-table.variants';\nimport { BILL_AMOUNT_SCALE, formatCalendarDay } from './model';\nimport {\n BILL_DIRECTION_COPY,\n BILL_DISABLED_REASON_COPY,\n BILL_PAYMENT_STATUS_COPY,\n BILL_SDI_STATUS_COPY,\n BILL_TYPE_COPY,\n BILL_WAREHOUSE_STATUS_COPY,\n type BillBadgeVariant,\n} from './status-maps';\nimport {\n BILL_DIRECTIONS,\n type BillCounterparty,\n type BillDirection,\n type BillPaymentStatus,\n type BillRow,\n type BillSdiStatus,\n type BillTableTotals,\n type BillWarehouseStatus,\n} from './types';\n\n/* ================================================================== */\n/* Number: the row header and the open control */\n/* ================================================================== */\n\nexport interface OpenBillCellProps {\n row: BillRow;\n /** Id of the static hidden \"Open bill\" text the table renders once. */\n openHintId: string;\n onOpen: (row: BillRow) => void;\n /** Privacy mode is on: a host's own disabled text gives way to kit copy,\n * whatever the counterparty (the kit cannot tell whether it names\n * someone). */\n hideHostText: boolean;\n}\n\n/**\n * The bill number. It names the row (the column is the row header) and is\n * the open control: a link-styled kit Button whose accessible name is the\n * visible number, so the row reads \"A12\", with the static \"Open bill\" as\n * its description. With no `open` in the row's map it is plain text. A\n * disabled `open` stays focusable and adds its reason to the description.\n * Non-final bills show their type on a muted second line.\n */\nexport function OpenBillCell({\n row,\n openHintId,\n onOpen,\n hideHostText,\n}: OpenBillCellProps) {\n const { t } = useTranslation('ui');\n const reasonId = useId();\n const state = row.actions.open;\n\n let typeLine: string | null = null;\n if (row.type !== 'full') {\n const copy = BILL_TYPE_COPY[row.type];\n typeLine = t(copy.key, copy.en);\n }\n\n let reason: string | null = null;\n if (state !== undefined && state !== 'enabled') {\n if (typeof state.disabled === 'string') {\n const copy = BILL_DISABLED_REASON_COPY[state.disabled];\n reason = t(copy.key, copy.en);\n } else {\n reason = hideHostText\n ? t(\n 'billTable.disabledReason.privacyHidden',\n 'Not available (reason hidden in privacy mode)',\n )\n : state.disabled.text;\n }\n }\n\n return (\n <span className={cellStackVariants()}>\n {state === undefined ? (\n <span className={numberTextVariants()}>{row.number}</span>\n ) : (\n <Button\n intent=\"link\"\n size=\"sm\"\n className={openButtonVariants()}\n aria-describedby={reason ? `${openHintId} ${reasonId}` : openHintId}\n // Not the HTML attribute: the button stays a Tab stop, so its\n // reason can be reached. The click guard below refuses it.\n aria-disabled={reason ? true : undefined}\n onClick={(event) => {\n if (reason) {\n event.preventDefault();\n return;\n }\n onOpen(row);\n }}\n >\n {row.number}\n </Button>\n )}\n {reason ? (\n <span hidden id={reasonId}>\n {reason}\n </span>\n ) : null}\n {typeLine ? (\n <span className={secondaryTextVariants()}>{typeLine}</span>\n ) : null}\n </span>\n );\n}\n\n/* ================================================================== */\n/* Date, direction, counterparty */\n/* ================================================================== */\n\n/** A calendar day in the UI language, read in UTC so it never shifts. */\nexport function CalendarDayCell({ day }: { day: string }) {\n const { i18n } = useTranslation('ui');\n return <span>{formatCalendarDay(day, i18n.language)}</span>;\n}\n\n/** The direction arrow, decorative (the label is always beside it). */\nexport function DirectionIcon({ direction }: { direction: BillDirection }) {\n const Icon = direction === 'incoming' ? ArrowDownLeft : ArrowUpRight;\n return <Icon aria-hidden=\"true\" className={directionIconVariants()} />;\n}\n\n/** Arrow and visible label: \"Incoming\" or \"Outgoing\". */\nexport function DirectionLabel({ direction }: { direction: BillDirection }) {\n const { t } = useTranslation('ui');\n const copy = BILL_DIRECTION_COPY[direction];\n return (\n <span className={inlineGroupVariants()}>\n <DirectionIcon direction={direction} />\n <span>{t(copy.key, copy.en)}</span>\n </span>\n );\n}\n\n/**\n * The counterparty's name, in its own text direction and truncated with\n * the full text in the DOM; a muted \"Deleted\" line for a deleted entity.\n * Never rendered for a masked cell: under privacy mode DataGrid shows the\n * mask for patients and people instead of calling the column's `cell`.\n */\nexport function CounterpartyCell({\n counterparty,\n}: {\n counterparty: BillCounterparty | null;\n}) {\n const { t } = useTranslation('ui');\n if (counterparty === null) {\n return (\n <span className={secondaryTextVariants()}>\n {t('billTable.counterparty.none', 'No counterparty')}\n </span>\n );\n }\n return (\n <span className={cellStackVariants()}>\n <span dir=\"auto\" className={truncatedTextVariants()}>\n {counterparty.name}\n </span>\n {counterparty.deleted ? (\n <span className={secondaryTextVariants()}>\n {t('billTable.counterparty.deleted', 'Deleted')}\n </span>\n ) : null}\n </span>\n );\n}\n\n/**\n * An amount in hundredths, in the table currency. Money's default tone: a\n * credit note is negative as stored and reads as a minus sign, not as an\n * alarm. `scale` keeps Money on its exact integer path.\n */\nexport function AmountCell({\n amountMinor,\n currency,\n}: {\n amountMinor: number;\n currency: string;\n}) {\n return (\n <Money\n size=\"sm\"\n value={amountMinor}\n currency={currency}\n scale={BILL_AMOUNT_SCALE}\n />\n );\n}\n\n/* ================================================================== */\n/* Statuses */\n/* ================================================================== */\n\n/** A status as text with a decorative dot: never colour alone. */\nfunction StatusBadge({\n label,\n variant,\n}: {\n label: string;\n variant: BillBadgeVariant;\n}) {\n return (\n <Badge size=\"sm\" variant={variant} withDot>\n {label}\n </Badge>\n );\n}\n\n/** Statuses that still have money to settle: they show the next due day. */\nconst DUE_STATUSES = new Set<BillPaymentStatus>([\n 'unpaid',\n 'partiallyPaid',\n 'overdue',\n]);\n\nexport function PaymentStatusCell({\n status,\n nextDueDate,\n}: {\n status: BillPaymentStatus;\n nextDueDate: string | null;\n}) {\n const { t, i18n } = useTranslation('ui');\n const copy = BILL_PAYMENT_STATUS_COPY[status];\n return (\n <span className={cellStackVariants()}>\n <StatusBadge label={t(copy.key, copy.en)} variant={copy.variant} />\n {nextDueDate && DUE_STATUSES.has(status) ? (\n <span className={secondaryTextVariants()}>\n {t('billTable.paymentStatus.due', 'Due {{date}}', {\n date: formatCalendarDay(nextDueDate, i18n.language),\n })}\n </span>\n ) : null}\n </span>\n );\n}\n\n/** Empty for `notApplicable` (not an Italian electronic invoice). */\nexport function SdiStatusCell({ status }: { status: BillSdiStatus }) {\n const { t } = useTranslation('ui');\n if (status === 'notApplicable') return null;\n const copy = BILL_SDI_STATUS_COPY[status];\n return <StatusBadge label={t(copy.key, copy.en)} variant={copy.variant} />;\n}\n\n/** Empty for `null` (not an incoming SDI bill, or no warehouse module). */\nexport function WarehouseStatusCell({\n status,\n}: {\n status: BillWarehouseStatus | null;\n}) {\n const { t } = useTranslation('ui');\n if (status === null) return null;\n const copy = BILL_WAREHOUSE_STATUS_COPY[status];\n return <StatusBadge label={t(copy.key, copy.en)} variant={copy.variant} />;\n}\n\n/** The InfoTip beside the \"SDI status\" header, outside its sort button. */\nexport function SdiHeaderTip() {\n const { t } = useTranslation('ui');\n return (\n <InfoTip\n size=\"sm\"\n content={t(\n 'billTable.sdiHelp',\n 'SDI is the Italian exchange system for electronic invoices.',\n )}\n />\n );\n}\n\n/* ================================================================== */\n/* Totals row */\n/* ================================================================== */\n\n/** One label and amount pair of the breakdown. */\nfunction BreakdownEntry({\n label,\n value,\n currency,\n}: {\n label: string;\n value: number;\n currency: string;\n}) {\n return (\n <>\n <dt className={breakdownTermVariants()}>{label}</dt>\n <dd className={breakdownValueVariants()}>\n <Money\n size=\"sm\"\n value={value}\n currency={currency}\n scale={BILL_AMOUNT_SCALE}\n />\n </dd>\n </>\n );\n}\n\n/** Today's six sums and the count, per present direction, as given by the\n * server. The kit adds, subtracts and rounds nothing. */\nfunction TotalsBreakdown({\n totals,\n currency,\n}: {\n totals: BillTableTotals;\n currency: string;\n}) {\n const { t, i18n } = useTranslation('ui');\n return (\n <div className={breakdownVariants()}>\n {BILL_DIRECTIONS.map((direction) => {\n const sums = totals[direction];\n if (!sums) return null;\n return (\n <div key={direction} className={breakdownGroupVariants()}>\n <p className={breakdownTextVariants({ tone: 'strong' })}>\n <DirectionLabel direction={direction} />\n <span>\n {t('billTable.totals.count', '{{formatted}} bills', {\n count: sums.count,\n formatted: formatNumber(sums.count, i18n.language),\n })}\n </span>\n </p>\n <dl className={breakdownListVariants()}>\n <BreakdownEntry\n label={t('billTable.totals.gross', 'Gross')}\n value={sums.grossMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.net', 'Net')}\n value={sums.netMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.vat', 'VAT')}\n value={sums.vatMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.taxAtSource', 'Withholding tax')}\n value={sums.taxAtSourceMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.paid', 'Paid')}\n value={sums.paidMinor}\n currency={currency}\n />\n <BreakdownEntry\n label={t('billTable.totals.unpaid', 'Unpaid')}\n value={sums.unpaidMinor}\n currency={currency}\n />\n </dl>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * The totals row header (`<th scope=\"row\">`): \"Total\" and a \"Totals\n * breakdown\" button that opens a kit Popover in click mode: a dialog\n * named by its heading, with the scope note as its description and every\n * sum per direction. Focus moves into the dialog on open, so a screen\n * reader user reaches the sums; Escape closes it and returns focus to the\n * button. The table does not widen.\n */\nexport function TotalsHeaderCell({\n totals,\n currency,\n}: {\n totals: BillTableTotals;\n currency: string;\n}) {\n const { t } = useTranslation('ui');\n const breakdown = t('billTable.totals.breakdown', 'Totals breakdown');\n return (\n <span className={inlineGroupVariants()}>\n <span>{t('dataTable.totalRow', 'Total')}</span>\n <Popover>\n <Popover.Trigger asChild>\n <IconButton\n intent=\"ghost\"\n size=\"sm\"\n icon={<Info aria-hidden=\"true\" />}\n aria-label={breakdown}\n className={accessibleTargetSquareClass}\n />\n </Popover.Trigger>\n <Popover.Content side=\"top\" align=\"start\" size=\"md\">\n <Popover.Heading>{breakdown}</Popover.Heading>\n <Popover.Description>\n {t(\n 'billTable.totals.scope',\n 'Every bill that matches the filters, on all pages.',\n )}\n </Popover.Description>\n <TotalsBreakdown totals={totals} currency={currency} />\n </Popover.Content>\n </Popover>\n </span>\n );\n}\n\n/**\n * One line per present direction, as the server gave it (all pages, never\n * mixed: a sum of costs and revenue means nothing). The amount column\n * shows the gross with the direction label; the payment column shows what\n * is still unpaid, its direction named for screen readers and drawn by the\n * same arrow as the amount line beside it.\n */\nexport function DirectionTotalsCell({\n totals,\n field,\n currency,\n}: {\n totals: BillTableTotals;\n field: 'grossMinor' | 'unpaidMinor';\n currency: string;\n}) {\n const { t } = useTranslation('ui');\n return (\n <span\n className={cellStackVariants({\n align: field === 'grossMinor' ? 'end' : 'start',\n })}\n >\n {BILL_DIRECTIONS.map((direction) => {\n const sums = totals[direction];\n if (!sums) return null;\n const copy = BILL_DIRECTION_COPY[direction];\n const directionText = t(copy.key, copy.en);\n return (\n <span key={direction} className={inlineGroupVariants()}>\n <DirectionIcon direction={direction} />\n {field === 'grossMinor' ? (\n <span>{directionText}</span>\n ) : (\n <>\n <VisuallyHidden>{directionText}</VisuallyHidden>\n <span>{t('billTable.totals.unpaid', 'Unpaid')}</span>\n </>\n )}\n <Money\n size=\"sm\"\n value={sums[field]}\n currency={currency}\n scale={BILL_AMOUNT_SCALE}\n />\n </span>\n );\n })}\n </span>\n );\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: the column definitions on the DataGrid column API. */\n/* */\n/* Reading copy: design-bill-table.md section 2. Widths are the initial */\n/* px (`size` puts the grid in fixed layout); tiers show a column from */\n/* 640, 900 or 1,200 px of grid width, and a user's own choice in */\n/* ColumnToggle always wins. Every cell renders inside the BillTable root */\n/* through its DataGrid; only `row.id` reaches the DOM (`data-row-id`). */\n/* -------------------------------------------------------------------- */\n\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { DataGridColumn, DataGridOption } from '../data-grid/types';\nimport type { NumberFilterOperator } from '../_shared/table-toolbar/seam';\nimport { RowActions, type RowActionDef } from '../row-actions/row-actions';\nimport { VisuallyHidden } from '../visually-hidden/visually-hidden';\nimport {\n AmountCell,\n CalendarDayCell,\n CounterpartyCell,\n DirectionLabel,\n DirectionTotalsCell,\n OpenBillCell,\n PaymentStatusCell,\n SdiHeaderTip,\n SdiStatusCell,\n TotalsHeaderCell,\n WarehouseStatusCell,\n} from './cells';\nimport { amountForExport, isPersonCounterparty } from './model';\nimport {\n BILL_DIRECTION_COPY,\n BILL_PAYMENT_STATUS_COPY,\n BILL_SDI_STATUS_COPY,\n BILL_WAREHOUSE_STATUS_COPY,\n} from './status-maps';\nimport {\n BILL_DIRECTIONS,\n BILL_PAYMENT_STATUSES,\n BILL_SDI_STATUSES,\n BILL_WAREHOUSE_STATUSES,\n type BillDirection,\n type BillPaymentStatus,\n type BillRow,\n type BillSdiStatus,\n type BillTableSortColumn,\n type BillTableTotals,\n type BillWarehouseStatus,\n} from './types';\n\n/** The amount filter's conditions; `inRange` first, as the platform form\n * (`amount_from` / `amount_to`). Bounds are major units, as typed. */\nconst AMOUNT_FILTER_OPERATORS: readonly NumberFilterOperator[] = [\n 'inRange',\n 'greaterThanOrEqual',\n 'lessThanOrEqual',\n 'equals',\n];\n\ntype BillSdiFilterStatus = Exclude<BillSdiStatus, 'notApplicable'>;\n\n/** SDI filter values: every status but `notApplicable`, which renders an\n * empty cell and is not something to filter by. */\nconst SDI_FILTER_STATUSES: readonly BillSdiFilterStatus[] =\n BILL_SDI_STATUSES.filter(\n (status): status is BillSdiFilterStatus => status !== 'notApplicable',\n );\n\nexport interface UseBillTableColumnsOptions {\n /** ISO 4217, for every amount and the amount filter. */\n currency: string;\n showWarehouseStatus: boolean;\n sortableColumns: readonly BillTableSortColumn[];\n /** Absent: no totals row (no column gets a footer). */\n totals: BillTableTotals | null;\n privacyMode: boolean;\n /** Id of the static hidden \"Open bill\" text. */\n openHintId: string;\n /** Stable; calls the host's `onOpen` with `source: 'user'`. */\n onOpenRow: (row: BillRow) => void;\n /** Stable kit RowActions definitions (`useBillRowActions`). */\n rowActions: readonly RowActionDef<BillRow>[];\n}\n\n/** BillTable's DataGrid columns, rebuilt only when an input changes. */\nexport function useBillTableColumns({\n currency,\n showWarehouseStatus,\n sortableColumns,\n totals,\n privacyMode,\n openHintId,\n onOpenRow,\n rowActions,\n}: UseBillTableColumnsOptions): DataGridColumn<BillRow>[] {\n const { t } = useTranslation('ui');\n // A host may pass a new array each render; the set of columns is what\n // matters.\n const sortableKey = sortableColumns.join('|');\n\n return useMemo(() => {\n const sortable = new Set(sortableKey.split('|'));\n\n const directionLabel = (direction: BillDirection): string => {\n const copy = BILL_DIRECTION_COPY[direction];\n return t(copy.key, copy.en);\n };\n const paymentLabel = (status: BillPaymentStatus): string => {\n const copy = BILL_PAYMENT_STATUS_COPY[status];\n return t(copy.key, copy.en);\n };\n const sdiLabel = (status: BillSdiFilterStatus): string => {\n const copy = BILL_SDI_STATUS_COPY[status];\n return t(copy.key, copy.en);\n };\n const warehouseLabel = (status: BillWarehouseStatus): string => {\n const copy = BILL_WAREHOUSE_STATUS_COPY[status];\n return t(copy.key, copy.en);\n };\n // Select filters in server mode need their options (a page cannot\n // derive them). Values are the enum values, never labels.\n const options = <TValue extends string>(\n values: readonly TValue[],\n label: (value: TValue) => string,\n ): DataGridOption[] =>\n values.map((value) => ({ value, label: label(value) }));\n\n const actionsLabel = t('dataTable.actions', 'Actions');\n\n const columns: DataGridColumn<BillRow>[] = [\n {\n id: 'number',\n header: t('billTable.column.number', 'Number'),\n // The number names the row: `<th scope=\"row\">`, \"Select A12\",\n // \"Actions, A12\". Pinned at the inline start, always shown.\n rowHeader: true,\n pin: 'start',\n hideable: false,\n reorderable: false,\n pinnable: false,\n size: 136,\n minSize: 112,\n value: (row) => row.number,\n exportValue: (row) => row.number,\n sort: sortable.has('number') ? 'text' : undefined,\n cell: (row) => (\n <OpenBillCell\n row={row}\n openHintId={openHintId}\n onOpen={onOpenRow}\n hideHostText={privacyMode}\n />\n ),\n footer: totals ? (\n <TotalsHeaderCell totals={totals} currency={currency} />\n ) : undefined,\n },\n {\n id: 'date',\n header: t('billTable.column.date', 'Date'),\n size: 120,\n responsiveTier: 1,\n // A calendar day `YYYY-MM-DD`; DataGrid formats it for export.\n value: (row) => row.date,\n sort: sortable.has('date') ? 'date' : undefined,\n sortDescFirst: true,\n // One request per range: the server filters on Apply.\n filter: { kind: 'dateRange', commitMode: 'apply' },\n search: false,\n cell: (row) => <CalendarDayCell day={row.date} />,\n },\n {\n id: 'direction',\n header: t('billTable.column.direction', 'Direction'),\n size: 132,\n responsiveTier: 1,\n value: (row) => row.direction,\n exportValue: (row) => directionLabel(row.direction),\n filter: {\n kind: 'select',\n options: options(BILL_DIRECTIONS, directionLabel),\n },\n search: false,\n cell: (row) => <DirectionLabel direction={row.direction} />,\n },\n {\n id: 'counterparty',\n header: t('billTable.column.counterparty', 'Counterparty'),\n size: 240,\n minSize: 160,\n value: (row) => row.counterparty?.name ?? null,\n // Off while privacy mode is on: the whole column leaves sorting and\n // the server query (DataGrid's whole-column privacy rule).\n sort: sortable.has('counterparty') ? 'text' : undefined,\n // Patients and other people are masked; companies stay visible.\n privacy: { mode: 'mask', appliesTo: isPersonCounterparty },\n cell: (row) => <CounterpartyCell counterparty={row.counterparty} />,\n },\n {\n id: 'amount',\n header: t('billTable.column.amount', 'Amount'),\n align: 'end',\n size: 136,\n value: (row) => row.amountMinor,\n exportValue: (row) => amountForExport(row.amountMinor),\n sort: sortable.has('amount') ? 'number' : undefined,\n sortDescFirst: true,\n // A currency NumberInput in the table currency. Bounds are MAJOR\n // units as typed (12.50), like the platform's amount_from/_to;\n // the server converts. Rows carry minor units.\n filter: {\n kind: 'number',\n mode: 'currency',\n currency,\n operators: AMOUNT_FILTER_OPERATORS,\n defaultOperator: 'inRange',\n },\n search: false,\n cell: (row) => (\n <AmountCell amountMinor={row.amountMinor} currency={currency} />\n ),\n footer: totals ? (\n <DirectionTotalsCell\n totals={totals}\n field=\"grossMinor\"\n currency={currency}\n />\n ) : undefined,\n },\n {\n id: 'paymentStatus',\n header: t('billTable.column.paymentStatus', 'Payment status'),\n size: 168,\n responsiveTier: 2,\n value: (row) => row.paymentStatus,\n exportValue: (row) => paymentLabel(row.paymentStatus),\n filter: {\n kind: 'select',\n options: options(BILL_PAYMENT_STATUSES, paymentLabel),\n },\n search: false,\n cell: (row) => (\n <PaymentStatusCell\n status={row.paymentStatus}\n nextDueDate={row.nextDueDate ?? null}\n />\n ),\n footer: totals ? (\n <DirectionTotalsCell\n totals={totals}\n field=\"unpaidMinor\"\n currency={currency}\n />\n ) : undefined,\n },\n {\n id: 'sdiStatus',\n header: t('billTable.column.sdiStatus', 'SDI status'),\n headerTip: <SdiHeaderTip />,\n size: 168,\n responsiveTier: 3,\n value: (row) =>\n row.sdiStatus === 'notApplicable' ? null : row.sdiStatus,\n exportValue: (row) =>\n row.sdiStatus === 'notApplicable' ? '' : sdiLabel(row.sdiStatus),\n filter: {\n kind: 'select',\n options: options(SDI_FILTER_STATUSES, sdiLabel),\n },\n search: false,\n cell: (row) => <SdiStatusCell status={row.sdiStatus} />,\n },\n ];\n\n if (showWarehouseStatus) {\n columns.push({\n id: 'warehouseStatus',\n header: t('billTable.column.warehouseStatus', 'Warehouse status'),\n size: 152,\n responsiveTier: 2,\n value: (row) => row.warehouseStatus ?? null,\n exportValue: (row) =>\n row.warehouseStatus ? warehouseLabel(row.warehouseStatus) : '',\n filter: {\n kind: 'select',\n options: options(BILL_WAREHOUSE_STATUSES, warehouseLabel),\n },\n search: false,\n cell: (row) => (\n <WarehouseStatusCell status={row.warehouseStatus ?? null} />\n ),\n });\n }\n\n columns.push({\n id: 'actions',\n header: <VisuallyHidden>{actionsLabel}</VisuallyHidden>,\n headerLabel: actionsLabel,\n pin: 'end',\n size: 64,\n hideable: false,\n reorderable: false,\n pinnable: false,\n resizable: false,\n exportable: false,\n printable: false,\n search: false,\n // Kit RowActions, menu only: one \"More actions\" button per row, the\n // group named by reference (\"Actions, A12\"), never by row data in an\n // attribute. A row that offers no menu item renders no button.\n cell: (row, context) => (\n <RowActions\n row={row}\n actions={rowActions}\n maxInline={0}\n aria-labelledby={context.inputLabelledBy}\n />\n ),\n });\n\n return columns;\n }, [\n t,\n currency,\n showWarehouseStatus,\n sortableKey,\n totals,\n privacyMode,\n openHintId,\n onOpenRow,\n rowActions,\n ]);\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: the curated handle (`ref`). */\n/* */\n/* Built over the inner DataGrid's handle and the props of the last */\n/* render. It hands out ids and kit shapes only: never the DataGrid */\n/* handle, a TanStack object, a row object or a DOM node. Reads go to the */\n/* live grid, so a read straight after a write is fresh (DataGrid's */\n/* freshness rule). Row actions call the same host callbacks as the UI, */\n/* with `source: 'api'`, after the same availability checks; a refused */\n/* call throws an Error whose message starts with its code. */\n/* -------------------------------------------------------------------- */\n\nimport { isDevelopment } from '../_shared/is-development';\nimport {\n DATA_GRID_DEFAULT_PAGE_SIZE,\n type DataGridHandle,\n} from '../data-grid/types';\nimport {\n API_ACTION,\n disabledReasonCode,\n hasActionCallback,\n offeredActions,\n summariseBillRow,\n toBillSortEntries,\n type BillTableCallbacks,\n} from './model';\nimport {\n BILL_TABLE_COLUMNS,\n type BillDownloadFormat,\n type BillRow,\n type BillRowActionId,\n type BillTableColumnId,\n type BillTableColumnInfo,\n type BillTableFeatureInfo,\n type BillTableFilterModel,\n type BillTableHandle,\n type BillTableQuery,\n} from './types';\n\n/** What the handle reads from the last render. */\nexport interface BillTableLive {\n /** The current page. */\n rows: readonly BillRow[];\n callbacks: BillTableCallbacks;\n features: BillTableFeatureInfo;\n /** Kit copy that stands in for every host's own disabled text under\n * privacy mode (host reads only; agent reads carry codes). */\n hiddenReasonText: string;\n}\n\ntype BillTableHandleErrorCode =\n | 'UNKNOWN_ROW'\n | 'ACTION_UNAVAILABLE'\n | 'ACTION_DISABLED';\n\nfunction refuse(code: BillTableHandleErrorCode, detail: string): never {\n throw new Error(`${code}: ${detail}`);\n}\n\nfunction warn(message: string): void {\n if (isDevelopment()) console.warn(`[BillTable] ${message}`);\n}\n\nconst COLUMN_IDS: ReadonlySet<string> = new Set(BILL_TABLE_COLUMNS);\n\nfunction isBillTableColumnId(id: string): id is BillTableColumnId {\n return COLUMN_IDS.has(id);\n}\n\n/** Ids of the columns privacy mode masks right now (the counterparty\n * while `privacyMode` is on). */\nfunction maskedColumnIds(grid: DataGridHandle): Set<string> {\n return new Set(\n grid\n .getColumns()\n .filter((column) => column.masked === true)\n .map((column) => column.id),\n );\n}\n\nexport function createBillTableHandle(\n gridRef: { readonly current: DataGridHandle | null },\n liveRef: { readonly current: BillTableLive },\n): BillTableHandle {\n const grid = (): DataGridHandle | null => gridRef.current;\n const live = (): BillTableLive => liveRef.current;\n\n function findRow(id: string): BillRow {\n const row = live().rows.find((candidate) => candidate.id === id);\n return row ?? refuse('UNKNOWN_ROW', `no bill \"${id}\" on the current page.`);\n }\n\n /** The row and callbacks for an action the row offers and allows. */\n function prepare(\n id: string,\n action: BillRowActionId,\n ): { row: BillRow; callbacks: BillTableCallbacks } {\n const row = findRow(id);\n const { callbacks } = live();\n const state = row.actions[action];\n if (state === undefined || !hasActionCallback(callbacks, action)) {\n refuse('ACTION_UNAVAILABLE', `bill \"${id}\" does not offer ${action}.`);\n }\n if (state !== 'enabled') {\n // The kit reason code, or `host`: never a host's text, which may\n // name a person.\n refuse('ACTION_DISABLED', disabledReasonCode(state));\n }\n return { row, callbacks };\n }\n\n return {\n getFeatures() {\n const { features } = live();\n return { ...features, sortableColumns: [...features.sortableColumns] };\n },\n\n /* ---- query ---- */\n\n getQuery(): BillTableQuery {\n const handle = grid();\n const { privacyMode } = live().features;\n if (!handle) {\n return {\n sorting: [],\n filters: {},\n quickFilter: '',\n pagination: { pageIndex: 0, pageSize: DATA_GRID_DEFAULT_PAGE_SIZE },\n privacyMode,\n };\n }\n // The effective query, as `onQueryChange` reports it: a masked\n // column's sort entries and filter keys are paused, not sent.\n const masked = maskedColumnIds(handle);\n const filters: Record<string, unknown> = { ...handle.getFilter() };\n for (const key of Object.keys(filters)) {\n if (masked.has(key)) delete filters[key];\n }\n return {\n sorting: toBillSortEntries(\n handle.getSort().filter((entry) => !masked.has(entry.colId)),\n ),\n filters: filters as BillTableFilterModel,\n quickFilter: handle.getQuickFilter(),\n pagination: {\n pageIndex: handle.getCurrentPage(),\n pageSize: handle.getPageSize(),\n },\n privacyMode,\n };\n },\n\n setSort(model) {\n const handle = grid();\n if (!handle) return;\n const { sortableColumns } = live().features;\n const masked = maskedColumnIds(handle);\n for (const entry of model) {\n if (!sortableColumns.includes(entry.colId)) {\n warn(`setSort: the server does not sort \"${entry.colId}\".`);\n return;\n }\n if (masked.has(entry.colId)) {\n warn(`setSort: \"${entry.colId}\" is hidden by privacy mode.`);\n return;\n }\n }\n if (model.length > 1) {\n warn('setSort: the server sorts by one column; the first one is used.');\n }\n handle.setSort(model.slice(0, 1));\n },\n\n getFilter() {\n return { ...(grid()?.getFilter() ?? {}) } as BillTableFilterModel;\n },\n\n setFilter(model, options) {\n grid()?.setFilter(model, options);\n },\n\n getQuickFilter() {\n return grid()?.getQuickFilter() ?? '';\n },\n\n setQuickFilter(text, options) {\n grid()?.setQuickFilter(text, options);\n },\n\n clearFilters() {\n grid()?.clearFilters();\n },\n\n goToPage(pageIndex) {\n grid()?.goToPage(pageIndex);\n },\n\n setPageSize(size) {\n grid()?.setPageSize(size);\n },\n\n getPageCount() {\n return grid()?.getPageCount() ?? 0;\n },\n\n getRowCount() {\n return grid()?.getRowCount() ?? 0;\n },\n\n getRowIds() {\n return grid()?.getRowIds() ?? live().rows.map((row) => row.id);\n },\n\n /* ---- selection ---- */\n\n getSelection() {\n return grid()?.getSelection() ?? [];\n },\n\n setSelection(ids) {\n grid()?.setSelection(ids);\n },\n\n selectRange(fromId, toId) {\n grid()?.selectRange(fromId, toId);\n },\n\n clearSelection() {\n grid()?.clearSelection();\n },\n\n /* ---- columns ---- */\n\n getColumns() {\n const handle = grid();\n if (!handle) return [];\n const { privacyMode } = live().features;\n const columns: BillTableColumnInfo[] = [];\n for (const column of handle.getColumns()) {\n if (!isBillTableColumnId(column.id)) continue;\n columns.push({\n id: column.id,\n label: column.label,\n visible: column.visible,\n canHide: column.canHide,\n sortable: column.sortable,\n // DataGrid reports `masked`; a missing value counts as masked\n // for the counterparty while privacy mode is on.\n masked:\n column.masked ?? (privacyMode && column.id === 'counterparty'),\n });\n }\n return columns;\n },\n\n setColumnVisible(id, visible) {\n grid()?.setColumnVisible(id, visible);\n },\n\n resetColumns() {\n grid()?.resetColumnState();\n },\n\n /* ---- focus ---- */\n\n scrollToRow(id) {\n grid()?.scrollToRow(id);\n },\n\n focusRow(id, columnId = 'number') {\n grid()?.focusRow(id, columnId);\n },\n\n /* ---- rows (agent-safe projection) ---- */\n\n getRowSummaries() {\n const { rows, callbacks } = live();\n return rows.map((row) => summariseBillRow(row, callbacks));\n },\n\n /* ---- row actions ---- */\n\n getRowActions(id) {\n const row = findRow(id);\n const { callbacks, features, hiddenReasonText } = live();\n return offeredActions(\n row,\n callbacks,\n features.privacyMode,\n hiddenReasonText,\n );\n },\n\n openBill(id) {\n const { row, callbacks } = prepare(id, 'open');\n callbacks.onOpen(row, API_ACTION);\n },\n\n downloadBill(id, format: BillDownloadFormat) {\n if (format !== 'pdf' && format !== 'xml') {\n refuse('ACTION_UNAVAILABLE', `unknown format \"${String(format)}\".`);\n }\n const { row, callbacks } = prepare(\n id,\n format === 'xml' ? 'downloadXml' : 'downloadPdf',\n );\n callbacks.onDownload?.(row, format, API_ACTION);\n },\n\n loadIntoWarehouse(id) {\n const { row, callbacks } = prepare(id, 'loadIntoWarehouse');\n callbacks.onLoadIntoWarehouse?.(row, {\n ...API_ACTION,\n warehouseStatus: row.warehouseStatus ?? null,\n });\n },\n\n /* ---- change feed ---- */\n\n subscribe(listener) {\n return grid()?.subscribe(listener) ?? (() => {});\n },\n };\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: the row menu as kit RowActions definitions. */\n/* */\n/* The actions column is the kit `RowActions` leaf with `maxInline={0}`: */\n/* one \"More actions\" button per row (one Tab stop), its menu in this */\n/* order (design section 3.6): downloads, warehouse, bill actions, then */\n/* delete in the destructive style, with a separator between the groups */\n/* (RowActions `section`). `open` is never here: the bill */\n/* number opens the bill. An action shows when the row's map lists it AND */\n/* its callback is set; a disabled one stays focusable in the menu and */\n/* shows its reason as the item's second line. BillTable composes nothing */\n/* of its own around RowActions. */\n/* -------------------------------------------------------------------- */\n\nimport { createElement, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n CircleOff,\n FileCode,\n FileText,\n HandCoins,\n PackagePlus,\n Pencil,\n Trash2,\n Undo2,\n type LucideIcon,\n} from 'lucide-react';\n\nimport type { RowActionDef } from '../row-actions/row-actions';\nimport { USER_ACTION, type BillTableCallbacks } from './model';\nimport {\n BILL_ACTION_COPY,\n BILL_DISABLED_REASON_COPY,\n type BillMenuActionId,\n} from './status-maps';\nimport type { BillRow } from './types';\n\n/** Design 3.6 menu groups. Developer constants, never row data. */\nconst BILL_ACTION_SECTION: Record<BillMenuActionId, string> = {\n downloadPdf: 'downloads',\n downloadXml: 'downloads',\n loadIntoWarehouse: 'warehouse',\n edit: 'bill',\n recordPayment: 'bill',\n writeOff: 'bill',\n undoWriteOff: 'bill',\n delete: 'delete',\n};\n\n/** Which optional callbacks the host passed. Each one adds its items. */\nexport interface BillRowActionAvailability {\n download: boolean;\n loadIntoWarehouse: boolean;\n edit: boolean;\n recordPayment: boolean;\n writeOff: boolean;\n delete: boolean;\n}\n\nexport interface UseBillRowActionsOptions {\n /** The host callbacks as of the last render, read when an item runs, so\n * a host's inline functions never rebuild the menu. */\n callbacksRef: { readonly current: BillTableCallbacks };\n available: BillRowActionAvailability;\n /** Under privacy mode every host's own disabled text gives way to kit\n * copy, whatever the counterparty: the kit cannot tell whether a text\n * names someone. */\n privacyMode: boolean;\n}\n\n/** The RowActions definitions for every row of the table. */\nexport function useBillRowActions({\n callbacksRef,\n available,\n privacyMode,\n}: UseBillRowActionsOptions): RowActionDef<BillRow>[] {\n const { t } = useTranslation('ui');\n const {\n download,\n loadIntoWarehouse,\n edit,\n recordPayment,\n writeOff,\n delete: remove,\n } = available;\n\n return useMemo(() => {\n const hiddenReason = t(\n 'billTable.disabledReason.privacyHidden',\n 'Not available (reason hidden in privacy mode)',\n );\n\n /** The translated reason of a disabled item, or `undefined`. */\n const reasonFor = (\n row: BillRow,\n action: BillMenuActionId,\n ): string | undefined => {\n const state = row.actions[action];\n if (state === undefined || state === 'enabled') return undefined;\n if (typeof state.disabled === 'string') {\n const copy = BILL_DISABLED_REASON_COPY[state.disabled];\n return t(copy.key, copy.en);\n }\n return privacyMode ? hiddenReason : state.disabled.text;\n };\n\n const item = (\n action: BillMenuActionId,\n icon: LucideIcon,\n run: (row: BillRow) => void,\n variant: 'default' | 'destructive' = 'default',\n ): RowActionDef<BillRow> => {\n const copy = BILL_ACTION_COPY[action];\n return {\n // Developer constant: React key and `data-action-id`, never row data.\n id: action,\n // Design 3.6 menu group: the menu draws a separator between groups.\n section: BILL_ACTION_SECTION[action],\n icon: createElement(icon, { 'aria-hidden': true }),\n label: t(copy.key, copy.en),\n onClick: run,\n variant,\n hidden: (row) => row.actions[action] === undefined,\n disabled: (row) => {\n const state = row.actions[action];\n return state !== undefined && state !== 'enabled';\n },\n disabledReason: (row) => reasonFor(row, action),\n };\n };\n\n const callbacks = () => callbacksRef.current;\n const items: RowActionDef<BillRow>[] = [];\n if (download) {\n items.push(\n item('downloadPdf', FileText, (row) =>\n callbacks().onDownload?.(row, 'pdf', USER_ACTION),\n ),\n item('downloadXml', FileCode, (row) =>\n callbacks().onDownload?.(row, 'xml', USER_ACTION),\n ),\n );\n }\n if (loadIntoWarehouse) {\n items.push(\n item('loadIntoWarehouse', PackagePlus, (row) =>\n callbacks().onLoadIntoWarehouse?.(row, {\n ...USER_ACTION,\n // HTP-7312 analytics: `bill_warehouse_load_clicked\n // { warehouse_status }`; `null` without the module.\n warehouseStatus: row.warehouseStatus ?? null,\n }),\n ),\n );\n }\n if (edit) {\n items.push(\n item('edit', Pencil, (row) => callbacks().onEdit?.(row, USER_ACTION)),\n );\n }\n if (recordPayment) {\n items.push(\n item('recordPayment', HandCoins, (row) =>\n callbacks().onRecordPayment?.(row, USER_ACTION),\n ),\n );\n }\n if (writeOff) {\n items.push(\n item('writeOff', CircleOff, (row) =>\n callbacks().onWriteOff?.(row, false, USER_ACTION),\n ),\n item('undoWriteOff', Undo2, (row) =>\n callbacks().onWriteOff?.(row, true, USER_ACTION),\n ),\n );\n }\n if (remove) {\n items.push(\n item(\n 'delete',\n Trash2,\n (row) => callbacks().onDelete?.(row, USER_ACTION),\n 'destructive',\n ),\n );\n }\n return items;\n }, [\n t,\n callbacksRef,\n download,\n loadIntoWarehouse,\n edit,\n recordPayment,\n writeOff,\n remove,\n privacyMode,\n ]);\n}\n","/* -------------------------------------------------------------------- */\n/* BillTable: the Accounting bills list (HTP-7312) on the kit DataGrid. */\n/* */\n/* Server mode only: the host owns the query and fetches; the kit */\n/* renders, reports one `onQueryChange` per change and never fetches. */\n/* Composes DataGrid (columns, pager, EmptyState, totals row), */\n/* DataGridToolbar parts and the kit RowActions leaf. Privacy mode hides */\n/* people (patient and person counterparties); companies stay visible. */\n/* One agent surface per table: `billTableAgent` over the curated handle; */\n/* the inner DataGrid registers none (`registerAgent={false}`). */\n/* Design: design-bill-table.md (Phase 2), decisions D1 to D20. */\n/* -------------------------------------------------------------------- */\n\nimport {\n forwardRef,\n useCallback,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { FileCode, FileText } from 'lucide-react';\n\nimport { useAgentRegistration } from '../../agent';\nimport { DataGrid } from '../data-grid/data-grid';\nimport { DataGridToolbar } from '../data-grid/toolbar';\nimport type { DataGridHandle, DataGridQuery } from '../data-grid/types';\nimport { IconButtonGroup } from '../icon-button-group/icon-button-group';\nimport { billTableAgent } from './bill-table.agent';\nimport { billTableVariants } from './bill-table.variants';\nimport { useBillTableColumns } from './columns';\nimport { createBillTableHandle, type BillTableLive } from './handle';\nimport {\n BILL_TABLE_DEFAULT_GRID_ID,\n BILL_TABLE_DEFAULT_SORT,\n BILL_TABLE_PAGE_SIZE_OPTIONS,\n USER_ACTION,\n resolveControlledSorting,\n sortKey,\n toBillSortEntries,\n type BillSortEcho,\n type BillTableCallbacks,\n} from './model';\nimport { useBillRowActions } from './row-actions';\nimport { BILL_DIRECTION_COPY, BILL_LIST_DOWNLOAD_COPY } from './status-maps';\nimport {\n BILL_DIRECTIONS,\n BILL_TABLE_SORT_COLUMNS,\n type BillListDownloadKind,\n type BillRow,\n type BillTableFilterModel,\n type BillTableHandle,\n type BillTableHostFilterKey,\n type BillTableProps,\n} from './types';\n\nexport type { BillTableProps, BillTableHandle } from './types';\n\nconst NO_LIST_DOWNLOADS: readonly BillListDownloadKind[] = [];\n\nconst getBillRowId = (row: BillRow): string => row.id;\n\n/** The bill number names the row: \"Select A12\", \"Actions, A12\". It is not\n * personal data, so it names the row under privacy mode too. */\nconst getBillRowLabel = (row: BillRow): string => row.number;\n\n/**\n * The Accounting bills list. Pass one page of `rows`, the total\n * `rowCount` and either a controlled `query` or a `defaultQuery`; fetch on\n * `onQueryChange`. `ref` gives the curated `BillTableHandle`.\n *\n * Saved views: wrap it in `DataGridTabs` (with `useBillTableDefaultTabs`\n * for the suggested views). The DataGrid inside registers itself with the\n * tabs through context, so the tabs need no `getTable`.\n */\nexport const BillTable = forwardRef<BillTableHandle, BillTableProps>(\n function BillTable(props, ref) {\n const {\n /* data */\n rows,\n rowCount,\n currency = 'EUR',\n totals = null,\n /* query */\n query,\n defaultQuery,\n onQueryChange,\n sortableColumns = BILL_TABLE_SORT_COLUMNS,\n pageSizeOptions = BILL_TABLE_PAGE_SIZE_OPTIONS,\n /* selection */\n selectable = true,\n selection,\n defaultSelection,\n onSelectionChange,\n /* columns */\n showWarehouseStatus = false,\n gridId = BILL_TABLE_DEFAULT_GRID_ID,\n persistColumnState = true,\n /* row actions */\n onOpen,\n onDownload,\n onLoadIntoWarehouse,\n onEdit,\n onRecordPayment,\n onWriteOff,\n onDelete,\n /* bulk and list actions */\n onBulkDownload,\n listDownloads = NO_LIST_DOWNLOADS,\n onListDownload,\n onRefresh,\n /* toolbar */\n toolbarStart,\n extraFilterLabels,\n /* states */\n status = 'ready',\n error,\n onCreateBill,\n headingLevel,\n /* privacy and layout */\n privacyMode = false,\n caption,\n density = 'default',\n height = 'auto',\n /* DOM: naming goes to the grid's scroll region */\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n ...rest\n } = props;\n\n const { t } = useTranslation('ui');\n const openHintId = useId();\n const gridRef = useRef<DataGridHandle | null>(null);\n\n /* ---------------- what the handle and the menu read ---------------- */\n\n const callbacks: BillTableCallbacks = {\n onOpen,\n onDownload,\n onLoadIntoWarehouse,\n onEdit,\n onRecordPayment,\n onWriteOff,\n onDelete,\n };\n // Read when an action runs, so a host's inline functions never rebuild\n // the columns or the menu.\n const callbacksRef = useRef(callbacks);\n callbacksRef.current = callbacks;\n\n const hiddenReasonText = t(\n 'billTable.disabledReason.privacyHidden',\n 'Not available (reason hidden in privacy mode)',\n );\n const live: BillTableLive = {\n rows,\n callbacks,\n features: {\n selectable,\n privacyMode,\n showWarehouseStatus,\n sortableColumns: [...sortableColumns],\n status,\n },\n hiddenReasonText,\n };\n const liveRef = useRef(live);\n liveRef.current = live;\n\n /* ---------------- curated handle and agent ---------------- */\n\n const [handle] = useState(() => createBillTableHandle(gridRef, liveRef));\n useImperativeHandle(ref, () => handle, [handle]);\n // `gridId` is the instance id. The DataGrid inside gets\n // `registerAgent={false}`, so one table exposes one agent surface.\n useAgentRegistration(billTableAgent, handle, gridId);\n\n /* ---------------- query ---------------- */\n\n // What the last `onQueryChange` carried, for `resolveControlledSorting`.\n const echoRef = useRef<BillSortEcho | null>(null);\n\n // DataGrid reports the effective query: under privacy mode a paused\n // counterparty sort is left out (DG-6), and DataGrid itself emits once\n // when privacy mode changes the query. BillTable adds `privacyMode` to\n // that call and never emits on its own.\n const handleQueryChange = (next: DataGridQuery) => {\n const sorting = toBillSortEntries(next.sorting);\n echoRef.current = {\n key: sortKey(sorting),\n raw: toBillSortEntries(gridRef.current?.getSort() ?? next.sorting),\n };\n onQueryChange?.({\n sorting,\n // Column models and host keys; DataGrid evaluates none of them in\n // server mode and passes the host's keys through as written.\n filters: next.filters as BillTableFilterModel,\n quickFilter: next.quickFilter,\n pagination: { ...next.pagination },\n privacyMode,\n });\n };\n const controlledSorting = query\n ? resolveControlledSorting(query.sorting, echoRef.current)\n : undefined;\n\n const pageSizeKey = pageSizeOptions.join(',');\n const paginationConfig = useMemo(\n () => ({\n pageSizeOptions:\n pageSizeKey === ''\n ? BILL_TABLE_PAGE_SIZE_OPTIONS\n : pageSizeKey.split(',').map(Number),\n }),\n [pageSizeKey],\n );\n\n // Chip labels for the platform's advanced filters (host keys). A chip\n // shows a host key's label only, never its value.\n const filterLabels = useMemo(() => {\n const kitLabels: Record<BillTableHostFilterKey | 'number', string> = {\n datePreset: t('billTable.filter.datePreset', 'Period'),\n type: t('billTable.filter.type', 'Type'),\n number: t('billTable.filter.number', 'Number'),\n prefix: t('billTable.filter.prefix', 'Prefix'),\n withInsuranceNet: t(\n 'billTable.filter.withInsuranceNet',\n 'Insurer amount',\n ),\n withVat: t('billTable.filter.withVat', 'VAT'),\n withTaxAtSource: t(\n 'billTable.filter.withTaxAtSource',\n 'Withholding tax',\n ),\n withWelfareFundContribution: t(\n 'billTable.filter.withWelfareFundContribution',\n 'Welfare fund contribution',\n ),\n withUnpaidAmount: t(\n 'billTable.filter.withUnpaidAmount',\n 'Amount still to pay',\n ),\n writtenOff: t('billTable.filter.writtenOff', 'Written off'),\n taxOfficeNotification: t(\n 'billTable.filter.taxOfficeNotification',\n 'Consent to send to Sistema TS',\n ),\n receivedFromSdi: t(\n 'billTable.filter.receivedFromSdi',\n 'Received from SDI',\n ),\n sentToSdi: t('billTable.filter.sentToSdi', 'Sent to SDI'),\n selfBill: t('billTable.filter.selfBill', 'Self-billing'),\n liabilityDate: t('billTable.filter.liabilityDate', 'Due date'),\n sdiEntryDate: t(\n 'billTable.filter.sdiEntryDate',\n 'Date received by SDI',\n ),\n relationType: t('billTable.filter.relationType', 'Counterparty type'),\n relation: t('billTable.filter.relation', 'Counterparty'),\n insurance: t('billTable.filter.insurance', 'Insurer'),\n personalAssistant: t(\n 'billTable.filter.personalAssistant',\n 'Personal assistant',\n ),\n };\n return { ...kitLabels, ...extraFilterLabels };\n }, [t, extraFilterLabels]);\n\n /* ---------------- columns ---------------- */\n\n const rowActions = useBillRowActions({\n callbacksRef,\n available: {\n download: Boolean(onDownload),\n loadIntoWarehouse: Boolean(onLoadIntoWarehouse),\n edit: Boolean(onEdit),\n recordPayment: Boolean(onRecordPayment),\n writeOff: Boolean(onWriteOff),\n delete: Boolean(onDelete),\n },\n privacyMode,\n });\n const onOpenRow = useCallback((row: BillRow) => {\n callbacksRef.current.onOpen(row, USER_ACTION);\n }, []);\n const columns = useBillTableColumns({\n currency,\n showWarehouseStatus,\n sortableColumns,\n totals,\n privacyMode,\n openHintId,\n onOpenRow,\n rowActions,\n });\n\n /* ---------------- toolbar ---------------- */\n\n const directionPills = BILL_DIRECTIONS.map((direction) => {\n const copy = BILL_DIRECTION_COPY[direction];\n return { value: direction, label: t(copy.key, copy.en) };\n });\n\n const toolbar = (\n <DataGridToolbar>\n <DataGridToolbar.FilterBar>\n {toolbarStart}\n <DataGridToolbar.QuickSearch\n placeholder={\n privacyMode\n ? t('billTable.search.placeholderPrivate', 'Search by number')\n : t(\n 'billTable.search.placeholder',\n 'Search by number or counterparty',\n )\n }\n />\n <DataGridToolbar.FacetFilter\n field=\"direction\"\n label={t('billTable.column.direction', 'Direction')}\n options={[\n { value: null, label: t('dataTable.selectFilter.all', 'All') },\n ...directionPills,\n ]}\n />\n <DataGridToolbar.FilterChips />\n </DataGridToolbar.FilterBar>\n <DataGridToolbar.Actions>\n {selectable && onBulkDownload ? (\n <>\n <DataGridToolbar.BulkAction\n label={t('billTable.bulk.downloadPdf', 'Download PDFs')}\n icon={<FileText aria-hidden=\"true\" />}\n onAction={({ selectedRowIds }) =>\n onBulkDownload([...selectedRowIds], 'pdf')\n }\n />\n <DataGridToolbar.BulkAction\n label={t('billTable.bulk.downloadXml', 'Download XML files')}\n icon={<FileCode aria-hidden=\"true\" />}\n onAction={({ selectedRowIds }) =>\n onBulkDownload([...selectedRowIds], 'xml')\n }\n />\n </>\n ) : null}\n <IconButtonGroup\n aria-label={t('dataTable.tableActions', 'Table actions')}\n >\n {listDownloads.length > 0 && onListDownload ? (\n // Today's list downloads apply the query to every matching\n // bill on the server; DataGrid's built-in CSV, Excel and PDF\n // would export one page, so only custom items are offered.\n <DataGridToolbar.ExportMenu\n label={t('billTable.export.menu', 'Download list')}\n >\n {listDownloads.map((kind) => {\n const copy = BILL_LIST_DOWNLOAD_COPY[kind];\n return (\n <DataGridToolbar.ExportMenu.Item\n key={kind}\n format=\"custom\"\n label={t(copy.key, copy.en)}\n onExport={() => onListDownload(kind, handle.getQuery())}\n />\n );\n })}\n </DataGridToolbar.ExportMenu>\n ) : null}\n {onRefresh ? (\n <DataGridToolbar.Refresh onRefresh={onRefresh} />\n ) : null}\n <DataGridToolbar.ColumnToggle />\n </IconButtonGroup>\n </DataGridToolbar.Actions>\n </DataGridToolbar>\n );\n\n /* ---------------- render ---------------- */\n\n return (\n <div\n data-component=\"bill-table\"\n data-component-id={gridId}\n className={billTableVariants({ height, className })}\n {...rest}\n >\n {/* The open button's description, once for every row: its name\n is the visible bill number, so the row header reads \"A12\". */}\n <span hidden id={openHintId}>\n {t('billTable.open', 'Open bill')}\n </span>\n <DataGrid<BillRow>\n ref={gridRef}\n columns={columns}\n rows={rows}\n getRowId={getBillRowId}\n caption={caption ?? t('billTable.caption', 'Bills')}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n /* identity: storage key only; BillTable is the agent surface */\n gridId={gridId}\n registerAgent={false}\n persistColumnState={persistColumnState}\n /* server mode: the host fetches on onQueryChange */\n dataMode=\"server\"\n rowCount={rowCount}\n sorting={controlledSorting}\n defaultSorting={defaultQuery?.sorting ?? BILL_TABLE_DEFAULT_SORT}\n filters={query?.filters}\n defaultFilters={defaultQuery?.filters}\n quickFilter={query?.quickFilter}\n defaultQuickFilter={defaultQuery?.quickFilter}\n page={query?.pagination}\n defaultPage={defaultQuery?.pagination}\n onQueryChange={handleQueryChange}\n filterLabels={filterLabels}\n /* the server sorts by one column */\n multiSort={false}\n maxSortLevels={1}\n pagination={paginationConfig}\n /* selection survives paging; a new filter or search clears it */\n selectionMode={selectable ? 'multiple' : 'none'}\n rowSelection={selection}\n defaultRowSelection={defaultSelection}\n onRowSelectionChange={onSelectionChange}\n selectAllScope=\"page\"\n rangeSelection\n clearSelectionOnFilterChange\n /* columns */\n columnResizing\n responsiveColumns\n getRowLabel={getBillRowLabel}\n rowLabelPrivacySafe\n /* states */\n status={status}\n error={{\n title:\n error?.title ??\n t('billTable.error.title', 'The bills could not be loaded'),\n description: error?.description,\n onRetry: error?.onRetry,\n headingLevel,\n }}\n empty={{\n title: t('billTable.empty.title', 'No bills yet'),\n description: t(\n 'billTable.empty.description',\n 'Bills you create, or receive from SDI, appear here.',\n ),\n action: onCreateBill\n ? {\n label: t('billTable.empty.action', 'Add bill'),\n onClick: onCreateBill,\n }\n : undefined,\n headingLevel,\n noResultsTitle: t(\n 'billTable.empty.noResultsTitle',\n 'No bills match your filters',\n ),\n }}\n toolbar={toolbar}\n density={density}\n height={height}\n privacyMode={privacyMode}\n />\n </div>\n );\n },\n);\n\nBillTable.displayName = 'BillTable';\n","/* -------------------------------------------------------------------- */\n/* BillTable: suggested saved views for DataGridTabs. */\n/* */\n/* The host wraps BillTable in DataGridTabs (composition): the DataGrid */\n/* inside BillTable registers itself with the tabs through context, so no */\n/* `getTable` is needed, and a tab switch reaches the host as one */\n/* `onQueryChange` with the whole restored view. Persistence stays with */\n/* the platform. A hook, not a factory that takes `t`: the labels are */\n/* translated here, from the `ui` namespace. */\n/* -------------------------------------------------------------------- */\n\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { DataGridSavedTab } from '../data-grid-tabs/types';\nimport type {\n BillDirection,\n BillPaymentStatus,\n BillSdiStatus,\n BillTableDefaultTabId,\n BillTableFilterModel,\n BillWarehouseStatus,\n} from './types';\n\nexport interface BillTableDefaultTabsOptions {\n /** Adds \"To load into warehouse\": practices with the warehouse module\n * (HTP-7314). Default `false`. */\n withWarehouse?: boolean;\n}\n\n/** A default tab: a stable developer id and a typed bill filter model. */\ninterface BillTableDefaultTab extends DataGridSavedTab {\n id: BillTableDefaultTabId;\n filterModel: BillTableFilterModel;\n}\n\nconst INCOMING: BillDirection[] = ['incoming'];\nconst OUTGOING: BillDirection[] = ['outgoing'];\n/** Money still to settle: the \"To pay\" and \"To collect\" views. */\nconst OPEN_PAYMENT: BillPaymentStatus[] = [\n 'unpaid',\n 'partiallyPaid',\n 'overdue',\n];\nconst FROM_SDI: BillSdiStatus[] = ['received'];\nconst TO_LOAD: BillWarehouseStatus[] = ['notLoaded', 'toReview'];\n\n/**\n * The kit's suggested saved views, for `DataGridTabs` `defaultTabs`:\n * This year (the default, locked), All (locked), Incoming, Outgoing, To pay,\n * To collect and, with the warehouse module, To load into warehouse.\n *\n * \"This year\" is the host key `datePreset: 'thisYear'`, which the server\n * resolves on every request, so a saved \"This year\" is still right next\n * year. Labels are kit copy, translated when the tabs are created; every\n * tab is marked `userNamed: false`, so the labels stay readable under\n * privacy mode (no label holds a name). Seed the host's first query from\n * the active tab's `filterModel`, so mounting the tabs costs no extra\n * request.\n */\nexport function useBillTableDefaultTabs({\n withWarehouse = false,\n}: BillTableDefaultTabsOptions = {}): DataGridSavedTab[] {\n const { t } = useTranslation('ui');\n return useMemo(() => {\n const tabs: BillTableDefaultTab[] = [\n {\n id: 'bills-this-year',\n label: t('billTable.tabs.thisYear', 'This year'),\n filterModel: { datePreset: 'thisYear' },\n locked: true,\n userNamed: false,\n },\n {\n id: 'bills-all',\n label: t('billTable.tabs.all', 'All'),\n filterModel: {},\n locked: true,\n userNamed: false,\n },\n {\n id: 'bills-incoming',\n label: t('billTable.tabs.incoming', 'Incoming'),\n filterModel: { direction: { type: 'set', values: [...INCOMING] } },\n userNamed: false,\n },\n {\n id: 'bills-outgoing',\n label: t('billTable.tabs.outgoing', 'Outgoing'),\n filterModel: { direction: { type: 'set', values: [...OUTGOING] } },\n userNamed: false,\n },\n {\n id: 'bills-to-pay',\n label: t('billTable.tabs.toPay', 'To pay'),\n filterModel: {\n direction: { type: 'set', values: [...INCOMING] },\n paymentStatus: { type: 'set', values: [...OPEN_PAYMENT] },\n },\n userNamed: false,\n },\n {\n id: 'bills-to-collect',\n label: t('billTable.tabs.toCollect', 'To collect'),\n filterModel: {\n direction: { type: 'set', values: [...OUTGOING] },\n paymentStatus: { type: 'set', values: [...OPEN_PAYMENT] },\n },\n userNamed: false,\n },\n ];\n if (withWarehouse) {\n tabs.push({\n id: 'bills-to-load',\n label: t('billTable.tabs.toLoad', 'To load into warehouse'),\n filterModel: {\n sdiStatus: { type: 'set', values: [...FROM_SDI] },\n warehouseStatus: { type: 'set', values: [...TO_LOAD] },\n },\n userNamed: false,\n });\n }\n return tabs;\n }, [t, withWarehouse]);\n}\n"],"names":["__iconNode","HandCoins","createLucideIcon","SORT_COLUMNS","DIRECTIONS","PAYMENT","SDI","WAREHOUSE","TYPES","PAGE_SIZES","HIDEABLE_COLUMNS","NON_PERSONAL_FILTER_KEYS","MASKED","refuse","code","detail","knownRow","handle","id","set","values","dateRange","yesNo","FILTER_SCHEMA","FILTER_KEYS","readFilter","model","view","key","value","ROW_ID_SCHEMA","billTableAgent","args","column","c","_a","row","billTableVariants","cva","cellStackVariants","secondaryTextVariants","inlineGroupVariants","directionIconVariants","truncatedTextVariants","openButtonVariants","accessibleTargetBlockClass","numberTextVariants","breakdownVariants","breakdownGroupVariants","breakdownTextVariants","breakdownListVariants","breakdownTermVariants","breakdownValueVariants","BILL_DIRECTIONS","BILL_TYPES","BILL_PAYMENT_STATUSES","BILL_SDI_STATUSES","BILL_WAREHOUSE_STATUSES","BILL_COUNTERPARTY_KINDS","BILL_ROW_ACTIONS","BILL_ACTION_DISABLED_REASONS","BILL_TABLE_COLUMNS","BILL_TABLE_SORT_COLUMNS","BILL_LIST_DOWNLOADS","BILL_TABLE_DEFAULT_TAB_IDS","BILL_TABLE_DEFAULT_GRID_ID","BILL_TABLE_DEFAULT_SORT","BILL_TABLE_PAGE_SIZE_OPTIONS","BILL_AMOUNT_SCALE","USER_ACTION","API_ACTION","isPersonCounterparty","amountForExport","amountMinor","decimalToNumber","dayFormatters","CALENDAR_DAY","formatCalendarDay","day","language","match","year","month","date","instant","locale","formatLocale","formatter","isBillTableSortColumn","colId","toBillSortEntries","entries","out","entry","sortKey","resolveControlledSorting","hostSorting","echo","BILL_ACTION_CALLBACK","hasActionCallback","callbacks","action","disabledReasonCode","state","offeredActions","privacyMode","hiddenReasonText","offered","summariseActions","summariseBillRow","summary","_b","BILL_PAYMENT_STATUS_COPY","BILL_SDI_STATUS_COPY","BILL_WAREHOUSE_STATUS_COPY","BILL_DIRECTION_COPY","BILL_TYPE_COPY","BILL_ACTION_COPY","BILL_DISABLED_REASON_COPY","BILL_LIST_DOWNLOAD_COPY","OpenBillCell","openHintId","onOpen","hideHostText","t","useTranslation","reasonId","useId","typeLine","copy","reason","jsxs","jsx","Button","event","CalendarDayCell","i18n","DirectionIcon","direction","ArrowDownLeft","ArrowUpRight","DirectionLabel","CounterpartyCell","counterparty","AmountCell","currency","Money","StatusBadge","label","variant","Badge","DUE_STATUSES","PaymentStatusCell","status","nextDueDate","SdiStatusCell","WarehouseStatusCell","SdiHeaderTip","InfoTip","BreakdownEntry","Fragment","TotalsBreakdown","totals","sums","formatNumber","TotalsHeaderCell","breakdown","Popover","IconButton","Info","accessibleTargetSquareClass","DirectionTotalsCell","field","directionText","VisuallyHidden","AMOUNT_FILTER_OPERATORS","SDI_FILTER_STATUSES","useBillTableColumns","showWarehouseStatus","sortableColumns","onOpenRow","rowActions","sortableKey","useMemo","sortable","directionLabel","paymentLabel","sdiLabel","warehouseLabel","options","actionsLabel","columns","context","RowActions","warn","message","isDevelopment","COLUMN_IDS","isBillTableColumnId","maskedColumnIds","grid","createBillTableHandle","gridRef","liveRef","live","findRow","candidate","prepare","features","DATA_GRID_DEFAULT_PAGE_SIZE","masked","filters","text","pageIndex","size","ids","fromId","toId","visible","columnId","rows","format","listener","BILL_ACTION_SECTION","useBillRowActions","callbacksRef","available","download","loadIntoWarehouse","edit","recordPayment","writeOff","remove","hiddenReason","reasonFor","item","icon","run","createElement","items","FileText","FileCode","PackagePlus","Pencil","CircleOff","Undo2","Trash2","NO_LIST_DOWNLOADS","getBillRowId","getBillRowLabel","BillTable","forwardRef","props","ref","rowCount","query","defaultQuery","onQueryChange","pageSizeOptions","selectable","selection","defaultSelection","onSelectionChange","gridId","persistColumnState","onDownload","onLoadIntoWarehouse","onEdit","onRecordPayment","onWriteOff","onDelete","onBulkDownload","listDownloads","onListDownload","onRefresh","toolbarStart","extraFilterLabels","error","onCreateBill","headingLevel","caption","density","height","className","ariaLabel","ariaLabelledBy","ariaDescribedBy","rest","useRef","useState","useImperativeHandle","useAgentRegistration","echoRef","handleQueryChange","next","sorting","controlledSorting","pageSizeKey","paginationConfig","filterLabels","useCallback","directionPills","toolbar","DataGridToolbar","selectedRowIds","IconButtonGroup","kind","DataGrid","INCOMING","OUTGOING","OPEN_PAYMENT","FROM_SDI","TO_LOAD","useBillTableDefaultTabs","withWarehouse","tabs"],"mappings":"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","x_google_ignoreList":[0]}