@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,10 @@
1
+ export function scaffold(shape) {
2
+ if (typeof shape === 'string') return shape.endsWith('[]') ? [] : ''
3
+ if (Array.isArray(shape)) return []
4
+ if (typeof shape === 'object' && shape !== null) {
5
+ const out = {}
6
+ for (const [k, v] of Object.entries(shape)) out[k] = scaffold(v)
7
+ return out
8
+ }
9
+ return ''
10
+ }
@@ -0,0 +1,303 @@
1
+ // The session core: everything an editing session is, independent of the chrome
2
+ // that renders it. Rule resolution, the ctx object every module reads, the first
3
+ // extract, the observer / undo / live-sync subscriptions, the global sortable
4
+ // wiring, event dispatch, and one idempotent teardown. A view (src/views/*)
5
+ // supplies the DOM; the session owns the state and the page.
6
+
7
+ import { engine } from 'hyper-html-api'
8
+ import { injectDefaults, injectComponents } from './templates.js'
9
+ import { deriveFormRules } from './form-rules.js'
10
+ import { warnUnmatchedTemplates } from './diagnostics.js'
11
+ import { findUnresolved, stripReadOnly } from './unresolved.js'
12
+ import { rowIdentitySeeder } from './row-identity.js'
13
+ import {
14
+ commit,
15
+ commitWithUndo,
16
+ suppressUndo,
17
+ extractFormData,
18
+ stableStringify,
19
+ restampAllSiblings,
20
+ coerceBooleans,
21
+ } from './events.js'
22
+ import { installObserver } from './refresh.js'
23
+ import { platform, onPlatformEvent, LIVESYNC_APPLIED } from './platform.js'
24
+
25
+ const ENGINE_OPTS = { skip: '[data-hcms-shell]', templateAttr: 'cms-template' }
26
+
27
+ export const state = {
28
+ isOpen: false,
29
+ ctx: null,
30
+ opts: null,
31
+ }
32
+
33
+ // Build the session for one open(): resolve the rules, hand them to the view for
34
+ // its own preparation, derive the form schema, and take the first read of the
35
+ // page. The view is not mounted yet — ctx reads its DOM handles lazily, so the
36
+ // mount can stay inside open()'s try block.
37
+ export function createSession({ view, doc, pageRoot, opts = {}, onCloseRequested, onViewRequested }) {
38
+ // Resolve rules via the union: an explicit rules object, a token string, or
39
+ // the default token "cms". findRules is document-scoped, so a head-mounted
40
+ // rules tag is found even though pageRoot defaults to <body>.
41
+ const source = opts.rules !== undefined ? opts.rules : 'cms'
42
+ const found = engine.findRules(doc, source)
43
+ if (!found) {
44
+ const what = typeof source === 'string' ? `data-rules-name~="${source}"` : 'the provided rules object'
45
+ throw new Error(`hypercms: no rules found for ${what}`)
46
+ }
47
+ // The view's rule seam. The sidebar applies the rich-text upgrade (default on):
48
+ // bare scalar rules whose page element contains child elements are rebound
49
+ // through @innerHTML so links and inline formatting survive the round-trip, and
50
+ // their form fields render the @richtext component.
51
+ const pageRules = view.prepareRules(found.rules)
52
+ const rulesTagNode = found.tagNode
53
+
54
+ injectDefaults(doc)
55
+ injectComponents(doc, pageRules)
56
+ warnUnmatchedTemplates(doc, pageRules)
57
+ const formRules = deriveFormRules(pageRules, doc)
58
+ // The write half of the rules; see stripReadOnly. The form and every extract
59
+ // keep the full tree.
60
+ const writeRules = stripReadOnly(pageRules)
61
+ // Runs before the first extract so a rule with invalid CSS names its field
62
+ // instead of throwing a bare SyntaxError out of querySelectorAll.
63
+ const unresolved = findUnresolved(pageRoot, pageRules)
64
+ // Bind each form row to the page row it stands for while the two are still
65
+ // known to correspond, which is now: the form the view builds comes from
66
+ // exactly this read. Without it the first structural operation of a session has
67
+ // no identity to go on and falls back to content matching.
68
+ const seeder = rowIdentitySeeder()
69
+ const data = coerceBooleans(engine.extract(pageRoot, pageRules, { ...ENGINE_OPTS, ...seeder.hooks }), pageRules)
70
+
71
+ const ctx = {
72
+ doc,
73
+ pageRoot,
74
+ pageRules,
75
+ writeRules,
76
+ formRules,
77
+ rulesTagNode,
78
+ rulesSource: source,
79
+ richText: view.richText,
80
+ view,
81
+ seeder,
82
+ initialData: data,
83
+ get formRoot() { return view.formRoot },
84
+ get shellRoot() { return view.root },
85
+ get errorEl() { return view.errorEl },
86
+ get noticeEl() { return view.noticeEl },
87
+ unresolved,
88
+ lastTwinSignature: null,
89
+ lastFingerprint: null,
90
+ lastData: null,
91
+ observerHandle: null,
92
+ undoUnsub: null,
93
+ livesyncUnsub: null,
94
+ onChange: opts.onChange,
95
+ onError: opts.onError,
96
+ confirmRemove: opts.confirmRemove,
97
+ previouslyFocused: doc.activeElement,
98
+ dispatch(name, detail) {
99
+ const Ctor = (doc.defaultView && doc.defaultView.CustomEvent) || (typeof CustomEvent !== 'undefined' ? CustomEvent : null)
100
+ if (!Ctor) return
101
+ // Every event carries the page it belongs to and which view is rendering
102
+ // it, so a document-level listener can tell a sidebar session from an
103
+ // inline one without inspecting the DOM. Merged into the caller's detail
104
+ // rather than replacing it: hcms:change still carries .data, hcms:error
105
+ // still carries .error.
106
+ const payload = { ...(detail || {}), pageRoot, view: view.name }
107
+ const ev = new Ctor(name, { bubbles: true, cancelable: name === 'hcms:change', detail: payload })
108
+ // A full-document morph (live sync, a version restore) can replace the
109
+ // view root between mount and dispatch. Falling back to the page keeps the
110
+ // event on the document instead of firing it into a detached tree where no
111
+ // listener will ever see it.
112
+ const target = view.root && view.root.isConnected !== false ? view.root : pageRoot
113
+ target.dispatchEvent(ev)
114
+ },
115
+ onCloseRequested,
116
+ // How a view asks to be rendered as a different one. The switch runs through
117
+ // open({ view }), which carries this session's options across it, so the
118
+ // request changes the presentation and not the session.
119
+ onViewRequested,
120
+ }
121
+ ctx.updateFingerprint = () => {
122
+ ctx.lastFingerprint = stableStringify(extractFormData(ctx))
123
+ }
124
+ view.ctx = ctx
125
+ return ctx
126
+ }
127
+
128
+ // Everything that outlives the mount: the fingerprint the commit path compares
129
+ // against, and the three external subscriptions plus the global sortable hook.
130
+ // Runs after the view is mounted, so a throw here is caught by open() and routed
131
+ // through teardownSession.
132
+ export function startSession(ctx) {
133
+ ctx.updateFingerprint()
134
+
135
+ ctx.observerHandle = installObserver({
136
+ onRefresh: (changes) => ctx.view.refresh('observer', changes),
137
+ })
138
+
139
+ // Undo/redo is a deliberate local action (unlike livesync or in-flight typing),
140
+ // so the focused form field SHOULD snap to the reverted value. The observer above
141
+ // is source-blind, so subscribe to the undo scope and force a non-ignoring refresh.
142
+ // Fires synchronously before the debounced observer refresh, which then no-ops on
143
+ // the active field. Guarded so it degrades to today's behavior when undo isn't loaded.
144
+ const u = platform('undo')
145
+ if (u && typeof u.on === 'function') {
146
+ const onRevert = () => {
147
+ if (state.ctx !== ctx) return
148
+ resyncForm(ctx, 'undo')
149
+ // A reverted change the consumer persists through onChange (e.g. the
150
+ // collection dashboard PUTs the record, not the page) would otherwise lag
151
+ // the undo: refreshForm re-syncs the form but never fires onChange, and a
152
+ // commit() here would be fingerprint-skipped (refreshForm already updated
153
+ // it). Extract the reverted state from the PAGE (the source of truth after
154
+ // an undo/redo; the form can lag a morph) and fire onChange directly, but
155
+ // only when it actually changed — guards spurious PUTs on undo/redo of
156
+ // unrelated edits elsewhere on the page.
157
+ const data = coerceBooleans(
158
+ engine.extract(ctx.pageRoot, ctx.pageRules, ENGINE_OPTS),
159
+ ctx.pageRules
160
+ )
161
+ if (stableStringify(data) !== stableStringify(ctx.lastData)) {
162
+ ctx.lastData = data
163
+ ctx.onChange?.(data, { path: '', structural: false })
164
+ }
165
+ }
166
+ u.on('undo', onRevert)
167
+ u.on('redo', onRevert)
168
+ ctx.undoUnsub = () => { u.off('undo', onRevert); u.off('redo', onRevert) }
169
+ }
170
+
171
+ // Live-sync / version-restore / any framework-applied full-document morph runs
172
+ // inside window.hyperclay.Mutation.pause(), which the source-blind observer
173
+ // above is deaf to — so without this the form stays stale after a remote edit
174
+ // and the next local commit re-applies the stale data, clobbering the remote
175
+ // change. Subscribe to the morph-applied signal live-sync emits and re-extract
176
+ // with ignoreActiveValue:true (preserve the user's in-progress field). Same
177
+ // document live-sync dispatches on; unsubscribed in teardownSession.
178
+ const onLivesync = () => resyncForm(ctx, 'livesync')
179
+ ctx.livesyncUnsub = onPlatformEvent(ctx.doc, LIVESYNC_APPLIED, onLivesync)
180
+
181
+ // Wire global sortable callback to current ctx (cleared by teardownSession).
182
+ globalCommitTarget.ctx = ctx
183
+ installGlobalSortableCommit(ctx.doc)
184
+ }
185
+
186
+ // Re-sync the view to the page after a change hypercms did NOT originate.
187
+ // `reason` selects whether the field the user is currently typing in snaps:
188
+ // 'undo' / 'redo' — the user's own deliberate action, so the focused field
189
+ // SHOULD snap to the reverted value (ignoreActiveValue:false).
190
+ // 'livesync' — someone else's / the framework's change, so the user's
191
+ // in-progress focused field must NOT be yanked away
192
+ // (ignoreActiveValue:true). morphForm re-extracts every
193
+ // other field to the new page value, killing the stale-form
194
+ // clobber, while leaving the active field alone until blur.
195
+ // Both reasons route through the view's one refresh entry point.
196
+ function resyncForm(ctx, reason) {
197
+ // open() may have moved on (closed, or reopened with a new ctx) between an
198
+ // async morph completing and this firing.
199
+ if (state.ctx !== ctx) return
200
+ ctx.view.refresh(reason)
201
+ }
202
+
203
+ // The one teardown. close(), the failed-open path inside open(), and (later) a
204
+ // view switch all route through it; the options say only which of the three
205
+ // close-specific side effects apply.
206
+ export function teardownSession(ctx, { dispatch = true, restoreFocus = true, updateUrl = true, reason = 'close' } = {}) {
207
+ if (!ctx || ctx.closed) return
208
+ // Mark this ctx dead so any in-flight async work (e.g. an upload awaiting the
209
+ // host uploader) bails instead of mutating the page / firing onChange after
210
+ // teardown. Mirrors the state.ctx !== ctx guards on the undo/livesync paths.
211
+ ctx.closed = true
212
+ // An upload still in flight is torn down like any other subscription. The
213
+ // ctx.closed check above already stops it writing; this stops it running.
214
+ for (const controller of ctx.uploads || []) { try { controller.abort() } catch {} }
215
+ ctx.uploads?.clear()
216
+ const previouslyFocused = ctx.previouslyFocused
217
+ if (dispatch) ctx.dispatch('hcms:close', { reason })
218
+ if (updateUrl) toggleCloseParam()
219
+ ctx.observerHandle?.unsubscribe?.()
220
+ ctx.undoUnsub?.()
221
+ ctx.livesyncUnsub?.()
222
+ ctx.detachEvents?.()
223
+ // destroy() removes the chrome-only body classes; suppress so the inverse
224
+ // class removal doesn't enter the undo stack either.
225
+ suppressUndo(() => ctx.view.destroy())
226
+ clearState()
227
+ if (restoreFocus && typeof previouslyFocused?.focus === 'function') {
228
+ try { previouslyFocused.focus() } catch (_) {}
229
+ }
230
+ }
231
+
232
+ function clearState() {
233
+ state.isOpen = false
234
+ state.ctx = null
235
+ state.opts = null
236
+ globalCommitTarget.ctx = null
237
+ }
238
+
239
+ const globalCommitTarget = { ctx: null }
240
+
241
+ function installGlobalSortableCommit(doc) {
242
+ const win = doc.defaultView || (typeof globalThis !== 'undefined' ? globalThis : null)
243
+ if (!win) return
244
+ const hypercmsCommitFn = function hypercmsCommitGlobal() {
245
+ const ctx = globalCommitTarget.ctx
246
+ if (!ctx) return
247
+ restampAllSiblings(ctx.formRoot)
248
+ // Route through commitWithUndo so a drag-reorder lands as a labeled
249
+ // 'Reorder' commit (not a generic idle 'Edit') and a failed apply's
250
+ // mutate+rollback is never recorded as a no-op commit. No-op pass-through
251
+ // when undo isn't loaded.
252
+ return commitWithUndo('Reorder', () =>
253
+ commit(extractFormData(ctx), { path: '', structural: true }, ctx)
254
+ )
255
+ }
256
+ if (typeof win.hypercmsCommit !== 'function') win.hypercmsCommit = hypercmsCommitFn
257
+ // Also mirror to globalThis so non-window contexts (Node tests, workers)
258
+ // can resolve the bare name from `new Function('hypercmsCommit()')`.
259
+ if (typeof globalThis !== 'undefined' && typeof globalThis.hypercmsCommit !== 'function') {
260
+ globalThis.hypercmsCommit = hypercmsCommitFn
261
+ }
262
+ }
263
+
264
+ // The query param that drives ?cms=true auto-open. Closing the CMS rewrites it
265
+ // to cms=false (param kept) so a refresh/share of the post-close URL does not
266
+ // auto-reopen.
267
+ const AUTO_OPEN_PARAM = 'cms'
268
+
269
+ // Pure: given a location.search string, return the search string after a close.
270
+ // Only rewrites when cms=true is present; every other param + ordering is
271
+ // preserved, and a search without cms (or already cms=false) is returned
272
+ // unchanged so we never inject the param into a page that never carried it.
273
+ export function nextSearchAfterClose(search) {
274
+ const str = typeof search === 'string' ? search : ''
275
+ const qIndex = str.indexOf('?')
276
+ const query = qIndex === -1 ? str : str.slice(qIndex + 1)
277
+ if (!query) return str
278
+ const params = new URLSearchParams(query)
279
+ if (params.get(AUTO_OPEN_PARAM) !== 'true') return str
280
+ params.set(AUTO_OPEN_PARAM, 'false')
281
+ return '?' + params.toString()
282
+ }
283
+
284
+ // Pure: should the CMS auto-open for this location.search? Exactly 'true'.
285
+ export function shouldAutoOpenFromSearch(search) {
286
+ const str = typeof search === 'string' ? search : ''
287
+ const qIndex = str.indexOf('?')
288
+ const query = qIndex === -1 ? str : str.slice(qIndex + 1)
289
+ if (!query) return false
290
+ return new URLSearchParams(query).get(AUTO_OPEN_PARAM) === 'true'
291
+ }
292
+
293
+ // Rewrite ?cms=true → ?cms=false via history.replaceState (no reload, hash and
294
+ // every other param preserved). No-op when the param isn't present or the
295
+ // History API is unavailable.
296
+ function toggleCloseParam() {
297
+ if (typeof window === 'undefined' || !window.location || !window.history) return
298
+ if (typeof window.history.replaceState !== 'function') return
299
+ const current = window.location.search
300
+ const next = nextSearchAfterClose(current)
301
+ if (next === current) return
302
+ window.history.replaceState(window.history.state, '', next + window.location.hash)
303
+ }
@@ -0,0 +1,248 @@
1
+ const SHELL_STYLE_ID = 'hcms-shell-styles'
2
+ const SHELL_BUNDLED_FLAG = 'hcms-bundled-styles-installed'
3
+ // "A session of either kind is open", so a page (or the toggle) can style off
4
+ // open state without reaching for hcms-open, which describes only this panel's
5
+ // page shift and is absent for an inline session. Additive: hcms-open keeps its
6
+ // meaning exactly. Both views add it on mount and drop it on destroy.
7
+ export const SESSION_OPEN_CLASS = 'hcms-session-open'
8
+ const FOCUSABLE = 'a[href], area[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
9
+
10
+ const styledDocs = new WeakSet()
11
+ let cssText = ''
12
+
13
+ export function setShellStyles(text) {
14
+ cssText = text
15
+ }
16
+
17
+ export function markStylesBundled(doc) {
18
+ // Bundler emits a <style data-hcms-bundled-styles> tag and sets this so
19
+ // the link-based path doesn't double-install.
20
+ if (!doc) return
21
+ styledDocs.add(doc)
22
+ doc[SHELL_BUNDLED_FLAG] = true
23
+ }
24
+
25
+ export function markSessionOpen(doc) {
26
+ doc?.body?.classList.add(SESSION_OPEN_CLASS)
27
+ }
28
+
29
+ export function clearSessionOpen(doc) {
30
+ doc?.body?.classList.remove(SESSION_OPEN_CLASS)
31
+ }
32
+
33
+ let titleIdCounter = 0
34
+
35
+ function escapeHtml(s) {
36
+ return String(s).replace(/[&<>"]/g, (c) => (
37
+ { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]
38
+ ))
39
+ }
40
+
41
+ export function mountShell({
42
+ mountTo,
43
+ side = 'right',
44
+ overlay = false,
45
+ showSaveButton = false,
46
+ title = 'Page content',
47
+ eyebrow = 'Edit',
48
+ theme = null,
49
+ doc,
50
+ }) {
51
+ ensureStyles(doc)
52
+ const titleId = `hcms-shell-title-${++titleIdCounter}`
53
+ const root = doc.createElement('div')
54
+ root.setAttribute('data-hcms-shell', '')
55
+ root.setAttribute('save-remove', '')
56
+ root.setAttribute('save-ignore', '')
57
+ root.setAttribute('tabindex', '-1')
58
+ // Dialog semantics: focus is trapped + body scrolling locked, so screen
59
+ // readers should announce this as a modal dialog with the shell title as
60
+ // its accessible name.
61
+ root.setAttribute('role', 'dialog')
62
+ root.setAttribute('aria-modal', 'true')
63
+ root.setAttribute('aria-labelledby', titleId)
64
+ // pixel-quiet is the baked-in look; an optional theme pins light/dark
65
+ // (otherwise the panel follows the OS via prefers-color-scheme).
66
+ const themeClass = theme === 'dark' ? ' dark' : theme === 'light' ? ' light' : ''
67
+ root.className =
68
+ 'hcms-shell pixel-quiet hcms-panel hcms-side-' + side + (overlay ? ' hcms-overlay' : '') + themeClass
69
+ const titleHtml = escapeHtml(title)
70
+ const eyebrowHtml = escapeHtml(eyebrow)
71
+ // Pixel Quiet shell: a scroll-away header + in-flow Save inside .hcms-shell-body,
72
+ // with a condensed minibar pinned to the panel top once the header scrolls out.
73
+ // Close + Save are real mirk buttons. The .hcms-* hooks stay so the engine and
74
+ // events bind exactly as before; only the chrome shape changed.
75
+ // The Save button has no wiring here: [trigger-save] is the hyperclayjs save
76
+ // attribute — its save system (or its view-mode notice) handles the click.
77
+ // Standalone hosts delegate their own [trigger-save] click listener.
78
+ root.innerHTML = `
79
+ <div class="hcms-shell-minibar" aria-hidden="true">
80
+ <span class="hcms-shell-minibar-title">${titleHtml}</span>
81
+ <button type="button" class="hcms-shell-close mirk-button mirk-button--small" data-hcms-action="close" aria-label="Close">
82
+ <span class="mirk-button__label">×</span>
83
+ </button>
84
+ </div>
85
+ <div class="hcms-shell-body">
86
+ <header class="hcms-shell-header">
87
+ <div class="hcms-shell-heading">
88
+ <div class="hcms-shell-eyebrow">${eyebrowHtml}</div>
89
+ <h2 class="hcms-shell-title" id="${titleId}">${titleHtml}</h2>
90
+ </div>
91
+ <button type="button" class="hcms-shell-close mirk-button mirk-button--small" data-hcms-action="close" aria-label="Close">
92
+ <span class="mirk-button__label">×</span>
93
+ </button>
94
+ </header>
95
+ <div class="hcms-shell-notice" role="status" hidden></div>
96
+ <div class="hcms-shell-error" role="alert" hidden></div>
97
+ <div data-hcms-form-root class="hcms-form"></div>
98
+ <footer class="hcms-shell-footer"${showSaveButton ? '' : ' hidden'}>
99
+ <button type="button" class="hcms-shell-save mirk-button" trigger-save>
100
+ <span class="mirk-button__label">Save</span>
101
+ </button>
102
+ </footer>
103
+ </div>
104
+ `
105
+
106
+ // mountTo may be a nested element inside pageRoot. Use it as-is for the
107
+ // visual hierarchy; engine reads/writes pass { skip: '[data-hcms-shell]' }
108
+ // so the engine never traverses into the form regardless of where it's mounted.
109
+ const host = mountTo || doc.body
110
+ host.appendChild(root)
111
+
112
+ const body = doc.body
113
+ body.classList.add('hcms-open')
114
+ markSessionOpen(doc)
115
+ if (overlay) body.classList.add('hcms-overlay')
116
+ if (side === 'left') body.classList.add('hcms-side-left')
117
+
118
+ const focusTrap = installFocusTrap(root, doc)
119
+ const condense = installCondenseOnScroll(root)
120
+
121
+ return {
122
+ root,
123
+ formRoot: root.querySelector('[data-hcms-form-root]'),
124
+ noticeEl: root.querySelector('.hcms-shell-notice'),
125
+ errorEl: root.querySelector('.hcms-shell-error'),
126
+ saveButton: root.querySelector('.hcms-shell-save'),
127
+ destroy() {
128
+ focusTrap.detach()
129
+ condense.detach()
130
+ root.remove()
131
+ body.classList.remove('hcms-open', 'hcms-overlay', 'hcms-side-left')
132
+ clearSessionOpen(doc)
133
+ },
134
+ // Re-assert the shell's out-of-subtree chrome after a full-document morph
135
+ // (e.g. a live-sync apply) wipes it: the stylesheet lives in <head> and the
136
+ // body classes live on <body>, both outside the save-ignore shell element,
137
+ // so hyper-morph's head-merge / class reconciliation can strip them.
138
+ restoreChrome() {
139
+ reensureStyles(doc)
140
+ body.classList.add('hcms-open')
141
+ markSessionOpen(doc)
142
+ if (overlay) body.classList.add('hcms-overlay')
143
+ if (side === 'left') body.classList.add('hcms-side-left')
144
+ },
145
+ }
146
+ }
147
+
148
+ // Re-inject the shell stylesheet if a morph (or anything else) removed it.
149
+ // Unlike ensureStyles, this does NOT trust the styledDocs WeakSet: a morph can
150
+ // remove the <style> tag while the WeakSet still marks the doc as "styled", so
151
+ // a naive ensureStyles() call would no-op. Re-check the live DOM, clear the
152
+ // stale mark, and let ensureStyles rebuild from cssText.
153
+ export function reensureStyles(doc) {
154
+ if (!doc) return
155
+ if (doc.getElementById(SHELL_STYLE_ID) ||
156
+ doc.querySelector('style[data-hcms-bundled-styles]')) return
157
+ styledDocs.delete(doc)
158
+ ensureStyles(doc)
159
+ }
160
+
161
+ function ensureStyles(doc) {
162
+ if (!doc) return
163
+ if (styledDocs.has(doc)) return
164
+ if (doc[SHELL_BUNDLED_FLAG]) {
165
+ styledDocs.add(doc)
166
+ return
167
+ }
168
+ if (doc.getElementById(SHELL_STYLE_ID) || doc.querySelector('style[data-hcms-bundled-styles]')) {
169
+ styledDocs.add(doc)
170
+ return
171
+ }
172
+ if (cssText) {
173
+ const style = doc.createElement('style')
174
+ style.id = SHELL_STYLE_ID
175
+ style.setAttribute('save-remove', '')
176
+ // save-ignore mirrors the shell root so a full-document morph (e.g. a live-sync
177
+ // head-merge) preserves the stylesheet instead of stripping it; without it the
178
+ // style survives only via restoreChrome's reactive re-injection.
179
+ style.setAttribute('save-ignore', '')
180
+ style.textContent = cssText
181
+ ;(doc.head || doc.documentElement).appendChild(style)
182
+ styledDocs.add(doc)
183
+ return
184
+ }
185
+ // No bundled CSS — try resolving the sibling generated theme via
186
+ // import.meta.url. Browsers ESM-resolved imports place a co-located
187
+ // theme.generated.css next to hypercms.js. Falls back silently if resolution
188
+ // fails (e.g., bundlers without an asset emitter).
189
+ try {
190
+ const href = new URL('./theme.generated.css', import.meta.url).href
191
+ const link = doc.createElement('link')
192
+ link.rel = 'stylesheet'
193
+ link.id = SHELL_STYLE_ID
194
+ link.setAttribute('save-remove', '')
195
+ link.setAttribute('save-ignore', '')
196
+ link.href = href
197
+ ;(doc.head || doc.documentElement).appendChild(link)
198
+ styledDocs.add(doc)
199
+ } catch (_) {
200
+ // No bundled CSS and no resolvable co-located theme (e.g. the IIFE bundle,
201
+ // where import.meta is undefined). Warn loudly rather than mount a silently
202
+ // unstyled shell — the host must call installStyles(themeText) before opening.
203
+ console.warn(
204
+ 'hypercms: shell stylesheet not applied — cssText is empty and the ' +
205
+ 'co-located theme fallback is unavailable. Call installStyles(themeText) ' +
206
+ 'before opening the CMS.'
207
+ )
208
+ }
209
+ }
210
+
211
+ // Reveal the condensed minibar once the full header scrolls out of the body
212
+ // (pixel-quiet decision 0003). Passive listener; toggles .is-condensed on the
213
+ // shell root when scrollTop passes the header height. No-op if the body or
214
+ // header is missing (e.g. a custom mount that omits them).
215
+ function installCondenseOnScroll(root) {
216
+ const bodyEl = root.querySelector('.hcms-shell-body')
217
+ const header = root.querySelector('.hcms-shell-header')
218
+ if (!bodyEl || !header || typeof bodyEl.addEventListener !== 'function') {
219
+ return { detach() {} }
220
+ }
221
+ const reveal = () => {
222
+ const trigger = (header.offsetHeight || 0) - 12
223
+ root.classList.toggle('is-condensed', bodyEl.scrollTop > trigger)
224
+ }
225
+ bodyEl.addEventListener('scroll', reveal, { passive: true })
226
+ reveal()
227
+ return { detach() { bodyEl.removeEventListener('scroll', reveal) } }
228
+ }
229
+
230
+ function installFocusTrap(root, doc) {
231
+ function onKeyDown(e) {
232
+ if (e.key !== 'Tab') return
233
+ if (!root.contains(doc.activeElement)) return
234
+ const focusables = Array.from(root.querySelectorAll(FOCUSABLE))
235
+ if (focusables.length === 0) return
236
+ const first = focusables[0]
237
+ const last = focusables[focusables.length - 1]
238
+ if (e.shiftKey && doc.activeElement === first) {
239
+ e.preventDefault()
240
+ last.focus()
241
+ } else if (!e.shiftKey && doc.activeElement === last) {
242
+ e.preventDefault()
243
+ first.focus()
244
+ }
245
+ }
246
+ doc.addEventListener('keydown', onKeyDown)
247
+ return { detach: () => doc.removeEventListener('keydown', onKeyDown) }
248
+ }