@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,666 @@
1
+ // Floating bottom-right button that toggles the CMS open/closed, so a page
2
+ // owner can reopen the CMS after closing it (the shell's X is the only other
3
+ // affordance, and nothing reopens it). Injected at page load only when the
4
+ // visitor is in edit mode AND the page actually has cms rules, so regular
5
+ // visitors and rules-less pages (hypercms rides in broad presets) never see it.
6
+ // Runtime-only chrome: no-save + snapshot-remove keep it out of every save and
7
+ // snapshot (a static no-save element written into the file would be stripped
8
+ // from disk on the first save), save-ignore keeps it out of autosave/undo,
9
+ // mirroring the shell's own attributes.
10
+ //
11
+ // The control is a <hypercms-toggle> host wrapping a real <button>. The host is
12
+ // an unregistered custom element on purpose: a host page's `button { ... }`
13
+ // reset cannot reach it, and that reset is the common way an injected control
14
+ // gets mangled. Only the structural facts that must survive a hostile
15
+ // `* { ... !important }` reset are pinned inline with !important; each reads a
16
+ // public custom property, so overriding still works. Everything cosmetic is a
17
+ // normal declaration selected by [data-hcms-toggle-host], which an author's own
18
+ // #hcms-toggle rule outranks on specificity.
19
+ //
20
+ // With two views to choose between it is a split button: the main button plus an
21
+ // arrow that opens a menu. The arrow's background and the menu's whole geometry
22
+ // are pinned for exactly the reason the host's position is — an unpinned arrow
23
+ // goes transparent under a page's `button { background: none !important }`, and
24
+ // an unpinned menu drops into the flow and shoves the page. The menu's `display`
25
+ // is pinned too: [hidden] is a UA rule with no specificity, so any page rule
26
+ // matching the element beats it and the menu would sit open forever.
27
+
28
+ const TOGGLE_ID = 'hcms-toggle'
29
+ const HOST_ATTR = 'data-hcms-toggle-host'
30
+ const STYLE_ID = 'hcms-toggle-style'
31
+ const STYLE_ATTR = 'data-hcms-toggle-style'
32
+ // "A session of either kind is up", written by the open/close events. NOT
33
+ // body.hcms-open: that class is the sidebar's page shift and an inline session
34
+ // sets nothing on <body>, so a body-class label reads "Edit content" over an
35
+ // open inline editor.
36
+ const SESSION_ATTR = 'data-hcms-session'
37
+ const SPLIT_ATTR = 'data-hcms-split'
38
+
39
+ // The preference, one setting across the origin. No version suffix: there are
40
+ // exactly two valid values and the membership check on read is what makes any
41
+ // other value — a stale name, a hand-edited entry, a future view this build does
42
+ // not have — read as first run rather than as a broken session.
43
+ export const VIEW_STORAGE_KEY = 'hcms.view'
44
+ const VIEW_NAMES = ['sidebar', 'inline']
45
+ const VIEW_LABELS = { sidebar: 'In the sidebar', inline: 'On the page' }
46
+
47
+ const SURFACE_VAR = 'var(--hcms-toggle-bg, var(--hcms-toggle-_surface))'
48
+
49
+ export function readStoredView(win) {
50
+ try {
51
+ const value = win && win.localStorage ? win.localStorage.getItem(VIEW_STORAGE_KEY) : null
52
+ return VIEW_NAMES.includes(value) ? value : null
53
+ } catch (_) {
54
+ return null
55
+ }
56
+ }
57
+
58
+ // Written when someone picks a view, and only once that view is actually up: a
59
+ // mount that throws must not teach the next page load to try the same broken
60
+ // view. localStorage throws outright in a few configurations (Safari private
61
+ // mode, cookies disabled), and a remembered view is a convenience, not a
62
+ // requirement.
63
+ export function writeStoredView(win, view) {
64
+ if (!VIEW_NAMES.includes(view)) return
65
+ try {
66
+ win?.localStorage?.setItem(VIEW_STORAGE_KEY, view)
67
+ } catch (_) {}
68
+ }
69
+
70
+ // The pill's surface is opaque and neutral, picked at inject time from the two
71
+ // values below by whichever has more contrast against the page's own ink. It is
72
+ // not a tint of currentColor: the button floats over a backdrop it cannot see,
73
+ // and a 10% tint over a dark hero measures 1.3:1. Opaque removes the backdrop
74
+ // from the question entirely. Measured floor for this pair is 4.36:1 across
75
+ // 1516 inks; a 4.5:1 floor needs #030303, which is black in all but name.
76
+ const SURFACE_LIGHT = '#fafafa'
77
+ const SURFACE_DARK = '#0a0a0a'
78
+
79
+ export const TOGGLE_STYLE = `
80
+ [${HOST_ATTR}] {
81
+ all: unset;
82
+ box-sizing: border-box;
83
+ display: var(--hcms-toggle-display, inline-flex);
84
+ --hcms-toggle-_surface: ${SURFACE_LIGHT};
85
+ }
86
+ [${HOST_ATTR}][data-hcms-surface="dark"] {
87
+ --hcms-toggle-_surface: ${SURFACE_DARK};
88
+ }
89
+ [${HOST_ATTR}] .hcms-toggle__main,
90
+ [${HOST_ATTR}] .hcms-toggle__arrow {
91
+ all: unset;
92
+ box-sizing: border-box;
93
+ display: inline-flex;
94
+ align-items: center;
95
+ gap: 7px;
96
+ padding: 0 14px;
97
+ min-height: 40px;
98
+ font-family: inherit;
99
+ font-weight: 500;
100
+ line-height: 1;
101
+ font-size: clamp(12px, 0.85em, 15px);
102
+ color: var(--hcms-toggle-color, currentColor);
103
+ border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
104
+ border-radius: 999px;
105
+ cursor: pointer;
106
+ box-shadow: 0 10px 28px -12px rgba(0, 0, 0, .35);
107
+ }
108
+ [${HOST_ATTR}] .hcms-toggle__main:hover,
109
+ [${HOST_ATTR}] .hcms-toggle__arrow:hover {
110
+ border-color: color-mix(in srgb, currentColor 45%, transparent);
111
+ box-shadow: 0 12px 32px -12px rgba(0, 0, 0, .45);
112
+ }
113
+ [${HOST_ATTR}] .hcms-toggle__main:focus-visible,
114
+ [${HOST_ATTR}] .hcms-toggle__arrow:focus-visible {
115
+ outline: 2px solid currentColor;
116
+ outline-offset: -5px;
117
+ }
118
+ [${HOST_ATTR}] .hcms-toggle__close { display: none; }
119
+ [${HOST_ATTR}][${SESSION_ATTR}="open"] .hcms-toggle__open { display: none; }
120
+ [${HOST_ATTR}][${SESSION_ATTR}="open"] .hcms-toggle__close { display: inline; }
121
+ [${HOST_ATTR}][${SPLIT_ATTR}] .hcms-toggle__main {
122
+ border-radius: 999px 0 0 999px;
123
+ padding-right: 12px;
124
+ }
125
+ [${HOST_ATTR}] .hcms-toggle__arrow {
126
+ gap: 0;
127
+ padding: 0 10px;
128
+ border-radius: 0 999px 999px 0;
129
+ border-left-width: 0;
130
+ }
131
+ [${HOST_ATTR}] .hcms-toggle__menu {
132
+ all: unset;
133
+ box-sizing: border-box;
134
+ min-width: 180px;
135
+ padding: 4px;
136
+ font-family: inherit;
137
+ font-size: clamp(12px, 0.85em, 15px);
138
+ line-height: 1;
139
+ color: var(--hcms-toggle-color, currentColor);
140
+ background: ${SURFACE_VAR};
141
+ border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
142
+ border-radius: 12px;
143
+ box-shadow: 0 14px 34px -14px rgba(0, 0, 0, .45);
144
+ }
145
+ [${HOST_ATTR}] .hcms-toggle__item {
146
+ all: unset;
147
+ box-sizing: border-box;
148
+ display: block;
149
+ width: 100%;
150
+ padding: 9px 10px;
151
+ border-radius: 8px;
152
+ cursor: pointer;
153
+ }
154
+ [${HOST_ATTR}] .hcms-toggle__item::before {
155
+ content: "○";
156
+ margin-right: 8px;
157
+ opacity: .55;
158
+ }
159
+ [${HOST_ATTR}] .hcms-toggle__item[aria-checked="true"]::before {
160
+ content: "●";
161
+ opacity: 1;
162
+ }
163
+ [${HOST_ATTR}] .hcms-toggle__item:hover {
164
+ background: color-mix(in srgb, currentColor 12%, transparent);
165
+ }
166
+ [${HOST_ATTR}] .hcms-toggle__item:focus-visible {
167
+ outline: 2px solid currentColor;
168
+ outline-offset: -3px;
169
+ }
170
+ @media (pointer: coarse) {
171
+ [${HOST_ATTR}] .hcms-toggle__main,
172
+ [${HOST_ATTR}] .hcms-toggle__arrow { min-height: 44px; }
173
+ }
174
+ `
175
+
176
+ // Mirrors hyperclayjs core/isAdminOfCurrentResource.js: an explicit
177
+ // ?editmode=true|false param wins, then the window.__hyperclayEditMode global
178
+ // (standalone opt-in), then the platform's isAdminOfCurrentResource cookie.
179
+ // Replicated here rather than read off window.hyperclay because the edit-mode
180
+ // module isn't part of the cms preset, so the global isn't reliably present.
181
+ export function detectEditMode({ search = '', cookie = '', forced = null } = {}) {
182
+ const str = typeof search === 'string' ? search : ''
183
+ const qIndex = str.indexOf('?')
184
+ const query = qIndex === -1 ? str : str.slice(qIndex + 1)
185
+ const param = new URLSearchParams(query).get('editmode')
186
+ if (param) return param === 'true'
187
+ if (forced != null) return Boolean(forced)
188
+ return /(?:^|;\s*)isAdminOfCurrentResource=[^;]/.test(cookie)
189
+ }
190
+
191
+ // A computed `color` is not always an rgb() string: CSS Color 4 keeps the
192
+ // authored space, so Chrome returns oklch(), lab() and color() as written, and
193
+ // Tailwind v4's whole palette is oklch. rgb()/rgba() is still what the great
194
+ // majority of pages compute to, so parse that directly and let the canvas
195
+ // handle only the rest.
196
+ const colorContexts = new WeakMap()
197
+
198
+ function readCanvasColor(ctx, value) {
199
+ try {
200
+ // 'copy' replaces the pixel instead of blending, so alpha survives.
201
+ ctx.globalCompositeOperation = 'copy'
202
+ ctx.fillStyle = value
203
+ ctx.fillRect(0, 0, 1, 1)
204
+ const d = ctx.getImageData(0, 0, 1, 1).data
205
+ return { r: d[0], g: d[1], b: d[2], a: d[3] / 255 }
206
+ } catch (_) {
207
+ return null
208
+ }
209
+ }
210
+
211
+ // Per document, not per module: the context retains its canvas, which retains
212
+ // its ownerDocument, and hypercms can be driven into a preview iframe.
213
+ function colorContextFor(doc) {
214
+ if (colorContexts.has(doc)) return colorContexts.get(doc)
215
+ let ctx = null
216
+ try {
217
+ const canvas = doc.createElement('canvas')
218
+ canvas.width = canvas.height = 1
219
+ ctx = canvas.getContext ? canvas.getContext('2d', { willReadFrequently: true }) : null
220
+ // A browser that fuzzes canvas readback (Firefox's resistFingerprinting)
221
+ // answers the same colour for everything, which would send every page to
222
+ // one surface at about 1:1. Round-trip a known value once and refuse the
223
+ // whole path if it does not come back exactly.
224
+ if (ctx) {
225
+ const probe = readCanvasColor(ctx, 'rgb(1, 2, 3)')
226
+ if (!probe || probe.r !== 1 || probe.g !== 2 || probe.b !== 3 || probe.a !== 1) ctx = null
227
+ }
228
+ } catch (_) {
229
+ ctx = null
230
+ }
231
+ colorContexts.set(doc, ctx)
232
+ return ctx
233
+ }
234
+
235
+ function normalizeColor(value, doc) {
236
+ const raw = String(value == null ? '' : value).trim()
237
+ if (!raw) return null
238
+ const direct = parseRgb(raw)
239
+ if (direct) return direct
240
+ const win = doc && doc.defaultView
241
+ // CSS.supports is the parse check AND the capability probe: jsdom has neither
242
+ // it nor a 2d context, so this short-circuits without jsdom logging a "not
243
+ // implemented" error for getContext. It matters because a rejected fillStyle
244
+ // silently keeps its previous value, so an unguarded read would report the
245
+ // last ink this page measured.
246
+ if (!win || !win.CSS || typeof win.CSS.supports !== 'function') return null
247
+ if (!win.CSS.supports('color', raw)) return null
248
+ const ctx = colorContextFor(doc)
249
+ return ctx ? readCanvasColor(ctx, raw) : null
250
+ }
251
+
252
+ export function parseRgb(value) {
253
+ const match = /rgba?\(([^)]+)\)/.exec(String(value == null ? '' : value))
254
+ if (!match) return null
255
+ const parts = match[1].split(/[\s,/]+/).filter(Boolean)
256
+ if (parts.length < 3) return null
257
+ const channels = parts.slice(0, 3).map(Number)
258
+ if (channels.some(Number.isNaN)) return null
259
+ const rawAlpha = parts[3]
260
+ const alpha = rawAlpha === undefined
261
+ ? 1
262
+ : (rawAlpha.endsWith('%') ? Number(rawAlpha.slice(0, -1)) / 100 : Number(rawAlpha))
263
+ return {
264
+ r: channels[0], g: channels[1], b: channels[2],
265
+ a: Number.isNaN(alpha) ? 1 : alpha,
266
+ }
267
+ }
268
+
269
+ function relativeLuminance({ r, g, b }) {
270
+ const channel = (v) => {
271
+ const s = v / 255
272
+ return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4
273
+ }
274
+ return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b)
275
+ }
276
+
277
+ function contrast(a, b) {
278
+ const la = relativeLuminance(a)
279
+ const lb = relativeLuminance(b)
280
+ return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05)
281
+ }
282
+
283
+ const DARK_RGB = { r: 10, g: 10, b: 10 }
284
+ const LIGHT_RGB = { r: 250, g: 250, b: 250 }
285
+
286
+ // Source-over composite, because the label is painted ON the surface: a
287
+ // translucent ink's rendered colour depends on which surface it lands on, so
288
+ // each candidate has to be judged against its own composite.
289
+ function over(fg, bg) {
290
+ const a = fg.a == null ? 1 : fg.a
291
+ return {
292
+ r: fg.r * a + bg.r * (1 - a),
293
+ g: fg.g * a + bg.g * (1 - a),
294
+ b: fg.b * a + bg.b * (1 - a),
295
+ }
296
+ }
297
+
298
+ // Which of the two surfaces the page's ink reads better on. Ties and unknown
299
+ // inks go light, which is the quieter result on the overwhelmingly common
300
+ // dark-ink-on-light-ground page. The 4.36:1 floor holds for opaque ink only:
301
+ // nothing can make `color: rgb(0 0 0 / 40%)` readable, and this picks the
302
+ // better of two bad options rather than pretending otherwise.
303
+ export function pickSurface(ink) {
304
+ if (!ink) return 'light'
305
+ const onDark = contrast(over(ink, DARK_RGB), DARK_RGB)
306
+ const onLight = contrast(over(ink, LIGHT_RGB), LIGHT_RGB)
307
+ return onDark > onLight ? 'dark' : 'light'
308
+ }
309
+
310
+ function pin(el, declarations) {
311
+ for (const [property, value] of Object.entries(declarations)) {
312
+ el.style.setProperty(property, value, 'important')
313
+ }
314
+ }
315
+
316
+ function applySurface(host) {
317
+ const win = host.ownerDocument && host.ownerDocument.defaultView
318
+ const main = host.querySelector('.hcms-toggle__main')
319
+ if (!win || !main || typeof win.getComputedStyle !== 'function') return
320
+ const ink = normalizeColor(win.getComputedStyle(main).color, host.ownerDocument)
321
+ host.setAttribute('data-hcms-surface', pickSurface(ink))
322
+ }
323
+
324
+ // The ink is read from the live cascade, so it is only final once the page's
325
+ // own stylesheets have applied, and it changes again whenever the page switches
326
+ // theme. A dark-mode toggle that flips <html> or <body> would otherwise leave a
327
+ // near-white label on the near-white surface picked at load. Two elements, no
328
+ // subtree, rAF-collapsed, and it unhooks itself once the host is gone.
329
+ function scheduleSurface(host) {
330
+ applySurface(host)
331
+ const doc = host.ownerDocument
332
+ const win = doc && doc.defaultView
333
+ if (!win) return
334
+
335
+ let frame = 0
336
+ const recompute = () => {
337
+ if (frame) return
338
+ if (typeof win.requestAnimationFrame !== 'function') {
339
+ if (!host.isConnected) return stop()
340
+ return applySurface(host)
341
+ }
342
+ frame = win.requestAnimationFrame(() => {
343
+ frame = 0
344
+ if (!host.isConnected) return stop()
345
+ applySurface(host)
346
+ })
347
+ }
348
+
349
+ if (typeof win.requestAnimationFrame === 'function') recompute()
350
+ if (doc.readyState !== 'complete') win.addEventListener('load', recompute, { once: true })
351
+
352
+ const observer = typeof win.MutationObserver === 'function' ? new win.MutationObserver(recompute) : null
353
+ if (observer) {
354
+ // No attributeFilter. Theme togglers write whatever attribute they like:
355
+ // Bootstrap 5.3 uses data-bs-theme, Primer uses data-color-mode, plenty use
356
+ // a class or an inline style. An allowlist is a guess about other people's
357
+ // markup and it was already wrong twice. Two elements, no subtree, and the
358
+ // callback collapses into one animation frame, so watching every attribute
359
+ // costs nothing measurable.
360
+ observer.observe(doc.documentElement, { attributes: true })
361
+ if (doc.body) observer.observe(doc.body, { attributes: true })
362
+ }
363
+
364
+ const scheme = typeof win.matchMedia === 'function' ? win.matchMedia('(prefers-color-scheme: dark)') : null
365
+ if (scheme && typeof scheme.addEventListener === 'function') scheme.addEventListener('change', recompute)
366
+
367
+ // Self-disconnecting: any attribute write on <html> or <body> schedules a
368
+ // recompute, which stops the watcher once the host has left the document.
369
+ // Round 2 added an explicit sweep at injection time as well; it was dead
370
+ // code, because injectToggle runs once per page. The residual is a single
371
+ // observer surviving on a page that removes our host and then never touches
372
+ // an attribute on <html> or <body> again, which is clutter on a page that
373
+ // has already thrown the control away.
374
+ function stop() {
375
+ if (observer) observer.disconnect()
376
+ if (scheme && typeof scheme.removeEventListener === 'function') scheme.removeEventListener('change', recompute)
377
+ }
378
+ }
379
+
380
+ export function injectToggle({ open, close, isOpen, views = VIEW_NAMES }, doc = document) {
381
+ const existing = doc.querySelector(`[${HOST_ATTR}]`)
382
+ if (existing) return existing
383
+
384
+ if (!doc.querySelector(`[${STYLE_ATTR}]`)) {
385
+ const style = doc.createElement('style')
386
+ style.setAttribute(STYLE_ATTR, '')
387
+ if (!doc.getElementById(STYLE_ID)) style.id = STYLE_ID
388
+ style.setAttribute('no-save', '')
389
+ style.setAttribute('snapshot-remove', '')
390
+ style.setAttribute('save-ignore', '')
391
+ style.textContent = TOGGLE_STYLE
392
+ // Prepended, not appended: an author who overrides with a selector no
393
+ // stronger than ours then wins the tie on document order.
394
+ doc.head.insertBefore(style, doc.head.firstChild)
395
+ }
396
+
397
+ const host = doc.createElement('hypercms-toggle')
398
+ // The id is the documented override handle, but it is the page's namespace:
399
+ // if the page already owns it, go without rather than shadow their element.
400
+ if (!doc.getElementById(TOGGLE_ID)) host.id = TOGGLE_ID
401
+ host.setAttribute(HOST_ATTR, '')
402
+ host.setAttribute('no-save', '')
403
+ host.setAttribute('snapshot-remove', '')
404
+ host.setAttribute('save-ignore', '')
405
+ host.innerHTML =
406
+ '<button type="button" class="hcms-toggle__main">' +
407
+ '<span class="hcms-toggle__open">Edit content</span>' +
408
+ '<span class="hcms-toggle__close">Close editor</span>' +
409
+ '</button>'
410
+
411
+ const win = doc.defaultView
412
+ const main = host.querySelector('.hcms-toggle__main')
413
+ // Fixed order, so the menu does not reorder itself from page to page, and
414
+ // filtered against the views this build actually has.
415
+ const available = VIEW_NAMES.filter((name) => views.includes(name))
416
+ // An arrow offering a choice of one is a menu that can only repeat what the
417
+ // button already does, so with a single view there is no arrow at all.
418
+ const split = available.length > 1
419
+ const arrow = split ? makeArrow(doc) : null
420
+ const menu = split ? makeMenu(doc, available) : null
421
+ if (split) {
422
+ host.setAttribute(SPLIT_ATTR, '')
423
+ host.appendChild(arrow)
424
+ host.appendChild(menu)
425
+ }
426
+
427
+ // The only declarations a page's `* { ... !important }` reset can take from
428
+ // us and leave the control broken rather than merely ugly. Each reads its
429
+ // public custom property first, so an author override still lands.
430
+ pin(host, {
431
+ position: 'fixed',
432
+ right: 'calc(var(--hcms-toggle-offset, 16px) + var(--hcms-toggle-shift, 0px))',
433
+ bottom: 'calc(var(--hcms-toggle-offset, 16px) + env(safe-area-inset-bottom, 0px))',
434
+ 'z-index': 'var(--hcms-toggle-z, 2147482900)',
435
+ })
436
+ pin(main, { background: SURFACE_VAR })
437
+ if (arrow) pin(arrow, { background: SURFACE_VAR })
438
+ if (menu) {
439
+ pin(menu, {
440
+ position: 'absolute',
441
+ right: '0',
442
+ bottom: 'calc(100% + 8px)',
443
+ 'z-index': 'var(--hcms-toggle-z, 2147482900)',
444
+ display: 'none',
445
+ })
446
+ }
447
+
448
+ const items = () => (menu ? [...menu.querySelectorAll('[role="menuitemradio"]')] : [])
449
+
450
+ function focusEl(el) {
451
+ if (!el || typeof el.focus !== 'function') return
452
+ try { el.focus({ preventScroll: true }) } catch (_) { el.focus() }
453
+ }
454
+
455
+ function focusItem(index) {
456
+ const list = items()
457
+ if (!list.length) return
458
+ focusEl(list[(index + list.length) % list.length])
459
+ }
460
+
461
+ // Read fresh every time the menu opens: the selection made two clicks ago is
462
+ // the one the radio should be sitting on.
463
+ function markChecked() {
464
+ const stored = readStoredView(win)
465
+ for (const item of items()) {
466
+ item.setAttribute('aria-checked', String(item.getAttribute('data-hcms-view') === stored))
467
+ }
468
+ }
469
+
470
+ function onOutsidePointer(event) {
471
+ if (host.contains(event.target)) return
472
+ closeMenu()
473
+ }
474
+
475
+ function setMenuOpen(show) {
476
+ if (!menu) return
477
+ menu.hidden = !show
478
+ pin(menu, { display: show ? 'block' : 'none' })
479
+ arrow.setAttribute('aria-expanded', String(show))
480
+ if (show) {
481
+ markChecked()
482
+ // Capture, so a page that swallows pointer events on the way up cannot
483
+ // leave the menu standing open over content it no longer belongs to.
484
+ doc.addEventListener('pointerdown', onOutsidePointer, true)
485
+ } else {
486
+ doc.removeEventListener('pointerdown', onOutsidePointer, true)
487
+ }
488
+ }
489
+
490
+ function openMenu(index = 0) {
491
+ setMenuOpen(true)
492
+ focusItem(index)
493
+ }
494
+
495
+ function closeMenu({ focusArrow = false } = {}) {
496
+ if (!menu || menu.hidden) return
497
+ setMenuOpen(false)
498
+ if (focusArrow) focusEl(arrow)
499
+ }
500
+
501
+ // A remembered view this page cannot render is ignored HERE and left in
502
+ // storage: the preference belongs to the person, not to the page, and the
503
+ // next page may well be able to honour it.
504
+ function rememberedView() {
505
+ const stored = readStoredView(win)
506
+ return stored && available.includes(stored) ? stored : null
507
+ }
508
+
509
+ // The one path that writes the preference, because it is the one where the
510
+ // person chose. After the open, never before: a mount that throws leaves the
511
+ // preference exactly as it was.
512
+ async function chooseView(name) {
513
+ await open({ view: name })
514
+ writeStoredView(win, name)
515
+ }
516
+
517
+ async function mainAction() {
518
+ if (isOpen()) {
519
+ close()
520
+ return
521
+ }
522
+ const remembered = rememberedView()
523
+ if (remembered) return open({ view: remembered })
524
+ // First run. With a real choice to make the button asks rather than
525
+ // guessing; with one view there is nothing to ask.
526
+ if (split) return openMenu()
527
+ // Opening the only view a page has is not a choice, so it is not
528
+ // remembered: writing it here would take the preference away from every
529
+ // page that does offer both, which is deletion by another name.
530
+ return open(available[0] ? { view: available[0] } : {})
531
+ }
532
+
533
+ async function run(action) {
534
+ try {
535
+ await action()
536
+ } catch (err) {
537
+ console.warn('hypercms: toggle failed to open the CMS', err)
538
+ }
539
+ }
540
+
541
+ // Delegated, so both a real click on the inner button and a programmatic
542
+ // host.click() fire exactly once. The arrow and the menu own their own
543
+ // clicks, which bubble through here on their way out.
544
+ host.addEventListener('click', async (event) => {
545
+ if (arrow && arrow.contains(event.target)) return
546
+ if (menu && menu.contains(event.target)) return
547
+ await run(mainAction)
548
+ })
549
+
550
+ if (arrow) {
551
+ arrow.addEventListener('click', (event) => {
552
+ event.preventDefault()
553
+ if (menu.hidden) openMenu()
554
+ else closeMenu({ focusArrow: true })
555
+ })
556
+ arrow.addEventListener('keydown', (event) => {
557
+ if (event.key === 'ArrowUp') {
558
+ event.preventDefault()
559
+ openMenu(-1)
560
+ return
561
+ }
562
+ // preventDefault on Enter and Space stops the button's own activation
563
+ // click, which would otherwise arrive and toggle the menu straight back
564
+ // shut.
565
+ if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {
566
+ event.preventDefault()
567
+ openMenu(0)
568
+ }
569
+ })
570
+ menu.addEventListener('click', (event) => {
571
+ const item = event.target.closest?.('[role="menuitemradio"]')
572
+ if (!item) return
573
+ event.preventDefault()
574
+ closeMenu()
575
+ run(() => chooseView(item.getAttribute('data-hcms-view')))
576
+ })
577
+ menu.addEventListener('keydown', (event) => {
578
+ const list = items()
579
+ const current = list.indexOf(doc.activeElement)
580
+ switch (event.key) {
581
+ case 'ArrowDown': event.preventDefault(); focusItem(current + 1); break
582
+ case 'ArrowUp': event.preventDefault(); focusItem(current - 1); break
583
+ case 'Home': event.preventDefault(); focusItem(0); break
584
+ case 'End': event.preventDefault(); focusItem(list.length - 1); break
585
+ case 'Enter':
586
+ case ' ':
587
+ event.preventDefault()
588
+ if (current === -1) break
589
+ closeMenu()
590
+ run(() => chooseView(list[current].getAttribute('data-hcms-view')))
591
+ break
592
+ case 'Escape': event.preventDefault(); closeMenu({ focusArrow: true }); break
593
+ // No preventDefault: Tab leaves the menu, it does not cycle inside it.
594
+ case 'Tab': closeMenu(); break
595
+ }
596
+ })
597
+ }
598
+
599
+ // Which label the main button shows, and nothing else decides it. hcms:close
600
+ // fires BEFORE the session is torn down, so isOpen() still answers true inside
601
+ // that handler: the event says what happened and re-asking would leave the
602
+ // button reading "Close editor" over a closed editor.
603
+ const setSessionState = (sessionOpen) => {
604
+ if (sessionOpen) host.setAttribute(SESSION_ATTR, 'open')
605
+ else host.removeAttribute(SESSION_ATTR)
606
+ }
607
+ setSessionState(isOpen())
608
+ doc.addEventListener('hcms:open', () => setSessionState(true))
609
+ doc.addEventListener('hcms:close', () => setSessionState(false))
610
+
611
+ doc.body.appendChild(host)
612
+ scheduleSurface(host)
613
+ return host
614
+ }
615
+
616
+ function makeArrow(doc) {
617
+ const arrow = doc.createElement('button')
618
+ arrow.type = 'button'
619
+ arrow.className = 'hcms-toggle__arrow'
620
+ arrow.setAttribute('aria-haspopup', 'menu')
621
+ arrow.setAttribute('aria-expanded', 'false')
622
+ // The arrow is a glyph, so unlike the main button it has no visible text to
623
+ // take its accessible name from.
624
+ arrow.setAttribute('aria-label', 'Choose where to edit')
625
+ arrow.textContent = '▾'
626
+ return arrow
627
+ }
628
+
629
+ function makeMenu(doc, available) {
630
+ const menu = doc.createElement('div')
631
+ menu.className = 'hcms-toggle__menu'
632
+ menu.setAttribute('role', 'menu')
633
+ menu.setAttribute('aria-label', 'Where to edit')
634
+ menu.hidden = true
635
+ for (const name of available) {
636
+ const item = doc.createElement('button')
637
+ item.type = 'button'
638
+ item.className = 'hcms-toggle__item'
639
+ // menuitemradio, not menuitem: the two are one choice with one answer, and
640
+ // the remembered one is checked.
641
+ item.setAttribute('role', 'menuitemradio')
642
+ item.setAttribute('aria-checked', 'false')
643
+ item.setAttribute('data-hcms-view', name)
644
+ // Roving focus: the menu is entered from the arrow and moved through with
645
+ // the arrow keys, never tabbed into item by item.
646
+ item.tabIndex = -1
647
+ item.textContent = VIEW_LABELS[name]
648
+ menu.appendChild(item)
649
+ }
650
+ return menu
651
+ }
652
+
653
+ // Inject at page load when in edit mode and the page has cms rules. DOM-ready
654
+ // deferral matters when the module evaluates while the document is still
655
+ // parsing (the rules tag or <body> may not exist yet).
656
+ export function maybeInjectToggle(api) {
657
+ if (typeof window === 'undefined' || typeof document === 'undefined') return
658
+ const forced = window.__hyperclayEditMode != null ? window.__hyperclayEditMode : null
659
+ if (!detectEditMode({ search: window.location.search, cookie: document.cookie, forced })) return
660
+ const run = () => { if (document.body && api.hasRules(document)) injectToggle(api) }
661
+ if (document.readyState === 'loading') {
662
+ document.addEventListener('DOMContentLoaded', run, { once: true })
663
+ } else {
664
+ run()
665
+ }
666
+ }