@invisibleloop/pulse 0.1.28 → 0.1.29

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 (117) hide show
  1. package/.claude/settings.local.json +113 -0
  2. package/.github/workflows/publish.yml +11 -21
  3. package/docs/public/.pulse-ui-version +1 -1
  4. package/docs/public/docs.css +19 -1
  5. package/docs/public/pulse-ui.css +1 -0
  6. package/docs/server.js +5 -2
  7. package/docs/src/lib/highlight.js +57 -13
  8. package/docs/src/lib/layout.js +5 -2
  9. package/docs/src/pages/faq.js +5 -2
  10. package/docs/src/pages/home.js +9 -5
  11. package/docs/src/pages/meta.js +21 -0
  12. package/docs/src/pages/routing.js +12 -1
  13. package/package.json +1 -1
  14. package/src/agent/guide-routing.md +20 -0
  15. package/src/agent/guide-spec.md +9 -1
  16. package/src/cli/scaffold.js +63 -2
  17. package/src/server/index.js +21 -6
  18. package/src/server/server.test.js +47 -0
  19. package/docs/public/dist/accessibility.boot-5DVTARJU.js +0 -115
  20. package/docs/public/dist/actions.boot-P66HKQEM.js +0 -164
  21. package/docs/public/dist/auth.boot-IMAJAUPH.js +0 -140
  22. package/docs/public/dist/caching.boot-DVR6KDE7.js +0 -53
  23. package/docs/public/dist/components--accordion.boot-3HVKMNWC.js +0 -11
  24. package/docs/public/dist/components--alert.boot-GCEXOZAC.js +0 -6
  25. package/docs/public/dist/components--app-badge.boot-DVT3GCHJ.js +0 -6
  26. package/docs/public/dist/components--avatar.boot-PSW24EVA.js +0 -5
  27. package/docs/public/dist/components--badge.boot-TYDY2RMK.js +0 -7
  28. package/docs/public/dist/components--banner.boot-EI5PZSZK.js +0 -7
  29. package/docs/public/dist/components--breadcrumbs.boot-SMA2E2GO.js +0 -34
  30. package/docs/public/dist/components--button.boot-J54BQM2E.js +0 -23
  31. package/docs/public/dist/components--card.boot-PZGNDIB6.js +0 -138
  32. package/docs/public/dist/components--carousel.boot-TP6LPFZZ.js +0 -12
  33. package/docs/public/dist/components--charts.boot-2EOYQWKL.js +0 -108
  34. package/docs/public/dist/components--checkbox.boot-DS5BSL6T.js +0 -54
  35. package/docs/public/dist/components--cluster.boot-HHVIBBJG.js +0 -9
  36. package/docs/public/dist/components--code-window.boot-2GR2DV33.js +0 -20
  37. package/docs/public/dist/components--container.boot-7LOOGK2K.js +0 -5
  38. package/docs/public/dist/components--cta.boot-FSNZ5YRT.js +0 -11
  39. package/docs/public/dist/components--divider.boot-3NI2C3QG.js +0 -6
  40. package/docs/public/dist/components--empty.boot-YX2UR3PV.js +0 -7
  41. package/docs/public/dist/components--feature.boot-MUD7NSUO.js +0 -13
  42. package/docs/public/dist/components--fieldset.boot-J7BYHMKF.js +0 -19
  43. package/docs/public/dist/components--fileupload.boot-NIKVTTPD.js +0 -52
  44. package/docs/public/dist/components--footer.boot-EYUK5FRG.js +0 -14
  45. package/docs/public/dist/components--grid.boot-URDQVDDR.js +0 -59
  46. package/docs/public/dist/components--heading.boot-BPQKU43E.js +0 -44
  47. package/docs/public/dist/components--hero.boot-4RAPRGAB.js +0 -17
  48. package/docs/public/dist/components--icons.boot-ZITNU5JP.js +0 -68
  49. package/docs/public/dist/components--image.boot-XEEGHQZF.js +0 -19
  50. package/docs/public/dist/components--input.boot-SGASZG5K.js +0 -7
  51. package/docs/public/dist/components--list.boot-W3XC5MHD.js +0 -55
  52. package/docs/public/dist/components--media.boot-5VFIETZO.js +0 -13
  53. package/docs/public/dist/components--modal.boot-RZUYXBN2.js +0 -47
  54. package/docs/public/dist/components--nav.boot-ODBOHU7O.js +0 -33
  55. package/docs/public/dist/components--pricing.boot-4AQ4ZVBY.js +0 -21
  56. package/docs/public/dist/components--progress.boot-GHAGYZOK.js +0 -30
  57. package/docs/public/dist/components--prose.boot-QANJL6JI.js +0 -67
  58. package/docs/public/dist/components--pullquote.boot-Q2WMNAZU.js +0 -22
  59. package/docs/public/dist/components--radio.boot-TJRDQ2OL.js +0 -75
  60. package/docs/public/dist/components--rating.boot-QBAN6DEL.js +0 -38
  61. package/docs/public/dist/components--search.boot-PXH5O5AG.js +0 -17
  62. package/docs/public/dist/components--section.boot-AQGIYHWW.js +0 -12
  63. package/docs/public/dist/components--segmented.boot-BEVTKEJO.js +0 -33
  64. package/docs/public/dist/components--select.boot-47X5RHOC.js +0 -10
  65. package/docs/public/dist/components--slider.boot-PSRRX7XL.js +0 -47
  66. package/docs/public/dist/components--spinner.boot-MZ5MO2OH.js +0 -22
  67. package/docs/public/dist/components--stack.boot-DI4NJXBF.js +0 -9
  68. package/docs/public/dist/components--stat.boot-QMFUWBQT.js +0 -9
  69. package/docs/public/dist/components--stepper.boot-34PP2NEV.js +0 -22
  70. package/docs/public/dist/components--table.boot-FCQGSFIQ.js +0 -11
  71. package/docs/public/dist/components--testimonial.boot-DWQPDKYG.js +0 -11
  72. package/docs/public/dist/components--textarea.boot-QVXLBOJ5.js +0 -4
  73. package/docs/public/dist/components--timeline.boot-26LN52P2.js +0 -95
  74. package/docs/public/dist/components--toggle.boot-IQQEI76S.js +0 -29
  75. package/docs/public/dist/components--tooltip.boot-LGHCO6NN.js +0 -9
  76. package/docs/public/dist/components.boot-SE6PQ4P7.js +0 -103
  77. package/docs/public/dist/config.boot-DTRRWUE6.js +0 -126
  78. package/docs/public/dist/constraints.boot-DUHDZBMC.js +0 -71
  79. package/docs/public/dist/deploy.boot-SLAD3NI2.js +0 -163
  80. package/docs/public/dist/docs-8e3d4b5c.css +0 -1
  81. package/docs/public/dist/extending.boot-UA3CN243.js +0 -159
  82. package/docs/public/dist/faq.boot-6EQAWLQR.js +0 -43
  83. package/docs/public/dist/getting-started.boot-TDKIFL5U.js +0 -86
  84. package/docs/public/dist/guard.boot-AUHAWTG4.js +0 -80
  85. package/docs/public/dist/home.boot-BVQXRH32.js +0 -383
  86. package/docs/public/dist/how-it-works.boot-LTWAKWKW.js +0 -104
  87. package/docs/public/dist/hydration.boot-JRM6IPJL.js +0 -78
  88. package/docs/public/dist/images.boot-M6ZVKTZS.js +0 -80
  89. package/docs/public/dist/manifest.json +0 -94
  90. package/docs/public/dist/meta.boot-7NXGPHR4.js +0 -79
  91. package/docs/public/dist/mutations.boot-F6F43UDX.js +0 -79
  92. package/docs/public/dist/navigation.boot-AOXWS3ZF.js +0 -57
  93. package/docs/public/dist/performance.boot-C3UPCOBK.js +0 -98
  94. package/docs/public/dist/persist.boot-WT32PQOQ.js +0 -61
  95. package/docs/public/dist/project-structure.boot-FB3LRVJ4.js +0 -63
  96. package/docs/public/dist/prompt-examples.boot-YKR4VDK4.js +0 -31
  97. package/docs/public/dist/pulse-ui-81a85c03.css +0 -1
  98. package/docs/public/dist/raw-responses.boot-M4KA5YXL.js +0 -104
  99. package/docs/public/dist/routing.boot-FNX5FDGH.js +0 -70
  100. package/docs/public/dist/runtime-B73WLANC.js +0 -1
  101. package/docs/public/dist/runtime-KO4BHUQ3.js +0 -49
  102. package/docs/public/dist/runtime-L2HNXIHW.js +0 -59
  103. package/docs/public/dist/runtime-QFURDKA2.js +0 -5
  104. package/docs/public/dist/runtime-UVPXO4IR.js +0 -375
  105. package/docs/public/dist/runtime-VMJA3Z4N.js +0 -10
  106. package/docs/public/dist/runtime-ZJ4FXT5O.js +0 -11
  107. package/docs/public/dist/server-api.boot-K7X3LCFB.js +0 -219
  108. package/docs/public/dist/server-data.boot-Y7HQYC4R.js +0 -157
  109. package/docs/public/dist/slash-commands.boot-V2UV7OW2.js +0 -26
  110. package/docs/public/dist/spec.boot-2WU7ZHCV.js +0 -159
  111. package/docs/public/dist/state.boot-B24GUE3R.js +0 -73
  112. package/docs/public/dist/store.boot-TLIB4XHH.js +0 -150
  113. package/docs/public/dist/streaming.boot-W2DZSMW4.js +0 -80
  114. package/docs/public/dist/stripe.boot-QN3C2GEL.js +0 -164
  115. package/docs/public/dist/supabase.boot-BG4XXLZE.js +0 -303
  116. package/docs/public/dist/testing.boot-6U4WKMTE.js +0 -130
  117. package/docs/public/dist/validation.boot-PQHYGW5B.js +0 -100
