@entifix/react-controls 0.18.2 → 0.20.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 (328) hide show
  1. package/README.md +13 -5
  2. package/dist/i18n/catalog/en.d.ts.map +1 -1
  3. package/dist/i18n/catalog/en.js +68 -10
  4. package/dist/i18n/catalog/en.js.map +1 -1
  5. package/dist/i18n/catalog/es.d.ts +76 -5
  6. package/dist/i18n/catalog/es.d.ts.map +1 -1
  7. package/dist/i18n/catalog/es.js +74 -10
  8. package/dist/i18n/catalog/es.js.map +1 -1
  9. package/dist/i18n/catalog/index.d.ts +126 -10
  10. package/dist/i18n/catalog/index.d.ts.map +1 -1
  11. package/dist/i18n/entity-labels.d.ts +14 -0
  12. package/dist/i18n/entity-labels.d.ts.map +1 -1
  13. package/dist/i18n/entity-labels.js +15 -0
  14. package/dist/i18n/entity-labels.js.map +1 -1
  15. package/dist/i18n/i18n-context.js +2 -2
  16. package/dist/i18n/i18n-context.js.map +1 -1
  17. package/dist/index.d.ts +13 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +13 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/primitives.d.ts +7 -1
  22. package/dist/primitives.d.ts.map +1 -1
  23. package/dist/primitives.js +7 -1
  24. package/dist/primitives.js.map +1 -1
  25. package/dist/theme/index.d.ts +1 -0
  26. package/dist/theme/index.d.ts.map +1 -1
  27. package/dist/theme/index.js +1 -0
  28. package/dist/theme/index.js.map +1 -1
  29. package/dist/theme/theme-context.d.ts +35 -7
  30. package/dist/theme/theme-context.d.ts.map +1 -1
  31. package/dist/theme/theme-context.js +109 -21
  32. package/dist/theme/theme-context.js.map +1 -1
  33. package/dist/theme/theme-cookie.d.ts +9 -0
  34. package/dist/theme/theme-cookie.d.ts.map +1 -0
  35. package/dist/theme/theme-cookie.js +8 -0
  36. package/dist/theme/theme-cookie.js.map +1 -0
  37. package/dist/theme/theme-script.d.ts +8 -5
  38. package/dist/theme/theme-script.d.ts.map +1 -1
  39. package/dist/theme/theme-script.js +24 -10
  40. package/dist/theme/theme-script.js.map +1 -1
  41. package/dist/theme/types.d.ts +19 -3
  42. package/dist/theme/types.d.ts.map +1 -1
  43. package/dist/theme/types.js.map +1 -1
  44. package/dist/ui/actions/action-surfaces.d.ts +1 -1
  45. package/dist/ui/actions/action-surfaces.js +1 -1
  46. package/dist/ui/actions/action-surfaces.js.map +1 -1
  47. package/dist/ui/actions/error-actions.d.ts +32 -0
  48. package/dist/ui/actions/error-actions.d.ts.map +1 -0
  49. package/dist/ui/actions/error-actions.js +40 -0
  50. package/dist/ui/actions/error-actions.js.map +1 -0
  51. package/dist/ui/actions/index.d.ts +2 -0
  52. package/dist/ui/actions/index.d.ts.map +1 -1
  53. package/dist/ui/actions/index.js +2 -0
  54. package/dist/ui/actions/index.js.map +1 -1
  55. package/dist/ui/actions/shortcut.d.ts +13 -0
  56. package/dist/ui/actions/shortcut.d.ts.map +1 -0
  57. package/dist/ui/actions/shortcut.js +18 -0
  58. package/dist/ui/actions/shortcut.js.map +1 -0
  59. package/dist/ui/actions/use-verb-invoker.d.ts +50 -0
  60. package/dist/ui/actions/use-verb-invoker.d.ts.map +1 -0
  61. package/dist/ui/actions/use-verb-invoker.js +93 -0
  62. package/dist/ui/actions/use-verb-invoker.js.map +1 -0
  63. package/dist/ui/atoms/alert/alert-dismiss.d.ts +9 -0
  64. package/dist/ui/atoms/alert/alert-dismiss.d.ts.map +1 -0
  65. package/dist/ui/atoms/alert/alert-dismiss.js +28 -0
  66. package/dist/ui/atoms/alert/alert-dismiss.js.map +1 -0
  67. package/dist/ui/atoms/alert/alert.d.ts +24 -0
  68. package/dist/ui/atoms/alert/alert.d.ts.map +1 -0
  69. package/dist/ui/atoms/alert/alert.js +50 -0
  70. package/dist/ui/atoms/alert/alert.js.map +1 -0
  71. package/dist/ui/atoms/alert/index.d.ts +3 -0
  72. package/dist/ui/atoms/alert/index.d.ts.map +1 -0
  73. package/dist/ui/atoms/alert/index.js +4 -0
  74. package/dist/ui/atoms/alert/index.js.map +1 -0
  75. package/dist/ui/atoms/alert/tone.d.ts +8 -0
  76. package/dist/ui/atoms/alert/tone.d.ts.map +1 -0
  77. package/dist/ui/atoms/alert/tone.js +11 -0
  78. package/dist/ui/atoms/alert/tone.js.map +1 -0
  79. package/dist/ui/atoms/button/button-recipe.js +1 -1
  80. package/dist/ui/atoms/button/button-recipe.js.map +1 -1
  81. package/dist/ui/atoms/button/index.d.ts +1 -0
  82. package/dist/ui/atoms/button/index.d.ts.map +1 -1
  83. package/dist/ui/atoms/button/index.js +1 -0
  84. package/dist/ui/atoms/button/index.js.map +1 -1
  85. package/dist/ui/atoms/button/submit-button.d.ts +13 -0
  86. package/dist/ui/atoms/button/submit-button.d.ts.map +1 -0
  87. package/dist/ui/atoms/button/submit-button.js +29 -0
  88. package/dist/ui/atoms/button/submit-button.js.map +1 -0
  89. package/dist/ui/atoms/cell-value/cell-value.d.ts +6 -1
  90. package/dist/ui/atoms/cell-value/cell-value.d.ts.map +1 -1
  91. package/dist/ui/atoms/cell-value/cell-value.js +48 -16
  92. package/dist/ui/atoms/cell-value/cell-value.js.map +1 -1
  93. package/dist/ui/atoms/field/checkbox.d.ts.map +1 -1
  94. package/dist/ui/atoms/field/checkbox.js +21 -1
  95. package/dist/ui/atoms/field/checkbox.js.map +1 -1
  96. package/dist/ui/atoms/field/field.js +1 -1
  97. package/dist/ui/atoms/field/field.js.map +1 -1
  98. package/dist/ui/atoms/field-control/field-control.d.ts +7 -1
  99. package/dist/ui/atoms/field-control/field-control.d.ts.map +1 -1
  100. package/dist/ui/atoms/field-control/field-control.js +25 -3
  101. package/dist/ui/atoms/field-control/field-control.js.map +1 -1
  102. package/dist/ui/atoms/money/index.d.ts +4 -0
  103. package/dist/ui/atoms/money/index.d.ts.map +1 -0
  104. package/dist/ui/atoms/money/index.js +5 -0
  105. package/dist/ui/atoms/money/index.js.map +1 -0
  106. package/dist/ui/atoms/money/money-input.d.ts +19 -0
  107. package/dist/ui/atoms/money/money-input.d.ts.map +1 -0
  108. package/dist/ui/atoms/money/money-input.js +75 -0
  109. package/dist/ui/atoms/money/money-input.js.map +1 -0
  110. package/dist/ui/atoms/money/money-math.d.ts +21 -0
  111. package/dist/ui/atoms/money/money-math.d.ts.map +1 -0
  112. package/dist/ui/atoms/money/money-math.js +36 -0
  113. package/dist/ui/atoms/money/money-math.js.map +1 -0
  114. package/dist/ui/atoms/money/money.d.ts +19 -0
  115. package/dist/ui/atoms/money/money.d.ts.map +1 -0
  116. package/dist/ui/atoms/money/money.js +26 -0
  117. package/dist/ui/atoms/money/money.js.map +1 -0
  118. package/dist/ui/atoms/number-input/index.d.ts +3 -0
  119. package/dist/ui/atoms/number-input/index.d.ts.map +1 -0
  120. package/dist/ui/atoms/number-input/index.js +4 -0
  121. package/dist/ui/atoms/number-input/index.js.map +1 -0
  122. package/dist/ui/atoms/number-input/number-input.d.ts +10 -0
  123. package/dist/ui/atoms/number-input/number-input.d.ts.map +1 -0
  124. package/dist/ui/atoms/number-input/number-input.js +23 -0
  125. package/dist/ui/atoms/number-input/number-input.js.map +1 -0
  126. package/dist/ui/atoms/number-input/quantity-input.d.ts +29 -0
  127. package/dist/ui/atoms/number-input/quantity-input.d.ts.map +1 -0
  128. package/dist/ui/atoms/number-input/quantity-input.js +100 -0
  129. package/dist/ui/atoms/number-input/quantity-input.js.map +1 -0
  130. package/dist/ui/atoms/skeleton/skeleton.js +1 -1
  131. package/dist/ui/atoms/skeleton/skeleton.js.map +1 -1
  132. package/dist/ui/atoms/status-tag/index.d.ts +2 -0
  133. package/dist/ui/atoms/status-tag/index.d.ts.map +1 -0
  134. package/dist/ui/atoms/status-tag/index.js +3 -0
  135. package/dist/ui/atoms/status-tag/index.js.map +1 -0
  136. package/dist/ui/atoms/status-tag/status-tag.d.ts +17 -0
  137. package/dist/ui/atoms/status-tag/status-tag.d.ts.map +1 -0
  138. package/dist/ui/atoms/status-tag/status-tag.js +37 -0
  139. package/dist/ui/atoms/status-tag/status-tag.js.map +1 -0
  140. package/dist/ui/atoms/switch/switch.d.ts.map +1 -1
  141. package/dist/ui/atoms/switch/switch.js +6 -3
  142. package/dist/ui/atoms/switch/switch.js.map +1 -1
  143. package/dist/ui/atoms/table/table.d.ts +12 -3
  144. package/dist/ui/atoms/table/table.d.ts.map +1 -1
  145. package/dist/ui/atoms/table/table.js +59 -10
  146. package/dist/ui/atoms/table/table.js.map +1 -1
  147. package/dist/ui/atoms/text/text.d.ts +2 -2
  148. package/dist/ui/atoms/text/text.d.ts.map +1 -1
  149. package/dist/ui/atoms/text/text.js.map +1 -1
  150. package/dist/ui/molecules/action-bar/action-bar.d.ts +76 -0
  151. package/dist/ui/molecules/action-bar/action-bar.d.ts.map +1 -0
  152. package/dist/ui/molecules/action-bar/action-bar.js +218 -0
  153. package/dist/ui/molecules/action-bar/action-bar.js.map +1 -0
  154. package/dist/ui/molecules/action-bar/index.d.ts +2 -0
  155. package/dist/ui/molecules/action-bar/index.d.ts.map +1 -0
  156. package/dist/ui/molecules/action-bar/index.js +3 -0
  157. package/dist/ui/molecules/action-bar/index.js.map +1 -0
  158. package/dist/ui/molecules/breadcrumbs/breadcrumbs.d.ts +11 -2
  159. package/dist/ui/molecules/breadcrumbs/breadcrumbs.d.ts.map +1 -1
  160. package/dist/ui/molecules/breadcrumbs/breadcrumbs.js +9 -7
  161. package/dist/ui/molecules/breadcrumbs/breadcrumbs.js.map +1 -1
  162. package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.d.ts.map +1 -1
  163. package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.js +8 -10
  164. package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.js.map +1 -1
  165. package/dist/ui/molecules/bulk-result/bulk-result.d.ts +3 -3
  166. package/dist/ui/molecules/bulk-result/bulk-result.js +4 -4
  167. package/dist/ui/molecules/bulk-result/bulk-result.js.map +1 -1
  168. package/dist/ui/molecules/column-settings/column-settings.js +1 -1
  169. package/dist/ui/molecules/column-settings/column-settings.js.map +1 -1
  170. package/dist/ui/molecules/confirm-dialog/confirm-dialog.d.ts +24 -9
  171. package/dist/ui/molecules/confirm-dialog/confirm-dialog.d.ts.map +1 -1
  172. package/dist/ui/molecules/confirm-dialog/confirm-dialog.js +38 -13
  173. package/dist/ui/molecules/confirm-dialog/confirm-dialog.js.map +1 -1
  174. package/dist/ui/molecules/description-list/description-list.d.ts +17 -0
  175. package/dist/ui/molecules/description-list/description-list.d.ts.map +1 -0
  176. package/dist/ui/molecules/description-list/description-list.js +36 -0
  177. package/dist/ui/molecules/description-list/description-list.js.map +1 -0
  178. package/dist/ui/molecules/description-list/index.d.ts +2 -0
  179. package/dist/ui/molecules/description-list/index.d.ts.map +1 -0
  180. package/dist/ui/molecules/description-list/index.js +3 -0
  181. package/dist/ui/molecules/description-list/index.js.map +1 -0
  182. package/dist/ui/molecules/drawer/drawer.js +3 -3
  183. package/dist/ui/molecules/drawer/drawer.js.map +1 -1
  184. package/dist/ui/molecules/empty-state/empty-state.d.ts +15 -0
  185. package/dist/ui/molecules/empty-state/empty-state.d.ts.map +1 -0
  186. package/dist/ui/molecules/empty-state/empty-state.js +29 -0
  187. package/dist/ui/molecules/empty-state/empty-state.js.map +1 -0
  188. package/dist/ui/molecules/empty-state/index.d.ts +2 -0
  189. package/dist/ui/molecules/empty-state/index.d.ts.map +1 -0
  190. package/dist/ui/molecules/empty-state/index.js +3 -0
  191. package/dist/ui/molecules/empty-state/index.js.map +1 -0
  192. package/dist/ui/molecules/entity-link-input/entity-link-input.d.ts.map +1 -1
  193. package/dist/ui/molecules/entity-link-input/entity-link-input.js +7 -4
  194. package/dist/ui/molecules/entity-link-input/entity-link-input.js.map +1 -1
  195. package/dist/ui/molecules/entity-link-picker/entity-link-picker.js +2 -2
  196. package/dist/ui/molecules/entity-link-picker/entity-link-picker.js.map +1 -1
  197. package/dist/ui/molecules/entity-record-card/entity-record-card.d.ts +33 -20
  198. package/dist/ui/molecules/entity-record-card/entity-record-card.d.ts.map +1 -1
  199. package/dist/ui/molecules/entity-record-card/entity-record-card.js +53 -20
  200. package/dist/ui/molecules/entity-record-card/entity-record-card.js.map +1 -1
  201. package/dist/ui/molecules/filter-builder/filter-builder.d.ts +8 -2
  202. package/dist/ui/molecules/filter-builder/filter-builder.d.ts.map +1 -1
  203. package/dist/ui/molecules/filter-builder/filter-builder.js +14 -5
  204. package/dist/ui/molecules/filter-builder/filter-builder.js.map +1 -1
  205. package/dist/ui/molecules/filter-chips/filter-chips.d.ts +16 -0
  206. package/dist/ui/molecules/filter-chips/filter-chips.d.ts.map +1 -0
  207. package/dist/ui/molecules/filter-chips/filter-chips.js +73 -0
  208. package/dist/ui/molecules/filter-chips/filter-chips.js.map +1 -0
  209. package/dist/ui/molecules/filter-chips/index.d.ts +2 -0
  210. package/dist/ui/molecules/filter-chips/index.d.ts.map +1 -0
  211. package/dist/ui/molecules/filter-chips/index.js +3 -0
  212. package/dist/ui/molecules/filter-chips/index.js.map +1 -0
  213. package/dist/ui/molecules/media-gallery/index.d.ts +2 -0
  214. package/dist/ui/molecules/media-gallery/index.d.ts.map +1 -0
  215. package/dist/ui/molecules/media-gallery/index.js +3 -0
  216. package/dist/ui/molecules/media-gallery/index.js.map +1 -0
  217. package/dist/ui/molecules/media-gallery/media-gallery.d.ts +31 -0
  218. package/dist/ui/molecules/media-gallery/media-gallery.d.ts.map +1 -0
  219. package/dist/ui/molecules/media-gallery/media-gallery.js +64 -0
  220. package/dist/ui/molecules/media-gallery/media-gallery.js.map +1 -0
  221. package/dist/ui/molecules/menu/menu.d.ts +11 -1
  222. package/dist/ui/molecules/menu/menu.d.ts.map +1 -1
  223. package/dist/ui/molecules/menu/menu.js +68 -6
  224. package/dist/ui/molecules/menu/menu.js.map +1 -1
  225. package/dist/ui/molecules/nav-menu/nav-menu.js +4 -4
  226. package/dist/ui/molecules/nav-menu/nav-menu.js.map +1 -1
  227. package/dist/ui/molecules/pagination/pagination.d.ts +5 -0
  228. package/dist/ui/molecules/pagination/pagination.d.ts.map +1 -1
  229. package/dist/ui/molecules/pagination/pagination.js +35 -18
  230. package/dist/ui/molecules/pagination/pagination.js.map +1 -1
  231. package/dist/ui/molecules/region-state/index.d.ts +2 -0
  232. package/dist/ui/molecules/region-state/index.d.ts.map +1 -0
  233. package/dist/ui/molecules/region-state/index.js +3 -0
  234. package/dist/ui/molecules/region-state/index.js.map +1 -0
  235. package/dist/ui/molecules/region-state/region-state.d.ts +42 -0
  236. package/dist/ui/molecules/region-state/region-state.d.ts.map +1 -0
  237. package/dist/ui/molecules/region-state/region-state.js +83 -0
  238. package/dist/ui/molecules/region-state/region-state.js.map +1 -0
  239. package/dist/ui/molecules/segmented-nav/segment-classes.d.ts +3 -3
  240. package/dist/ui/molecules/segmented-nav/segment-classes.d.ts.map +1 -1
  241. package/dist/ui/molecules/segmented-nav/segment-classes.js +2 -2
  242. package/dist/ui/molecules/segmented-nav/segment-classes.js.map +1 -1
  243. package/dist/ui/molecules/segmented-nav/segmented-nav.d.ts +14 -4
  244. package/dist/ui/molecules/segmented-nav/segmented-nav.d.ts.map +1 -1
  245. package/dist/ui/molecules/segmented-nav/segmented-nav.js +6 -5
  246. package/dist/ui/molecules/segmented-nav/segmented-nav.js.map +1 -1
  247. package/dist/ui/molecules/split-view/split-view.js +3 -3
  248. package/dist/ui/molecules/split-view/split-view.js.map +1 -1
  249. package/dist/ui/molecules/tab-strip/tab-strip.d.ts +51 -12
  250. package/dist/ui/molecules/tab-strip/tab-strip.d.ts.map +1 -1
  251. package/dist/ui/molecules/tab-strip/tab-strip.js +125 -34
  252. package/dist/ui/molecules/tab-strip/tab-strip.js.map +1 -1
  253. package/dist/ui/molecules/table-toolbar/table-toolbar.d.ts +3 -1
  254. package/dist/ui/molecules/table-toolbar/table-toolbar.d.ts.map +1 -1
  255. package/dist/ui/molecules/table-toolbar/table-toolbar.js +3 -2
  256. package/dist/ui/molecules/table-toolbar/table-toolbar.js.map +1 -1
  257. package/dist/ui/molecules/toast-region/toast-region.d.ts +63 -19
  258. package/dist/ui/molecules/toast-region/toast-region.d.ts.map +1 -1
  259. package/dist/ui/molecules/toast-region/toast-region.js +129 -42
  260. package/dist/ui/molecules/toast-region/toast-region.js.map +1 -1
  261. package/dist/ui/organisms/command-palette/command-palette.d.ts.map +1 -1
  262. package/dist/ui/organisms/command-palette/command-palette.js +25 -18
  263. package/dist/ui/organisms/command-palette/command-palette.js.map +1 -1
  264. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.d.ts.map +1 -1
  265. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.js +8 -3
  266. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.js.map +1 -1
  267. package/dist/ui/organisms/entity-form/entity-form.d.ts +1 -1
  268. package/dist/ui/organisms/entity-form/entity-form.d.ts.map +1 -1
  269. package/dist/ui/organisms/entity-form/entity-form.js +325 -215
  270. package/dist/ui/organisms/entity-form/entity-form.js.map +1 -1
  271. package/dist/ui/organisms/entity-form/entity-form.types.d.ts +8 -0
  272. package/dist/ui/organisms/entity-form/entity-form.types.d.ts.map +1 -1
  273. package/dist/ui/organisms/entity-form/entity-form.types.js.map +1 -1
  274. package/dist/ui/organisms/entity-table/entity-table.d.ts +1 -1
  275. package/dist/ui/organisms/entity-table/entity-table.d.ts.map +1 -1
  276. package/dist/ui/organisms/entity-table/entity-table.js +334 -198
  277. package/dist/ui/organisms/entity-table/entity-table.js.map +1 -1
  278. package/dist/ui/organisms/entity-table/entity-table.types.d.ts +19 -4
  279. package/dist/ui/organisms/entity-table/entity-table.types.d.ts.map +1 -1
  280. package/dist/ui/organisms/entity-table/entity-table.types.js.map +1 -1
  281. package/dist/ui/organisms/entity-table/header-sort.d.ts +18 -0
  282. package/dist/ui/organisms/entity-table/header-sort.d.ts.map +1 -0
  283. package/dist/ui/organisms/entity-table/header-sort.js +54 -0
  284. package/dist/ui/organisms/entity-table/header-sort.js.map +1 -0
  285. package/dist/ui/organisms/entity-table/pivot.d.ts +25 -0
  286. package/dist/ui/organisms/entity-table/pivot.d.ts.map +1 -0
  287. package/dist/ui/organisms/entity-table/pivot.js +106 -0
  288. package/dist/ui/organisms/entity-table/pivot.js.map +1 -0
  289. package/dist/ui/organisms/entity-table/use-result-announcement.d.ts +13 -0
  290. package/dist/ui/organisms/entity-table/use-result-announcement.d.ts.map +1 -0
  291. package/dist/ui/organisms/entity-table/use-result-announcement.js +31 -0
  292. package/dist/ui/organisms/entity-table/use-result-announcement.js.map +1 -0
  293. package/dist/ui/organisms/top-bar/live-indicator.d.ts +11 -0
  294. package/dist/ui/organisms/top-bar/live-indicator.d.ts.map +1 -0
  295. package/dist/ui/organisms/top-bar/live-indicator.js +46 -0
  296. package/dist/ui/organisms/top-bar/live-indicator.js.map +1 -0
  297. package/dist/ui/organisms/top-bar/top-bar.d.ts +11 -2
  298. package/dist/ui/organisms/top-bar/top-bar.d.ts.map +1 -1
  299. package/dist/ui/organisms/top-bar/top-bar.js +14 -5
  300. package/dist/ui/organisms/top-bar/top-bar.js.map +1 -1
  301. package/dist/ui/organisms/wizard/wizard.d.ts +1 -1
  302. package/dist/ui/organisms/wizard/wizard.d.ts.map +1 -1
  303. package/dist/ui/organisms/wizard/wizard.js +7 -1
  304. package/dist/ui/organisms/wizard/wizard.js.map +1 -1
  305. package/dist/ui/organisms/wizard/wizard.types.d.ts +8 -0
  306. package/dist/ui/organisms/wizard/wizard.types.d.ts.map +1 -1
  307. package/dist/ui/organisms/wizard/wizard.types.js.map +1 -1
  308. package/dist/ui/utils/live-updates.d.ts +24 -0
  309. package/dist/ui/utils/live-updates.d.ts.map +1 -0
  310. package/dist/ui/utils/live-updates.js +20 -0
  311. package/dist/ui/utils/live-updates.js.map +1 -0
  312. package/dist/ui/utils/use-focus-on-arrival.d.ts +14 -0
  313. package/dist/ui/utils/use-focus-on-arrival.d.ts.map +1 -0
  314. package/dist/ui/utils/use-focus-on-arrival.js +42 -0
  315. package/dist/ui/utils/use-focus-on-arrival.js.map +1 -0
  316. package/dist/ui/utils/use-hotkey.d.ts +44 -25
  317. package/dist/ui/utils/use-hotkey.d.ts.map +1 -1
  318. package/dist/ui/utils/use-hotkey.js +80 -48
  319. package/dist/ui/utils/use-hotkey.js.map +1 -1
  320. package/package.json +5 -5
  321. package/dist/ui/molecules/split-button/index.d.ts +0 -2
  322. package/dist/ui/molecules/split-button/index.d.ts.map +0 -1
  323. package/dist/ui/molecules/split-button/index.js +0 -3
  324. package/dist/ui/molecules/split-button/index.js.map +0 -1
  325. package/dist/ui/molecules/split-button/split-button.d.ts +0 -21
  326. package/dist/ui/molecules/split-button/split-button.d.ts.map +0 -1
  327. package/dist/ui/molecules/split-button/split-button.js +0 -35
  328. package/dist/ui/molecules/split-button/split-button.js.map +0 -1
