@eifi1/ui-kit 0.32.2 → 0.33.0

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 (363) hide show
  1. package/README.md +16 -8
  2. package/dist/account/delete-account-setting.d.ts +10 -10
  3. package/dist/account/delete-account-setting.js +2 -1
  4. package/dist/account/delete-account-setting.js.map +1 -1
  5. package/dist/account/email-change-setting.d.ts +5 -0
  6. package/dist/account/email-change-setting.js +4 -3
  7. package/dist/account/email-change-setting.js.map +1 -1
  8. package/dist/account/sessions-setting.d.ts +4 -0
  9. package/dist/account/sessions-setting.js +3 -2
  10. package/dist/account/sessions-setting.js.map +1 -1
  11. package/dist/admin/admin-action-confirm.d.ts +10 -10
  12. package/dist/admin/admin-action-confirm.js.map +1 -1
  13. package/dist/admin/invitations-panel.d.ts +10 -10
  14. package/dist/admin/invitations-panel.js +4 -3
  15. package/dist/admin/invitations-panel.js.map +1 -1
  16. package/dist/admin/plan-change.d.ts +100 -0
  17. package/dist/admin/plan-change.js +208 -0
  18. package/dist/admin/plan-change.js.map +1 -0
  19. package/dist/admin/reviewer-scope-editor.d.ts +10 -10
  20. package/dist/admin/reviewer-scope-editor.js.map +1 -1
  21. package/dist/admin/role-select.d.ts +7 -7
  22. package/dist/admin/role-select.js.map +1 -1
  23. package/dist/admin/transfer-ownership-dialog.d.ts +10 -10
  24. package/dist/admin/user-roster.d.ts +7 -7
  25. package/dist/admin/user-roster.js +2 -2
  26. package/dist/admin/user-roster.js.map +1 -1
  27. package/dist/auth/auth-errors.d.ts +13 -2
  28. package/dist/auth/auth-errors.js +5 -1
  29. package/dist/auth/auth-errors.js.map +1 -1
  30. package/dist/auth/complete-name-dialog.d.ts +4 -1
  31. package/dist/auth/complete-name-dialog.js +2 -1
  32. package/dist/auth/complete-name-dialog.js.map +1 -1
  33. package/dist/auth/register-form.d.ts +10 -10
  34. package/dist/billing/billing-banner.d.ts +13 -11
  35. package/dist/billing/billing-banner.js.map +1 -1
  36. package/dist/billing/billing-labels.d.ts +10 -10
  37. package/dist/billing/billing-labels.js +10 -1
  38. package/dist/billing/billing-labels.js.map +1 -1
  39. package/dist/billing/billing-lock.d.ts +39 -12
  40. package/dist/billing/billing-lock.js +9 -3
  41. package/dist/billing/billing-lock.js.map +1 -1
  42. package/dist/billing/billing-overview.d.ts +154 -0
  43. package/dist/billing/billing-overview.js +2 -0
  44. package/dist/billing/billing-overview.js.map +1 -0
  45. package/dist/billing/billing-standing.d.ts +10 -10
  46. package/dist/billing/checkout-processing.d.ts +217 -0
  47. package/dist/billing/checkout-processing.js +198 -0
  48. package/dist/billing/checkout-processing.js.map +1 -0
  49. package/dist/billing/checkout-return.d.ts +51 -0
  50. package/dist/billing/checkout-return.js +43 -0
  51. package/dist/billing/checkout-return.js.map +1 -0
  52. package/dist/billing/pay-page.d.ts +210 -0
  53. package/dist/billing/pay-page.js +113 -0
  54. package/dist/billing/pay-page.js.map +1 -0
  55. package/dist/billing/plan-card.d.ts +10 -10
  56. package/dist/billing/plan-limit-notice.d.ts +10 -10
  57. package/dist/billing/plan-limit-toast.d.ts +143 -0
  58. package/dist/billing/plan-limit-toast.js +40 -0
  59. package/dist/billing/plan-limit-toast.js.map +1 -0
  60. package/dist/billing/subscription-actions.d.ts +38 -15
  61. package/dist/billing/subscription-actions.js +9 -2
  62. package/dist/billing/subscription-actions.js.map +1 -1
  63. package/dist/billing/subscription-status-chip.d.ts +9 -9
  64. package/dist/bin/eifi1-pay-page.mjs +166 -0
  65. package/dist/chart.d.ts +10 -10
  66. package/dist/components/account-chips.d.ts +6 -1
  67. package/dist/components/account-settings.d.ts +4 -1
  68. package/dist/components/account-settings.js +2 -1
  69. package/dist/components/account-settings.js.map +1 -1
  70. package/dist/components/amount-input.d.ts +10 -10
  71. package/dist/components/autocomplete.d.ts +2 -1
  72. package/dist/components/autocomplete.js +3 -1
  73. package/dist/components/autocomplete.js.map +1 -1
  74. package/dist/components/button-group.d.ts +10 -10
  75. package/dist/components/button-group.js +1 -1
  76. package/dist/components/button-group.js.map +1 -1
  77. package/dist/components/calculator.d.ts +10 -10
  78. package/dist/components/calculator.js +3 -3
  79. package/dist/components/calculator.js.map +1 -1
  80. package/dist/components/checkbox-group.d.ts +2 -1
  81. package/dist/components/checkbox-group.js.map +1 -1
  82. package/dist/components/checkbox.d.ts +2 -1
  83. package/dist/components/checkbox.js.map +1 -1
  84. package/dist/components/chip.d.ts +2 -1
  85. package/dist/components/chip.js +19 -17
  86. package/dist/components/chip.js.map +1 -1
  87. package/dist/components/choice-card.d.ts +3 -1
  88. package/dist/components/choice-card.js +1 -1
  89. package/dist/components/choice-card.js.map +1 -1
  90. package/dist/components/combobox.d.ts +4 -3
  91. package/dist/components/combobox.js.map +1 -1
  92. package/dist/components/confirm-dialog.d.ts +10 -10
  93. package/dist/components/confirm-dialog.js +6 -3
  94. package/dist/components/confirm-dialog.js.map +1 -1
  95. package/dist/components/copy-button.d.ts +11 -11
  96. package/dist/components/country-select.d.ts +2 -1
  97. package/dist/components/country-select.js.map +1 -1
  98. package/dist/components/danger-confirm.d.ts +10 -10
  99. package/dist/components/danger-confirm.js.map +1 -1
  100. package/dist/components/data-table-cells.d.ts +12 -1
  101. package/dist/components/data-table-filter-popover.d.ts +12 -1
  102. package/dist/components/data-table-filters.d.ts +12 -1
  103. package/dist/components/data-table-labels.d.ts +12 -1
  104. package/dist/components/data-table-pagination.d.ts +12 -1
  105. package/dist/components/data-table.d.ts +12 -1
  106. package/dist/components/data-table.js +3 -3
  107. package/dist/components/data-table.js.map +1 -1
  108. package/dist/components/date-picker.js +6 -4
  109. package/dist/components/date-picker.js.map +1 -1
  110. package/dist/components/entity-combobox.d.ts +3 -2
  111. package/dist/components/entity-combobox.js.map +1 -1
  112. package/dist/components/facing-pair.d.ts +10 -10
  113. package/dist/components/field-parts.d.ts +32 -4
  114. package/dist/components/field-parts.js +54 -19
  115. package/dist/components/field-parts.js.map +1 -1
  116. package/dist/components/file-button.d.ts +10 -10
  117. package/dist/components/file-button.js +3 -2
  118. package/dist/components/file-button.js.map +1 -1
  119. package/dist/components/file-dropzone.d.ts +11 -11
  120. package/dist/components/file-dropzone.js.map +1 -1
  121. package/dist/components/floating-panel.js +5 -5
  122. package/dist/components/floating-panel.js.map +1 -1
  123. package/dist/components/form-actions.d.ts +9 -9
  124. package/dist/components/form-actions.js +3 -3
  125. package/dist/components/form-actions.js.map +1 -1
  126. package/dist/components/iban-input.d.ts +10 -10
  127. package/dist/components/inline-edit-field.d.ts +2 -1
  128. package/dist/components/inline-edit-field.js +6 -6
  129. package/dist/components/inline-edit-field.js.map +1 -1
  130. package/dist/components/language-select.d.ts +10 -10
  131. package/dist/components/legal-page.d.ts +10 -10
  132. package/dist/components/legal.d.ts +10 -10
  133. package/dist/components/list.d.ts +2 -1
  134. package/dist/components/list.js +4 -5
  135. package/dist/components/list.js.map +1 -1
  136. package/dist/components/money-field.d.ts +10 -10
  137. package/dist/components/month-picker.js +54 -44
  138. package/dist/components/month-picker.js.map +1 -1
  139. package/dist/components/multi-entity-combobox.d.ts +3 -2
  140. package/dist/components/multi-entity-combobox.js.map +1 -1
  141. package/dist/components/number-field.d.ts +10 -10
  142. package/dist/components/number-input.d.ts +10 -10
  143. package/dist/components/numpad-sheet.d.ts +10 -10
  144. package/dist/components/numpad-sheet.js +2 -2
  145. package/dist/components/numpad-sheet.js.map +1 -1
  146. package/dist/components/phone-input.d.ts +10 -10
  147. package/dist/components/row-actions.d.ts +5 -5
  148. package/dist/components/row-actions.js +130 -32
  149. package/dist/components/row-actions.js.map +1 -1
  150. package/dist/components/series-chart.d.ts +10 -10
  151. package/dist/components/settings-fields.d.ts +10 -10
  152. package/dist/components/share-card.d.ts +7 -7
  153. package/dist/components/share-card.js +26 -10
  154. package/dist/components/share-card.js.map +1 -1
  155. package/dist/components/status-dot.d.ts +1 -0
  156. package/dist/components/status-dot.js +2 -2
  157. package/dist/components/status-dot.js.map +1 -1
  158. package/dist/components/swatch-picker.d.ts +2 -1
  159. package/dist/components/swatch-picker.js.map +1 -1
  160. package/dist/components/swipeable-row.d.ts +88 -17
  161. package/dist/components/swipeable-row.js +46 -9
  162. package/dist/components/swipeable-row.js.map +1 -1
  163. package/dist/components/switch.d.ts +2 -1
  164. package/dist/components/switch.js.map +1 -1
  165. package/dist/components/table.d.ts +2 -1
  166. package/dist/components/table.js +6 -0
  167. package/dist/components/table.js.map +1 -1
  168. package/dist/components/text-link.d.ts +9 -9
  169. package/dist/components/time-input.d.ts +10 -10
  170. package/dist/components/toggle-group.d.ts +2 -1
  171. package/dist/components/toggle-group.js +1 -1
  172. package/dist/components/toggle-group.js.map +1 -1
  173. package/dist/components/translation-review-editor.d.ts +4 -0
  174. package/dist/components/translation-review-editor.js +4 -3
  175. package/dist/components/translation-review-editor.js.map +1 -1
  176. package/dist/components/translation-review-parts.d.ts +1 -0
  177. package/dist/components/translation-review.d.ts +1 -0
  178. package/dist/components/translation-review.js +15 -18
  179. package/dist/components/translation-review.js.map +1 -1
  180. package/dist/components/ui.d.ts +9 -9
  181. package/dist/components/ui.js +47 -27
  182. package/dist/components/ui.js.map +1 -1
  183. package/dist/components/use-table-state.d.ts +12 -1
  184. package/dist/components/user-avatar.d.ts +1 -0
  185. package/dist/components/write-lock.d.ts +101 -13
  186. package/dist/components/write-lock.js +37 -13
  187. package/dist/components/write-lock.js.map +1 -1
  188. package/dist/{data-table-labels-kpAAVi6g.d.ts → data-table-labels-BJ5JE_X2.d.ts} +17 -0
  189. package/dist/data-table.d.ts +12 -1
  190. package/dist/{delete-account-setting-Dy4kJgUm.d.ts → delete-account-setting-DiPX4Vue.d.ts} +355 -41
  191. package/dist/feedback/feedback-attachment.d.ts +10 -10
  192. package/dist/feedback/feedback-attachment.js +7 -7
  193. package/dist/feedback/feedback-attachment.js.map +1 -1
  194. package/dist/feedback/feedback-context.d.ts +10 -10
  195. package/dist/feedback/feedback-crash.d.ts +10 -10
  196. package/dist/feedback/feedback-dialog.d.ts +10 -10
  197. package/dist/feedback/feedback-inbox.d.ts +9 -9
  198. package/dist/feedback/feedback-inbox.js +7 -3
  199. package/dist/feedback/feedback-inbox.js.map +1 -1
  200. package/dist/feedback/feedback-labels.d.ts +10 -10
  201. package/dist/feedback/feedback-menu.d.ts +3 -3
  202. package/dist/feedback/feedback-record.d.ts +10 -10
  203. package/dist/feedback/feedback-row-detail.d.ts +10 -10
  204. package/dist/feedback/feedback-row-detail.js.map +1 -1
  205. package/dist/feedback/feedback-status-undo.d.ts +10 -10
  206. package/dist/feedback/feedback-submit.d.ts +10 -10
  207. package/dist/feedback/feedback-swipe.d.ts +10 -10
  208. package/dist/feedback/feedback-swipe.js +3 -6
  209. package/dist/feedback/feedback-swipe.js.map +1 -1
  210. package/dist/feedback/feedback-table.d.ts +10 -10
  211. package/dist/feedback/feedback-table.js.map +1 -1
  212. package/dist/feedback/feedback-thread.d.ts +10 -10
  213. package/dist/feedback.d.ts +10 -10
  214. package/dist/hooks/use-file-drop.d.ts +10 -10
  215. package/dist/i18n/defaults.d.ts +10 -10
  216. package/dist/i18n/defaults.js +2 -0
  217. package/dist/i18n/defaults.js.map +1 -1
  218. package/dist/i18n/german.d.ts +10 -10
  219. package/dist/i18n/german.js +34 -1
  220. package/dist/i18n/german.js.map +1 -1
  221. package/dist/i18n/kit-labels.d.ts +4 -4
  222. package/dist/i18n/kit-labels.js.map +1 -1
  223. package/dist/i18n/languages.d.ts +10 -10
  224. package/dist/i18n/locales/de-CH.d.ts +10 -10
  225. package/dist/i18n/locales/en.d.ts +10 -10
  226. package/dist/i18n/locales/es.d.ts +10 -10
  227. package/dist/i18n/locales/es.js +34 -1
  228. package/dist/i18n/locales/es.js.map +1 -1
  229. package/dist/i18n/locales/fr.d.ts +10 -10
  230. package/dist/i18n/locales/fr.js +35 -1
  231. package/dist/i18n/locales/fr.js.map +1 -1
  232. package/dist/i18n/locales/hu.d.ts +10 -10
  233. package/dist/i18n/locales/hu.js +36 -1
  234. package/dist/i18n/locales/hu.js.map +1 -1
  235. package/dist/i18n/locales/it.d.ts +10 -10
  236. package/dist/i18n/locales/it.js +34 -1
  237. package/dist/i18n/locales/it.js.map +1 -1
  238. package/dist/i18n/locales/zh.d.ts +10 -10
  239. package/dist/i18n/locales/zh.js +34 -1
  240. package/dist/i18n/locales/zh.js.map +1 -1
  241. package/dist/i18n/review.d.ts +10 -10
  242. package/dist/i18n/review.js +8 -1
  243. package/dist/i18n/review.js.map +1 -1
  244. package/dist/index.d.ts +10 -5
  245. package/dist/index.js +40 -2
  246. package/dist/index.js.map +1 -1
  247. package/dist/landing/landing-actions.d.ts +10 -10
  248. package/dist/landing/landing-sections.d.ts +10 -10
  249. package/dist/landing/public-header.d.ts +10 -10
  250. package/dist/landing/routing.d.ts +10 -10
  251. package/dist/pay/.well-known/apple-developer-merchantid-domain-association +1 -0
  252. package/dist/pay/index.html +30 -0
  253. package/dist/pay/pay.css +126 -0
  254. package/dist/pay/pay.js +198 -0
  255. package/dist/rhf/fields.d.ts +10 -10
  256. package/dist/rhf/form.d.ts +10 -10
  257. package/dist/rhf.d.ts +10 -10
  258. package/dist/settings/settings-section.d.ts +10 -10
  259. package/dist/shell/app-shell.d.ts +9 -9
  260. package/dist/shell/top-bar-brand.d.ts +10 -10
  261. package/dist/shell/topbar-action-menu.d.ts +1 -0
  262. package/dist/shell.d.ts +10 -10
  263. package/dist/testing/css-variables.d.ts +74 -0
  264. package/dist/testing/css-variables.generated.d.ts +7 -0
  265. package/dist/testing/css-variables.generated.js +8 -0
  266. package/dist/testing/css-variables.generated.js.map +1 -0
  267. package/dist/testing/css-variables.js +93 -0
  268. package/dist/testing/css-variables.js.map +1 -0
  269. package/dist/testing/index.d.ts +1 -0
  270. package/dist/testing/index.js +12 -0
  271. package/dist/testing/index.js.map +1 -0
  272. package/dist/theme/contrast-tokens.d.ts +44 -1
  273. package/dist/theme/contrast-tokens.js +21 -0
  274. package/dist/theme/contrast-tokens.js.map +1 -1
  275. package/dist/theme/contrast.d.ts +2 -2
  276. package/dist/theme/palette-derive.js +60 -11
  277. package/dist/theme/palette-derive.js.map +1 -1
  278. package/dist/theme/palette-presets.js +45 -43
  279. package/dist/theme/palette-presets.js.map +1 -1
  280. package/dist/wizard/stepper-nav.d.ts +11 -11
  281. package/dist/wizard/stepper-nav.js.map +1 -1
  282. package/dist/wizard.d.ts +10 -10
  283. package/package.json +10 -2
  284. package/src/account/delete-account-setting.tsx +6 -1
  285. package/src/account/email-change-setting.tsx +9 -3
  286. package/src/account/sessions-setting.tsx +7 -2
  287. package/src/admin/admin-action-confirm.tsx +2 -1
  288. package/src/admin/invitations-panel.tsx +9 -3
  289. package/src/admin/plan-change.tsx +459 -0
  290. package/src/admin/reviewer-scope-editor.tsx +2 -1
  291. package/src/admin/role-select.tsx +2 -1
  292. package/src/admin/user-roster.tsx +5 -3
  293. package/src/auth/auth-errors.ts +25 -2
  294. package/src/auth/complete-name-dialog.tsx +6 -2
  295. package/src/billing/billing-banner.tsx +3 -1
  296. package/src/billing/billing-labels.ts +45 -0
  297. package/src/billing/billing-lock.ts +36 -3
  298. package/src/billing/billing-overview.ts +58 -0
  299. package/src/billing/checkout-processing.ts +391 -0
  300. package/src/billing/checkout-return.ts +90 -0
  301. package/src/billing/pay-page.ts +242 -0
  302. package/src/billing/plan-limit-toast.tsx +91 -0
  303. package/src/billing/subscription-actions.tsx +41 -8
  304. package/src/components/account-settings.tsx +6 -2
  305. package/src/components/autocomplete.tsx +5 -2
  306. package/src/components/button-group.tsx +4 -1
  307. package/src/components/calculator.tsx +10 -6
  308. package/src/components/checkbox-group.tsx +2 -2
  309. package/src/components/checkbox.tsx +2 -1
  310. package/src/components/chip.tsx +37 -32
  311. package/src/components/choice-card.tsx +4 -2
  312. package/src/components/combobox.tsx +4 -4
  313. package/src/components/confirm-dialog.tsx +13 -6
  314. package/src/components/country-select.tsx +2 -2
  315. package/src/components/danger-confirm.tsx +2 -2
  316. package/src/components/data-table.tsx +20 -9
  317. package/src/components/date-picker.tsx +10 -7
  318. package/src/components/entity-combobox.tsx +3 -3
  319. package/src/components/field-parts.tsx +61 -14
  320. package/src/components/file-button.tsx +5 -4
  321. package/src/components/file-dropzone.tsx +2 -2
  322. package/src/components/floating-panel.tsx +7 -5
  323. package/src/components/form-actions.tsx +12 -5
  324. package/src/components/inline-edit-field.tsx +13 -13
  325. package/src/components/list.tsx +10 -9
  326. package/src/components/month-picker.tsx +8 -2
  327. package/src/components/multi-entity-combobox.tsx +3 -3
  328. package/src/components/numpad-sheet.tsx +8 -4
  329. package/src/components/row-actions.tsx +208 -58
  330. package/src/components/share-card.tsx +67 -13
  331. package/src/components/status-dot.tsx +7 -7
  332. package/src/components/swatch-picker.tsx +2 -2
  333. package/src/components/swipeable-row.tsx +138 -27
  334. package/src/components/switch.tsx +2 -1
  335. package/src/components/table.tsx +8 -1
  336. package/src/components/toggle-group.tsx +5 -3
  337. package/src/components/translation-review-editor.tsx +8 -3
  338. package/src/components/translation-review.tsx +18 -22
  339. package/src/components/ui.tsx +92 -43
  340. package/src/components/write-lock.tsx +150 -24
  341. package/src/feedback/feedback-attachment.tsx +13 -9
  342. package/src/feedback/feedback-inbox.tsx +10 -6
  343. package/src/feedback/feedback-row-detail.tsx +3 -2
  344. package/src/feedback/feedback-swipe.tsx +6 -11
  345. package/src/feedback/feedback-table.tsx +2 -1
  346. package/src/i18n/defaults.ts +2 -0
  347. package/src/i18n/german.ts +38 -0
  348. package/src/i18n/kit-labels.tsx +4 -0
  349. package/src/i18n/locales/es.ts +34 -0
  350. package/src/i18n/locales/fr.ts +39 -0
  351. package/src/i18n/locales/hu.ts +37 -0
  352. package/src/i18n/locales/it.ts +35 -0
  353. package/src/i18n/locales/zh.ts +33 -0
  354. package/src/i18n/review.ts +7 -0
  355. package/src/index.ts +48 -4
  356. package/src/testing/css-variables.generated.ts +112 -0
  357. package/src/testing/css-variables.ts +191 -0
  358. package/src/testing/index.ts +13 -0
  359. package/src/theme/contrast-tokens.ts +53 -2
  360. package/src/theme/palette-derive.ts +87 -10
  361. package/src/theme/palette-presets.ts +45 -43
  362. package/src/wizard/stepper-nav.tsx +2 -1
  363. package/tokens.css +306 -46
