@entifix/react-controls 0.1.0-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 (471) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -0
  3. package/dist/i18n/catalog/en.d.ts +10 -0
  4. package/dist/i18n/catalog/en.d.ts.map +1 -0
  5. package/dist/i18n/catalog/en.js +211 -0
  6. package/dist/i18n/catalog/en.js.map +1 -0
  7. package/dist/i18n/catalog/es.d.ts +275 -0
  8. package/dist/i18n/catalog/es.d.ts.map +1 -0
  9. package/dist/i18n/catalog/es.js +261 -0
  10. package/dist/i18n/catalog/es.js.map +1 -0
  11. package/dist/i18n/catalog/index.d.ts +403 -0
  12. package/dist/i18n/catalog/index.d.ts.map +1 -0
  13. package/dist/i18n/catalog/index.js +23 -0
  14. package/dist/i18n/catalog/index.js.map +1 -0
  15. package/dist/i18n/entity-labels.d.ts +29 -0
  16. package/dist/i18n/entity-labels.d.ts.map +1 -0
  17. package/dist/i18n/entity-labels.js +49 -0
  18. package/dist/i18n/entity-labels.js.map +1 -0
  19. package/dist/i18n/fallback-catalogs.d.ts +5 -0
  20. package/dist/i18n/fallback-catalogs.d.ts.map +1 -0
  21. package/dist/i18n/fallback-catalogs.js +34 -0
  22. package/dist/i18n/fallback-catalogs.js.map +1 -0
  23. package/dist/i18n/i18n-context.d.ts +62 -0
  24. package/dist/i18n/i18n-context.d.ts.map +1 -0
  25. package/dist/i18n/i18n-context.js +128 -0
  26. package/dist/i18n/i18n-context.js.map +1 -0
  27. package/dist/i18n/index.d.ts +5 -0
  28. package/dist/i18n/index.d.ts.map +1 -0
  29. package/dist/i18n/index.js +6 -0
  30. package/dist/i18n/index.js.map +1 -0
  31. package/dist/i18n/spec-support/catalogs.d.ts +2 -0
  32. package/dist/i18n/spec-support/catalogs.d.ts.map +1 -0
  33. package/dist/i18n/spec-support/catalogs.js +142 -0
  34. package/dist/i18n/spec-support/catalogs.js.map +1 -0
  35. package/dist/i18next/index.d.ts +20 -0
  36. package/dist/i18next/index.d.ts.map +1 -0
  37. package/dist/i18next/index.js +60 -0
  38. package/dist/i18next/index.js.map +1 -0
  39. package/dist/index.d.ts +46 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +47 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/preferences/index.d.ts +7 -0
  44. package/dist/preferences/index.d.ts.map +1 -0
  45. package/dist/preferences/index.js +8 -0
  46. package/dist/preferences/index.js.map +1 -0
  47. package/dist/preferences/indexeddb-ui-preferences-state.d.ts +16 -0
  48. package/dist/preferences/indexeddb-ui-preferences-state.d.ts.map +1 -0
  49. package/dist/preferences/indexeddb-ui-preferences-state.js +50 -0
  50. package/dist/preferences/indexeddb-ui-preferences-state.js.map +1 -0
  51. package/dist/preferences/local-storage-ui-preferences-state.d.ts +16 -0
  52. package/dist/preferences/local-storage-ui-preferences-state.d.ts.map +1 -0
  53. package/dist/preferences/local-storage-ui-preferences-state.js +51 -0
  54. package/dist/preferences/local-storage-ui-preferences-state.js.map +1 -0
  55. package/dist/preferences/ui-preferences-context.d.ts +16 -0
  56. package/dist/preferences/ui-preferences-context.d.ts.map +1 -0
  57. package/dist/preferences/ui-preferences-context.js +31 -0
  58. package/dist/preferences/ui-preferences-context.js.map +1 -0
  59. package/dist/preferences/ui-preferences-state.d.ts +23 -0
  60. package/dist/preferences/ui-preferences-state.d.ts.map +1 -0
  61. package/dist/preferences/ui-preferences-state.js +5 -0
  62. package/dist/preferences/ui-preferences-state.js.map +1 -0
  63. package/dist/preferences/use-ui-preference.d.ts +20 -0
  64. package/dist/preferences/use-ui-preference.d.ts.map +1 -0
  65. package/dist/preferences/use-ui-preference.js +72 -0
  66. package/dist/preferences/use-ui-preference.js.map +1 -0
  67. package/dist/preferences/use-viewport-mode.d.ts +33 -0
  68. package/dist/preferences/use-viewport-mode.d.ts.map +1 -0
  69. package/dist/preferences/use-viewport-mode.js +53 -0
  70. package/dist/preferences/use-viewport-mode.js.map +1 -0
  71. package/dist/primitives.d.ts +25 -0
  72. package/dist/primitives.d.ts.map +1 -0
  73. package/dist/primitives.js +54 -0
  74. package/dist/primitives.js.map +1 -0
  75. package/dist/theme/index.d.ts +3 -0
  76. package/dist/theme/index.d.ts.map +1 -0
  77. package/dist/theme/index.js +4 -0
  78. package/dist/theme/index.js.map +1 -0
  79. package/dist/theme/theme-context.d.ts +26 -0
  80. package/dist/theme/theme-context.d.ts.map +1 -0
  81. package/dist/theme/theme-context.js +79 -0
  82. package/dist/theme/theme-context.js.map +1 -0
  83. package/dist/theme/types.d.ts +22 -0
  84. package/dist/theme/types.d.ts.map +1 -0
  85. package/dist/theme/types.js +6 -0
  86. package/dist/theme/types.js.map +1 -0
  87. package/dist/ui/actions/action-surfaces.d.ts +59 -0
  88. package/dist/ui/actions/action-surfaces.d.ts.map +1 -0
  89. package/dist/ui/actions/action-surfaces.js +109 -0
  90. package/dist/ui/actions/action-surfaces.js.map +1 -0
  91. package/dist/ui/actions/index.d.ts +2 -0
  92. package/dist/ui/actions/index.d.ts.map +1 -0
  93. package/dist/ui/actions/index.js +3 -0
  94. package/dist/ui/actions/index.js.map +1 -0
  95. package/dist/ui/atoms/button/button-link.d.ts +27 -0
  96. package/dist/ui/atoms/button/button-link.d.ts.map +1 -0
  97. package/dist/ui/atoms/button/button-link.js +23 -0
  98. package/dist/ui/atoms/button/button-link.js.map +1 -0
  99. package/dist/ui/atoms/button/button-recipe.d.ts +19 -0
  100. package/dist/ui/atoms/button/button-recipe.d.ts.map +1 -0
  101. package/dist/ui/atoms/button/button-recipe.js +42 -0
  102. package/dist/ui/atoms/button/button-recipe.js.map +1 -0
  103. package/dist/ui/atoms/button/button.d.ts +7 -0
  104. package/dist/ui/atoms/button/button.d.ts.map +1 -0
  105. package/dist/ui/atoms/button/button.js +22 -0
  106. package/dist/ui/atoms/button/button.js.map +1 -0
  107. package/dist/ui/atoms/button/index.d.ts +4 -0
  108. package/dist/ui/atoms/button/index.d.ts.map +1 -0
  109. package/dist/ui/atoms/button/index.js +5 -0
  110. package/dist/ui/atoms/button/index.js.map +1 -0
  111. package/dist/ui/atoms/cell-value/cell-value.d.ts +12 -0
  112. package/dist/ui/atoms/cell-value/cell-value.d.ts.map +1 -0
  113. package/dist/ui/atoms/cell-value/cell-value.js +101 -0
  114. package/dist/ui/atoms/cell-value/cell-value.js.map +1 -0
  115. package/dist/ui/atoms/cell-value/index.d.ts +2 -0
  116. package/dist/ui/atoms/cell-value/index.d.ts.map +1 -0
  117. package/dist/ui/atoms/cell-value/index.js +3 -0
  118. package/dist/ui/atoms/cell-value/index.js.map +1 -0
  119. package/dist/ui/atoms/field/checkbox.d.ts +35 -0
  120. package/dist/ui/atoms/field/checkbox.d.ts.map +1 -0
  121. package/dist/ui/atoms/field/checkbox.js +46 -0
  122. package/dist/ui/atoms/field/checkbox.js.map +1 -0
  123. package/dist/ui/atoms/field/field.d.ts +4 -0
  124. package/dist/ui/atoms/field/field.d.ts.map +1 -0
  125. package/dist/ui/atoms/field/field.js +29 -0
  126. package/dist/ui/atoms/field/field.js.map +1 -0
  127. package/dist/ui/atoms/field/index.d.ts +3 -0
  128. package/dist/ui/atoms/field/index.d.ts.map +1 -0
  129. package/dist/ui/atoms/field/index.js +4 -0
  130. package/dist/ui/atoms/field/index.js.map +1 -0
  131. package/dist/ui/atoms/field-control/field-control.d.ts +50 -0
  132. package/dist/ui/atoms/field-control/field-control.d.ts.map +1 -0
  133. package/dist/ui/atoms/field-control/field-control.js +82 -0
  134. package/dist/ui/atoms/field-control/field-control.js.map +1 -0
  135. package/dist/ui/atoms/field-control/index.d.ts +2 -0
  136. package/dist/ui/atoms/field-control/index.d.ts.map +1 -0
  137. package/dist/ui/atoms/field-control/index.js +3 -0
  138. package/dist/ui/atoms/field-control/index.js.map +1 -0
  139. package/dist/ui/atoms/skeleton/index.d.ts +2 -0
  140. package/dist/ui/atoms/skeleton/index.d.ts.map +1 -0
  141. package/dist/ui/atoms/skeleton/index.js +3 -0
  142. package/dist/ui/atoms/skeleton/index.js.map +1 -0
  143. package/dist/ui/atoms/skeleton/skeleton.d.ts +21 -0
  144. package/dist/ui/atoms/skeleton/skeleton.d.ts.map +1 -0
  145. package/dist/ui/atoms/skeleton/skeleton.js +33 -0
  146. package/dist/ui/atoms/skeleton/skeleton.js.map +1 -0
  147. package/dist/ui/atoms/table/index.d.ts +2 -0
  148. package/dist/ui/atoms/table/index.d.ts.map +1 -0
  149. package/dist/ui/atoms/table/index.js +3 -0
  150. package/dist/ui/atoms/table/index.js.map +1 -0
  151. package/dist/ui/atoms/table/table.d.ts +30 -0
  152. package/dist/ui/atoms/table/table.d.ts.map +1 -0
  153. package/dist/ui/atoms/table/table.js +84 -0
  154. package/dist/ui/atoms/table/table.js.map +1 -0
  155. package/dist/ui/atoms/text/index.d.ts +2 -0
  156. package/dist/ui/atoms/text/index.d.ts.map +1 -0
  157. package/dist/ui/atoms/text/index.js +3 -0
  158. package/dist/ui/atoms/text/index.js.map +1 -0
  159. package/dist/ui/atoms/text/text.d.ts +86 -0
  160. package/dist/ui/atoms/text/text.d.ts.map +1 -0
  161. package/dist/ui/atoms/text/text.js +221 -0
  162. package/dist/ui/atoms/text/text.js.map +1 -0
  163. package/dist/ui/layout/_demo.d.ts +6 -0
  164. package/dist/ui/layout/_demo.d.ts.map +1 -0
  165. package/dist/ui/layout/_demo.js +11 -0
  166. package/dist/ui/layout/_demo.js.map +1 -0
  167. package/dist/ui/layout/_shared.d.ts +9 -0
  168. package/dist/ui/layout/_shared.d.ts.map +1 -0
  169. package/dist/ui/layout/_shared.js +30 -0
  170. package/dist/ui/layout/_shared.js.map +1 -0
  171. package/dist/ui/layout/box/box.d.ts +10 -0
  172. package/dist/ui/layout/box/box.d.ts.map +1 -0
  173. package/dist/ui/layout/box/box.js +28 -0
  174. package/dist/ui/layout/box/box.js.map +1 -0
  175. package/dist/ui/layout/box/index.d.ts +2 -0
  176. package/dist/ui/layout/box/index.d.ts.map +1 -0
  177. package/dist/ui/layout/box/index.js +3 -0
  178. package/dist/ui/layout/box/index.js.map +1 -0
  179. package/dist/ui/layout/center/center.d.ts +13 -0
  180. package/dist/ui/layout/center/center.d.ts.map +1 -0
  181. package/dist/ui/layout/center/center.js +22 -0
  182. package/dist/ui/layout/center/center.js.map +1 -0
  183. package/dist/ui/layout/center/index.d.ts +2 -0
  184. package/dist/ui/layout/center/index.d.ts.map +1 -0
  185. package/dist/ui/layout/center/index.js +3 -0
  186. package/dist/ui/layout/center/index.js.map +1 -0
  187. package/dist/ui/layout/cluster/cluster.d.ts +11 -0
  188. package/dist/ui/layout/cluster/cluster.d.ts.map +1 -0
  189. package/dist/ui/layout/cluster/cluster.js +19 -0
  190. package/dist/ui/layout/cluster/cluster.js.map +1 -0
  191. package/dist/ui/layout/cluster/index.d.ts +2 -0
  192. package/dist/ui/layout/cluster/index.d.ts.map +1 -0
  193. package/dist/ui/layout/cluster/index.js +3 -0
  194. package/dist/ui/layout/cluster/index.js.map +1 -0
  195. package/dist/ui/layout/cover/cover.d.ts +26 -0
  196. package/dist/ui/layout/cover/cover.d.ts.map +1 -0
  197. package/dist/ui/layout/cover/cover.js +57 -0
  198. package/dist/ui/layout/cover/cover.js.map +1 -0
  199. package/dist/ui/layout/cover/index.d.ts +2 -0
  200. package/dist/ui/layout/cover/index.d.ts.map +1 -0
  201. package/dist/ui/layout/cover/index.js +3 -0
  202. package/dist/ui/layout/cover/index.js.map +1 -0
  203. package/dist/ui/layout/grid/grid.d.ts +14 -0
  204. package/dist/ui/layout/grid/grid.d.ts.map +1 -0
  205. package/dist/ui/layout/grid/grid.js +25 -0
  206. package/dist/ui/layout/grid/grid.js.map +1 -0
  207. package/dist/ui/layout/grid/index.d.ts +2 -0
  208. package/dist/ui/layout/grid/index.d.ts.map +1 -0
  209. package/dist/ui/layout/grid/index.js +3 -0
  210. package/dist/ui/layout/grid/index.js.map +1 -0
  211. package/dist/ui/layout/sidebar/index.d.ts +2 -0
  212. package/dist/ui/layout/sidebar/index.d.ts.map +1 -0
  213. package/dist/ui/layout/sidebar/index.js +3 -0
  214. package/dist/ui/layout/sidebar/index.js.map +1 -0
  215. package/dist/ui/layout/sidebar/sidebar.d.ts +33 -0
  216. package/dist/ui/layout/sidebar/sidebar.d.ts.map +1 -0
  217. package/dist/ui/layout/sidebar/sidebar.js +54 -0
  218. package/dist/ui/layout/sidebar/sidebar.js.map +1 -0
  219. package/dist/ui/layout/switcher/index.d.ts +2 -0
  220. package/dist/ui/layout/switcher/index.d.ts.map +1 -0
  221. package/dist/ui/layout/switcher/index.js +3 -0
  222. package/dist/ui/layout/switcher/index.js.map +1 -0
  223. package/dist/ui/layout/switcher/switcher.d.ts +15 -0
  224. package/dist/ui/layout/switcher/switcher.d.ts.map +1 -0
  225. package/dist/ui/layout/switcher/switcher.js +26 -0
  226. package/dist/ui/layout/switcher/switcher.js.map +1 -0
  227. package/dist/ui/molecules/breadcrumbs/breadcrumbs.d.ts +27 -0
  228. package/dist/ui/molecules/breadcrumbs/breadcrumbs.d.ts.map +1 -0
  229. package/dist/ui/molecules/breadcrumbs/breadcrumbs.js +50 -0
  230. package/dist/ui/molecules/breadcrumbs/breadcrumbs.js.map +1 -0
  231. package/dist/ui/molecules/breadcrumbs/index.d.ts +2 -0
  232. package/dist/ui/molecules/breadcrumbs/index.d.ts.map +1 -0
  233. package/dist/ui/molecules/breadcrumbs/index.js +3 -0
  234. package/dist/ui/molecules/breadcrumbs/index.js.map +1 -0
  235. package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.d.ts +47 -0
  236. package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.d.ts.map +1 -0
  237. package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.js +63 -0
  238. package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.js.map +1 -0
  239. package/dist/ui/molecules/bulk-action-bar/index.d.ts +2 -0
  240. package/dist/ui/molecules/bulk-action-bar/index.d.ts.map +1 -0
  241. package/dist/ui/molecules/bulk-action-bar/index.js +3 -0
  242. package/dist/ui/molecules/bulk-action-bar/index.js.map +1 -0
  243. package/dist/ui/molecules/bulk-result/bulk-result.d.ts +31 -0
  244. package/dist/ui/molecules/bulk-result/bulk-result.d.ts.map +1 -0
  245. package/dist/ui/molecules/bulk-result/bulk-result.js +86 -0
  246. package/dist/ui/molecules/bulk-result/bulk-result.js.map +1 -0
  247. package/dist/ui/molecules/bulk-result/index.d.ts +2 -0
  248. package/dist/ui/molecules/bulk-result/index.d.ts.map +1 -0
  249. package/dist/ui/molecules/bulk-result/index.js +3 -0
  250. package/dist/ui/molecules/bulk-result/index.js.map +1 -0
  251. package/dist/ui/molecules/card/card.d.ts +5 -0
  252. package/dist/ui/molecules/card/card.d.ts.map +1 -0
  253. package/dist/ui/molecules/card/card.js +14 -0
  254. package/dist/ui/molecules/card/card.js.map +1 -0
  255. package/dist/ui/molecules/card/index.d.ts +2 -0
  256. package/dist/ui/molecules/card/index.d.ts.map +1 -0
  257. package/dist/ui/molecules/card/index.js +3 -0
  258. package/dist/ui/molecules/card/index.js.map +1 -0
  259. package/dist/ui/molecules/column-settings/column-settings.d.ts +29 -0
  260. package/dist/ui/molecules/column-settings/column-settings.d.ts.map +1 -0
  261. package/dist/ui/molecules/column-settings/column-settings.js +117 -0
  262. package/dist/ui/molecules/column-settings/column-settings.js.map +1 -0
  263. package/dist/ui/molecules/column-settings/index.d.ts +2 -0
  264. package/dist/ui/molecules/column-settings/index.d.ts.map +1 -0
  265. package/dist/ui/molecules/column-settings/index.js +3 -0
  266. package/dist/ui/molecules/column-settings/index.js.map +1 -0
  267. package/dist/ui/molecules/confirm-dialog/confirm-dialog.d.ts +31 -0
  268. package/dist/ui/molecules/confirm-dialog/confirm-dialog.d.ts.map +1 -0
  269. package/dist/ui/molecules/confirm-dialog/confirm-dialog.js +68 -0
  270. package/dist/ui/molecules/confirm-dialog/confirm-dialog.js.map +1 -0
  271. package/dist/ui/molecules/confirm-dialog/index.d.ts +2 -0
  272. package/dist/ui/molecules/confirm-dialog/index.d.ts.map +1 -0
  273. package/dist/ui/molecules/confirm-dialog/index.js +3 -0
  274. package/dist/ui/molecules/confirm-dialog/index.js.map +1 -0
  275. package/dist/ui/molecules/drawer/drawer.d.ts +25 -0
  276. package/dist/ui/molecules/drawer/drawer.d.ts.map +1 -0
  277. package/dist/ui/molecules/drawer/drawer.js +60 -0
  278. package/dist/ui/molecules/drawer/drawer.js.map +1 -0
  279. package/dist/ui/molecules/drawer/index.d.ts +2 -0
  280. package/dist/ui/molecules/drawer/index.d.ts.map +1 -0
  281. package/dist/ui/molecules/drawer/index.js +3 -0
  282. package/dist/ui/molecules/drawer/index.js.map +1 -0
  283. package/dist/ui/molecules/entity-link-input/entity-link-input.d.ts +36 -0
  284. package/dist/ui/molecules/entity-link-input/entity-link-input.d.ts.map +1 -0
  285. package/dist/ui/molecules/entity-link-input/entity-link-input.js +191 -0
  286. package/dist/ui/molecules/entity-link-input/entity-link-input.js.map +1 -0
  287. package/dist/ui/molecules/entity-link-input/index.d.ts +2 -0
  288. package/dist/ui/molecules/entity-link-input/index.d.ts.map +1 -0
  289. package/dist/ui/molecules/entity-link-input/index.js +3 -0
  290. package/dist/ui/molecules/entity-link-input/index.js.map +1 -0
  291. package/dist/ui/molecules/entity-link-picker/entity-link-picker.d.ts +19 -0
  292. package/dist/ui/molecules/entity-link-picker/entity-link-picker.d.ts.map +1 -0
  293. package/dist/ui/molecules/entity-link-picker/entity-link-picker.js +78 -0
  294. package/dist/ui/molecules/entity-link-picker/entity-link-picker.js.map +1 -0
  295. package/dist/ui/molecules/entity-link-picker/index.d.ts +2 -0
  296. package/dist/ui/molecules/entity-link-picker/index.d.ts.map +1 -0
  297. package/dist/ui/molecules/entity-link-picker/index.js +3 -0
  298. package/dist/ui/molecules/entity-link-picker/index.js.map +1 -0
  299. package/dist/ui/molecules/entity-record-card/entity-record-card.d.ts +30 -0
  300. package/dist/ui/molecules/entity-record-card/entity-record-card.d.ts.map +1 -0
  301. package/dist/ui/molecules/entity-record-card/entity-record-card.js +39 -0
  302. package/dist/ui/molecules/entity-record-card/entity-record-card.js.map +1 -0
  303. package/dist/ui/molecules/entity-record-card/index.d.ts +2 -0
  304. package/dist/ui/molecules/entity-record-card/index.d.ts.map +1 -0
  305. package/dist/ui/molecules/entity-record-card/index.js +3 -0
  306. package/dist/ui/molecules/entity-record-card/index.js.map +1 -0
  307. package/dist/ui/molecules/filter-builder/filter-builder.d.ts +19 -0
  308. package/dist/ui/molecules/filter-builder/filter-builder.d.ts.map +1 -0
  309. package/dist/ui/molecules/filter-builder/filter-builder.js +333 -0
  310. package/dist/ui/molecules/filter-builder/filter-builder.js.map +1 -0
  311. package/dist/ui/molecules/filter-builder/filter-operators.d.ts +20 -0
  312. package/dist/ui/molecules/filter-builder/filter-operators.d.ts.map +1 -0
  313. package/dist/ui/molecules/filter-builder/filter-operators.js +56 -0
  314. package/dist/ui/molecules/filter-builder/filter-operators.js.map +1 -0
  315. package/dist/ui/molecules/filter-builder/index.d.ts +3 -0
  316. package/dist/ui/molecules/filter-builder/index.d.ts.map +1 -0
  317. package/dist/ui/molecules/filter-builder/index.js +4 -0
  318. package/dist/ui/molecules/filter-builder/index.js.map +1 -0
  319. package/dist/ui/molecules/loading-boundary/index.d.ts +2 -0
  320. package/dist/ui/molecules/loading-boundary/index.d.ts.map +1 -0
  321. package/dist/ui/molecules/loading-boundary/index.js +3 -0
  322. package/dist/ui/molecules/loading-boundary/index.js.map +1 -0
  323. package/dist/ui/molecules/loading-boundary/loading-boundary.d.ts +27 -0
  324. package/dist/ui/molecules/loading-boundary/loading-boundary.d.ts.map +1 -0
  325. package/dist/ui/molecules/loading-boundary/loading-boundary.js +42 -0
  326. package/dist/ui/molecules/loading-boundary/loading-boundary.js.map +1 -0
  327. package/dist/ui/molecules/menu/index.d.ts +2 -0
  328. package/dist/ui/molecules/menu/index.d.ts.map +1 -0
  329. package/dist/ui/molecules/menu/index.js +3 -0
  330. package/dist/ui/molecules/menu/index.js.map +1 -0
  331. package/dist/ui/molecules/menu/menu.d.ts +37 -0
  332. package/dist/ui/molecules/menu/menu.d.ts.map +1 -0
  333. package/dist/ui/molecules/menu/menu.js +71 -0
  334. package/dist/ui/molecules/menu/menu.js.map +1 -0
  335. package/dist/ui/molecules/pagination/index.d.ts +2 -0
  336. package/dist/ui/molecules/pagination/index.d.ts.map +1 -0
  337. package/dist/ui/molecules/pagination/index.js +3 -0
  338. package/dist/ui/molecules/pagination/index.js.map +1 -0
  339. package/dist/ui/molecules/pagination/pagination.d.ts +13 -0
  340. package/dist/ui/molecules/pagination/pagination.d.ts.map +1 -0
  341. package/dist/ui/molecules/pagination/pagination.js +68 -0
  342. package/dist/ui/molecules/pagination/pagination.js.map +1 -0
  343. package/dist/ui/molecules/sort-builder/index.d.ts +2 -0
  344. package/dist/ui/molecules/sort-builder/index.d.ts.map +1 -0
  345. package/dist/ui/molecules/sort-builder/index.js +3 -0
  346. package/dist/ui/molecules/sort-builder/index.js.map +1 -0
  347. package/dist/ui/molecules/sort-builder/sort-builder.d.ts +18 -0
  348. package/dist/ui/molecules/sort-builder/sort-builder.d.ts.map +1 -0
  349. package/dist/ui/molecules/sort-builder/sort-builder.js +185 -0
  350. package/dist/ui/molecules/sort-builder/sort-builder.js.map +1 -0
  351. package/dist/ui/molecules/stack/index.d.ts +2 -0
  352. package/dist/ui/molecules/stack/index.d.ts.map +1 -0
  353. package/dist/ui/molecules/stack/index.js +3 -0
  354. package/dist/ui/molecules/stack/index.js.map +1 -0
  355. package/dist/ui/molecules/stack/stack.d.ts +12 -0
  356. package/dist/ui/molecules/stack/stack.d.ts.map +1 -0
  357. package/dist/ui/molecules/stack/stack.js +36 -0
  358. package/dist/ui/molecules/stack/stack.js.map +1 -0
  359. package/dist/ui/molecules/tab-strip/index.d.ts +2 -0
  360. package/dist/ui/molecules/tab-strip/index.d.ts.map +1 -0
  361. package/dist/ui/molecules/tab-strip/index.js +3 -0
  362. package/dist/ui/molecules/tab-strip/index.js.map +1 -0
  363. package/dist/ui/molecules/tab-strip/tab-strip.d.ts +29 -0
  364. package/dist/ui/molecules/tab-strip/tab-strip.d.ts.map +1 -0
  365. package/dist/ui/molecules/tab-strip/tab-strip.js +82 -0
  366. package/dist/ui/molecules/tab-strip/tab-strip.js.map +1 -0
  367. package/dist/ui/molecules/table-toolbar/index.d.ts +2 -0
  368. package/dist/ui/molecules/table-toolbar/index.d.ts.map +1 -0
  369. package/dist/ui/molecules/table-toolbar/index.js +3 -0
  370. package/dist/ui/molecules/table-toolbar/index.js.map +1 -0
  371. package/dist/ui/molecules/table-toolbar/table-toolbar.d.ts +13 -0
  372. package/dist/ui/molecules/table-toolbar/table-toolbar.d.ts.map +1 -0
  373. package/dist/ui/molecules/table-toolbar/table-toolbar.js +28 -0
  374. package/dist/ui/molecules/table-toolbar/table-toolbar.js.map +1 -0
  375. package/dist/ui/molecules/theme-switcher/index.d.ts +2 -0
  376. package/dist/ui/molecules/theme-switcher/index.d.ts.map +1 -0
  377. package/dist/ui/molecules/theme-switcher/index.js +3 -0
  378. package/dist/ui/molecules/theme-switcher/index.js.map +1 -0
  379. package/dist/ui/molecules/theme-switcher/theme-switcher.d.ts +6 -0
  380. package/dist/ui/molecules/theme-switcher/theme-switcher.d.ts.map +1 -0
  381. package/dist/ui/molecules/theme-switcher/theme-switcher.js +24 -0
  382. package/dist/ui/molecules/theme-switcher/theme-switcher.js.map +1 -0
  383. package/dist/ui/organisms/command-palette/command-palette.d.ts +67 -0
  384. package/dist/ui/organisms/command-palette/command-palette.d.ts.map +1 -0
  385. package/dist/ui/organisms/command-palette/command-palette.js +226 -0
  386. package/dist/ui/organisms/command-palette/command-palette.js.map +1 -0
  387. package/dist/ui/organisms/command-palette/index.d.ts +2 -0
  388. package/dist/ui/organisms/command-palette/index.d.ts.map +1 -0
  389. package/dist/ui/organisms/command-palette/index.js +3 -0
  390. package/dist/ui/organisms/command-palette/index.js.map +1 -0
  391. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.d.ts +43 -0
  392. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.d.ts.map +1 -0
  393. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.js +281 -0
  394. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.js.map +1 -0
  395. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.types.d.ts +49 -0
  396. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.types.d.ts.map +1 -0
  397. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.types.js +3 -0
  398. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.types.js.map +1 -0
  399. package/dist/ui/organisms/entity-detail-grid/index.d.ts +3 -0
  400. package/dist/ui/organisms/entity-detail-grid/index.d.ts.map +1 -0
  401. package/dist/ui/organisms/entity-detail-grid/index.js +4 -0
  402. package/dist/ui/organisms/entity-detail-grid/index.js.map +1 -0
  403. package/dist/ui/organisms/entity-form/entity-form-slots.d.ts +53 -0
  404. package/dist/ui/organisms/entity-form/entity-form-slots.d.ts.map +1 -0
  405. package/dist/ui/organisms/entity-form/entity-form-slots.js +44 -0
  406. package/dist/ui/organisms/entity-form/entity-form-slots.js.map +1 -0
  407. package/dist/ui/organisms/entity-form/entity-form.d.ts +4 -0
  408. package/dist/ui/organisms/entity-form/entity-form.d.ts.map +1 -0
  409. package/dist/ui/organisms/entity-form/entity-form.js +494 -0
  410. package/dist/ui/organisms/entity-form/entity-form.js.map +1 -0
  411. package/dist/ui/organisms/entity-form/entity-form.types.d.ts +151 -0
  412. package/dist/ui/organisms/entity-form/entity-form.types.d.ts.map +1 -0
  413. package/dist/ui/organisms/entity-form/entity-form.types.js +3 -0
  414. package/dist/ui/organisms/entity-form/entity-form.types.js.map +1 -0
  415. package/dist/ui/organisms/entity-form/index.d.ts +5 -0
  416. package/dist/ui/organisms/entity-form/index.d.ts.map +1 -0
  417. package/dist/ui/organisms/entity-form/index.js +6 -0
  418. package/dist/ui/organisms/entity-form/index.js.map +1 -0
  419. package/dist/ui/organisms/entity-form/use-entity-form-fields.d.ts +13 -0
  420. package/dist/ui/organisms/entity-form/use-entity-form-fields.d.ts.map +1 -0
  421. package/dist/ui/organisms/entity-form/use-entity-form-fields.js +50 -0
  422. package/dist/ui/organisms/entity-form/use-entity-form-fields.js.map +1 -0
  423. package/dist/ui/organisms/entity-table/entity-table-slots.d.ts +55 -0
  424. package/dist/ui/organisms/entity-table/entity-table-slots.d.ts.map +1 -0
  425. package/dist/ui/organisms/entity-table/entity-table-slots.js +50 -0
  426. package/dist/ui/organisms/entity-table/entity-table-slots.js.map +1 -0
  427. package/dist/ui/organisms/entity-table/entity-table.d.ts +4 -0
  428. package/dist/ui/organisms/entity-table/entity-table.d.ts.map +1 -0
  429. package/dist/ui/organisms/entity-table/entity-table.js +529 -0
  430. package/dist/ui/organisms/entity-table/entity-table.js.map +1 -0
  431. package/dist/ui/organisms/entity-table/entity-table.types.d.ts +126 -0
  432. package/dist/ui/organisms/entity-table/entity-table.types.d.ts.map +1 -0
  433. package/dist/ui/organisms/entity-table/entity-table.types.js +3 -0
  434. package/dist/ui/organisms/entity-table/entity-table.types.js.map +1 -0
  435. package/dist/ui/organisms/entity-table/index.d.ts +5 -0
  436. package/dist/ui/organisms/entity-table/index.d.ts.map +1 -0
  437. package/dist/ui/organisms/entity-table/index.js +6 -0
  438. package/dist/ui/organisms/entity-table/index.js.map +1 -0
  439. package/dist/ui/organisms/entity-table/use-entity-table-columns.d.ts +29 -0
  440. package/dist/ui/organisms/entity-table/use-entity-table-columns.d.ts.map +1 -0
  441. package/dist/ui/organisms/entity-table/use-entity-table-columns.js +103 -0
  442. package/dist/ui/organisms/entity-table/use-entity-table-columns.js.map +1 -0
  443. package/dist/ui/organisms/top-bar/index.d.ts +2 -0
  444. package/dist/ui/organisms/top-bar/index.d.ts.map +1 -0
  445. package/dist/ui/organisms/top-bar/index.js +3 -0
  446. package/dist/ui/organisms/top-bar/index.js.map +1 -0
  447. package/dist/ui/organisms/top-bar/top-bar.d.ts +20 -0
  448. package/dist/ui/organisms/top-bar/top-bar.d.ts.map +1 -0
  449. package/dist/ui/organisms/top-bar/top-bar.js +43 -0
  450. package/dist/ui/organisms/top-bar/top-bar.js.map +1 -0
  451. package/dist/ui/organisms/wizard/index.d.ts +3 -0
  452. package/dist/ui/organisms/wizard/index.d.ts.map +1 -0
  453. package/dist/ui/organisms/wizard/index.js +4 -0
  454. package/dist/ui/organisms/wizard/index.js.map +1 -0
  455. package/dist/ui/organisms/wizard/wizard.d.ts +21 -0
  456. package/dist/ui/organisms/wizard/wizard.d.ts.map +1 -0
  457. package/dist/ui/organisms/wizard/wizard.js +260 -0
  458. package/dist/ui/organisms/wizard/wizard.js.map +1 -0
  459. package/dist/ui/organisms/wizard/wizard.types.d.ts +83 -0
  460. package/dist/ui/organisms/wizard/wizard.types.d.ts.map +1 -0
  461. package/dist/ui/organisms/wizard/wizard.types.js +3 -0
  462. package/dist/ui/organisms/wizard/wizard.types.js.map +1 -0
  463. package/dist/ui/utils/cn.d.ts +4 -0
  464. package/dist/ui/utils/cn.d.ts.map +1 -0
  465. package/dist/ui/utils/cn.js +5 -0
  466. package/dist/ui/utils/cn.js.map +1 -0
  467. package/dist/ui/utils/use-hotkey.d.ts +31 -0
  468. package/dist/ui/utils/use-hotkey.d.ts.map +1 -0
  469. package/dist/ui/utils/use-hotkey.js +69 -0
  470. package/dist/ui/utils/use-hotkey.js.map +1 -0
  471. package/package.json +118 -0