@@ -1,48 +1,34 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { emptySelection, extractMetaEntity, hierarchyOf, isSelected, selectionSize, toggleSelected } from '@entifix/core';
4
- import { Fragment, useMemo, useRef, useState } from 'react';
5
- import { useErrorMessage, useT, useTranslateKey } from '../../../i18n/index.js';
6
- import { OVERFLOW_GLYPH, renderAnchor, useCasesForSurface } from '../../actions/index.js';
7
- import { Button } from '../../atoms/button/index.js';
3
+ import { emptySelection, extractMetaEntity, hierarchyOf, isSelected, queryPropertyFor, selectionSize, toggleSelected } from '@entifix/core';
4
+ import { Fragment, useId, useMemo, useRef, useState } from 'react';
5
+ import { useEntityNoun, useLocale, useT, useTranslateKey } from '../../../i18n/index.js';
6
+ import { renderAnchor, useCasesForSurface } from '../../actions/index.js';
7
+ import { useVerbInvoker } from '../../actions/use-verb-invoker.js';
8
+ import { Button, button } from '../../atoms/button/index.js';
8
9
  import { CellValue } from '../../atoms/cell-value/index.js';
9
10
  import { Checkbox } from '../../atoms/field/index.js';
10
11
  import { Skeleton } from '../../atoms/skeleton/index.js';
