@storyshelf/app 0.6.2 → 0.8.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 (429) hide show
  1. package/README.md +42 -4
  2. package/dist/app-types.d.mts +2 -6
  3. package/dist/asset-manifest.mjs +14 -7
  4. package/dist/asset-manifest.mjs.map +1 -1
  5. package/dist/assets/{htmx.min.js → htmx.mjs} +9 -1
  6. package/dist/assets/htmx.mjs.map +1 -0
  7. package/dist/assets/mark.mjs +9 -0
  8. package/dist/assets/mark.mjs.map +1 -0
  9. package/dist/boot-tasks.mjs +79 -0
  10. package/dist/boot-tasks.mjs.map +1 -0
  11. package/dist/build-state-flags.mjs +17 -0
  12. package/dist/build-state-flags.mjs.map +1 -0
  13. package/dist/build-state-setup.mjs +74 -0
  14. package/dist/build-state-setup.mjs.map +1 -0
  15. package/dist/capture-alerts.mjs +45 -0
  16. package/dist/capture-alerts.mjs.map +1 -0
  17. package/dist/capture-process.mjs +58 -0
  18. package/dist/capture-process.mjs.map +1 -0
  19. package/dist/capture-setup.mjs +96 -119
  20. package/dist/capture-setup.mjs.map +1 -1
  21. package/dist/connections.mjs +33 -0
  22. package/dist/connections.mjs.map +1 -0
  23. package/dist/consumer-setup.mjs +57 -0
  24. package/dist/consumer-setup.mjs.map +1 -0
  25. package/dist/credential-keys.mjs +1 -2
  26. package/dist/credentials.mjs +1 -2
  27. package/dist/git-status.mjs +45 -0
  28. package/dist/git-status.mjs.map +1 -0
  29. package/dist/hidden-data.mjs +23 -0
  30. package/dist/hidden-data.mjs.map +1 -0
  31. package/dist/index.d.mts +3 -5
  32. package/dist/index.mjs +204 -127
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/insights/budget.mjs +48 -0
  35. package/dist/insights/budget.mjs.map +1 -0
  36. package/dist/insights/deps.mjs +20 -0
  37. package/dist/insights/deps.mjs.map +1 -0
  38. package/dist/insights/errors.mjs +21 -0
  39. package/dist/insights/errors.mjs.map +1 -0
  40. package/dist/insights/health-panel.mjs +39 -0
  41. package/dist/insights/health-panel.mjs.map +1 -0
  42. package/dist/insights/job.mjs +102 -0
  43. package/dist/insights/job.mjs.map +1 -0
  44. package/dist/insights/load-health.mjs +58 -0
  45. package/dist/insights/load-health.mjs.map +1 -0
  46. package/dist/insights/load-triage.mjs +97 -0
  47. package/dist/insights/load-triage.mjs.map +1 -0
  48. package/dist/insights/panel.mjs +27 -0
  49. package/dist/insights/panel.mjs.map +1 -0
  50. package/dist/insights/request.mjs +112 -0
  51. package/dist/insights/request.mjs.map +1 -0
  52. package/dist/insights/stale.mjs +20 -0
  53. package/dist/insights/stale.mjs.map +1 -0
  54. package/dist/insights/usage-report.mjs +59 -0
  55. package/dist/insights/usage-report.mjs.map +1 -0
  56. package/dist/insights/view.mjs +47 -0
  57. package/dist/insights/view.mjs.map +1 -0
  58. package/dist/job-canceller.mjs +13 -0
  59. package/dist/job-canceller.mjs.map +1 -0
  60. package/dist/job-queue.mjs +50 -0
  61. package/dist/job-queue.mjs.map +1 -0
  62. package/dist/jobs-setup.mjs +131 -0
  63. package/dist/jobs-setup.mjs.map +1 -0
  64. package/dist/lifecycle.mjs +93 -22
  65. package/dist/lifecycle.mjs.map +1 -1
  66. package/dist/middleware/auth-gate.mjs +5 -4
  67. package/dist/middleware/auth-gate.mjs.map +1 -1
  68. package/dist/middleware/csrf.mjs +1 -2
  69. package/dist/middleware/rate-limit.mjs +42 -35
  70. package/dist/middleware/rate-limit.mjs.map +1 -1
  71. package/dist/middleware/request-log.mjs +4 -4
  72. package/dist/middleware/request-log.mjs.map +1 -1
  73. package/dist/middleware/require-review.mjs +50 -0
  74. package/dist/middleware/require-review.mjs.map +1 -0
  75. package/dist/middleware/require-testing.mjs +40 -0
  76. package/dist/middleware/require-testing.mjs.map +1 -0
  77. package/dist/middleware/server-timing.mjs +1 -2
  78. package/dist/middleware/setup-gate.mjs +1 -2
  79. package/dist/middleware/setup-gate.mjs.map +1 -1
  80. package/dist/middleware/store-scope.mjs +13 -4
  81. package/dist/middleware/store-scope.mjs.map +1 -1
  82. package/dist/notifications-pause.mjs +32 -0
  83. package/dist/notifications-pause.mjs.map +1 -0
  84. package/dist/notify.d.mts +3 -4
  85. package/dist/notify.mjs +79 -41
  86. package/dist/notify.mjs.map +1 -1
  87. package/dist/pages/a11y-violations.mjs +115 -0
  88. package/dist/pages/a11y-violations.mjs.map +1 -0
  89. package/dist/pages/admin-ai.mjs +77 -0
  90. package/dist/pages/admin-ai.mjs.map +1 -0
  91. package/dist/pages/admin-system-origin.mjs +132 -0
  92. package/dist/pages/admin-system-origin.mjs.map +1 -0
  93. package/dist/pages/admin-system-targets.mjs +52 -0
  94. package/dist/pages/admin-system-targets.mjs.map +1 -0
  95. package/dist/pages/admin-system.mjs +64 -15
  96. package/dist/pages/admin-system.mjs.map +1 -1
  97. package/dist/pages/build-detail.mjs +105 -78
  98. package/dist/pages/build-detail.mjs.map +1 -1
  99. package/dist/pages/build-diff-actions.mjs +88 -35
  100. package/dist/pages/build-diff-actions.mjs.map +1 -1
  101. package/dist/pages/build-diff-comments.mjs +17 -16
  102. package/dist/pages/build-diff-comments.mjs.map +1 -1
  103. package/dist/pages/build-diff-default.mjs +53 -0
  104. package/dist/pages/build-diff-default.mjs.map +1 -0
  105. package/dist/pages/build-diff-environment.mjs +81 -0
  106. package/dist/pages/build-diff-environment.mjs.map +1 -0
  107. package/dist/pages/build-diff-header.mjs +23 -6
  108. package/dist/pages/build-diff-header.mjs.map +1 -1
  109. package/dist/pages/build-diff-insight.mjs +112 -0
  110. package/dist/pages/build-diff-insight.mjs.map +1 -0
  111. package/dist/pages/build-diff-model.mjs +74 -12
  112. package/dist/pages/build-diff-model.mjs.map +1 -1
  113. package/dist/pages/build-diff-nav.mjs +29 -14
  114. package/dist/pages/build-diff-nav.mjs.map +1 -1
  115. package/dist/pages/build-diff-reference.mjs +84 -0
  116. package/dist/pages/build-diff-reference.mjs.map +1 -0
  117. package/dist/pages/build-diff-shortcuts.mjs +6 -3
  118. package/dist/pages/build-diff-shortcuts.mjs.map +1 -1
  119. package/dist/pages/build-diff-stale.mjs +1 -2
  120. package/dist/pages/build-diff-usage.mjs +62 -0
  121. package/dist/pages/build-diff-usage.mjs.map +1 -0
  122. package/dist/pages/build-diff-viewer.mjs +97 -14
  123. package/dist/pages/build-diff-viewer.mjs.map +1 -1
  124. package/dist/pages/build-diff.mjs +37 -22
  125. package/dist/pages/build-diff.mjs.map +1 -1
  126. package/dist/pages/build-tests.mjs +73 -0
  127. package/dist/pages/build-tests.mjs.map +1 -0
  128. package/dist/pages/component-detail.mjs +248 -0
  129. package/dist/pages/component-detail.mjs.map +1 -0
  130. package/dist/pages/component-stories.mjs +167 -0
  131. package/dist/pages/component-stories.mjs.map +1 -0
  132. package/dist/pages/compute-jobs.mjs +14 -28
  133. package/dist/pages/compute-jobs.mjs.map +1 -1
  134. package/dist/pages/design-links.mjs +181 -0
  135. package/dist/pages/design-links.mjs.map +1 -0
  136. package/dist/pages/environment-change.mjs +52 -0
  137. package/dist/pages/environment-change.mjs.map +1 -0
  138. package/dist/pages/health-panel.mjs +125 -0
  139. package/dist/pages/health-panel.mjs.map +1 -0
  140. package/dist/pages/invite.mjs +1 -2
  141. package/dist/pages/label-detail.mjs +1 -2
  142. package/dist/pages/library-grid.mjs +104 -0
  143. package/dist/pages/library-grid.mjs.map +1 -0
  144. package/dist/pages/library-model.mjs +46 -0
  145. package/dist/pages/library-model.mjs.map +1 -0
  146. package/dist/pages/library-snapshots.mjs +129 -0
  147. package/dist/pages/library-snapshots.mjs.map +1 -0
  148. package/dist/pages/library.mjs +113 -220
  149. package/dist/pages/library.mjs.map +1 -1
  150. package/dist/pages/login.mjs +1 -2
  151. package/dist/pages/notifications-paused.mjs +21 -0
  152. package/dist/pages/notifications-paused.mjs.map +1 -0
  153. package/dist/pages/passkey-ceremony.mjs +1 -2
  154. package/dist/pages/profile.mjs +54 -50
  155. package/dist/pages/profile.mjs.map +1 -1
  156. package/dist/pages/project-builds-table.mjs +3 -4
  157. package/dist/pages/project-builds-table.mjs.map +1 -1
  158. package/dist/pages/project-builds.mjs +52 -23
  159. package/dist/pages/project-builds.mjs.map +1 -1
  160. package/dist/pages/project-create.mjs +1 -2
  161. package/dist/pages/project-settings.mjs +52 -14
  162. package/dist/pages/project-settings.mjs.map +1 -1
  163. package/dist/pages/projects-card.mjs +15 -3
  164. package/dist/pages/projects-card.mjs.map +1 -1
  165. package/dist/pages/projects.mjs +7 -4
  166. package/dist/pages/projects.mjs.map +1 -1
  167. package/dist/pages/review-changeset.mjs +115 -0
  168. package/dist/pages/review-changeset.mjs.map +1 -0
  169. package/dist/pages/review-comments.mjs +102 -0
  170. package/dist/pages/review-comments.mjs.map +1 -0
  171. package/dist/pages/review-verdict.mjs +101 -0
  172. package/dist/pages/review-verdict.mjs.map +1 -0
  173. package/dist/pages/root.mjs +1 -2
  174. package/dist/pages/settings-ai.mjs +68 -0
  175. package/dist/pages/settings-ai.mjs.map +1 -0
  176. package/dist/pages/settings-capture.mjs +123 -0
  177. package/dist/pages/settings-capture.mjs.map +1 -0
  178. package/dist/pages/settings-design-credential.mjs +98 -0
  179. package/dist/pages/settings-design-credential.mjs.map +1 -0
  180. package/dist/pages/settings-design-links.mjs +178 -0
  181. package/dist/pages/settings-design-links.mjs.map +1 -0
  182. package/dist/pages/settings-design.mjs +47 -0
  183. package/dist/pages/settings-design.mjs.map +1 -0
  184. package/dist/pages/settings-general.mjs +47 -23
  185. package/dist/pages/settings-general.mjs.map +1 -1
  186. package/dist/pages/settings-labels.mjs +44 -4
  187. package/dist/pages/settings-labels.mjs.map +1 -1
  188. package/dist/pages/settings-links.mjs +111 -0
  189. package/dist/pages/settings-links.mjs.map +1 -0
  190. package/dist/pages/settings-members.mjs +1 -2
  191. package/dist/pages/settings-notifications-git.mjs +127 -0
  192. package/dist/pages/settings-notifications-git.mjs.map +1 -0
  193. package/dist/pages/settings-notifications.mjs +80 -44
  194. package/dist/pages/settings-notifications.mjs.map +1 -1
  195. package/dist/pages/settings-tests.mjs +34 -4
  196. package/dist/pages/settings-tests.mjs.map +1 -1
  197. package/dist/pages/settings-tokens.mjs +1 -2
  198. package/dist/pages/settings-webhooks.mjs +1 -2
  199. package/dist/pages/storybook.mjs +1 -2
  200. package/dist/pages/target-choices.mjs +38 -0
  201. package/dist/pages/target-choices.mjs.map +1 -0
  202. package/dist/publish-setup.mjs +88 -0
  203. package/dist/publish-setup.mjs.map +1 -0
  204. package/dist/retention-timer.mjs +12 -12
  205. package/dist/retention-timer.mjs.map +1 -1
  206. package/dist/review-events.mjs +47 -0
  207. package/dist/review-events.mjs.map +1 -0
  208. package/dist/routers/admin-pages.mjs +46 -5
  209. package/dist/routers/admin-pages.mjs.map +1 -1
  210. package/dist/routers/admin-public-origin.mjs +92 -0
  211. package/dist/routers/admin-public-origin.mjs.map +1 -0
  212. package/dist/routers/admin.mjs +8 -4
  213. package/dist/routers/admin.mjs.map +1 -1
  214. package/dist/routers/assets.mjs +10 -4
  215. package/dist/routers/assets.mjs.map +1 -1
  216. package/dist/routers/attempts.mjs +1 -2
  217. package/dist/routers/auth-sync.mjs +1 -2
  218. package/dist/routers/auth.mjs +2 -3
  219. package/dist/routers/baseline-guard.mjs +4 -5
  220. package/dist/routers/baseline-guard.mjs.map +1 -1
  221. package/dist/routers/baseline-reference.mjs +72 -0
  222. package/dist/routers/baseline-reference.mjs.map +1 -0
  223. package/dist/routers/baselines.handlers.mjs +63 -0
  224. package/dist/routers/baselines.handlers.mjs.map +1 -0
  225. package/dist/routers/baselines.mjs +124 -0
  226. package/dist/routers/baselines.mjs.map +1 -0
  227. package/dist/routers/build-cancel.mjs +67 -0
  228. package/dist/routers/build-cancel.mjs.map +1 -0
  229. package/dist/routers/build-changeset.mjs +69 -0
  230. package/dist/routers/build-changeset.mjs.map +1 -0
  231. package/dist/routers/build-reviews.handlers.mjs +85 -0
  232. package/dist/routers/build-reviews.handlers.mjs.map +1 -0
  233. package/dist/routers/build-reviews.mjs +73 -0
  234. package/dist/routers/build-reviews.mjs.map +1 -0
  235. package/dist/routers/builds.handlers.mjs +65 -60
  236. package/dist/routers/builds.handlers.mjs.map +1 -1
  237. package/dist/routers/builds.mjs +77 -19
  238. package/dist/routers/builds.mjs.map +1 -1
  239. package/dist/routers/capture-cache.mjs +29 -0
  240. package/dist/routers/capture-cache.mjs.map +1 -0
  241. package/dist/routers/capture-config.mjs +34 -0
  242. package/dist/routers/capture-config.mjs.map +1 -0
  243. package/dist/routers/comments.mjs +42 -17
  244. package/dist/routers/comments.mjs.map +1 -1
  245. package/dist/routers/comparison-image.mjs +29 -0
  246. package/dist/routers/comparison-image.mjs.map +1 -0
  247. package/dist/routers/component-catalog.handlers.mjs +70 -0
  248. package/dist/routers/component-catalog.handlers.mjs.map +1 -0
  249. package/dist/routers/component.handlers.mjs +120 -0
  250. package/dist/routers/component.handlers.mjs.map +1 -0
  251. package/dist/routers/connections.mjs +117 -0
  252. package/dist/routers/connections.mjs.map +1 -0
  253. package/dist/routers/design-connect.handlers.mjs +43 -0
  254. package/dist/routers/design-connect.handlers.mjs.map +1 -0
  255. package/dist/routers/design.handlers.mjs +113 -0
  256. package/dist/routers/design.handlers.mjs.map +1 -0
  257. package/dist/routers/flash.mjs +1 -2
  258. package/dist/routers/health-report.mjs +3 -5
  259. package/dist/routers/health-report.mjs.map +1 -1
  260. package/dist/routers/health.mjs +5 -5
  261. package/dist/routers/health.mjs.map +1 -1
  262. package/dist/routers/helpers.mjs +20 -5
  263. package/dist/routers/helpers.mjs.map +1 -1
  264. package/dist/routers/htmx.mjs +1 -2
  265. package/dist/routers/insights-ui.mjs +63 -0
  266. package/dist/routers/insights-ui.mjs.map +1 -0
  267. package/dist/routers/insights.handlers.mjs +44 -0
  268. package/dist/routers/insights.handlers.mjs.map +1 -0
  269. package/dist/routers/insights.mjs +188 -0
  270. package/dist/routers/insights.mjs.map +1 -0
  271. package/dist/routers/labels.mjs +1 -2
  272. package/dist/routers/links.handlers.mjs +79 -0
  273. package/dist/routers/links.handlers.mjs.map +1 -0
  274. package/dist/routers/links.mjs +138 -0
  275. package/dist/routers/links.mjs.map +1 -0
  276. package/dist/routers/media.mjs +30 -7
  277. package/dist/routers/media.mjs.map +1 -1
  278. package/dist/routers/members.mjs +3 -3
  279. package/dist/routers/members.mjs.map +1 -1
  280. package/dist/routers/notification-channels.mjs +18 -25
  281. package/dist/routers/notification-channels.mjs.map +1 -1
  282. package/dist/routers/notification-subscriptions.mjs +1 -2
  283. package/dist/routers/oauth-state.mjs +44 -0
  284. package/dist/routers/oauth-state.mjs.map +1 -0
  285. package/dist/routers/preview-base.mjs +37 -0
  286. package/dist/routers/preview-base.mjs.map +1 -0
  287. package/dist/routers/preview-token.mjs +50 -0
  288. package/dist/routers/preview-token.mjs.map +1 -0
  289. package/dist/routers/profile.mjs +4 -3
  290. package/dist/routers/profile.mjs.map +1 -1
  291. package/dist/routers/projects.mjs +18 -3
  292. package/dist/routers/projects.mjs.map +1 -1
  293. package/dist/routers/publish-upload.mjs +85 -0
  294. package/dist/routers/publish-upload.mjs.map +1 -0
  295. package/dist/routers/published-access.mjs +51 -0
  296. package/dist/routers/published-access.mjs.map +1 -0
  297. package/dist/routers/published-compression.mjs +109 -0
  298. package/dist/routers/published-compression.mjs.map +1 -0
  299. package/dist/routers/published-files.mjs +69 -0
  300. package/dist/routers/published-files.mjs.map +1 -0
  301. package/dist/routers/review-forms.mjs +71 -0
  302. package/dist/routers/review-forms.mjs.map +1 -0
  303. package/dist/routers/review-next.mjs +1 -2
  304. package/dist/routers/review-section.handlers.mjs +84 -0
  305. package/dist/routers/review-section.handlers.mjs.map +1 -0
  306. package/dist/routers/review-switch-off.mjs +28 -0
  307. package/dist/routers/review-switch-off.mjs.map +1 -0
  308. package/dist/routers/schemas.mjs +141 -24
  309. package/dist/routers/schemas.mjs.map +1 -1
  310. package/dist/routers/scoped-models.mjs +21 -0
  311. package/dist/routers/scoped-models.mjs.map +1 -0
  312. package/dist/routers/settings-ai.mjs +34 -0
  313. package/dist/routers/settings-ai.mjs.map +1 -0
  314. package/dist/routers/settings-capture.mjs +76 -0
  315. package/dist/routers/settings-capture.mjs.map +1 -0
  316. package/dist/routers/settings-design.mjs +102 -0
  317. package/dist/routers/settings-design.mjs.map +1 -0
  318. package/dist/routers/settings-general.mjs +56 -12
  319. package/dist/routers/settings-general.mjs.map +1 -1
  320. package/dist/routers/settings-git-channel.mjs +76 -0
  321. package/dist/routers/settings-git-channel.mjs.map +1 -0
  322. package/dist/routers/settings-labels.mjs +28 -3
  323. package/dist/routers/settings-labels.mjs.map +1 -1
  324. package/dist/routers/settings-links.mjs +62 -0
  325. package/dist/routers/settings-links.mjs.map +1 -0
  326. package/dist/routers/settings-members.mjs +5 -9
  327. package/dist/routers/settings-members.mjs.map +1 -1
  328. package/dist/routers/settings-notifications.mjs +16 -12
  329. package/dist/routers/settings-notifications.mjs.map +1 -1
  330. package/dist/routers/settings-tokens.mjs +3 -7
  331. package/dist/routers/settings-tokens.mjs.map +1 -1
  332. package/dist/routers/settings-webhooks.mjs +8 -26
  333. package/dist/routers/settings-webhooks.mjs.map +1 -1
  334. package/dist/routers/settings.handlers.mjs +108 -28
  335. package/dist/routers/settings.handlers.mjs.map +1 -1
  336. package/dist/routers/settings.mjs +17 -6
  337. package/dist/routers/settings.mjs.map +1 -1
  338. package/dist/routers/signed-storybook.mjs +55 -0
  339. package/dist/routers/signed-storybook.mjs.map +1 -0
  340. package/dist/routers/snapshot-groups.mjs +62 -0
  341. package/dist/routers/snapshot-groups.mjs.map +1 -0
  342. package/dist/routers/snapshots.mjs +104 -7
  343. package/dist/routers/snapshots.mjs.map +1 -1
  344. package/dist/routers/storybook.mjs +57 -104
  345. package/dist/routers/storybook.mjs.map +1 -1
  346. package/dist/routers/tokens.mjs +3 -7
  347. package/dist/routers/tokens.mjs.map +1 -1
  348. package/dist/routers/ui.mjs +38 -7
  349. package/dist/routers/ui.mjs.map +1 -1
  350. package/dist/routers/webhooks.mjs +6 -13
  351. package/dist/routers/webhooks.mjs.map +1 -1
  352. package/dist/routers/well-known.mjs +12 -6
  353. package/dist/routers/well-known.mjs.map +1 -1
  354. package/dist/routes/api-routes.mjs +92 -0
  355. package/dist/routes/api-routes.mjs.map +1 -0
  356. package/dist/routes/classification.mjs +37 -0
  357. package/dist/routes/classification.mjs.map +1 -0
  358. package/dist/routes/openapi-classes.mjs +21 -0
  359. package/dist/routes/openapi-classes.mjs.map +1 -0
  360. package/dist/routes/page-routes.mjs +103 -0
  361. package/dist/routes/page-routes.mjs.map +1 -0
  362. package/dist/runtime.mjs +19 -15
  363. package/dist/runtime.mjs.map +1 -1
  364. package/dist/serverless.mjs +4 -0
  365. package/dist/store.mjs +20 -3
  366. package/dist/store.mjs.map +1 -1
  367. package/dist/targets.mjs +45 -0
  368. package/dist/targets.mjs.map +1 -0
  369. package/dist/ui/avatar.mjs +1 -2
  370. package/dist/ui/buttons.mjs +17 -5
  371. package/dist/ui/buttons.mjs.map +1 -1
  372. package/dist/ui/code-block.mjs +1 -2
  373. package/dist/ui/compare-stage.mjs +86 -54
  374. package/dist/ui/compare-stage.mjs.map +1 -1
  375. package/dist/ui/csrf-field.mjs +1 -2
  376. package/dist/ui/css.mjs +1 -2
  377. package/dist/ui/design-reference.mjs +96 -0
  378. package/dist/ui/design-reference.mjs.map +1 -0
  379. package/dist/ui/document.mjs +2 -4
  380. package/dist/ui/document.mjs.map +1 -1
  381. package/dist/ui/dropdown.mjs +1 -2
  382. package/dist/ui/feedback.mjs +1 -2
  383. package/dist/ui/filter-input.mjs +1 -2
  384. package/dist/ui/forms.mjs +7 -7
  385. package/dist/ui/forms.mjs.map +1 -1
  386. package/dist/ui/icons/icon.mjs +1 -2
  387. package/dist/ui/icons/paths.mjs +2 -2
  388. package/dist/ui/icons/paths.mjs.map +1 -1
  389. package/dist/ui/icons/sprite.mjs +1 -2
  390. package/dist/ui/kbd.mjs +1 -2
  391. package/dist/ui/layout.mjs +1 -2
  392. package/dist/ui/preview-embed.mjs +81 -0
  393. package/dist/ui/preview-embed.mjs.map +1 -0
  394. package/dist/ui/progress.mjs +1 -2
  395. package/dist/ui/segmented.mjs +1 -2
  396. package/dist/ui/shell/account.mjs +1 -2
  397. package/dist/ui/shell/bare.mjs +1 -2
  398. package/dist/ui/shell/boot-script.mjs +1 -2
  399. package/dist/ui/shell/client-script.mjs +86 -2
  400. package/dist/ui/shell/client-script.mjs.map +1 -1
  401. package/dist/ui/shell/nav.mjs +13 -10
  402. package/dist/ui/shell/nav.mjs.map +1 -1
  403. package/dist/ui/shell/review-script.mjs +25 -3
  404. package/dist/ui/shell/review-script.mjs.map +1 -1
  405. package/dist/ui/shell/sidebar.mjs +3 -4
  406. package/dist/ui/shell/sidebar.mjs.map +1 -1
  407. package/dist/ui/shell/topbar.mjs +1 -2
  408. package/dist/ui/stacks.mjs +1 -2
  409. package/dist/ui/styles/base.mjs +1 -2
  410. package/dist/ui/styles/behavior.mjs +1 -2
  411. package/dist/ui/styles/review-layout.mjs +1 -2
  412. package/dist/ui/styles/review.mjs +1 -2
  413. package/dist/ui/styles/tokens.mjs +1 -2
  414. package/dist/ui/styles.mjs +1 -2
  415. package/dist/ui/subnav.mjs +1 -2
  416. package/dist/ui/table.mjs +1 -2
  417. package/dist/ui/theme.mjs +1 -2
  418. package/dist/ui/thumbnail.mjs +1 -2
  419. package/dist/ui/time.mjs +1 -2
  420. package/package.json +14 -12
  421. package/dist/asset-paths.mjs +0 -23
  422. package/dist/asset-paths.mjs.map +0 -1
  423. package/dist/assets/mark.svg +0 -1
  424. package/dist/pages/settings-status.mjs +0 -137
  425. package/dist/pages/settings-status.mjs.map +0 -1
  426. package/dist/routers/settings-status.mjs +0 -77
  427. package/dist/routers/settings-status.mjs.map +0 -1
  428. package/dist/routers/status-configs.mjs +0 -108
  429. package/dist/routers/status-configs.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"document.mjs","names":[],"sources":["../../src/ui/document.tsx"],"sourcesContent":["import { raw } from \"hono/html\";\nimport type { FC } from \"hono/jsx\";\nimport { assetManifest } from \"../asset-manifest.ts\";\nimport { getCsrfToken } from \"../middleware/csrf.ts\";\nimport { getStore } from \"../store.ts\";\nimport { Style, css } from \"./css.ts\";\nimport { BareShell } from \"./shell/bare.tsx\";\nimport { bootScript } from \"./shell/boot-script.ts\";\nimport { clientScript } from \"./shell/client-script.ts\";\nimport type { NavConfig } from \"./shell/nav.ts\";\nimport { Sidebar } from \"./shell/sidebar.tsx\";\nimport { ToastRegion, TopBar } from \"./shell/topbar.tsx\";\nimport { baseStyle } from \"./styles.ts\";\nimport { DARK_THEME, LIGHT_THEME } from \"./theme.ts\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\n/** Active section, project, and breadcrumb trail passed to the shell. */\nexport type { NavConfig };\n\n/** Rendered HTML content returned by page components. */\nexport type RenderedContent = string | Promise<string>;\n\n/**\n * Page frame: `default` is a readable column, `wide` uses the full viewport,\n * `bare` drops the app chrome (sign-in, invites).\n */\ntype PageLayout = \"default\" | \"wide\" | \"bare\";\n\nconst shellRoot = css`\n /* shell */\n display: grid;\n grid-template-columns: var(--sidebar-width) minmax(0, 1fr);\n min-height: 100vh;\n @media (max-width: 880px) {\n & {\n grid-template-columns: minmax(0, 1fr);\n }\n }\n`;\n\nconst shellContent = css`\n /* shell-content */\n width: 100%;\n max-width: 1200px;\n margin: 0 auto;\n padding: var(--space-6) var(--space-6) var(--space-8);\n min-width: 0;\n @media (max-width: 880px) {\n & {\n padding: var(--space-4);\n }\n }\n`;\n\nconst shellContentWide = css`\n /* shell-content-wide */\n ${shellContent}\n max-width: none;\n`;\n\nconst shellBackdrop = css`\n /* shell-backdrop */\n position: fixed;\n inset: 0;\n z-index: 55;\n background: rgb(0 0 0 / 0.4);\n &[hidden] {\n display: none;\n }\n`;\n\n// Hono's JSX.Element is typed as `HtmlEscapedString | Promise<...>`, so JSX-returning\n// Functions can legitimately return a promise; the rule is a false positive here.\n/** Full HTML document shell with sidebar, top bar, theme, toasts, and HTMX. */\nexport const DocumentLayout: FC<{\n title: string;\n nav?: NavConfig;\n layout?: PageLayout;\n children?: unknown;\n}> = ({ title, nav, layout = \"default\", children }) => {\n const { ui, config, sessionId } = getStore();\n const name = ui.name ?? \"StoryShelf\";\n const logo = ui.logo ?? assetManifest.mark.href;\n const light = ui.lightTheme ?? LIGHT_THEME;\n const dark = ui.darkTheme ?? DARK_THEME;\n\n return (\n <>\n {/* Without a doctype browsers use quirks mode (form margins, line-box struts, …). */}\n {raw(\"<!DOCTYPE html>\")}\n <html lang=\"en\" data-theme=\"system\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta name=\"color-scheme\" content=\"light dark\" />\n <meta name=\"csrf-token\" content={getCsrfToken(config.secret, sessionId)} />\n {/* Favicon is the product's own mark, not brandable: it identifies\n StoryShelf in the tab strip. `ui.logo` stays overridable. */}\n <link rel=\"icon\" type=\"image/svg+xml\" href={assetManifest.mark.href} />\n <title>\n {title} · {name}\n </title>\n <style dangerouslySetInnerHTML={{ __html: baseStyle(light, dark) }} />\n <Style />\n <script dangerouslySetInnerHTML={{ __html: bootScript() }} />\n </head>\n <body>\n <a class=\"skip-link\" href=\"#main-content\">\n Skip to content\n </a>\n {layout === \"bare\" ? (\n <BareShell name={name} logo={logo}>\n {children}\n </BareShell>\n ) : (\n <>\n <div class={shellRoot}>\n <Sidebar nav={nav} name={name} logo={logo} />\n <div>\n <TopBar nav={nav} />\n <main\n id=\"main-content\"\n class={layout === \"wide\" ? shellContentWide : shellContent}\n tabindex={-1}\n >\n {children}\n </main>\n </div>\n </div>\n <div class={shellBackdrop} data-sidebar-backdrop hidden />\n </>\n )}\n <ToastRegion />\n <script src={assetManifest.htmx.href} />\n <script dangerouslySetInnerHTML={{ __html: clientScript() }} />\n </body>\n </html>\n </>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AA6BA,MAAM,YAAY,GAAG;;;;;;;;;;;AAYrB,MAAM,eAAe,GAAG;;;;;;;;;;;;;AAcxB,MAAM,mBAAmB,GAAG;;IAExB,aAAa;;;AAIjB,MAAM,gBAAgB,GAAG;;;;;;;;;;;AAczB,MAAa,kBAKP,EAAE,OAAO,KAAK,SAAS,WAAW,eAAe;CACrD,MAAM,EAAE,IAAI,QAAQ,cAAc,SAAS;CAC3C,MAAM,OAAO,GAAG,QAAQ;CACxB,MAAM,OAAO,GAAG,QAAQ,cAAc,KAAK;CAC3C,MAAM,QAAQ,GAAG,cAAc;CAC/B,MAAM,OAAO,GAAG,aAAa;CAE7B,OACE,qBAAA,UAAA,EAAA,UAAA,CAEG,IAAI,iBAAiB,GACtB,qBAAC,QAAD;EAAM,MAAK;EAAK,cAAW;EAA3B,UAAA,CACE,qBAAC,QAAD,EAAA,UAAA;GACE,oBAAC,QAAD,EAAM,SAAQ,QAAS,CAAA;GACvB,oBAAC,QAAD;IAAM,MAAK;IAAW,SAAQ;GAAuC,CAAA;GACrE,oBAAC,QAAD;IAAM,MAAK;IAAe,SAAQ;GAAc,CAAA;GAChD,oBAAC,QAAD;IAAM,MAAK;IAAa,SAAS,aAAa,OAAO,QAAQ,SAAS;GAAI,CAAA;GAG1E,oBAAC,QAAD;IAAM,KAAI;IAAO,MAAK;IAAgB,MAAM,cAAc,KAAK;GAAO,CAAA;GACtE,qBAAC,SAAD,EAAA,UAAA;IACG;IAAM;IAAI;GACN,EAAA,CAAA;GACP,oBAAC,SAAD,EAAO,yBAAyB,EAAE,QAAQ,UAAU,OAAO,IAAI,EAAE,EAAI,CAAA;GACrE,oBAAC,OAAD,CAAQ,CAAA;GACR,oBAAC,UAAD,EAAQ,yBAAyB,EAAE,QAAQ,WAAW,EAAE,EAAI,CAAA;EACxD,EAAA,CAAA,GACN,qBAAC,QAAD,EAAA,UAAA;GACE,oBAAC,KAAD;IAAG,OAAM;IAAY,MAAK;IAAgB,UAAA;GAEvC,CAAA;GACF,WAAW,SACV,oBAAC,WAAD;IAAiB;IAAY;IAC1B;GACQ,CAAA,IAEX,qBAAA,UAAA,EAAA,UAAA,CACE,qBAAC,OAAD;IAAK,OAAO;IAAZ,UAAA,CACE,oBAAC,SAAD;KAAc;KAAW;KAAY;IAAO,CAAA,GAC5C,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,QAAD,EAAa,IAAM,CAAA,GACnB,oBAAC,QAAD;KACE,IAAG;KACH,OAAO,WAAW,SAAS,mBAAmB;KAC9C,UAAU;KAET;IACG,CAAA,CACH,EAAA,CAAA,CACF;GACL,CAAA,GAAA,oBAAC,OAAD;IAAK,OAAO;IAAe,yBAAA;IAAsB,QAAA;GAAQ,CAAA,CACzD,EAAA,CAAA;GAEJ,oBAAC,aAAD,CAAc,CAAA;GACd,oBAAC,UAAD,EAAQ,KAAK,cAAc,KAAK,KAAO,CAAA;GACvC,oBAAC,UAAD,EAAQ,yBAAyB,EAAE,QAAQ,aAAa,EAAE,EAAI,CAAA;EAC1D,EAAA,CAAA,CACF;CACN,CAAA,CAAA,EAAA,CAAA;AAEN"}
