@invisibleloop/pulse 0.1.21

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 (344) hide show
  1. package/.claude/commands/build-page.md +59 -0
  2. package/.claude/commands/new-doc-page.md +45 -0
  3. package/.claude/commands/verify.md +52 -0
  4. package/.claude/pulse-checklist.md +111 -0
  5. package/.claude/settings.local.json +102 -0
  6. package/.github/workflows/ci.yml +22 -0
  7. package/.github/workflows/publish.yml +41 -0
  8. package/.pulse/load-reports/home/1773432711417.json +22 -0
  9. package/CLAUDE.md +383 -0
  10. package/README.md +95 -0
  11. package/docs/.claude/pulse-checklist.md +111 -0
  12. package/docs/public/.pulse-ui-version +1 -0
  13. package/docs/public/dist/accessibility.boot-5DVTARJU.js +115 -0
  14. package/docs/public/dist/actions.boot-P66HKQEM.js +164 -0
  15. package/docs/public/dist/auth.boot-IMAJAUPH.js +140 -0
  16. package/docs/public/dist/caching.boot-DVR6KDE7.js +53 -0
  17. package/docs/public/dist/components--accordion.boot-3HVKMNWC.js +11 -0
  18. package/docs/public/dist/components--alert.boot-GCEXOZAC.js +6 -0
  19. package/docs/public/dist/components--app-badge.boot-DVT3GCHJ.js +6 -0
  20. package/docs/public/dist/components--avatar.boot-PSW24EVA.js +5 -0
  21. package/docs/public/dist/components--badge.boot-TYDY2RMK.js +7 -0
  22. package/docs/public/dist/components--banner.boot-EI5PZSZK.js +7 -0
  23. package/docs/public/dist/components--breadcrumbs.boot-SMA2E2GO.js +34 -0
  24. package/docs/public/dist/components--button.boot-J54BQM2E.js +23 -0
  25. package/docs/public/dist/components--card.boot-PZGNDIB6.js +138 -0
  26. package/docs/public/dist/components--carousel.boot-TP6LPFZZ.js +12 -0
  27. package/docs/public/dist/components--charts.boot-2EOYQWKL.js +108 -0
  28. package/docs/public/dist/components--checkbox.boot-DS5BSL6T.js +54 -0
  29. package/docs/public/dist/components--cluster.boot-HHVIBBJG.js +9 -0
  30. package/docs/public/dist/components--code-window.boot-2GR2DV33.js +20 -0
  31. package/docs/public/dist/components--container.boot-7LOOGK2K.js +5 -0
  32. package/docs/public/dist/components--cta.boot-FSNZ5YRT.js +11 -0
  33. package/docs/public/dist/components--divider.boot-3NI2C3QG.js +6 -0
  34. package/docs/public/dist/components--empty.boot-YX2UR3PV.js +7 -0
  35. package/docs/public/dist/components--feature.boot-MUD7NSUO.js +13 -0
  36. package/docs/public/dist/components--fieldset.boot-J7BYHMKF.js +19 -0
  37. package/docs/public/dist/components--fileupload.boot-NIKVTTPD.js +52 -0
  38. package/docs/public/dist/components--footer.boot-EYUK5FRG.js +14 -0
  39. package/docs/public/dist/components--grid.boot-URDQVDDR.js +59 -0
  40. package/docs/public/dist/components--heading.boot-BPQKU43E.js +44 -0
  41. package/docs/public/dist/components--hero.boot-4RAPRGAB.js +17 -0
  42. package/docs/public/dist/components--icons.boot-ZITNU5JP.js +68 -0
  43. package/docs/public/dist/components--image.boot-XEEGHQZF.js +19 -0
  44. package/docs/public/dist/components--input.boot-SGASZG5K.js +7 -0
  45. package/docs/public/dist/components--list.boot-W3XC5MHD.js +55 -0
  46. package/docs/public/dist/components--media.boot-5VFIETZO.js +13 -0
  47. package/docs/public/dist/components--modal.boot-RZUYXBN2.js +47 -0
  48. package/docs/public/dist/components--nav.boot-ODBOHU7O.js +33 -0
  49. package/docs/public/dist/components--pricing.boot-4AQ4ZVBY.js +21 -0
  50. package/docs/public/dist/components--progress.boot-GHAGYZOK.js +30 -0
  51. package/docs/public/dist/components--prose.boot-QANJL6JI.js +67 -0
  52. package/docs/public/dist/components--pullquote.boot-Q2WMNAZU.js +22 -0
  53. package/docs/public/dist/components--radio.boot-TJRDQ2OL.js +75 -0
  54. package/docs/public/dist/components--rating.boot-QBAN6DEL.js +38 -0
  55. package/docs/public/dist/components--search.boot-PXH5O5AG.js +17 -0
  56. package/docs/public/dist/components--section.boot-AQGIYHWW.js +12 -0
  57. package/docs/public/dist/components--segmented.boot-BEVTKEJO.js +33 -0
  58. package/docs/public/dist/components--select.boot-47X5RHOC.js +10 -0
  59. package/docs/public/dist/components--slider.boot-PSRRX7XL.js +47 -0
  60. package/docs/public/dist/components--spinner.boot-MZ5MO2OH.js +22 -0
  61. package/docs/public/dist/components--stack.boot-DI4NJXBF.js +9 -0
  62. package/docs/public/dist/components--stat.boot-QMFUWBQT.js +9 -0
  63. package/docs/public/dist/components--stepper.boot-34PP2NEV.js +22 -0
  64. package/docs/public/dist/components--table.boot-FCQGSFIQ.js +11 -0
  65. package/docs/public/dist/components--testimonial.boot-DWQPDKYG.js +11 -0
  66. package/docs/public/dist/components--textarea.boot-QVXLBOJ5.js +4 -0
  67. package/docs/public/dist/components--timeline.boot-26LN52P2.js +95 -0
  68. package/docs/public/dist/components--toggle.boot-IQQEI76S.js +29 -0
  69. package/docs/public/dist/components--tooltip.boot-LGHCO6NN.js +9 -0
  70. package/docs/public/dist/components.boot-SE6PQ4P7.js +103 -0
  71. package/docs/public/dist/config.boot-DTRRWUE6.js +126 -0
  72. package/docs/public/dist/constraints.boot-DUHDZBMC.js +71 -0
  73. package/docs/public/dist/deploy.boot-SLAD3NI2.js +163 -0
  74. package/docs/public/dist/docs-8e3d4b5c.css +1 -0
  75. package/docs/public/dist/extending.boot-UA3CN243.js +159 -0
  76. package/docs/public/dist/faq.boot-6EQAWLQR.js +43 -0
  77. package/docs/public/dist/getting-started.boot-TDKIFL5U.js +86 -0
  78. package/docs/public/dist/guard.boot-AUHAWTG4.js +80 -0
  79. package/docs/public/dist/home.boot-BVQXRH32.js +383 -0
  80. package/docs/public/dist/how-it-works.boot-LTWAKWKW.js +104 -0
  81. package/docs/public/dist/hydration.boot-JRM6IPJL.js +78 -0
  82. package/docs/public/dist/images.boot-M6ZVKTZS.js +80 -0
  83. package/docs/public/dist/manifest.json +94 -0
  84. package/docs/public/dist/meta.boot-7NXGPHR4.js +79 -0
  85. package/docs/public/dist/mutations.boot-F6F43UDX.js +79 -0
  86. package/docs/public/dist/navigation.boot-AOXWS3ZF.js +57 -0
  87. package/docs/public/dist/performance.boot-C3UPCOBK.js +98 -0
  88. package/docs/public/dist/persist.boot-WT32PQOQ.js +61 -0
  89. package/docs/public/dist/project-structure.boot-FB3LRVJ4.js +63 -0
  90. package/docs/public/dist/prompt-examples.boot-YKR4VDK4.js +31 -0
  91. package/docs/public/dist/pulse-ui-81a85c03.css +1 -0
  92. package/docs/public/dist/raw-responses.boot-M4KA5YXL.js +104 -0
  93. package/docs/public/dist/routing.boot-FNX5FDGH.js +70 -0
  94. package/docs/public/dist/runtime-B73WLANC.js +1 -0
  95. package/docs/public/dist/runtime-KO4BHUQ3.js +49 -0
  96. package/docs/public/dist/runtime-L2HNXIHW.js +59 -0
  97. package/docs/public/dist/runtime-QFURDKA2.js +5 -0
  98. package/docs/public/dist/runtime-UVPXO4IR.js +375 -0
  99. package/docs/public/dist/runtime-VMJA3Z4N.js +10 -0
  100. package/docs/public/dist/runtime-ZJ4FXT5O.js +11 -0
  101. package/docs/public/dist/server-api.boot-K7X3LCFB.js +219 -0
  102. package/docs/public/dist/server-data.boot-Y7HQYC4R.js +157 -0
  103. package/docs/public/dist/slash-commands.boot-V2UV7OW2.js +26 -0
  104. package/docs/public/dist/spec.boot-2WU7ZHCV.js +159 -0
  105. package/docs/public/dist/state.boot-B24GUE3R.js +73 -0
  106. package/docs/public/dist/store.boot-TLIB4XHH.js +150 -0
  107. package/docs/public/dist/streaming.boot-W2DZSMW4.js +80 -0
  108. package/docs/public/dist/stripe.boot-QN3C2GEL.js +164 -0
  109. package/docs/public/dist/supabase.boot-BG4XXLZE.js +303 -0
  110. package/docs/public/dist/testing.boot-6U4WKMTE.js +130 -0
  111. package/docs/public/dist/validation.boot-PQHYGW5B.js +100 -0
  112. package/docs/public/docs.css +2020 -0
  113. package/docs/public/menu.js +83 -0
  114. package/docs/public/pulse-ui.css +2739 -0
  115. package/docs/public/pulse-ui.js +236 -0
  116. package/docs/server.js +192 -0
  117. package/docs/src/lib/component-page.js +47 -0
  118. package/docs/src/lib/highlight.js +255 -0
  119. package/docs/src/lib/layout.js +131 -0
  120. package/docs/src/lib/metrics-store.js +6 -0
  121. package/docs/src/lib/nav.js +159 -0
  122. package/docs/src/lib/stats.js +81 -0
  123. package/docs/src/pages/accessibility.js +157 -0
  124. package/docs/src/pages/actions.js +191 -0
  125. package/docs/src/pages/auth.js +177 -0
  126. package/docs/src/pages/caching.js +95 -0
  127. package/docs/src/pages/components/accordion.js +48 -0
  128. package/docs/src/pages/components/alert.js +35 -0
  129. package/docs/src/pages/components/app-badge.js +41 -0
  130. package/docs/src/pages/components/avatar.js +35 -0
  131. package/docs/src/pages/components/badge.js +36 -0
  132. package/docs/src/pages/components/banner.js +45 -0
  133. package/docs/src/pages/components/breadcrumbs.js +94 -0
  134. package/docs/src/pages/components/button.js +84 -0
  135. package/docs/src/pages/components/card.js +225 -0
  136. package/docs/src/pages/components/carousel.js +72 -0
  137. package/docs/src/pages/components/charts.js +278 -0
  138. package/docs/src/pages/components/checkbox.js +129 -0
  139. package/docs/src/pages/components/cluster.js +47 -0
  140. package/docs/src/pages/components/code-window.js +57 -0
  141. package/docs/src/pages/components/container.js +40 -0
  142. package/docs/src/pages/components/cta.js +53 -0
  143. package/docs/src/pages/components/divider.js +37 -0
  144. package/docs/src/pages/components/empty.js +36 -0
  145. package/docs/src/pages/components/feature.js +60 -0
  146. package/docs/src/pages/components/fieldset.js +65 -0
  147. package/docs/src/pages/components/fileupload.js +127 -0
  148. package/docs/src/pages/components/footer.js +58 -0
  149. package/docs/src/pages/components/grid.js +165 -0
  150. package/docs/src/pages/components/heading.js +107 -0
  151. package/docs/src/pages/components/hero.js +65 -0
  152. package/docs/src/pages/components/icons.js +285 -0
  153. package/docs/src/pages/components/image.js +71 -0
  154. package/docs/src/pages/components/input.js +51 -0
  155. package/docs/src/pages/components/list.js +112 -0
  156. package/docs/src/pages/components/media.js +51 -0
  157. package/docs/src/pages/components/modal.js +111 -0
  158. package/docs/src/pages/components/nav.js +86 -0
  159. package/docs/src/pages/components/pricing.js +68 -0
  160. package/docs/src/pages/components/progress.js +102 -0
  161. package/docs/src/pages/components/prose.js +111 -0
  162. package/docs/src/pages/components/pullquote.js +71 -0
  163. package/docs/src/pages/components/radio.js +194 -0
  164. package/docs/src/pages/components/rating.js +106 -0
  165. package/docs/src/pages/components/search.js +61 -0
  166. package/docs/src/pages/components/section.js +59 -0
  167. package/docs/src/pages/components/segmented.js +121 -0
  168. package/docs/src/pages/components/select.js +45 -0
  169. package/docs/src/pages/components/slider.js +114 -0
  170. package/docs/src/pages/components/spinner.js +73 -0
  171. package/docs/src/pages/components/stack.js +48 -0
  172. package/docs/src/pages/components/stat.js +55 -0
  173. package/docs/src/pages/components/stepper.js +66 -0
  174. package/docs/src/pages/components/table.js +45 -0
  175. package/docs/src/pages/components/testimonial.js +49 -0
  176. package/docs/src/pages/components/textarea.js +31 -0
  177. package/docs/src/pages/components/timeline.js +227 -0
  178. package/docs/src/pages/components/toggle.js +84 -0
  179. package/docs/src/pages/components/tooltip.js +48 -0
  180. package/docs/src/pages/components.js +204 -0
  181. package/docs/src/pages/config.js +193 -0
  182. package/docs/src/pages/constraints.js +99 -0
  183. package/docs/src/pages/deploy.js +233 -0
  184. package/docs/src/pages/extending.js +198 -0
  185. package/docs/src/pages/faq.js +96 -0
  186. package/docs/src/pages/getting-started.js +106 -0
  187. package/docs/src/pages/guard.js +121 -0
  188. package/docs/src/pages/home.js +401 -0
  189. package/docs/src/pages/how-it-works.js +183 -0
  190. package/docs/src/pages/hydration.js +98 -0
  191. package/docs/src/pages/images.js +121 -0
  192. package/docs/src/pages/meta.js +120 -0
  193. package/docs/src/pages/mutations.js +106 -0
  194. package/docs/src/pages/navigation.js +85 -0
  195. package/docs/src/pages/performance.js +157 -0
  196. package/docs/src/pages/persist.js +88 -0
  197. package/docs/src/pages/project-structure.js +90 -0
  198. package/docs/src/pages/prompt-examples.js +186 -0
  199. package/docs/src/pages/raw-responses.js +124 -0
  200. package/docs/src/pages/routing.js +99 -0
  201. package/docs/src/pages/server-api.js +281 -0
  202. package/docs/src/pages/server-data.js +185 -0
  203. package/docs/src/pages/slash-commands.js +55 -0
  204. package/docs/src/pages/spec.js +207 -0
  205. package/docs/src/pages/state.js +101 -0
  206. package/docs/src/pages/store.js +181 -0
  207. package/docs/src/pages/streaming.js +108 -0
  208. package/docs/src/pages/stripe.js +193 -0
  209. package/docs/src/pages/supabase.js +323 -0
  210. package/docs/src/pages/testing.js +198 -0
  211. package/docs/src/pages/validation.js +138 -0
  212. package/examples/contact.js +166 -0
  213. package/examples/counter.js +94 -0
  214. package/examples/dev.server.js +91 -0
  215. package/examples/examples.test.js +394 -0
  216. package/examples/pricing.js +244 -0
  217. package/examples/products.js +191 -0
  218. package/examples/quiz.js +208 -0
  219. package/examples/shared.js +78 -0
  220. package/examples/todos.js +162 -0
  221. package/package.json +75 -0
  222. package/public/.pulse-ui-version +1 -0
  223. package/public/chippy-bird.css +246 -0
  224. package/public/examples/contact.css +119 -0
  225. package/public/examples/counter.css +79 -0
  226. package/public/examples/pricing.css +132 -0
  227. package/public/examples/products.css +100 -0
  228. package/public/examples/quiz.css +200 -0
  229. package/public/examples/todos.css +137 -0
  230. package/public/favicon.ico +0 -0
  231. package/public/log-dashboard.css +383 -0
  232. package/public/pulse-ui.css +2740 -0
  233. package/public/pulse-ui.js +236 -0
  234. package/public/pulse.css +149 -0
  235. package/scripts/build.js +411 -0
  236. package/src/agent/checklist.md +111 -0
  237. package/src/agent/coverage-check.js +66 -0
  238. package/src/agent/guide-components.md +274 -0
  239. package/src/agent/guide-examples.md +54 -0
  240. package/src/agent/guide-routing.md +36 -0
  241. package/src/agent/guide-server.md +258 -0
  242. package/src/agent/guide-spec.md +103 -0
  243. package/src/agent/guide-styles.md +191 -0
  244. package/src/agent/guide.md +979 -0
  245. package/src/agent/identity.md +106 -0
  246. package/src/agent/workflow.md +108 -0
  247. package/src/cli/cli.test.js +82 -0
  248. package/src/cli/dev.js +195 -0
  249. package/src/cli/discover.js +113 -0
  250. package/src/cli/index.js +361 -0
  251. package/src/cli/load-report.js +91 -0
  252. package/src/cli/load-runner.js +121 -0
  253. package/src/cli/report-server.js +723 -0
  254. package/src/cli/report.js +116 -0
  255. package/src/cli/scaffold.archive.js +1371 -0
  256. package/src/cli/scaffold.js +349 -0
  257. package/src/cli/start.js +74 -0
  258. package/src/html.js +19 -0
  259. package/src/mcp/server.js +884 -0
  260. package/src/mcp/validate-worker.js +110 -0
  261. package/src/runtime/image.js +74 -0
  262. package/src/runtime/image.test.js +111 -0
  263. package/src/runtime/index.js +621 -0
  264. package/src/runtime/navigate.js +146 -0
  265. package/src/runtime/runtime.test.js +773 -0
  266. package/src/runtime/ssr.js +464 -0
  267. package/src/runtime/ssr.test.js +421 -0
  268. package/src/runtime/store.js +92 -0
  269. package/src/runtime/toast.js +163 -0
  270. package/src/server/index.js +1386 -0
  271. package/src/server/server.test.js +1248 -0
  272. package/src/spec/schema.js +428 -0
  273. package/src/spec/schema.test.js +291 -0
  274. package/src/store/index.js +102 -0
  275. package/src/store/store.test.js +210 -0
  276. package/src/testing/html.js +283 -0
  277. package/src/testing/index.js +249 -0
  278. package/src/testing/testing.test.js +450 -0
  279. package/src/ui/accordion.js +28 -0
  280. package/src/ui/alert.js +43 -0
  281. package/src/ui/app-badge.js +48 -0
  282. package/src/ui/avatar.js +47 -0
  283. package/src/ui/badge.js +24 -0
  284. package/src/ui/banner.js +26 -0
  285. package/src/ui/breadcrumbs.js +38 -0
  286. package/src/ui/button.js +66 -0
  287. package/src/ui/card.js +34 -0
  288. package/src/ui/carousel.js +59 -0
  289. package/src/ui/charts.js +321 -0
  290. package/src/ui/checkbox.js +65 -0
  291. package/src/ui/cluster.js +44 -0
  292. package/src/ui/code-window.js +39 -0
  293. package/src/ui/container.js +24 -0
  294. package/src/ui/cta.js +37 -0
  295. package/src/ui/divider.js +29 -0
  296. package/src/ui/empty.js +33 -0
  297. package/src/ui/feature.js +33 -0
  298. package/src/ui/fieldset.js +37 -0
  299. package/src/ui/fileupload.js +89 -0
  300. package/src/ui/footer.js +38 -0
  301. package/src/ui/grid.js +36 -0
  302. package/src/ui/heading.js +45 -0
  303. package/src/ui/hero.js +37 -0
  304. package/src/ui/icons.js +161 -0
  305. package/src/ui/index.js +89 -0
  306. package/src/ui/input.js +74 -0
  307. package/src/ui/list.js +36 -0
  308. package/src/ui/media.js +44 -0
  309. package/src/ui/modal.js +80 -0
  310. package/src/ui/nav.js +61 -0
  311. package/src/ui/pricing.js +56 -0
  312. package/src/ui/progress.js +62 -0
  313. package/src/ui/prose.js +29 -0
  314. package/src/ui/pullquote.js +34 -0
  315. package/src/ui/radio.js +102 -0
  316. package/src/ui/rating.js +93 -0
  317. package/src/ui/search.js +77 -0
  318. package/src/ui/section.js +69 -0
  319. package/src/ui/segmented.js +50 -0
  320. package/src/ui/select.js +77 -0
  321. package/src/ui/slider.js +84 -0
  322. package/src/ui/spinner.js +34 -0
  323. package/src/ui/stack.js +36 -0
  324. package/src/ui/stat.js +52 -0
  325. package/src/ui/stepper.js +46 -0
  326. package/src/ui/switch.js +57 -0
  327. package/src/ui/table.js +45 -0
  328. package/src/ui/testimonial.js +48 -0
  329. package/src/ui/textarea.js +72 -0
  330. package/src/ui/timeline.js +72 -0
  331. package/src/ui/tooltip.js +28 -0
  332. package/src/ui/ui.test.js +1241 -0
  333. package/src/ui/uiimage.js +65 -0
  334. package/tsconfig.json +13 -0
  335. package/types/html.d.ts +17 -0
  336. package/types/image.d.ts +70 -0
  337. package/types/index.d.ts +7 -0
  338. package/types/navigate.d.ts +38 -0
  339. package/types/runtime.d.ts +63 -0
  340. package/types/schema.d.ts +243 -0
  341. package/types/server.d.ts +145 -0
  342. package/types/ssr.d.ts +110 -0
  343. package/types/testing.d.ts +154 -0
  344. package/types/ui.d.ts +704 -0