@@ -1,4 +1,15 @@
1
1
  import 'react';
2
2
  import './data-table-sort.js';
3
- export { I as DEFAULT_PERSIST_PREFIX, T as TableUrlState, k as TableUrlStateProps, l as TableUrlSync, U as UseTableUrlStateOptions, m as UseTableUrlStateReturn, w as readTableUrlState, J as useTableState, E as useTableUrlState } from '../data-table-labels-kpAAVi6g.js';
3
+ export { I as DEFAULT_PERSIST_PREFIX, T as TableUrlState, k as TableUrlStateProps, l as TableUrlSync, U as UseTableUrlStateOptions, m as UseTableUrlStateReturn, w as readTableUrlState, J as useTableState, E as useTableUrlState } from '../data-table-labels-BJ5JE_X2.js';
4
4
  import './swipeable-row.js';
5
+ import './status-dot.js';
6
+ import './progress-bar.js';
7
+ import './signed-amount.js';
8
+ import './stat-tile.js';
9
+ import './chip.js';
10
+ import 'lucide-react';
11
+ import './field-parts.js';
12
+ import './tooltip.js';
13
+ import '../hooks/use-anchored-rect.js';
14
+ import '../lib/clipping.js';
15
+ import './write-lock.js';
@@ -11,6 +11,7 @@ import './field-parts.js';
11
11
  import './tooltip.js';