1
+ {"version":3,"file":"document.mjs","names":[],"sources":["../../src/ui/document.tsx"],"sourcesContent":["import { raw } from \"hono/html\";\nimport type { FC } from \"hono/jsx\";\nimport { assetManifest } from \"../asset-manifest.ts\";\nimport { getCsrfToken } from \"../middleware/csrf.ts\";\nimport { getStore } from \"../store.ts\";\nimport { Style, css } from \"./css.ts\";\nimport { BareShell } from \"./shell/bare.tsx\";\nimport { bootScript } from \"./shell/boot-script.ts\";\nimport type { NavConfig } from \"./shell/nav.ts\";\nimport { Sidebar } from \"./shell/sidebar.tsx\";\nimport { ToastRegion, TopBar } from \"./shell/topbar.tsx\";\nimport { baseStyle } from \"./styles.ts\";\nimport { DARK_THEME, LIGHT_THEME } from \"./theme.ts\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\n/** Active section, project, and breadcrumb trail passed to the shell. */\nexport type { NavConfig };\n\n/** Rendered HTML content returned by page components. */\nexport type RenderedContent = string | Promise<string>;\n\n/**\n * Page frame: `default` is a readable column, `wide` uses the full viewport,\n * `bare` drops the app chrome (sign-in, invites).\n */\ntype PageLayout = \"default\" | \"wide\" | \"bare\";\n\nconst shellRoot = css`\n /* shell */\n display: grid;\n grid-template-columns: var(--sidebar-width) minmax(0, 1fr);\n min-height: 100vh;\n @media (max-width: 880px) {\n & {\n grid-template-columns: minmax(0, 1fr);\n }\n }\n`;\n\nconst shellContent = css`\n /* shell-content */\n width: 100%;\n max-width: 1200px;\n margin: 0 auto;\n padding: var(--space-6) var(--space-6) var(--space-8);\n min-width: 0;\n @media (max-width: 880px) {\n & {\n padding: var(--space-4);\n }\n }\n`;\n\nconst shellContentWide = css`\n /* shell-content-wide */\n ${shellContent}\n max-width: none;\n`;\n\nconst shellBackdrop = css`\n /* shell-backdrop */\n position: fixed;\n inset: 0;\n z-index: 55;\n background: rgb(0 0 0 / 0.4);\n &[hidden] {\n display: none;\n }\n`;\n\n// Hono's JSX.Element is typed as `HtmlEscapedString | Promise<...>`, so JSX-returning\n// Functions can legitimately return a promise; the rule is a false positive here.\n/** Full HTML document shell with sidebar, top bar, theme, toasts, and HTMX. */\nexport const DocumentLayout: FC<{\n title: string;\n nav?: NavConfig;\n layout?: PageLayout;\n children?: unknown;\n}> = ({ title, nav, layout = \"default\", children }) => {\n const { ui, config, sessionId } = getStore();\n const name = ui.name ?? \"StoryShelf\";\n const logo = ui.logo ?? assetManifest.mark.href;\n const light = ui.lightTheme ?? LIGHT_THEME;\n const dark = ui.darkTheme ?? DARK_THEME;\n\n return (\n <>\n {/* Without a doctype browsers use quirks mode (form margins, line-box struts, …). */}\n {raw(\"<!DOCTYPE html>\")}\n <html lang=\"en\" data-theme=\"system\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta name=\"color-scheme\" content=\"light dark\" />\n <meta name=\"csrf-token\" content={getCsrfToken(config.secret, sessionId)} />\n {/* Favicon is the product's own mark, not brandable: it identifies\n StoryShelf in the tab strip. `ui.logo` stays overridable. */}\n <link rel=\"icon\" type=\"image/svg+xml\" href={assetManifest.mark.href} />\n <title>\n {title} · {name}\n </title>\n <style dangerouslySetInnerHTML={{ __html: baseStyle(light, dark) }} />\n <Style />\n <script dangerouslySetInnerHTML={{ __html: bootScript() }} />\n </head>\n <body>\n <a class=\"skip-link\" href=\"#main-content\">\n Skip to content\n </a>\n {layout === \"bare\" ? (\n <BareShell name={name} logo={logo}>\n {children}\n </BareShell>\n ) : (\n <>\n <div class={shellRoot}>\n <Sidebar nav={nav} name={name} logo={logo} />\n <div>\n <TopBar nav={nav} />\n <main\n id=\"main-content\"\n class={layout === \"wide\" ? shellContentWide : shellContent}\n tabindex={-1}\n >\n {children}\n </main>\n </div>\n </div>\n <div class={shellBackdrop} data-sidebar-backdrop hidden />\n </>\n )}\n <ToastRegion />\n <script src={assetManifest.htmx.href} />\n <script src={assetManifest.client.href} />\n </body>\n </html>\n </>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;AA4BA,MAAM,YAAY,GAAG;;;;;;;;;;;AAYrB,MAAM,eAAe,GAAG;;;;;;;;;;;;;AAcxB,MAAM,mBAAmB,GAAG;;IAExB,aAAa;;;AAIjB,MAAM,gBAAgB,GAAG;;;;;;;;;;;AAczB,MAAa,kBAKP,EAAE,OAAO,KAAK,SAAS,WAAW,eAAe;CACrD,MAAM,EAAE,IAAI,QAAQ,cAAc,SAAS;CAC3C,MAAM,OAAO,GAAG,QAAQ;CACxB,MAAM,OAAO,GAAG,QAAQ,cAAc,KAAK;CAC3C,MAAM,QAAQ,GAAG,cAAc;CAC/B,MAAM,OAAO,GAAG,aAAa;CAE7B,OACE,qBAAA,UAAA,EAAA,UAAA,CAEG,IAAI,iBAAiB,GACtB,qBAAC,QAAD;EAAM,MAAK;EAAK,cAAW;EAA3B,UAAA,CACE,qBAAC,QAAD,EAAA,UAAA;GACE,oBAAC,QAAD,EAAM,SAAQ,QAAS,CAAA;GACvB,oBAAC,QAAD;IAAM,MAAK;IAAW,SAAQ;GAAuC,CAAA;GACrE,oBAAC,QAAD;IAAM,MAAK;IAAe,SAAQ;GAAc,CAAA;GAChD,oBAAC,QAAD;IAAM,MAAK;IAAa,SAAS,aAAa,OAAO,QAAQ,SAAS;GAAI,CAAA;GAG1E,oBAAC,QAAD;IAAM,KAAI;IAAO,MAAK;IAAgB,MAAM,cAAc,KAAK;GAAO,CAAA;GACtE,qBAAC,SAAD,EAAA,UAAA;IACG;IAAM;IAAI;GACN,EAAA,CAAA;GACP,oBAAC,SAAD,EAAO,yBAAyB,EAAE,QAAQ,UAAU,OAAO,IAAI,EAAE,EAAI,CAAA;GACrE,oBAAC,OAAD,CAAQ,CAAA;GACR,oBAAC,UAAD,EAAQ,yBAAyB,EAAE,QAAQ,WAAW,EAAE,EAAI,CAAA;EACxD,EAAA,CAAA,GACN,qBAAC,QAAD,EAAA,UAAA;GACE,oBAAC,KAAD;IAAG,OAAM;IAAY,MAAK;IAAgB,UAAA;GAEvC,CAAA;GACF,WAAW,SACV,oBAAC,WAAD;IAAiB;IAAY;IAC1B;GACQ,CAAA,IAEX,qBAAA,UAAA,EAAA,UAAA,CACE,qBAAC,OAAD;IAAK,OAAO;IAAZ,UAAA,CACE,oBAAC,SAAD;KAAc;KAAW;KAAY;IAAO,CAAA,GAC5C,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,QAAD,EAAa,IAAM,CAAA,GACnB,oBAAC,QAAD;KACE,IAAG;KACH,OAAO,WAAW,SAAS,mBAAmB;KAC9C,UAAU;KAET;IACG,CAAA,CACH,EAAA,CAAA,CACF;GACL,CAAA,GAAA,oBAAC,OAAD;IAAK,OAAO;IAAe,yBAAA;IAAsB,QAAA;GAAQ,CAAA,CACzD,EAAA,CAAA;GAEJ,oBAAC,aAAD,CAAc,CAAA;GACd,oBAAC,UAAD,EAAQ,KAAK,cAAc,KAAK,KAAO,CAAA;GACvC,oBAAC,UAAD,EAAQ,KAAK,cAAc,OAAO,KAAO,CAAA;EACrC,EAAA,CAAA,CACF;CACN,CAAA,CAAA,EAAA,CAAA;AAEN"}
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { css } from "./css.mjs";
5
5
  import { Icon } from "./icons/icon.mjs";
6
6
  import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
7
- //#region src/ui/dropdown.tsx
7
+ // src/ui/dropdown.tsx
8
8
  const dropdownRoot = css`
9
9
  /* dropdown */
10
10
  position: relative;
@@ -175,7 +175,6 @@ const DropdownDivider = () => {
175
175
  role: "separator"
176
176
  });
177
177
  };
178
- //#endregion
179
178
  export { Dropdown, DropdownDivider, DropdownItem };
180
179
 
181
180
  //# sourceMappingURL=dropdown.mjs.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { css } from "./css.mjs";
5
5
  import { Icon } from "./icons/icon.mjs";
6
6
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
7
- //#region src/ui/feedback.tsx
7
+ // src/ui/feedback.tsx
8
8
  const badgeBase = css`
9
9
  /* badge */
10
10
  display: inline-flex;
@@ -335,7 +335,6 @@ const Meta = ({ as = "p", mono = false, tone = "neutral", center = false, childr
335
335
  children
336
336
  });
337
337
  };
