@panphora/bevel 0.1.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 (539) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +226 -0
  3. package/bevel-fonts.css +16 -0
  4. package/bevel.css +3075 -0
  5. package/bevel.js +2126 -0
  6. package/dist/react/components/activity-feed.d.ts +89 -0
  7. package/dist/react/components/activity-feed.js +54 -0
  8. package/dist/react/components/alert-dialog.d.ts +14 -0
  9. package/dist/react/components/alert-dialog.js +19 -0
  10. package/dist/react/components/app-shell.d.ts +98 -0
  11. package/dist/react/components/app-shell.js +86 -0
  12. package/dist/react/components/app-toolbar.d.ts +19 -0
  13. package/dist/react/components/app-toolbar.js +22 -0
  14. package/dist/react/components/avatar-group.d.ts +67 -0
  15. package/dist/react/components/avatar-group.js +49 -0
  16. package/dist/react/components/badge-and-pill.d.ts +34 -0
  17. package/dist/react/components/badge-and-pill.js +12 -0
  18. package/dist/react/components/breadcrumbs.d.ts +56 -0
  19. package/dist/react/components/breadcrumbs.js +44 -0
  20. package/dist/react/components/bulk-bar.d.ts +22 -0
  21. package/dist/react/components/bulk-bar.js +59 -0
  22. package/dist/react/components/button.d.ts +15 -0
  23. package/dist/react/components/button.js +20 -0
  24. package/dist/react/components/callout-and-hint.d.ts +17 -0
  25. package/dist/react/components/callout-and-hint.js +8 -0
  26. package/dist/react/components/checkbox.d.ts +5 -0
  27. package/dist/react/components/checkbox.js +13 -0
  28. package/dist/react/components/chip.d.ts +149 -0
  29. package/dist/react/components/chip.js +29 -0
  30. package/dist/react/components/code-block.d.ts +50 -0
  31. package/dist/react/components/code-block.js +77 -0
  32. package/dist/react/components/code-editor.d.ts +122 -0
  33. package/dist/react/components/code-editor.js +695 -0
  34. package/dist/react/components/column-manager.d.ts +28 -0
  35. package/dist/react/components/column-manager.js +85 -0
  36. package/dist/react/components/combobox.d.ts +32 -0
  37. package/dist/react/components/combobox.js +37 -0
  38. package/dist/react/components/data-grid.d.ts +108 -0
  39. package/dist/react/components/data-grid.js +159 -0
  40. package/dist/react/components/data-table.d.ts +2 -0
  41. package/dist/react/components/data-table.js +6 -0
  42. package/dist/react/components/date.d.ts +23 -0
  43. package/dist/react/components/date.js +11 -0
  44. package/dist/react/components/details.d.ts +13 -0
  45. package/dist/react/components/details.js +20 -0
  46. package/dist/react/components/dialog.d.ts +74 -0
  47. package/dist/react/components/dialog.js +31 -0
  48. package/dist/react/components/diff-view.d.ts +73 -0
  49. package/dist/react/components/diff-view.js +68 -0
  50. package/dist/react/components/documents.d.ts +70 -0
  51. package/dist/react/components/documents.js +10 -0
  52. package/dist/react/components/drawer.d.ts +45 -0
  53. package/dist/react/components/drawer.js +35 -0
  54. package/dist/react/components/editable-grid-cells.d.ts +32 -0
  55. package/dist/react/components/editable-grid-cells.js +116 -0
  56. package/dist/react/components/eyebrow-kicker-lede-pull-quote.d.ts +39 -0
  57. package/dist/react/components/eyebrow-kicker-lede-pull-quote.js +12 -0
  58. package/dist/react/components/field.d.ts +32 -0
  59. package/dist/react/components/field.js +27 -0
  60. package/dist/react/components/file-tree.d.ts +75 -0
  61. package/dist/react/components/file-tree.js +247 -0
  62. package/dist/react/components/file.d.ts +43 -0
  63. package/dist/react/components/file.js +73 -0
  64. package/dist/react/components/files-table.d.ts +174 -0
  65. package/dist/react/components/files-table.js +237 -0
  66. package/dist/react/components/filter-builder.d.ts +37 -0
  67. package/dist/react/components/filter-builder.js +109 -0
  68. package/dist/react/components/form-error-summary.d.ts +16 -0
  69. package/dist/react/components/form-error-summary.js +49 -0
  70. package/dist/react/components/icon-button.d.ts +8 -0
  71. package/dist/react/components/icon-button.js +14 -0
  72. package/dist/react/components/icon.d.ts +7 -0
  73. package/dist/react/components/icon.js +15 -0
  74. package/dist/react/components/image.d.ts +72 -0
  75. package/dist/react/components/image.js +24 -0
  76. package/dist/react/components/inline-edit.d.ts +70 -0
  77. package/dist/react/components/inline-edit.js +149 -0
  78. package/dist/react/components/input.d.ts +29 -0
  79. package/dist/react/components/input.js +20 -0
  80. package/dist/react/components/kanban-board.d.ts +140 -0
  81. package/dist/react/components/kanban-board.js +374 -0
  82. package/dist/react/components/layout.d.ts +51 -0
  83. package/dist/react/components/layout.js +28 -0
  84. package/dist/react/components/list.d.ts +28 -0
  85. package/dist/react/components/list.js +6 -0
  86. package/dist/react/components/masthead-and-verdict.d.ts +60 -0
  87. package/dist/react/components/masthead-and-verdict.js +8 -0
  88. package/dist/react/components/menu.d.ts +26 -0
  89. package/dist/react/components/menu.js +31 -0
  90. package/dist/react/components/multi-select-picker.d.ts +49 -0
  91. package/dist/react/components/multi-select-picker.js +20 -0
  92. package/dist/react/components/note.d.ts +33 -0
  93. package/dist/react/components/note.js +8 -0
  94. package/dist/react/components/number-field.d.ts +16 -0
  95. package/dist/react/components/number-field.js +17 -0
  96. package/dist/react/components/pagination.d.ts +45 -0
  97. package/dist/react/components/pagination.js +87 -0
  98. package/dist/react/components/persistent-action-banner.d.ts +71 -0
  99. package/dist/react/components/persistent-action-banner.js +39 -0
  100. package/dist/react/components/popconfirm.d.ts +42 -0
  101. package/dist/react/components/popconfirm.js +59 -0
  102. package/dist/react/components/popover.d.ts +16 -0
  103. package/dist/react/components/popover.js +21 -0
  104. package/dist/react/components/progress-and-gauge.d.ts +44 -0
  105. package/dist/react/components/progress-and-gauge.js +19 -0
  106. package/dist/react/components/radio.d.ts +7 -0
  107. package/dist/react/components/radio.js +13 -0
  108. package/dist/react/components/rich-text-toolbar.d.ts +26 -0
  109. package/dist/react/components/rich-text-toolbar.js +64 -0
  110. package/dist/react/components/rows-and-card.d.ts +88 -0
  111. package/dist/react/components/rows-and-card.js +10 -0
  112. package/dist/react/components/save-status-indicator.d.ts +11 -0
  113. package/dist/react/components/save-status-indicator.js +33 -0
  114. package/dist/react/components/segmented-control.d.ts +21 -0
  115. package/dist/react/components/segmented-control.js +15 -0
  116. package/dist/react/components/select.d.ts +29 -0
  117. package/dist/react/components/select.js +29 -0
  118. package/dist/react/components/selectable-cards.d.ts +30 -0
  119. package/dist/react/components/selectable-cards.js +29 -0
  120. package/dist/react/components/settings-rows.d.ts +51 -0
  121. package/dist/react/components/settings-rows.js +8 -0
  122. package/dist/react/components/sidebar-nav.d.ts +77 -0
  123. package/dist/react/components/sidebar-nav.js +41 -0
  124. package/dist/react/components/skeleton-and-empty.d.ts +51 -0
  125. package/dist/react/components/skeleton-and-empty.js +14 -0
  126. package/dist/react/components/slider.d.ts +19 -0
  127. package/dist/react/components/slider.js +17 -0
  128. package/dist/react/components/small-charts.d.ts +60 -0
  129. package/dist/react/components/small-charts.js +76 -0
  130. package/dist/react/components/sortable.d.ts +30 -0
  131. package/dist/react/components/sortable.js +85 -0
  132. package/dist/react/components/split-button.d.ts +38 -0
  133. package/dist/react/components/split-button.js +43 -0
  134. package/dist/react/components/split-panes.d.ts +35 -0
  135. package/dist/react/components/split-panes.js +102 -0
  136. package/dist/react/components/stat-tiles.d.ts +54 -0
  137. package/dist/react/components/stat-tiles.js +8 -0
  138. package/dist/react/components/steps.d.ts +11 -0
  139. package/dist/react/components/steps.js +13 -0
  140. package/dist/react/components/switch.d.ts +6 -0
  141. package/dist/react/components/switch.js +13 -0
  142. package/dist/react/components/table.d.ts +61 -0
  143. package/dist/react/components/table.js +6 -0
  144. package/dist/react/components/tabs.d.ts +7 -0
  145. package/dist/react/components/tabs.js +13 -0
  146. package/dist/react/components/tags.d.ts +33 -0
  147. package/dist/react/components/tags.js +83 -0
  148. package/dist/react/components/textarea.d.ts +10 -0
  149. package/dist/react/components/textarea.js +6 -0
  150. package/dist/react/components/toast.d.ts +35 -0
  151. package/dist/react/components/toast.js +90 -0
  152. package/dist/react/components/tooltip-and-key.d.ts +20 -0
  153. package/dist/react/components/tooltip-and-key.js +20 -0
  154. package/dist/react/components/tree-view.d.ts +34 -0
  155. package/dist/react/components/tree-view.js +118 -0
  156. package/dist/react/components/upload-dropzone.d.ts +92 -0
  157. package/dist/react/components/upload-dropzone.js +116 -0
  158. package/dist/react/components/wizard-shell.d.ts +78 -0
  159. package/dist/react/components/wizard-shell.js +176 -0
  160. package/dist/react/fonts.css.d.ts +1 -0
  161. package/dist/react/index.d.ts +76 -0
  162. package/dist/react/index.js +77 -0
  163. package/dist/react/integrations/quickcrop.d.ts +58 -0
  164. package/dist/react/integrations/quickcrop.js +137 -0
  165. package/dist/react/integrations/richclay.d.ts +43 -0
  166. package/dist/react/integrations/richclay.js +129 -0
  167. package/dist/react/internal/classes.d.ts +3 -0
  168. package/dist/react/internal/classes.js +10 -0
  169. package/dist/react/internal/close-mark.d.ts +1 -0
  170. package/dist/react/internal/close-mark.js +10 -0
  171. package/dist/react/internal/controllable-state.d.ts +9 -0
  172. package/dist/react/internal/controllable-state.js +22 -0
  173. package/dist/react/internal/drop-effect.d.ts +28 -0
  174. package/dist/react/internal/drop-effect.js +8 -0
  175. package/dist/react/internal/form-reset.d.ts +2 -0
  176. package/dist/react/internal/form-reset.js +22 -0
  177. package/dist/react/internal/format.d.ts +1 -0
  178. package/dist/react/internal/format.js +14 -0
  179. package/dist/react/internal/link.d.ts +2 -0
  180. package/dist/react/internal/link.js +8 -0
  181. package/dist/react/internal/part.d.ts +20 -0
  182. package/dist/react/internal/part.js +47 -0
  183. package/dist/react/internal/pointer-session.d.ts +8 -0
  184. package/dist/react/internal/pointer-session.js +60 -0
  185. package/dist/react/internal/refs.d.ts +2 -0
  186. package/dist/react/internal/refs.js +22 -0
  187. package/dist/react/internal/rich-text.d.ts +28 -0
  188. package/dist/react/internal/rich-text.js +4 -0
  189. package/dist/react/internal/table-context.d.ts +39 -0
  190. package/dist/react/internal/table-context.js +12 -0
  191. package/dist/react/internal/use-object-url.d.ts +1 -0
  192. package/dist/react/internal/use-object-url.js +15 -0
  193. package/dist/react/layout.css +274 -0
  194. package/dist/react/layout.css.d.ts +1 -0
  195. package/dist/react/models/filter.d.ts +31 -0
  196. package/dist/react/models/filter.js +79 -0
  197. package/dist/react/models/kanban.d.ts +51 -0
  198. package/dist/react/models/kanban.js +35 -0
  199. package/dist/react/models/reorder.d.ts +9 -0
  200. package/dist/react/models/reorder.js +23 -0
  201. package/dist/react/models/table.d.ts +85 -0
  202. package/dist/react/models/table.js +144 -0
  203. package/dist/react/models/tree.d.ts +16 -0
  204. package/dist/react/models/tree.js +26 -0
  205. package/dist/react/provider.d.ts +18 -0
  206. package/dist/react/provider.js +31 -0
  207. package/dist/react/recipes/context-hypercms.d.ts +17 -0
  208. package/dist/react/recipes/context-hypercms.js +71 -0
  209. package/dist/react/recipes/context-quickcrop.d.ts +8 -0
  210. package/dist/react/recipes/context-quickcrop.js +49 -0
  211. package/dist/react/theme.css +8004 -0
  212. package/dist/react/theme.css.d.ts +1 -0
  213. package/examples/README.md +34 -0
  214. package/examples/components/activity-feed.html +28 -0
  215. package/examples/components/app-shell.html +12 -0
  216. package/examples/components/app-toolbar.html +38 -0
  217. package/examples/components/avatar-group.html +27 -0
  218. package/examples/components/breadcrumbs.html +26 -0
  219. package/examples/components/bulk-bar.html +22 -0
  220. package/examples/components/code-block.html +12 -0
  221. package/examples/components/code-editor.html +25 -0
  222. package/examples/components/column-manager.html +9 -0
  223. package/examples/components/combobox.html +13 -0
  224. package/examples/components/context-hypercms.css +41 -0
  225. package/examples/components/context-hypercms.html +40 -0
  226. package/examples/components/context-hypercms.js +62 -0
  227. package/examples/components/context-quickcrop.html +137 -0
  228. package/examples/components/diff-view.html +9 -0
  229. package/examples/components/drawer.html +11 -0
  230. package/examples/components/editable-grid-cells.html +9 -0
  231. package/examples/components/file-browser.html +53 -0
  232. package/examples/components/file-tree.html +34 -0
  233. package/examples/components/files-table.html +80 -0
  234. package/examples/components/filter-builder.html +11 -0
  235. package/examples/components/form-error-summary.html +11 -0
  236. package/examples/components/index.html +51 -0
  237. package/examples/components/inline-edit.html +42 -0
  238. package/examples/components/kanban-board.html +42 -0
  239. package/examples/components/manifest.json +3279 -0
  240. package/examples/components/modal.html +11 -0
  241. package/examples/components/multi-select-picker.html +13 -0
  242. package/examples/components/pagination.html +32 -0
  243. package/examples/components/persistent-action-banner.html +23 -0
  244. package/examples/components/popconfirm.html +13 -0
  245. package/examples/components/popover-menu.html +13 -0
  246. package/examples/components/reference/baseline/DECISIONS.md +85 -0
  247. package/examples/components/reference/baseline/README.md +58 -0
  248. package/examples/components/reference/baseline/bevel-fonts.css +16 -0
  249. package/examples/components/reference/baseline/bevel.css +1339 -0
  250. package/examples/components/reference/baseline/bevel.js +496 -0
  251. package/examples/components/reference/baseline/fonts/LICENSE-ibm-plex-mono.txt +93 -0
  252. package/examples/components/reference/baseline/fonts/LICENSE-ibm-plex-sans.txt +93 -0
  253. package/examples/components/reference/baseline/fonts/LICENSE-newsreader.txt +93 -0
  254. package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  255. package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
  256. package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
  257. package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-400-italic.woff2 +0 -0
  258. package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
  259. package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
  260. package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
  261. package/examples/components/reference/baseline/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
  262. package/examples/components/reference/baseline/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
  263. package/examples/components/reference/fable/IMPROVEMENTS.md +106 -0
  264. package/examples/components/reference/fable/PARENT-REPAIRS.md +17 -0
  265. package/examples/components/reference/fable/__pycache__/build_repairs.cpython-311.pyc +0 -0
  266. package/examples/components/reference/fable/__pycache__/kanban.cpython-311.pyc +0 -0
  267. package/examples/components/reference/fable/as-authored/IMPROVEMENTS-completed.md +106 -0
  268. package/examples/components/reference/fable/as-authored/base-astra.css +17 -0
  269. package/examples/components/reference/fable/as-authored/base-parent.css +416 -0
  270. package/examples/components/reference/fable/as-authored/build.py +858 -0
  271. package/examples/components/reference/fable/as-authored/fable.css +823 -0
  272. package/examples/components/reference/fable/as-authored/kanban-completed.css +235 -0
  273. package/examples/components/reference/fable/as-authored/kanban-completed.html +53 -0
  274. package/examples/components/reference/fable/as-authored/kanban-completed.py +212 -0
  275. package/examples/components/reference/fable/as-authored/kanban.py +207 -0
  276. package/examples/components/reference/fable/base-astra.css +17 -0
  277. package/examples/components/reference/fable/base-parent.css +416 -0
  278. package/examples/components/reference/fable/build.py +858 -0
  279. package/examples/components/reference/fable/build_repairs.py +25 -0
  280. package/examples/components/reference/fable/components/activity-feed.html +3 -0
  281. package/examples/components/reference/fable/components/app-toolbar.html +3 -0
  282. package/examples/components/reference/fable/components/avatar-group.html +4 -0
  283. package/examples/components/reference/fable/components/breadcrumbs.html +3 -0
  284. package/examples/components/reference/fable/components/code-block.html +9 -0
  285. package/examples/components/reference/fable/components/column-manager.html +3 -0
  286. package/examples/components/reference/fable/components/combobox.html +6 -0
  287. package/examples/components/reference/fable/components/context-hypercms.html +3 -0
  288. package/examples/components/reference/fable/components/context-quickcrop.html +4 -0
  289. package/examples/components/reference/fable/components/diff-view.html +13 -0
  290. package/examples/components/reference/fable/components/drawer.html +3 -0
  291. package/examples/components/reference/fable/components/editable-grid-cells.html +3 -0
  292. package/examples/components/reference/fable/components/filter-builder.html +3 -0
  293. package/examples/components/reference/fable/components/form-error-summary.html +4 -0
  294. package/examples/components/reference/fable/components/inline-edit.html +3 -0
  295. package/examples/components/reference/fable/components/kanban-board.html +53 -0
  296. package/examples/components/reference/fable/components/modal.html +3 -0
  297. package/examples/components/reference/fable/components/multi-select-picker.html +5 -0
  298. package/examples/components/reference/fable/components/pagination.html +3 -0
  299. package/examples/components/reference/fable/components/persistent-action-banner.html +4 -0
  300. package/examples/components/reference/fable/components/popconfirm.html +5 -0
  301. package/examples/components/reference/fable/components/popover-menu.html +3 -0
  302. package/examples/components/reference/fable/components/rich-text-toolbar.html +3 -0
  303. package/examples/components/reference/fable/components/save-status-indicator.html +2 -0
  304. package/examples/components/reference/fable/components/selectable-cards.html +3 -0
  305. package/examples/components/reference/fable/components/settings-rows.html +3 -0
  306. package/examples/components/reference/fable/components/sidebar-nav.html +4 -0
  307. package/examples/components/reference/fable/components/small-charts.html +5 -0
  308. package/examples/components/reference/fable/components/split-button.html +4 -0
  309. package/examples/components/reference/fable/components/split-panes.html +8 -0
  310. package/examples/components/reference/fable/components/stat-tiles.html +3 -0
  311. package/examples/components/reference/fable/components/toast-stack.html +5 -0
  312. package/examples/components/reference/fable/components/tree-view.html +4 -0
  313. package/examples/components/reference/fable/components/upload-dropzone.html +6 -0
  314. package/examples/components/reference/fable/components/wizard-shell.html +3 -0
  315. package/examples/components/reference/fable/coverage.json +414 -0
  316. package/examples/components/reference/fable/fable.css +823 -0
  317. package/examples/components/reference/fable/index.html +5 -0
  318. package/examples/components/reference/fable/kanban.css +237 -0
  319. package/examples/components/reference/fable/kanban.py +212 -0
  320. package/examples/components/reference/fable/parent-repairs.css +9 -0
  321. package/examples/components/reference/fixtures/data.json +102 -0
  322. package/examples/components/reference/fixtures/host.js +47 -0
  323. package/examples/components/reference/fixtures/static-host.js +39 -0
  324. package/examples/components/reference/fixtures/workspace.jpg +0 -0
  325. package/examples/components/reference/parent/CHANGES.md +179 -0
  326. package/examples/components/reference/parent/__pycache__/kanban.cpython-311.pyc +0 -0
  327. package/examples/components/reference/parent/base-astra.css +17 -0
  328. package/examples/components/reference/parent/base-parent.css +416 -0
  329. package/examples/components/reference/parent/build.py +148 -0
  330. package/examples/components/reference/parent/components/activity-feed.html +2 -0
  331. package/examples/components/reference/parent/components/app-toolbar.html +2 -0
  332. package/examples/components/reference/parent/components/avatar-group.html +4 -0
  333. package/examples/components/reference/parent/components/breadcrumbs.html +2 -0
  334. package/examples/components/reference/parent/components/code-block.html +8 -0
  335. package/examples/components/reference/parent/components/column-manager.html +2 -0
  336. package/examples/components/reference/parent/components/combobox.html +6 -0
  337. package/examples/components/reference/parent/components/context-hypercms.html +2 -0
  338. package/examples/components/reference/parent/components/context-quickcrop.html +4 -0
  339. package/examples/components/reference/parent/components/diff-view.html +4 -0
  340. package/examples/components/reference/parent/components/drawer.html +2 -0
  341. package/examples/components/reference/parent/components/editable-grid-cells.html +2 -0
  342. package/examples/components/reference/parent/components/filter-builder.html +2 -0
  343. package/examples/components/reference/parent/components/form-error-summary.html +2 -0
  344. package/examples/components/reference/parent/components/inline-edit.html +2 -0
  345. package/examples/components/reference/parent/components/kanban-board.html +84 -0
  346. package/examples/components/reference/parent/components/modal.html +2 -0
  347. package/examples/components/reference/parent/components/multi-select-picker.html +5 -0
  348. package/examples/components/reference/parent/components/pagination.html +2 -0
  349. package/examples/components/reference/parent/components/persistent-action-banner.html +4 -0
  350. package/examples/components/reference/parent/components/popconfirm.html +5 -0
  351. package/examples/components/reference/parent/components/popover-menu.html +2 -0
  352. package/examples/components/reference/parent/components/rich-text-toolbar.html +2 -0
  353. package/examples/components/reference/parent/components/save-status-indicator.html +2 -0
  354. package/examples/components/reference/parent/components/selectable-cards.html +2 -0
  355. package/examples/components/reference/parent/components/settings-rows.html +2 -0
  356. package/examples/components/reference/parent/components/sidebar-nav.html +4 -0
  357. package/examples/components/reference/parent/components/small-charts.html +2 -0
  358. package/examples/components/reference/parent/components/split-button.html +5 -0
  359. package/examples/components/reference/parent/components/split-panes.html +8 -0
  360. package/examples/components/reference/parent/components/stat-tiles.html +2 -0
  361. package/examples/components/reference/parent/components/toast-stack.html +5 -0
  362. package/examples/components/reference/parent/components/tree-view.html +4 -0
  363. package/examples/components/reference/parent/components/upload-dropzone.html +6 -0
  364. package/examples/components/reference/parent/components/wizard-shell.html +2 -0
  365. package/examples/components/reference/parent/coverage.json +414 -0
  366. package/examples/components/reference/parent/index.html +1 -0
  367. package/examples/components/reference/parent/kanban.css +114 -0
  368. package/examples/components/reference/parent/kanban.py +55 -0
  369. package/examples/components/reference/parent/refinement.css +53 -0
  370. package/examples/components/reference/selected/build.py +70 -0
  371. package/examples/components/reference/selected/components/activity-feed.html +3 -0
  372. package/examples/components/reference/selected/components/app-toolbar.html +3 -0
  373. package/examples/components/reference/selected/components/avatar-group.html +4 -0
  374. package/examples/components/reference/selected/components/breadcrumbs.html +3 -0
  375. package/examples/components/reference/selected/components/code-block.html +9 -0
  376. package/examples/components/reference/selected/components/column-manager.html +3 -0
  377. package/examples/components/reference/selected/components/combobox.html +6 -0
  378. package/examples/components/reference/selected/components/context-hypercms.html +3 -0
  379. package/examples/components/reference/selected/components/context-quickcrop.html +4 -0
  380. package/examples/components/reference/selected/components/diff-view.html +13 -0
  381. package/examples/components/reference/selected/components/drawer.html +3 -0
  382. package/examples/components/reference/selected/components/editable-grid-cells.html +3 -0
  383. package/examples/components/reference/selected/components/filter-builder.html +3 -0
  384. package/examples/components/reference/selected/components/form-error-summary.html +4 -0
  385. package/examples/components/reference/selected/components/inline-edit.html +3 -0
  386. package/examples/components/reference/selected/components/kanban-board.html +53 -0
  387. package/examples/components/reference/selected/components/modal.html +2 -0
  388. package/examples/components/reference/selected/components/multi-select-picker.html +5 -0
  389. package/examples/components/reference/selected/components/pagination.html +3 -0
  390. package/examples/components/reference/selected/components/persistent-action-banner.html +4 -0
  391. package/examples/components/reference/selected/components/popconfirm.html +5 -0
  392. package/examples/components/reference/selected/components/popover-menu.html +3 -0
  393. package/examples/components/reference/selected/components/rich-text-toolbar.html +3 -0
  394. package/examples/components/reference/selected/components/save-status-indicator.html +2 -0
  395. package/examples/components/reference/selected/components/selectable-cards.html +3 -0
  396. package/examples/components/reference/selected/components/settings-rows.html +3 -0
  397. package/examples/components/reference/selected/components/sidebar-nav.html +4 -0
  398. package/examples/components/reference/selected/components/small-charts.html +5 -0
  399. package/examples/components/reference/selected/components/split-button.html +4 -0
  400. package/examples/components/reference/selected/components/split-panes.html +8 -0
  401. package/examples/components/reference/selected/components/stat-tiles.html +3 -0
  402. package/examples/components/reference/selected/components/toast-stack.html +5 -0
  403. package/examples/components/reference/selected/components/tree-view.html +4 -0
  404. package/examples/components/reference/selected/components/upload-dropzone.html +6 -0
  405. package/examples/components/reference/selected/components/wizard-shell.html +3 -0
  406. package/examples/components/reference/selected/corrections.css +11 -0
  407. package/examples/components/reference/selected/coverage.json +413 -0
  408. package/examples/components/reference/selected/gallery-build.mjs +49 -0
  409. package/examples/components/reference/selected/gallery-spec.json +12 -0
  410. package/examples/components/reference/selected/index.html +1 -0
  411. package/examples/components/reference/selected/kanban-comparison.json +6 -0
  412. package/examples/components/reference/selected/manifest.json +476 -0
  413. package/examples/components/reference/sha256.json +142 -0
  414. package/examples/components/reference/sources/diagonal-close.svg +1 -0
  415. package/examples/components/reference/sources/hyperclay/public-assets/css/hyperclay-app-source.css +614 -0
  416. package/examples/components/reference/sources/hyperclay/public-assets/js/app.js +94 -0
  417. package/examples/components/reference/sources/hyperclayjs/src/ui/theModal.js +897 -0
  418. package/examples/components/reference/sources/hypercms/scripts/build-theme.js +203 -0
  419. package/examples/components/reference/sources/hypercms/src/anchor.js +24 -0
  420. package/examples/components/reference/sources/hypercms/src/apply-loop.js +167 -0
  421. package/examples/components/reference/sources/hypercms/src/diagnostics.js +44 -0
  422. package/examples/components/reference/sources/hypercms/src/enhance.js +173 -0
  423. package/examples/components/reference/sources/hypercms/src/events.js +955 -0
  424. package/examples/components/reference/sources/hypercms/src/form-builder.js +518 -0
  425. package/examples/components/reference/sources/hypercms/src/form-rules.js +208 -0
  426. package/examples/components/reference/sources/hypercms/src/hooks.js +100 -0
  427. package/examples/components/reference/sources/hypercms/src/hypercms-bundle.js +10 -0
  428. package/examples/components/reference/sources/hypercms/src/hypercms.js +347 -0
  429. package/examples/components/reference/sources/hypercms/src/morph.js +10 -0
  430. package/examples/components/reference/sources/hypercms/src/path.js +61 -0
  431. package/examples/components/reference/sources/hypercms/src/place.js +131 -0
  432. package/examples/components/reference/sources/hypercms/src/platform.js +131 -0
  433. package/examples/components/reference/sources/hypercms/src/refresh.js +87 -0
  434. package/examples/components/reference/sources/hypercms/src/richclay-bridge.js +140 -0
  435. package/examples/components/reference/sources/hypercms/src/row-identity.js +111 -0
  436. package/examples/components/reference/sources/hypercms/src/scaffold.js +10 -0
  437. package/examples/components/reference/sources/hypercms/src/session.js +303 -0
  438. package/examples/components/reference/sources/hypercms/src/shell.js +248 -0
  439. package/examples/components/reference/sources/hypercms/src/styles.css +298 -0
  440. package/examples/components/reference/sources/hypercms/src/targets.js +144 -0
  441. package/examples/components/reference/sources/hypercms/src/templates.js +656 -0
  442. package/examples/components/reference/sources/hypercms/src/theme/pixel-quiet.overrides.css +761 -0
  443. package/examples/components/reference/sources/hypercms/src/theme.generated.css +1772 -0
  444. package/examples/components/reference/sources/hypercms/src/toggle.js +666 -0
  445. package/examples/components/reference/sources/hypercms/src/unresolved.js +211 -0
  446. package/examples/components/reference/sources/hypercms/src/vendor/mirk.vendor.js +212 -0
  447. package/examples/components/reference/sources/hypercms/src/views/inline-layer.js +421 -0
  448. package/examples/components/reference/sources/hypercms/src/views/inline.js +1072 -0
  449. package/examples/components/reference/sources/hypercms/src/views/sidebar.js +97 -0
  450. package/examples/components/reference/sources/modal-reference.html +301 -0
  451. package/examples/components/reference/sources/quickcrop/quickcrop.css +124 -0
  452. package/examples/components/reference/sources/quickcrop/quickcrop.js +400 -0
  453. package/examples/components/reference/sources/richclay/richclay.css +416 -0
  454. package/examples/components/reference/sources/richclay/richclay.js +2962 -0
  455. package/examples/components/reference/sources/richclay/src/a11y.js +67 -0
  456. package/examples/components/reference/sources/richclay/src/browser-global.js +7 -0
  457. package/examples/components/reference/sources/richclay/src/buttons.js +254 -0
  458. package/examples/components/reference/sources/richclay/src/hyperclay.js +470 -0
  459. package/examples/components/reference/sources/richclay/src/normalize.js +380 -0
  460. package/examples/components/reference/sources/richclay/src/richclay.js +1356 -0
  461. package/examples/components/reference/sources/richclay/src/sanitize.js +189 -0
  462. package/examples/components/reference/sources/richclay/src/styles.js +23 -0
  463. package/examples/components/reference/sources/richclay/src/toolbar-float.js +175 -0
  464. package/examples/components/reference/sources/richclay/src/toolbar.js +394 -0
  465. package/examples/components/reference/sources/richclay/src/vendor-bundle.js +15 -0
  466. package/examples/components/reference/sources/richclay/vendor/DOMPURIFY-LICENSE +202 -0
  467. package/examples/components/reference/sources/richclay/vendor/DOMPURIFY-LICENSE-MPL +373 -0
  468. package/examples/components/reference/sources/richclay/vendor/SQUIRE-LICENSE +21 -0
  469. package/examples/components/reference/sources/richclay/vendor/purify.es.mjs +2249 -0
  470. package/examples/components/reference/sources/richclay/vendor/purify.min.js +3 -0
  471. package/examples/components/reference/sources/richclay/vendor/squire.js +22 -0
  472. package/examples/components/reference/sources/richclay/vendor/squire.mjs +22 -0
  473. package/examples/components/reference/sources/richclay/vendor/squire.provenance.json +19 -0
  474. package/examples/components/rich-text-toolbar.html +43 -0
  475. package/examples/components/save-status-indicator.html +11 -0
  476. package/examples/components/selectable-cards.html +9 -0
  477. package/examples/components/settings-rows.html +10 -0
  478. package/examples/components/sidebar-nav.html +9 -0
  479. package/examples/components/small-charts.html +21 -0
  480. package/examples/components/split-button.html +13 -0
  481. package/examples/components/split-panes-editor.html +6 -0
  482. package/examples/components/split-panes.html +9 -0
  483. package/examples/components/stat-tiles.html +23 -0
  484. package/examples/components/toast-stack.html +21 -0
  485. package/examples/components/tree-view.html +9 -0
  486. package/examples/components/upload-dropzone.html +88 -0
  487. package/examples/components/wizard-shell.html +50 -0
  488. package/examples/datastar/index.html +38 -0
  489. package/examples/datastar/server.mjs +31 -0
  490. package/examples/fixtures/field-guide.pdf +14 -0
  491. package/examples/fixtures/workspace.jpg +0 -0
  492. package/examples/setup-peers.mjs +35 -0
  493. package/fonts/LICENSE-ibm-plex-mono.txt +93 -0
  494. package/fonts/LICENSE-ibm-plex-sans.txt +93 -0
  495. package/fonts/LICENSE-newsreader.txt +93 -0
  496. package/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  497. package/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
  498. package/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
  499. package/fonts/ibm-plex-sans-latin-400-italic.woff2 +0 -0
  500. package/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
  501. package/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
  502. package/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
  503. package/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
  504. package/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
  505. package/icons/LICENSE +21 -0
  506. package/icons/house.json +71 -0
  507. package/icons/icons.d.ts +17 -0
  508. package/icons/icons.js +648 -0
  509. package/icons/icons.svg +126 -0
  510. package/icons/marks/build-tray.source.mjs +45 -0
  511. package/icons/marks/hyperclay-local.svg +11 -0
  512. package/icons/phosphor.json +53 -0
  513. package/icons/round.json +8 -0
  514. package/integrations/datastar.js +202 -0
  515. package/integrations/quickcrop.css +26 -0
  516. package/integrations/quickcrop.js +56 -0
  517. package/integrations/richclay.css +100 -0
  518. package/integrations/richclay.js +131 -0
  519. package/package.json +630 -0
  520. package/react/README.md +244 -0
  521. package/src/README.md +83 -0
  522. package/vendor/datastar/datastar-1.0.3.js +10 -0
  523. package/vendor/datastar/provenance.json +6 -0
  524. package/vendor/floating-ui/LICENSE-core +20 -0
  525. package/vendor/floating-ui/LICENSE-dom +20 -0
  526. package/vendor/floating-ui/floating-ui.core.umd.min.js +1 -0
  527. package/vendor/floating-ui/floating-ui.dom.umd.min.js +1 -0
  528. package/vendor/floating-ui/provenance.json +17 -0
  529. package/vendor/richclay/LICENSE +16 -0
  530. package/vendor/richclay/THIRD-PARTY-NOTICES.md +45 -0
  531. package/vendor/richclay/provenance.json +17 -0
  532. package/vendor/richclay/richclay.css +404 -0
  533. package/vendor/richclay/richclay.js +2940 -0
  534. package/vendor/richclay/vendor/DOMPURIFY-LICENSE +202 -0
  535. package/vendor/richclay/vendor/DOMPURIFY-LICENSE-MPL +373 -0
  536. package/vendor/richclay/vendor/SQUIRE-LICENSE +21 -0
  537. package/vendor/richclay/vendor/purify.min.js +3 -0
  538. package/vendor/richclay/vendor/squire.js +22 -0
  539. package/vendor/richclay/vendor/squire.provenance.json +30 -0
