@coffer-org/web-ui 4.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 (387) hide show
  1. package/README.md +87 -0
  2. package/dist/Markdown.d.ts +4 -0
  3. package/dist/Markdown.js +13 -0
  4. package/dist/MarkdownEditor.d.ts +6 -0
  5. package/dist/MarkdownEditor.js +83 -0
  6. package/dist/actions/ActionButton.d.ts +7 -0
  7. package/dist/actions/ActionButton.js +54 -0
  8. package/dist/actions/PopupBody.d.ts +4 -0
  9. package/dist/actions/PopupBody.js +8 -0
  10. package/dist/actions/TemplateHost.d.ts +4 -0
  11. package/dist/actions/TemplateHost.js +36 -0
  12. package/dist/actions/registry.d.ts +20 -0
  13. package/dist/actions/registry.js +9 -0
  14. package/dist/components/ExtendReasonInfo.d.ts +6 -0
  15. package/dist/components/ExtendReasonInfo.js +12 -0
  16. package/dist/components/FavoriteButton.d.ts +8 -0
  17. package/dist/components/FavoriteButton.js +7 -0
  18. package/dist/components/Icon.d.ts +6 -0
  19. package/dist/components/Icon.js +12 -0
  20. package/dist/components/PageBody.d.ts +4 -0
  21. package/dist/components/PageBody.js +4 -0
  22. package/dist/components/RecordInline.d.ts +8 -0
  23. package/dist/components/RecordInline.js +29 -0
  24. package/dist/components/SaveStatus.d.ts +1 -0
  25. package/dist/components/SaveStatus.js +11 -0
  26. package/dist/components/Toolbar.d.ts +5 -0
  27. package/dist/components/Toolbar.js +4 -0
  28. package/dist/components/icons/color.d.ts +2 -0
  29. package/dist/components/icons/color.js +10 -0
  30. package/dist/components/icons/flag.d.ts +2 -0
  31. package/dist/components/icons/flag.js +6 -0
  32. package/dist/components/icons/lucide.d.ts +2 -0
  33. package/dist/components/icons/lucide.js +111 -0
  34. package/dist/components/icons/registry.d.ts +4 -0
  35. package/dist/components/icons/registry.js +22 -0
  36. package/dist/components/icons/simple.d.ts +2 -0
  37. package/dist/components/icons/simple.js +15 -0
  38. package/dist/components/icons/tabler.d.ts +2 -0
  39. package/dist/components/icons/tabler.js +11 -0
  40. package/dist/components/ui/FieldLabel.d.ts +9 -0
  41. package/dist/components/ui/FieldLabel.js +4 -0
  42. package/dist/components/ui/badge.d.ts +9 -0
  43. package/dist/components/ui/badge.js +19 -0
  44. package/dist/components/ui/button.d.ts +11 -0
  45. package/dist/components/ui/button.js +33 -0
  46. package/dist/components/ui/calendar.d.ts +8 -0
  47. package/dist/components/ui/calendar.js +72 -0
  48. package/dist/components/ui/card.d.ts +8 -0
  49. package/dist/components/ui/card.js +16 -0
  50. package/dist/components/ui/checkbox.d.ts +4 -0
  51. package/dist/components/ui/checkbox.js +8 -0
  52. package/dist/components/ui/chip-cls.d.ts +1 -0
  53. package/dist/components/ui/chip-cls.js +1 -0
  54. package/dist/components/ui/combobox.d.ts +24 -0
  55. package/dist/components/ui/combobox.js +58 -0
  56. package/dist/components/ui/confirm.d.ts +10 -0
  57. package/dist/components/ui/confirm.js +37 -0
  58. package/dist/components/ui/date-picker.d.ts +5 -0
  59. package/dist/components/ui/date-picker.js +16 -0
  60. package/dist/components/ui/dialog.d.ts +16 -0
  61. package/dist/components/ui/dialog.js +27 -0
  62. package/dist/components/ui/dropdown-menu.d.ts +15 -0
  63. package/dist/components/ui/dropdown-menu.js +18 -0
  64. package/dist/components/ui/input-group.d.ts +16 -0
  65. package/dist/components/ui/input-group.js +56 -0
  66. package/dist/components/ui/input.d.ts +3 -0
  67. package/dist/components/ui/input.js +6 -0
  68. package/dist/components/ui/label.d.ts +4 -0
  69. package/dist/components/ui/label.js +7 -0
  70. package/dist/components/ui/mask-input.d.ts +61 -0
  71. package/dist/components/ui/mask-input.js +1052 -0
  72. package/dist/components/ui/month-year-picker.d.ts +10 -0
  73. package/dist/components/ui/month-year-picker.js +46 -0
  74. package/dist/components/ui/option-icon.d.ts +15 -0
  75. package/dist/components/ui/option-icon.js +19 -0
  76. package/dist/components/ui/phone-input.d.ts +13 -0
  77. package/dist/components/ui/phone-input.js +53 -0
  78. package/dist/components/ui/popover.d.ts +11 -0
  79. package/dist/components/ui/popover.js +28 -0
  80. package/dist/components/ui/rating.d.ts +44 -0
  81. package/dist/components/ui/rating.js +501 -0
  82. package/dist/components/ui/scroll-area.d.ts +5 -0
  83. package/dist/components/ui/scroll-area.js +11 -0
  84. package/dist/components/ui/select-combobox.d.ts +25 -0
  85. package/dist/components/ui/select-combobox.js +36 -0
  86. package/dist/components/ui/select.d.ts +13 -0
  87. package/dist/components/ui/select.js +24 -0
  88. package/dist/components/ui/separator.d.ts +4 -0
  89. package/dist/components/ui/separator.js +7 -0
  90. package/dist/components/ui/switch.d.ts +4 -0
  91. package/dist/components/ui/switch.js +7 -0
  92. package/dist/components/ui/textarea.d.ts +3 -0
  93. package/dist/components/ui/textarea.js +6 -0
  94. package/dist/components/ui/time-picker.d.ts +84 -0
  95. package/dist/components/ui/time-picker.js +1258 -0
  96. package/dist/components/visually-hidden-input.d.ts +10 -0
  97. package/dist/components/visually-hidden-input.js +96 -0
  98. package/dist/hooks/use-as-ref.d.ts +3 -0
  99. package/dist/hooks/use-as-ref.js +10 -0
  100. package/dist/hooks/use-isomorphic-layout-effect.d.ts +3 -0
  101. package/dist/hooks/use-isomorphic-layout-effect.js +3 -0
  102. package/dist/hooks/use-lazy-ref.d.ts +3 -0
  103. package/dist/hooks/use-lazy-ref.js +9 -0
  104. package/dist/hooks/use-media-query.d.ts +3 -0
  105. package/dist/hooks/use-media-query.js +26 -0
  106. package/dist/host-services.d.ts +47 -0
  107. package/dist/host-services.js +35 -0
  108. package/dist/index.d.ts +70 -0
  109. package/dist/index.js +69 -0
  110. package/dist/layout.d.ts +29 -0
  111. package/dist/layout.js +323 -0
  112. package/dist/lib/cat-color.d.ts +1 -0
  113. package/dist/lib/cat-color.js +7 -0
  114. package/dist/lib/compose-refs.d.ts +5 -0
  115. package/dist/lib/compose-refs.js +38 -0
  116. package/dist/lib/date-format.d.ts +9 -0
  117. package/dist/lib/date-format.js +31 -0
  118. package/dist/lib/format.d.ts +14 -0
  119. package/dist/lib/format.js +34 -0
  120. package/dist/lib/json.d.ts +1 -0
  121. package/dist/lib/json.js +12 -0
  122. package/dist/lib/multi-value.d.ts +3 -0
  123. package/dist/lib/multi-value.js +22 -0
  124. package/dist/lib/record-option.d.ts +7 -0
  125. package/dist/lib/record-option.js +52 -0
  126. package/dist/lib/use-record-labels.d.ts +14 -0
  127. package/dist/lib/use-record-labels.js +130 -0
  128. package/dist/lib/utils.d.ts +2 -0
  129. package/dist/lib/utils.js +5 -0
  130. package/dist/list-view.d.ts +26 -0
  131. package/dist/list-view.js +11 -0
  132. package/dist/markdown/blocks.d.ts +10 -0
  133. package/dist/markdown/blocks.js +57 -0
  134. package/dist/markdown/extensions.d.ts +6 -0
  135. package/dist/markdown/extensions.js +25 -0
  136. package/dist/markdown/slash.d.ts +23 -0
  137. package/dist/markdown/slash.js +27 -0
  138. package/dist/markdown/toolbar.d.ts +13 -0
  139. package/dist/markdown/toolbar.js +119 -0
  140. package/dist/plugin-ui.d.ts +43 -0
  141. package/dist/plugin-ui.js +37 -0
  142. package/dist/registry.d.ts +26 -0
  143. package/dist/registry.js +169 -0
  144. package/dist/render/blocks/accordion.d.ts +1 -0
  145. package/dist/render/blocks/accordion.js +15 -0
  146. package/dist/render/blocks/aside.d.ts +1 -0
  147. package/dist/render/blocks/aside.js +14 -0
  148. package/dist/render/blocks/balance.d.ts +1 -0
  149. package/dist/render/blocks/balance.js +14 -0
  150. package/dist/render/blocks/bento.d.ts +1 -0
  151. package/dist/render/blocks/bento.js +24 -0
  152. package/dist/render/blocks/block-shell.d.ts +15 -0
  153. package/dist/render/blocks/block-shell.js +20 -0
  154. package/dist/render/blocks/calendar.d.ts +1 -0
  155. package/dist/render/blocks/calendar.js +142 -0
  156. package/dist/render/blocks/callout.d.ts +1 -0
  157. package/dist/render/blocks/callout.js +21 -0
  158. package/dist/render/blocks/chart.d.ts +1 -0
  159. package/dist/render/blocks/chart.js +46 -0
  160. package/dist/render/blocks/compare.d.ts +1 -0
  161. package/dist/render/blocks/compare.js +16 -0
  162. package/dist/render/blocks/countdown.d.ts +1 -0
  163. package/dist/render/blocks/countdown.js +36 -0
  164. package/dist/render/blocks/deck.d.ts +1 -0
  165. package/dist/render/blocks/deck.js +29 -0
  166. package/dist/render/blocks/epigraph.d.ts +1 -0
  167. package/dist/render/blocks/epigraph.js +13 -0
  168. package/dist/render/blocks/facets.d.ts +1 -0
  169. package/dist/render/blocks/facets.js +23 -0
  170. package/dist/render/blocks/figure.d.ts +1 -0
  171. package/dist/render/blocks/figure.js +13 -0
  172. package/dist/render/blocks/grid.d.ts +1 -0
  173. package/dist/render/blocks/grid.js +21 -0
  174. package/dist/render/blocks/heatmap.d.ts +1 -0
  175. package/dist/render/blocks/heatmap.js +135 -0
  176. package/dist/render/blocks/idcard.d.ts +1 -0
  177. package/dist/render/blocks/idcard.js +30 -0
  178. package/dist/render/blocks/identity.d.ts +1 -0
  179. package/dist/render/blocks/identity.js +46 -0
  180. package/dist/render/blocks/index.d.ts +40 -0
  181. package/dist/render/blocks/index.js +40 -0
  182. package/dist/render/blocks/journal.d.ts +1 -0
  183. package/dist/render/blocks/journal.js +50 -0
  184. package/dist/render/blocks/ledger.d.ts +1 -0
  185. package/dist/render/blocks/ledger.js +23 -0
  186. package/dist/render/blocks/manifest.d.ts +1 -0
  187. package/dist/render/blocks/manifest.js +50 -0
  188. package/dist/render/blocks/masthead.d.ts +1 -0
  189. package/dist/render/blocks/masthead.js +15 -0
  190. package/dist/render/blocks/meter.d.ts +1 -0
  191. package/dist/render/blocks/meter.js +32 -0
  192. package/dist/render/blocks/nutrition.d.ts +1 -0
  193. package/dist/render/blocks/nutrition.js +27 -0
  194. package/dist/render/blocks/people.d.ts +1 -0
  195. package/dist/render/blocks/people.js +35 -0
  196. package/dist/render/blocks/plaque.d.ts +1 -0
  197. package/dist/render/blocks/plaque.js +15 -0
  198. package/dist/render/blocks/properties.d.ts +1 -0
  199. package/dist/render/blocks/properties.js +22 -0
  200. package/dist/render/blocks/prose.d.ts +1 -0
  201. package/dist/render/blocks/prose.js +17 -0
  202. package/dist/render/blocks/receipt.d.ts +1 -0
  203. package/dist/render/blocks/receipt.js +23 -0
  204. package/dist/render/blocks/registry.d.ts +16 -0
  205. package/dist/render/blocks/registry.js +7 -0
  206. package/dist/render/blocks/relation-source.d.ts +2 -0
  207. package/dist/render/blocks/relation-source.js +6 -0
  208. package/dist/render/blocks/route.d.ts +1 -0
  209. package/dist/render/blocks/route.js +23 -0
  210. package/dist/render/blocks/score.d.ts +1 -0
  211. package/dist/render/blocks/score.js +15 -0
  212. package/dist/render/blocks/series.d.ts +23 -0
  213. package/dist/render/blocks/series.js +57 -0
  214. package/dist/render/blocks/specimen.d.ts +1 -0
  215. package/dist/render/blocks/specimen.js +19 -0
  216. package/dist/render/blocks/split.d.ts +1 -0
  217. package/dist/render/blocks/split.js +15 -0
  218. package/dist/render/blocks/spread.d.ts +1 -0
  219. package/dist/render/blocks/spread.js +15 -0
  220. package/dist/render/blocks/stack.d.ts +1 -0
  221. package/dist/render/blocks/stack.js +15 -0
  222. package/dist/render/blocks/stats.d.ts +1 -0
  223. package/dist/render/blocks/stats.js +23 -0
  224. package/dist/render/blocks/status.d.ts +1 -0
  225. package/dist/render/blocks/status.js +18 -0
  226. package/dist/render/blocks/table.d.ts +11 -0
  227. package/dist/render/blocks/table.js +136 -0
  228. package/dist/render/blocks/tabs.d.ts +1 -0
  229. package/dist/render/blocks/tabs.js +17 -0
  230. package/dist/render/blocks/terminal.d.ts +1 -0
  231. package/dist/render/blocks/terminal.js +18 -0
  232. package/dist/render/blocks/timeline.d.ts +1 -0
  233. package/dist/render/blocks/timeline.js +31 -0
  234. package/dist/render/box.d.ts +5 -0
  235. package/dist/render/box.js +23 -0
  236. package/dist/render/chrome.d.ts +64 -0
  237. package/dist/render/chrome.js +92 -0
  238. package/dist/render/core/amount.d.ts +1 -0
  239. package/dist/render/core/amount.js +19 -0
  240. package/dist/render/core/attachment.d.ts +29 -0
  241. package/dist/render/core/attachment.js +102 -0
  242. package/dist/render/core/choice.d.ts +1 -0
  243. package/dist/render/core/choice.js +40 -0
  244. package/dist/render/core/composite.d.ts +1 -0
  245. package/dist/render/core/composite.js +132 -0
  246. package/dist/render/core/datetime.d.ts +2 -0
  247. package/dist/render/core/datetime.js +215 -0
  248. package/dist/render/core/dimensions.d.ts +1 -0
  249. package/dist/render/core/dimensions.js +44 -0
  250. package/dist/render/core/embed.d.ts +11 -0
  251. package/dist/render/core/embed.js +99 -0
  252. package/dist/render/core/file.d.ts +12 -0
  253. package/dist/render/core/file.js +238 -0
  254. package/dist/render/core/illustrated.d.ts +39 -0
  255. package/dist/render/core/illustrated.js +113 -0
  256. package/dist/render/core/index.d.ts +23 -0
  257. package/dist/render/core/index.js +23 -0
  258. package/dist/render/core/layout-elements.d.ts +1 -0
  259. package/dist/render/core/layout-elements.js +78 -0
  260. package/dist/render/core/localpath.d.ts +6 -0
  261. package/dist/render/core/localpath.js +73 -0
  262. package/dist/render/core/money.d.ts +1 -0
  263. package/dist/render/core/money.js +39 -0
  264. package/dist/render/core/number.d.ts +17 -0
  265. package/dist/render/core/number.js +104 -0
  266. package/dist/render/core/period.d.ts +1 -0
  267. package/dist/render/core/period.js +60 -0
  268. package/dist/render/core/range.d.ts +1 -0
  269. package/dist/render/core/range.js +55 -0
  270. package/dist/render/core/reminder.d.ts +2 -0
  271. package/dist/render/core/reminder.js +56 -0
  272. package/dist/render/core/source.d.ts +3 -0
  273. package/dist/render/core/source.js +65 -0
  274. package/dist/render/core/stepper.d.ts +1 -0
  275. package/dist/render/core/stepper.js +81 -0
  276. package/dist/render/core/storage-group.d.ts +1 -0
  277. package/dist/render/core/storage-group.js +30 -0
  278. package/dist/render/core/text.d.ts +15 -0
  279. package/dist/render/core/text.js +370 -0
  280. package/dist/render/core/tristate.d.ts +1 -0
  281. package/dist/render/core/tristate.js +42 -0
  282. package/dist/render/core/weight.d.ts +4 -0
  283. package/dist/render/core/weight.js +38 -0
  284. package/dist/render/dispatch.d.ts +12 -0
  285. package/dist/render/dispatch.js +53 -0
  286. package/dist/render/display-override.d.ts +25 -0
  287. package/dist/render/display-override.js +23 -0
  288. package/dist/render/editor-mode.d.ts +4 -0
  289. package/dist/render/editor-mode.js +11 -0
  290. package/dist/render/field-address.d.ts +14 -0
  291. package/dist/render/field-address.js +10 -0
  292. package/dist/render/field-errors.d.ts +8 -0
  293. package/dist/render/field-errors.js +25 -0
  294. package/dist/render/field-frame.d.ts +20 -0
  295. package/dist/render/field-frame.js +78 -0
  296. package/dist/render/field-scope.d.ts +8 -0
  297. package/dist/render/field-scope.js +25 -0
  298. package/dist/render/field-width.d.ts +7 -0
  299. package/dist/render/field-width.js +12 -0
  300. package/dist/render/form-types.d.ts +12 -0
  301. package/dist/render/form-types.js +1 -0
  302. package/dist/render/hybrid-scope.d.ts +5 -0
  303. package/dist/render/hybrid-scope.js +9 -0
  304. package/dist/render/image.d.ts +64 -0
  305. package/dist/render/image.js +322 -0
  306. package/dist/render/live-kind.d.ts +7 -0
  307. package/dist/render/live-kind.js +104 -0
  308. package/dist/render/markdown-view.d.ts +5 -0
  309. package/dist/render/markdown-view.js +17 -0
  310. package/dist/render/multi.d.ts +10 -0
  311. package/dist/render/multi.js +26 -0
  312. package/dist/render/multiple-chips.d.ts +24 -0
  313. package/dist/render/multiple-chips.js +18 -0
  314. package/dist/render/option-list.d.ts +15 -0
  315. package/dist/render/option-list.js +47 -0
  316. package/dist/render/option-value.d.ts +20 -0
  317. package/dist/render/option-value.js +41 -0
  318. package/dist/render/picker-scrim.d.ts +7 -0
  319. package/dist/render/picker-scrim.js +32 -0
  320. package/dist/render/picker-surface.d.ts +5 -0
  321. package/dist/render/picker-surface.js +9 -0
  322. package/dist/render/popover-field.d.ts +16 -0
  323. package/dist/render/popover-field.js +153 -0
  324. package/dist/render/record-save-ctx.d.ts +11 -0
  325. package/dist/render/record-save-ctx.js +41 -0
  326. package/dist/render/shared.d.ts +92 -0
  327. package/dist/render/shared.js +182 -0
  328. package/dist/render/slot.d.ts +45 -0
  329. package/dist/render/slot.js +194 -0
  330. package/dist/render/sort-rows.d.ts +3 -0
  331. package/dist/render/sort-rows.js +38 -0
  332. package/dist/render/use-collection-rows.d.ts +10 -0
  333. package/dist/render/use-collection-rows.js +11 -0
  334. package/dist/render/use-field-edit.d.ts +28 -0
  335. package/dist/render/use-field-edit.js +50 -0
  336. package/dist/render/use-file-upload.d.ts +10 -0
  337. package/dist/render/use-file-upload.js +35 -0
  338. package/dist/render/use-form-bridge.d.ts +21 -0
  339. package/dist/render/use-form-bridge.js +53 -0
  340. package/dist/render/use-hybrid.d.ts +2 -0
  341. package/dist/render/use-hybrid.js +5 -0
  342. package/dist/render/widgets/attachment-group.d.ts +1 -0
  343. package/dist/render/widgets/attachment-group.js +35 -0
  344. package/dist/render/widgets/checklist-content.d.ts +15 -0
  345. package/dist/render/widgets/checklist-content.js +12 -0
  346. package/dist/render/widgets/checklist-group.d.ts +11 -0
  347. package/dist/render/widgets/checklist-group.js +47 -0
  348. package/dist/render/widgets/checklist-row.d.ts +14 -0
  349. package/dist/render/widgets/checklist-row.js +14 -0
  350. package/dist/render/widgets/display.d.ts +33 -0
  351. package/dist/render/widgets/display.js +97 -0
  352. package/dist/render/widgets/edit.d.ts +63 -0
  353. package/dist/render/widgets/edit.js +283 -0
  354. package/dist/render/widgets/fixed-collection.d.ts +11 -0
  355. package/dist/render/widgets/fixed-collection.js +34 -0
  356. package/dist/render/widgets/flow-row.d.ts +14 -0
  357. package/dist/render/widgets/flow-row.js +27 -0
  358. package/dist/render/widgets/group-edit.d.ts +9 -0
  359. package/dist/render/widgets/group-edit.js +23 -0
  360. package/dist/render/widgets/group-field.d.ts +9 -0
  361. package/dist/render/widgets/group-field.js +42 -0
  362. package/dist/render/widgets/group-widgets.d.ts +2 -0
  363. package/dist/render/widgets/group-widgets.js +41 -0
  364. package/dist/render/widgets/group.d.ts +26 -0
  365. package/dist/render/widgets/group.js +139 -0
  366. package/dist/render/widgets/illustrated-group.d.ts +1 -0
  367. package/dist/render/widgets/illustrated-group.js +41 -0
  368. package/dist/render/widgets/table-group.d.ts +11 -0
  369. package/dist/render/widgets/table-group.js +58 -0
  370. package/dist/render/widgets/two-cell-group.d.ts +21 -0
  371. package/dist/render/widgets/two-cell-group.js +42 -0
  372. package/dist/render/widgets/url-widget.d.ts +7 -0
  373. package/dist/render/widgets/url-widget.js +15 -0
  374. package/dist/render/widgets/weekday-grid.d.ts +13 -0
  375. package/dist/render/widgets/weekday-grid.js +47 -0
  376. package/dist/render/write.d.ts +5 -0
  377. package/dist/render/write.js +14 -0
  378. package/dist/schema-registry.d.ts +6 -0
  379. package/dist/schema-registry.js +25 -0
  380. package/dist/site-links.d.ts +13 -0
  381. package/dist/site-links.js +18 -0
  382. package/dist/strip-markdown.d.ts +1 -0
  383. package/dist/strip-markdown.js +11 -0
  384. package/dist/theme.css +189 -0
  385. package/dist/types.d.ts +84 -0
  386. package/dist/types.js +1 -0
  387. package/package.json +85 -0