@@ -0,0 +1,72 @@
1
+ import { renderComponentPage, demo } from '../../lib/component-page.js'
2
+ import { prevNext } from '../../lib/nav.js'
3
+ import { table } from '../../lib/layout.js'
4
+ import { carousel } from '../../../../src/ui/index.js'
5
+
6
+ const { prev, next } = prevNext('/components/carousel')
7
+
8
+ function slide(bg, label) {
9
+ return `<div style="height:220px;display:flex;align-items:center;justify-content:center;background:${bg};border-radius:10px;font-size:1.1rem;font-weight:700;color:var(--ui-text)">${label}</div>`
10
+ }
11
+
12
+ export default {
13
+ route: '/components/carousel',
14
+ meta: {
15
+ title: 'Carousel — Pulse Docs',
16
+ description: 'Carousel / slider component for Pulse UI.',
17
+ styles: ['/pulse-ui.css', '/docs.css'],
18
+ },
19
+ state: {},
20
+ view: () => renderComponentPage({
21
+ currentHref: '/components/carousel',
22
+ prev,
23
+ next,
24
+ name: 'carousel',
25
+ description: 'CSS scroll-snap carousel with optional prev/next arrows and dot navigation. Touch / swipe friendly out of the box. Requires <code>pulse-ui.js</code> for button and dot interactivity.',
26
+ content: `
27
+ ${demo(
28
+ carousel({
29
+ slides: [
30
+ slide('var(--ui-surface-2)', 'Slide 1'),
31
+ slide('var(--ui-surface)', 'Slide 2'),
32
+ slide('var(--ui-surface-2)', 'Slide 3'),
33
+ ],
34
+ }),
35
+ `carousel({
36
+ slides: [
37
+ \`<div class="slide">Slide 1</div>\`,
38
+ \`<div class="slide">Slide 2</div>\`,
39
+ \`<div class="slide">Slide 3</div>\`,
40
+ ],
41
+ })`
42
+ )}
43
+
44
+ <h3 class="doc-h3" id="arrows-dots"><a href="#arrows-dots" class="heading-anchor">Arrows and dots</a></h3>
45
+ ${demo(
46
+ carousel({
47
+ arrows: true,
48
+ dots: false,
49
+ slides: [
50
+ slide('var(--ui-surface-2)', 'Arrows only — Slide 1'),
51
+ slide('var(--ui-surface)', 'Arrows only — Slide 2'),
52
+ ],
53
+ }),
54
+ `carousel({
55
+ slides: [ /* ... */ ],
56
+ arrows: true,
57
+ dots: false, // hide dot navigation
58
+ })`
59
+ )}
60
+
61
+ ${table(
62
+ ['Prop', 'Type', 'Default', ''],
63
+ [
64
+ ['<code>slides</code>', 'string[] (HTML)', '[]', 'Array of raw HTML strings — one per slide'],
65
+ ['<code>arrows</code>', 'boolean', '<code>true</code>', 'Show prev/next arrow buttons'],
66
+ ['<code>dots</code>', 'boolean', '<code>true</code>', 'Show dot navigation (hidden when only one slide)'],
67
+ ['<code>class</code>', 'string', '—', ''],
68
+ ]
69
+ )}
70
+ `,
71
+ }),
72
+ }
@@ -0,0 +1,278 @@
1
+ import { renderComponentPage, demo } from '../../lib/component-page.js'
2
+ import { prevNext } from '../../lib/nav.js'
3
+ import { table } from '../../lib/layout.js'
4
+ import { barChart, lineChart, donutChart, sparkline, stat, card, grid } from '../../../../src/ui/index.js'
5
+
6
+ const { prev, next } = prevNext('/components/charts')
7
+
8
+ // Shared sample data
9
+ const monthly = [
10
+ { label: 'Jan', value: 42 },
11
+ { label: 'Feb', value: 78 },
12
+ { label: 'Mar', value: 55 },
13
+ { label: 'Apr', value: 91 },
14
+ { label: 'May', value: 63 },
15
+ { label: 'Jun', value: 84 },
16
+ ]
17
+
18
+ const traffic = [
19
+ { label: 'Mon', value: 1200 },
20
+ { label: 'Tue', value: 1850 },
21
+ { label: 'Wed', value: 1540 },
22
+ { label: 'Thu', value: 2100 },
23
+ { label: 'Fri', value: 1760 },
24
+ { label: 'Sat', value: 890 },
25
+ { label: 'Sun', value: 720 },
26
+ ]
27
+
28
+ export default {
29
+ route: '/components/charts',
30
+ meta: {
31
+ title: 'Charts — Pulse Docs',
32
+ description: 'Server-rendered SVG charts for Pulse UI.',
33
+ styles: ['/pulse-ui.css', '/docs.css'],
34
+ },
35
+ state: {},
36
+ view: () => renderComponentPage({
37
+ currentHref: '/components/charts',
38
+ prev,
39
+ next,
40
+ name: 'charts',
41
+ description: 'Server-rendered SVG charts — no JavaScript, no external library. Pure functions that return SVG strings, composable with any layout component. All colours use design tokens and respond to light/dark theme.',
42
+ content: `
43
+
44
+ <h2 class="doc-h2" id="bar">Bar chart</h2>
45
+ <p>Vertical bars with optional grid, value labels, and a zero baseline. All colour variants available.</p>
46
+ ${demo(
47
+ barChart({ data: monthly, color: 'accent' }),
48
+ `barChart({
49
+ data: [
50
+ { label: 'Jan', value: 42 },
51
+ { label: 'Feb', value: 78 },
52
+ { label: 'Mar', value: 55 },
53
+ { label: 'Apr', value: 91 },
54
+ { label: 'May', value: 63 },
55
+ { label: 'Jun', value: 84 },
56
+ ],
57
+ color: 'accent',
58
+ })`
59
+ )}
60
+
61
+ <h3 class="doc-h3">With value labels</h3>
62
+ ${demo(
63
+ barChart({ data: monthly, color: 'success', showValues: true }),
64
+ `barChart({ data, color: 'success', showValues: true })`
65
+ )}
66
+
67
+ <h3 class="doc-h3">Large dataset with tight gap</h3>
68
+ ${demo(
69
+ barChart({ data: traffic, color: 'blue', gap: 0.15 }),
70
+ `barChart({ data: traffic, color: 'blue', gap: 0.15 })`
71
+ )}
72
+
73
+ <h3 class="doc-h3">Negative values</h3>
74
+ ${demo(
75
+ barChart({
76
+ data: [
77
+ { label: 'Q1', value: 24 },
78
+ { label: 'Q2', value: -8 },
79
+ { label: 'Q3', value: 41 },
80
+ { label: 'Q4', value: -15 },
81
+ ],
82
+ color: 'warning',
83
+ showValues: true,
84
+ }),
85
+ `barChart({
86
+ data: [
87
+ { label: 'Q1', value: 24 },
88
+ { label: 'Q2', value: -8 },
89
+ { label: 'Q3', value: 41 },
90
+ { label: 'Q4', value: -15 },
91
+ ],
92
+ color: 'warning',
93
+ showValues: true,
94
+ })`
95
+ )}
96
+
97
+ <h2 class="doc-h2" id="line">Line chart</h2>
98
+ <p>Connected data points with optional dots, area fill, and grid lines.</p>
99
+ ${demo(
100
+ lineChart({ data: monthly, color: 'accent' }),
101
+ `lineChart({
102
+ data: [
103
+ { label: 'Jan', value: 42 },
104
+ ...
105
+ ],
106
+ color: 'accent',
107
+ })`
108
+ )}
109
+
110
+ <h3 class="doc-h3">With area fill</h3>
111
+ ${demo(
112
+ lineChart({ data: monthly, color: 'accent', area: true }),
113
+ `lineChart({ data, color: 'accent', area: true })`
114
+ )}
115
+
116
+ <h3 class="doc-h3">No dots, area fill, success colour</h3>
117
+ ${demo(
118
+ lineChart({ data: traffic, color: 'success', area: true, showDots: false }),
119
+ `lineChart({ data, color: 'success', area: true, showDots: false })`
120
+ )}
121
+
122
+ <h2 class="doc-h2" id="donut">Donut chart</h2>
123
+ <p>Ring chart with multiple segments. Each item can override its colour. Pass <code>label</code> and <code>sublabel</code> for a centred annotation.</p>
124
+ ${demo(
125
+ `<div style="display:flex;justify-content:center">` +
126
+ donutChart({
127
+ label: '73%',
128
+ sublabel: 'satisfied',
129
+ data: [
130
+ { label: 'Satisfied', value: 73, color: 'success' },
131
+ { label: 'Neutral', value: 18, color: 'muted' },
132
+ { label: 'Unsatisfied', value: 9, color: 'error' },
133
+ ],
134
+ }) + `</div>`,
135
+ `donutChart({
136
+ label: '73%',
137
+ sublabel: 'satisfied',
138
+ data: [
139
+ { label: 'Satisfied', value: 73, color: 'success' },
140
+ { label: 'Neutral', value: 18, color: 'muted' },
141
+ { label: 'Unsatisfied', value: 9, color: 'error' },
142
+ ],
143
+ })`
144
+ )}
145
+
146
+ <h3 class="doc-h3">Thinner ring</h3>
147
+ ${demo(
148
+ `<div style="display:flex;justify-content:center">` +
149
+ donutChart({
150
+ size: 180,
151
+ thickness: 22,
152
+ label: '4',
153
+ sublabel: 'segments',
154
+ data: [
155
+ { label: 'A', value: 40, color: 'accent' },
156
+ { label: 'B', value: 30, color: 'blue' },
157
+ { label: 'C', value: 20, color: 'success' },
158
+ { label: 'D', value: 10, color: 'warning' },
159
+ ],
160
+ }) + `</div>`,
161
+ `donutChart({
162
+ size: 180, thickness: 22,
163
+ label: '4', sublabel: 'segments',
164
+ data: [
165
+ { label: 'A', value: 40, color: 'accent' },
166
+ { label: 'B', value: 30, color: 'blue' },
167
+ { label: 'C', value: 20, color: 'success' },
168
+ { label: 'D', value: 10, color: 'warning' },
169
+ ],
170
+ })`
171
+ )}
172
+
173
+ <h2 class="doc-h2" id="sparkline">Sparkline</h2>
174
+ <p>Minimal inline trend line — pass a plain array of numbers. Designed to sit alongside <code>stat()</code> tiles or inside table cells.</p>
175
+ ${demo(
176
+ `<div style="display:flex;gap:.75rem;align-items:center;flex-wrap:wrap">` +
177
+ sparkline({ data: [12,18,14,22,19,28,24,31], color: 'accent', area: true }) +
178
+ sparkline({ data: [31,24,28,19,22,14,18,12], color: 'error', area: true }) +
179
+ sparkline({ data: [12,18,14,22,19,28,24,31], color: 'success', area: false }) +
180
+ `</div>`,
181
+ `sparkline({ data: [12,18,14,22,19,28,24,31], color: 'accent', area: true })
182
+ sparkline({ data: [31,24,28,19,22,14,18,12], color: 'error', area: true })`
183
+ )}
184
+
185
+ <h2 class="doc-h2" id="composition">Composition</h2>
186
+ <p>Charts compose with <code>card()</code>, <code>stat()</code>, <code>grid()</code> — drop any chart into any content slot.</p>
187
+ ${demo(
188
+ grid({
189
+ cols: 2,
190
+ gap: 'md',
191
+ content:
192
+ card({
193
+ title: 'Monthly signups',
194
+ content: barChart({ data: monthly, color: 'accent', height: 180 }),
195
+ }) +
196
+ card({
197
+ title: 'Daily traffic',
198
+ content: lineChart({ data: traffic, color: 'blue', area: true, height: 180 }),
199
+ }),
200
+ }),
201
+ `grid({
202
+ cols: 2,
203
+ content:
204
+ card({ title: 'Monthly signups', content: barChart({ data, height: 180 }) }) +
205
+ card({ title: 'Daily traffic', content: lineChart({ data, color: 'blue', area: true, height: 180 }) }),
206
+ })`
207
+ )}
208
+
209
+ <h3 class="doc-h3">Sparkline in stat tiles</h3>
210
+ ${demo(
211
+ grid({
212
+ cols: 3,
213
+ gap: 'md',
214
+ content:
215
+ card({ content: stat({ label: 'Revenue', value: '$18.2k', change: '+12%', trend: 'up' }) + `<div style="margin-top:.75rem">${sparkline({ data: [8,11,9,14,12,16,15,18], width: '100%', color: 'success', area: true })}</div>` }) +
216
+ card({ content: stat({ label: 'Users', value: '4,821', change: '+8.4%', trend: 'up' }) + `<div style="margin-top:.75rem">${sparkline({ data: [22,28,24,31,27,34,30,38], width: '100%', color: 'accent', area: true })}</div>` }) +
217
+ card({ content: stat({ label: 'Churn', value: '2.1%', change: '−0.3%', trend: 'down' }) + `<div style="margin-top:.75rem">${sparkline({ data: [8,6,7,5,6,4,5,3], width: '100%', color: 'error', area: true })}</div>` }),
218
+ }),
219
+ `card({
220
+ content: stat({ label: 'Revenue', value: '$18.2k', change: '+12%', trend: 'up' }) +
221
+ \`<div style="margin-top:.75rem">\${sparkline({ data, color: 'success', area: true })}</div>\`,
222
+ })`
223
+ )}
224
+
225
+ <h2 class="doc-h2" id="props">Props</h2>
226
+
227
+ <h3 class="doc-h3">barChart()</h3>
228
+ ${table(
229
+ ['Prop', 'Type', 'Default', ''],
230
+ [
231
+ ['<code>data</code>', 'array', '—', '<code>{ label, value }[]</code>'],
232
+ ['<code>height</code>', 'number', '220', 'SVG height in px'],
233
+ ['<code>color</code>', 'string', "'accent'", 'accent · success · warning · error · blue · muted'],
234
+ ['<code>showValues</code>', 'boolean', 'false', 'Value labels above each bar'],
235
+ ['<code>showGrid</code>', 'boolean', 'true', 'Horizontal grid lines'],
236
+ ['<code>gap</code>', 'number', '0.25', 'Gap between bars as fraction 0–0.9'],
237
+ ]
238
+ )}
239
+
240
+ <h3 class="doc-h3" style="margin-top:2rem">lineChart()</h3>
241
+ ${table(
242
+ ['Prop', 'Type', 'Default', ''],
243
+ [
244
+ ['<code>data</code>', 'array', '—', '<code>{ label, value }[]</code>'],
245
+ ['<code>height</code>', 'number', '220', 'SVG height in px'],
246
+ ['<code>color</code>', 'string', "'accent'", 'accent · success · warning · error · blue · muted'],
247
+ ['<code>area</code>', 'boolean', 'false', 'Fill area under the line'],
248
+ ['<code>showDots</code>', 'boolean', 'true', 'Dots at each data point'],
249
+ ['<code>showGrid</code>', 'boolean', 'true', 'Horizontal grid lines'],
250
+ ]
251
+ )}
252
+
253
+ <h3 class="doc-h3" style="margin-top:2rem">donutChart()</h3>
254
+ ${table(
255
+ ['Prop', 'Type', 'Default', ''],
256
+ [
257
+ ['<code>data</code>', 'array', '—', '<code>{ label, value, color? }[]</code> — color per segment'],
258
+ ['<code>size</code>', 'number', '200', 'Diameter in px'],
259
+ ['<code>thickness</code>', 'number', '40', 'Ring thickness in px'],
260
+ ['<code>label</code>', 'string', '—', 'Large centre text'],
261
+ ['<code>sublabel</code>', 'string', '—', 'Smaller text below centre label'],
262
+ ]
263
+ )}
264
+
265
+ <h3 class="doc-h3" style="margin-top:2rem">sparkline()</h3>
266
+ ${table(
267
+ ['Prop', 'Type', 'Default', ''],
268
+ [
269
+ ['<code>data</code>', 'number[]', '—', 'Plain array of numbers'],
270
+ ['<code>width</code>', 'number', '80', 'SVG width in px'],
271
+ ['<code>height</code>', 'number', '32', 'SVG height in px'],
272
+ ['<code>color</code>', 'string', "'accent'", 'accent · success · warning · error · blue · muted'],
273
+ ['<code>area</code>', 'boolean', 'false', 'Fill area under the line'],
274
+ ]
275
+ )}
276
+ `,
277
+ }),
278
+ }
@@ -0,0 +1,129 @@
1
+ import { renderComponentPage, demo } from '../../lib/component-page.js'
2
+ import { prevNext } from '../../lib/nav.js'
3
+ import { table, callout } from '../../lib/layout.js'
4
+ import { checkbox, fieldset } from '../../../../src/ui/index.js'
5
+
6
+ const { prev, next } = prevNext('/components/checkbox')
7
+
8
+ export default {
9
+ route: '/components/checkbox',
10
+ meta: {
11
+ title: 'Checkbox — Pulse Docs',
12
+ description: 'Custom-styled checkbox component for Pulse UI.',
13
+ styles: ['/pulse-ui.css', '/docs.css'],
14
+ },
15
+ state: {},
16
+ view: () => renderComponentPage({
17
+ currentHref: '/components/checkbox',
18
+ prev,
19
+ next,
20
+ name: 'checkbox',
21
+ description: 'Custom-styled checkbox with animated check mark, full keyboard and screen-reader support. Pairs with <a href="/components/fieldset">fieldset</a> for labelled groups.',
22
+ content: `
23
+
24
+ <h2 class="doc-h2" id="basic">Basic</h2>
25
+ <p>Pass <code>label</code> for the visible text. The <code>id</code> is auto-generated from <code>name</code> and <code>value</code>.</p>
26
+ ${demo(
27
+ checkbox({ name: 'agree', label: 'I agree to the terms' }),
28
+ `checkbox({ name: 'agree', label: 'I agree to the terms' })`,
29
+ { col: true }
30
+ )}
31
+
32
+ <h2 class="doc-h2" id="checked">Checked</h2>
33
+ ${demo(
34
+ checkbox({ name: 'newsletter', label: 'Send me updates', checked: true }),
35
+ `checkbox({ name: 'newsletter', label: 'Send me updates', checked: state.newsletter })`,
36
+ { col: true }
37
+ )}
38
+
39
+ <h2 class="doc-h2" id="hint">Hint</h2>
40
+ <p>A <code>hint</code> string renders below the label as supporting copy.</p>
41
+ ${demo(
42
+ checkbox({ name: 'marketing', label: 'Marketing emails', hint: 'Product news and tips. Unsubscribe any time.', checked: true }),
43
+ `checkbox({
44
+ name: 'marketing',
45
+ label: 'Marketing emails',
46
+ hint: 'Product news and tips. Unsubscribe any time.',
47
+ checked: state.marketing,
48
+ })`,
49
+ { col: true }
50
+ )}
51
+
52
+ <h2 class="doc-h2" id="error">Error state</h2>
53
+ <p>Pass <code>error</code> to show a validation message. The error is announced via <code>role="alert"</code>.</p>
54
+ ${demo(
55
+ checkbox({ name: 'terms', label: 'I accept the terms and conditions', error: 'You must accept the terms to continue.' }),
56
+ `checkbox({
57
+ name: 'terms',
58
+ label: 'I accept the terms and conditions',
59
+ error: server.errors.terms,
60
+ })`,
61
+ { col: true }
62
+ )}
63
+
64
+ <h2 class="doc-h2" id="disabled">Disabled</h2>
65
+ ${demo(
66
+ checkbox({ name: 'feature', label: 'Enable beta features', disabled: true }) +
67
+ ' ' +
68
+ checkbox({ name: 'feature2', label: 'Beta feature (on)', disabled: true, checked: true }),
69
+ `checkbox({ name: 'feature', label: 'Enable beta features', disabled: true })`,
70
+ { col: true }
71
+ )}
72
+
73
+ <h2 class="doc-h2" id="group">Group in a fieldset</h2>
74
+ <p>Compose multiple checkboxes inside a <a href="/components/fieldset">fieldset</a> for a semantic group.</p>
75
+ ${demo(
76
+ fieldset({
77
+ legend: 'Notifications',
78
+ content:
79
+ checkbox({ name: 'notif', value: 'email', label: 'Email', checked: true }) +
80
+ checkbox({ name: 'notif', value: 'sms', label: 'SMS' }) +
81
+ checkbox({ name: 'notif', value: 'browser', label: 'Browser push', checked: true }) +
82
+ checkbox({ name: 'notif', value: 'weekly', label: 'Weekly digest', disabled: true }),
83
+ }),
84
+ `fieldset({
85
+ legend: 'Notifications',
86
+ content:
87
+ checkbox({ name: 'notif', value: 'email', label: 'Email', checked: true }) +
88
+ checkbox({ name: 'notif', value: 'sms', label: 'SMS' }) +
89
+ checkbox({ name: 'notif', value: 'browser', label: 'Browser push', checked: true }) +
90
+ checkbox({ name: 'notif', value: 'weekly', label: 'Weekly digest', disabled: true }),
91
+ })`,
92
+ { col: true }
93
+ )}
94
+
95
+ <h2 class="doc-h2" id="in-forms">In forms</h2>
96
+ ${callout('note', 'Checkboxes submit their <code>value</code> string (defaulting to <code>"on"</code>) under <code>name</code> in FormData only when checked. Unchecked checkboxes are absent from FormData. Read them in <code>action.onStart</code> via <code>formData.get(\'agree\')</code> — a <code>null</code> result means unchecked.')}
97
+
98
+ <h2 class="doc-h2" id="labelhtml">Custom label HTML</h2>
99
+ <p>When the label needs inline styling — for example a strikethrough on a completed todo — use <code>labelHtml</code> instead of <code>label</code>. The value is inserted as raw HTML so you are responsible for escaping any user content.</p>
100
+ ${demo(
101
+ checkbox({ name: 'task', labelHtml: '<span style="text-decoration:line-through;opacity:.5">Buy milk</span>', checked: true }),
102
+ `checkbox({
103
+ name: 'task',
104
+ checked: todo.done,
105
+ labelHtml: \`<span class="\${todo.done ? 'u-text-muted' : ''}">\${esc(todo.text)}</span>\`,
106
+ })`,
107
+ { col: true }
108
+ )}
109
+
110
+ <h2 class="doc-h2" id="props">Props</h2>
111
+ ${table(
112
+ ['Prop', 'Type', 'Default', ''],
113
+ [
114
+ ['<code>name</code>', 'string', '—', 'Field name'],
115
+ ['<code>value</code>', 'string', '—', 'Submitted value when checked (defaults to browser default <code>"on"</code>)'],
116
+ ['<code>label</code>', 'string', '—', 'Visible label text — escaped'],
117
+ ['<code>labelHtml</code>', 'string', '—', 'Raw HTML label slot — not escaped, use for styled spans'],
118
+ ['<code>checked</code>', 'boolean', 'false', ''],
119
+ ['<code>disabled</code>', 'boolean', 'false', ''],
120
+ ['<code>id</code>', 'string', '—', 'Override the auto-generated <code>id</code>'],
121
+ ['<code>event</code>', 'string', '—', '<code>data-event</code> binding, e.g. <code>"change:toggle"</code>'],
122
+ ['<code>hint</code>', 'string', '—', 'Helper text below the label'],
123
+ ['<code>error</code>', 'string', '—', 'Validation error — announced via <code>role="alert"</code>'],
124
+ ['<code>class</code>', 'string', '—', ''],
125
+ ]
126
+ )}
127
+ `,
128
+ }),
129
+ }
@@ -0,0 +1,47 @@
1
+ import { renderComponentPage, demo } from '../../lib/component-page.js'
2
+ import { prevNext } from '../../lib/nav.js'
3
+ import { table } from '../../lib/layout.js'
4
+ import { badge, cluster } from '../../../../src/ui/index.js'
5
+
6
+ const { prev, next } = prevNext('/components/cluster')
7
+
8
+ export default {
9
+ route: '/components/cluster',
10
+ meta: {
11
+ title: 'Cluster — Pulse Docs',
12
+ description: 'Cluster component for Pulse UI.',
13
+ styles: ['/pulse-ui.css', '/docs.css'],
14
+ },
15
+ state: {},
16
+ view: () => renderComponentPage({
17
+ currentHref: '/components/cluster',
18
+ prev,
19
+ next,
20
+ name: 'cluster',
21
+ description: 'Flex row with wrapping. Groups inline elements horizontally — action buttons, badges, app store badges, stat rows.',
22
+ content: `
23
+ ${demo(
24
+ cluster({
25
+ gap: 'sm',
26
+ content: badge({ label: 'Performance' }) + badge({ label: 'Accessibility' }) + badge({ label: 'Zero JS', variant: 'success' }) + badge({ label: 'SSR', variant: 'info' }),
27
+ }),
28
+ `cluster({ gap: 'sm', justify: 'center', content:
29
+ badge({ label: 'Performance' }) +
30
+ badge({ label: 'Zero JS', variant: 'success' }) +
31
+ appBadge({ store: 'apple', href: url })
32
+ })`
33
+ )}
34
+
35
+ ${table(
36
+ ['Prop', 'Type', 'Default', ''],
37
+ [
38
+ ['<code>content</code>', 'string (HTML)', '—', 'Raw HTML slot'],
39
+ ['<code>gap</code>', 'string', "'md'", "'xs' · 'sm' · 'md' · 'lg'"],
40
+ ['<code>justify</code>', 'string', "'start'", "'start' · 'center' · 'end' · 'between'"],
41
+ ['<code>align</code>', 'string', "'center'","'start' · 'center' · 'end'"],
42
+ ['<code>wrap</code>', 'boolean', 'true', 'Set false to prevent wrapping'],
43
+ ]
44
+ )}
45
+ `,
46
+ }),
47
+ }
@@ -0,0 +1,57 @@
1
+ import { renderComponentPage, demo } from '../../lib/component-page.js'
2
+ import { prevNext } from '../../lib/nav.js'
3
+ import { table } from '../../lib/layout.js'
4
+ import { codeWindow } from '../../../../src/ui/index.js'
5
+
6
+ const { prev, next } = prevNext('/components/code-window')
7
+
8
+ export default {
9
+ route: '/components/code-window',
10
+ meta: {
11
+ title: 'Code Window — Pulse Docs',
12
+ description: 'macOS-style window chrome around a code block. Accepts pre-highlighted HTML as the content slot.',
13
+ styles: ['/pulse-ui.css', '/docs.css'],
14
+ },
15
+ state: {},
16
+ view: () => renderComponentPage({
17
+ currentHref: '/components/code-window',
18
+ prev,
19
+ next,
20
+ name: 'codeWindow',
21
+ description: 'macOS-style window chrome around a code block. Accepts pre-highlighted HTML as the content slot — the component handles all the chrome, layout, scrolling, and monospace typography.',
22
+ content: `
23
+ ${demo(
24
+ codeWindow({
25
+ filename: 'home.js',
26
+ lang: 'JavaScript',
27
+ content: `<span style="color:var(--ui-accent)">export default</span> {
28
+ <span style="color:var(--ui-text)">state</span>: { count: <span style="color:var(--ui-green)">0</span> },
29
+
30
+ <span style="color:var(--ui-text)">view</span>: (state) =&gt; \`
31
+ &lt;h1&gt;\${state.count}&lt;/h1&gt;
32
+ &lt;button data-event=<span style="color:var(--ui-yellow)">"inc"</span>&gt;+&lt;/button&gt;
33
+ \`,
34
+
35
+ <span style="color:var(--ui-text)">mutations</span>: {
36
+ inc: (state) =&gt; ({ count: state.count + <span style="color:var(--ui-green)">1</span> }),
37
+ },
38
+ }`,
39
+ }),
40
+ `codeWindow({
41
+ filename: 'home.js',
42
+ lang: 'JavaScript',
43
+ content: highlightedHtml, // pre-rendered HTML with syntax token spans
44
+ })`
45
+ )}
46
+
47
+ ${table(
48
+ ['Prop', 'Type', 'Default', ''],
49
+ [
50
+ ['<code>content</code>', 'string (HTML)', '—', 'Raw HTML slot — pre-highlighted code HTML or plain text'],
51
+ ['<code>filename</code>', 'string', '—', "Filename shown in the chrome bar (e.g. 'home.js')"],
52
+ ['<code>lang</code>', 'string', '—', "Language label shown on the right of the chrome (e.g. 'JavaScript')"],
53
+ ]
54
+ )}
55
+ `,
56
+ }),
57
+ }
@@ -0,0 +1,40 @@
1
+ import { renderComponentPage, demo } from '../../lib/component-page.js'
2
+ import { prevNext } from '../../lib/nav.js'
3
+ import { table } from '../../lib/layout.js'
4
+ import { container } from '../../../../src/ui/index.js'
5
+
6
+ const { prev, next } = prevNext('/components/container')
7
+
8
+ export default {
9
+ route: '/components/container',
10
+ meta: {
11
+ title: 'Container — Pulse Docs',
12
+ description: 'Container component for Pulse UI.',
13
+ styles: ['/pulse-ui.css', '/docs.css'],
14
+ },
15
+ state: {},
16
+ view: () => renderComponentPage({
17
+ currentHref: '/components/container',
18
+ prev,
19
+ next,
20
+ name: 'container',
21
+ description: 'Max-width wrapper with horizontal padding. The four size presets cover the most common layout widths.',
22
+ content: `
23
+ ${demo(
24
+ container({ content: '<p style="background:var(--surface-2);border:1px dashed var(--border);padding:1rem;border-radius:6px;text-align:center;color:var(--muted)">Content constrained to 768px</p>', size: 'md' }),
25
+ `container({ size: 'md', content: \`
26
+ \${hero({ title: 'Hello' })}
27
+ \${grid({ cols: 3, content: features })}
28
+ \` })`
29
+ )}
30
+
31
+ ${table(
32
+ ['Prop', 'Type', 'Default', ''],
33
+ [
34
+ ['<code>content</code>', 'string (HTML)', '—', 'Raw HTML slot'],
35
+ ['<code>size</code>', 'string', "'lg'", "'sm' (640px) · 'md' (768px) · 'lg' (1100px) · 'xl' (1280px)"],
36
+ ]
37
+ )}
38
+ `,
39
+ }),
40
+ }