11
12
  import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableMessageRow, TableRow } from '../../atoms/table/index.js';
12
13
  import { linkClassName } from '../../atoms/text/index.js';
14
+ import { ActionBar, itemsForUseCases } from '../../molecules/action-bar/index.js';
13
15
  import { BulkActionBar } from '../../molecules/bulk-action-bar/index.js';
14
16
  import { BulkResult } from '../../molecules/bulk-result/index.js';
15
17
  import { ColumnSettings } from '../../molecules/column-settings/index.js';
16
- import { ConfirmDialog } from '../../molecules/confirm-dialog/index.js';
17
18
  import { EntityRecordCard } from '../../molecules/entity-record-card/index.js';
18
19
  import { FilterBuilder } from '../../molecules/filter-builder/index.js';
20
+ import { FilterChips } from '../../molecules/filter-chips/index.js';
19
21
  import { LoadingBoundary } from '../../molecules/loading-boundary/index.js';
20
- import { Menu } from '../../molecules/menu/index.js';
21
22
  import { Pagination } from '../../molecules/pagination/index.js';
23
+ import { RegionState } from '../../molecules/region-state/index.js';
22
24
  import { SortBuilder } from '../../molecules/sort-builder/index.js';
23
25
  import { TableToolbar } from '../../molecules/table-toolbar/index.js';