@@ -1,6 +0,0 @@
1
- import{a as n,b as d}from"./runtime-ZJ4FXT5O.js";import{Ma as t}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as r,h as a}from"./runtime-L2HNXIHW.js";import{a as o,b as s}from"./runtime-B73WLANC.js";var{prev:i,next:l}=r("/components/app-badge"),p={route:"/components/app-badge",meta:{title:"App Badge \u2014 Pulse Docs",description:"App Badge component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>d({currentHref:"/components/app-badge",prev:i,next:l,name:"appBadge",description:"App Store and Google Play download buttons. Designed to sit in a <code>hero()</code> actions slot, or anywhere a download CTA is needed.",content:`
2
- ${n('<div style="display:flex;gap:.75rem;flex-wrap:wrap">'+t({store:"apple",href:"#"})+t({store:"google",href:"#"})+"</div>",`appBadge({ store: 'apple', href: appStoreUrl })
3
- appBadge({ store: 'google', href: playStoreUrl })`)}
4
-
5
- ${a(["Prop","Type","Default",""],[["<code>store</code>","string","'apple'","'apple' or 'google'"],["<code>href</code>","string","'#'","Link to the app store listing"]])}
6
- `})};var e=document.getElementById("pulse-root");e&&!e.dataset.pulseMounted&&(e.dataset.pulseMounted="1",o(p,e,window.__PULSE_SERVER__||{},{ssr:!0}),s(e,o));var B=p;export{B as default};
@@ -1,5 +0,0 @@
1
- import{a as s,b as n}from"./runtime-ZJ4FXT5O.js";import{Da as e}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as r}from"./runtime-L2HNXIHW.js";import{a,b as i}from"./runtime-B73WLANC.js";var{prev:l,next:c}=r("/components/avatar"),o={route:"/components/avatar",meta:{title:"Avatar \u2014 Pulse Docs",description:"Avatar component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>n({currentHref:"/components/avatar",prev:l,next:c,name:"avatar",description:'When <code>src</code> is set, renders an <code>&lt;img&gt;</code> with <code>loading="lazy"</code>. Without <code>src</code>, shows initials derived from <code>alt</code>.',content:`
2
- ${s('<div style="display:flex;gap:1rem;align-items:center">'+e({alt:"Alice Smith",size:"sm"})+e({alt:"Bob Jones",size:"md"})+e({alt:"Carol White",size:"lg"})+e({alt:"Dan Brown",size:"xl"})+"</div>",`avatar({ src: user.avatarUrl, alt: user.name, size: 'md' })
3
- avatar({ alt: 'Alice Smith' }) // renders initials "AS"
4
- avatar({ alt: 'Alice', initials: 'A' }) // explicit initials`)}
5
- `})};var t=document.getElementById("pulse-root");t&&!t.dataset.pulseMounted&&(t.dataset.pulseMounted="1",a(o,t,window.__PULSE_SERVER__||{},{ssr:!0}),i(t,a));var h=o;export{h as default};
@@ -1,7 +0,0 @@
1
- import{a as s,b as i}from"./runtime-ZJ4FXT5O.js";import{b as e}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as n}from"./runtime-L2HNXIHW.js";import{a as t,b as o}from"./runtime-B73WLANC.js";var{prev:l,next:d}=n("/components/badge"),r={route:"/components/badge",meta:{title:"Badge \u2014 Pulse Docs",description:"Badge component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>i({currentHref:"/components/badge",prev:l,next:d,name:"badge",description:"Inline status and label indicator. Five semantic variants cover the most common states.",content:`
2
- ${s(e({label:"Default",variant:"default"})+" "+e({label:"Info",variant:"info"})+" "+e({label:"Success",variant:"success"})+" "+e({label:"Warning",variant:"warning"})+" "+e({label:"Error",variant:"error"}),`badge({ label: 'Default', variant: 'default' })
3
- badge({ label: 'Info', variant: 'info' })
4
- badge({ label: 'Success', variant: 'success' })
5
- badge({ label: 'Warning', variant: 'warning' })
6
- badge({ label: 'Error', variant: 'error' })`)}
7
- `})};var a=document.getElementById("pulse-root");a&&!a.dataset.pulseMounted&&(a.dataset.pulseMounted="1",t(r,a,window.__PULSE_SERVER__||{},{ssr:!0}),o(a,t));var v=r;export{v as default};
@@ -1,7 +0,0 @@
1
- import{a as s,b as c}from"./runtime-ZJ4FXT5O.js";import{Qa as m,Ta as t}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as r,h as a}from"./runtime-L2HNXIHW.js";import{a as e,b as i}from"./runtime-B73WLANC.js";var{prev:p,next:d}=r("/components/banner"),o={route:"/components/banner",meta:{title:"Banner \u2014 Pulse Docs",description:"Banner component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>c({currentHref:"/components/banner",prev:p,next:d,name:"banner",description:"Full-width announcement bar. Sits above the nav for promotions and launch announcements. The content slot accepts links and formatted text.",content:`
2
- ${s(m({gap:"sm",content:t({variant:"promo",content:`\u{1F389} Chippy Bird v2.0 is out \u2014 <a href="#" style="color:inherit;text-decoration:underline">see what's new</a>`})+t({variant:"info",content:'Android support is coming soon. <a href="#" style="color:inherit;text-decoration:underline">Join the waitlist</a>'})+t({variant:"warning",content:"Scheduled maintenance Sunday 2\u20134am UTC."})}),`banner({ variant: 'promo', content:
3
- '\u{1F389} v2.0 is out \u2014 ' + button({ label: "See what's new", variant: 'ghost', size: 'sm', href: '/changelog' })
4
- })`)}
5
-
6
- ${a(["Prop","Type","Default",""],[["<code>content</code>","string (HTML)","\u2014","Raw HTML slot"],["<code>variant</code>","string","'info'","'info' \xB7 'promo' \xB7 'warning'"]])}
7
- `})};var n=document.getElementById("pulse-root");n&&!n.dataset.pulseMounted&&(n.dataset.pulseMounted="1",e(o,n,window.__PULSE_SERVER__||{},{ssr:!0}),i(n,e));var x=o;export{x as default};
@@ -1,34 +0,0 @@
1
- import{a as r,b as d}from"./runtime-ZJ4FXT5O.js";import{pb as o}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as t,h as c}from"./runtime-L2HNXIHW.js";import{a as s,b as l}from"./runtime-B73WLANC.js";var{prev:n,next:m}=t("/components/breadcrumbs"),a={route:"/components/breadcrumbs",meta:{title:"Breadcrumbs \u2014 Pulse Docs",description:"Accessible breadcrumb navigation component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>d({currentHref:"/components/breadcrumbs",prev:n,next:m,name:"breadcrumbs",description:'Accessible breadcrumb navigation. The current page item renders as a <code>&lt;span&gt;</code> with <code>aria-current="page"</code>; all preceding items render as links.',content:`
2
-
3
- <h2 class="doc-h2" id="basic">Basic</h2>
4
- ${r(o({items:[{label:"Home",href:"/"},{label:"Products",href:"/products"},{label:"Sneakers"}]}),`breadcrumbs({
5
- items: [
6
- { label: 'Home', href: '/' },
7
- { label: 'Products', href: '/products' },
8
- { label: 'Sneakers' },
9
- ],
10
- })`)}
11
-
12
- <h2 class="doc-h2" id="longer">Longer trail</h2>
13
- ${r(o({items:[{label:"Home",href:"/"},{label:"Shop",href:"/shop"},{label:"Footwear",href:"/shop/footwear"},{label:"Sneakers",href:"/shop/footwear/sneakers"},{label:"Air Max 90"}]}),`breadcrumbs({
14
- items: [
15
- { label: 'Home', href: '/' },
16
- { label: 'Shop', href: '/shop' },
17
- { label: 'Footwear', href: '/shop/footwear' },
18
- { label: 'Sneakers', href: '/shop/footwear/sneakers' },
19
- { label: 'Air Max 90' },
20
- ],
21
- })`)}
22
-
23
- <h2 class="doc-h2" id="separator">Custom separator</h2>
24
- ${r(o({separator:"\u203A",items:[{label:"Docs",href:"/docs"},{label:"Components",href:"/docs/components"},{label:"Breadcrumbs"}]}),`breadcrumbs({
25
- separator: '\u203A',
26
- items: [
27
- { label: 'Docs', href: '/docs' },
28
- { label: 'Components', href: '/docs/components' },
29
- { label: 'Breadcrumbs' },
30
- ],
31
- })`)}
32
-
33
- ${c(["Prop","Type","Default",""],[["<code>items</code>","array","[]","Array of <code>{ label, href }</code>. The last item should have no <code>href</code> \u2014 it becomes the current page."],["<code>separator</code>","string","'/'","Character rendered between items"],["<code>class</code>","string","\u2014",""]])}
34
- `})};var e=document.getElementById("pulse-root");e&&!e.dataset.pulseMounted&&(e.dataset.pulseMounted="1",s(a,e,window.__PULSE_SERVER__||{},{ssr:!0}),l(e,s));var S=a;export{S as default};
@@ -1,23 +0,0 @@
1
- import{a as t,b as s}from"./runtime-ZJ4FXT5O.js";import{E as b,H as u,a as e,f as d,x as c}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as i,h as r}from"./runtime-L2HNXIHW.js";import{a as n,b as l}from"./runtime-B73WLANC.js";var{prev:m,next:p}=i("/components/button"),a={route:"/components/button",meta:{title:"Button \u2014 Pulse Docs",description:"Button component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>s({currentHref:"/components/button",prev:m,next:p,name:"button",description:"Renders as <code>&lt;button&gt;</code> by default. Pass <code>href</code> to get an <code>&lt;a&gt;</code> that looks identical. All four variants are shown below.",content:`
2
- ${t(e({label:"Primary",variant:"primary"})+e({label:"Secondary",variant:"secondary"})+e({label:"Ghost",variant:"ghost"})+e({label:"Danger",variant:"danger"}),`button({ label: 'Primary', variant: 'primary' })
3
- button({ label: 'Secondary', variant: 'secondary' })
4
- button({ label: 'Ghost', variant: 'ghost' })
5
- button({ label: 'Danger', variant: 'danger' })`)}
6
-
7
- ${t(e({label:"Small",size:"sm"})+e({label:"Medium",size:"md"})+e({label:"Large",size:"lg"}),`button({ label: 'Small', size: 'sm' })
8
- button({ label: 'Medium', size: 'md' })
9
- button({ label: 'Large', size: 'lg' })`)}
10
-
11
- ${t(e({label:"Download",icon:b({size:14})})+e({label:"New item",icon:c({size:14}),variant:"secondary"})+e({label:"Continue",iconAfter:d({size:14})})+e({label:"Send",iconAfter:u({size:14}),variant:"ghost"}),`import { iconDownload, iconPlus, iconArrowRight, iconSend } from '@invisibleloop/pulse/ui'
12
-
13
- button({ label: 'Download', icon: iconDownload({ size: 14 }) })
14
- button({ label: 'New item', icon: iconPlus({ size: 14 }), variant: 'secondary' })
15
- button({ label: 'Continue', iconAfter: iconArrowRight({ size: 14 }) })
16
- button({ label: 'Send', iconAfter: iconSend({ size: 14 }), variant: 'ghost' })`)}
17
-
18
- ${t(e({label:"Disabled",disabled:!0})+e({label:"Link",href:"/docs"})+e({label:"Submit",type:"submit",variant:"primary"}),`button({ label: 'Disabled', disabled: true })
19
- button({ label: 'Link', href: '/docs' })
20
- button({ label: 'Submit', type: 'submit', variant: 'primary' })`)}
21
-
22
- ${r(["Prop","Type","Default",""],[["<code>label</code>","string","\u2014","Visible text"],["<code>variant</code>","string","primary","primary \xB7 secondary \xB7 ghost \xB7 danger"],["<code>size</code>","string","md","sm \xB7 md \xB7 lg"],["<code>href</code>","string","\u2014","Renders <code>&lt;a&gt;</code> instead of <code>&lt;button&gt;</code>"],["<code>disabled</code>","boolean","false",""],["<code>type</code>","string","button","button \xB7 submit \xB7 reset"],["<code>icon</code>","string","\u2014","SVG HTML prepended inside"],["<code>iconAfter</code>","string","\u2014","SVG HTML appended inside"],["<code>fullWidth</code>","boolean","false",""],["<code>class</code>","string","\u2014","Extra classes appended to the element"],["<code>attrs</code>","object","{}","Extra HTML attributes (button only)"]])}
23
- `})};var o=document.getElementById("pulse-root");o&&!o.dataset.pulseMounted&&(o.dataset.pulseMounted="1",n(a,o,window.__PULSE_SERVER__||{},{ssr:!0}),l(o,n));var P=a;export{P as default};
@@ -1,138 +0,0 @@
1
- import{a as e,b as c}from"./runtime-ZJ4FXT5O.js";import{Pa as n,a as s,b as i,c as t}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as l,h as d}from"./runtime-L2HNXIHW.js";import{a as o,b as u}from"./runtime-B73WLANC.js";var{prev:p,next:m}=l("/components/card"),r={route:"/components/card",meta:{title:"Card \u2014 Pulse Docs",description:"Card component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>c({currentHref:"/components/card",prev:p,next:m,name:"card",description:"<code>content</code> and <code>footer</code> are raw HTML slots \u2014 they pass through as-is. Wrap user-supplied values in <code>escHtml()</code> before composing them into the string.",content:`
2
- ${e(t({title:"Recent activity",content:'<p class="u-text-muted u-text-sm" style="margin:0">No activity in the last 7 days.</p>',footer:s({label:"View all",href:"#",variant:"ghost",size:"sm"})}),`card({
3
- title: 'Recent activity',
4
- content: \`<p class="u-text-muted u-text-sm">No activity in the last 7 days.</p>\`,
5
- footer: button({ label: 'View all', href: '/activity', variant: 'ghost', size: 'sm' }),
6
- })`)}
7
-
8
- <h2 class="doc-h2" id="image">With image</h2>
9
- <p>Use <code>flush</code> to remove body padding, then add an image at the top and restore padding on the text content below it.</p>
10
-
11
- ${e(t({flush:!0,content:`
12
- <div class="u-rounded-md u-overflow-hidden" style="height:180px;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;">
13
- <span style="font-size:3rem">\u{1F304}</span>
14
- </div>
15
- <div class="u-p-5">
16
- <p class="u-font-semibold u-mb-2" style="margin-top:0">Mountain retreat</p>
17
- <p class="u-text-muted u-text-sm" style="margin:0">A peaceful escape in the highlands. Three nights, all-inclusive.</p>
18
- </div>
19
- `,footer:s({label:"Book now",href:"#",variant:"primary",size:"sm"})}),`card({
20
- flush: true,
21
- content: \`
22
- <div class="u-rounded-md u-overflow-hidden" style="height:180px;background:...">
23
- <img src="/img/retreat.jpg" alt="Mountain retreat" style="width:100%;height:100%;object-fit:cover">
24
- </div>
25
- <div class="u-p-5">
26
- <p class="u-font-semibold u-mb-2">Mountain retreat</p>
27
- <p class="u-text-muted u-text-sm">A peaceful escape in the highlands.</p>
28
- </div>
29
- \`,
30
- footer: button({ label: 'Book now', href: '/book', variant: 'primary', size: 'sm' }),
31
- })`)}
32
-
33
- <h2 class="doc-h2" id="badges">With badges</h2>
34
- <p>Compose <code>badge()</code> inside <code>content</code> to show status labels or category tags.</p>
35
-
36
- ${e(t({title:"API rate limits",content:`
37
- <div class="u-flex u-gap-2 u-mb-4">
38
- ${i({label:"Production",variant:"success"})}
39
- ${i({label:"v2.1",variant:"info"})}
40
- </div>
41
- <p class="u-text-muted u-text-sm" style="margin:0">Requests are capped at 1,000/min per API key. Contact support to increase your limit.</p>
42
- `,footer:`
43
- <div class="u-flex u-gap-2">
44
- ${s({label:"View docs",href:"#",variant:"ghost",size:"sm"})}
45
- ${s({label:"Request increase",href:"#",variant:"secondary",size:"sm"})}
46
- </div>
47
- `}),`card({
48
- title: 'API rate limits',
49
- content: \`
50
- <div class="u-flex u-gap-2 u-mb-4">
51
- \${badge({ label: 'Production', variant: 'success' })}
52
- \${badge({ label: 'v2.1', variant: 'info' })}
53
- </div>
54
- <p class="u-text-muted u-text-sm">Requests are capped at 1,000/min per API key.</p>
55
- \`,
56
- footer: \`
57
- \${button({ label: 'View docs', href: '/docs', variant: 'ghost', size: 'sm' })}
58
- \${button({ label: 'Request increase', href: '/contact', variant: 'secondary', size: 'sm' })}
59
- \`,
60
- })`)}
61
-
62
- <h2 class="doc-h2" id="metadata">With metadata row</h2>
63
- <p>A flex row inside <code>content</code> works well for author, date, read-time and similar metadata.</p>
64
-
65
- ${e(t({title:"Building with Pulse",content:`
66
- <p class="u-text-muted u-text-sm u-mb-4">Learn how to scaffold a new project and ship your first spec-driven page in under ten minutes.</p>
67
- <div class="u-flex u-gap-3" style="align-items:center;flex-wrap:wrap">
68
- <div style="width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#667eea,#764ba2);flex-shrink:0"></div>
69
- <span class="u-text-sm u-text-muted">Jane Smith</span>
70
- <span class="u-text-sm u-text-muted">\xB7</span>
71
- <span class="u-text-sm u-text-muted">Mar 15, 2024</span>
72
- <span class="u-text-sm u-text-muted u-ml-auto">5 min read</span>
73
- </div>
74
- `,footer:s({label:"Read article \u2192",href:"#",variant:"ghost",size:"sm"})}),`card({
75
- title: 'Building with Pulse',
76
- content: \`
77
- <p class="u-text-muted u-text-sm u-mb-4">Learn how to scaffold a new project...</p>
78
- <div class="u-flex u-gap-3" style="align-items:center;flex-wrap:wrap">
79
- <img src="/img/avatar.jpg" class="u-rounded-full" style="width:28px;height:28px" alt="">
80
- <span class="u-text-sm u-text-muted">Jane Smith</span>
81
- <span class="u-text-sm u-text-muted">\xB7</span>
82
- <span class="u-text-sm u-text-muted">Mar 15, 2024</span>
83
- <span class="u-text-sm u-text-muted u-ml-auto">5 min read</span>
84
- </div>
85
- \`,
86
- footer: button({ label: 'Read article \u2192', href: '/blog/pulse', variant: 'ghost', size: 'sm' }),
87
- })`)}
88
-
89
- <h2 class="doc-h2" id="stat">Stat / metric card</h2>
90
- <p>Cards without a title work well as simple metric tiles. Use <code>grid()</code> to lay multiple cards out side by side.</p>
91
-
92
- ${e(n({cols:3,gap:"sm",content:[t({content:'<p class="u-text-muted u-text-sm u-mb-1" style="margin-top:0">Total revenue</p><p class="u-text-3xl u-font-bold" style="margin:0">\xA348,295</p><p class="u-text-sm u-text-green u-mb-0" style="margin-top:.25rem">\u2191 12% this month</p>'}),t({content:'<p class="u-text-muted u-text-sm u-mb-1" style="margin-top:0">Active users</p><p class="u-text-3xl u-font-bold" style="margin:0">3,842</p><p class="u-text-sm u-text-muted u-mb-0" style="margin-top:.25rem">Across all plans</p>'}),t({content:'<p class="u-text-muted u-text-sm u-mb-1" style="margin-top:0">Churn rate</p><p class="u-text-3xl u-font-bold" style="margin:0">1.4%</p><p class="u-text-sm u-text-red u-mb-0" style="margin-top:.25rem">\u2191 0.2% vs last month</p>'})].join("")}),`grid({
93
- cols: 3,
94
- gap: 'sm',
95
- content: [
96
- card({
97
- content: \`
98
- <p class="u-text-muted u-text-sm u-mb-1">Total revenue</p>
99
- <p class="u-text-3xl u-font-bold">\xA348,295</p>
100
- <p class="u-text-sm u-text-green">\u2191 12% this month</p>
101
- \`,
102
- }),
103
- card({ ... }),
104
- card({ ... }),
105
- ].join(''),
106
- })`)}
107
-
108
- <h2 class="doc-h2" id="grid-inside">Grid inside a card</h2>
109
- <p>Components compose freely \u2014 pass a <code>grid()</code> into a card's <code>content</code> slot for structured layouts inside a surface.</p>
110
-
111
- ${e(t({title:"Plan comparison",content:n({cols:3,gap:"sm",content:[`<div class="u-text-center u-p-2">
112
- <p class="u-font-semibold u-mb-1" style="margin-top:0">Starter</p>
113
- <p class="u-text-2xl u-font-bold u-mb-1" style="margin:0">\xA30</p>
114
- <p class="u-text-muted u-text-sm" style="margin:0">Up to 3 projects</p>
115
- </div>`,`<div class="u-text-center u-p-2" style="border-left:1px solid var(--ui-border);border-right:1px solid var(--ui-border)">
116
- <p class="u-font-semibold u-mb-1" style="margin-top:0;color:var(--ui-accent)">Pro</p>
117
- <p class="u-text-2xl u-font-bold u-mb-1" style="margin:0">\xA312</p>
118
- <p class="u-text-muted u-text-sm" style="margin:0">Unlimited projects</p>
119
- </div>`,`<div class="u-text-center u-p-2">
120
- <p class="u-font-semibold u-mb-1" style="margin-top:0">Enterprise</p>
121
- <p class="u-text-2xl u-font-bold u-mb-1" style="margin:0">Custom</p>
122
- <p class="u-text-muted u-text-sm" style="margin:0">SLA + support</p>
123
- </div>`].join("")}),footer:s({label:"View full pricing",href:"#",variant:"ghost",size:"sm"})}),`card({
124
- title: 'Plan comparison',
125
- content: grid({
126
- cols: 3,
127
- gap: 'sm',
128
- content: [
129
- \`<div class="u-text-center u-p-2">...</div>\`,
130
- \`<div class="u-text-center u-p-2">...</div>\`,
131
- \`<div class="u-text-center u-p-2">...</div>\`,
132
- ].join(''),
133
- }),
134
- footer: button({ label: 'View full pricing', href: '/pricing', variant: 'ghost', size: 'sm' }),
135
- })`)}
136
-
137
- ${d(["Prop","Type","Default",""],[["<code>title</code>","string","\u2014","Escaped automatically"],["<code>level</code>","number","3","Heading tag for the title (1\u20136). Visual style is unchanged \u2014 use this to keep the document outline correct when the surrounding context already has an h2 or h3."],["<code>content</code>","string","\u2014","HTML string \u2014 not escaped"],["<code>footer</code>","string","\u2014","HTML string \u2014 not escaped"],["<code>flush</code>","boolean","false","Removes body padding \u2014 useful for full-bleed images or tables"],["<code>class</code>","string","\u2014",""]])}
138
- `})};var a=document.getElementById("pulse-root");a&&!a.dataset.pulseMounted&&(a.dataset.pulseMounted="1",o(r,a,window.__PULSE_SERVER__||{},{ssr:!0}),u(a,o));var P=r;export{P as default};
@@ -1,12 +0,0 @@
1
- import{a as r,b as l}from"./runtime-ZJ4FXT5O.js";import{Ya as t}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as d,h as a}from"./runtime-L2HNXIHW.js";import{a as s,b as n}from"./runtime-B73WLANC.js";var{prev:p,next:f}=d("/components/carousel");function e(c,u){return`<div style="height:220px;display:flex;align-items:center;justify-content:center;background:${c};border-radius:10px;font-size:1.1rem;font-weight:700;color:var(--ui-text)">${u}</div>`}var i={route:"/components/carousel",meta:{title:"Carousel \u2014 Pulse Docs",description:"Carousel / slider component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>l({currentHref:"/components/carousel",prev:p,next:f,name:"carousel",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.",content:`
2
- ${r(t({slides:[e("var(--ui-surface-2)","Slide 1"),e("var(--ui-surface)","Slide 2"),e("var(--ui-surface-2)","Slide 3")]}),'carousel({\n slides: [\n `<div class="slide">Slide 1</div>`,\n `<div class="slide">Slide 2</div>`,\n `<div class="slide">Slide 3</div>`,\n ],\n})')}
3
-
4
- <h3 class="doc-h3" id="arrows-dots"><a href="#arrows-dots" class="heading-anchor">Arrows and dots</a></h3>
5
- ${r(t({arrows:!0,dots:!1,slides:[e("var(--ui-surface-2)","Arrows only \u2014 Slide 1"),e("var(--ui-surface)","Arrows only \u2014 Slide 2")]}),`carousel({
6
- slides: [ /* ... */ ],
7
- arrows: true,
8
- dots: false, // hide dot navigation
9
- })`)}
10
-
11
- ${a(["Prop","Type","Default",""],[["<code>slides</code>","string[] (HTML)","[]","Array of raw HTML strings \u2014 one per slide"],["<code>arrows</code>","boolean","<code>true</code>","Show prev/next arrow buttons"],["<code>dots</code>","boolean","<code>true</code>","Show dot navigation (hidden when only one slide)"],["<code>class</code>","string","\u2014",""]])}
12
- `})};var o=document.getElementById("pulse-root");o&&!o.dataset.pulseMounted&&(o.dataset.pulseMounted="1",s(i,o,window.__PULSE_SERVER__||{},{ssr:!0}),n(o,s));var b=i;export{b as default};
@@ -1,108 +0,0 @@
1
- import{a as e,b as m}from"./runtime-ZJ4FXT5O.js";import{Ca as n,Pa as i,c as l,ib as t,jb as r,kb as u,lb as a}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as p,h as o}from"./runtime-L2HNXIHW.js";import{a as d,b as v}from"./runtime-B73WLANC.js";var{prev:g,next:f}=p("/components/charts"),c=[{label:"Jan",value:42},{label:"Feb",value:78},{label:"Mar",value:55},{label:"Apr",value:91},{label:"May",value:63},{label:"Jun",value:84}],h=[{label:"Mon",value:1200},{label:"Tue",value:1850},{label:"Wed",value:1540},{label:"Thu",value:2100},{label:"Fri",value:1760},{label:"Sat",value:890},{label:"Sun",value:720}],b={route:"/components/charts",meta:{title:"Charts \u2014 Pulse Docs",description:"Server-rendered SVG charts for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>m({currentHref:"/components/charts",prev:g,next:f,name:"charts",description:"Server-rendered SVG charts \u2014 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.",content:`
2
-
3
- <h2 class="doc-h2" id="bar">Bar chart</h2>
4
- <p>Vertical bars with optional grid, value labels, and a zero baseline. All colour variants available.</p>
5
- ${e(t({data:c,color:"accent"}),`barChart({
6
- data: [
7
- { label: 'Jan', value: 42 },
8
- { label: 'Feb', value: 78 },
9
- { label: 'Mar', value: 55 },
10
- { label: 'Apr', value: 91 },
11
- { label: 'May', value: 63 },
12
- { label: 'Jun', value: 84 },
13
- ],
14
- color: 'accent',
15
- })`)}
16
-
17
- <h3 class="doc-h3">With value labels</h3>
18
- ${e(t({data:c,color:"success",showValues:!0}),"barChart({ data, color: 'success', showValues: true })")}
19
-
20
- <h3 class="doc-h3">Large dataset with tight gap</h3>
21
- ${e(t({data:h,color:"blue",gap:.15}),"barChart({ data: traffic, color: 'blue', gap: 0.15 })")}
22
-
23
- <h3 class="doc-h3">Negative values</h3>
24
- ${e(t({data:[{label:"Q1",value:24},{label:"Q2",value:-8},{label:"Q3",value:41},{label:"Q4",value:-15}],color:"warning",showValues:!0}),`barChart({
25
- data: [
26
- { label: 'Q1', value: 24 },
27
- { label: 'Q2', value: -8 },
28
- { label: 'Q3', value: 41 },
29
- { label: 'Q4', value: -15 },
30
- ],
31
- color: 'warning',
32
- showValues: true,
33
- })`)}
34
-
35
- <h2 class="doc-h2" id="line">Line chart</h2>
36
- <p>Connected data points with optional dots, area fill, and grid lines.</p>
37
- ${e(r({data:c,color:"accent"}),`lineChart({
38
- data: [
39
- { label: 'Jan', value: 42 },
40
- ...
41
- ],
42
- color: 'accent',
43
- })`)}
44
-
45
- <h3 class="doc-h3">With area fill</h3>
46
- ${e(r({data:c,color:"accent",area:!0}),"lineChart({ data, color: 'accent', area: true })")}
47
-
48
- <h3 class="doc-h3">No dots, area fill, success colour</h3>
49
- ${e(r({data:h,color:"success",area:!0,showDots:!1}),"lineChart({ data, color: 'success', area: true, showDots: false })")}
50
-
51
- <h2 class="doc-h2" id="donut">Donut chart</h2>
52
- <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>
53
- ${e('<div style="display:flex;justify-content:center">'+u({label:"73%",sublabel:"satisfied",data:[{label:"Satisfied",value:73,color:"success"},{label:"Neutral",value:18,color:"muted"},{label:"Unsatisfied",value:9,color:"error"}]})+"</div>",`donutChart({
54
- label: '73%',
55
- sublabel: 'satisfied',
56
- data: [
57
- { label: 'Satisfied', value: 73, color: 'success' },
58
- { label: 'Neutral', value: 18, color: 'muted' },
59
- { label: 'Unsatisfied', value: 9, color: 'error' },
60
- ],
61
- })`)}
62
-
63
- <h3 class="doc-h3">Thinner ring</h3>
64
- ${e('<div style="display:flex;justify-content:center">'+u({size:180,thickness:22,label:"4",sublabel:"segments",data:[{label:"A",value:40,color:"accent"},{label:"B",value:30,color:"blue"},{label:"C",value:20,color:"success"},{label:"D",value:10,color:"warning"}]})+"</div>",`donutChart({
65
- size: 180, thickness: 22,
66
- label: '4', sublabel: 'segments',
67
- data: [
68
- { label: 'A', value: 40, color: 'accent' },
69
- { label: 'B', value: 30, color: 'blue' },
70
- { label: 'C', value: 20, color: 'success' },
71
- { label: 'D', value: 10, color: 'warning' },
72
- ],
73
- })`)}
74
-
75
- <h2 class="doc-h2" id="sparkline">Sparkline</h2>
76
- <p>Minimal inline trend line \u2014 pass a plain array of numbers. Designed to sit alongside <code>stat()</code> tiles or inside table cells.</p>
77
- ${e('<div style="display:flex;gap:.75rem;align-items:center;flex-wrap:wrap">'+a({data:[12,18,14,22,19,28,24,31],color:"accent",area:!0})+a({data:[31,24,28,19,22,14,18,12],color:"error",area:!0})+a({data:[12,18,14,22,19,28,24,31],color:"success",area:!1})+"</div>",`sparkline({ data: [12,18,14,22,19,28,24,31], color: 'accent', area: true })
78
- sparkline({ data: [31,24,28,19,22,14,18,12], color: 'error', area: true })`)}
79
-
80
- <h2 class="doc-h2" id="composition">Composition</h2>
81
- <p>Charts compose with <code>card()</code>, <code>stat()</code>, <code>grid()</code> \u2014 drop any chart into any content slot.</p>
82
- ${e(i({cols:2,gap:"md",content:l({title:"Monthly signups",content:t({data:c,color:"accent",height:180})})+l({title:"Daily traffic",content:r({data:h,color:"blue",area:!0,height:180})})}),`grid({
83
- cols: 2,
84
- content:
85
- card({ title: 'Monthly signups', content: barChart({ data, height: 180 }) }) +
86
- card({ title: 'Daily traffic', content: lineChart({ data, color: 'blue', area: true, height: 180 }) }),
87
- })`)}
88
-
89
- <h3 class="doc-h3">Sparkline in stat tiles</h3>
90
- ${e(i({cols:3,gap:"md",content:l({content:n({label:"Revenue",value:"$18.2k",change:"+12%",trend:"up"})+`<div style="margin-top:.75rem">${a({data:[8,11,9,14,12,16,15,18],width:"100%",color:"success",area:!0})}</div>`})+l({content:n({label:"Users",value:"4,821",change:"+8.4%",trend:"up"})+`<div style="margin-top:.75rem">${a({data:[22,28,24,31,27,34,30,38],width:"100%",color:"accent",area:!0})}</div>`})+l({content:n({label:"Churn",value:"2.1%",change:"\u22120.3%",trend:"down"})+`<div style="margin-top:.75rem">${a({data:[8,6,7,5,6,4,5,3],width:"100%",color:"error",area:!0})}</div>`})}),`card({
91
- content: stat({ label: 'Revenue', value: '$18.2k', change: '+12%', trend: 'up' }) +
92
- \`<div style="margin-top:.75rem">\${sparkline({ data, color: 'success', area: true })}</div>\`,
93
- })`)}
94
-
95
- <h2 class="doc-h2" id="props">Props</h2>
96
-
97
- <h3 class="doc-h3">barChart()</h3>
98
- ${o(["Prop","Type","Default",""],[["<code>data</code>","array","\u2014","<code>{ label, value }[]</code>"],["<code>height</code>","number","220","SVG height in px"],["<code>color</code>","string","'accent'","accent \xB7 success \xB7 warning \xB7 error \xB7 blue \xB7 muted"],["<code>showValues</code>","boolean","false","Value labels above each bar"],["<code>showGrid</code>","boolean","true","Horizontal grid lines"],["<code>gap</code>","number","0.25","Gap between bars as fraction 0\u20130.9"]])}
99
-
100
- <h3 class="doc-h3" style="margin-top:2rem">lineChart()</h3>
101
- ${o(["Prop","Type","Default",""],[["<code>data</code>","array","\u2014","<code>{ label, value }[]</code>"],["<code>height</code>","number","220","SVG height in px"],["<code>color</code>","string","'accent'","accent \xB7 success \xB7 warning \xB7 error \xB7 blue \xB7 muted"],["<code>area</code>","boolean","false","Fill area under the line"],["<code>showDots</code>","boolean","true","Dots at each data point"],["<code>showGrid</code>","boolean","true","Horizontal grid lines"]])}
102
-
103
- <h3 class="doc-h3" style="margin-top:2rem">donutChart()</h3>
104
- ${o(["Prop","Type","Default",""],[["<code>data</code>","array","\u2014","<code>{ label, value, color? }[]</code> \u2014 color per segment"],["<code>size</code>","number","200","Diameter in px"],["<code>thickness</code>","number","40","Ring thickness in px"],["<code>label</code>","string","\u2014","Large centre text"],["<code>sublabel</code>","string","\u2014","Smaller text below centre label"]])}
105
-
106
- <h3 class="doc-h3" style="margin-top:2rem">sparkline()</h3>
107
- ${o(["Prop","Type","Default",""],[["<code>data</code>","number[]","\u2014","Plain array of numbers"],["<code>width</code>","number","80","SVG width in px"],["<code>height</code>","number","32","SVG height in px"],["<code>color</code>","string","'accent'","accent \xB7 success \xB7 warning \xB7 error \xB7 blue \xB7 muted"],["<code>area</code>","boolean","false","Fill area under the line"]])}
108
- `})};var s=document.getElementById("pulse-root");s&&!s.dataset.pulseMounted&&(s.dataset.pulseMounted="1",d(b,s,window.__PULSE_SERVER__||{},{ssr:!0}),v(s,d));var V=b;export{V as default};
@@ -1,54 +0,0 @@
1
- import{a as o,b as r}from"./runtime-ZJ4FXT5O.js";import{cb as e,ya as i}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as s,h as d,i as l}from"./runtime-L2HNXIHW.js";import{a,b as n}from"./runtime-B73WLANC.js";var{prev:m,next:h}=s("/components/checkbox"),c={route:"/components/checkbox",meta:{title:"Checkbox \u2014 Pulse Docs",description:"Custom-styled checkbox component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>r({currentHref:"/components/checkbox",prev:m,next:h,name:"checkbox",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.',content:`
2
-
3
- <h2 class="doc-h2" id="basic">Basic</h2>
4
- <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>
5
- ${o(e({name:"agree",label:"I agree to the terms"}),"checkbox({ name: 'agree', label: 'I agree to the terms' })",{col:!0})}
6
-
7
- <h2 class="doc-h2" id="checked">Checked</h2>
8
- ${o(e({name:"newsletter",label:"Send me updates",checked:!0}),"checkbox({ name: 'newsletter', label: 'Send me updates', checked: state.newsletter })",{col:!0})}
9
-
10
- <h2 class="doc-h2" id="hint">Hint</h2>
11
- <p>A <code>hint</code> string renders below the label as supporting copy.</p>
12
- ${o(e({name:"marketing",label:"Marketing emails",hint:"Product news and tips. Unsubscribe any time.",checked:!0}),`checkbox({
13
- name: 'marketing',
14
- label: 'Marketing emails',
15
- hint: 'Product news and tips. Unsubscribe any time.',
16
- checked: state.marketing,
17
- })`,{col:!0})}
18
-
19
- <h2 class="doc-h2" id="error">Error state</h2>
20
- <p>Pass <code>error</code> to show a validation message. The error is announced via <code>role="alert"</code>.</p>
21
- ${o(e({name:"terms",label:"I accept the terms and conditions",error:"You must accept the terms to continue."}),`checkbox({
22
- name: 'terms',
23
- label: 'I accept the terms and conditions',
24
- error: server.errors.terms,
25
- })`,{col:!0})}
26
-
27
- <h2 class="doc-h2" id="disabled">Disabled</h2>
28
- ${o(e({name:"feature",label:"Enable beta features",disabled:!0})+" "+e({name:"feature2",label:"Beta feature (on)",disabled:!0,checked:!0}),"checkbox({ name: 'feature', label: 'Enable beta features', disabled: true })",{col:!0})}
29
-
30
- <h2 class="doc-h2" id="group">Group in a fieldset</h2>
31
- <p>Compose multiple checkboxes inside a <a href="/components/fieldset">fieldset</a> for a semantic group.</p>
32
- ${o(i({legend:"Notifications",content:e({name:"notif",value:"email",label:"Email",checked:!0})+e({name:"notif",value:"sms",label:"SMS"})+e({name:"notif",value:"browser",label:"Browser push",checked:!0})+e({name:"notif",value:"weekly",label:"Weekly digest",disabled:!0})}),`fieldset({
33
- legend: 'Notifications',
34
- content:
35
- checkbox({ name: 'notif', value: 'email', label: 'Email', checked: true }) +
36
- checkbox({ name: 'notif', value: 'sms', label: 'SMS' }) +
37
- checkbox({ name: 'notif', value: 'browser', label: 'Browser push', checked: true }) +
38
- checkbox({ name: 'notif', value: 'weekly', label: 'Weekly digest', disabled: true }),
39
- })`,{col:!0})}
40
-
41
- <h2 class="doc-h2" id="in-forms">In forms</h2>
42
- ${l("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> \u2014 a <code>null</code> result means unchecked.`)}
43
-
44
- <h2 class="doc-h2" id="labelhtml">Custom label HTML</h2>
45
- <p>When the label needs inline styling \u2014 for example a strikethrough on a completed todo \u2014 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>
46
- ${o(e({name:"task",labelHtml:'<span style="text-decoration:line-through;opacity:.5">Buy milk</span>',checked:!0}),`checkbox({
47
- name: 'task',
48
- checked: todo.done,
49
- labelHtml: \`<span class="\${todo.done ? 'u-text-muted' : ''}">\${esc(todo.text)}</span>\`,
50
- })`,{col:!0})}
51
-
52
- <h2 class="doc-h2" id="props">Props</h2>
53
- ${d(["Prop","Type","Default",""],[["<code>name</code>","string","\u2014","Field name"],["<code>value</code>","string","\u2014",'Submitted value when checked (defaults to browser default <code>"on"</code>)'],["<code>label</code>","string","\u2014","Visible label text \u2014 escaped"],["<code>labelHtml</code>","string","\u2014","Raw HTML label slot \u2014 not escaped, use for styled spans"],["<code>checked</code>","boolean","false",""],["<code>disabled</code>","boolean","false",""],["<code>id</code>","string","\u2014","Override the auto-generated <code>id</code>"],["<code>event</code>","string","\u2014",'<code>data-event</code> binding, e.g. <code>"change:toggle"</code>'],["<code>hint</code>","string","\u2014","Helper text below the label"],["<code>error</code>","string","\u2014",'Validation error \u2014 announced via <code>role="alert"</code>'],["<code>class</code>","string","\u2014",""]])}
54
- `})};var t=document.getElementById("pulse-root");t&&!t.dataset.pulseMounted&&(t.dataset.pulseMounted="1",a(c,t,window.__PULSE_SERVER__||{},{ssr:!0}),n(t,a));var w=c;export{w as default};
@@ -1,9 +0,0 @@
1
- import{a as c,b as l}from"./runtime-ZJ4FXT5O.js";import{Ra as i,b as e}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as s,h as n}from"./runtime-L2HNXIHW.js";import{a as o,b as a}from"./runtime-B73WLANC.js";var{prev:p,next:d}=s("/components/cluster"),r={route:"/components/cluster",meta:{title:"Cluster \u2014 Pulse Docs",description:"Cluster component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>l({currentHref:"/components/cluster",prev:p,next:d,name:"cluster",description:"Flex row with wrapping. Groups inline elements horizontally \u2014 action buttons, badges, app store badges, stat rows.",content:`
2
- ${c(i({gap:"sm",content:e({label:"Performance"})+e({label:"Accessibility"})+e({label:"Zero JS",variant:"success"})+e({label:"SSR",variant:"info"})}),`cluster({ gap: 'sm', justify: 'center', content:
3
- badge({ label: 'Performance' }) +
4
- badge({ label: 'Zero JS', variant: 'success' }) +
5
- appBadge({ store: 'apple', href: url })
6
- })`)}
7
-
8
- ${n(["Prop","Type","Default",""],[["<code>content</code>","string (HTML)","\u2014","Raw HTML slot"],["<code>gap</code>","string","'md'","'xs' \xB7 'sm' \xB7 'md' \xB7 'lg'"],["<code>justify</code>","string","'start'","'start' \xB7 'center' \xB7 'end' \xB7 'between'"],["<code>align</code>","string","'center'","'start' \xB7 'center' \xB7 'end'"],["<code>wrap</code>","boolean","true","Set false to prevent wrapping"]])}
9
- `})};var t=document.getElementById("pulse-root");t&&!t.dataset.pulseMounted&&(t.dataset.pulseMounted="1",o(r,t,window.__PULSE_SERVER__||{},{ssr:!0}),a(t,o));var P=r;export{P as default};
@@ -1,20 +0,0 @@
1
- import{a as r,b as c}from"./runtime-ZJ4FXT5O.js";import"./runtime-UVPXO4IR.js";import{b as i}from"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as n,h as a}from"./runtime-L2HNXIHW.js";import{a as t,b as s}from"./runtime-B73WLANC.js";var{prev:l,next:p}=n("/components/code-window"),o={route:"/components/code-window",meta:{title:"Code Window \u2014 Pulse Docs",description:"macOS-style window chrome around a code block. Accepts pre-highlighted HTML as the content slot.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>c({currentHref:"/components/code-window",prev:l,next:p,name:"codeWindow",description:"macOS-style window chrome around a code block. Accepts pre-highlighted HTML as the content slot \u2014 the component handles all the chrome, layout, scrolling, and monospace typography.",content:`
2
- ${r(i({filename:"home.js",lang:"JavaScript",content:`<span style="color:var(--ui-accent)">export default</span> {
3
- <span style="color:var(--ui-text)">state</span>: { count: <span style="color:var(--ui-green)">0</span> },
4
-
5
- <span style="color:var(--ui-text)">view</span>: (state) =&gt; \`
6
- &lt;h1&gt;\${state.count}&lt;/h1&gt;
7
- &lt;button data-event=<span style="color:var(--ui-yellow)">"inc"</span>&gt;+&lt;/button&gt;
8
- \`,
9
-
10
- <span style="color:var(--ui-text)">mutations</span>: {
11
- inc: (state) =&gt; ({ count: state.count + <span style="color:var(--ui-green)">1</span> }),
12
- },
13
- }`}),`codeWindow({
14
- filename: 'home.js',
15
- lang: 'JavaScript',
16
- content: highlightedHtml, // pre-rendered HTML with syntax token spans
17
- })`)}
18
-
19
- ${a(["Prop","Type","Default",""],[["<code>content</code>","string (HTML)","\u2014","Raw HTML slot \u2014 pre-highlighted code HTML or plain text"],["<code>filename</code>","string","\u2014","Filename shown in the chrome bar (e.g. 'home.js')"],["<code>lang</code>","string","\u2014","Language label shown on the right of the chrome (e.g. 'JavaScript')"]])}
20
- `})};var e=document.getElementById("pulse-root");e&&!e.dataset.pulseMounted&&(e.dataset.pulseMounted="1",t(o,e,window.__PULSE_SERVER__||{},{ssr:!0}),s(e,t));var v=o;export{v as default};
@@ -1,5 +0,0 @@
1
- import{a as i,b as a}from"./runtime-ZJ4FXT5O.js";import{Na as p}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as r,h as n}from"./runtime-L2HNXIHW.js";import{a as t,b as s}from"./runtime-B73WLANC.js";var{prev:c,next:d}=r("/components/container"),o={route:"/components/container",meta:{title:"Container \u2014 Pulse Docs",description:"Container component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>a({currentHref:"/components/container",prev:c,next:d,name:"container",description:"Max-width wrapper with horizontal padding. The four size presets cover the most common layout widths.",content:`
2
- ${i(p({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"}),"container({ size: 'md', content: `\n ${hero({ title: 'Hello' })}\n ${grid({ cols: 3, content: features })}\n` })")}
3
-
4
- ${n(["Prop","Type","Default",""],[["<code>content</code>","string (HTML)","\u2014","Raw HTML slot"],["<code>size</code>","string","'lg'","'sm' (640px) \xB7 'md' (768px) \xB7 'lg' (1100px) \xB7 'xl' (1280px)"]])}
5
- `})};var e=document.getElementById("pulse-root");e&&!e.dataset.pulseMounted&&(e.dataset.pulseMounted="1",t(o,e,window.__PULSE_SERVER__||{},{ssr:!0}),s(e,t));var w=o;export{w as default};
@@ -1,11 +0,0 @@
1
- import{a as s,b as l}from"./runtime-ZJ4FXT5O.js";import{Za as c,a as o}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a,h as n}from"./runtime-L2HNXIHW.js";import{a as e,b as r}from"./runtime-B73WLANC.js";var{prev:d,next:p}=a("/components/cta"),i={route:"/components/cta",meta:{title:"CTA \u2014 Pulse Docs",description:"Call-to-action block with eyebrow, heading, body text, and an actions slot.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>l({currentHref:"/components/cta",prev:d,next:p,name:"cta",description:"Call-to-action block with eyebrow, heading, body text, and an actions slot. Sits inside <code>section()</code> + <code>container()</code> \u2014 adds no padding of its own.",content:`
2
- ${s(c({eyebrow:"Get started today",title:"Ready to build?",subtitle:"One spec file per page. SSR always on. Lighthouse 100 out of the box.",actions:o({label:"Start building \u2192",href:"#",variant:"primary",size:"lg"})+o({label:"View on GitHub",href:"#",variant:"ghost",size:"lg"})}),`cta({
3
- eyebrow: 'Get started today',
4
- title: 'Ready to build?',
5
- subtitle: 'One spec file per page. SSR always on. Lighthouse 100 out of the box.',
6
- actions: button({ label: 'Start building \u2192', href: '/docs', variant: 'primary', size: 'lg' }) +
7
- button({ label: 'View on GitHub', href: 'https://github.com/...', variant: 'ghost', size: 'lg' }),
8
- })`)}
9
-
10
- ${n(["Prop","Type","Default",""],[["<code>eyebrow</code>","string","\u2014","Small label above the heading"],["<code>title</code>","string","\u2014","Main heading"],["<code>level</code>","number","2","Heading tag for the title (1\u20136). Visual style is unchanged."],["<code>subtitle</code>","string","\u2014","Supporting paragraph"],["<code>actions</code>","string (HTML)","\u2014","Raw HTML slot \u2014 typically button() calls"],["<code>align</code>","string","'center'","'center' \xB7 'left'"]])}
11
- `})};var t=document.getElementById("pulse-root");t&&!t.dataset.pulseMounted&&(t.dataset.pulseMounted="1",e(i,t,window.__PULSE_SERVER__||{},{ssr:!0}),r(t,e));var S=i;export{S as default};
@@ -1,6 +0,0 @@
1
- import{a as s,b as l}from"./runtime-ZJ4FXT5O.js";import{Qa as p,Sa as o}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as i,h as n}from"./runtime-L2HNXIHW.js";import{a as t,b as d}from"./runtime-B73WLANC.js";var{prev:a,next:c}=i("/components/divider"),r={route:"/components/divider",meta:{title:"Divider \u2014 Pulse Docs",description:"Divider component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>l({currentHref:"/components/divider",prev:a,next:c,name:"divider",description:'Horizontal rule for visual separation. With a <code>label</code>, the line splits either side of the text \u2014 the classic "or" pattern between login options.',content:`
2
- ${s(p({gap:"lg",content:o()+o({label:"or continue with"})}),`divider()
3
- divider({ label: 'or continue with' })`)}
4
-
5
- ${n(["Prop","Type","Default",""],[["<code>label</code>","string","\u2014",'Optional centred text \u2014 renders as <code>&lt;div&gt;</code> with role="separator" when provided, <code>&lt;hr&gt;</code> otherwise']])}
6
- `})};var e=document.getElementById("pulse-root");e&&!e.dataset.pulseMounted&&(e.dataset.pulseMounted="1",t(r,e,window.__PULSE_SERVER__||{},{ssr:!0}),d(e,t));var x=r;export{x as default};
@@ -1,7 +0,0 @@
1
- import{a as s,b as i}from"./runtime-ZJ4FXT5O.js";import{Ea as a}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as r}from"./runtime-L2HNXIHW.js";import{a as e,b as n}from"./runtime-B73WLANC.js";var{prev:p,next:l}=r("/components/empty"),o={route:"/components/empty",meta:{title:"Empty \u2014 Pulse Docs",description:"Empty state component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>i({currentHref:"/components/empty",prev:p,next:l,name:"empty",description:"Empty state placeholder. Shows a centred title, optional description, and an optional call-to-action when there is nothing to display.",content:`
2
- ${s(a({title:"No results found",description:"Try adjusting your search or clearing the filters.",action:{label:"Clear filters",href:"#",variant:"secondary"}}),`empty({
3
- title: 'No results found',
4
- description: 'Try adjusting your search or clearing the filters.',
5
- action: { label: 'Clear filters', href: '/products', variant: 'secondary' },
6
- })`)}
7
- `})};var t=document.getElementById("pulse-root");t&&!t.dataset.pulseMounted&&(t.dataset.pulseMounted="1",e(o,t,window.__PULSE_SERVER__||{},{ssr:!0}),n(t,e));var g=o;export{g as default};
@@ -1,13 +0,0 @@
1
- import{a as o,b as p}from"./runtime-ZJ4FXT5O.js";import{Ia as e,K as n,ga as r,qa as s}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a,h as l}from"./runtime-L2HNXIHW.js";import{a as i,b as d}from"./runtime-B73WLANC.js";var{prev:u,next:f}=a("/components/feature"),c={route:"/components/feature",meta:{title:"Feature \u2014 Pulse Docs",description:"Feature component for Pulse UI.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>p({currentHref:"/components/feature",prev:u,next:f,name:"feature",description:'Icon + title + description block. Compose three or four in a CSS grid for the standard "why us" section.',content:`
2
- ${o('<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:2rem">'+e({icon:s({size:20}),title:"Instant load",description:"Streaming SSR ships HTML before data resolves. Fast by default."})+e({icon:n({size:20}),title:"Private by default",description:"No trackers. No third-party scripts. Ever."})+e({icon:r({size:20}),title:"Works offline",description:"Full functionality without a connection."})+"</div>",`import { iconZap, iconLock, iconPhone } from '@invisibleloop/pulse/ui'
3
-
4
- feature({ icon: iconZap({ size: 20 }), title: 'Instant load', description: 'Streaming SSR ships HTML before data resolves.' })
5
- feature({ icon: iconLock({ size: 20 }), title: 'Private by default', description: 'No trackers, ever.' })
6
- feature({ icon: iconPhone({ size: 20 }), title: 'Works offline', description: 'Full functionality without a connection.' })`)}
7
-
8
- ${o('<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:2rem">'+e({icon:s({size:20}),title:"Instant load",description:"Streaming SSR ships HTML before data resolves. Fast by default.",center:!0})+e({icon:n({size:20}),title:"Private by default",description:"No trackers. No third-party scripts. Ever.",center:!0})+e({icon:r({size:20}),title:"Works offline",description:"Full functionality without a connection.",center:!0})+"</div>",`feature({ icon: iconZap({ size: 20 }), title: 'Instant load', description: '...', center: true })
9
- feature({ icon: iconLock({ size: 20 }), title: 'Private by default', description: '...', center: true })
10
- feature({ icon: iconPhone({ size: 20 }), title: 'Works offline', description: '...', center: true })`)}
11
-
12
- ${l(["Prop","Type","Default",""],[["<code>icon</code>","string (HTML)","\u2014","Raw HTML slot \u2014 SVG or emoji; displayed in an accent-tinted box"],["<code>title</code>","string","\u2014",""],["<code>level</code>","number","3","Heading tag for the title (1\u20136). Visual style is unchanged."],["<code>description</code>","string","\u2014",""],["<code>center</code>","boolean","false","Centre-align the icon, title, and description"]])}
13
- `})};var t=document.getElementById("pulse-root");t&&!t.dataset.pulseMounted&&(t.dataset.pulseMounted="1",i(c,t,window.__PULSE_SERVER__||{},{ssr:!0}),d(t,i));var z=c;export{z as default};
@@ -1,19 +0,0 @@
1
- import{a as i,b as d}from"./runtime-ZJ4FXT5O.js";import{Aa as c,Pa as m,a as u,d as t,ya as o}from"./runtime-UVPXO4IR.js";import"./runtime-VMJA3Z4N.js";import"./runtime-QFURDKA2.js";import{a as s,h as l}from"./runtime-L2HNXIHW.js";import{a as r,b as n}from"./runtime-B73WLANC.js";var{prev:p,next:f}=s("/components/fieldset"),a={route:"/components/fieldset",meta:{title:"Fieldset \u2014 Pulse Docs",description:"Semantic grouping of related form fields with an accessible legend.",styles:["/pulse-ui.css","/docs.css"]},state:{},view:()=>d({currentHref:"/components/fieldset",prev:p,next:f,name:"fieldset",description:'Wraps related fields in a semantic <code>&lt;fieldset&gt;</code> with a styled <code>&lt;legend&gt;</code>. Screen readers announce the legend when focus enters the group \u2014 use it whenever fields belong together (address, card details, contact info). Works naturally inside a <code>&lt;form data-action="..."&gt;</code>.',content:`
2
- ${i('<form class="u-flex u-flex-col u-gap-4">'+o({legend:"Your details",content:m({cols:2,gap:"md",content:t({name:"first",label:"First name",required:!0})+t({name:"last",label:"Last name",required:!0})})+t({name:"email",label:"Email address",type:"email",required:!0})})+o({legend:"Message",content:c({name:"message",label:"Tell us about your project",rows:4,required:!0})})+u({label:"Send message",type:"submit",variant:"primary",fullWidth:!0})+"</form>",`import { fieldset, grid, input, textarea, button } from '@invisibleloop/pulse/ui'
3
-
4
- \`<form data-action="submit" class="u-flex u-flex-col u-gap-4">
5
- \${fieldset({ legend: 'Your details', content: \`
6
- \${grid({ cols: 2, gap: 'md', content: \`
7
- \${input({ name: 'first', label: 'First name', required: true })}
8
- \${input({ name: 'last', label: 'Last name', required: true })}
9
- \` })}
10
- \${input({ name: 'email', label: 'Email address', type: 'email', required: true })}
11
- \` })}
12
- \${fieldset({ legend: 'Message', content: \`
13
- \${textarea({ name: 'message', label: 'Tell us about your project', rows: 4, required: true })}
14
- \` })}
15
- \${button({ label: 'Send message', type: 'submit', variant: 'primary', fullWidth: true })}
16
- </form>\``)}
17
-
18
- ${l(["Prop","Type","Default",""],[["<code>legend</code>","string","\u2014","Group label \u2014 rendered as <code>&lt;legend&gt;</code>, announced by screen readers on focus"],["<code>content</code>","string","\u2014","Raw HTML slot \u2014 input(), select(), textarea(), grid(), etc."],["<code>gap</code>","string","md","Vertical gap between fields: xs / sm / md / lg"],["<code>class</code>","string","\u2014","Extra classes on the <code>&lt;fieldset&gt;</code> element"]])}
19
- `})};var e=document.getElementById("pulse-root");e&&!e.dataset.pulseMounted&&(e.dataset.pulseMounted="1",r(a,e,window.__PULSE_SERVER__||{},{ssr:!0}),n(e,r));var v=a;export{v as default};