338
- //#endregion
339
338
  export { Alert, Badge, EmptyState, Meta, Stat, statusTone };
340
339
 
341
340
  //# sourceMappingURL=feedback.mjs.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { css } from "./css.mjs";
5
5
  import { Icon } from "./icons/icon.mjs";
6
6
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
7
- //#region src/ui/filter-input.tsx
7
+ // src/ui/filter-input.tsx
8
8
  const filterWrap = css`
9
9
  /* filter-input */
10
10
  position: relative;
@@ -52,7 +52,6 @@ const FilterInput = ({ label, placeholder = "Filter…" }) => {
52
52
  })]
53
53
  });
54
54
  };
55
- //#endregion
56
55
  export { FilterInput };
57
56
 
58
57
  //# sourceMappingURL=filter-input.mjs.map
package/dist/ui/forms.mjs CHANGED
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { css } from "./css.mjs";
5
5
  import { Icon } from "./icons/icon.mjs";
6
6
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
7
- //#region src/ui/forms.tsx
7
+ // src/ui/forms.tsx
8
8
  const fieldWrap = css`
9
9
  /* field */
10
10
  display: grid;
@@ -226,28 +226,29 @@ const CheckField = ({ label, name, value, checked, disabled, hint }) => {
226
226
  });
227
227
  };