12
12
  import '../hooks/use-anchored-rect.js';
13
13
  import '../lib/clipping.js';
14
+ import './write-lock.js';
14
15
 
15
16
  /** Initials from a display name (first + last) or, failing that, an email —
16
17
  * e.g. "Marcel Eifert" → "ME", "marcel@x.com" → "MA". App-agnostic.
@@ -7,12 +7,62 @@ interface WriteLockLabels {
7
7
  reason: string;
8
8
  }
9
9
  declare const DEFAULT_WRITE_LOCK_LABELS: WriteLockLabels;
10
- /** What {@link useWriteLock} returns: whether commits are locked here, and why. */
10
+ /**
11
+ * What kind of lock a source is (docs/billing-harmonization.md §12.36, ui-kit 0.33).
12
+ * `"demo"` (the read-only demo, `demo.writeLocked`) and `"billing"` (a lapsed plan,
13
+ * `billing.lockReason`) are the kit's; an app names its own — Kurvenschmiede's
14
+ * `"access"` (a curve shared to view) and `"customer"` (an account that owns nothing).
15
+ * A control exempts itself from a kind with {@link CommitScope}; a source without a
16
+ * kind is never exempted.
17
+ */
18
+ type WriteLockKind = "demo" | "billing" | (string & {});
19
+ /** One locked source, as the provider holds it: its kind and its one sentence. */
20
+ interface WriteLockHold {
21
+ kind: WriteLockKind | undefined;
22
+ reason: ReactNode;
23
+ }
24
+ /**
25
+ * A control's opt-in to the lock — the type of every `commit` prop in the kit.
26
+ *
27
+ * - `true`: every lock refuses the control (a save, an add, an invite).
28
+ * - `{ except: [kinds] }`: every lock but those kinds. A billing lock leaves the
29
+ * reader able to remove access, revoke sessions, delete the account and change their
30
+ * own settings (§3.3, §12.13), so the kit's parts for those take
31
+ * {@link COMMIT_EXCEPT_BILLING} built in, and an app's own controls of that sort do
32
+ * too.
33
+ * - `false` or left out: no lock reaches it.
34
+ *
35
+ * Under a demo lock and a billing lock together, a control exempt from billing is
36
+ * still refused, with the demo's reason.
37
+ */
38
+ type CommitScope = boolean | {
39
+ readonly except: readonly WriteLockKind[];
40
+ };
41
+ /** Every lock but billing's: the scope of an action a lapsed plan still allows — removing
42
+ * access, the account's own settings, an operator's admin route (§12.13). One constant,
43
+ * so the call sites read alike. */
44
+ declare const COMMIT_EXCEPT_BILLING: {
45
+ readonly except: readonly ["billing"];
46
+ };
47
+ /**
48
+ * What {@link useWriteLock} returns: whether commits are locked here as a control with
49
+ * the scope asked for sees it, and why.
50
+ */
11
51
  interface WriteLock {
12
52
  locked: boolean;
13
- /** The one sentence a locked commit shows in its tooltip. Always set while
14
- * `locked`; `undefined` when not. */
53
+ /** The one sentence a locked commit shows in its tooltip: the first hold in scope's.
54
+ * Always set while `locked`; `undefined` when not. */
15
55
  reason: ReactNode | undefined;
56
+ /** The first hold in scope's kind; `undefined` while unlocked, or for a source that
57
+ * names none. */
58
+ kind: WriteLockKind | undefined;
59
+ /**
60
+ * EVERY locked source the provider holds, in the order the server refuses them
61
+ * (§12.3: the demo's 403 before billing's 402) — unfiltered by the scope, for code
62
+ * that must know what else locks (a toast that names the plan, a swipe plan). Empty
63
+ * while the provider is unlocked.
64
+ */
65
+ holds: readonly WriteLockHold[];
16
66
  }