@@ -0,0 +1,139 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { hasChildren, isNamedField, isStorageGroup } from '@coffer-org/sdk/fields';
5
+ import { Trash2 } from 'lucide-react';
6
+ import { AddBtn, usedElsewhere } from "../shared.js";
7
+ import { RemoveBtn } from "../multiple-chips.js";
8
+ import { FieldLabel, Rail, STACK, GroupTitle, groupIcon, useGroupDepth, GroupDepthProvider, groupScopeClass, } from "../chrome.js";
9
+ import { Button } from "../../components/ui/button.js";
10
+ import { FieldSlot } from "../dispatch.js";
11
+ import { useFieldErrors } from "../field-errors.js";
12
+ import { GroupField } from "./group-field.js";
13
+ import { useGroupEdit } from "./group-edit.js";
14
+ import { useHybridScope } from "../hybrid-scope.js";
15
+ import { FlowRow } from "./flow-row.js";
16
+ import { fieldLayout } from "../../registry.js";
17
+ export const subFull = (f) => fieldLayout(f) === 'block';
18
+ function RowActionSlot({ onRemove }) {
19
+ const { t } = useTranslation();
20
+ return (_jsxs("div", { className: "flex shrink-0 flex-col", children: [_jsx("div", { className: "min-h-8 mb-1.5", "aria-hidden": true }), _jsx(Button, { type: "button", variant: "outline", size: "iconSm", onClick: onRemove, title: t('actions.delete'), "aria-hidden": onRemove ? undefined : true, tabIndex: onRemove ? undefined : -1, className: `rounded-lg text-muted hover:border-danger hover:text-danger${onRemove ? '' : ' invisible'}`, children: _jsx(Trash2, { size: 14 }) })] }));
21
+ }
22
+ export function CollectionWidget({ group, value, onChange, recordCtx, }) {
23
+ const { t } = useTranslation();
24
+ const errorAt = useFieldErrors();
25
+ const rows = Array.isArray(value) ? value : [];
26
+ const unique = group.unique ?? [];
27
+ function update(idx, key, v) {
28
+ onChange(rows.map((r, i) => (i === idx ? { ...r, [key]: v } : r)));
29
+ }
30
+ function renderSubField(sub, row, idx) {
31
+ if (sub.type.derived) {
32
+ return (_jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [sub.type.label ? _jsx(FieldLabel, { label: t(sub.type.label) }) : null, _jsx(FieldSlot, { field: sub.type, value: row[sub.key] ?? '', mode: "view", bare: true, recordCtx: recordCtx })] }, sub.key));
33
+ }
34
+ return (_jsx("div", { className: "flex flex-col gap-0.5 min-w-0", children: _jsx(FieldSlot, { field: sub.type, fieldKey: sub.key, value: row[sub.key] ?? '', excludeValues: usedElsewhere(rows, unique, sub.key, idx), onChange: (v) => update(idx, sub.key, v), label: sub.type.label ? t(sub.type.label) : undefined, mode: "edit", recordCtx: recordCtx, error: isStorageGroup(group) ? errorAt([group.key, idx, sub.key]) : undefined }) }, sub.key));
35
+ }
36
+ function renderRow(row, idx) {
37
+ return (_jsx(Rail, { children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx("div", { className: "flex-1 min-w-0", children: _jsx(FlowRow, { scroll: group.display === 'scroll', items: group.fields.flatMap((sub, sIdx) => {
38
+ if (hasChildren(sub)) {
39
+ if (!isStorageGroup(sub) && sub.display === 'scroll') {
40
+ return [
41
+ {
42
+ key: sub.label ?? 'flow',
43
+ full: true,
44
+ node: (_jsx(FlowRow, { scroll: true, items: sub.fields.flatMap((c) => isNamedField(c) ? [{ key: c.key, node: renderSubField(c, row, idx) }] : []) })),
45
+ },
46
+ ];
47
+ }
48
+ return [
49
+ {
50
+ key: sub.key ?? sub.label ?? 'g',
51
+ full: sub.kind === 'per-weekday' ? false : true,
52
+ node: (_jsx(GroupField, { group: sub, value: row[sub.key], onChange: (v) => update(idx, sub.key, v), recordCtx: recordCtx, mode: "edit" })),
53
+ },
54
+ ];
55
+ }
56
+ if (!isNamedField(sub))
57
+ return [];
58
+ return [{ key: sub.key, full: subFull(sub.type), node: renderSubField(sub, row, idx) }];
59
+ }) }) }), _jsx(RowActionSlot, { onRemove: () => onChange(rows.filter((_, i) => i !== idx)) })] }) }, idx));
60
+ }
61
+ return (_jsxs("div", { className: `flex flex-col ${STACK}`, children: [rows.map(renderRow), _jsx(AddBtn, { onClick: () => onChange([...rows, {}]), children: t('form.addRow') })] }));
62
+ }
63
+ export function CollectionGroup({ group, value, onChange, recordCtx, mode, }) {
64
+ const { t } = useTranslation();
65
+ const depth = useGroupDepth();
66
+ const live = useHybridScope() && mode === 'view';
67
+ const g = useGroupEdit(mode, value, (v) => onChange(v));
68
+ if (g.mode === 'view') {
69
+ return (_jsx(CollectionView, { group: group, value: g.value, onChange: (v) => g.onChange(v), recordCtx: recordCtx, actions: live ? null : g.actions, editable: live }));
70
+ }
71
+ return (_jsxs("fieldset", { className: `${groupScopeClass(depth)} flex flex-col min-w-0 ${STACK}`, children: [_jsx(GroupTitle, { as: "legend", label: t(group.label), icon: groupIcon(group), actions: g.actions }), _jsx(CollectionWidget, { group: group, value: g.value, onChange: (v) => g.onChange(v), recordCtx: recordCtx })] }));
72
+ }
73
+ const fieldsetCls = (depth) => `${groupScopeClass(depth)} flex flex-col min-w-0 ${STACK}`;
74
+ function CollectionCell({ sub, row, group, recordCtx, onChange, }) {
75
+ const { t } = useTranslation();
76
+ const live = useHybridScope() && Boolean(onChange);
77
+ const wired = live ? onChange : undefined;
78
+ return (_jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [sub.type.label ? _jsx(FieldLabel, { label: t(sub.type.label) }) : null, _jsx(FieldSlot, { field: sub.type, fieldKey: live ? sub.key : undefined, value: row[sub.key] ?? '', mode: "view", bare: !live, recordCtx: recordCtx, onChange: wired })] }));
79
+ }
80
+ export function CollectionView({ group, value, onChange, recordCtx, actions, editable = false, }) {
81
+ const { t } = useTranslation();
82
+ const depth = useGroupDepth();
83
+ const saved = Array.isArray(value) ? value : [];
84
+ const [pending, setPending] = useState([]);
85
+ const rows = [...saved, ...pending];
86
+ const filled = (r) => Object.values(r).some((v) => v !== '' && v != null && v !== false);
87
+ function persistCell(idx, key, v) {
88
+ const next = rows.map((r, i) => (i === idx ? { ...r, [key]: v } : r)).filter(filled);
89
+ setPending([]);
90
+ onChange(next);
91
+ }
92
+ function removeRow(idx) {
93
+ if (idx < saved.length) {
94
+ setPending([]);
95
+ onChange(saved.filter((_, i) => i !== idx));
96
+ return;
97
+ }
98
+ setPending((ps) => ps.filter((_, i) => i !== idx - saved.length));
99
+ }
100
+ return (_jsxs("fieldset", { className: fieldsetCls(depth), children: [_jsx(GroupTitle, { as: "legend", label: t(group.label), icon: groupIcon(group), actions: actions }), _jsx(GroupDepthProvider, { depth: depth + 1, children: _jsxs("div", { className: `flex flex-col ${STACK}`, children: [rows.map((row, idx) => (_jsx(Rail, { children: _jsxs("div", { className: "flex min-w-0 items-start gap-2", children: [_jsx("div", { className: "min-w-0 flex-1", children: _jsx(FlowRow, { scroll: group.display === 'scroll', items: group.fields.flatMap((sub, sIdx) => {
101
+ if (hasChildren(sub)) {
102
+ if (!isStorageGroup(sub) && sub.display === 'scroll') {
103
+ return [
104
+ {
105
+ key: sub.label ?? 'flow',
106
+ full: true,
107
+ node: (_jsx(FlowRow, { scroll: true, items: sub.fields.flatMap((c) => {
108
+ if (!isNamedField(c))
109
+ return [];
110
+ const cKey = c.key;
111
+ return [
112
+ {
113
+ key: cKey,
114
+ node: (_jsx(CollectionCell, { sub: c, row: row, group: group, recordCtx: recordCtx, onChange: (v) => persistCell(idx, cKey, v) })),
115
+ },
116
+ ];
117
+ }) })),
118
+ },
119
+ ];
120
+ }
121
+ return [
122
+ {
123
+ key: sub.key ?? sub.label ?? 'g',
124
+ full: sub.kind === 'per-weekday' ? false : true,
125
+ node: (_jsx(GroupField, { group: sub, value: row[sub.key], onChange: (v) => persistCell(idx, sub.key, v), recordCtx: recordCtx, mode: "view" })),
126
+ },
127
+ ];
128
+ }
129
+ if (!isNamedField(sub))
130
+ return [];
131
+ return [
132
+ {
133
+ key: sub.key,
134
+ full: subFull(sub.type),
135
+ node: (_jsx(CollectionCell, { sub: sub, row: row, group: group, recordCtx: recordCtx, onChange: (v) => persistCell(idx, sub.key, v) })),
136
+ },
137
+ ];
138
+ }) }) }), editable && _jsx(RemoveBtn, { className: "mt-6", onClick: () => removeRow(idx) })] }) }, idx))), editable && _jsx(AddBtn, { onClick: () => setPending((ps) => [...ps, {}]), children: t('form.addRow') })] }) })] }));
139
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { registerRenderer } from "../../registry.js";
3
+ import { Textarea } from "../../components/ui/textarea.js";
4
+ import { Dash, compositeRoleValue } from "../shared.js";
5
+ import { twoCellGroupPage } from "./two-cell-group.js";
6
+ import { ImageWidget, parseFileRecs } from "../image.js";
7
+ import { IllustratedBody, IllustratedFloat, illustratedSlots, illustratedLayout, illustratedImageKind, IllustratedPicture, IllustratedImageCell, IllustratedTextCell, } from "../core/illustrated.js";
8
+ function IllustratedRowEdit({ meta, row, onChange }) {
9
+ const { tKey, iKey } = illustratedSlots(meta);
10
+ const { width } = illustratedLayout(meta);
11
+ const kind = illustratedImageKind(meta);
12
+ const text = row[tKey];
13
+ const image = row[iKey];
14
+ const textPart = meta.parts?.find((p) => p.role === 'text');
15
+ const textFixed = textPart != null && textPart.mode !== 'stored';
16
+ const imagePart = meta.parts?.find((p) => p.role === 'image');
17
+ const imageFixed = imagePart != null && imagePart.mode !== 'stored';
18
+ const rec = image != null && image !== '' ? parseFileRecs(image)[0] : undefined;
19
+ return (_jsxs("div", { className: "flex flex-1 flex-col gap-3 min-w-0", children: [imageFixed ? (_jsx("div", { className: "text-sm text-muted", children: rec ? _jsx(IllustratedPicture, { name: rec.name, width: width, kind: kind }) : _jsx(Dash, {}) })) : (_jsx(ImageWidget, { value: image ?? '', onChange: (v) => onChange({ ...row, [iKey]: compositeRoleValue(v) }), width: width, poster: kind === 'poster' })), textFixed ? (_jsx("p", { className: "text-[15px] text-muted whitespace-pre-wrap", children: text != null && text !== '' ? String(text) : _jsx(Dash, {}) })) : (_jsx(Textarea, { value: text == null ? '' : String(text), onChange: (e) => onChange({ ...row, [tKey]: compositeRoleValue(e.target.value) }) }))] }));
20
+ }
21
+ function IllustratedRowLive({ meta, row, onChange }) {
22
+ const { tKey, iKey } = illustratedSlots(meta);
23
+ const { width, side } = illustratedLayout(meta);
24
+ const kind = illustratedImageKind(meta);
25
+ const text = row[tKey];
26
+ const image = row[iKey];
27
+ const textPart = meta.parts?.find((p) => p.role === 'text');
28
+ const textFixed = textPart != null && textPart.mode !== 'stored';
29
+ const imagePart = meta.parts?.find((p) => p.role === 'image');
30
+ const imageFixed = imagePart != null && imagePart.mode !== 'stored';
31
+ return (_jsx("div", { className: "flex-1 min-w-0", children: _jsx(IllustratedFloat, { width: width, side: side, picture: _jsx(IllustratedImageCell, { image: image, fixed: imageFixed, width: width, kind: kind, onChange: imageFixed ? undefined : (v) => onChange({ ...row, [iKey]: compositeRoleValue(v) }) }), prose: _jsx(IllustratedTextCell, { text: text, fixed: textFixed, meta: textPart?.meta ?? meta, onChange: textFixed ? undefined : (v) => onChange({ ...row, [tKey]: compositeRoleValue(v) }) }) }) }));
32
+ }
33
+ const IllustratedGroupPage = twoCellGroupPage({
34
+ kind: 'illustrated',
35
+ testid: 'illustrated-list',
36
+ rowGap: 'gap-4',
37
+ RowEdit: IllustratedRowEdit,
38
+ RowLive: IllustratedRowLive,
39
+ Body: IllustratedBody,
40
+ });
41
+ registerRenderer({ kinds: ['illustratedList'], layout: 'block', Page: IllustratedGroupPage, editor: 'custom' });
@@ -0,0 +1,11 @@
1
+ import type { ContainerNode } from '@coffer-org/sdk/fields';
2
+ import type { RecordCtx, FieldMode } from '../../types.ts';
3
+ type Row = Record<string, unknown>;
4
+ export declare function TableGroup({ group, value, onChange, recordCtx, mode, }: {
5
+ group: ContainerNode;
6
+ value: unknown;
7
+ onChange: (v: Row[]) => void;
8
+ recordCtx: RecordCtx;
9
+ mode: FieldMode;
10
+ }): import("react").JSX.Element;
11
+ export {};
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { Trash2 } from 'lucide-react';
5
+ import { hasValue, hasChildren, isNamedField, isStorageGroup } from '@coffer-org/sdk/fields';
6
+ import { FieldSlot } from "../dispatch.js";
7
+ import { useFieldErrors } from "../field-errors.js";
8
+ import { AddBtn, usedElsewhere } from "../shared.js";
9
+ import { GroupTitle, groupIcon, useGroupDepth, GroupDepthProvider, groupScopeClass } from "../chrome.js";
10
+ import { Button } from "../../components/ui/button.js";
11
+ import { useGroupEdit } from "./group-edit.js";
12
+ import { useHybridScope } from "../hybrid-scope.js";
13
+ export function TableGroup({ group, value, onChange, recordCtx, mode, }) {
14
+ const { t } = useTranslation();
15
+ const errorAt = useFieldErrors();
16
+ const depth = useGroupDepth();
17
+ const subs = group.fields.filter((f) => isNamedField(f) || (hasChildren(f) && !!f.kind));
18
+ const colKey = (s) => s.key;
19
+ const colLabel = (s) => (hasValue(s) ? s.type.label : s.label);
20
+ const colSlot = (s) => hasValue(s) ? { field: s.type } : { field: s, el: s };
21
+ const growColIdx = (() => {
22
+ const textIdx = subs.findIndex((s) => hasValue(s) && s.type.prim === 'text');
23
+ if (textIdx !== -1)
24
+ return textIdx;
25
+ const stringIdx = subs.findIndex((s) => hasValue(s) &&
26
+ (s.type.prim === 'string' || s.type.kind === 'link' || s.type.kind === 'url' || s.type.kind === 'relation'));
27
+ if (stringIdx !== -1)
28
+ return stringIdx;
29
+ return 0;
30
+ })();
31
+ const isGrowCol = (_s, i) => i === growColIdx;
32
+ const unique = group.unique ?? [];
33
+ const g = useGroupEdit(mode, value, (v) => onChange(v));
34
+ const isEdit = g.mode !== 'view';
35
+ const live = useHybridScope() && mode === 'view';
36
+ const saved = Array.isArray(g.value) ? g.value : [];
37
+ const [pending, setPending] = useState([]);
38
+ const rows = live ? [...saved, ...pending] : saved;
39
+ const filled = (r) => Object.values(r).some((v) => v !== '' && v != null && v !== false);
40
+ const setRows = (next) => {
41
+ setPending([]);
42
+ g.onChange(live ? next.filter(filled) : next);
43
+ };
44
+ const update = (idx, key, v) => setRows(rows.map((r, i) => (i === idx ? { ...r, [key]: v } : r)));
45
+ const removeRow = (idx) => {
46
+ if (!live || idx < saved.length)
47
+ return setRows(rows.filter((_, i) => i !== idx));
48
+ setPending((ps) => ps.filter((_, i) => i !== idx - saved.length));
49
+ };
50
+ const addRow = () => (live ? setPending((ps) => [...ps, {}]) : setRows([...rows, {}]));
51
+ const rowTools = isEdit || live;
52
+ const header = (_jsx("thead", { children: _jsxs("tr", { className: "border-b border-border/60 bg-muted/15", children: [subs.map((s, i) => (_jsx("th", { className: `text-left text-[11px] font-semibold text-muted uppercase tracking-wider px-3.5 py-2.5 ${isGrowCol(s, i) ? 'w-full min-w-[140px]' : 'whitespace-nowrap min-w-[90px]'}`, children: colLabel(s) ? t(colLabel(s)) : '' }, colKey(s)))), rowTools && _jsx("th", { className: "w-10 px-2", "aria-hidden": true })] }) }));
53
+ const body = (_jsx("tbody", { className: "divide-y divide-border/30", children: rows.map((row, idx) => (_jsxs("tr", { className: "align-top hover:bg-muted/10 transition-colors", children: [subs.map((s, i) => (_jsx("td", { className: `px-3.5 py-2.5 min-h-10 ${isGrowCol(s, i) ? 'min-w-[140px]' : 'min-w-[90px]'}`, children: _jsx(FieldSlot, { ...colSlot(s), value: row[colKey(s)] ?? (hasValue(s) ? '' : null), excludeValues: usedElsewhere(rows, unique, colKey(s), idx), onChange: (v) => update(idx, colKey(s), v), fieldKey: live ? colKey(s) : undefined, mode: isEdit ? 'edit' : 'view', bare: !live, recordCtx: recordCtx, error: isStorageGroup(group) ? errorAt([group.key, idx, colKey(s)]) : undefined }) }, colKey(s)))), rowTools && (_jsx("td", { className: "px-2 py-2 min-h-10 w-10", children: _jsx(Button, { type: "button", variant: "outline", size: "iconSm", onClick: () => removeRow(idx), title: t('actions.delete'), className: "rounded-lg text-muted hover:border-danger hover:text-danger", children: _jsx(Trash2, { size: 14 }) }) }))] }, idx))) }));
54
+ const tableEl = (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("div", { className: "overflow-x-auto rounded-lg border border-border/60 bg-card/20 shadow-2xs", children: _jsxs("table", { className: "w-full border-collapse text-sm", children: [header, body] }) }), rowTools && _jsx(AddBtn, { onClick: addRow, children: t('form.addRow') })] }));
55
+ if (mode !== 'view')
56
+ return tableEl;
57
+ return (_jsxs("section", { className: `${groupScopeClass(depth)} flex flex-col gap-2 min-w-0`, children: [_jsx(GroupTitle, { as: "h3", label: t(group.label), icon: groupIcon(group), actions: live ? null : g.actions }), _jsx(GroupDepthProvider, { depth: depth + 1, children: tableEl })] }));
58
+ }
@@ -0,0 +1,21 @@
1
+ import type { FC } from 'react';
2
+ import type { FieldMeta } from '@coffer-org/sdk/fields';
3
+ import type { ElementRenderProps } from '../../types.ts';
4
+ export type Row = Record<string, unknown>;
5
+ export interface TwoCellRowProps {
6
+ meta: FieldMeta;
7
+ row: Row;
8
+ onChange: (row: Row) => void;
9
+ }
10
+ export interface TwoCellGroupSpec {
11
+ kind: string;
12
+ testid: string;
13
+ rowGap: string;
14
+ RowEdit: FC<TwoCellRowProps>;
15
+ RowLive: FC<TwoCellRowProps>;
16
+ Body: FC<{
17
+ field: FieldMeta;
18
+ value: unknown;
19
+ }>;
20
+ }
21
+ export declare function twoCellGroupPage(spec: TwoCellGroupSpec): FC<ElementRenderProps>;
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Trash2 } from 'lucide-react';
4
+ import { Button } from "../../components/ui/button.js";
5
+ import { AddBtn, useRowIdentity } from "../shared.js";
6
+ import { useGroupDepth, GroupDepthProvider, groupScopeClass } from "../chrome.js";
7
+ import { useGroupEdit } from "./group-edit.js";
8
+ import { useHybridScope } from "../hybrid-scope.js";
9
+ import { useSlot } from "../slot.js";
10
+ function compositeRowMeta(group, kind) {
11
+ const parts = group.fields.map((f) => {
12
+ const item = f;
13
+ return {
14
+ role: item.key,
15
+ key: item.key,
16
+ meta: item.type,
17
+ mode: item.type.derived ? 'computedStored' : 'stored',
18
+ overridden: false,
19
+ };
20
+ });
21
+ return { kind, label: '', required: false, prim: kind, column: 'text', hints: {}, parts };
22
+ }
23
+ export function twoCellGroupPage(spec) {
24
+ const { RowEdit, RowLive, Body } = spec;
25
+ return function TwoCellGroupPage({ el, value, mode }) {
26
+ const { t } = useTranslation();
27
+ const depth = useGroupDepth();
28
+ const { write } = useSlot();
29
+ const group = el;
30
+ const meta = compositeRowMeta(group, spec.kind);
31
+ const g = useGroupEdit(mode, value, write);
32
+ const rows = Array.isArray(g.value) ? g.value : [];
33
+ const controlled = g.mode !== 'view';
34
+ const live = useHybridScope() && mode === 'view';
35
+ const rowTools = controlled || live;
36
+ const { rowId, updateRow, removeRow } = useRowIdentity(rows, g.onChange);
37
+ const content = (_jsxs("div", { className: `flex min-w-0 flex-col ${spec.rowGap}`, "data-testid": spec.testid, children: [rows.map((row, idx) => (_jsxs("div", { className: "flex items-start gap-2", children: [controlled ? (_jsx(RowEdit, { meta: meta, row: row, onChange: (next) => updateRow(idx, next) })) : live ? (_jsx(RowLive, { meta: meta, row: row, onChange: (next) => updateRow(idx, next) })) : (_jsx("div", { className: "min-w-0 flex-1", children: _jsx(Body, { field: meta, value: row }) })), rowTools && (_jsx(Button, { type: "button", variant: "ghost", size: "iconSm", onClick: () => removeRow(idx), title: t('actions.delete'), className: "h-5 w-5 shrink-0 rounded text-muted hover:text-danger", children: _jsx(Trash2, { size: 12 }) }))] }, rowId(row)))), rowTools && _jsx(AddBtn, { onClick: () => g.onChange([...rows, {}]), children: t('form.addRow') })] }));
38
+ if (mode !== 'view')
39
+ return content;
40
+ return (_jsxs("section", { className: `${groupScopeClass(depth)} flex min-w-0 flex-col gap-1`, children: [_jsx("div", { className: "flex items-center gap-2", children: _jsx("h3", { className: "text-[13px] font-semibold text-accent", children: t(group.label) }) }), _jsx(GroupDepthProvider, { depth: depth + 1, children: content })] }));
41
+ };
42
+ }
@@ -0,0 +1,7 @@
1
+ import { type UrlValue } from '@coffer-org/sdk/fields';
2
+ import type { FieldMode } from '../../types.ts';
3
+ export declare function UrlWidget({ value, onChange, mode, }: {
4
+ value: unknown;
5
+ onChange: (v: UrlValue | null) => void;
6
+ mode: FieldMode;
7
+ }): import("react").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ExternalLink } from 'lucide-react';
3
+ import { parseUrl, buildUrl, hrefOf } from '@coffer-org/sdk/fields';
4
+ import { Input } from "../../components/ui/input.js";
5
+ import { Dash } from "../shared.js";
6
+ export function UrlWidget({ value, onChange, mode, }) {
7
+ const v = (value ?? null);
8
+ if (mode === 'view') {
9
+ const text = buildUrl(v);
10
+ if (!text)
11
+ return _jsx(Dash, {});
12
+ return (_jsxs("a", { href: hrefOf(v), target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1 text-accent hover:underline text-sm break-all", children: [text, " ", _jsx(ExternalLink, { size: 12 })] }));
13
+ }
14
+ return _jsx(Input, { type: "text", inputMode: "url", value: buildUrl(v), onChange: (e) => onChange(parseUrl(e.target.value)) });
15
+ }
@@ -0,0 +1,13 @@
1
+ import type { ContainerNode } from '@coffer-org/sdk/fields';
2
+ import type { FieldMode } from '../../types.ts';
3
+ type DayRow = {
4
+ day: string;
5
+ value: number;
6
+ };
7
+ export declare function WeekdayGrid({ group, value, onChange, mode, }: {
8
+ group: ContainerNode;
9
+ value: unknown;
10
+ onChange: (v: DayRow[]) => void;
11
+ mode: FieldMode;
12
+ }): import("react").JSX.Element;
13
+ export {};
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useTranslation } from 'react-i18next';
3
+ import { isNamedField } from '@coffer-org/sdk/fields';
4
+ import { Input } from "../../components/ui/input.js";
5
+ import { Dash } from "../shared.js";
6
+ import { EDIT_INLINE_PAD } from "../chrome.js";
7
+ import { PopoverField } from "../popover-field.js";
8
+ import { useHybridScope } from "../hybrid-scope.js";
9
+ const DAYS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
10
+ const DAY_META = {
11
+ kind: 'number',
12
+ prim: 'number',
13
+ column: 'real',
14
+ label: '',
15
+ required: false,
16
+ hints: {},
17
+ };
18
+ export function WeekdayGrid({ group, value, onChange, mode, }) {
19
+ const { t } = useTranslation();
20
+ const daysShort = t('weekdaysShort', { returnObjects: true });
21
+ const onRecordPage = useHybridScope();
22
+ const rows = Array.isArray(value) ? value : [];
23
+ const byDay = new Map(rows.map((r) => [r.day, Number(r.value)]));
24
+ const editing = mode !== 'view';
25
+ const valueField = group.fields.slice(1).find((f) => isNamedField(f));
26
+ const min = valueField?.type.hints['min'];
27
+ const max = valueField?.type.hints['max'];
28
+ const step = valueField?.type.hints['step'];
29
+ const dayField = valueField ? { ...valueField.type, label: '', required: false } : DAY_META;
30
+ function setDay(day, n) {
31
+ const next = DAYS.flatMap((d) => {
32
+ const v = d === day ? n : (byDay.get(d) ?? 0);
33
+ return v > 0 ? [{ day: d, value: v }] : [];
34
+ });
35
+ onChange(next);
36
+ }
37
+ const numberInput = (v, set) => (_jsx(Input, { type: "number", className: "w-full text-center px-1 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none", min: min, max: max, step: step ?? 'any', value: v === 0 || v == null ? '' : String(v), onChange: (e) => set(e.target.value === '' ? '' : Number(e.target.value)) }));
38
+ const peak = Math.max(max ?? 0, ...DAYS.map((d) => byDay.get(d) ?? 0), 1);
39
+ const today = DAYS[(new Date().getDay() + 6) % 7];
40
+ const cell = (n) => (_jsxs("div", { className: `relative h-11 w-full overflow-hidden rounded-lg border ${n ? 'border-accent/30 text-accent' : 'border-border text-muted/40'}`, children: [n > 0 && (_jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 bottom-0 bg-accent/15", style: { height: `${Math.round((Math.min(n, peak) / peak) * 100)}%` } })), _jsx("span", { className: "relative flex h-full items-center justify-center text-sm font-semibold tabular-nums", children: n || '·' })] }));
41
+ if (!editing && !onRecordPage && !rows.some((r) => Number(r.value) > 0))
42
+ return _jsx(Dash, {});
43
+ return (_jsx("div", { className: `flex ${EDIT_INLINE_PAD}`, children: _jsx("div", { className: "grid grid-cols-[repeat(7,minmax(2.25rem,1fr))] gap-1.5 w-full max-w-72", children: DAYS.map((day, i) => {
44
+ const n = byDay.get(day) ?? 0;
45
+ return (_jsxs("div", { className: "flex flex-col items-stretch gap-1 min-w-0 text-center", children: [_jsx("span", { className: `text-[10px] ${day === today ? 'font-semibold text-accent' : 'text-muted'}`, children: daysShort[i] }), onRecordPage ? (_jsx(PopoverField, { field: dayField, value: n || '', geom: "none", width: "w-full", view: () => cell(n), edit: numberInput, onCommit: (v) => setDay(day, Number(v) || 0) })) : editing ? (numberInput(n || '', (nv) => setDay(day, Number(nv) || 0))) : (cell(n))] }, day));
46
+ }) }) }));
47
+ }
@@ -0,0 +1,5 @@
1
+ import { type FieldMeta } from '@coffer-org/sdk/fields';
2
+ export type Commit = (next: unknown) => void | Promise<string | undefined>;
3
+ export type IssueText = (code: string, params?: Record<string, unknown>) => string;
4
+ export declare function makeWriter(field: FieldMeta | undefined, commit: Commit, issueText?: IssueText, validateWith?: FieldMeta): (next: unknown) => Promise<string | undefined>;
5
+ export declare function notWritable(issueText?: IssueText): Commit;
@@ -0,0 +1,14 @@
1
+ import { validateField } from '@coffer-org/sdk/fields';
2
+ const bareCode = (code) => code;
3
+ export function makeWriter(field, commit, issueText = bareCode, validateWith) {
4
+ return async (next) => {
5
+ const judge = validateWith ?? field;
6
+ const issue = judge?.zod ? validateField(judge, next) : null;
7
+ if (issue)
8
+ return issueText(issue.code, issue.params);
9
+ return (await commit(next)) ?? undefined;
10
+ };
11
+ }
12
+ export function notWritable(issueText = bareCode) {
13
+ return async () => issueText('notWritable');
14
+ }
@@ -0,0 +1,6 @@
1
+ import type { Registry } from '@coffer-org/sdk/compose';
2
+ export type SchemaRegistry = Pick<Registry, 'getShelf' | 'getOptionList'>;
3
+ export declare function setSchemaRegistry(registry: SchemaRegistry): void;
4
+ export declare function resetSchemaRegistry(): void;
5
+ export declare const getShelf: SchemaRegistry['getShelf'];
6
+ export declare const getOptionList: SchemaRegistry['getOptionList'];
@@ -0,0 +1,25 @@
1
+ const MEMBERS = ['getShelf', 'getOptionList'];
2
+ let schema = null;
3
+ export function setSchemaRegistry(registry) {
4
+ if (!registry || typeof registry !== 'object') {
5
+ throw new Error('[web-ui] setSchemaRegistry() needs the composed registry object');
6
+ }
7
+ const missing = MEMBERS.filter((name) => typeof registry[name] !== 'function');
8
+ if (missing.length) {
9
+ throw new Error(`[web-ui] setSchemaRegistry() is missing ${missing.join(', ')} — ` +
10
+ `the kit reads these from the host's composed schema`);
11
+ }
12
+ schema = registry;
13
+ }
14
+ export function resetSchemaRegistry() {
15
+ schema = null;
16
+ }
17
+ function must() {
18
+ if (!schema) {
19
+ throw new Error('[web-ui] the schema registry is not registered — the application must call ' +
20
+ 'setSchemaRegistry() with its composed registry before the first render');
21
+ }
22
+ return schema;
23
+ }
24
+ export const getShelf = (library, shelf) => must().getShelf(library, shelf);
25
+ export const getOptionList = (name) => must().getOptionList(name);
@@ -0,0 +1,13 @@
1
+ export interface SiteRoute {
2
+ pattern: string;
3
+ purpose: string;
4
+ }
5
+ export interface SiteShelf {
6
+ library: string;
7
+ shelf: string;
8
+ }
9
+ export declare function registerSiteLinks(next: SiteRoute[]): void;
10
+ export declare function getSiteLinks(): SiteRoute[];
11
+ export declare function registerSiteShelves(next: SiteShelf[]): void;
12
+ export declare function getSiteShelves(): SiteShelf[];
13
+ export declare function resetSiteLinks(): void;
@@ -0,0 +1,18 @@
1
+ let routes = [];
2
+ let shelves = [];
3
+ export function registerSiteLinks(next) {
4
+ routes = [...next];
5
+ }
6
+ export function getSiteLinks() {
7
+ return [...routes];
8
+ }
9
+ export function registerSiteShelves(next) {
10
+ shelves = [...next];
11
+ }
12
+ export function getSiteShelves() {
13
+ return [...shelves];
14
+ }
15
+ export function resetSiteLinks() {
16
+ routes = [];
17
+ shelves = [];
18
+ }
@@ -0,0 +1 @@
1
+ export declare function stripMarkdown(src: string): string;
@@ -0,0 +1,11 @@
1
+ export function stripMarkdown(src) {
2
+ return (src ?? '')
3
+ .replace(/```[\s\S]*?```/g, ' ')
4
+ .replace(/`([^`]+)`/g, '$1')
5
+ .replace(/!\[[^\]]*\]\([^)]*\)/g, ' ')
6
+ .replace(/\[([^\]]+)\]\([^)]*\)/g, '$1')
7
+ .replace(/^#{1,6}\s+/gm, '')
8
+ .replace(/[*_~>#-]+/g, ' ')
9
+ .replace(/\s+/g, ' ')
10
+ .trim();
11
+ }