228
228
  /** Labeled textarea with error and hint states. */
229
- const TextareaField = ({ label, name, value, placeholder, rows = 3, required, hint, error }) => {
229
+ const TextareaField = ({ label, name, id, value, placeholder, rows = 3, required, hint, error }) => {
230
+ const domId = id ?? name;
230
231
  return /* @__PURE__ */ jsxs("div", {
231
232
  class: fieldWrap,
232
233
  children: [
233
234
  /* @__PURE__ */ jsx("label", {
234
235
  class: fieldLabel,
235
- for: name,
236
+ for: domId,
236
237
  children: label
237
238
  }),
238
239
  /* @__PURE__ */ jsx("textarea", {
239
240
  class: error ? fieldTextareaError : fieldTextarea,
240
- id: name,
241
+ id: domId,
241
242
  name,
242
243
  placeholder,
243
244
  rows,
244
245
  required,
245
246
  "aria-invalid": error ? "true" : void 0,
246
- "aria-describedby": fieldDescribedBy(name, error, hint),
247
+ "aria-describedby": fieldDescribedBy(domId, error, hint),
247
248
  children: value
248
249
  }),
249
250
  /* @__PURE__ */ jsx(FieldAssistant, {
250
- name,
251
+ name: domId,
251
252
  error,
252
253
  hint
253
254
  })
@@ -285,7 +286,6 @@ const SelectField = ({ label, name, value, options, hint, disabled, required, la
285
286
  ]
286
287
  });
287
288
  };
288
- //#endregion
289
289
  export { CheckField, Field, FormActions, SelectField, TextareaField };
290
290
 
291
291
  //# sourceMappingURL=forms.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"forms.mjs","names":[],"sources":["../../src/ui/forms.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\nimport { css } from \"./css.ts\";\nimport { Icon } from \"./icons/icon.tsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\ntype FieldLayout = \"stack\" | \"inline\";\n\nconst fieldWrap = css`\n /* field */\n display: grid;\n gap: var(--space-1);\n /* Don't stretch rows when a neighbouring field is taller (hint text). */\n align-content: start;\n margin-bottom: var(--space-4);\n`;\n\nconst fieldWrapInline = css`\n /* field-inline */\n ${fieldWrap}\n grid-template-columns: auto minmax(0, 1fr);\n align-items: center;\n gap: var(--space-2);\n margin-bottom: 0;\n`;\n\nconst fieldLabel = css`\n /* field-label */\n color: var(--text-primary);\n font-weight: 600;\n font-size: var(--text-sm);\n & span[aria-hidden] {\n color: var(--status-rejected);\n }\n`;\n\nconst fieldInput = css`\n /* field-input */\n width: 100%;\n min-height: 40px;\n padding: 0.5rem 0.75rem;\n border-radius: var(--radius);\n border: 1px solid var(--border);\n background: var(--surface-card);\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-base);\n box-shadow: var(--shadow);\n transition:\n border-color var(--dur-fast) var(--ease),\n box-shadow var(--dur-fast) var(--ease);\n &::placeholder {\n color: var(--text-muted);\n }\n &:hover:not(:disabled) {\n border-color: color-mix(in srgb, var(--text-secondary) 45%, var(--border));\n }\n &:focus {\n outline: none;\n border-color: var(--ring);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--ring) 25%, transparent);\n }\n &:disabled {\n background: var(--surface-muted);\n color: var(--text-secondary);\n cursor: not-allowed;\n }\n`;\n\nconst fieldInputError = css`\n /* field-input-error */\n ${fieldInput}\n border-color: var(--status-rejected);\n &:focus {\n border-color: var(--status-rejected);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-rejected) 25%, transparent);\n }\n`;\n\nconst fieldTextarea = css`\n /* field-textarea */\n ${fieldInput}\n resize: vertical;\n min-height: 5.5rem;\n line-height: var(--leading-normal);\n`;\n\nconst fieldTextareaError = css`\n /* field-textarea-error */\n ${fieldInputError}\n resize: vertical;\n min-height: 5.5rem;\n line-height: var(--leading-normal);\n`;\n\nconst fieldHint = css`\n /* field-hint */\n margin: 0;\n color: var(--text-secondary);\n font-size: var(--text-sm);\n`;\n\nconst fieldError = css`\n /* field-error */\n display: flex;\n gap: var(--space-1);\n align-items: flex-start;\n margin: 0;\n color: var(--status-rejected-fg);\n font-size: var(--text-sm);\n font-weight: 600;\n`;\n\nconst formActions = css`\n /* form-actions */\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-2);\n align-items: center;\n margin-top: var(--space-4);\n`;\n\nconst formActionsEnd = css`\n /* form-actions-end */\n ${formActions}\n justify-content: flex-end;\n`;\n\nconst formActionsSplit = css`\n /* form-actions-split */\n ${formActions}\n justify-content: space-between;\n`;\n\n/** Row of form buttons: primary action first; `align=\"end\"` right-aligns, `\"split\"` spreads. */\nexport const FormActions: FC<{ align?: \"start\" | \"end\" | \"split\"; children?: unknown }> = ({\n align = \"start\",\n children,\n}) => {\n const cls = align === \"end\" ? formActionsEnd : align === \"split\" ? formActionsSplit : formActions;\n return <div class={cls}>{children}</div>;\n};\n\nfunction fieldDescribedBy(\n name: string,\n error: string | undefined,\n hint: string | undefined,\n): string | undefined {\n if (error) {\n return `${name}-error`;\n }\n if (hint) {\n return `${name}-hint`;\n }\n return undefined;\n}\n\n// eslint-disable-next-line promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString>\nconst FieldAssistant: FC<{ name: string; error: string | undefined; hint: string | undefined }> = ({\n name,\n error,\n hint,\n}) => {\n if (error) {\n return (\n <p class={fieldError} id={`${name}-error`} role=\"alert\">\n <Icon name=\"x-circle\" size=\"sm\" />\n <span>{error}</span>\n </p>\n );\n }\n if (hint) {\n return (\n <p class={fieldHint} id={`${name}-hint`}>\n {hint}\n </p>\n );\n }\n return null;\n};\n\n/** Labeled text input with error and hint states. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Field: FC<{\n label: string;\n name: string;\n type?: string;\n value?: string;\n placeholder?: string;\n required?: boolean;\n disabled?: boolean;\n autofocus?: boolean;\n pattern?: string;\n min?: string;\n max?: string;\n step?: string;\n layout?: FieldLayout;\n error?: string;\n hint?: string;\n autocomplete?: string;\n}> = ({\n label,\n name,\n type = \"text\",\n value,\n placeholder,\n required,\n disabled,\n autofocus,\n pattern,\n min,\n max,\n step,\n layout = \"stack\",\n error,\n hint,\n autocomplete,\n}) => {\n return (\n <div class={layout === \"inline\" ? fieldWrapInline : fieldWrap}>\n <label class={fieldLabel} for={name}>\n {label}\n {required ? <span aria-hidden=\"true\"> *</span> : null}\n </label>\n <input\n class={error ? fieldInputError : fieldInput}\n id={name}\n name={name}\n type={type}\n value={value}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n autofocus={autofocus}\n pattern={pattern}\n min={min}\n max={max}\n step={step}\n aria-invalid={error ? \"true\" : undefined}\n aria-describedby={fieldDescribedBy(name, error, hint)}\n autocomplete={autocomplete}\n />\n <FieldAssistant name={name} error={error} hint={hint} />\n </div>\n );\n};\n\nconst checkLabel = css`\n /* check-label */\n display: flex;\n gap: var(--space-2);\n align-items: center;\n font-weight: 500;\n font-size: var(--text-base);\n cursor: pointer;\n`;\n\nconst checkInput = css`\n /* check-input */\n width: 1rem;\n height: 1rem;\n accent-color: var(--accent);\n flex: none;\n`;\n\n/** Inline checkbox row with an optional hint. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const CheckField: FC<{\n label: unknown;\n name: string;\n value?: string;\n checked?: boolean;\n disabled?: boolean;\n hint?: string;\n}> = ({ label, name, value, checked, disabled, hint }) => {\n return (\n <div class={fieldWrap}>\n <label class={checkLabel} for={name}>\n <input\n class={checkInput}\n type=\"checkbox\"\n id={name}\n name={name}\n value={value}\n checked={checked}\n disabled={disabled}\n />\n {label}\n </label>\n {hint ? (\n <p class={fieldHint} id={`${name}-hint`}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n};\n\n/** Labeled textarea with error and hint states. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const TextareaField: FC<{\n label: string;\n name: string;\n value?: string;\n placeholder?: string;\n rows?: number;\n required?: boolean;\n hint?: string;\n error?: string;\n}> = ({ label, name, value, placeholder, rows = 3, required, hint, error }) => {\n return (\n <div class={fieldWrap}>\n <label class={fieldLabel} for={name}>\n {label}\n </label>\n <textarea\n class={error ? fieldTextareaError : fieldTextarea}\n id={name}\n name={name}\n placeholder={placeholder}\n rows={rows}\n required={required}\n aria-invalid={error ? \"true\" : undefined}\n aria-describedby={fieldDescribedBy(name, error, hint)}\n >\n {value}\n </textarea>\n <FieldAssistant name={name} error={error} hint={hint} />\n </div>\n );\n};\n\n/** Labeled select dropdown with an optional hint. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const SelectField: FC<{\n label: string;\n name: string;\n value?: string;\n options: { value: string; label: string }[];\n hint?: string;\n disabled?: boolean;\n required?: boolean;\n layout?: FieldLayout;\n}> = ({ label, name, value, options, hint, disabled, required, layout = \"stack\" }) => {\n return (\n <div class={layout === \"inline\" ? fieldWrapInline : fieldWrap}>\n <label class={fieldLabel} for={name}>\n {label}\n </label>\n <select\n class={fieldInput}\n id={name}\n name={name}\n disabled={disabled}\n required={required}\n aria-describedby={hint ? `${name}-hint` : undefined}\n >\n {options.map((opt) => (\n <option value={opt.value} selected={opt.value === value}>\n {opt.label}\n </option>\n ))}\n </select>\n {hint ? (\n <p class={fieldHint} id={`${name}-hint`}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"forms.mjs","names":[],"sources":["../../src/ui/forms.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\nimport { css } from \"./css.ts\";\nimport { Icon } from \"./icons/icon.tsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\ntype FieldLayout = \"stack\" | \"inline\";\n\nconst fieldWrap = css`\n /* field */\n display: grid;\n gap: var(--space-1);\n /* Don't stretch rows when a neighbouring field is taller (hint text). */\n align-content: start;\n margin-bottom: var(--space-4);\n`;\n\nconst fieldWrapInline = css`\n /* field-inline */\n ${fieldWrap}\n grid-template-columns: auto minmax(0, 1fr);\n align-items: center;\n gap: var(--space-2);\n margin-bottom: 0;\n`;\n\nconst fieldLabel = css`\n /* field-label */\n color: var(--text-primary);\n font-weight: 600;\n font-size: var(--text-sm);\n & span[aria-hidden] {\n color: var(--status-rejected);\n }\n`;\n\nconst fieldInput = css`\n /* field-input */\n width: 100%;\n min-height: 40px;\n padding: 0.5rem 0.75rem;\n border-radius: var(--radius);\n border: 1px solid var(--border);\n background: var(--surface-card);\n color: var(--text-primary);\n font: inherit;\n font-size: var(--text-base);\n box-shadow: var(--shadow);\n transition:\n border-color var(--dur-fast) var(--ease),\n box-shadow var(--dur-fast) var(--ease);\n &::placeholder {\n color: var(--text-muted);\n }\n &:hover:not(:disabled) {\n border-color: color-mix(in srgb, var(--text-secondary) 45%, var(--border));\n }\n &:focus {\n outline: none;\n border-color: var(--ring);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--ring) 25%, transparent);\n }\n &:disabled {\n background: var(--surface-muted);\n color: var(--text-secondary);\n cursor: not-allowed;\n }\n`;\n\nconst fieldInputError = css`\n /* field-input-error */\n ${fieldInput}\n border-color: var(--status-rejected);\n &:focus {\n border-color: var(--status-rejected);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-rejected) 25%, transparent);\n }\n`;\n\nconst fieldTextarea = css`\n /* field-textarea */\n ${fieldInput}\n resize: vertical;\n min-height: 5.5rem;\n line-height: var(--leading-normal);\n`;\n\nconst fieldTextareaError = css`\n /* field-textarea-error */\n ${fieldInputError}\n resize: vertical;\n min-height: 5.5rem;\n line-height: var(--leading-normal);\n`;\n\nconst fieldHint = css`\n /* field-hint */\n margin: 0;\n color: var(--text-secondary);\n font-size: var(--text-sm);\n`;\n\nconst fieldError = css`\n /* field-error */\n display: flex;\n gap: var(--space-1);\n align-items: flex-start;\n margin: 0;\n color: var(--status-rejected-fg);\n font-size: var(--text-sm);\n font-weight: 600;\n`;\n\nconst formActions = css`\n /* form-actions */\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-2);\n align-items: center;\n margin-top: var(--space-4);\n`;\n\nconst formActionsEnd = css`\n /* form-actions-end */\n ${formActions}\n justify-content: flex-end;\n`;\n\nconst formActionsSplit = css`\n /* form-actions-split */\n ${formActions}\n justify-content: space-between;\n`;\n\n/** Row of form buttons: primary action first; `align=\"end\"` right-aligns, `\"split\"` spreads. */\nexport const FormActions: FC<{ align?: \"start\" | \"end\" | \"split\"; children?: unknown }> = ({\n align = \"start\",\n children,\n}) => {\n const cls = align === \"end\" ? formActionsEnd : align === \"split\" ? formActionsSplit : formActions;\n return <div class={cls}>{children}</div>;\n};\n\nfunction fieldDescribedBy(\n name: string,\n error: string | undefined,\n hint: string | undefined,\n): string | undefined {\n if (error) {\n return `${name}-error`;\n }\n if (hint) {\n return `${name}-hint`;\n }\n return undefined;\n}\n\n// eslint-disable-next-line promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString>\nconst FieldAssistant: FC<{ name: string; error: string | undefined; hint: string | undefined }> = ({\n name,\n error,\n hint,\n}) => {\n if (error) {\n return (\n <p class={fieldError} id={`${name}-error`} role=\"alert\">\n <Icon name=\"x-circle\" size=\"sm\" />\n <span>{error}</span>\n </p>\n );\n }\n if (hint) {\n return (\n <p class={fieldHint} id={`${name}-hint`}>\n {hint}\n </p>\n );\n }\n return null;\n};\n\n/** Labeled text input with error and hint states. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Field: FC<{\n label: string;\n name: string;\n type?: string;\n value?: string;\n placeholder?: string;\n required?: boolean;\n disabled?: boolean;\n autofocus?: boolean;\n pattern?: string;\n min?: string;\n max?: string;\n step?: string;\n layout?: FieldLayout;\n error?: string;\n hint?: string;\n autocomplete?: string;\n}> = ({\n label,\n name,\n type = \"text\",\n value,\n placeholder,\n required,\n disabled,\n autofocus,\n pattern,\n min,\n max,\n step,\n layout = \"stack\",\n error,\n hint,\n autocomplete,\n}) => {\n return (\n <div class={layout === \"inline\" ? fieldWrapInline : fieldWrap}>\n <label class={fieldLabel} for={name}>\n {label}\n {required ? <span aria-hidden=\"true\"> *</span> : null}\n </label>\n <input\n class={error ? fieldInputError : fieldInput}\n id={name}\n name={name}\n type={type}\n value={value}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n autofocus={autofocus}\n pattern={pattern}\n min={min}\n max={max}\n step={step}\n aria-invalid={error ? \"true\" : undefined}\n aria-describedby={fieldDescribedBy(name, error, hint)}\n autocomplete={autocomplete}\n />\n <FieldAssistant name={name} error={error} hint={hint} />\n </div>\n );\n};\n\nconst checkLabel = css`\n /* check-label */\n display: flex;\n gap: var(--space-2);\n align-items: center;\n font-weight: 500;\n font-size: var(--text-base);\n cursor: pointer;\n`;\n\nconst checkInput = css`\n /* check-input */\n width: 1rem;\n height: 1rem;\n accent-color: var(--accent);\n flex: none;\n`;\n\n/** Inline checkbox row with an optional hint. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const CheckField: FC<{\n label: unknown;\n name: string;\n value?: string;\n checked?: boolean;\n disabled?: boolean;\n hint?: string;\n}> = ({ label, name, value, checked, disabled, hint }) => {\n return (\n <div class={fieldWrap}>\n <label class={checkLabel} for={name}>\n <input\n class={checkInput}\n type=\"checkbox\"\n id={name}\n name={name}\n value={value}\n checked={checked}\n disabled={disabled}\n />\n {label}\n </label>\n {hint ? (\n <p class={fieldHint} id={`${name}-hint`}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n};\n\n/** Labeled textarea with error and hint states. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const TextareaField: FC<{\n label: string;\n name: string;\n /** DOM id when several forms on a page post the same field name (defaults to `name`). */\n id?: string;\n value?: string;\n placeholder?: string;\n rows?: number;\n required?: boolean;\n hint?: string;\n error?: string;\n}> = ({ label, name, id, value, placeholder, rows = 3, required, hint, error }) => {\n const domId = id ?? name;\n return (\n <div class={fieldWrap}>\n <label class={fieldLabel} for={domId}>\n {label}\n </label>\n <textarea\n class={error ? fieldTextareaError : fieldTextarea}\n id={domId}\n name={name}\n placeholder={placeholder}\n rows={rows}\n required={required}\n aria-invalid={error ? \"true\" : undefined}\n aria-describedby={fieldDescribedBy(domId, error, hint)}\n >\n {value}\n </textarea>\n <FieldAssistant name={domId} error={error} hint={hint} />\n </div>\n );\n};\n\n/** Labeled select dropdown with an optional hint. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const SelectField: FC<{\n label: string;\n name: string;\n value?: string;\n options: { value: string; label: string }[];\n hint?: string;\n disabled?: boolean;\n required?: boolean;\n layout?: FieldLayout;\n}> = ({ label, name, value, options, hint, disabled, required, layout = \"stack\" }) => {\n return (\n <div class={layout === \"inline\" ? fieldWrapInline : fieldWrap}>\n <label class={fieldLabel} for={name}>\n {label}\n </label>\n <select\n class={fieldInput}\n id={name}\n name={name}\n disabled={disabled}\n required={required}\n aria-describedby={hint ? `${name}-hint` : undefined}\n >\n {options.map((opt) => (\n <option value={opt.value} selected={opt.value === value}>\n {opt.label}\n </option>\n ))}\n </select>\n {hint ? (\n <p class={fieldHint} id={`${name}-hint`}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n};\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { css } from "../css.mjs";
5
5
  import { iconHref } from "./sprite.mjs";
6
6
  import { jsx } from "hono/jsx/jsx-runtime";
7
- //#region src/ui/icons/icon.tsx
7
+ // src/ui/icons/icon.tsx
8
8
  const iconBase = css`
9
9
  /* icon */
10
10
  flex: none;
@@ -47,7 +47,6 @@ const Icon = ({ name, size = "md", label }) => {
47
47
  children: /* @__PURE__ */ jsx("use", { href: iconHref(name) })
48
48
  });
49
49
  };
50
- //#endregion
51
50
  export { Icon };
52
51
 
53
52
  //# sourceMappingURL=icon.mjs.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/ui/icons/paths.ts
4
+ // src/ui/icons/paths.ts
5
5
  /**
6
6
  * Icon set: inner SVG markup per icon on a 24x24 grid, stroke-based
7
7
  * (Lucide-style, ISC). Add an icon here and it is in the sprite and the
@@ -23,6 +23,7 @@ const ICON_PATHS = {
23
23
  "git-branch": "<path d=\"M6 3v12\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><path d=\"M18 9a9 9 0 0 1-9 9\"/>",
24
24
  "git-commit": "<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M3 12h6M15 12h6\"/>",
25
25
  activity: "<path d=\"M22 12h-4l-3 9L9 3l-3 9H2\"/>",
26
+ sparkles: "<path d=\"M9.9 15.5A2 2 0 0 0 8.5 14.1l-6.1-1.6a.5.5 0 0 1 0-1L8.5 9.9A2 2 0 0 0 9.9 8.5l1.6-6.1a.5.5 0 0 1 1 0l1.6 6.1a2 2 0 0 0 1.4 1.4l6.1 1.6a.5.5 0 0 1 0 1l-6.1 1.6a2 2 0 0 0-1.4 1.4l-1.6 6.1a.5.5 0 0 1-1 0z\"/><path d=\"M20 3v4M22 5h-4M4 17v2M5 18H3\"/>",
26
27
  tag: "<path d=\"M12.6 2.6A2 2 0 0 0 11.2 2H4a2 2 0 0 0-2 2v7.2a2 2 0 0 0 .6 1.4l8.7 8.7a2.4 2.4 0 0 0 3.4 0l6.6-6.6a2.4 2.4 0 0 0 0-3.4z\"/><circle cx=\"7.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/>",
27
28
  settings: "<path d=\"M12.2 2h-.4a2 2 0 0 0-2 2v.2a2 2 0 0 1-1 1.7l-.4.3a2 2 0 0 1-2 0l-.2-.1a2 2 0 0 0-2.7.7l-.2.4a2 2 0 0 0 .7 2.7l.2.1a2 2 0 0 1 1 1.7v.5a2 2 0 0 1-1 1.8l-.2.1a2 2 0 0 0-.7 2.7l.2.4a2 2 0 0 0 2.7.7l.2-.1a2 2 0 0 1 2 0l.4.3a2 2 0 0 1 1 1.7v.2a2 2 0 0 0 2 2h.4a2 2 0 0 0 2-2v-.2a2 2 0 0 1 1-1.7l.4-.3a2 2 0 0 1 2 0l.2.1a2 2 0 0 0 2.7-.7l.2-.4a2 2 0 0 0-.7-2.7l-.2-.1a2 2 0 0 1-1-1.8v-.5a2 2 0 0 1 1-1.7l.2-.1a2 2 0 0 0 .7-2.7l-.2-.4a2 2 0 0 0-2.7-.7l-.2.1a2 2 0 0 1-2 0l-.4-.3a2 2 0 0 1-1-1.7V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>",
28
29
  users: "<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8\"/>",
@@ -55,7 +56,6 @@ const ICON_PATHS = {
55
56
  book: "<path d=\"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20\"/>",
56
57
  server: "<rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\"/><rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\"/><path d=\"M6 6h.01M6 18h.01\"/>"
57
58
  };
58
- //#endregion
59
59
  export { ICON_PATHS };
60
60
 
61
61
  //# sourceMappingURL=paths.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.mjs","names":[],"sources":["../../../src/ui/icons/paths.ts"],"sourcesContent":["/**\n * Icon set: inner SVG markup per icon on a 24x24 grid, stroke-based\n * (Lucide-style, ISC). Add an icon here and it is in the sprite and the\n * `IconName` union automatically.\n */\nexport const ICON_PATHS = {\n check: '<path d=\"M20 6 9 17l-5-5\"/>',\n x: '<path d=\"M18 6 6 18M6 6l12 12\"/>',\n plus: '<path d=\"M5 12h14M12 5v14\"/>',\n \"chevron-down\": '<path d=\"m6 9 6 6 6-6\"/>',\n \"chevron-up\": '<path d=\"m18 15-6-6-6 6\"/>',\n \"chevron-right\": '<path d=\"m9 18 6-6-6-6\"/>',\n \"chevron-left\": '<path d=\"m15 18-6-6 6-6\"/>',\n \"chevrons-left\": '<path d=\"m11 17-5-5 5-5M18 17l-5-5 5-5\"/>',\n \"arrow-right\": '<path d=\"M5 12h14M12 5l7 7-7 7\"/>',\n folder:\n '<path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\"/>',\n layers: '<path d=\"m12 2 10 5-10 5L2 7zM2 17l10 5 10-5M2 12l10 5 10-5\"/>',\n image:\n '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"2\"/><path d=\"m21 15-3.1-3.1a2 2 0 0 0-2.8 0L6 21\"/>',\n \"git-branch\":\n '<path d=\"M6 3v12\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><path d=\"M18 9a9 9 0 0 1-9 9\"/>',\n \"git-commit\": '<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M3 12h6M15 12h6\"/>',\n activity: '<path d=\"M22 12h-4l-3 9L9 3l-3 9H2\"/>',\n tag: '<path d=\"M12.6 2.6A2 2 0 0 0 11.2 2H4a2 2 0 0 0-2 2v7.2a2 2 0 0 0 .6 1.4l8.7 8.7a2.4 2.4 0 0 0 3.4 0l6.6-6.6a2.4 2.4 0 0 0 0-3.4z\"/><circle cx=\"7.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/>',\n settings:\n '<path d=\"M12.2 2h-.4a2 2 0 0 0-2 2v.2a2 2 0 0 1-1 1.7l-.4.3a2 2 0 0 1-2 0l-.2-.1a2 2 0 0 0-2.7.7l-.2.4a2 2 0 0 0 .7 2.7l.2.1a2 2 0 0 1 1 1.7v.5a2 2 0 0 1-1 1.8l-.2.1a2 2 0 0 0-.7 2.7l.2.4a2 2 0 0 0 2.7.7l.2-.1a2 2 0 0 1 2 0l.4.3a2 2 0 0 1 1 1.7v.2a2 2 0 0 0 2 2h.4a2 2 0 0 0 2-2v-.2a2 2 0 0 1 1-1.7l.4-.3a2 2 0 0 1 2 0l.2.1a2 2 0 0 0 2.7-.7l.2-.4a2 2 0 0 0-.7-2.7l-.2-.1a2 2 0 0 1-1-1.8v-.5a2 2 0 0 1 1-1.7l.2-.1a2 2 0 0 0 .7-2.7l-.2-.4a2 2 0 0 0-2.7-.7l-.2.1a2 2 0 0 1-2 0l-.4-.3a2 2 0 0 1-1-1.7V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n users:\n '<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8\"/>',\n user: '<path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/>',\n key: '<path d=\"m21 2-9.6 9.6M15.5 7.5l3 3L22 7l-3-3\"/><circle cx=\"7.5\" cy=\"15.5\" r=\"5.5\"/>',\n bell: '<path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9M10.3 21a1.9 1.9 0 0 0 3.4 0\"/>',\n webhook:\n '<path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2M9 17l3.13-5.78c.53-.97.43-2.22-.26-3.07a4 4 0 1 1 6.58-4.2c.38.6.58 1.3.57 2M6 17a4 4 0 0 1 6-3.5\"/><path d=\"M12 17h6a2 2 0 1 1 0 4\"/>',\n code: '<path d=\"m16 18 6-6-6-6M8 6l-6 6 6 6\"/>',\n terminal: '<path d=\"m4 17 6-6-6-6M12 19h8\"/>',\n shield:\n '<path d=\"M20 13c0 5-3.5 7.5-7.7 8.9a1 1 0 0 1-.6 0C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.2-2.7a1.2 1.2 0 0 1 1.6 0C14.5 3.8 17 5 19 5a1 1 0 0 1 1 1z\"/>',\n search: '<circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>',\n sun: '<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M6.3 17.7l-1.4 1.4M19.1 4.9l-1.4 1.4\"/>',\n moon: '<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"/>',\n monitor: '<rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\"/><path d=\"M8 21h8M12 17v4\"/>',\n menu: '<path d=\"M4 6h16M4 12h16M4 18h16\"/>',\n \"more-horizontal\":\n '<circle cx=\"12\" cy=\"12\" r=\"1\"/><circle cx=\"19\" cy=\"12\" r=\"1\"/><circle cx=\"5\" cy=\"12\" r=\"1\"/>',\n \"log-out\": '<path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9\"/>',\n \"external-link\":\n '<path d=\"M15 3h6v6M10 14 21 3M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/>',\n copy: '<rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/>',\n \"check-circle\": '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m9 12 2 2 4-4\"/>',\n \"x-circle\": '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m15 9-6 6M9 9l6 6\"/>',\n \"alert-triangle\":\n '<path d=\"m21.7 18-8-14a2 2 0 0 0-3.5 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3M12 9v4M12 17h.01\"/>',\n info: '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4M12 8h.01\"/>',\n clock: '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 6v6l4 2\"/>',\n loader: '<path d=\"M21 12a9 9 0 1 1-6.2-8.6\"/>',\n \"message-square\": '<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>',\n columns: '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/><path d=\"M12 3v18\"/>',\n maximize:\n '<path d=\"M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M16 21h3a2 2 0 0 0 2-2v-3\"/>',\n \"zoom-in\": '<circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3M11 8v6M8 11h6\"/>',\n book: '<path d=\"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20\"/>',\n server:\n '<rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\"/><rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\"/><path d=\"M6 6h.01M6 18h.01\"/>',\n} as const;\n\n/** Every icon name available in the sprite. */\nexport type IconName = keyof typeof ICON_PATHS;\n"],"mappings":";;;;;;;;;AAKA,MAAa,aAAa;CACxB,OAAO;CACP,GAAG;CACH,MAAM;CACN,gBAAgB;CAChB,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,iBAAiB;CACjB,eAAe;CACf,QACE;CACF,QAAQ;CACR,OACE;CACF,cACE;CACF,cAAc;CACd,UAAU;CACV,KAAK;CACL,UACE;CACF,OACE;CACF,MAAM;CACN,KAAK;CACL,MAAM;CACN,SACE;CACF,MAAM;CACN,UAAU;CACV,QACE;CACF,QAAQ;CACR,KAAK;CACL,MAAM;CACN,SAAS;CACT,MAAM;CACN,mBACE;CACF,WAAW;CACX,iBACE;CACF,MAAM;CACN,gBAAgB;CAChB,YAAY;CACZ,kBACE;CACF,MAAM;CACN,OAAO;CACP,QAAQ;CACR,kBAAkB;CAClB,SAAS;CACT,UACE;CACF,WAAW;CACX,MAAM;CACN,QACE;AACJ"}
1
+ {"version":3,"file":"paths.mjs","names":[],"sources":["../../../src/ui/icons/paths.ts"],"sourcesContent":["/**\n * Icon set: inner SVG markup per icon on a 24x24 grid, stroke-based\n * (Lucide-style, ISC). Add an icon here and it is in the sprite and the\n * `IconName` union automatically.\n */\nexport const ICON_PATHS = {\n check: '<path d=\"M20 6 9 17l-5-5\"/>',\n x: '<path d=\"M18 6 6 18M6 6l12 12\"/>',\n plus: '<path d=\"M5 12h14M12 5v14\"/>',\n \"chevron-down\": '<path d=\"m6 9 6 6 6-6\"/>',\n \"chevron-up\": '<path d=\"m18 15-6-6-6 6\"/>',\n \"chevron-right\": '<path d=\"m9 18 6-6-6-6\"/>',\n \"chevron-left\": '<path d=\"m15 18-6-6 6-6\"/>',\n \"chevrons-left\": '<path d=\"m11 17-5-5 5-5M18 17l-5-5 5-5\"/>',\n \"arrow-right\": '<path d=\"M5 12h14M12 5l7 7-7 7\"/>',\n folder:\n '<path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\"/>',\n layers: '<path d=\"m12 2 10 5-10 5L2 7zM2 17l10 5 10-5M2 12l10 5 10-5\"/>',\n image:\n '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"2\"/><path d=\"m21 15-3.1-3.1a2 2 0 0 0-2.8 0L6 21\"/>',\n \"git-branch\":\n '<path d=\"M6 3v12\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><path d=\"M18 9a9 9 0 0 1-9 9\"/>',\n \"git-commit\": '<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M3 12h6M15 12h6\"/>',\n activity: '<path d=\"M22 12h-4l-3 9L9 3l-3 9H2\"/>',\n sparkles:\n '<path d=\"M9.9 15.5A2 2 0 0 0 8.5 14.1l-6.1-1.6a.5.5 0 0 1 0-1L8.5 9.9A2 2 0 0 0 9.9 8.5l1.6-6.1a.5.5 0 0 1 1 0l1.6 6.1a2 2 0 0 0 1.4 1.4l6.1 1.6a.5.5 0 0 1 0 1l-6.1 1.6a2 2 0 0 0-1.4 1.4l-1.6 6.1a.5.5 0 0 1-1 0z\"/><path d=\"M20 3v4M22 5h-4M4 17v2M5 18H3\"/>',\n tag: '<path d=\"M12.6 2.6A2 2 0 0 0 11.2 2H4a2 2 0 0 0-2 2v7.2a2 2 0 0 0 .6 1.4l8.7 8.7a2.4 2.4 0 0 0 3.4 0l6.6-6.6a2.4 2.4 0 0 0 0-3.4z\"/><circle cx=\"7.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/>',\n settings:\n '<path d=\"M12.2 2h-.4a2 2 0 0 0-2 2v.2a2 2 0 0 1-1 1.7l-.4.3a2 2 0 0 1-2 0l-.2-.1a2 2 0 0 0-2.7.7l-.2.4a2 2 0 0 0 .7 2.7l.2.1a2 2 0 0 1 1 1.7v.5a2 2 0 0 1-1 1.8l-.2.1a2 2 0 0 0-.7 2.7l.2.4a2 2 0 0 0 2.7.7l.2-.1a2 2 0 0 1 2 0l.4.3a2 2 0 0 1 1 1.7v.2a2 2 0 0 0 2 2h.4a2 2 0 0 0 2-2v-.2a2 2 0 0 1 1-1.7l.4-.3a2 2 0 0 1 2 0l.2.1a2 2 0 0 0 2.7-.7l.2-.4a2 2 0 0 0-.7-2.7l-.2-.1a2 2 0 0 1-1-1.8v-.5a2 2 0 0 1 1-1.7l.2-.1a2 2 0 0 0 .7-2.7l-.2-.4a2 2 0 0 0-2.7-.7l-.2.1a2 2 0 0 1-2 0l-.4-.3a2 2 0 0 1-1-1.7V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n users:\n '<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8\"/>',\n user: '<path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/>',\n key: '<path d=\"m21 2-9.6 9.6M15.5 7.5l3 3L22 7l-3-3\"/><circle cx=\"7.5\" cy=\"15.5\" r=\"5.5\"/>',\n bell: '<path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9M10.3 21a1.9 1.9 0 0 0 3.4 0\"/>',\n webhook:\n '<path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2M9 17l3.13-5.78c.53-.97.43-2.22-.26-3.07a4 4 0 1 1 6.58-4.2c.38.6.58 1.3.57 2M6 17a4 4 0 0 1 6-3.5\"/><path d=\"M12 17h6a2 2 0 1 1 0 4\"/>',\n code: '<path d=\"m16 18 6-6-6-6M8 6l-6 6 6 6\"/>',\n terminal: '<path d=\"m4 17 6-6-6-6M12 19h8\"/>',\n shield:\n '<path d=\"M20 13c0 5-3.5 7.5-7.7 8.9a1 1 0 0 1-.6 0C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.2-2.7a1.2 1.2 0 0 1 1.6 0C14.5 3.8 17 5 19 5a1 1 0 0 1 1 1z\"/>',\n search: '<circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>',\n sun: '<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M6.3 17.7l-1.4 1.4M19.1 4.9l-1.4 1.4\"/>',\n moon: '<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"/>',\n monitor: '<rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\"/><path d=\"M8 21h8M12 17v4\"/>',\n menu: '<path d=\"M4 6h16M4 12h16M4 18h16\"/>',\n \"more-horizontal\":\n '<circle cx=\"12\" cy=\"12\" r=\"1\"/><circle cx=\"19\" cy=\"12\" r=\"1\"/><circle cx=\"5\" cy=\"12\" r=\"1\"/>',\n \"log-out\": '<path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9\"/>',\n \"external-link\":\n '<path d=\"M15 3h6v6M10 14 21 3M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/>',\n copy: '<rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/>',\n \"check-circle\": '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m9 12 2 2 4-4\"/>',\n \"x-circle\": '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m15 9-6 6M9 9l6 6\"/>',\n \"alert-triangle\":\n '<path d=\"m21.7 18-8-14a2 2 0 0 0-3.5 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3M12 9v4M12 17h.01\"/>',\n info: '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4M12 8h.01\"/>',\n clock: '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 6v6l4 2\"/>',\n loader: '<path d=\"M21 12a9 9 0 1 1-6.2-8.6\"/>',\n \"message-square\": '<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>',\n columns: '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/><path d=\"M12 3v18\"/>',\n maximize:\n '<path d=\"M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M16 21h3a2 2 0 0 0 2-2v-3\"/>',\n \"zoom-in\": '<circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3M11 8v6M8 11h6\"/>',\n book: '<path d=\"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20\"/>',\n server:\n '<rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\"/><rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\"/><path d=\"M6 6h.01M6 18h.01\"/>',\n} as const;\n\n/** Every icon name available in the sprite. */\nexport type IconName = keyof typeof ICON_PATHS;\n"],"mappings":";;;;;;;;;AAKA,MAAa,aAAa;CACxB,OAAO;CACP,GAAG;CACH,MAAM;CACN,gBAAgB;CAChB,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,iBAAiB;CACjB,eAAe;CACf,QACE;CACF,QAAQ;CACR,OACE;CACF,cACE;CACF,cAAc;CACd,UAAU;CACV,UACE;CACF,KAAK;CACL,UACE;CACF,OACE;CACF,MAAM;CACN,KAAK;CACL,MAAM;CACN,SACE;CACF,MAAM;CACN,UAAU;CACV,QACE;CACF,QAAQ;CACR,KAAK;CACL,MAAM;CACN,SAAS;CACT,MAAM;CACN,mBACE;CACF,WAAW;CACX,iBACE;CACF,MAAM;CACN,gBAAgB;CAChB,YAAY;CACZ,kBACE;CACF,MAAM;CACN,OAAO;CACP,QAAQ;CACR,kBAAkB;CAClB,SAAS;CACT,UACE;CACF,WAAW;CACX,MAAM;CACN,QACE;AACJ"}
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { ICON_PATHS } from "./paths.mjs";
5
5
  import { createHash } from "node:crypto";
6
- //#region src/ui/icons/sprite.ts
6
+ // src/ui/icons/sprite.ts
7
7
  /** Assembled `<svg>` sprite of `<symbol id="i-<name>">` entries. */
8
8
  function buildSprite(paths = ICON_PATHS) {
9
9
  return `<svg xmlns="http://www.w3.org/2000/svg">${Object.entries(paths).toSorted(([a], [b]) => a.localeCompare(b)).map(([name, body]) => `<symbol id="i-${name}" viewBox="0 0 24 24">${body}</symbol>`).join("")}</svg>`;
@@ -20,7 +20,6 @@ const iconSpriteHref = `/assets/icons-${iconSpriteHash}.svg`;
20
20
  function iconHref(name) {
21
21
  return `${iconSpriteHref}#i-${name}`;
22
22
  }
23
- //#endregion
24
23
  export { buildSprite, contentHash, iconHref, iconSprite, iconSpriteHash, iconSpriteHref };
25
24
 
26
25
  //# sourceMappingURL=sprite.mjs.map
package/dist/ui/kbd.mjs CHANGED
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { css } from "./css.mjs";
5
5
  import { Fragment, jsx } from "hono/jsx/jsx-runtime";
6
- //#region src/ui/kbd.tsx
6
+ // src/ui/kbd.tsx
7
7
  const kbdKey = css`
8
8
  /* kbd */
9
9
  display: inline-flex;
@@ -27,7 +27,6 @@ const Kbd = ({ keys }) => {
27
27
  children: key
28
28
  }, String(index))) });
29
29
  };
30
- //#endregion
31
30
  export { Kbd };
32
31
 
33
32
  //# sourceMappingURL=kbd.mjs.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { css } from "./css.mjs";
5
5
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
6
- //#region src/ui/layout.tsx
6
+ // src/ui/layout.tsx
7
7
  const cardBase = css`
8
8
  /* card */
9
9
  background: var(--surface-card);
@@ -167,7 +167,6 @@ const SectionTitle = ({ level = 2, tone = "neutral", children }) => {
167
167
  children
168
168
  });
169
169
  };