@@ -0,0 +1,518 @@
1
+ import {
2
+ findTemplate,
3
+ isInlineTemplate,
4
+ humanize,
5
+ shapeKindOf,
6
+ componentForScalarRule,
7
+ componentForScalarArrayRule,
8
+ winningScalarArrayComponent,
9
+ resolveTemplate,
10
+ declaredComponentKey,
11
+ readOptionsOverride,
12
+ readCropOverride,
13
+ } from './templates.js'
14
+ import { fieldPropertyFor } from './form-rules.js'
15
+
16
+ // The visible label for a file field is the basename of its URL value; the
17
+ // bound leaf still carries the full URL in href so it round-trips byte-stable.
18
+ export function fileNameFromUrl(url) {
19
+ if (!url) return ''
20
+ const clean = String(url).split(/[?#]/)[0]
21
+ const base = clean.split('/').pop() || clean
22
+ try {
23
+ return decodeURIComponent(base)
24
+ } catch {
25
+ return base
26
+ }
27
+ }
28
+
29
+ export function buildForm({ pageRules, formRules: _formRules, data, doc }) {
30
+ const fragment = doc.createDocumentFragment()
31
+ const root = buildNode(pageRules, [], data, doc, pageRules)
32
+ if (root) fragment.appendChild(root)
33
+ return fragment
34
+ }
35
+
36
+ // pageRules rides alongside doc so a scalar bound to its own context element
37
+ // ("." / "@attr") can resolve the row that carries its named control; doc alone
38
+ // cannot answer that, because the row is only knowable from the enclosing array
39
+ // rule. deriveFormRules resolves it from the same pair, which is what keeps the
40
+ // built form and the derived rules in lockstep.
41
+ export function buildItem({ shape, itemShape, pathArr, data, doc, itemKey, pageRules }) {
42
+ if (shape === 'object-array-item') {
43
+ return buildObjectArrayItem(itemShape, pathArr, data, doc, pageRules)
44
+ }
45
+ if (shape === 'scalar-array-item') {
46
+ return buildScalarArrayItem(pathArr, data, doc, itemKey || null)
47
+ }
48
+ throw new Error(`hypercms: buildItem called with unknown shape "${shape}"`)
49
+ }
50
+
51
+ function buildNode(rule, pathArr, data, doc, pageRules) {
52
+ const kind = shapeKindOf(rule)
53
+ if (kind === 'scalar') return buildScalar(rule, pathArr, data, doc, pageRules)
54
+ if (kind === 'object') return buildObject(rule, pathArr, data, doc, pageRules)
55
+ if (kind === 'object-array') return buildObjectArray(rule, pathArr, data, doc, pageRules)
56
+ if (kind === 'scalar-array') return buildScalarArray(rule, pathArr, data, doc)
57
+ return null
58
+ }
59
+
60
+ function buildScalar(rule, pathArr, data, doc, pageRules) {
61
+ // Opt-in components select a richer template off the bound rule (explicit
62
+ // data-hcms-component, then @prop inference); plain scalars stay @scalar.
63
+ // A path-bound template override still wins inside resolveTemplate.
64
+ const componentKey = componentForScalarRule(rule, doc, pathArr, pageRules)
65
+ const tpl = resolveTemplate(pathArr, componentKey, doc)
66
+ if (!tpl) throw new Error(`hypercms: missing template for scalar at "${pathArr.join('.')}"`)
67
+ const declaredKey = declaredComponentKey(rule, doc, pathArr, pageRules)
68
+ // A value-guard fell back to text: say so, or "where did my number input /
69
+ // checkbox go" has no answer.
70
+ if (declaredKey === '@number' && componentKey === '@scalar') {
71
+ console.info(
72
+ `[hypercms] field "${pathArr.join('.')}" declares component "@number" but its value isn't a plain number; rendering a text input so the value is preserved`
73
+ )
74
+ }
75
+ if ((declaredKey === '@checkbox' || declaredKey === '@toggle') && componentKey === '@scalar') {
76
+ console.info(
77
+ `[hypercms] field "${pathArr.join('.')}" declares component "${declaredKey}" but its value isn't true/false; rendering a text input so the value is preserved`
78
+ )
79
+ }
80
+ noteShadowedComponent(tpl, declaredKey === componentKey ? declaredKey : null, pathArr)
81
+ const node = cloneTemplate(tpl, doc)
82
+ stampPath(node, pathArr)
83
+ // Component-specific setup runs only when the component's own template won —
84
+ // a custom path/wildcard template that shadows it is the author's UI, and
85
+ // injecting options, dropping radio rows, or stamping crop into it would
86
+ // corrupt that UI.
87
+ const winnerKey = tpl.getAttribute?.('data-hcms-tpl')
88
+ if ((componentKey === '@select' || componentKey === '@radio') && winnerKey === componentKey) {
89
+ populateOptions(node, rule, pathArr, data, doc, componentKey, pageRules)
90
+ }
91
+ if (componentKey === '@image' && winnerKey === '@image') {
92
+ const crop = readCropOverride(rule, doc, pathArr, pageRules)
93
+ if (crop != null && !node.hasAttribute('data-hcms-crop')) node.setAttribute('data-hcms-crop', crop)
94
+ }
95
+ // Stamp leaf input(s) FIRST so the container's data-hcms-field doesn't
96
+ // make stampScalarField early-return (which would leave the input without
97
+ // a key).
98
+ stampScalarField(node, lastKey(pathArr))
99
+ // Then stamp the wrapping container so engine selectors can scope by key.
100
+ stampContainerField(node, lastKey(pathArr))
101
+ setLabel(node, lastKey(pathArr))
102
+ populateScalarValue(node, data)
103
+ if (componentKey === '@file') syncFileLeafText(node)
104
+ return node
105
+ }
106
+
107
+ // A custom template (exact or wildcard path) outranks a named component, by
108
+ // design: the author's template is the stronger signal. Surface the shadowing
109
+ // so "my data-hcms-component does nothing" has a visible answer — but only for
110
+ // EXPLICITLY declared components (declaredKey non-null): a custom template
111
+ // quietly outranking @src/@checked inference is unremarkable.
112
+ function noteShadowedComponent(tpl, declaredKey, pathArr) {
113
+ if (!declaredKey) return
114
+ const winner = tpl.getAttribute?.('data-hcms-tpl')
115
+ if (winner && winner !== declaredKey) {
116
+ console.info(
117
+ `[hypercms] field "${pathArr.join('.')}" declares component "${declaredKey}" but custom template "${winner}" wins`
118
+ )
119
+ }
120
+ }
121
+
122
+ // Fill a @select's <select> with <option>s, or clone a @radio's prototype row
123
+ // per option, from the page element's data-hcms-options tokens. The current
124
+ // page value is prepended when it isn't in the list, so opening the editor
125
+ // never silently changes data. Radio inputs get a per-field name derived from
126
+ // the path so sibling fields (and array items) never cross-group.
127
+ function populateOptions(node, rule, pathArr, data, doc, componentKey, pageRules) {
128
+ const provided = readOptionsOverride(rule, doc, pathArr, pageRules)
129
+ const values = provided ? [...provided] : []
130
+ const current = data == null ? '' : String(data)
131
+ if (current !== '' && !values.includes(current)) values.unshift(current)
132
+ if (!provided) {
133
+ // Missing data-hcms-options is an authoring error: surface it ALWAYS, not
134
+ // just when the page value is empty too. When a value exists, fall through
135
+ // and render it as the single option so the data still round-trips while
136
+ // the attribute is missing.
137
+ setFieldError(node, 'data-hcms-options required (space-separated values)')
138
+ if (values.length === 0) {
139
+ // No options AND no value: drop the radio prototype so no phantom empty
140
+ // row renders. The null/'' extract this leaves behind applies as ''
141
+ // (writePropOrAttr), matching the already empty page value, so no data
142
+ // moves.
143
+ node.querySelector('.mirk-radio')?.remove()
144
+ return
145
+ }
146
+ }
147
+ if (componentKey === '@select') {
148
+ const select = node.querySelector('select[data-hcms-field]')
149
+ if (!select) return
150
+ for (const v of values) {
151
+ const opt = doc.createElement('option')
152
+ opt.value = v
153
+ opt.textContent = humanize(v)
154
+ select.appendChild(opt)
155
+ }
156
+ return
157
+ }
158
+ const proto = node.querySelector('.mirk-radio')
159
+ if (!proto || !proto.parentNode) return
160
+ const name = radioGroupName(pathArr.join('.'))
161
+ for (const v of values) {
162
+ const row = proto.cloneNode(true)
163
+ const input = row.querySelector('input[type="radio"]')
164
+ if (input) {
165
+ input.value = v
166
+ input.name = name
167
+ }
168
+ const label = row.querySelector('.mirk-radio__label')
169
+ if (label) label.textContent = humanize(v)
170
+ proto.parentNode.insertBefore(row, proto)
171
+ }
172
+ proto.remove()
173
+ }
174
+
175
+ // The radio group name a field at this dot-path gets. Shared with the restamp
176
+ // machinery in events.js: names derive from paths, so when a remove/move
177
+ // restamps paths, the names must be recomputed with the same formula or
178
+ // sibling items end up sharing a group.
179
+ export function radioGroupName(pathStr) {
180
+ return 'hcms-' + String(pathStr).replace(/[^A-Za-z0-9_-]/g, '-')
181
+ }
182
+
183
+ function setFieldError(node, message) {
184
+ const slot = node.querySelector ? node.querySelector('.hcms-error') : null
185
+ if (!slot) return
186
+ slot.textContent = message
187
+ slot.hidden = false
188
+ }
189
+
190
+ // The @file leaf is an <a> whose value is the href; populateScalarValue sets
191
+ // href but not the visible text, so derive the filename here. Empty href leaves
192
+ // the anchor empty, which the theme's :empty placeholder dresses as "No file
193
+ // chosen". Scoped to the default chrome's .mirk-file__name so author overrides
194
+ // keep their own text.
195
+ function syncFileLeafText(node) {
196
+ const a = node.querySelector ? node.querySelector('a.mirk-file__name[data-hcms-field]') : null
197
+ if (a) a.textContent = fileNameFromUrl(a.getAttribute('href'))
198
+ }
199
+
200
+ function buildObject(rule, pathArr, data, doc, pageRules) {
201
+ const tpl = resolveTemplate(pathArr, '@object', doc)
202
+ if (!tpl) throw new Error(`hypercms: missing template for object at "${pathArr.join('.')}"`)
203
+ const node = cloneTemplate(tpl, doc)
204
+ stampPath(node, pathArr)
205
+ stampContainerField(node, lastKey(pathArr))
206
+ setLabel(node, lastKey(pathArr))
207
+
208
+ if (isInlineTemplate(tpl)) {
209
+ stampInlineFieldPaths(node, rule, pathArr)
210
+ populateInlineFields(node, rule, data)
211
+ return node
212
+ }
213
+
214
+ const slot = requireSlot(node, '.hcms-object-fields', tpl, pathArr)
215
+ for (const [k, child] of Object.entries(rule)) {
216
+ const childData = data == null ? null : data[k]
217
+ const childNode = buildNode(child, [...pathArr, k], childData, doc, pageRules)
218
+ if (childNode) slot.appendChild(childNode)
219
+ }
220
+ return node
221
+ }
222
+
223
+ function buildObjectArray(rule, pathArr, data, doc, pageRules) {
224
+ const tpl = resolveTemplate(pathArr, '@object-array', doc)
225
+ if (!tpl) throw new Error(`hypercms: missing template for object-array at "${pathArr.join('.')}"`)
226
+ const node = cloneTemplate(tpl, doc)
227
+ stampPath(node, pathArr)
228
+ stampContainerField(node, lastKey(pathArr))
229
+ setLabel(node, lastKey(pathArr))
230
+ copyArrayConstraintAttrs(node, tpl)
231
+ wireSortable(node, tpl, pathArr)
232
+
233
+ const slot = requireSlot(node, '.hcms-array-items', tpl, pathArr)
234
+ const [, itemShape] = rule
235
+ const items = Array.isArray(data) ? data : []
236
+ items.forEach((itemData, i) => {
237
+ const itemNode = buildObjectArrayItem(itemShape, [...pathArr, i], itemData, doc, pageRules)
238
+ if (itemNode) slot.appendChild(itemNode)
239
+ })
240
+ applyConstraintVisibility(node)
241
+ return node
242
+ }
243
+
244
+ function buildObjectArrayItem(itemShape, pathArr, data, doc, pageRules) {
245
+ const tpl = resolveItemTemplate(pathArr, 'object-array-item', doc)
246
+ if (!tpl) throw new Error(`hypercms: missing item template for "${pathArr.join('.')}"`)
247
+ const node = cloneTemplate(tpl, doc)
248
+ node.setAttribute('data-hcms-card', '')
249
+ if (!node.classList.contains('hcms-card')) node.classList.add('hcms-card')
250
+ stampPath(node, pathArr)
251
+
252
+ if (isInlineTemplate(tpl)) {
253
+ if (itemShape && typeof itemShape === 'object' && !Array.isArray(itemShape)) {
254
+ stampInlineFieldPaths(node, itemShape, pathArr)
255
+ populateInlineFields(node, itemShape, data)
256
+ }
257
+ return node
258
+ }
259
+
260
+ const slot = requireSlot(node, '.hcms-card-fields', tpl, pathArr)
261
+ if (itemShape && typeof itemShape === 'object' && !Array.isArray(itemShape)) {
262
+ for (const [k, child] of Object.entries(itemShape)) {
263
+ const childData = data == null ? null : data[k]
264
+ const childNode = buildNode(child, [...pathArr, k], childData, doc, pageRules)
265
+ if (childNode) slot.appendChild(childNode)
266
+ }
267
+ }
268
+ return node
269
+ }
270
+
271
+ function buildScalarArray(rule, pathArr, data, doc) {
272
+ // The chips component swaps the scalar-array chrome (data-hcms-component=
273
+ // "chips" on the list container or an item ancestor). A path-bound template
274
+ // still wins inside resolveTemplate — and when it does, `comp` is null
275
+ // (winningScalarArrayComponent shares that verdict with deriveFormRules, so
276
+ // the item chrome and the derived item selector can never diverge) and the
277
+ // custom template's own UI is left untouched.
278
+ const declared = componentForScalarArrayRule(rule, doc)
279
+ const comp = winningScalarArrayComponent(rule, pathArr, doc)
280
+ const defaultKey = declared ? declared.array : '@scalar-array'
281
+ const tpl = resolveTemplate(pathArr, defaultKey, doc)
282
+ if (!tpl) throw new Error(`hypercms: missing template for scalar-array at "${pathArr.join('.')}"`)
283
+ // chips is always an explicit declaration (attr-driven), so always notable.
284
+ noteShadowedComponent(tpl, declared ? declared.array : null, pathArr)
285
+ const node = cloneTemplate(tpl, doc)
286
+ stampPath(node, pathArr)
287
+ stampContainerField(node, lastKey(pathArr))
288
+ setLabel(node, lastKey(pathArr))
289
+ copyArrayConstraintAttrs(node, tpl)
290
+ wireSortable(node, tpl, pathArr)
291
+ // Record the resolved item-template key so onAdd (which has no rule context)
292
+ // builds new items with the same component chrome.
293
+ if (comp) node.setAttribute('data-hcms-item-tpl', comp.item)
294
+
295
+ const slot = requireSlot(node, '.hcms-array-items', tpl, pathArr)
296
+ const items = Array.isArray(data) ? data : []
297
+ items.forEach((itemValue, i) => {
298
+ const itemNode = buildScalarArrayItem([...pathArr, i], itemValue, doc, comp ? comp.item : null)
299
+ if (itemNode) slot.appendChild(itemNode)
300
+ })
301
+ applyConstraintVisibility(node)
302
+ return node
303
+ }
304
+
305
+ function buildScalarArrayItem(pathArr, value, doc, itemKey) {
306
+ const tpl = resolveItemTemplate(pathArr, 'scalar-array-item', doc, itemKey)
307
+ if (!tpl) throw new Error(`hypercms: missing item template for "${pathArr.join('.')}"`)
308
+ const node = cloneTemplate(tpl, doc)
309
+ node.setAttribute('data-hcms-array-item', '')
310
+ if (!node.classList.contains('hcms-array-item')) node.classList.add('hcms-array-item')
311
+ stampPath(node, pathArr)
312
+
313
+ populateScalarValue(node, value)
314
+ return node
315
+ }
316
+
317
+ function resolveItemTemplate(pathArr, defaultShape, doc, itemKey) {
318
+ const wildcardKey = pathArr.map((s) => (typeof s === 'number' ? '*' : s)).join('.')
319
+ return (
320
+ findTemplate(doc, wildcardKey) ||
321
+ (itemKey && findTemplate(doc, itemKey)) ||
322
+ findTemplate(doc, '@' + defaultShape)
323
+ )
324
+ }
325
+
326
+ function cloneTemplate(tpl, doc) {
327
+ const content = tpl.content || tpl
328
+ const wrapper = doc.createElement('div')
329
+ wrapper.appendChild(content.cloneNode(true))
330
+ return wrapper.firstElementChild || wrapper
331
+ }
332
+
333
+ function stampPath(node, pathArr) {
334
+ node.setAttribute('data-hcms-path', pathArr.join('.'))
335
+ }
336
+
337
+ function stampScalarField(node, key) {
338
+ const targetKey = key == null ? '' : String(key)
339
+ if (node.matches && node.matches('[data-hcms-field]')) {
340
+ if (!node.getAttribute('data-hcms-field')) node.setAttribute('data-hcms-field', targetKey)
341
+ return
342
+ }
343
+ // Stamp every descendant input that's marked as a field but missing its key
344
+ // (radio groups have multiple inputs sharing the same key).
345
+ const fields = node.querySelectorAll ? node.querySelectorAll('[data-hcms-field]') : []
346
+ fields.forEach((field) => {
347
+ if (!field.getAttribute('data-hcms-field')) field.setAttribute('data-hcms-field', targetKey)
348
+ })
349
+ }
350
+
351
+ // Stamp data-hcms-field on the WRAPPING container so engine selectors can
352
+ // scope by key (e.g. nested arrays sharing a terminal name). The leaf input's
353
+ // data-hcms-field carries the same key — form-rules selectors use tag-specific
354
+ // qualifiers (`input[data-hcms-field=...]`) so the container doesn't shadow.
355
+ function stampContainerField(node, key) {
356
+ if (key == null || key === '' || !node.setAttribute) return
357
+ // Don't overwrite an existing data-hcms-field attribute (e.g. when the
358
+ // template author already stamped it deliberately).
359
+ if (node.hasAttribute?.('data-hcms-field')) return
360
+ node.setAttribute('data-hcms-field', String(key))
361
+ }
362
+
363
+ function setLabel(node, key) {
364
+ if (key == null || key === '') return
365
+ const labels = node.querySelectorAll
366
+ ? node.querySelectorAll('[data-hcms-label]')
367
+ : []
368
+ labels.forEach((el) => {
369
+ const t = el.textContent || ''
370
+ if (t.trim() === '') el.textContent = humanize(String(key))
371
+ })
372
+ }
373
+
374
+ function copyArrayConstraintAttrs(node, tpl) {
375
+ ;['data-hcms-no-add', 'data-hcms-no-remove', 'data-hcms-no-reorder'].forEach((attr) => {
376
+ if (tpl.hasAttribute(attr)) node.setAttribute(attr, '')
377
+ })
378
+ ;['data-hcms-min-items', 'data-hcms-max-items'].forEach((attr) => {
379
+ if (tpl.hasAttribute(attr)) node.setAttribute(attr, tpl.getAttribute(attr))
380
+ })
381
+ }
382
+
383
+ function applyConstraintVisibility(arrayEl) {
384
+ const slot = arrayEl.querySelector ? arrayEl.querySelector('.hcms-array-items') : null
385
+ if (!slot) return
386
+ const items = Array.from(slot.querySelectorAll(':scope > [data-hcms-card], :scope > [data-hcms-array-item]'))
387
+ const count = items.length
388
+ const max = readIntAttr(arrayEl, 'data-hcms-max-items')
389
+ const min = readIntAttr(arrayEl, 'data-hcms-min-items')
390
+ const noAdd = arrayEl.hasAttribute('data-hcms-no-add')
391
+ const noRemove = arrayEl.hasAttribute('data-hcms-no-remove')
392
+ const noReorder = arrayEl.hasAttribute('data-hcms-no-reorder')
393
+ const addBtn = arrayEl.querySelector('[data-hcms-action="add"]')
394
+ if (addBtn) addBtn.hidden = noAdd || (max != null && count >= max)
395
+ items.forEach((item, i) => {
396
+ const rm = item.querySelector('[data-hcms-action="remove"]')
397
+ if (rm) rm.hidden = noRemove || (min != null && count <= min)
398
+ const up = item.querySelector('[data-hcms-action="move-up"]')
399
+ if (up) up.hidden = noReorder || i === 0
400
+ const dn = item.querySelector('[data-hcms-action="move-down"]')
401
+ if (dn) dn.hidden = noReorder || i === count - 1
402
+ })
403
+ }
404
+
405
+ function readIntAttr(el, name) {
406
+ if (!el || !el.hasAttribute(name)) return null
407
+ const n = parseInt(el.getAttribute(name), 10)
408
+ return Number.isFinite(n) ? n : null
409
+ }
410
+
411
+ function wireSortable(node, tpl, pathArr) {
412
+ if (node.hasAttribute('data-hcms-no-reorder') || tpl.hasAttribute('data-hcms-no-reorder')) return
413
+ const slot = node.querySelector('.hcms-array-items')
414
+ if (!slot) return
415
+ const groupName = 'hcms-' + pathArr.join('.')
416
+ slot.setAttribute('sortable', groupName)
417
+ // hyperclayjs's [sortable] attribute compiles `onsorted` as a code body
418
+ // (new Function), so we invoke a top-level callable instead of pointing at
419
+ // a function reference. The callable is installed by hypercms.js open().
420
+ slot.setAttribute('onsorted', 'hypercmsCommit && hypercmsCommit()')
421
+ }
422
+
423
+ function lastKey(pathArr) {
424
+ if (!pathArr.length) return null
425
+ return pathArr[pathArr.length - 1]
426
+ }
427
+
428
+ function populateScalarValue(node, value) {
429
+ // Radio groups have multiple <input data-hcms-field>s; writeValue handles
430
+ // each radio individually (checks against its `value`). Write to ALL leaf
431
+ // fields under the wrapper, skipping the wrapper itself if it happens to
432
+ // carry data-hcms-field too.
433
+ const targets = collectLeafFields(node)
434
+ if (targets.length === 0) return
435
+ for (const t of targets) writeValue(t, value)
436
+ }
437
+
438
+ function collectLeafFields(node) {
439
+ if (!node) return []
440
+ const out = []
441
+ // The node itself is a leaf only if it's a recognized leaf tag (input,
442
+ // textarea, select, img, a, or contenteditable). Container shapes — even
443
+ // shape="scalar" wrappers — have child inputs we should target instead.
444
+ if (node.matches?.('[data-hcms-field]') && isLeafFieldEl(node)) {
445
+ out.push(node)
446
+ }
447
+ const descendants = node.querySelectorAll
448
+ ? node.querySelectorAll('input[data-hcms-field], textarea[data-hcms-field], select[data-hcms-field], img[data-hcms-field], a[data-hcms-field], [contenteditable][data-hcms-field]')
449
+ : []
450
+ descendants.forEach((d) => out.push(d))
451
+ return out
452
+ }
453
+
454
+ function isLeafFieldEl(el) {
455
+ const tag = (el.tagName || '').toUpperCase()
456
+ if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || tag === 'IMG' || tag === 'A') return true
457
+ if (el.hasAttribute?.('contenteditable')) return true
458
+ return false
459
+ }
460
+
461
+ function populateInlineFields(node, shape, data) {
462
+ const fields = node.querySelectorAll ? node.querySelectorAll('[data-hcms-field]') : []
463
+ fields.forEach((el) => {
464
+ const key = el.getAttribute('data-hcms-field')
465
+ if (!key) return
466
+ if (!shape || typeof shape !== 'object' || !(key in shape)) {
467
+ console.warn(`[hypercms] inline template field "${key}" is not in the rule shape; ignoring`)
468
+ return
469
+ }
470
+ const childValue = data == null ? null : data[key]
471
+ writeValue(el, childValue)
472
+ })
473
+ }
474
+
475
+ function stampInlineFieldPaths(node, shape, parentPath) {
476
+ if (!node.querySelectorAll) return
477
+ const fields = node.querySelectorAll('[data-hcms-field]')
478
+ fields.forEach((el) => {
479
+ const key = el.getAttribute('data-hcms-field')
480
+ if (!key) return
481
+ if (shape && typeof shape === 'object' && !(key in shape)) return
482
+ const childPath = [...parentPath, key].join('.')
483
+ el.setAttribute('data-hcms-path', childPath)
484
+ })
485
+ }
486
+
487
+ function requireSlot(node, slotSelector, tpl, pathArr) {
488
+ if (!node.querySelector) return node
489
+ const slot = node.querySelector(slotSelector)
490
+ if (slot) return slot
491
+ // Slotted templates must declare their slot. Inline-template detection has
492
+ // already short-circuited above, so missing slot here is a real authoring bug.
493
+ const id = tpl?.getAttribute?.('data-hcms-tpl') || pathArr.join('.')
494
+ throw new Error(
495
+ `hypercms: template "${id}" is in slotted mode but has no ${slotSelector} element`
496
+ )
497
+ }
498
+
499
+ function writeValue(el, value) {
500
+ const prop = fieldPropertyFor(el)
501
+ const tag = (el.tagName || '').toUpperCase()
502
+ const type = (el.getAttribute('type') || '').toLowerCase()
503
+ if (tag === 'INPUT' && type === 'radio') {
504
+ el.checked = el.value != null && String(el.value) === String(value ?? '')
505
+ return
506
+ }
507
+ if (prop === 'checked') {
508
+ // Coerce strings "true"/"false" the same way coerceBooleans does, so even
509
+ // raw page-extract values (which engine stringifies) don't flip false → true.
510
+ el.checked = value === true || value === 'true'
511
+ return
512
+ }
513
+ if (prop) {
514
+ el[prop] = value == null ? '' : String(value)
515
+ return
516
+ }
517
+ el.textContent = value == null ? '' : String(value)
518
+ }