24
26
  import { readEntityTableSlots } from './entity-table-slots.js';
25
27
  import { shownTreeRows, TreeCell, treeRows } from './entity-table-tree.js';
28
+ import { nextHeaderSorting, sortKeys } from './header-sort.js';
29
+ import { ACTIONS_WIDTH, pivotClasses, pivotWidth, SELECTION_WIDTH } from './pivot.js';
26
30
  import { useEntityTableColumns } from './use-entity-table-columns.js';
27
- /**
28
- * The grid and the card list are both rendered, and CSS picks one. A JS
29
- * breakpoint hook would have to guess during SSR and correct after mount —
30
- * a hydration mismatch on every page load. Classes are written out in full
31
- * because Tailwind cannot see a class name that is concatenated at runtime.
32
- */ const PIVOT_CLASS = {
33
- sm: {
34
- grid: 'hidden sm:block',
35
- cards: 'sm:hidden'
36
- },
37
- md: {
38
- grid: 'hidden md:block',
39
- cards: 'md:hidden'
40
- },
41
- lg: {
42
- grid: 'hidden lg:block',
43
- cards: 'lg:hidden'
44
- }
45
- };
31
+ import { useResultAnnouncement } from './use-result-announcement.js';
46
32
  /**
47
33
  * How many placeholder rows the built-in skeleton draws.
48
34
  *
@@ -51,36 +37,18 @@ import { useEntityTableColumns } from './use-entity-table-columns.js';
51
37
  * a fifty-row page would otherwise paint fifty shimmer rows to stand in for
52
38
  * content that arrives below the fold anyway.
53
39
  */ const SKELETON_ROW_CAP = 5;