170
- //#endregion
171
170
  export { Card, CardSection, PageHeader, SectionTitle };
172
171
 
173
172
  //# sourceMappingURL=layout.mjs.map
@@ -0,0 +1,81 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { css } from "./css.mjs";
5
+ import { Button } from "./buttons.mjs";
6
+ import { Meta } from "./feedback.mjs";
7
+ import { jsx, jsxs } from "hono/jsx/jsx-runtime";
8
+ // src/ui/preview-embed.tsx
9
+ /**
10
+ * Sandbox of the embedded story frame (ADR 0006, decision 9). Scripts only: no `allow-same-origin`,
11
+ * so a customer's Storybook never runs with the app's origin and its cookies, and no top navigation,
12
+ * forms or popups.
13
+ */
14
+ const PREVIEW_SANDBOX = "allow-scripts";
15
+ const previewHost = css`
16
+ /* preview-embed */
17
+ display: grid;
18
+ min-height: 12rem;
19
+ border: 1px solid var(--border-subtle);
20
+ border-radius: var(--radius);
21
+ background: var(--surface-muted);
22
+ overflow: hidden;
23
+ `;
24
+ const previewIdle = css`
25
+ /* preview-embed-idle */
26
+ display: grid;
27
+ gap: 0.5rem;
28
+ place-items: center;
29
+ align-content: center;
30
+ padding: 2rem 1rem;
31
+ text-align: center;
32
+ `;
33
+ const previewFrame = css`
34
+ /* preview-embed-frame */
35
+ display: block;
36
+ width: 100%;
37
+ height: 28rem;
38
+ border: 0;
39
+ background: var(--surface-card);
40
+ `;
41
+ /**
42
+ * A published story in a sandboxed frame that loads on click. The frame is inert markup (a
43
+ * `<template>`) until the visitor asks for it, so opening a page never runs the customer's
44
+ * Storybook; the shell script moves the frame in on click and, for a signed URL, re-points it
45
+ * to a fresh token before the current one expires.
46
+ */
47
+ const PreviewEmbed = ({ src, title, refresh }) => /* @__PURE__ */ jsxs("div", {
48
+ class: previewHost,
49
+ "data-preview-embed": true,
50
+ ...refresh ? {
51
+ "data-preview-refresh-url": refresh.url,
52
+ "data-preview-path": refresh.path,
53
+ "data-preview-refresh-seconds": String(refresh.seconds)
54
+ } : {},
55
+ children: [/* @__PURE__ */ jsxs("div", {
56
+ class: previewIdle,
57
+ "data-preview-idle": true,
58
+ children: [/* @__PURE__ */ jsx(Button, {
59
+ variant: "secondary",
60
+ size: "sm",
61
+ icon: "image",
62
+ "data-preview-load": true,
63
+ children: "Load preview"
64
+ }), /* @__PURE__ */ jsx(Meta, {
65
+ as: "span",
66
+ children: "Runs the published story in a sandboxed frame, only when you ask."
67
+ })]
68
+ }), /* @__PURE__ */ jsx("template", {
69
+ "data-preview-template": true,
70
+ children: /* @__PURE__ */ jsx("iframe", {
71
+ class: previewFrame,
72
+ src,
73
+ title,
74
+ sandbox: PREVIEW_SANDBOX,
75
+ referrerpolicy: "no-referrer"
76
+ })
77
+ })]
78
+ });
79
+ export { PREVIEW_SANDBOX, PreviewEmbed };
80
+
81
+ //# sourceMappingURL=preview-embed.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-embed.mjs","names":[],"sources":["../../src/ui/preview-embed.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\nimport { Button } from \"./buttons.tsx\";\nimport { css } from \"./css.ts\";\nimport { Meta } from \"./feedback.tsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\n/**\n * Sandbox of the embedded story frame (ADR 0006, decision 9). Scripts only: no `allow-same-origin`,\n * so a customer's Storybook never runs with the app's origin and its cookies, and no top navigation,\n * forms or popups.\n */\nexport const PREVIEW_SANDBOX = \"allow-scripts\";\n\nconst previewHost = css`\n /* preview-embed */\n display: grid;\n min-height: 12rem;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius);\n background: var(--surface-muted);\n overflow: hidden;\n`;\n\nconst previewIdle = css`\n /* preview-embed-idle */\n display: grid;\n gap: 0.5rem;\n place-items: center;\n align-content: center;\n padding: 2rem 1rem;\n text-align: center;\n`;\n\nconst previewFrame = css`\n /* preview-embed-frame */\n display: block;\n width: 100%;\n height: 28rem;\n border: 0;\n background: var(--surface-card);\n`;\n\n/**\n * A published story in a sandboxed frame that loads on click. The frame is inert markup (a\n * `<template>`) until the visitor asks for it, so opening a page never runs the customer's\n * Storybook; the shell script moves the frame in on click and, for a signed URL, re-points it\n * to a fresh token before the current one expires.\n */\nexport const PreviewEmbed: FC<{\n src: string;\n title: string;\n /** For a frame under a signed URL: where to ask for a fresh root, the path after it, how often. */\n refresh?: { url: string; path: string; seconds: number };\n}> = ({ src, title, refresh }) => (\n <div\n class={previewHost}\n data-preview-embed\n {...(refresh\n ? {\n \"data-preview-refresh-url\": refresh.url,\n \"data-preview-path\": refresh.path,\n \"data-preview-refresh-seconds\": String(refresh.seconds),\n }\n : {})}\n >\n <div class={previewIdle} data-preview-idle>\n <Button variant=\"secondary\" size=\"sm\" icon=\"image\" data-preview-load>\n Load preview\n </Button>\n <Meta as=\"span\">Runs the published story in a sandboxed frame, only when you ask.</Meta>\n </div>\n <template data-preview-template>\n <iframe\n class={previewFrame}\n src={src}\n title={title}\n sandbox={PREVIEW_SANDBOX}\n referrerpolicy=\"no-referrer\"\n />\n </template>\n </div>\n);\n"],"mappings":";;;;;;;;;;;;;AAYA,MAAa,kBAAkB;AAE/B,MAAM,cAAc,GAAG;;;;;;;;;AAUvB,MAAM,cAAc,GAAG;;;;;;;;;AAUvB,MAAM,eAAe,GAAG;;;;;;;;;;;;;;AAexB,MAAa,gBAKP,EAAE,KAAK,OAAO,cAClB,qBAAC,OAAD;CACE,OAAO;CACP,sBAAA;CACA,GAAK,UACD;EACE,4BAA4B,QAAQ;EACpC,qBAAqB,QAAQ;EAC7B,gCAAgC,OAAO,QAAQ,OAAO;CACxD,IACA,CAAC;CATP,UAAA,CAWE,qBAAC,OAAD;EAAK,OAAO;EAAa,qBAAA;EAAzB,UAAA,CACE,oBAAC,QAAD;GAAQ,SAAQ;GAAY,MAAK;GAAK,MAAK;GAAQ,qBAAA;GAAkB,UAAA;EAE7D,CAAA,GACR,oBAAC,MAAD;GAAM,IAAG;GAAO,UAAA;EAAuE,CAAA,CACpF;CACL,CAAA,GAAA,oBAAC,YAAD;EAAU,yBAAA;EACR,UAAA,oBAAC,UAAD;GACE,OAAO;GACF;GACE;GACP,SAAS;GACT,gBAAe;EAChB,CAAA;CACO,CAAA,CACP"}
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { css } from "./css.mjs";
5
5
  import { jsx } from "hono/jsx/jsx-runtime";