17
67
  interface WriteLockProviderProps {
18
68
  /** Commits below are locked. `false` unlocks a subtree under an outer lock. */
@@ -23,6 +73,17 @@ interface WriteLockProviderProps {
23
73
  * already translated. Left out: `labels.reason`.
24
74
  */
25
75
  reason?: ReactNode;
76
+ /** What kind of lock this is — `"demo"`, `"billing"` or the app's own (see
77
+ * {@link WriteLockKind}), for a provider of one source. Left out, no control can be
78
+ * exempt from it. */
79
+ kind?: WriteLockKind;
80
+ /**
81
+ * Every locked source, in refusal order — what `combineWriteLocks` answers, so
82
+ * `<WriteLockProvider {...combineWriteLocks([...])}>` carries them. Given while
83
+ * `locked`, it wins over `kind` and `reason`; a hold without a reason takes
84
+ * `labels.reason`.
85
+ */
86
+ holds?: readonly WriteLockHold[];
26
87
  labels?: Partial<WriteLockLabels>;
27
88
  children?: ReactNode;
28
89
  }
@@ -50,19 +111,46 @@ interface WriteLockProviderProps {
50
111
  * {@link useWriteLock} and disables itself. The lock is a courtesy, not a guard: the
51
112
  * server still refuses the write.
52
113
  *
114
+ * **A lock says its source** (0.33, docs/billing-harmonization.md §12.36). A lapsed
115
+ * plan locks creating and changing, but not removing access or the account's own
116
+ * settings (§3.3, §12.13), and the kit's parts for those hard-coded `commit` — so
117
+ * kastlan's app-wide lock locked a member's own sign-out everywhere. Each source now
118
+ * has a kind, the provider holds every locked one in order (`holds`, from
119
+ * `combineWriteLocks`), and a control's `commit` may name the kinds it is exempt from
120
+ * ({@link CommitScope}). The kit's parts follow §3.3 and §12.13 by themselves.
121
+ *
53
122
  * Nested providers: the nearest wins, so an inner `locked={false}` reopens a section
54
- * the caller may write (a viewer's own notes on a shared curve), and an inner lock
55
- * with its own reason (Kurvenschmiede's owner lock beside the viewer lock) overrides
56
- * the outer one's sentence.
123
+ * the caller may write (a viewer's own notes on a shared curve) — every source at
124
+ * once — and an inner lock with its own reason (Kurvenschmiede's owner lock beside the
125
+ * viewer lock) overrides the outer one's sentence and its holds.
126
+ */
127
+ declare function WriteLockProvider({ locked, reason, kind, holds, labels, children }: WriteLockProviderProps): react.JSX.Element;
128
+ /**
129
+ * The lock as a control with `scope` sees it — {@link useWriteLock}'s answer, pure, for
130
+ * a scope known only at call time: `useConfirm` reads the CALLER's lock when it is
131
+ * called, and applies each `confirm({ commit })`'s own scope to it when it runs.
132
+ *
133
+ * `undefined` and `false` see no lock (a control without `commit`); `true` sees the
134
+ * lock as it is; `{ except }` sees the first hold of another kind, with its reason
135
+ * and kind. `holds` is passed on unfiltered.
136
+ */
137
+ declare function writeLockFor(lock: WriteLock, scope: CommitScope | undefined): WriteLock;
138
+ /**
139
+ * The nearest {@link WriteLockProvider}'s lock, as a control with `scope` sees it —
140
+ * unlocked with no provider. Left out, the scope is `true`: every lock.
141
+ *
142
+ * For code that must KNOW rather than a control that opts in: a toast that says why,
143
+ * a swipe plan that leaves an action out, a hand-rolled toggle that disables itself.
144
+ * `useWriteLock(COMMIT_EXCEPT_BILLING)` answers "would a lapsed plan's lock refuse me?"
145
+ * as a removal sees it — what keksdose's `useWriteLockKind() !== "billing"` asked.
57
146
  */
58
- declare function WriteLockProvider({ locked, reason, labels, children }: WriteLockProviderProps): react.JSX.Element;
59
- /** The nearest {@link WriteLockProvider}'s lock; unlocked with no provider. */
60
- declare function useWriteLock(): WriteLock;
147
+ declare function useWriteLock(scope?: CommitScope): WriteLock;
61
148
  /**
62
149
  * The `disabledReason` a control with `commit` should use: the lock's reason while
63
- * locked — it wins over the control's own, since it is the answer to the question the
64
- * hover is asking — else the control's own. Internal to the kit's commit controls.
150
+ * the lock refuses this scope — it wins over the control's own, since it is the answer
151
+ * to the question the hover is asking — else the control's own. Internal to the kit's
152
+ * commit controls.
65
153
  */
66
- declare function useCommitReason(commit: boolean | undefined, own: ReactNode): ReactNode;
154
+ declare function useCommitReason(commit: CommitScope | undefined, own: ReactNode): ReactNode;
67
155
 
68
- export { DEFAULT_WRITE_LOCK_LABELS, type WriteLock, type WriteLockLabels, WriteLockProvider, type WriteLockProviderProps, useCommitReason, useWriteLock };
156
+ export { COMMIT_EXCEPT_BILLING, type CommitScope, DEFAULT_WRITE_LOCK_LABELS, type WriteLock, type WriteLockHold, type WriteLockKind, type WriteLockLabels, WriteLockProvider, type WriteLockProviderProps, useCommitReason, useWriteLock, writeLockFor };
@@ -5,29 +5,53 @@ import { useKitLabels } from "../i18n/kit-labels.js";
5
5
  const DEFAULT_WRITE_LOCK_LABELS = {
6
6
  reason: "You can view this but not change it."
7
7
  };
8
- const UNLOCKED = { locked: false, reason: void 0 };
8
+ const COMMIT_EXCEPT_BILLING = { except: ["billing"] };
9
+ const NO_HOLDS = [];
10
+ const UNLOCKED = { locked: false, reason: void 0, kind: void 0, holds: NO_HOLDS };
9
11
  const WriteLockContext = createContext(UNLOCKED);
10
- function WriteLockProvider({ locked, reason, labels, children }) {
12
+ function given(reason) {
13
+ return reason !== void 0 && reason !== null && reason !== false && reason !== "";
14
+ }
15
+ function WriteLockProvider({ locked, reason, kind, holds, labels, children }) {
11
16
  const fallback = useKitLabels("writeLock", DEFAULT_WRITE_LOCK_LABELS, labels).reason;
12
- const given = reason !== void 0 && reason !== null && reason !== false && reason !== "";
13
- const resolved = locked ? given ? reason : fallback : void 0;
14
- const value = useMemo(
15
- () => locked ? { locked: true, reason: resolved } : UNLOCKED,
16
- [locked, resolved]
17
- );
17
+ const several = locked && holds !== void 0 && holds.length > 0 ? holds : void 0;
18
+ const firstKind = several ? several[0].kind : kind;
19
+ const firstGiven = several ? several[0].reason : reason;
20
+ const firstReason = given(firstGiven) ? firstGiven : fallback;
21
+ const many = several && several.length > 1 ? several : void 0;
22
+ const value = useMemo(() => {
23
+ if (!locked) return UNLOCKED;
24
+ const all = many ? many.map((hold) => ({ kind: hold.kind, reason: given(hold.reason) ? hold.reason : fallback })) : [{ kind: firstKind, reason: firstReason }];
25
+ return { locked: true, reason: firstReason, kind: firstKind, holds: all };
26
+ }, [locked, many, firstKind, firstReason, fallback]);
18
27
  return /* @__PURE__ */ jsx(WriteLockContext.Provider, { value, children });
19
28
  }
20
- function useWriteLock() {
21
- return useContext(WriteLockContext);
29
+ function inScope(hold, scope) {
30
+ if (scope === true) return true;
31
+ if (scope === false) return false;
32
+ return hold.kind === void 0 || !scope.except.includes(hold.kind);
33
+ }
34
+ function writeLockFor(lock, scope) {
35
+ if (!lock.locked || scope === true) return lock;
36
+ const holds = lock.holds.length > 0 ? lock.holds : [{ kind: lock.kind, reason: lock.reason }];
37
+ const first = scope === void 0 ? void 0 : holds.find((hold) => inScope(hold, scope));
38
+ if (!first) return { ...UNLOCKED, holds: lock.holds };
39
+ if (first === holds[0]) return lock;
40
+ return { locked: true, reason: first.reason, kind: first.kind, holds: lock.holds };
41
+ }
42
+ function useWriteLock(scope = true) {
43
+ return writeLockFor(useContext(WriteLockContext), scope);
22
44
  }
23
45
  function useCommitReason(commit, own) {
24
- const lock = useWriteLock();
25
- return commit && lock.locked ? lock.reason : own;
46
+ const lock = writeLockFor(useContext(WriteLockContext), commit);
47
+ return lock.locked ? lock.reason : own;
26
48
  }
27
49
  export {
50
+ COMMIT_EXCEPT_BILLING,
28
51
  DEFAULT_WRITE_LOCK_LABELS,
29
52
  WriteLockProvider,
30
53
  useCommitReason,
31
- useWriteLock
54
+ useWriteLock,
55
+ writeLockFor
32
56
  };
33
57
  //# sourceMappingURL=write-lock.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/write-lock.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useKitLabels } from \"../i18n/kit-labels\";\n\n/** The words {@link WriteLockProvider} renders on its own behalf. */\nexport interface WriteLockLabels {\n /** The tooltip of a locked commit when the provider gives no `reason`. */\n reason: string;\n}\n\nexport const DEFAULT_WRITE_LOCK_LABELS: WriteLockLabels = {\n reason: \"You can view this but not change it.\",\n};\n\n/** What {@link useWriteLock} returns: whether commits are locked here, and why. */\nexport interface WriteLock {\n locked: boolean;\n /** The one sentence a locked commit shows in its tooltip. Always set while\n * `locked`; `undefined` when not. */\n reason: ReactNode | undefined;\n}\n\nconst UNLOCKED: WriteLock = { locked: false, reason: undefined };\n\nconst WriteLockContext = createContext<WriteLock>(UNLOCKED);\n\nexport interface WriteLockProviderProps {\n /** Commits below are locked. `false` unlocks a subtree under an outer lock. */\n locked: boolean;\n /**\n * The one sentence that says why — \"Shared with you to read\", \"Read-only demo —\n * saving is disabled\", \"A customer account cannot create curves\". The app's policy,\n * already translated. Left out: `labels.reason`.\n */\n reason?: ReactNode;\n labels?: Partial<WriteLockLabels>;\n children?: ReactNode;\n}\n\n/**\n * The read-only lock — **everything renders; only the commit is locked.**\n *\n * keksdose (features/budgets/write-lock.tsx, the read-only demo budget) and\n * Kurvenschmiede (features/sharing/write-lock.tsx, a curve shared to view, a customer\n * account that owns nothing) each built the same `SaveGuard`: the page, its tabs,\n * forms and dialogs render exactly as for an owner, because a viewer looking at half\n * a page is not looking at what they were sent; what changes is that the control\n * that SAVES is off and says why on hover or focus. Both wrapped each Save in a\n * Tooltip and forced a native `disabled` on it — out of the tab order, so the reason\n * never reached a keyboard — and both had to remember it at thirty call sites.\n *\n * Here the page mounts one provider and each commit control opts in with `commit`\n * ({@link Button}, {@link IconButton}, {@link FormActions}): under a lock it takes the\n * kit's `disabledReason` path with this reason — `aria-disabled` and focusable,\n * every activation swallowed, the reason in the kit Tooltip and its description.\n *\n * Who is locked is the app's: the provider takes a boolean, never a role. Fields stay\n * editable — nothing in them reaches the server until the commit is pressed, and a\n * form you cannot fill in is not a demo of the form (keksdose accounts-page). A\n * control that IS its own commit (a toggle that saves on change) reads\n * {@link useWriteLock} and disables itself. The lock is a courtesy, not a guard: the\n * server still refuses the write.\n *\n * Nested providers: the nearest wins, so an inner `locked={false}` reopens a section\n * the caller may write (a viewer's own notes on a shared curve), and an inner lock\n * with its own reason (Kurvenschmiede's owner lock beside the viewer lock) overrides\n * the outer one's sentence.\n */\nexport function WriteLockProvider({ locked, reason, labels, children }: WriteLockProviderProps) {\n // The `writeLock` namespace: prop > `<UiKitProvider labels>` > English.\n const fallback = useKitLabels(\"writeLock\", DEFAULT_WRITE_LOCK_LABELS, labels).reason;\n // `null`/`\"\"`/`false` count as \"no reason given\": a lock whose tooltip is empty\n // would be a disabled button that cannot say why, the thing this replaces.\n const given = reason !== undefined && reason !== null && reason !== false && reason !== \"\";\n const resolved = locked ? (given ? reason : fallback) : undefined;\n const value = useMemo<WriteLock>(\n () => (locked ? { locked: true, reason: resolved } : UNLOCKED),\n [locked, resolved],\n );\n return <WriteLockContext.Provider value={value}>{children}</WriteLockContext.Provider>;\n}\n\n/** The nearest {@link WriteLockProvider}'s lock; unlocked with no provider. */\nexport function useWriteLock(): WriteLock {\n return useContext(WriteLockContext);\n}\n\n/**\n * The `disabledReason` a control with `commit` should use: the lock's reason while\n * locked — it wins over the control's own, since it is the answer to the question the\n * hover is asking — else the control's own. Internal to the kit's commit controls.\n */\nexport function useCommitReason(commit: boolean | undefined, own: ReactNode): ReactNode {\n const lock = useWriteLock();\n return commit && lock.locked ? lock.reason : own;\n}\n"],"mappings":";AA+ES;AA/ET,SAAS,eAAe,YAAY,eAAe;AAEnD,SAAS,oBAAoB;AAQtB,MAAM,4BAA6C;AAAA,EACxD,QAAQ;AACV;AAUA,MAAM,WAAsB,EAAE,QAAQ,OAAO,QAAQ,OAAU;AAE/D,MAAM,mBAAmB,cAAyB,QAAQ;AA4CnD,SAAS,kBAAkB,EAAE,QAAQ,QAAQ,QAAQ,SAAS,GAA2B;AAE9F,QAAM,WAAW,aAAa,aAAa,2BAA2B,MAAM,EAAE;AAG9E,QAAM,QAAQ,WAAW,UAAa,WAAW,QAAQ,WAAW,SAAS,WAAW;AACxF,QAAM,WAAW,SAAU,QAAQ,SAAS,WAAY;AACxD,QAAM,QAAQ;AAAA,IACZ,MAAO,SAAS,EAAE,QAAQ,MAAM,QAAQ,SAAS,IAAI;AAAA,IACrD,CAAC,QAAQ,QAAQ;AAAA,EACnB;AACA,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAe,UAAS;AAC5D;AAGO,SAAS,eAA0B;AACxC,SAAO,WAAW,gBAAgB;AACpC;AAOO,SAAS,gBAAgB,QAA6B,KAA2B;AACtF,QAAM,OAAO,aAAa;AAC1B,SAAO,UAAU,KAAK,SAAS,KAAK,SAAS;AAC/C;","names":[]}
1
+ {"version":3,"sources":["../../src/components/write-lock.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useKitLabels } from \"../i18n/kit-labels\";\n\n/** The words {@link WriteLockProvider} renders on its own behalf. */\nexport interface WriteLockLabels {\n /** The tooltip of a locked commit when the provider gives no `reason`. */\n reason: string;\n}\n\nexport const DEFAULT_WRITE_LOCK_LABELS: WriteLockLabels = {\n reason: \"You can view this but not change it.\",\n};\n\n/**\n * What kind of lock a source is (docs/billing-harmonization.md §12.36, ui-kit 0.33).\n * `\"demo\"` (the read-only demo, `demo.writeLocked`) and `\"billing\"` (a lapsed plan,\n * `billing.lockReason`) are the kit's; an app names its own — Kurvenschmiede's\n * `\"access\"` (a curve shared to view) and `\"customer\"` (an account that owns nothing).\n * A control exempts itself from a kind with {@link CommitScope}; a source without a\n * kind is never exempted.\n */\nexport type WriteLockKind = \"demo\" | \"billing\" | (string & {});\n\n/** One locked source, as the provider holds it: its kind and its one sentence. */\nexport interface WriteLockHold {\n kind: WriteLockKind | undefined;\n reason: ReactNode;\n}\n\n/**\n * A control's opt-in to the lock — the type of every `commit` prop in the kit.\n *\n * - `true`: every lock refuses the control (a save, an add, an invite).\n * - `{ except: [kinds] }`: every lock but those kinds. A billing lock leaves the\n * reader able to remove access, revoke sessions, delete the account and change their\n * own settings (§3.3, §12.13), so the kit's parts for those take\n * {@link COMMIT_EXCEPT_BILLING} built in, and an app's own controls of that sort do\n * too.\n * - `false` or left out: no lock reaches it.\n *\n * Under a demo lock and a billing lock together, a control exempt from billing is\n * still refused, with the demo's reason.\n */\nexport type CommitScope = boolean | { readonly except: readonly WriteLockKind[] };\n\n/** Every lock but billing's: the scope of an action a lapsed plan still allows — removing\n * access, the account's own settings, an operator's admin route (§12.13). One constant,\n * so the call sites read alike. */\nexport const COMMIT_EXCEPT_BILLING = { except: [\"billing\"] } as const;\n\n/**\n * What {@link useWriteLock} returns: whether commits are locked here as a control with\n * the scope asked for sees it, and why.\n */\nexport interface WriteLock {\n locked: boolean;\n /** The one sentence a locked commit shows in its tooltip: the first hold in scope's.\n * Always set while `locked`; `undefined` when not. */\n reason: ReactNode | undefined;\n /** The first hold in scope's kind; `undefined` while unlocked, or for a source that\n * names none. */\n kind: WriteLockKind | undefined;\n /**\n * EVERY locked source the provider holds, in the order the server refuses them\n * (§12.3: the demo's 403 before billing's 402) — unfiltered by the scope, for code\n * that must know what else locks (a toast that names the plan, a swipe plan). Empty\n * while the provider is unlocked.\n */\n holds: readonly WriteLockHold[];\n}\n\nconst NO_HOLDS: readonly WriteLockHold[] = [];\n\nconst UNLOCKED: WriteLock = { locked: false, reason: undefined, kind: undefined, holds: NO_HOLDS };\n\nconst WriteLockContext = createContext<WriteLock>(UNLOCKED);\n\nexport interface WriteLockProviderProps {\n /** Commits below are locked. `false` unlocks a subtree under an outer lock. */\n locked: boolean;\n /**\n * The one sentence that says why — \"Shared with you to read\", \"Read-only demo —\n * saving is disabled\", \"A customer account cannot create curves\". The app's policy,\n * already translated. Left out: `labels.reason`.\n */\n reason?: ReactNode;\n /** What kind of lock this is — `\"demo\"`, `\"billing\"` or the app's own (see\n * {@link WriteLockKind}), for a provider of one source. Left out, no control can be\n * exempt from it. */\n kind?: WriteLockKind;\n /**\n * Every locked source, in refusal order — what `combineWriteLocks` answers, so\n * `<WriteLockProvider {...combineWriteLocks([...])}>` carries them. Given while\n * `locked`, it wins over `kind` and `reason`; a hold without a reason takes\n * `labels.reason`.\n */\n holds?: readonly WriteLockHold[];\n labels?: Partial<WriteLockLabels>;\n children?: ReactNode;\n}\n\n// `null`/`\"\"`/`false` count as \"no reason given\": a lock whose tooltip is empty would be\n// a disabled button that cannot say why, the thing this replaces.\nfunction given(reason: ReactNode): boolean {\n return reason !== undefined && reason !== null && reason !== false && reason !== \"\";\n}\n\n/**\n * The read-only lock — **everything renders; only the commit is locked.**\n *\n * keksdose (features/budgets/write-lock.tsx, the read-only demo budget) and\n * Kurvenschmiede (features/sharing/write-lock.tsx, a curve shared to view, a customer\n * account that owns nothing) each built the same `SaveGuard`: the page, its tabs,\n * forms and dialogs render exactly as for an owner, because a viewer looking at half\n * a page is not looking at what they were sent; what changes is that the control\n * that SAVES is off and says why on hover or focus. Both wrapped each Save in a\n * Tooltip and forced a native `disabled` on it — out of the tab order, so the reason\n * never reached a keyboard — and both had to remember it at thirty call sites.\n *\n * Here the page mounts one provider and each commit control opts in with `commit`\n * ({@link Button}, {@link IconButton}, {@link FormActions}): under a lock it takes the\n * kit's `disabledReason` path with this reason — `aria-disabled` and focusable,\n * every activation swallowed, the reason in the kit Tooltip and its description.\n *\n * Who is locked is the app's: the provider takes a boolean, never a role. Fields stay\n * editable — nothing in them reaches the server until the commit is pressed, and a\n * form you cannot fill in is not a demo of the form (keksdose accounts-page). A\n * control that IS its own commit (a toggle that saves on change) reads\n * {@link useWriteLock} and disables itself. The lock is a courtesy, not a guard: the\n * server still refuses the write.\n *\n * **A lock says its source** (0.33, docs/billing-harmonization.md §12.36). A lapsed\n * plan locks creating and changing, but not removing access or the account's own\n * settings (§3.3, §12.13), and the kit's parts for those hard-coded `commit` — so\n * kastlan's app-wide lock locked a member's own sign-out everywhere. Each source now\n * has a kind, the provider holds every locked one in order (`holds`, from\n * `combineWriteLocks`), and a control's `commit` may name the kinds it is exempt from\n * ({@link CommitScope}). The kit's parts follow §3.3 and §12.13 by themselves.\n *\n * Nested providers: the nearest wins, so an inner `locked={false}` reopens a section\n * the caller may write (a viewer's own notes on a shared curve) — every source at\n * once — and an inner lock with its own reason (Kurvenschmiede's owner lock beside the\n * viewer lock) overrides the outer one's sentence and its holds.\n */\nexport function WriteLockProvider({ locked, reason, kind, holds, labels, children }: WriteLockProviderProps) {\n // The `writeLock` namespace: prop > `<UiKitProvider labels>` > English.\n const fallback = useKitLabels(\"writeLock\", DEFAULT_WRITE_LOCK_LABELS, labels).reason;\n // `holds` wins while it has any; otherwise this provider is one source of its own.\n const several = locked && holds !== undefined && holds.length > 0 ? holds : undefined;\n const firstKind = several ? several[0].kind : kind;\n const firstGiven = several ? several[0].reason : reason;\n const firstReason = given(firstGiven) ? firstGiven : fallback;\n // Memoised on the first hold's kind and sentence — the strings an app passes — so a\n // one-source lock keeps one context value across renders; a list of several is\n // memoised on its own identity.\n const many = several && several.length > 1 ? several : undefined;\n const value = useMemo<WriteLock>(() => {\n if (!locked) return UNLOCKED;\n const all = many\n ? many.map((hold) => ({ kind: hold.kind, reason: given(hold.reason) ? hold.reason : fallback }))\n : [{ kind: firstKind, reason: firstReason }];\n return { locked: true, reason: firstReason, kind: firstKind, holds: all };\n }, [locked, many, firstKind, firstReason, fallback]);\n return <WriteLockContext.Provider value={value}>{children}</WriteLockContext.Provider>;\n}\n\n/**\n * Whether a hold refuses a control with this scope: `true` refuses with every hold,\n * `{ except }` with every hold whose kind it does not name. A hold with no kind is\n * never exempted — an app that forgot to name its source must not reopen by accident.\n */\nfunction inScope(hold: WriteLockHold, scope: CommitScope): boolean {\n if (scope === true) return true;\n if (scope === false) return false;\n return hold.kind === undefined || !scope.except.includes(hold.kind);\n}\n\n/**\n * The lock as a control with `scope` sees it — {@link useWriteLock}'s answer, pure, for\n * a scope known only at call time: `useConfirm` reads the CALLER's lock when it is\n * called, and applies each `confirm({ commit })`'s own scope to it when it runs.\n *\n * `undefined` and `false` see no lock (a control without `commit`); `true` sees the\n * lock as it is; `{ except }` sees the first hold of another kind, with its reason\n * and kind. `holds` is passed on unfiltered.\n */\nexport function writeLockFor(lock: WriteLock, scope: CommitScope | undefined): WriteLock {\n if (!lock.locked || scope === true) return lock;\n // A lock built by hand (a test's, an app's own context) may carry no holds: it is\n // then the one source it describes.\n const holds = lock.holds.length > 0 ? lock.holds : [{ kind: lock.kind, reason: lock.reason }];\n const first = scope === undefined ? undefined : holds.find((hold) => inScope(hold, scope));\n if (!first) return { ...UNLOCKED, holds: lock.holds };\n // The first in scope is the provider's own first: the lock as it is, same object.\n if (first === holds[0]) return lock;\n return { locked: true, reason: first.reason, kind: first.kind, holds: lock.holds };\n}\n\n/**\n * The nearest {@link WriteLockProvider}'s lock, as a control with `scope` sees it —\n * unlocked with no provider. Left out, the scope is `true`: every lock.\n *\n * For code that must KNOW rather than a control that opts in: a toast that says why,\n * a swipe plan that leaves an action out, a hand-rolled toggle that disables itself.\n * `useWriteLock(COMMIT_EXCEPT_BILLING)` answers \"would a lapsed plan's lock refuse me?\"\n * as a removal sees it — what keksdose's `useWriteLockKind() !== \"billing\"` asked.\n */\nexport function useWriteLock(scope: CommitScope = true): WriteLock {\n return writeLockFor(useContext(WriteLockContext), scope);\n}\n\n/**\n * The `disabledReason` a control with `commit` should use: the lock's reason while\n * the lock refuses this scope — it wins over the control's own, since it is the answer\n * to the question the hover is asking — else the control's own. Internal to the kit's\n * commit controls.\n */\nexport function useCommitReason(commit: CommitScope | undefined, own: ReactNode): ReactNode {\n const lock = writeLockFor(useContext(WriteLockContext), commit);\n return lock.locked ? lock.reason : own;\n}\n"],"mappings":";AAoKS;AApKT,SAAS,eAAe,YAAY,eAAe;AAEnD,SAAS,oBAAoB;AAQtB,MAAM,4BAA6C;AAAA,EACxD,QAAQ;AACV;AAqCO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,SAAS,EAAE;AAuB3D,MAAM,WAAqC,CAAC;AAE5C,MAAM,WAAsB,EAAE,QAAQ,OAAO,QAAQ,QAAW,MAAM,QAAW,OAAO,SAAS;AAEjG,MAAM,mBAAmB,cAAyB,QAAQ;AA4B1D,SAAS,MAAM,QAA4B;AACzC,SAAO,WAAW,UAAa,WAAW,QAAQ,WAAW,SAAS,WAAW;AACnF;AAuCO,SAAS,kBAAkB,EAAE,QAAQ,QAAQ,MAAM,OAAO,QAAQ,SAAS,GAA2B;AAE3G,QAAM,WAAW,aAAa,aAAa,2BAA2B,MAAM,EAAE;AAE9E,QAAM,UAAU,UAAU,UAAU,UAAa,MAAM,SAAS,IAAI,QAAQ;AAC5E,QAAM,YAAY,UAAU,QAAQ,CAAC,EAAE,OAAO;AAC9C,QAAM,aAAa,UAAU,QAAQ,CAAC,EAAE,SAAS;AACjD,QAAM,cAAc,MAAM,UAAU,IAAI,aAAa;AAIrD,QAAM,OAAO,WAAW,QAAQ,SAAS,IAAI,UAAU;AACvD,QAAM,QAAQ,QAAmB,MAAM;AACrC,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,MAAM,OACR,KAAK,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,IAAI,KAAK,SAAS,SAAS,EAAE,IAC7F,CAAC,EAAE,MAAM,WAAW,QAAQ,YAAY,CAAC;AAC7C,WAAO,EAAE,QAAQ,MAAM,QAAQ,aAAa,MAAM,WAAW,OAAO,IAAI;AAAA,EAC1E,GAAG,CAAC,QAAQ,MAAM,WAAW,aAAa,QAAQ,CAAC;AACnD,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAe,UAAS;AAC5D;AAOA,SAAS,QAAQ,MAAqB,OAA6B;AACjE,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,MAAO,QAAO;AAC5B,SAAO,KAAK,SAAS,UAAa,CAAC,MAAM,OAAO,SAAS,KAAK,IAAI;AACpE;AAWO,SAAS,aAAa,MAAiB,OAA2C;AACvF,MAAI,CAAC,KAAK,UAAU,UAAU,KAAM,QAAO;AAG3C,QAAM,QAAQ,KAAK,MAAM,SAAS,IAAI,KAAK,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO,CAAC;AAC5F,QAAM,QAAQ,UAAU,SAAY,SAAY,MAAM,KAAK,CAAC,SAAS,QAAQ,MAAM,KAAK,CAAC;AACzF,MAAI,CAAC,MAAO,QAAO,EAAE,GAAG,UAAU,OAAO,KAAK,MAAM;AAEpD,MAAI,UAAU,MAAM,CAAC,EAAG,QAAO;AAC/B,SAAO,EAAE,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK,MAAM;AACnF;AAWO,SAAS,aAAa,QAAqB,MAAiB;AACjE,SAAO,aAAa,WAAW,gBAAgB,GAAG,KAAK;AACzD;AAQO,SAAS,gBAAgB,QAAiC,KAA2B;AAC1F,QAAM,OAAO,aAAa,WAAW,gBAAgB,GAAG,MAAM;AAC9D,SAAO,KAAK,SAAS,KAAK,SAAS;AACrC;","names":[]}
@@ -387,6 +387,23 @@ interface DataTableProps<T> {
387
387
  rowHref?: (row: T) => string | undefined;
388
388
  expandedRow?: (row: T) => ReactNode | null;
389
389
  isExpanded?: (row: T) => boolean;
390
+ /**
391
+ * Extra classes for a row — the `<tr>` on desktop, the card on mobile. Merged last,
392
+ * so a `hover:` fill here replaces the row's own `hover:bg-[var(--bg-hover)]`.
393
+ *
394
+ * **A row you paint has to pick its own hover** (0.33, docs/colour-roles-harmonization.md
395
+ * §12.2): the kit cannot see your rest colour, and `--bg-hover` is mixed against the
396
+ * card. The rule: a hover differs from its rest by 1.08:1 or more, and every text role
397
+ * on it keeps 4.5:1.
398
+ * - A row that rests on the well (`bg-surface-2`) hovers to the CARD,
399
+ * `hover:bg-surface`: in light the well is the page, and `--bg-hover` sits 1.04:1
400
+ * from it.
401
+ * - A row whose well MARKS A STATE (selected) keeps its fill and draws a 1 px inside
402
+ * line instead, since the card would read as "not selected":
403
+ * `bg-surface-2 hover:bg-surface-2 hover:outline hover:-outline-offset-1 hover:outline-strong`.
404
+ * An outline, not a shadow: a shadow on a `<tr>` is not painted by every engine.
405
+ * - Not `--bg-active` for a selected row: its muted and money text fall to 3.8–4.7:1.
406
+ */
390
407
  rowClassName?: (row: T) => string | undefined;
391
408
  /**
392
409
  * Extra DOM attributes for a row's container — the `<tr>` on desktop, the
@@ -1,7 +1,18 @@
1
- export { C as ColumnFilter, D as DEFAULT_DATA_TABLE_LABELS, a as DEFAULT_DATA_TABLE_SORT_LABELS, b as DataTable, c as DataTableChrome, d as DataTableColumn, e as DataTableDensity, f as DataTableLabels, g as DataTableProps, h as DataTableRowAction, i as DataTableSortLabels, F as FilterState, j as FilterValue, M as MobileSwipeActions, S as ServerPagination, T as TableUrlState, k as TableUrlStateProps, l as TableUrlSync, U as UseTableUrlStateOptions, m as UseTableUrlStateReturn, n as dateFilter, o as decodeFilterValue, p as decodeFilterValueOfType, q as defaultFilterState, r as encodeFilterValue, s as filterHref, t as isFilterActive, u as missingDataTableLabels, v as numberFilter, w as readTableUrlState, x as resolveDataTableLabels, y as resolveFilter, z as rowMatches, A as selectFilter, B as textFilter, E as useTableUrlState } from './data-table-labels-kpAAVi6g.js';
1
+ export { C as ColumnFilter, D as DEFAULT_DATA_TABLE_LABELS, a as DEFAULT_DATA_TABLE_SORT_LABELS, b as DataTable, c as DataTableChrome, d as DataTableColumn, e as DataTableDensity, f as DataTableLabels, g as DataTableProps, h as DataTableRowAction, i as DataTableSortLabels, F as FilterState, j as FilterValue, M as MobileSwipeActions, S as ServerPagination, T as TableUrlState, k as TableUrlStateProps, l as TableUrlSync, U as UseTableUrlStateOptions, m as UseTableUrlStateReturn, n as dateFilter, o as decodeFilterValue, p as decodeFilterValueOfType, q as defaultFilterState, r as encodeFilterValue, s as filterHref, t as isFilterActive, u as missingDataTableLabels, v as numberFilter, w as readTableUrlState, x as resolveDataTableLabels, y as resolveFilter, z as rowMatches, A as selectFilter, B as textFilter, E as useTableUrlState } from './data-table-labels-BJ5JE_X2.js';
2
2
  export { SortCycle, SortDir, SortState, SortStepOptions, decodeSorts, encodeSorts, nextSorts, normalizeSorts } from './components/data-table-sort.js';
3
3
  export { PAGE_SIZE_OPTIONS, Pagination } from './components/data-table-pagination.js';
4
4
  export { FilterPopover } from './components/data-table-filter-popover.js';
5
5
  export { BooleanColumnOptions, BooleanMark, BooleanMarkProps, booleanColumn } from './components/data-table-cells.js';
6
6
  import 'react';
7
7
  import './components/swipeable-row.js';
8
+ import './components/status-dot.js';
9
+ import './components/progress-bar.js';
10
+ import './components/signed-amount.js';
11
+ import './components/stat-tile.js';
12
+ import './components/chip.js';
13
+ import 'lucide-react';
14
+ import './components/field-parts.js';
15
+ import './components/tooltip.js';
16
+ import './hooks/use-anchored-rect.js';
17
+ import './lib/clipping.js';
18
+ import './components/write-lock.js';