54
- export function EntityTable({ entityConstructor, isLoading, skeleton = true, error, items, totalItems, currentPage, pageSize, onPageChange, onPageSizeChange, hrefFor, newHref, renderLink = renderAnchor, onSelect, preferencesKey, showControls = true, pivotBreakpoint = 'md', filtering, sorting, onFilteringChange, onSortingChange, selection, onSelectionChange, metadata, isMetadataLoading = false, onBulkUseCase, onUseCase, bulkOutcomes, onBulkDismiss, onBulkRetry, isBulkRunning = false, children }) {
55
- var _ref;
40
+ /** How many members a card shows as meta when none declares a `card` role. */ const UNDECLARED_META_CAP = 3;
41
+ export function EntityTable({ entityConstructor, isLoading, skeleton = true, error, items, totalItems, currentPage, pageSize, onPageChange, onPageSizeChange, hrefFor, newHref, renderLink = renderAnchor, onSelect, preferencesKey, showControls = true, pivotBreakpoint, filtering, sorting, onFilteringChange, onSortingChange, facets, selection, onSelectionChange, metadata, isMetadataLoading = false, onBulkUseCase, onUseCase, onRetry, bulkOutcomes, onBulkDismiss, onBulkRetry, isBulkRunning = false, children }) {
42
+ var _ref, _ref1;
56
43
  const t = useT();
57
44
  // A descriptor's label is a runtime catalog key — the typed gate cannot see
58
45
  // it, which is why a host's catalog check is what catches a typo.
59
46
  const translateKey = useTranslateKey();
60
- const errorMessage = useErrorMessage();
47
+ const entityNoun = useEntityNoun();
61
48
  const metaEntity = extractMetaEntity(entityConstructor);
62
49
  const slots = readEntityTableSlots(children);
63
50
  const [panel, setPanel] = useState('none');
64
- /**
65
- * A verb waiting to be confirmed, and what it will act on.
66
- *
67
- * ⚠️ **The table had no confirmation flow at all** until a change moved a
68
- * destructive verb onto it. It read `confirm.tone` — only to pick a tone for
69
- * a button or a menu item — and then fired on the first click. `unpublish` is
70
- * declared `destructive`, so a verb reachable from a row menu without this
71
- * would have been a one-click unpublish with a red label explaining what had
72
- * already happened.
73
- *
74
- * The state holds the confirmation itself rather than the descriptor, so the
75
- * dialog cannot open for a verb that never asked for one — the same shape
76
- * `EntityForm` uses, and for the same reason.
77
- *
78
- * It carries the **target** too, which the form's does not need: a form has
79
- * one record and a table has a row or a selection, and those run through two
80
- * different handlers with two different payloads.
81
- */ const [pending, setPending] = useState(undefined);
82
51
  const { columns, visibleColumns, hidden, setPersonalization } = useEntityTableColumns(entityConstructor, slots.columns, items[0], `entity-table:${(_ref = preferencesKey != null ? preferencesKey : metaEntity.key) != null ? _ref : metaEntity.name}`);
83
- const pivot = PIVOT_CLASS[pivotBreakpoint];
84
52
  // A picker's table is choosing *one* value; a multi-selection there would
85
53
  // offer a set to a form member that holds a single reference, and the two
86
54
  // controls would fight over the same row. This is a wiring mistake rather
@@ -116,28 +84,90 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
116
84
  total: totalItems,
117
85
  excluded: new Set()
118
86
  };
119
- const hasRowAction = onSelect !== undefined || hrefFor !== undefined || hasRowMenu;
87
+ // Opening a record is its title's link, so a row needs an actions column
88
+ // only to pick it or to run a verb on it.
89
+ const hasRowAction = onSelect !== undefined || hasRowMenu;
120
90
  const columnCount = visibleColumns.length + (hasRowAction ? 1 : 0) + (selectable ? 1 : 0);
121
91
  /**
92
+ * The grid and the cards are both rendered, and a container query on the
93
+ * table's own box picks one — at the width its visible columns need. A
94
+ * viewport breakpoint was wrong inside a split view, a drawer or a wizard
95
+ * step, and a JS measurement would guess during SSR and correct after mount.
96
+ */ const pivot = pivotClasses(pivotWidth(visibleColumns, (selectable ? SELECTION_WIDTH : 0) + (hasRowAction ? ACTIONS_WIDTH : 0), pivotBreakpoint));
97
+ /**
122
98
  * The first load has nothing to show and is held with a skeleton; a refetch
123
99
  * already has rows, so it keeps them and only marks the region busy. Splitting
124
100
  * the two is what stops every pagination click flashing grey.
125
101
  */ const isFirstLoad = isLoading && items.length === 0;
126
- const isRefetching = isLoading && items.length > 0;
127
102
  /** `true`/omitted → the built-in default; a node → that node; `false` → none. */ const customSkeleton = typeof skeleton === 'boolean' ? undefined : skeleton;
128
103
  const showSkeleton = isFirstLoad && skeleton !== false;
129
104
  const skeletonRows = Array.from({
130
105
  length: Math.min(pageSize, SKELETON_ROW_CAP)
131
106
  }, (_, index)=>index);
132
107
  /**
133
- * The refetch hint, and it is deliberately the only one: rows stay readable
134
- * and simply dim, because a second skeleton over live data would be two
135
- * loading signals in one region.
136
- */ const busyClass = isRefetching ? 'opacity-60 transition-opacity duration-200 ease-smooth' : '';
137
- const renderCell = (column, item)=>column.render ? column.render(item) : /*#__PURE__*/ _jsx(CellValue, {
108
+ * A refetch keeps its rows at full contrast and marks them `aria-busy`:
109
+ * dimming them through opacity took the text under the contrast a reader
110
+ * needs, on every page change.
111
+ */ const busy = isLoading || undefined;
112
+ /** The column a row reads *as*: the first non-identifier one it filled in. */ const titleColumn = (item)=>visibleColumns.find((column)=>{
113
+ if (column.type === 'id') return false;
114
+ const value = item[column.name];
115
+ return value != null && String(value) !== '';
116
+ });
117
+ /** The column that links to the record: one declared `card: 'title'`, else the row's title. */ const declaredTitle = visibleColumns.find((column)=>column.card === 'title');
118
+ const linkColumn = (item)=>declaredTitle != null ? declaredTitle : titleColumn(item);
119
+ /**
120
+ * What a record's card shows, by each member's declared `card` role or the
121
+ * default: an id is hidden, the first enum is the badge, and up to
122
+ * {@link UNDECLARED_META_CAP} more members are meta — a card is a summary,
123
+ * and the grid holds the rest.
124
+ */ const firstEnum = visibleColumns.find((column)=>column.card === undefined && column.type === 'enum');
125
+ const roleOf = (column)=>{
126
+ var _column_card;
127
+ return (_column_card = column.card) != null ? _column_card : column.type === 'id' ? 'hidden' : column === firstEnum ? 'badge' : 'meta';
128
+ };
129
+ const cardParts = (item)=>{
130
+ const title = linkColumn(item);
131
+ const rest = visibleColumns.filter((column)=>column !== title);
132
+ let undeclared = 0;
133
+ return {
134
+ title,
135
+ subtitle: rest.find((column)=>roleOf(column) === 'subtitle'),
136
+ badges: rest.filter((column)=>roleOf(column) === 'badge'),
137
+ meta: rest.filter((column)=>{
138
+ if (roleOf(column) !== 'meta') return false;
139
+ if (column.card !== undefined) return true;
140
+ undeclared += 1;
141
+ return undeclared <= UNDECLARED_META_CAP;
142
+ })
143
+ };
144
+ };
145
+ const renderValue = (column, item)=>column.render ? column.render(item) : /*#__PURE__*/ _jsx(CellValue, {
138
146
  value: item[column.name],
139
- descriptor: column
147
+ descriptor: column,
148
+ record: item
149
+ });
150
+ /**
151
+ * A cell, and the row's title cell is the record's link
152
+ * ([ADR 0026](../../../../../../../docs/adr/0026-actions-hierarchy-overflow-and-destructive-verbs.md)).
153
+ * A column of identical "Open" links named nothing, and a reader tabbing
154
+ * down it heard "Open" once per row; the title says which record it opens.
155
+ * A picker's rows are chosen, not opened, so they stay plain.
156
+ */ const renderCell = (column, item)=>{
157
+ var _linkColumn;
158
+ const value = renderValue(column, item);
159
+ if (hrefFor === undefined || onSelect !== undefined) return value;
160
+ if (((_linkColumn = linkColumn(item)) == null ? void 0 : _linkColumn.name) !== column.name) return value;
161
+ return renderLink({
162
+ href: hrefFor(item.id),
163
+ className: linkClassName,
164
+ children: value,
165
+ intent: {
166
+ kind: 'open',
167
+ id: item.id
168
+ }
140
169
  });
170
+ };
141
171
  /**
142
172
  * The row a shift-click ranges *from* — the last box the user actually
143
173
  * toggled. Held in a ref rather than state because it changes nothing on
@@ -219,11 +249,7 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
219
249
  //
220
250
  // The id remains the last resort, because a row with nothing rendered
221
251
  // still has to announce itself.
222
- const named = visibleColumns.find((column)=>{
223
- if (column.type === 'id') return false;
224
- const value = item[column.name];
225
- return value != null && String(value) !== '';
226
- });
252
+ const named = titleColumn(item);
227
253
  return named ? String(item[named.name]) : String(item.id);
228
254
  };
229
255
  const selectionCell = (item, index, // Passed in rather than closed over: this is only ever called under
@@ -244,113 +270,196 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
244
270
  if (target.kind === 'row') onUseCase == null ? void 0 : onUseCase(key, target.item);
245
271
  else onBulkUseCase == null ? void 0 : onBulkUseCase(key, target.selection);
246
272
  };
273
+ /**
274
+ * Every verb on the table goes through here — the row menu, the bulk bar and
275
+ * the toolbar — so none reaches a destructive verb around its confirmation,
276
+ * its typed check or its Undo.
277
+ */ const verbs = useVerbInvoker({
278
+ run: runTarget,
279
+ busy: isBulkRunning,
280
+ served: metadata == null ? void 0 : metadata.useCases
281
+ });
247
282
  const invoke = (useCase, target)=>{
248
- const confirm = useCase.confirm;
249
- if (confirm) {
250
- setPending({
251
- key: useCase.key,
252
- labelKey: useCase.labelKey,
253
- confirm,
254
- target
283
+ if (target.kind === 'row') {
284
+ verbs.invoke({
285
+ descriptor: useCase,
286
+ target,
287
+ object: rowLabel(target.item),
288
+ count: 1
255
289
  });
256
290
  return;
257
291
  }
258
- runTarget(useCase.key, target);
292
+ const count = selectionSize(target.selection);
293
+ verbs.invoke({
294
+ descriptor: useCase,
295
+ target,
296
+ object: t('confirm.selection', {
297
+ count,
298
+ label: entityNoun(metaEntity),
299
+ plural: entityNoun(metaEntity, 'plural')
300
+ }),
301
+ count,
302
+ matching: target.selection.mode === 'matching'
303
+ });
259
304
  };
260
- const rowMenu = (item)=>hasRowMenu ? /*#__PURE__*/ _jsxs(Menu, {
261
- children: [
262
- /*#__PURE__*/ _jsx(Menu.Trigger, {
263
- "aria-label": t('table.actions'),
264
- children: OVERFLOW_GLYPH
265
- }),
266
- /*#__PURE__*/ _jsx(Menu.Items, {
267
- children: rowUseCases.map((useCase)=>{
268
- var _useCase_confirm;
269
- return /*#__PURE__*/ _jsx(Menu.Item, {
270
- tone: ((_useCase_confirm = useCase.confirm) == null ? void 0 : _useCase_confirm.tone) === 'destructive' ? 'destructive' : 'neutral',
271
- onClick: ()=>invoke(useCase, {
272
- kind: 'row',
273
- item
274
- }),
275
- children: translateKey(useCase.labelKey)
276
- }, useCase.key);
277
- })
278
- })
279
- ]
305
+ const rowMenu = (item)=>hasRowMenu ? /*#__PURE__*/ _jsx(ActionBar, {
306
+ surface: "row-menu",
307
+ menuLabel: t('actions.forRecord', {
308
+ record: rowLabel(item)
309
+ }),
310
+ items: itemsForUseCases(rowUseCases, translateKey, (useCase)=>invoke(useCase, {
311
+ kind: 'row',
312
+ item
313
+ }))
280
314
  }) : undefined;
281
315
  /**
282
- * Selection wins over navigation: a picker's row must set the value, not send
283
- * the user away from the form they came from.
284
- *
285
- * The row menu sits *beside* whichever of the two applies rather than
286
- * replacing it — "open this record" and "run a verb on it" are both true at
287
- * once, and folding the first into the menu would bury the action every row
288
- * of a list exists for.
316
+ * A picker's Select, then the row's verbs. Opening the record is not here:
317
+ * it is the title's link.
289
318
  */ const recordAction = (item)=>{
290
- const primary = onSelect ? /*#__PURE__*/ _jsx(Button, {
319
+ const pick = onSelect ? /*#__PURE__*/ _jsx(Button, {
291
320
  type: "button",
292
321
  variant: "secondary",
293
322
  size: "sm",
294
323
  onClick: ()=>onSelect(item),
295
324
  children: t('table.select')
296
- }) : hrefFor ? renderLink({
297
- href: hrefFor(item.id),
298
- className: linkClassName,
299
- children: t('table.open'),
300
- intent: {
301
- kind: 'open',
302
- id: item.id
303
- }
304
325
  }) : undefined;
305
326
  const menu = rowMenu(item);
306
- if (!menu) return primary;
327
+ if (!menu) return pick;
307
328
  return /*#__PURE__*/ _jsxs("span", {
308
329
  className: "flex items-center gap-2xs",
309
330
  children: [
310
- primary,
331
+ pick,
311
332
  menu
312
333
  ]
313
334
  });
314
335
  };
315
336
  /**
316
- * "No records" is a statement about the data; after a failed load it would be
317
- * a lie about it. The distinction matters most to the user who is deciding
318
- * whether their catalog is empty or their backend is down.
319
- */ const emptyMessage = error ? t('table.error') : t('table.empty');
337
+ * "New" is the list's primary, and only where something can be created
338
+ * here: the entity is not one only a flow writes (`creatable: false`), and
339
+ * the caller may write it. A list that offered "New" to a reader who could
340
+ * never save opened a form with no Save on it.
341
+ */ const mayCreate = newHref !== undefined && metaEntity.creatable && (metadata === undefined || metadata.actions.includes('write'));
342
+ const toolbarItems = itemsForUseCases(toolbarUseCases, translateKey, (useCase)=>invoke(useCase, {
343
+ kind: 'selection',
344
+ selection: everythingMatching
345
+ }), isBulkRunning);
346
+ const declaresToolbarPrimary = toolbarItems.some((item)=>item.emphasis === 'primary');
347
+ const toolbarActions = [
348
+ ...mayCreate ? [
349
+ {
350
+ key: 'new',
351
+ label: t('table.new'),
352
+ emphasis: declaresToolbarPrimary ? 'default' : 'primary',
353
+ href: newHref,
354
+ intent: {
355
+ kind: 'new'
356
+ }
357
+ }
358
+ ] : [],
359
+ ...toolbarItems
360
+ ];
361
+ const locale = useLocale();
362
+ const panelId = useId();
363
+ const keys = sortKeys(sorting, columns);
364
+ const activeFilters = (_ref1 = filtering == null ? void 0 : filtering.values.length) != null ? _ref1 : 0;
365
+ const results = t('table.results', {
366
+ count: totalItems
367
+ });
368
+ /**
369
+ * What the status region says once a filter, a sort or a page has settled —
370
+ * debounced, and silent on the first load.
371
+ */ const announcement = useResultAnnouncement(!isLoading, totalItems === 0 && activeFilters > 0 ? t('table.noResultsFiltered') : results, JSON.stringify([
372
+ filtering,
373
+ sorting,
374
+ currentPage,
375
+ pageSize
376
+ ]));
377
+ /** The caption: what the table holds, how many, and in what order. */ const primaryKey = keys[0];
378
+ const primaryColumn = primaryKey === undefined ? undefined : columns.find((column)=>column.name === primaryKey.member);
379
+ const caption = primaryKey === undefined || primaryColumn === undefined ? t('table.caption', {
380
+ entity: entityNoun(metaEntity, 'plural'),
381
+ results
382
+ }) : t('table.captionSorted', {
383
+ entity: entityNoun(metaEntity, 'plural'),
384
+ results,
385
+ column: primaryColumn.label,
386
+ direction: t(primaryKey.type === 'asc' ? 'sort.ascending' : 'sort.descending')
387
+ });
388
+ /**
389
+ * A column's header: its name, and — for a sortable one — a button that
390
+ * cycles it ascending → descending → unsorted, with Shift adding it as the
391
+ * next key. Only the primary key carries `aria-sort`.
392
+ */ const headerCell = (column)=>{
393
+ var _column_header;
394
+ var _keys_position;
395
+ const label = (_column_header = column.header) != null ? _column_header : column.label;
396
+ if (!column.sortable || onSortingChange === undefined) return /*#__PURE__*/ _jsx(TableHeaderCell, {
397
+ children: label
398
+ }, column.name);
399
+ const position = keys.findIndex((key)=>key.member === column.name);
400
+ const type = (_keys_position = keys[position]) == null ? void 0 : _keys_position.type;
401
+ return /*#__PURE__*/ _jsx(TableHeaderCell, {
402
+ "aria-sort": position === 0 ? type === 'asc' ? 'ascending' : 'descending' : undefined,
403
+ children: /*#__PURE__*/ _jsxs("button", {
404
+ type: "button",
405
+ className: "inline-flex min-h-(--target-min) items-center gap-3xs rounded-sm focus-ring hover:text-content",
406
+ onClick: (event)=>onSortingChange(nextHeaderSorting(keys, {
407
+ member: column.name,
408
+ property: queryPropertyFor(column, locale)
409
+ }, event.shiftKey)),
410
+ children: [
411
+ label,
412
+ /*#__PURE__*/ _jsx("span", {
413
+ "aria-hidden": "true",
414
+ children: type === 'asc' ? '▲' : type === 'desc' ? '▼' : '↕'
415
+ }),
416
+ keys.length > 1 && position >= 0 && /*#__PURE__*/ _jsx("span", {
417
+ "aria-hidden": "true",
418
+ className: "text-step-sm",
419
+ children: position + 1
420
+ })
421
+ ]
422
+ })
423
+ }, column.name);
424
+ };
425
+ /** A panel toggle: its state said by `aria-expanded`, and its count shown. */ const panelToggle = (which, count)=>/*#__PURE__*/ _jsxs(Button, {
426
+ type: "button",
427
+ variant: panel === which ? 'primary' : 'secondary',
428
+ size: "sm",
429
+ "aria-expanded": panel === which,
430
+ "aria-controls": panelId,
431
+ onClick: ()=>setPanel((current)=>current === which ? 'none' : which),
432
+ children: [
433
+ t(which === 'filters' ? 'table.filters' : 'table.sorting'),
434
+ count > 0 && // Its name stays "Filters": the chips say which filters, and a count
435
+ // in the name would change it under the reader with every filter.
436
+ /*#__PURE__*/ _jsx("span", {
437
+ "aria-hidden": "true",
438
+ className: "ms-3xs rounded-full bg-surface px-3xs text-step-sm text-content",
439
+ children: count
440
+ })
441
+ ]
442
+ });
320
443
  return /*#__PURE__*/ _jsxs("div", {
321
- className: "flex flex-col gap-s",
444
+ className: "@container/entity-table flex flex-col gap-s",
322
445
  children: [
323
446
  /*#__PURE__*/ _jsx("span", {
324
447
  role: "status",
325
448
  "aria-live": "polite",
326
449
  className: "sr-only",
327
- children: isFirstLoad ? t('table.loading') : ''
450
+ children: isFirstLoad ? t('table.loading') : announcement
328
451
  }),
329
452
  showControls && /*#__PURE__*/ _jsx(TableToolbar, {
330
453
  start: /*#__PURE__*/ _jsxs(_Fragment, {
331
454
  children: [
332
- newHref && renderLink({
333
- href: newHref,
334
- className: linkClassName,
335
- children: t('table.new'),
336
- intent: {
337
- kind: 'new'
338
- }
339
- }),
340
455
  /*#__PURE__*/ _jsx(LoadingBoundary, {
341
456
  isLoading: isMetadataLoading,
342
457
  lines: 0,
343
458
  children: /*#__PURE__*/ _jsx(_Fragment, {
344
- children: toolbarUseCases.map((useCase)=>{
345
- var _useCase_confirm;
346
- return /*#__PURE__*/ _jsx(Button, {
347
- type: "button",
348
- variant: ((_useCase_confirm = useCase.confirm) == null ? void 0 : _useCase_confirm.tone) === 'destructive' ? 'destructive' : 'secondary',
349
- size: "sm",
350
- disabled: isBulkRunning,
351
- onClick: ()=>onBulkUseCase == null ? void 0 : onBulkUseCase(useCase.key, everythingMatching),
352
- children: translateKey(useCase.labelKey)
353
- }, useCase.key);
459
+ children: toolbarActions.length > 0 && /*#__PURE__*/ _jsx(ActionBar, {
460
+ surface: "table-toolbar",
461
+ items: toolbarActions,
462
+ renderLink: renderLink
354
463
  })
355
464
  })
356
465
  }),
@@ -359,20 +468,8 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
359
468
  }),
360
469
  end: /*#__PURE__*/ _jsxs(_Fragment, {
361
470
  children: [
362
- /*#__PURE__*/ _jsx(Button, {
363
- type: "button",
364
- variant: panel === 'filters' ? 'primary' : 'secondary',
365
- size: "sm",
366
- onClick: ()=>setPanel((current)=>current === 'filters' ? 'none' : 'filters'),
367
- children: t('table.filters')
368
- }),
369
- /*#__PURE__*/ _jsx(Button, {
370
- type: "button",
371
- variant: panel === 'sorting' ? 'primary' : 'secondary',
372
- size: "sm",
373
- onClick: ()=>setPanel((current)=>current === 'sorting' ? 'none' : 'sorting'),
374
- children: t('table.sorting')
375
- }),
471
+ panelToggle('filters', activeFilters),
472
+ panelToggle('sorting', keys.length),
376
473
  /*#__PURE__*/ _jsx(ColumnSettings, {
377
474
  columns: columns,
378
475
  hidden: hidden,
@@ -380,16 +477,23 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
380
477
  })
381
478
  ]
382
479
  }),
480
+ panelId: panelId,
383
481
  panel: panel === 'filters' ? /*#__PURE__*/ _jsx(FilterBuilder, {
384
482
  descriptors: columns.filter((column)=>column.filterable),
483
+ facets: facets,
385
484
  value: filtering,
386
485
  onChange: (applied)=>onFilteringChange == null ? void 0 : onFilteringChange(applied)
387
- }) : panel === 'sorting' ? /*#__PURE__*/ _jsx(SortBuilder, {
486
+ }, JSON.stringify(filtering != null ? filtering : null)) : panel === 'sorting' ? /*#__PURE__*/ _jsx(SortBuilder, {
388
487
  descriptors: columns.filter((column)=>column.sortable),
389
488
  value: sorting,
390
489
  onChange: (applied)=>onSortingChange == null ? void 0 : onSortingChange(applied)
391
490
  }) : undefined
392
491
  }),
492
+ showControls && onFilteringChange !== undefined && /*#__PURE__*/ _jsx(FilterChips, {
493
+ descriptors: columns.filter((column)=>column.filterable),
494
+ value: filtering,
495
+ onChange: onFilteringChange
496
+ }),
393
497
  selectionState && selectionSize(selectionState) > 0 && /*#__PURE__*/ _jsx(BulkActionBar, {
394
498
  count: selectionSize(selectionState),
395
499
  useCases: bulkUseCases,
@@ -404,19 +508,7 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
404
508
  selection: selectionState
405
509
  })
406
510
  }),
407
- pending && /*#__PURE__*/ _jsx(ConfirmDialog, {
408
- open: true,
409
- tone: pending.confirm.tone,
410
- title: translateKey(pending.labelKey),
411
- message: translateKey(pending.confirm.messageKey),
412
- busy: isBulkRunning,
413
- onCancel: ()=>setPending(undefined),
414
- onConfirm: ()=>{
415
- const { key, target } = pending;
416
- setPending(undefined);
417
- runTarget(key, target);
418
- }
419
- }),
511
+ verbs.dialog,
420
512
  bulkOutcomes && bulkOutcomes.length > 0 && onBulkDismiss && /*#__PURE__*/ _jsx(BulkResult, {
421
513
  outcomes: bulkOutcomes,
422
514
  busy: isBulkRunning,
@@ -427,15 +519,37 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
427
519
  onRetryFailed: onBulkRetry,
428
520
  onDismiss: onBulkDismiss
429
521
  }),
430
- error && /*#__PURE__*/ _jsx("p", {
431
- role: "alert",
432
- "data-testid": "entity-table-error",
433
- className: "rounded-sm border border-danger bg-danger-subtle px-s py-2xs text-step-sm text-danger",
434
- children: errorMessage(error)
522
+ /*#__PURE__*/ _jsx(RegionState, {
523
+ plural: entityNoun(metaEntity, 'plural'),
524
+ isLoading: isLoading,
525
+ error: error,
526
+ onRetry: onRetry,
527
+ hasStaleData: items.length > 0,
528
+ isEmpty: items.length === 0,
529
+ isFiltered: activeFilters > 0,
530
+ onClearFilters: onFilteringChange === undefined ? undefined : ()=>onFilteringChange({
531
+ // Only offered under a filter, so there is one to keep the
532
+ // logic of.
533
+ operator: filtering.operator,
534
+ values: []
535
+ }),
536
+ emptyAction: mayCreate ? renderLink({
537
+ href: newHref,
538
+ className: button({
539
+ variant: 'primary'
540
+ }),
541
+ children: t('table.new'),
542
+ intent: {
543
+ kind: 'new'
544
+ }
545
+ }) : undefined
435
546
  }),
436
547
  /*#__PURE__*/ _jsx("div", {
437
- className: `${pivot.grid} ${busyClass}`,
548
+ className: pivot.grid,
549
+ "aria-busy": busy,
438
550
  children: /*#__PURE__*/ _jsxs(Table, {
551
+ caption: caption,
552
+ containerClassName: "max-h-(--table-max-block) scroll-pt-12",
439
553
  children: [
440
554
  /*#__PURE__*/ _jsx(TableHead, {
441
555
  children: slots.header ? slots.header.render(visibleColumns) : /*#__PURE__*/ _jsxs("tr", {
@@ -449,12 +563,7 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
449
563
  onChange: (event)=>toggleAllOnPage(event.currentTarget.checked, selectionState)
450
564
  })
451
565
  }),
452
- visibleColumns.map((column)=>{
453
- var _column_header;
454
- return /*#__PURE__*/ _jsx(TableHeaderCell, {
455
- children: (_column_header = column.header) != null ? _column_header : column.label
456
- }, column.name);
457
- }),
566
+ visibleColumns.map(headerCell),
458
567
  hasRowAction && /*#__PURE__*/ _jsx(TableHeaderCell, {
459
568
  children: t('table.actions')
460
569
  })
@@ -462,7 +571,6 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
462
571
  })
463
572
  }),
464
573
  /*#__PURE__*/ _jsxs(TableBody, {
465
- "aria-busy": isLoading || undefined,
466
574
  children: [
467
575
  showSkeleton && (customSkeleton ? /*#__PURE__*/ _jsx(TableMessageRow, {
468
576
  colSpan: columnCount,
@@ -489,10 +597,6 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
489
597
  })
490
598
  ]
491
599
  }, row))),
492
- !isLoading && items.length === 0 && /*#__PURE__*/ _jsx(TableMessageRow, {
493
- colSpan: columnCount,
494
- children: emptyMessage
495
- }),
496
600
  shown.map(({ item, depth, hasChildren }, index)=>{
497
601
  var _item_id, _item_id1;
498
602
  return slots.row ? // A Fragment carries the key without wrapping the custom row in
@@ -528,30 +632,62 @@ export function EntityTable({ entityConstructor, isLoading, skeleton = true, err
528
632
  })
529
633
  }),
530
634
  /*#__PURE__*/ _jsxs("div", {
531
- className: `${pivot.cards} flex flex-col gap-2xs ${busyClass}`,
532
- "aria-busy": isLoading || undefined,
635
+ className: pivot.cards,
636
+ "aria-busy": busy,
533
637
  children: [
534
- showSkeleton && (customSkeleton != null ? customSkeleton : skeletonRows.map((row)=>/*#__PURE__*/ _jsx(EntityRecordCard, {
535
- columns: visibleColumns,
536
- renderCell: ()=>/*#__PURE__*/ _jsx(Skeleton, {
537
- shape: "line",
538
- className: "w-24"
638
+ showSkeleton && (customSkeleton != null ? customSkeleton : /*#__PURE__*/ _jsx("ul", {
639
+ role: "list",
640
+ className: "m-0 p-0 flex list-none flex-col gap-2xs",
641
+ children: skeletonRows.map((row)=>/*#__PURE__*/ _jsx("li", {
642
+ children: /*#__PURE__*/ _jsx(EntityRecordCard, {
643
+ title: /*#__PURE__*/ _jsx(Skeleton, {
644
+ shape: "line",
645
+ className: "w-32"
646
+ }),
647
+ meta: visibleColumns.slice(1).map((column)=>({
648
+ key: column.name,
649
+ label: column.label,
650
+ value: /*#__PURE__*/ _jsx(Skeleton, {
651
+ shape: "line",
652
+ className: "w-24"
653
+ })
654
+ }))
539
655
  })
540
- }, row))),
541
- !isLoading && items.length === 0 && /*#__PURE__*/ _jsx("p", {
542
- className: "text-step-sm text-content-muted",
543
- children: emptyMessage
544
- }),
545
- shown.map(({ item }, index)=>{
546
- var _item_id;
547
- return /*#__PURE__*/ _jsx(EntityRecordCard, {
548
- columns: visibleColumns,
549
- // The card is handed the resolved columns themselves, so the
550
- // narrow layout goes through the exact same renderers as the grid.
551
- renderCell: (column)=>renderCell(column, item),
552
- leading: selectionState ? selectionCell(item, index, selectionState) : undefined,
553
- actions: recordAction(item)
554
- }, String((_item_id = item.id) != null ? _item_id : index));
656
+ }, row))
657
+ })),
658
+ shown.length > 0 && /*#__PURE__*/ _jsx("ul", {
659
+ role: "list",
660
+ className: "m-0 p-0 flex list-none flex-col gap-2xs",
661
+ children: shown.map(({ item, depth }, index)=>{
662
+ var _item_id;
663
+ const parts = cardParts(item);
664
+ return /*#__PURE__*/ _jsx("li", {
665
+ // A tree's card says how deep it sits, as its row does.
666
+ "aria-level": treeKeys === undefined ? undefined : depth + 1,
667
+ style: treeKeys === undefined ? undefined : {
668
+ marginInlineStart: `${depth * 1.5}rem`
669
+ },
670
+ children: /*#__PURE__*/ _jsx(EntityRecordCard, {
671
+ // The same renderers as the grid, so the two layouts agree.
672
+ title: parts.title === undefined ? rowLabel(item) : renderCell(parts.title, item),
673
+ subtitle: parts.subtitle === undefined ? undefined : renderCell(parts.subtitle, item),
674
+ badges: parts.badges.map((column)=>({
675
+ key: column.name,
676
+ value: renderCell(column, item)
677
+ })),
678
+ meta: parts.meta.map((column)=>{
679
+ var _column_header;
680
+ return {
681
+ key: column.name,
682
+ label: (_column_header = column.header) != null ? _column_header : column.label,
683
+ value: renderCell(column, item)
684
+ };
685
+ }),
686
+ leading: selectionState ? selectionCell(item, index, selectionState) : undefined,
687
+ actions: recordAction(item)
688
+ })
689
+ }, String((_item_id = item.id) != null ? _item_id : index));
690
+ })
555
691
  })
556
692
  ]
557
693
  }),