6
- //#region src/ui/progress.tsx
6
+ // src/ui/progress.tsx
7
7
  const track = css`
8
8
  /* progress */
9
9
  height: 6px;
@@ -38,7 +38,6 @@ const Progress = ({ value, max, label }) => {
38
38
  children: /* @__PURE__ */ jsx("span", { style: `width:${percent}%` })
39
39
  });
40
40
  };
41
- //#endregion
42
41
  export { Progress };
43
42
 
44
43
  //# sourceMappingURL=progress.mjs.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { css } from "./css.mjs";
5
5
  import { jsx } from "hono/jsx/jsx-runtime";
6
- //#region src/ui/segmented.tsx
6
+ // src/ui/segmented.tsx
7
7
  const segmentedRoot = css`
8
8
  /* segmented */
9
9
  display: inline-flex;
@@ -71,7 +71,6 @@ const Segmented = ({ items, label, ...rest }) => {
71
71
  }, item.value))
72
72
  });
73
73
  };
74
- //#endregion
75
74
  export { Segmented };
76
75
 
77
76
  //# sourceMappingURL=segmented.mjs.map
@@ -10,7 +10,7 @@ import { Dropdown, DropdownDivider, DropdownItem } from "../dropdown.mjs";
10
10
  import { csrfField } from "../csrf-field.mjs";