@@ -0,0 +1,494 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { cloneEntityDraft, describeEntityColumns, EntifixLogicError, readDraftString, readRowDrafts } from '@entifix/core';
4
+ import { useId, useState } from 'react';
5
+ import { useErrorMessage, useLocalizedDescriptors, useT, useTranslateKey } from '../../../i18n/index.js';
6
+ import { OVERFLOW_GLYPH, useCasesForSurface } from '../../actions/index.js';
7
+ import { Button } from '../../atoms/button/index.js';
8
+ import { CellValue } from '../../atoms/cell-value/index.js';
9
+ import { FieldControl } from '../../atoms/field-control/index.js';
10
+ import { Skeleton } from '../../atoms/skeleton/index.js';
11
+ import { Text } from '../../atoms/text/index.js';
12
+ import { Card } from '../../molecules/card/index.js';
13
+ import { ConfirmDialog } from '../../molecules/confirm-dialog/index.js';
14
+ import { EntityLinkInput } from '../../molecules/entity-link-input/index.js';
15
+ import { LoadingBoundary } from '../../molecules/loading-boundary/index.js';
16
+ import { Menu } from '../../molecules/menu/index.js';
17
+ import { Stack } from '../../molecules/stack/index.js';
18
+ import { EntityDetailGrid } from '../entity-detail-grid/index.js';
19
+ import { readEntityFormFields } from './entity-form-slots.js';
20
+ import { resolveEntityFormFields } from './use-entity-form-fields.js';
21
+ /**
22
+ * The member types a `linkSources` entry can actually produce an editor for.
23
+ *
24
+ * `link` is the obvious one. `string` is here because a foreign key does not
25
+ * have to be a typed relation: when the target lives in **another slice's
26
+ * store**, an `EntityLink` would be an illegal edge and a storage-layer join
27
+ * across a store boundary, so the member is a plain id and the relation exists
28
+ * only in the operator's head (ADR 0022, and `ProductSpecification.brandId` is
29
+ * the live case). Nothing about the editor cares which of the two it is —
30
+ * `EntityLinkInput` writes `String(target.id)` into the draft either way, and
31
+ * the *only* place `link`-ness still matters is `applyEntityLinks` at submit,
32
+ * which skips a non-`link` descriptor and so leaves the id as the truth.
33
+ *
34
+ * Everything else is excluded on purpose rather than by omission: a `boolean`,
35
+ * `enum`, `number` or `date` member cannot name another record, so a source
36
+ * pointed at one is a wiring mistake — see {@link assertLinkSourcesAreEditable}.
37
+ */ const PICKABLE_TYPES = new Set([
38
+ 'link',
39
+ 'string'
40
+ ]);
41
+ /**
42
+ * A form that builds itself from an entity's metadata: fields, labels and value
43
+ * formatting all come from `@accessor()` declarations, so editing a new entity
44
+ * needs no bespoke form. The read/edit toggle is the whole point — the same
45
+ * component shows a record as text or as inputs.
46
+ *
47
+ * Two things layer on top of that default:
48
+ * - **modes** — `read` renders each member through `CellValue`; `edit` renders
49
+ * the matching `FieldControl`. A member in {@link PICKABLE_TYPES} with an
50
+ * entry in `linkSources` gets the full picker instead — a to-one `link`, or a
51
+ * `string` holding a foreign key into another slice's store. Without a source,
52
+ * a relation stays read-only, and a `linkCollection` always does, the to-many
53
+ * editor being a follow-up. A source aimed at a member that can render no
54
+ * picker is a wiring mistake rather than a no-op, and throws.
55
+ * - **slots** — `<EntityField>` children override one field's label, control or
56
+ * read display, or add a computed field.
57
+ *
58
+ * It is presentational: the draft, its errors and the save/delete actions are
59
+ * all props, so the same form hosts on a plain route and inside a workspace tab.
60
+ */ /**
61
+ * How many verbs a surface shows before the rest fold into an overflow menu.
62
+ *
63
+ * Four, because that is roughly what fits beside a title at a laptop width
64
+ * without the row wrapping — the same number Fiori's object-page header settles
65
+ * on. It is a layout constant, not a policy: raising it does not grant anything.
66
+ */ const VISIBLE_ACTION_LIMIT = 4;
67
+ export function EntityForm({ entityConstructor, entity, values, onFieldChange, linkSources, onLinkChange, mode: modeProp, defaultMode, onModeChange, errors, formError, onSubmit, onDelete, embedded = false, isLoading = false, skeleton = true, isSaving = false, isDeleting = false, error, backHref, title, metadata, isMetadataLoading = false, onUseCase, onClone, children }) {
68
+ const formId = useId();
69
+ const slots = readEntityFormFields(children);
70
+ // The *field* descriptors, which stay local and synchronous — a column is a
71
+ // property of the class every caller holds. Only an action's availability is
72
+ // a property of the caller, which is why that half arrives as `metadata`.
73
+ const columnDescriptors = describeEntityColumns(entityConstructor, entity);
74
+ // Before slots resolve, so an `<EntityField label>` override still wins.
75
+ const described = useLocalizedDescriptors(columnDescriptors);
76
+ const resolved = resolveEntityFormFields(described, slots.fields);
77
+ assertLinkSourcesAreEditable(resolved, linkSources);
78
+ // **Form above, table below**, and it is a partition rather than an ordering
79
+ // hint. A grid rendered between two labelled inputs reads as a field, which
80
+ // it is not — it is a second record list — so every owned collection is
81
+ // pulled out of the field stack whatever `order` it declared, and rendered
82
+ // full width beneath it. A composition that named no child has nothing to
83
+ // render and stays where it was, showing its row count as before.
84
+ const fields = resolved.filter((field)=>!isOwnedCollection(field));
85
+ const ownedCollections = resolved.filter(isOwnedCollection);
86
+ /**
87
+ * `true`/omitted → the built-in default, which draws one label+control pair
88
+ * per resolved field; a node → that node; `false` → nothing. The field list
89
+ * comes from the constructor's metadata, not from the record, so it is already
90
+ * complete while the record is still in flight — which is what lets the
91
+ * placeholder match the form it is standing in for.
92
+ */ const customSkeleton = typeof skeleton === 'boolean' ? undefined : skeleton;
93
+ const showSkeleton = isLoading && skeleton !== false;
94
+ const [internalMode, setInternalMode] = useState(defaultMode != null ? defaultMode : entity ? 'read' : 'edit');
95
+ const mode = modeProp != null ? modeProp : internalMode;
96
+ const editing = mode === 'edit';
97
+ const draft = values != null ? values : {};
98
+ const setField = (name, value)=>onFieldChange == null ? void 0 : onFieldChange(name, value);
99
+ const toggleMode = ()=>{
100
+ const next = editing ? 'read' : 'edit';
101
+ setInternalMode(next);
102
+ onModeChange == null ? void 0 : onModeChange(next);
103
+ };
104
+ const t = useT();
105
+ const translateKey = useTranslateKey();
106
+ const errorMessage = useErrorMessage();
107
+ const busy = isSaving || isDeleting;
108
+ // A draft restored from storage holds relation ids and no instances, so every
109
+ // picker is resolving its target for a moment after mount. Saving inside that
110
+ // window is exactly the case `applyEntityLinks` refuses: an `embedded` member
111
+ // with an id and nothing to inline. Gating the save is the honest answer —
112
+ // the form is still assembling itself, and the wait is one lookup long.
113
+ //
114
+ // Deliberately not narrowed to `embedded` members: a descriptor's
115
+ // serialization is not what makes an in-flight lookup a bad moment to submit,
116
+ // and a form that saves half-resolved is confusing whichever shape it writes.
117
+ const resolvingLinks = Object.values(linkSources != null ? linkSources : {}).some((source)=>source.selected.isLoading);
118
+ // Absent metadata keeps the pre-ADR-0026 behaviour, so an un-migrated call
119
+ // site renders exactly as before. Present metadata is authoritative: it is
120
+ // what the service already decided this caller may do.
121
+ const may = (action)=>metadata === undefined || metadata.actions.includes(action);
122
+ // A single-record form shows the verbs that act on *this* record. Which cell
123
+ // lands where is `action-surfaces`' business and nobody else's — a
124
+ // `context-dependent` entity verb belongs to a row's overflow menu and a
125
+ // `collection`-bound one to the bulk bar, and resolving that here as well is
126
+ // how the two surfaces drifted apart in the first place.
127
+ //
128
+ // ⚠️ **Only when there is somewhere for them to go.** Every cell these two
129
+ // surfaces render is `binding: 'entity'`, so without an `onUseCase` the
130
+ // button has no handler and clicking it does nothing at all. That is not a
131
+ // hypothetical: `makeEntityCrud` withholds the handler on a create, because
132
+ // there is no record for a verb to act on — and Publish and Unpublish
133
+ // rendered on a new `ProductOffering` and were inert, which reads as a broken
134
+ // feature rather than an inapplicable one.
135
+ //
136
+ // The hooks are called unconditionally and their *results* are gated: React's
137
+ // hook count must stay fixed across renders.
138
+ const declaredHeaderUseCases = useCasesForSurface('form-header', metadata == null ? void 0 : metadata.useCases);
139
+ const declaredFooterUseCases = useCasesForSurface('form-footer', metadata == null ? void 0 : metadata.useCases);
140
+ const headerUseCases = onUseCase ? declaredHeaderUseCases : [];
141
+ const footerUseCases = onUseCase ? declaredFooterUseCases : [];
142
+ // A descriptor carrying `confirm` must be asked about before it fires;
143
+ // `revoke-sessions` ends every session a user holds. The state holds the
144
+ // confirmation itself rather than the descriptor, so the dialog cannot be
145
+ // opened for a verb that never asked for one.
146
+ const [pending, setPending] = useState(undefined);
147
+ const invoke = (descriptor)=>{
148
+ const confirm = descriptor.confirm;
149
+ if (confirm) {
150
+ setPending({
151
+ key: descriptor.key,
152
+ labelKey: descriptor.labelKey,
153
+ confirm
154
+ });
155
+ return;
156
+ }
157
+ onUseCase == null ? void 0 : onUseCase(descriptor.key);
158
+ };
159
+ const useCaseButton = (descriptor)=>{
160
+ var _descriptor_confirm;
161
+ return /*#__PURE__*/ _jsx(Button, {
162
+ type: "button",
163
+ variant: ((_descriptor_confirm = descriptor.confirm) == null ? void 0 : _descriptor_confirm.tone) === 'destructive' ? 'destructive' : 'secondary',
164
+ size: descriptor.placement === 'context-independent' ? 'sm' : 'md',
165
+ disabled: busy,
166
+ onClick: ()=>invoke(descriptor),
167
+ children: translateKey(descriptor.labelKey)
168
+ }, descriptor.key);
169
+ };
170
+ const useCaseMenuItem = (descriptor)=>{
171
+ var _descriptor_confirm;
172
+ return /*#__PURE__*/ _jsx(Menu.Item, {
173
+ tone: ((_descriptor_confirm = descriptor.confirm) == null ? void 0 : _descriptor_confirm.tone) === 'destructive' ? 'destructive' : 'neutral',
174
+ disabled: busy,
175
+ onClick: ()=>invoke(descriptor),
176
+ children: translateKey(descriptor.labelKey)
177
+ }, descriptor.key);
178
+ };
179
+ /**
180
+ * Four actions fit a row; twelve do not.
181
+ *
182
+ * So a surface renders its first {@link VISIBLE_ACTION_LIMIT} verbs as
183
+ * buttons and folds the rest behind one overflow trigger, in **declaration
184
+ * order** — the entity's author decided which verbs matter by writing them
185
+ * first, and a rule that sorted by anything else (alphabetical, destructive
186
+ * last) would reorder the row every time a verb was added.
187
+ *
188
+ * The split is only applied when there is something to fold: a fifth action
189
+ * is the point at which a menu is cheaper than a wider row, and a menu
190
+ * holding one entry is strictly worse than the button it replaced.
191
+ */ const withOverflow = (descriptors)=>{
192
+ if (descriptors.length <= VISIBLE_ACTION_LIMIT) {
193
+ return descriptors.map(useCaseButton);
194
+ }
195
+ const visible = descriptors.slice(0, VISIBLE_ACTION_LIMIT);
196
+ const folded = descriptors.slice(VISIBLE_ACTION_LIMIT);
197
+ return [
198
+ ...visible.map(useCaseButton),
199
+ /*#__PURE__*/ _jsxs(Menu, {
200
+ children: [
201
+ /*#__PURE__*/ _jsx(Menu.Trigger, {
202
+ "aria-label": t('form.moreActions'),
203
+ children: OVERFLOW_GLYPH
204
+ }),
205
+ /*#__PURE__*/ _jsx(Menu.Items, {
206
+ children: folded.map(useCaseMenuItem)
207
+ })
208
+ ]
209
+ }, "overflow")
210
+ ];
211
+ };
212
+ return /*#__PURE__*/ _jsxs(Card, {
213
+ children: [
214
+ /*#__PURE__*/ _jsxs(Stack, {
215
+ gap: "s",
216
+ children: [
217
+ !embedded && /*#__PURE__*/ _jsxs(Stack, {
218
+ direction: "row",
219
+ gap: "xs",
220
+ align: "center",
221
+ children: [
222
+ /*#__PURE__*/ _jsx(Text, {
223
+ as: "h2",
224
+ step: 1,
225
+ weight: "semibold",
226
+ children: title != null ? title : entity || isLoading ? t('form.details') : t('form.new')
227
+ }),
228
+ modeProp === undefined && entity && /*#__PURE__*/ _jsx(Button, {
229
+ type: "button",
230
+ variant: "ghost",
231
+ size: "sm",
232
+ onClick: toggleMode,
233
+ children: editing ? t('form.view') : t('form.edit')
234
+ }),
235
+ /*#__PURE__*/ _jsx(LoadingBoundary, {
236
+ isLoading: isMetadataLoading,
237
+ lines: 0,
238
+ children: /*#__PURE__*/ _jsxs(_Fragment, {
239
+ children: [
240
+ withOverflow(headerUseCases),
241
+ slots.headerActions
242
+ ]
243
+ })
244
+ })
245
+ ]
246
+ }),
247
+ /*#__PURE__*/ _jsx("span", {
248
+ role: "status",
249
+ "aria-live": "polite",
250
+ className: "sr-only",
251
+ children: isLoading ? t('form.loading') : ''
252
+ }),
253
+ error && /*#__PURE__*/ _jsx("p", {
254
+ role: "alert",
255
+ "data-testid": "entity-form-error",
256
+ className: "rounded-sm border border-danger bg-danger-subtle px-s py-2xs text-step-sm text-danger",
257
+ children: errorMessage(error)
258
+ }),
259
+ showSkeleton ? customSkeleton != null ? customSkeleton : fields.map((field)=>/*#__PURE__*/ _jsxs(Stack, {
260
+ gap: "3xs",
261
+ children: [
262
+ /*#__PURE__*/ _jsx(Skeleton, {
263
+ shape: "line",
264
+ className: "w-24"
265
+ }),
266
+ /*#__PURE__*/ _jsx(Skeleton, {
267
+ className: "h-9 w-full"
268
+ })
269
+ ]
270
+ }, field.name)) : fields.map((field)=>/*#__PURE__*/ _jsx(FieldRow, {
271
+ field: field,
272
+ entity: entity,
273
+ draft: draft,
274
+ value: readDraftString(draft, field.name),
275
+ editing: editing,
276
+ error: editing ? errors == null ? void 0 : errors[field.name] : undefined,
277
+ setField: setField,
278
+ linkSource: linkSources == null ? void 0 : linkSources[field.name],
279
+ onLinkChange: onLinkChange,
280
+ id: `${formId}-${field.name}`
281
+ }, field.name)),
282
+ ownedCollections.map((field)=>/*#__PURE__*/ _jsx(EntityDetailGrid, {
283
+ descriptor: field,
284
+ rows: readRowDrafts(draft[field.name]),
285
+ onRowsChange: (rows)=>setField(field.name, rows),
286
+ errors: editing ? errors : undefined,
287
+ editing: editing,
288
+ isLoading: isLoading,
289
+ skeleton: skeleton
290
+ }, field.name)),
291
+ editing && formError && /*#__PURE__*/ _jsx("span", {
292
+ role: "alert",
293
+ className: "text-step-sm text-danger",
294
+ children: formError
295
+ }),
296
+ editing && !embedded && /*#__PURE__*/ _jsxs(Stack, {
297
+ direction: "row",
298
+ gap: "xs",
299
+ children: [
300
+ may('write') && /*#__PURE__*/ _jsx(Button, {
301
+ type: "button",
302
+ onClick: ()=>onSubmit == null ? void 0 : onSubmit(draft),
303
+ disabled: busy || resolvingLinks,
304
+ children: isSaving ? t('form.saving') : t('form.save')
305
+ }),
306
+ onDelete && may('delete') && /*#__PURE__*/ _jsx(Button, {
307
+ type: "button",
308
+ variant: "secondary",
309
+ onClick: onDelete,
310
+ disabled: busy,
311
+ children: isDeleting ? t('form.deleting') : t('form.delete')
312
+ }),
313
+ withOverflow(footerUseCases),
314
+ onClone && entity && may('write') && /*#__PURE__*/ _jsx(Button, {
315
+ type: "button",
316
+ variant: "secondary",
317
+ disabled: busy,
318
+ onClick: ()=>onClone(cloneEntityDraft(entityConstructor, draft)),
319
+ children: t('form.clone')
320
+ }),
321
+ slots.footerActions,
322
+ backHref && /*#__PURE__*/ _jsx("a", {
323
+ href: backHref,
324
+ children: /*#__PURE__*/ _jsx(Button, {
325
+ type: "button",
326
+ variant: "ghost",
327
+ disabled: busy,
328
+ children: t('form.back')
329
+ })
330
+ })
331
+ ]
332
+ }),
333
+ slots.rest
334
+ ]
335
+ }),
336
+ pending && /*#__PURE__*/ _jsx(ConfirmDialog, {
337
+ open: true,
338
+ tone: pending.confirm.tone,
339
+ title: translateKey(pending.labelKey),
340
+ message: translateKey(pending.confirm.messageKey),
341
+ busy: busy,
342
+ onCancel: ()=>setPending(undefined),
343
+ onConfirm: ()=>{
344
+ const key = pending.key;
345
+ setPending(undefined);
346
+ onUseCase == null ? void 0 : onUseCase(key);
347
+ }
348
+ })
349
+ ]
350
+ });
351
+ }
352
+ /**
353
+ * A member the detail grid renders rather than the field stack.
354
+ *
355
+ * The `childType` half is not defensive: a `composition` that declared no child
356
+ * has no columns, so there is nothing for a grid to draw. It keeps its place in
357
+ * the field stack and reads as its row count, which is what it did before this
358
+ * control existed — an honest "some rows" rather than an empty table implying
359
+ * there are none.
360
+ */ function isOwnedCollection(field) {
361
+ return field.type === 'composition' && field.childType !== undefined;
362
+ }
363
+ /**
364
+ * Refuse a `linkSources` entry that names a member no picker can be built for.
365
+ *
366
+ * `FieldRow` asks for {@link PICKABLE_TYPES} before it builds an editor, so a
367
+ * source handed to anything else used to fall through to the read-only display
368
+ * or a plain `FieldControl` with nothing said: the caller wired a picker, no
369
+ * picker appeared, and the field was indistinguishable from one the entity had
370
+ * declared read-only. That is a wiring mistake rather than a state — the entry
371
+ * is dead in *every* shape such a field can render, since an
372
+ * `<EntityField render>` slot is handed the draft and never the source — so it
373
+ * costs the render instead of a warning nobody reads. `useEntityLinkSource`
374
+ * already throws `EntifixLogicError` at render for the sibling mistake (a search
375
+ * property the target does not declare `filterable`); this is the same fault
376
+ * caught one level up.
377
+ *
378
+ * Two messages, because the two faults are not the same thing. A
379
+ * `linkCollection` is a member the editor has simply not been built for yet
380
+ * (#26), so the fix is to wait or to point at the to-one you meant. Any other
381
+ * type is a member that can never name another record at all, so the fix is to
382
+ * remove the entry.
383
+ *
384
+ * Here rather than inside `FieldRow`, and that is the whole reason it is a
385
+ * separate pass: a row only reaches its editor branch in **edit** mode, so a
386
+ * per-row check would stay silent on a form that opens in `read` — the default
387
+ * whenever there is a record — and then throw on a click, minutes later. One
388
+ * pass over the registry fires on the first render either way.
389
+ *
390
+ * Against the resolved fields rather than the raw metadata: a slot may drop a
391
+ * member, and a source left behind for a field that no longer renders is not
392
+ * worth a page.
393
+ */ function assertLinkSourcesAreEditable(fields, // Same reason as the prop's own declaration: a source's target is another
394
+ // entity entirely and cannot be expressed in terms of `TEntity`.
395
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
396
+ linkSources) {
397
+ if (linkSources === undefined) return;
398
+ const sourced = fields.filter((field)=>linkSources[field.name] !== undefined && !PICKABLE_TYPES.has(field.type));
399
+ if (sourced.length === 0) return;
400
+ const toMany = sourced.filter((field)=>field.type === 'linkCollection').map((field)=>field.name);
401
+ if (toMany.length > 0) {
402
+ throw new EntifixLogicError(`EntityForm was given a link source for a to-many member: ${toMany.join(', ')}. ` + 'A `linkCollection` has no editor yet, so the source can only be dropped ' + 'and the field would render read-only with no sign anything was wired. ' + 'Remove the entry, or point it at the to-one `link` you meant.', undefined, {
403
+ fields: toMany
404
+ });
405
+ }
406
+ const owned = sourced.filter((field)=>field.type === 'composition').map((field)=>field.name);
407
+ if (owned.length > 0) {
408
+ throw new EntifixLogicError(`EntityForm was given a link source for an owned collection: ${owned.join(', ')}. ` + 'A `composition` is not a reference — its rows have no life outside this ' + 'record and are never picked from existing ones, so there is nothing for a ' + 'picker to look up. The detail grid that edits them is #122.', undefined, {
409
+ fields: owned
410
+ });
411
+ }
412
+ const unpickable = sourced.map((field)=>`${field.name} (${field.type})`);
413
+ throw new EntifixLogicError(`EntityForm was given a link source for a member that cannot hold one: ${unpickable.join(', ')}. ` + 'A picker writes the target’s id into the draft, so the member has to be a ' + '`link` or the `string` that carries a foreign key. Remove the entry, or ' + 'point it at the member that actually holds the reference.', undefined, {
414
+ fields: sourced.map((field)=>field.name)
415
+ });
416
+ }
417
+ /**
418
+ * One label + control (or value) row. A `readonly` member renders its read
419
+ * display even in edit mode, and so does a relation with no source; everything
420
+ * else edits through `FieldControl` — or, when a source was supplied for a
421
+ * member in {@link PICKABLE_TYPES}, through `EntityLinkInput`. A boolean edited
422
+ * inline carries its own label, so the row does not add a second one.
423
+ *
424
+ * The source branch sits above the `virtual || isRelation` fallback and below
425
+ * `field.render`, which is what lets a slot still override a picked field.
426
+ */ function FieldRow({ field, entity, draft, value, editing, error, setField, linkSource, onLinkChange, id }) {
427
+ const readNode = field.readRender ? field.readRender(entity) : /*#__PURE__*/ _jsx(CellValue, {
428
+ value: entity ? entity[field.name] : undefined,
429
+ descriptor: field
430
+ });
431
+ // Members with no editor of their own here: a to-one `link` whose picker was
432
+ // never wired, a `linkCollection` (#26) and a `composition` (#122). All three
433
+ // fall back to the read display, which is honest — a disabled text box
434
+ // holding `[object Object]` is not.
435
+ const isRelation = field.type === 'link' || field.type === 'linkCollection' || field.type === 'composition';
436
+ let control;
437
+ if (!editing) {
438
+ control = readNode;
439
+ } else if (field.render) {
440
+ control = field.render({
441
+ draft,
442
+ value,
443
+ setField,
444
+ id
445
+ });
446
+ } else if (linkSource && PICKABLE_TYPES.has(field.type)) {
447
+ control = /*#__PURE__*/ _jsx(EntityLinkInput, {
448
+ descriptor: field,
449
+ value: value,
450
+ source: linkSource,
451
+ id: id,
452
+ disabled: field.readonly,
453
+ onSelect: (target)=>{
454
+ setField(field.name, target.id == null ? '' : String(target.id));
455
+ onLinkChange == null ? void 0 : onLinkChange(field.name, target);
456
+ },
457
+ onClear: ()=>{
458
+ setField(field.name, '');
459
+ onLinkChange == null ? void 0 : onLinkChange(field.name, undefined);
460
+ }
461
+ });
462
+ } else if (field.virtual || isRelation) {
463
+ // A relation with no source has no input to offer, and a virtual field has
464
+ // no member to edit unless a `render` was supplied — both fall back to the
465
+ // read display.
466
+ control = readNode;
467
+ } else {
468
+ control = /*#__PURE__*/ _jsx(FieldControl, {
469
+ descriptor: field,
470
+ value: value,
471
+ onChange: (next)=>setField(field.name, next),
472
+ id: id
473
+ });
474
+ }
475
+ const ownsLabel = editing && field.type === 'boolean' && !field.render && !field.virtual;
476
+ return /*#__PURE__*/ _jsxs(Stack, {
477
+ gap: "3xs",
478
+ children: [
479
+ !ownsLabel && /*#__PURE__*/ _jsx("label", {
480
+ htmlFor: id,
481
+ className: "text-step-sm text-content-muted",
482
+ children: field.label
483
+ }),
484
+ control,
485
+ error && /*#__PURE__*/ _jsx("span", {
486
+ role: "alert",
487
+ className: "text-step-sm text-danger",
488
+ children: error
489
+ })
490
+ ]
491
+ });
492
+ }
493
+
494
+ //# sourceMappingURL=entity-form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/ui/organisms/entity-form/entity-form.tsx"],"sourcesContent":["'use client';\n\nimport {\n cloneEntityDraft,\n describeEntityColumns,\n EntifixLogicError,\n type Entity,\n type EntityAction,\n type EntityDraft,\n type EntityDraftValue,\n type EntityLinkSource,\n type MetaAccessorType,\n readDraftString,\n readRowDrafts,\n type UseCaseDescriptor,\n} from '@entifix/core';\nimport { type ReactNode, useId, useState } from 'react';\n\nimport {\n useErrorMessage,\n useLocalizedDescriptors,\n useT,\n useTranslateKey,\n} from '../../../i18n/index.js';\nimport { OVERFLOW_GLYPH, useCasesForSurface } from '../../actions/index.js';\nimport { Button } from '../../atoms/button/index.js';\nimport { CellValue } from '../../atoms/cell-value/index.js';\nimport { FieldControl } from '../../atoms/field-control/index.js';\nimport { Skeleton } from '../../atoms/skeleton/index.js';\nimport { Text } from '../../atoms/text/index.js';\nimport { Card } from '../../molecules/card/index.js';\nimport { ConfirmDialog } from '../../molecules/confirm-dialog/index.js';\nimport { EntityLinkInput } from '../../molecules/entity-link-input/index.js';\nimport { LoadingBoundary } from '../../molecules/loading-boundary/index.js';\nimport { Menu } from '../../molecules/menu/index.js';\nimport { Stack } from '../../molecules/stack/index.js';\nimport { EntityDetailGrid } from '../entity-detail-grid/index.js';\nimport type {\n EntityFormField,\n EntityFormMode,\n EntityFormProps,\n} from './entity-form.types.js';\nimport { readEntityFormFields } from './entity-form-slots.js';\nimport { resolveEntityFormFields } from './use-entity-form-fields.js';\n\n/**\n * The member types a `linkSources` entry can actually produce an editor for.\n *\n * `link` is the obvious one. `string` is here because a foreign key does not\n * have to be a typed relation: when the target lives in **another slice's\n * store**, an `EntityLink` would be an illegal edge and a storage-layer join\n * across a store boundary, so the member is a plain id and the relation exists\n * only in the operator's head (ADR 0022, and `ProductSpecification.brandId` is\n * the live case). Nothing about the editor cares which of the two it is —\n * `EntityLinkInput` writes `String(target.id)` into the draft either way, and\n * the *only* place `link`-ness still matters is `applyEntityLinks` at submit,\n * which skips a non-`link` descriptor and so leaves the id as the truth.\n *\n * Everything else is excluded on purpose rather than by omission: a `boolean`,\n * `enum`, `number` or `date` member cannot name another record, so a source\n * pointed at one is a wiring mistake — see {@link assertLinkSourcesAreEditable}.\n */\nconst PICKABLE_TYPES: ReadonlySet<MetaAccessorType> = new Set<MetaAccessorType>(\n ['link', 'string'],\n);\n\n/**\n * A form that builds itself from an entity's metadata: fields, labels and value\n * formatting all come from `@accessor()` declarations, so editing a new entity\n * needs no bespoke form. The read/edit toggle is the whole point — the same\n * component shows a record as text or as inputs.\n *\n * Two things layer on top of that default:\n * - **modes** — `read` renders each member through `CellValue`; `edit` renders\n * the matching `FieldControl`. A member in {@link PICKABLE_TYPES} with an\n * entry in `linkSources` gets the full picker instead — a to-one `link`, or a\n * `string` holding a foreign key into another slice's store. Without a source,\n * a relation stays read-only, and a `linkCollection` always does, the to-many\n * editor being a follow-up. A source aimed at a member that can render no\n * picker is a wiring mistake rather than a no-op, and throws.\n * - **slots** — `<EntityField>` children override one field's label, control or\n * read display, or add a computed field.\n *\n * It is presentational: the draft, its errors and the save/delete actions are\n * all props, so the same form hosts on a plain route and inside a workspace tab.\n */\n/**\n * How many verbs a surface shows before the rest fold into an overflow menu.\n *\n * Four, because that is roughly what fits beside a title at a laptop width\n * without the row wrapping — the same number Fiori's object-page header settles\n * on. It is a layout constant, not a policy: raising it does not grant anything.\n */\nconst VISIBLE_ACTION_LIMIT = 4;\n\n/** A verb waiting on its confirmation — narrowed so `confirm` is not optional. */\ninterface PendingConfirmation {\n key: string;\n labelKey: string;\n confirm: NonNullable<UseCaseDescriptor['confirm']>;\n}\n\nexport function EntityForm<TEntity extends Entity>({\n entityConstructor,\n entity,\n values,\n onFieldChange,\n linkSources,\n onLinkChange,\n mode: modeProp,\n defaultMode,\n onModeChange,\n errors,\n formError,\n onSubmit,\n onDelete,\n embedded = false,\n isLoading = false,\n skeleton = true,\n isSaving = false,\n isDeleting = false,\n error,\n backHref,\n title,\n metadata,\n isMetadataLoading = false,\n onUseCase,\n onClone,\n children,\n}: EntityFormProps<TEntity>) {\n const formId = useId();\n const slots = readEntityFormFields<TEntity>(children);\n // The *field* descriptors, which stay local and synchronous — a column is a\n // property of the class every caller holds. Only an action's availability is\n // a property of the caller, which is why that half arrives as `metadata`.\n const columnDescriptors = describeEntityColumns(\n entityConstructor,\n entity,\n ) as Array<EntityFormField<TEntity>>;\n // Before slots resolve, so an `<EntityField label>` override still wins.\n const described = useLocalizedDescriptors(columnDescriptors);\n const resolved = resolveEntityFormFields(described, slots.fields);\n assertLinkSourcesAreEditable(resolved, linkSources);\n\n // **Form above, table below**, and it is a partition rather than an ordering\n // hint. A grid rendered between two labelled inputs reads as a field, which\n // it is not — it is a second record list — so every owned collection is\n // pulled out of the field stack whatever `order` it declared, and rendered\n // full width beneath it. A composition that named no child has nothing to\n // render and stays where it was, showing its row count as before.\n const fields = resolved.filter(field => !isOwnedCollection(field));\n const ownedCollections = resolved.filter(isOwnedCollection);\n\n /**\n * `true`/omitted → the built-in default, which draws one label+control pair\n * per resolved field; a node → that node; `false` → nothing. The field list\n * comes from the constructor's metadata, not from the record, so it is already\n * complete while the record is still in flight — which is what lets the\n * placeholder match the form it is standing in for.\n */\n const customSkeleton = typeof skeleton === 'boolean' ? undefined : skeleton;\n const showSkeleton = isLoading && skeleton !== false;\n\n const [internalMode, setInternalMode] = useState<EntityFormMode>(\n defaultMode ?? (entity ? 'read' : 'edit'),\n );\n const mode = modeProp ?? internalMode;\n const editing = mode === 'edit';\n\n const draft: EntityDraft = values ?? {};\n const setField = (name: string, value: EntityDraftValue) =>\n onFieldChange?.(name, value);\n\n const toggleMode = () => {\n const next: EntityFormMode = editing ? 'read' : 'edit';\n setInternalMode(next);\n onModeChange?.(next);\n };\n\n const t = useT();\n const translateKey = useTranslateKey();\n const errorMessage = useErrorMessage();\n const busy = isSaving || isDeleting;\n\n // A draft restored from storage holds relation ids and no instances, so every\n // picker is resolving its target for a moment after mount. Saving inside that\n // window is exactly the case `applyEntityLinks` refuses: an `embedded` member\n // with an id and nothing to inline. Gating the save is the honest answer —\n // the form is still assembling itself, and the wait is one lookup long.\n //\n // Deliberately not narrowed to `embedded` members: a descriptor's\n // serialization is not what makes an in-flight lookup a bad moment to submit,\n // and a form that saves half-resolved is confusing whichever shape it writes.\n const resolvingLinks = Object.values(linkSources ?? {}).some(\n source => source.selected.isLoading,\n );\n\n // Absent metadata keeps the pre-ADR-0026 behaviour, so an un-migrated call\n // site renders exactly as before. Present metadata is authoritative: it is\n // what the service already decided this caller may do.\n const may = (action: EntityAction) =>\n metadata === undefined || metadata.actions.includes(action);\n\n // A single-record form shows the verbs that act on *this* record. Which cell\n // lands where is `action-surfaces`' business and nobody else's — a\n // `context-dependent` entity verb belongs to a row's overflow menu and a\n // `collection`-bound one to the bulk bar, and resolving that here as well is\n // how the two surfaces drifted apart in the first place.\n //\n // ⚠️ **Only when there is somewhere for them to go.** Every cell these two\n // surfaces render is `binding: 'entity'`, so without an `onUseCase` the\n // button has no handler and clicking it does nothing at all. That is not a\n // hypothetical: `makeEntityCrud` withholds the handler on a create, because\n // there is no record for a verb to act on — and Publish and Unpublish\n // rendered on a new `ProductOffering` and were inert, which reads as a broken\n // feature rather than an inapplicable one.\n //\n // The hooks are called unconditionally and their *results* are gated: React's\n // hook count must stay fixed across renders.\n const declaredHeaderUseCases = useCasesForSurface(\n 'form-header',\n metadata?.useCases,\n );\n const declaredFooterUseCases = useCasesForSurface(\n 'form-footer',\n metadata?.useCases,\n );\n const headerUseCases = onUseCase ? declaredHeaderUseCases : [];\n const footerUseCases = onUseCase ? declaredFooterUseCases : [];\n\n // A descriptor carrying `confirm` must be asked about before it fires;\n // `revoke-sessions` ends every session a user holds. The state holds the\n // confirmation itself rather than the descriptor, so the dialog cannot be\n // opened for a verb that never asked for one.\n const [pending, setPending] = useState<PendingConfirmation | undefined>(\n undefined,\n );\n const invoke = (descriptor: UseCaseDescriptor) => {\n const confirm = descriptor.confirm;\n if (confirm) {\n setPending({\n key: descriptor.key,\n labelKey: descriptor.labelKey,\n confirm,\n });\n return;\n }\n onUseCase?.(descriptor.key);\n };\n\n const useCaseButton = (descriptor: UseCaseDescriptor) => (\n <Button\n key={descriptor.key}\n type=\"button\"\n variant={\n descriptor.confirm?.tone === 'destructive' ? 'destructive' : 'secondary'\n }\n size={descriptor.placement === 'context-independent' ? 'sm' : 'md'}\n disabled={busy}\n onClick={() => invoke(descriptor)}\n >\n {/* A descriptor's labels are *runtime* catalog keys — they never resolve\n at compile time, which is why `@r10c/i18n-check` is what catches a\n typo here rather than the type system. */}\n {translateKey(descriptor.labelKey)}\n </Button>\n );\n\n const useCaseMenuItem = (descriptor: UseCaseDescriptor) => (\n <Menu.Item\n key={descriptor.key}\n tone={\n descriptor.confirm?.tone === 'destructive' ? 'destructive' : 'neutral'\n }\n disabled={busy}\n onClick={() => invoke(descriptor)}\n >\n {translateKey(descriptor.labelKey)}\n </Menu.Item>\n );\n\n /**\n * Four actions fit a row; twelve do not.\n *\n * So a surface renders its first {@link VISIBLE_ACTION_LIMIT} verbs as\n * buttons and folds the rest behind one overflow trigger, in **declaration\n * order** — the entity's author decided which verbs matter by writing them\n * first, and a rule that sorted by anything else (alphabetical, destructive\n * last) would reorder the row every time a verb was added.\n *\n * The split is only applied when there is something to fold: a fifth action\n * is the point at which a menu is cheaper than a wider row, and a menu\n * holding one entry is strictly worse than the button it replaced.\n */\n const withOverflow = (descriptors: UseCaseDescriptor[]) => {\n if (descriptors.length <= VISIBLE_ACTION_LIMIT) {\n return descriptors.map(useCaseButton);\n }\n\n const visible = descriptors.slice(0, VISIBLE_ACTION_LIMIT);\n const folded = descriptors.slice(VISIBLE_ACTION_LIMIT);\n\n return [\n ...visible.map(useCaseButton),\n <Menu key=\"overflow\">\n <Menu.Trigger aria-label={t('form.moreActions')}>\n {OVERFLOW_GLYPH}\n </Menu.Trigger>\n <Menu.Items>{folded.map(useCaseMenuItem)}</Menu.Items>\n </Menu>,\n ];\n };\n\n return (\n <Card>\n <Stack gap=\"s\">\n {/* An embedded form brings only its fields: the heading and the action\n row belong to whatever is hosting it — a wizard step sits under the\n wizard's own heading and advances with the wizard's own footer, so\n rendering a second of each is two controls for one job. */}\n {!embedded && (\n <Stack direction=\"row\" gap=\"xs\" align=\"center\">\n <Text as=\"h2\" step={1} weight=\"semibold\">\n {/* `entity` is undefined while the record is still in flight, so\n testing it alone made a loading edit form announce itself as\n \"New\" for as long as the fetch took, then relabel when the\n record landed. A form that is loading is never a create. */}\n {title ??\n (entity || isLoading ? t('form.details') : t('form.new'))}\n </Text>\n {/* The built-in toggle only appears when the form owns its mode and\n there is a record to view — a create form has nothing to read. */}\n {modeProp === undefined && entity && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={toggleMode}\n >\n {editing ? t('form.view') : t('form.edit')}\n </Button>\n )}\n <LoadingBoundary isLoading={isMetadataLoading} lines={0}>\n <>\n {withOverflow(headerUseCases)}\n {slots.headerActions}\n </>\n </LoadingBoundary>\n </Stack>\n )}\n\n {/* One announcement for the form; the shimmer below is aria-hidden. */}\n <span role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {isLoading ? t('form.loading') : ''}\n </span>\n\n {error && (\n <p\n role=\"alert\"\n data-testid=\"entity-form-error\"\n className=\"rounded-sm border border-danger bg-danger-subtle px-s py-2xs text-step-sm text-danger\"\n >\n {errorMessage(error)}\n </p>\n )}\n\n {/* The placeholder *replaces* the rows rather than sitting above them.\n Rendering both meant a shimmer stacked on a full set of empty fields,\n which is two loading signals for one region and twice the height the\n loaded form settles at. */}\n {showSkeleton\n ? (customSkeleton ??\n fields.map(field => (\n <Stack key={field.name} gap=\"3xs\">\n <Skeleton shape=\"line\" className=\"w-24\" />\n <Skeleton className=\"h-9 w-full\" />\n </Stack>\n )))\n : fields.map(field => (\n <FieldRow\n key={field.name}\n field={field}\n entity={entity}\n draft={draft}\n value={readDraftString(draft, field.name)}\n editing={editing}\n error={editing ? errors?.[field.name] : undefined}\n setField={setField}\n linkSource={linkSources?.[field.name]}\n onLinkChange={onLinkChange}\n id={`${formId}-${field.name}`}\n />\n ))}\n\n {/* The rows the record owns, full width and below every field. Each\n grid is handed the *whole* error map and picks out the keys naming\n its own member, so a record owning two collections needs no\n bookkeeping here. */}\n {ownedCollections.map(field => (\n <EntityDetailGrid\n key={field.name}\n descriptor={field}\n rows={readRowDrafts(draft[field.name])}\n onRowsChange={rows => setField(field.name, rows)}\n errors={editing ? errors : undefined}\n editing={editing}\n isLoading={isLoading}\n skeleton={skeleton}\n />\n ))}\n\n {/* A cross-field rule has no row to sit under, so it sits with the\n actions it blocks. */}\n {editing && formError && (\n <span role=\"alert\" className=\"text-step-sm text-danger\">\n {formError}\n </span>\n )}\n\n {editing && !embedded && (\n <Stack direction=\"row\" gap=\"xs\">\n {may('write') && (\n <Button\n type=\"button\"\n onClick={() => onSubmit?.(draft)}\n disabled={busy || resolvingLinks}\n >\n {isSaving ? t('form.saving') : t('form.save')}\n </Button>\n )}\n {onDelete && may('delete') && (\n <Button\n type=\"button\"\n variant=\"secondary\"\n onClick={onDelete}\n disabled={busy}\n >\n {isDeleting ? t('form.deleting') : t('form.delete')}\n </Button>\n )}\n {withOverflow(footerUseCases)}\n {/* Clone is the CRUD triple's, not a declared verb's: every entity\n can be copied, so giving it a `@useCase()` would mean declaring\n the same verb on all 28 of them. It needs `write`, because what\n it produces is a create. */}\n {onClone && entity && may('write') && (\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={busy}\n onClick={() =>\n onClone(cloneEntityDraft(entityConstructor, draft))\n }\n >\n {t('form.clone')}\n </Button>\n )}\n {slots.footerActions}\n {backHref && (\n <a href={backHref}>\n <Button type=\"button\" variant=\"ghost\" disabled={busy}>\n {t('form.back')}\n </Button>\n </a>\n )}\n </Stack>\n )}\n\n {slots.rest}\n </Stack>\n\n {pending && (\n <ConfirmDialog\n open\n tone={pending.confirm.tone}\n title={translateKey(pending.labelKey)}\n message={translateKey(pending.confirm.messageKey)}\n busy={busy}\n onCancel={() => setPending(undefined)}\n onConfirm={() => {\n const key = pending.key;\n setPending(undefined);\n onUseCase?.(key);\n }}\n />\n )}\n </Card>\n );\n}\n\n/**\n * A member the detail grid renders rather than the field stack.\n *\n * The `childType` half is not defensive: a `composition` that declared no child\n * has no columns, so there is nothing for a grid to draw. It keeps its place in\n * the field stack and reads as its row count, which is what it did before this\n * control existed — an honest \"some rows\" rather than an empty table implying\n * there are none.\n */\nfunction isOwnedCollection<TEntity extends Entity>(\n field: EntityFormField<TEntity>,\n): boolean {\n return field.type === 'composition' && field.childType !== undefined;\n}\n\n/**\n * Refuse a `linkSources` entry that names a member no picker can be built for.\n *\n * `FieldRow` asks for {@link PICKABLE_TYPES} before it builds an editor, so a\n * source handed to anything else used to fall through to the read-only display\n * or a plain `FieldControl` with nothing said: the caller wired a picker, no\n * picker appeared, and the field was indistinguishable from one the entity had\n * declared read-only. That is a wiring mistake rather than a state — the entry\n * is dead in *every* shape such a field can render, since an\n * `<EntityField render>` slot is handed the draft and never the source — so it\n * costs the render instead of a warning nobody reads. `useEntityLinkSource`\n * already throws `EntifixLogicError` at render for the sibling mistake (a search\n * property the target does not declare `filterable`); this is the same fault\n * caught one level up.\n *\n * Two messages, because the two faults are not the same thing. A\n * `linkCollection` is a member the editor has simply not been built for yet\n * (#26), so the fix is to wait or to point at the to-one you meant. Any other\n * type is a member that can never name another record at all, so the fix is to\n * remove the entry.\n *\n * Here rather than inside `FieldRow`, and that is the whole reason it is a\n * separate pass: a row only reaches its editor branch in **edit** mode, so a\n * per-row check would stay silent on a form that opens in `read` — the default\n * whenever there is a record — and then throw on a click, minutes later. One\n * pass over the registry fires on the first render either way.\n *\n * Against the resolved fields rather than the raw metadata: a slot may drop a\n * member, and a source left behind for a field that no longer renders is not\n * worth a page.\n */\nfunction assertLinkSourcesAreEditable<TEntity extends Entity>(\n fields: Array<EntityFormField<TEntity>>,\n // Same reason as the prop's own declaration: a source's target is another\n // entity entirely and cannot be expressed in terms of `TEntity`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n linkSources: Record<string, EntityLinkSource<any>> | undefined,\n): void {\n if (linkSources === undefined) return;\n\n const sourced = fields.filter(\n field =>\n linkSources[field.name] !== undefined && !PICKABLE_TYPES.has(field.type),\n );\n if (sourced.length === 0) return;\n\n const toMany = sourced\n .filter(field => field.type === 'linkCollection')\n .map(field => field.name);\n if (toMany.length > 0) {\n throw new EntifixLogicError(\n `EntityForm was given a link source for a to-many member: ${toMany.join(', ')}. ` +\n 'A `linkCollection` has no editor yet, so the source can only be dropped ' +\n 'and the field would render read-only with no sign anything was wired. ' +\n 'Remove the entry, or point it at the to-one `link` you meant.',\n undefined,\n { fields: toMany },\n );\n }\n\n const owned = sourced\n .filter(field => field.type === 'composition')\n .map(field => field.name);\n if (owned.length > 0) {\n throw new EntifixLogicError(\n `EntityForm was given a link source for an owned collection: ${owned.join(', ')}. ` +\n 'A `composition` is not a reference — its rows have no life outside this ' +\n 'record and are never picked from existing ones, so there is nothing for a ' +\n 'picker to look up. The detail grid that edits them is #122.',\n undefined,\n { fields: owned },\n );\n }\n\n const unpickable = sourced.map(field => `${field.name} (${field.type})`);\n throw new EntifixLogicError(\n `EntityForm was given a link source for a member that cannot hold one: ${unpickable.join(', ')}. ` +\n 'A picker writes the target’s id into the draft, so the member has to be a ' +\n '`link` or the `string` that carries a foreign key. Remove the entry, or ' +\n 'point it at the member that actually holds the reference.',\n undefined,\n { fields: sourced.map(field => field.name) },\n );\n}\n\ninterface FieldRowProps<TEntity extends Entity> {\n field: EntityFormField<TEntity>;\n entity: TEntity | undefined;\n draft: EntityDraft;\n value: string;\n editing: boolean;\n error: string | undefined;\n setField: (name: string, value: EntityDraftValue) => void;\n // The target of a relation is a different entity than the form's own.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n linkSource: EntityLinkSource<any> | undefined;\n onLinkChange:\n ((name: string, entity: Entity | undefined) => void) | undefined;\n id: string;\n}\n\n/**\n * One label + control (or value) row. A `readonly` member renders its read\n * display even in edit mode, and so does a relation with no source; everything\n * else edits through `FieldControl` — or, when a source was supplied for a\n * member in {@link PICKABLE_TYPES}, through `EntityLinkInput`. A boolean edited\n * inline carries its own label, so the row does not add a second one.\n *\n * The source branch sits above the `virtual || isRelation` fallback and below\n * `field.render`, which is what lets a slot still override a picked field.\n */\nfunction FieldRow<TEntity extends Entity>({\n field,\n entity,\n draft,\n value,\n editing,\n error,\n setField,\n linkSource,\n onLinkChange,\n id,\n}: FieldRowProps<TEntity>) {\n const readNode: ReactNode = field.readRender ? (\n field.readRender(entity)\n ) : (\n <CellValue\n value={\n entity ? (entity as Record<string, unknown>)[field.name] : undefined\n }\n descriptor={field}\n />\n );\n\n // Members with no editor of their own here: a to-one `link` whose picker was\n // never wired, a `linkCollection` (#26) and a `composition` (#122). All three\n // fall back to the read display, which is honest — a disabled text box\n // holding `[object Object]` is not.\n const isRelation =\n field.type === 'link' ||\n field.type === 'linkCollection' ||\n field.type === 'composition';\n\n let control: ReactNode;\n if (!editing) {\n control = readNode;\n } else if (field.render) {\n control = field.render({ draft, value, setField, id });\n } else if (linkSource && PICKABLE_TYPES.has(field.type)) {\n control = (\n <EntityLinkInput\n descriptor={field}\n value={value}\n source={linkSource}\n id={id}\n disabled={field.readonly}\n onSelect={target => {\n setField(field.name, target.id == null ? '' : String(target.id));\n onLinkChange?.(field.name, target);\n }}\n onClear={() => {\n setField(field.name, '');\n onLinkChange?.(field.name, undefined);\n }}\n />\n );\n } else if (field.virtual || isRelation) {\n // A relation with no source has no input to offer, and a virtual field has\n // no member to edit unless a `render` was supplied — both fall back to the\n // read display.\n control = readNode;\n } else {\n control = (\n <FieldControl\n descriptor={field}\n value={value}\n onChange={next => setField(field.name, next)}\n id={id}\n />\n );\n }\n\n const ownsLabel =\n editing && field.type === 'boolean' && !field.render && !field.virtual;\n\n return (\n <Stack gap=\"3xs\">\n {!ownsLabel && (\n <label htmlFor={id} className=\"text-step-sm text-content-muted\">\n {field.label}\n </label>\n )}\n {control}\n {error && (\n <span role=\"alert\" className=\"text-step-sm text-danger\">\n {error}\n </span>\n )}\n </Stack>\n );\n}\n"],"names":["cloneEntityDraft","describeEntityColumns","EntifixLogicError","readDraftString","readRowDrafts","useId","useState","useErrorMessage","useLocalizedDescriptors","useT","useTranslateKey","OVERFLOW_GLYPH","useCasesForSurface","Button","CellValue","FieldControl","Skeleton","Text","Card","ConfirmDialog","EntityLinkInput","LoadingBoundary","Menu","Stack","EntityDetailGrid","readEntityFormFields","resolveEntityFormFields","PICKABLE_TYPES","Set","VISIBLE_ACTION_LIMIT","EntityForm","entityConstructor","entity","values","onFieldChange","linkSources","onLinkChange","mode","modeProp","defaultMode","onModeChange","errors","formError","onSubmit","onDelete","embedded","isLoading","skeleton","isSaving","isDeleting","error","backHref","title","metadata","isMetadataLoading","onUseCase","onClone","children","formId","slots","columnDescriptors","described","resolved","fields","assertLinkSourcesAreEditable","filter","field","isOwnedCollection","ownedCollections","customSkeleton","undefined","showSkeleton","internalMode","setInternalMode","editing","draft","setField","name","value","toggleMode","next","t","translateKey","errorMessage","busy","resolvingLinks","Object","some","source","selected","may","action","actions","includes","declaredHeaderUseCases","useCases","declaredFooterUseCases","headerUseCases","footerUseCases","pending","setPending","invoke","descriptor","confirm","key","labelKey","useCaseButton","type","variant","tone","size","placement","disabled","onClick","useCaseMenuItem","Item","withOverflow","descriptors","length","map","visible","slice","folded","Trigger","aria-label","Items","gap","direction","align","as","step","weight","lines","headerActions","span","role","aria-live","className","p","data-testid","shape","FieldRow","linkSource","id","rows","onRowsChange","footerActions","a","href","rest","open","message","messageKey","onCancel","onConfirm","childType","sourced","has","toMany","join","owned","unpickable","readNode","readRender","isRelation","control","render","readonly","onSelect","target","String","onClear","virtual","onChange","ownsLabel","label","htmlFor"],"mappings":"AAAA;;AAEA,SACEA,gBAAgB,EAChBC,qBAAqB,EACrBC,iBAAiB,EAOjBC,eAAe,EACfC,aAAa,QAER,gBAAgB;AACvB,SAAyBC,KAAK,EAAEC,QAAQ,QAAQ,QAAQ;AAExD,SACEC,eAAe,EACfC,uBAAuB,EACvBC,IAAI,EACJC,eAAe,QACV,yBAAyB;AAChC,SAASC,cAAc,EAAEC,kBAAkB,QAAQ,yBAAyB;AAC5E,SAASC,MAAM,QAAQ,8BAA8B;AACrD,SAASC,SAAS,QAAQ,kCAAkC;AAC5D,SAASC,YAAY,QAAQ,qCAAqC;AAClE,SAASC,QAAQ,QAAQ,gCAAgC;AACzD,SAASC,IAAI,QAAQ,4BAA4B;AACjD,SAASC,IAAI,QAAQ,gCAAgC;AACrD,SAASC,aAAa,QAAQ,0CAA0C;AACxE,SAASC,eAAe,QAAQ,6CAA6C;AAC7E,SAASC,eAAe,QAAQ,4CAA4C;AAC5E,SAASC,IAAI,QAAQ,gCAAgC;AACrD,SAASC,KAAK,QAAQ,iCAAiC;AACvD,SAASC,gBAAgB,QAAQ,iCAAiC;AAMlE,SAASC,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,uBAAuB,QAAQ,8BAA8B;AAEtE;;;;;;;;;;;;;;;;CAgBC,GACD,MAAMC,iBAAgD,IAAIC,IACxD;IAAC;IAAQ;CAAS;AAGpB;;;;;;;;;;;;;;;;;;;CAmBC,GACD;;;;;;CAMC,GACD,MAAMC,uBAAuB;AAS7B,OAAO,SAASC,WAAmC,EACjDC,iBAAiB,EACjBC,MAAM,EACNC,MAAM,EACNC,aAAa,EACbC,WAAW,EACXC,YAAY,EACZC,MAAMC,QAAQ,EACdC,WAAW,EACXC,YAAY,EACZC,MAAM,EACNC,SAAS,EACTC,QAAQ,EACRC,QAAQ,EACRC,WAAW,KAAK,EAChBC,YAAY,KAAK,EACjBC,WAAW,IAAI,EACfC,WAAW,KAAK,EAChBC,aAAa,KAAK,EAClBC,KAAK,EACLC,QAAQ,EACRC,KAAK,EACLC,QAAQ,EACRC,oBAAoB,KAAK,EACzBC,SAAS,EACTC,OAAO,EACPC,QAAQ,EACiB;IACzB,MAAMC,SAASrD;IACf,MAAMsD,QAAQlC,qBAA8BgC;IAC5C,4EAA4E;IAC5E,6EAA6E;IAC7E,0EAA0E;IAC1E,MAAMG,oBAAoB3D,sBACxB8B,mBACAC;IAEF,yEAAyE;IACzE,MAAM6B,YAAYrD,wBAAwBoD;IAC1C,MAAME,WAAWpC,wBAAwBmC,WAAWF,MAAMI,MAAM;IAChEC,6BAA6BF,UAAU3B;IAEvC,6EAA6E;IAC7E,4EAA4E;IAC5E,wEAAwE;IACxE,2EAA2E;IAC3E,0EAA0E;IAC1E,kEAAkE;IAClE,MAAM4B,SAASD,SAASG,MAAM,CAACC,CAAAA,QAAS,CAACC,kBAAkBD;IAC3D,MAAME,mBAAmBN,SAASG,MAAM,CAACE;IAEzC;;;;;;GAMC,GACD,MAAME,iBAAiB,OAAOtB,aAAa,YAAYuB,YAAYvB;IACnE,MAAMwB,eAAezB,aAAaC,aAAa;IAE/C,MAAM,CAACyB,cAAcC,gBAAgB,GAAGnE,SACtCiC,sBAAAA,cAAgBP,SAAS,SAAS;IAEpC,MAAMK,OAAOC,mBAAAA,WAAYkC;IACzB,MAAME,UAAUrC,SAAS;IAEzB,MAAMsC,QAAqB1C,iBAAAA,SAAU,CAAC;IACtC,MAAM2C,WAAW,CAACC,MAAcC,QAC9B5C,iCAAAA,cAAgB2C,MAAMC;IAExB,MAAMC,aAAa;QACjB,MAAMC,OAAuBN,UAAU,SAAS;QAChDD,gBAAgBO;QAChBxC,gCAAAA,aAAewC;IACjB;IAEA,MAAMC,IAAIxE;IACV,MAAMyE,eAAexE;IACrB,MAAMyE,eAAe5E;IACrB,MAAM6E,OAAOpC,YAAYC;IAEzB,8EAA8E;IAC9E,8EAA8E;IAC9E,8EAA8E;IAC9E,2EAA2E;IAC3E,wEAAwE;IACxE,EAAE;IACF,kEAAkE;IAClE,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAMoC,iBAAiBC,OAAOrD,MAAM,CAACE,sBAAAA,cAAe,CAAC,GAAGoD,IAAI,CAC1DC,CAAAA,SAAUA,OAAOC,QAAQ,CAAC3C,SAAS;IAGrC,2EAA2E;IAC3E,2EAA2E;IAC3E,uDAAuD;IACvD,MAAM4C,MAAM,CAACC,SACXtC,aAAaiB,aAAajB,SAASuC,OAAO,CAACC,QAAQ,CAACF;IAEtD,6EAA6E;IAC7E,mEAAmE;IACnE,yEAAyE;IACzE,6EAA6E;IAC7E,yDAAyD;IACzD,EAAE;IACF,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,4EAA4E;IAC5E,sEAAsE;IACtE,8EAA8E;IAC9E,2CAA2C;IAC3C,EAAE;IACF,8EAA8E;IAC9E,6CAA6C;IAC7C,MAAMG,yBAAyBlF,mBAC7B,eACAyC,4BAAAA,SAAU0C,QAAQ;IAEpB,MAAMC,yBAAyBpF,mBAC7B,eACAyC,4BAAAA,SAAU0C,QAAQ;IAEpB,MAAME,iBAAiB1C,YAAYuC,yBAAyB,EAAE;IAC9D,MAAMI,iBAAiB3C,YAAYyC,yBAAyB,EAAE;IAE9D,uEAAuE;IACvE,yEAAyE;IACzE,0EAA0E;IAC1E,8CAA8C;IAC9C,MAAM,CAACG,SAASC,WAAW,GAAG9F,SAC5BgE;IAEF,MAAM+B,SAAS,CAACC;QACd,MAAMC,UAAUD,WAAWC,OAAO;QAClC,IAAIA,SAAS;YACXH,WAAW;gBACTI,KAAKF,WAAWE,GAAG;gBACnBC,UAAUH,WAAWG,QAAQ;gBAC7BF;YACF;YACA;QACF;QACAhD,6BAAAA,UAAY+C,WAAWE,GAAG;IAC5B;IAEA,MAAME,gBAAgB,CAACJ;YAKjBA;6BAJJ,KAACzF;YAEC8F,MAAK;YACLC,SACEN,EAAAA,sBAAAA,WAAWC,OAAO,qBAAlBD,oBAAoBO,IAAI,MAAK,gBAAgB,gBAAgB;YAE/DC,MAAMR,WAAWS,SAAS,KAAK,wBAAwB,OAAO;YAC9DC,UAAU5B;YACV6B,SAAS,IAAMZ,OAAOC;sBAKrBpB,aAAaoB,WAAWG,QAAQ;WAZ5BH,WAAWE,GAAG;;IAgBvB,MAAMU,kBAAkB,CAACZ;YAInBA;6BAHJ,KAAChF,KAAK6F,IAAI;YAERN,MACEP,EAAAA,sBAAAA,WAAWC,OAAO,qBAAlBD,oBAAoBO,IAAI,MAAK,gBAAgB,gBAAgB;YAE/DG,UAAU5B;YACV6B,SAAS,IAAMZ,OAAOC;sBAErBpB,aAAaoB,WAAWG,QAAQ;WAP5BH,WAAWE,GAAG;;IAWvB;;;;;;;;;;;;GAYC,GACD,MAAMY,eAAe,CAACC;QACpB,IAAIA,YAAYC,MAAM,IAAIzF,sBAAsB;YAC9C,OAAOwF,YAAYE,GAAG,CAACb;QACzB;QAEA,MAAMc,UAAUH,YAAYI,KAAK,CAAC,GAAG5F;QACrC,MAAM6F,SAASL,YAAYI,KAAK,CAAC5F;QAEjC,OAAO;eACF2F,QAAQD,GAAG,CAACb;0BACf,MAACpF;;kCACC,KAACA,KAAKqG,OAAO;wBAACC,cAAY3C,EAAE;kCACzBtE;;kCAEH,KAACW,KAAKuG,KAAK;kCAAEH,OAAOH,GAAG,CAACL;;;eAJhB;SAMX;IACH;IAEA,qBACE,MAAChG;;0BACC,MAACK;gBAAMuG,KAAI;;oBAKR,CAACjF,0BACA,MAACtB;wBAAMwG,WAAU;wBAAMD,KAAI;wBAAKE,OAAM;;0CACpC,KAAC/G;gCAAKgH,IAAG;gCAAKC,MAAM;gCAAGC,QAAO;0CAK3B/E,gBAAAA,QACEpB,UAAUc,YAAYmC,EAAE,kBAAkBA,EAAE;;4BAIhD3C,aAAagC,aAAatC,wBACzB,KAACnB;gCACC8F,MAAK;gCACLC,SAAQ;gCACRE,MAAK;gCACLG,SAASlC;0CAERL,UAAUO,EAAE,eAAeA,EAAE;;0CAGlC,KAAC5D;gCAAgByB,WAAWQ;gCAAmB8E,OAAO;0CACpD,cAAA;;wCACGhB,aAAanB;wCACbtC,MAAM0E,aAAa;;;;;;kCAO5B,KAACC;wBAAKC,MAAK;wBAASC,aAAU;wBAASC,WAAU;kCAC9C3F,YAAYmC,EAAE,kBAAkB;;oBAGlC/B,uBACC,KAACwF;wBACCH,MAAK;wBACLI,eAAY;wBACZF,WAAU;kCAETtD,aAAajC;;oBAQjBqB,eACIF,yBAAAA,iBACDN,OAAOwD,GAAG,CAACrD,CAAAA,sBACT,MAAC3C;4BAAuBuG,KAAI;;8CAC1B,KAAC9G;oCAAS4H,OAAM;oCAAOH,WAAU;;8CACjC,KAACzH;oCAASyH,WAAU;;;2BAFVvE,MAAMW,IAAI,KAKxBd,OAAOwD,GAAG,CAACrD,CAAAA,sBACT,KAAC2E;4BAEC3E,OAAOA;4BACPlC,QAAQA;4BACR2C,OAAOA;4BACPG,OAAO3E,gBAAgBwE,OAAOT,MAAMW,IAAI;4BACxCH,SAASA;4BACTxB,OAAOwB,UAAUjC,0BAAAA,MAAQ,CAACyB,MAAMW,IAAI,CAAC,GAAGP;4BACxCM,UAAUA;4BACVkE,UAAU,EAAE3G,+BAAAA,WAAa,CAAC+B,MAAMW,IAAI,CAAC;4BACrCzC,cAAcA;4BACd2G,IAAI,GAAGrF,OAAO,CAAC,EAAEQ,MAAMW,IAAI,EAAE;2BAVxBX,MAAMW,IAAI;oBAkBtBT,iBAAiBmD,GAAG,CAACrD,CAAAA,sBACpB,KAAC1C;4BAEC8E,YAAYpC;4BACZ8E,MAAM5I,cAAcuE,KAAK,CAACT,MAAMW,IAAI,CAAC;4BACrCoE,cAAcD,CAAAA,OAAQpE,SAASV,MAAMW,IAAI,EAAEmE;4BAC3CvG,QAAQiC,UAAUjC,SAAS6B;4BAC3BI,SAASA;4BACT5B,WAAWA;4BACXC,UAAUA;2BAPLmB,MAAMW,IAAI;oBAalBH,WAAWhC,2BACV,KAAC4F;wBAAKC,MAAK;wBAAQE,WAAU;kCAC1B/F;;oBAIJgC,WAAW,CAAC7B,0BACX,MAACtB;wBAAMwG,WAAU;wBAAMD,KAAI;;4BACxBpC,IAAI,0BACH,KAAC7E;gCACC8F,MAAK;gCACLM,SAAS,IAAMtE,4BAAAA,SAAWgC;gCAC1BqC,UAAU5B,QAAQC;0CAEjBrC,WAAWiC,EAAE,iBAAiBA,EAAE;;4BAGpCrC,YAAY8C,IAAI,2BACf,KAAC7E;gCACC8F,MAAK;gCACLC,SAAQ;gCACRK,SAASrE;gCACToE,UAAU5B;0CAETnC,aAAagC,EAAE,mBAAmBA,EAAE;;4BAGxCmC,aAAalB;4BAKb1C,WAAWxB,UAAU0D,IAAI,0BACxB,KAAC7E;gCACC8F,MAAK;gCACLC,SAAQ;gCACRI,UAAU5B;gCACV6B,SAAS,IACPzD,QAAQxD,iBAAiB+B,mBAAmB4C;0CAG7CM,EAAE;;4BAGNtB,MAAMuF,aAAa;4BACnB/F,0BACC,KAACgG;gCAAEC,MAAMjG;0CACP,cAAA,KAACtC;oCAAO8F,MAAK;oCAASC,SAAQ;oCAAQI,UAAU5B;8CAC7CH,EAAE;;;;;oBAOZtB,MAAM0F,IAAI;;;YAGZlD,yBACC,KAAChF;gBACCmI,IAAI;gBACJzC,MAAMV,QAAQI,OAAO,CAACM,IAAI;gBAC1BzD,OAAO8B,aAAaiB,QAAQM,QAAQ;gBACpC8C,SAASrE,aAAaiB,QAAQI,OAAO,CAACiD,UAAU;gBAChDpE,MAAMA;gBACNqE,UAAU,IAAMrD,WAAW9B;gBAC3BoF,WAAW;oBACT,MAAMlD,MAAML,QAAQK,GAAG;oBACvBJ,WAAW9B;oBACXf,6BAAAA,UAAYiD;gBACd;;;;AAKV;AAEA;;;;;;;;CAQC,GACD,SAASrC,kBACPD,KAA+B;IAE/B,OAAOA,MAAMyC,IAAI,KAAK,iBAAiBzC,MAAMyF,SAAS,KAAKrF;AAC7D;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BC,GACD,SAASN,6BACPD,MAAuC,EACvC,0EAA0E;AAC1E,iEAAiE;AACjE,8DAA8D;AAC9D5B,WAA8D;IAE9D,IAAIA,gBAAgBmC,WAAW;IAE/B,MAAMsF,UAAU7F,OAAOE,MAAM,CAC3BC,CAAAA,QACE/B,WAAW,CAAC+B,MAAMW,IAAI,CAAC,KAAKP,aAAa,CAAC3C,eAAekI,GAAG,CAAC3F,MAAMyC,IAAI;IAE3E,IAAIiD,QAAQtC,MAAM,KAAK,GAAG;IAE1B,MAAMwC,SAASF,QACZ3F,MAAM,CAACC,CAAAA,QAASA,MAAMyC,IAAI,KAAK,kBAC/BY,GAAG,CAACrD,CAAAA,QAASA,MAAMW,IAAI;IAC1B,IAAIiF,OAAOxC,MAAM,GAAG,GAAG;QACrB,MAAM,IAAIpH,kBACR,CAAC,yDAAyD,EAAE4J,OAAOC,IAAI,CAAC,MAAM,EAAE,CAAC,GAC/E,6EACA,2EACA,iEACFzF,WACA;YAAEP,QAAQ+F;QAAO;IAErB;IAEA,MAAME,QAAQJ,QACX3F,MAAM,CAACC,CAAAA,QAASA,MAAMyC,IAAI,KAAK,eAC/BY,GAAG,CAACrD,CAAAA,QAASA,MAAMW,IAAI;IAC1B,IAAImF,MAAM1C,MAAM,GAAG,GAAG;QACpB,MAAM,IAAIpH,kBACR,CAAC,4DAA4D,EAAE8J,MAAMD,IAAI,CAAC,MAAM,EAAE,CAAC,GACjF,6EACA,+EACA,+DACFzF,WACA;YAAEP,QAAQiG;QAAM;IAEpB;IAEA,MAAMC,aAAaL,QAAQrC,GAAG,CAACrD,CAAAA,QAAS,GAAGA,MAAMW,IAAI,CAAC,EAAE,EAAEX,MAAMyC,IAAI,CAAC,CAAC,CAAC;IACvE,MAAM,IAAIzG,kBACR,CAAC,sEAAsE,EAAE+J,WAAWF,IAAI,CAAC,MAAM,EAAE,CAAC,GAChG,+EACA,6EACA,6DACFzF,WACA;QAAEP,QAAQ6F,QAAQrC,GAAG,CAACrD,CAAAA,QAASA,MAAMW,IAAI;IAAE;AAE/C;AAkBA;;;;;;;;;CASC,GACD,SAASgE,SAAiC,EACxC3E,KAAK,EACLlC,MAAM,EACN2C,KAAK,EACLG,KAAK,EACLJ,OAAO,EACPxB,KAAK,EACL0B,QAAQ,EACRkE,UAAU,EACV1G,YAAY,EACZ2G,EAAE,EACqB;IACvB,MAAMmB,WAAsBhG,MAAMiG,UAAU,GAC1CjG,MAAMiG,UAAU,CAACnI,wBAEjB,KAAClB;QACCgE,OACE9C,SAAS,AAACA,MAAkC,CAACkC,MAAMW,IAAI,CAAC,GAAGP;QAE7DgC,YAAYpC;;IAIhB,6EAA6E;IAC7E,8EAA8E;IAC9E,uEAAuE;IACvE,oCAAoC;IACpC,MAAMkG,aACJlG,MAAMyC,IAAI,KAAK,UACfzC,MAAMyC,IAAI,KAAK,oBACfzC,MAAMyC,IAAI,KAAK;IAEjB,IAAI0D;IACJ,IAAI,CAAC3F,SAAS;QACZ2F,UAAUH;IACZ,OAAO,IAAIhG,MAAMoG,MAAM,EAAE;QACvBD,UAAUnG,MAAMoG,MAAM,CAAC;YAAE3F;YAAOG;YAAOF;YAAUmE;QAAG;IACtD,OAAO,IAAID,cAAcnH,eAAekI,GAAG,CAAC3F,MAAMyC,IAAI,GAAG;QACvD0D,wBACE,KAACjJ;YACCkF,YAAYpC;YACZY,OAAOA;YACPU,QAAQsD;YACRC,IAAIA;YACJ/B,UAAU9C,MAAMqG,QAAQ;YACxBC,UAAUC,CAAAA;gBACR7F,SAASV,MAAMW,IAAI,EAAE4F,OAAO1B,EAAE,IAAI,OAAO,KAAK2B,OAAOD,OAAO1B,EAAE;gBAC9D3G,gCAAAA,aAAe8B,MAAMW,IAAI,EAAE4F;YAC7B;YACAE,SAAS;gBACP/F,SAASV,MAAMW,IAAI,EAAE;gBACrBzC,gCAAAA,aAAe8B,MAAMW,IAAI,EAAEP;YAC7B;;IAGN,OAAO,IAAIJ,MAAM0G,OAAO,IAAIR,YAAY;QACtC,2EAA2E;QAC3E,2EAA2E;QAC3E,gBAAgB;QAChBC,UAAUH;IACZ,OAAO;QACLG,wBACE,KAACtJ;YACCuF,YAAYpC;YACZY,OAAOA;YACP+F,UAAU7F,CAAAA,OAAQJ,SAASV,MAAMW,IAAI,EAAEG;YACvC+D,IAAIA;;IAGV;IAEA,MAAM+B,YACJpG,WAAWR,MAAMyC,IAAI,KAAK,aAAa,CAACzC,MAAMoG,MAAM,IAAI,CAACpG,MAAM0G,OAAO;IAExE,qBACE,MAACrJ;QAAMuG,KAAI;;YACR,CAACgD,2BACA,KAACC;gBAAMC,SAASjC;gBAAIN,WAAU;0BAC3BvE,MAAM6G,KAAK;;YAGfV;YACAnH,uBACC,KAACoF;gBAAKC,MAAK;gBAAQE,WAAU;0BAC1BvF;;;;AAKX"}