11
11
  import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
12
12
  import { safeImageUrl } from "@storyshelf/core/urls";
13
- //#region src/ui/shell/account.tsx
13
+ // src/ui/shell/account.tsx
14
14
  /** Styles for the account widgets that live in the sidebar footer. */
15
15
  const accountRoot = css`
16
16
  /* account */
@@ -155,7 +155,6 @@ const UserMenu = () => {
155
155
  })
156
156
  });
157
157
  };
158
- //#endregion
159
158
  export { ThemeMenu, UserMenu };
160
159
 
161
160
  //# sourceMappingURL=account.mjs.map
@@ -5,7 +5,7 @@ import { css } from "../css.mjs";
5
5
  import { Icon } from "../icons/icon.mjs";
6
6
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
7
7
  import { safeImageUrl } from "@storyshelf/core/urls";
8
- //#region src/ui/shell/bare.tsx
8
+ // src/ui/shell/bare.tsx
9
9
  /** Chrome-free page for signed-out flows: brand over a centered column. */
10
10
  const bareRoot = css`
11
11
  /* bare */
@@ -63,7 +63,6 @@ const BareShell = ({ name, logo, children }) => {
63
63
  })]
64
64
  });
65
65
  };
66
- //#endregion
67
66
  export { BareShell };
68
67
 
69
68
  //# sourceMappingURL=bare.mjs.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/ui/shell/boot-script.ts
4
+ // src/ui/shell/boot-script.ts
5
5
  /**
6
6
  * Runs in `<head>` before first paint so the saved theme and sidebar state
7
7
  * apply without a flash. Exposes cookie helpers to the client script.
@@ -40,7 +40,6 @@ function bootScript() {
40
40
  })();
41
41
  `.trim();
42
42
  }
43
- //#endregion
44
43
  export { bootScript };
45
44
 
46
45
  //# sourceMappingURL=boot-script.mjs.map