@invisibleloop/pulse 0.20.11 → 0.20.20
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.
- package/package.json +6 -5
- package/public/.pulse-ui-version +1 -1
- package/scripts/build.js +26 -0
- package/scripts/release-version.js +17 -8
- package/scripts/strip-server.test.js +60 -0
- package/src/agent/checklist.md +8 -12
- package/src/agent/commands/pulse-start.md +2 -0
- package/src/agent/commands/verify.md +30 -8
- package/src/agent/guide-components.md +7 -25
- package/src/agent/guide-routing.md +0 -12
- package/src/agent/guide-server.md +102 -1
- package/src/agent/guide-spec.md +8 -1
- package/src/agent/guide-styles.md +23 -0
- package/src/agent/identity.md +9 -0
- package/src/agent/workflow.md +4 -23
- package/src/cli/check-bundles.js +113 -0
- package/src/cli/check-bundles.test.js +137 -0
- package/src/cli/cli.test.js +105 -0
- package/src/cli/dev.js +48 -3
- package/src/cli/diagnose.js +105 -0
- package/src/cli/diagnose.test.js +124 -0
- package/src/cli/discover.js +9 -2
- package/src/cli/index.js +171 -9
- package/src/cli/process-utils.js +57 -0
- package/src/cli/process-utils.test.js +114 -0
- package/src/cli/review.js +391 -0
- package/src/cli/review.test.js +143 -0
- package/src/cli/scaffold.js +9 -4
- package/src/cli/stamp.js +102 -0
- package/src/cli/stamp.test.js +149 -0
- package/src/cli/start.js +15 -2
- package/src/cli/validate.js +184 -0
- package/src/cli/validate.test.js +153 -0
- package/src/mcp/mcp.test.js +261 -30
- package/src/mcp/server.js +207 -515
- package/src/mcp/validate-worker.js +18 -1
- package/src/runtime/index.js +144 -11
- package/src/runtime/runtime.test.js +199 -0
- package/src/runtime/ssr.js +13 -6
- package/src/runtime/ssr.test.js +31 -0
- package/src/server/index.js +162 -9
- package/src/server/server.test.js +225 -2
- package/src/spec/schema.js +1 -1
- package/src/ui/index.js +0 -5
- package/src/ui/ui.test.js +0 -75
- package/types/ui.d.ts +0 -21
- package/.claude/commands/build-page.md +0 -63
- package/.claude/commands/new-doc-page.md +0 -45
- package/.claude/commands/pulse-start.md +0 -11
- package/.claude/commands/pulse-stop.md +0 -5
- package/.claude/commands/verify.md +0 -118
- package/.claude/pulse-checklist.md +0 -189
- package/.github/workflows/ci.yml +0 -25
- package/.github/workflows/publish.yml +0 -45
- package/.pulse/load-reports/home/1773432711417.json +0 -22
- package/.pulse-verified +0 -1
- package/AGENTS.md +0 -697
- package/CLAUDE.md +0 -697
- package/README.md +0 -95
- package/benchmark/public/dist/counter.boot-PO6SNSJZ.js +0 -8
- package/benchmark/public/dist/home.boot-YK6VAEQI.js +0 -6
- package/benchmark/public/dist/manifest.json +0 -5
- package/benchmark/public/dist/runtime-5Y7ESAIB.js +0 -2
- package/benchmark/public/dist/runtime-KO4BHUQ3.js +0 -49
- package/benchmark/results/2026-03-27-09-20.json +0 -188
- package/benchmark/results/2026-03-27-09-21.json +0 -188
- package/benchmark/results/2026-03-27-09-29.json +0 -188
- package/benchmark/results/2026-03-27-10-14.json +0 -188
- package/benchmark/results/2026-03-27-10-18.json +0 -232
- package/benchmark/src/pages/counter.js +0 -37
- package/benchmark/src/pages/home.js +0 -21
- package/docs/.claude/commands/pulse-build.md +0 -7
- package/docs/.claude/commands/pulse-dev.md +0 -7
- package/docs/.claude/commands/pulse-start.md +0 -9
- package/docs/.claude/commands/pulse-stop.md +0 -5
- package/docs/.claude/commands/verify.md +0 -84
- package/docs/.claude/coverage-check.js +0 -196
- package/docs/.claude/pulse-checklist.md +0 -189
- package/docs/public/.pulse-ui-version +0 -1
- package/docs/public/andypixel.css +0 -237
- package/docs/public/bookworms.css +0 -422
- package/docs/public/coutumes.css +0 -561
- package/docs/public/docs.css +0 -2388
- package/docs/public/favicon.svg +0 -4
- package/docs/public/home-brut.css +0 -982
- package/docs/public/images/bookworms/hero-books.jpg +0 -0
- package/docs/public/images/bookworms/how-we-read-now.jpg +0 -0
- package/docs/public/images/bookworms/lantern-keepers.jpg +0 -0
- package/docs/public/images/bookworms/provincial-bookseller.jpg +0 -0
- package/docs/public/images/journey/178.jpg +0 -0
- package/docs/public/images/journey/29.jpg +0 -0
- package/docs/public/images/retrowheels/hero.jpg +0 -0
- package/docs/public/images/shop/devbook-pro.jpg +0 -0
- package/docs/public/images/suzukibento/1015.jpg +0 -0
- package/docs/public/images/suzukibento/1025.jpg +0 -0
- package/docs/public/images/suzukibento/1043.jpg +0 -0
- package/docs/public/images/suzukibento/1059.jpg +0 -0
- package/docs/public/images/suzukibento/1062.jpg +0 -0
- package/docs/public/images/suzukibento/1084.jpg +0 -0
- package/docs/public/images/swish/1469334031218-e382a71b716b.jpg +0 -0
- package/docs/public/images/swish/1483985988355-763728e1935b.jpg +0 -0
- package/docs/public/images/swish/1485518882345-15568b007407.jpg +0 -0
- package/docs/public/images/swish/1490481651871-ab68de25d43d.jpg +0 -0
- package/docs/public/images/swish/1496747611176-843222e1e57c.jpg +0 -0
- package/docs/public/images/swish/1502716119720-b23a93e5fe1b.jpg +0 -0
- package/docs/public/images/swish/1539109136881-3be0616acf4b.jpg +0 -0
- package/docs/public/images/swish/1551803091-e20673f15770.jpg +0 -0
- package/docs/public/images/swish/1558769132-cb1aea458c5e.jpg +0 -0
- package/docs/public/images/swish/1572804013309-59a88b7e92f1.jpg +0 -0
- package/docs/public/img/heic1501a.jpg +0 -0
- package/docs/public/img/placeholder-landscape.svg +0 -18
- package/docs/public/img/placeholder-square.svg +0 -14
- package/docs/public/img/placeholder-tall.svg +0 -22
- package/docs/public/journey.css +0 -528
- package/docs/public/menu.js +0 -327
- package/docs/public/pulse-ui.css +0 -3028
- package/docs/public/pulse-ui.js +0 -257
- package/docs/public/retrowheels.css +0 -425
- package/docs/public/shop.css +0 -269
- package/docs/public/sparkys.css +0 -382
- package/docs/public/suzukibento.css +0 -517
- package/docs/public/swish.css +0 -394
- package/docs/public/theme.css +0 -52
- package/docs/public/themes/lumio.css +0 -50
- package/docs/public/themes/observatory.css +0 -104
- package/docs/server.js +0 -161
- package/docs/src/lib/component-page.js +0 -49
- package/docs/src/lib/highlight.js +0 -2
- package/docs/src/lib/layout.js +0 -190
- package/docs/src/lib/metrics-store.js +0 -6
- package/docs/src/lib/nav.js +0 -171
- package/docs/src/lib/stats.js +0 -81
- package/docs/src/pages/accessibility.js +0 -157
- package/docs/src/pages/actions.js +0 -194
- package/docs/src/pages/auth.js +0 -176
- package/docs/src/pages/caching.js +0 -95
- package/docs/src/pages/components/accordion.js +0 -48
- package/docs/src/pages/components/alert.js +0 -35
- package/docs/src/pages/components/app-badge.js +0 -41
- package/docs/src/pages/components/avatar.js +0 -35
- package/docs/src/pages/components/badge.js +0 -36
- package/docs/src/pages/components/breadcrumbs.js +0 -94
- package/docs/src/pages/components/button.js +0 -84
- package/docs/src/pages/components/card.js +0 -225
- package/docs/src/pages/components/charts.js +0 -283
- package/docs/src/pages/components/checkbox.js +0 -129
- package/docs/src/pages/components/cluster.js +0 -47
- package/docs/src/pages/components/container.js +0 -40
- package/docs/src/pages/components/cta.js +0 -54
- package/docs/src/pages/components/divider.js +0 -37
- package/docs/src/pages/components/empty.js +0 -36
- package/docs/src/pages/components/feature.js +0 -60
- package/docs/src/pages/components/fieldset.js +0 -65
- package/docs/src/pages/components/fileupload.js +0 -128
- package/docs/src/pages/components/footer.js +0 -58
- package/docs/src/pages/components/grid.js +0 -169
- package/docs/src/pages/components/heading.js +0 -107
- package/docs/src/pages/components/hero.js +0 -123
- package/docs/src/pages/components/icons.js +0 -410
- package/docs/src/pages/components/image.js +0 -71
- package/docs/src/pages/components/input.js +0 -51
- package/docs/src/pages/components/media.js +0 -51
- package/docs/src/pages/components/modal.js +0 -111
- package/docs/src/pages/components/nav.js +0 -136
- package/docs/src/pages/components/phone-frame.js +0 -74
- package/docs/src/pages/components/progress.js +0 -102
- package/docs/src/pages/components/prose.js +0 -111
- package/docs/src/pages/components/pullquote.js +0 -71
- package/docs/src/pages/components/radio.js +0 -194
- package/docs/src/pages/components/rating.js +0 -106
- package/docs/src/pages/components/search.js +0 -61
- package/docs/src/pages/components/section.js +0 -98
- package/docs/src/pages/components/segmented.js +0 -121
- package/docs/src/pages/components/select.js +0 -45
- package/docs/src/pages/components/slider.js +0 -115
- package/docs/src/pages/components/spinner.js +0 -73
- package/docs/src/pages/components/stack.js +0 -48
- package/docs/src/pages/components/stat.js +0 -55
- package/docs/src/pages/components/stepper.js +0 -66
- package/docs/src/pages/components/table.js +0 -45
- package/docs/src/pages/components/textarea.js +0 -31
- package/docs/src/pages/components/toggle.js +0 -84
- package/docs/src/pages/components/tooltip.js +0 -48
- package/docs/src/pages/components.js +0 -200
- package/docs/src/pages/config.js +0 -193
- package/docs/src/pages/constraints.js +0 -100
- package/docs/src/pages/deploy.js +0 -233
- package/docs/src/pages/error-pages.js +0 -99
- package/docs/src/pages/extending.js +0 -198
- package/docs/src/pages/faq.js +0 -99
- package/docs/src/pages/forms.js +0 -129
- package/docs/src/pages/getting-started.js +0 -147
- package/docs/src/pages/guard.js +0 -120
- package/docs/src/pages/home.js +0 -350
- package/docs/src/pages/how-it-works.js +0 -244
- package/docs/src/pages/hydration.js +0 -108
- package/docs/src/pages/images.js +0 -120
- package/docs/src/pages/markdown.js +0 -156
- package/docs/src/pages/meta.js +0 -193
- package/docs/src/pages/mutations.js +0 -107
- package/docs/src/pages/navigation.js +0 -85
- package/docs/src/pages/performance.js +0 -157
- package/docs/src/pages/persist.js +0 -89
- package/docs/src/pages/project-structure.js +0 -91
- package/docs/src/pages/prompt-examples.js +0 -186
- package/docs/src/pages/raw-responses.js +0 -122
- package/docs/src/pages/routing.js +0 -120
- package/docs/src/pages/server-api.js +0 -291
- package/docs/src/pages/server-data.js +0 -203
- package/docs/src/pages/slash-commands.js +0 -55
- package/docs/src/pages/spec.js +0 -207
- package/docs/src/pages/state.js +0 -102
- package/docs/src/pages/store.js +0 -203
- package/docs/src/pages/streaming.js +0 -107
- package/docs/src/pages/stripe.js +0 -194
- package/docs/src/pages/supabase.js +0 -324
- package/docs/src/pages/templates/andypixel.js +0 -260
- package/docs/src/pages/templates/blog-post.js +0 -226
- package/docs/src/pages/templates/bookworms.js +0 -227
- package/docs/src/pages/templates/coutumes.js +0 -237
- package/docs/src/pages/templates/journey.js +0 -186
- package/docs/src/pages/templates/mobile-app.js +0 -371
- package/docs/src/pages/templates/retrowheels.js +0 -355
- package/docs/src/pages/templates/shop.js +0 -268
- package/docs/src/pages/templates/sparkys.js +0 -264
- package/docs/src/pages/templates/suzukibento.js +0 -200
- package/docs/src/pages/templates/swish.js +0 -313
- package/docs/src/pages/templates.js +0 -534
- package/docs/src/pages/testing.js +0 -199
- package/docs/src/pages/validation.js +0 -138
- package/examples/.claude/commands/pulse-build.md +0 -7
- package/examples/.claude/commands/pulse-dev.md +0 -7
- package/examples/.claude/commands/pulse-start.md +0 -9
- package/examples/.claude/commands/pulse-stop.md +0 -5
- package/examples/.claude/commands/verify.md +0 -84
- package/examples/.claude/coverage-check.js +0 -196
- package/examples/.claude/pulse-checklist.md +0 -189
- package/examples/andypixel.css +0 -237
- package/examples/andypixel.js +0 -258
- package/examples/bookworms.css +0 -422
- package/examples/bookworms.js +0 -225
- package/examples/contact.js +0 -166
- package/examples/counter.js +0 -94
- package/examples/dev.server.js +0 -110
- package/examples/examples.test.js +0 -394
- package/examples/journey.css +0 -528
- package/examples/journey.js +0 -186
- package/examples/pricing.js +0 -262
- package/examples/products.js +0 -190
- package/examples/public/.pulse-ui-version +0 -1
- package/examples/public/pulse-ui.css +0 -3028
- package/examples/public/pulse-ui.js +0 -257
- package/examples/quiz.js +0 -208
- package/examples/retrowheels.css +0 -425
- package/examples/retrowheels.js +0 -353
- package/examples/shared.js +0 -84
- package/examples/suzukibento.css +0 -513
- package/examples/suzukibento.js +0 -200
- package/examples/swish.css +0 -394
- package/examples/swish.js +0 -311
- package/examples/todos.js +0 -162
- package/src/ui/fieldset.js +0 -37
- package/src/ui/phone-frame.js +0 -40
- package/src/ui/search.js +0 -78
- package/src/ui/segmented.js +0 -50
- package/src/ui/tooltip.js +0 -28
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { renderLayout, h1, lead, section, sub, codeBlock, callout, table } from '../lib/layout.js'
|
|
2
|
-
import { prevNext } from '../lib/nav.js'
|
|
3
|
-
import { highlight } from '../lib/highlight.js'
|
|
4
|
-
|
|
5
|
-
const { prev, next } = prevNext('/caching')
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
route: '/caching',
|
|
9
|
-
meta: {
|
|
10
|
-
theme: 'light',
|
|
11
|
-
title: 'Caching — Pulse Docs',
|
|
12
|
-
description: 'HTTP cache headers, in-process server data caching, and asset caching in Pulse.',
|
|
13
|
-
styles: ['/theme.css', '/docs.css'],
|
|
14
|
-
},
|
|
15
|
-
view: () => renderLayout({
|
|
16
|
-
currentHref: '/caching',
|
|
17
|
-
prev,
|
|
18
|
-
next,
|
|
19
|
-
content: `
|
|
20
|
-
${h1('Caching')}
|
|
21
|
-
${lead('Pulse handles asset caching automatically — production bundles are content-hashed and served with immutable cache headers. Page caching is controlled declaratively in the spec: <code>serverTtl</code> for in-process data, <code>cache</code> for HTTP headers. Nothing is cached by default unless you declare it.')}
|
|
22
|
-
|
|
23
|
-
${section('server-ttl', 'serverTtl — in-process data cache')}
|
|
24
|
-
<p><code>serverTtl</code> is a number of seconds to cache the result of <code>server.data()</code> in memory. Subsequent requests within the TTL window skip the async data fetch entirely and serve the cached result.</p>
|
|
25
|
-
${codeBlock(highlight(`export default {
|
|
26
|
-
route: '/homepage',
|
|
27
|
-
serverTtl: 60, // cache server data for 60 seconds
|
|
28
|
-
server: {
|
|
29
|
-
data: async () => ({
|
|
30
|
-
featured: await db.products.getFeatured(),
|
|
31
|
-
stats: await analytics.getGlobalStats(),
|
|
32
|
-
}),
|
|
33
|
-
},
|
|
34
|
-
}`, 'js'))}
|
|
35
|
-
${table(
|
|
36
|
-
['Value', 'Behaviour'],
|
|
37
|
-
[
|
|
38
|
-
['<code>undefined</code> (default)', 'No caching — <code>server.data()</code> runs on every request'],
|
|
39
|
-
['<code>0</code>', 'No caching (same as undefined)'],
|
|
40
|
-
['<code>60</code>', 'Cache for 60 seconds — at most one database hit per minute'],
|
|
41
|
-
['<code>3600</code>', 'Cache for 1 hour'],
|
|
42
|
-
]
|
|
43
|
-
)}
|
|
44
|
-
${callout('note', 'The in-process cache is per-process and per-route. It is not shared across multiple server instances. Use a distributed cache (Redis, etc.) for cross-instance consistency.')}
|
|
45
|
-
${callout('warning', 'In development, setting a long <code>serverTtl</code> can mask stale data. Set it to <code>0</code> or omit it during development, and add it when deploying to production.')}
|
|
46
|
-
|
|
47
|
-
${section('http-cache', 'cache — HTTP response headers')}
|
|
48
|
-
<p>The <code>cache</code> field controls the <code>Cache-Control</code> header sent with the page HTML response. This tells browsers and CDNs how to cache the response.</p>
|
|
49
|
-
${codeBlock(highlight(`export default {
|
|
50
|
-
route: '/blog/:slug',
|
|
51
|
-
cache: {
|
|
52
|
-
public: true, // allow CDN/proxy caching
|
|
53
|
-
maxAge: 300, // cache for 5 minutes
|
|
54
|
-
staleWhileRevalidate: 86400, // serve stale for up to 24 hours while revalidating
|
|
55
|
-
},
|
|
56
|
-
// ...
|
|
57
|
-
}`, 'js'))}
|
|
58
|
-
|
|
59
|
-
${section('cache-fields', 'Cache field reference')}
|
|
60
|
-
${table(
|
|
61
|
-
['Field', 'Type', 'Description'],
|
|
62
|
-
[
|
|
63
|
-
['<code>public</code>', '<code>boolean</code>', 'If true, emits <code>public</code> — allows CDN/proxy caching. Default: <code>private</code>.'],
|
|
64
|
-
['<code>maxAge</code>', '<code>number</code>', 'Seconds before the response is considered stale. Emits <code>max-age=N</code>.'],
|
|
65
|
-
['<code>staleWhileRevalidate</code>', '<code>number</code>', 'Seconds to serve stale content while revalidating in the background. Emits <code>stale-while-revalidate=N</code>.'],
|
|
66
|
-
]
|
|
67
|
-
)}
|
|
68
|
-
${codeBlock(highlight(`// private page — user-specific content
|
|
69
|
-
cache: { public: false, maxAge: 0 }
|
|
70
|
-
// → Cache-Control: private, no-store
|
|
71
|
-
|
|
72
|
-
// public marketing page — cached at CDN
|
|
73
|
-
cache: { public: true, maxAge: 3600, staleWhileRevalidate: 86400 }
|
|
74
|
-
// → Cache-Control: public, max-age=3600, stale-while-revalidate=86400`, 'js'))}
|
|
75
|
-
|
|
76
|
-
${section('html-default', 'Default HTML caching')}
|
|
77
|
-
<p>By default, Pulse sends <code>Cache-Control: no-store</code> for all HTML responses. Users always see fresh content — stale HTML is never served from browser or proxy caches unless you explicitly declare a <code>cache</code> policy in the spec.</p>
|
|
78
|
-
|
|
79
|
-
${section('asset-caching', 'Asset caching')}
|
|
80
|
-
<p>Static assets in <code>public/</code> receive <code>Cache-Control: max-age=3600</code> (one hour).</p>
|
|
81
|
-
<p>Production bundles in <code>public/dist/</code> receive <code>Cache-Control: public, max-age=31536000, immutable</code> (one year, immutable). This is guaranteed safe because bundle filenames include a content hash — code changes produce a new hash, and browsers fetch the updated file automatically. There is nothing to configure.</p>
|
|
82
|
-
|
|
83
|
-
${section('dev-vs-prod', 'Development vs production')}
|
|
84
|
-
${table(
|
|
85
|
-
['Resource', 'Development', 'Production'],
|
|
86
|
-
[
|
|
87
|
-
['HTML pages', '<code>no-store</code>', '<code>no-store</code> (or your <code>cache</code> config)'],
|
|
88
|
-
['Static assets (<code>/public/*</code>)', '<code>max-age=3600</code>', '<code>max-age=3600</code>'],
|
|
89
|
-
['JS bundles (<code>/dist/*</code>)', 'N/A (source files served directly)', '<code>immutable, max-age=31536000</code>'],
|
|
90
|
-
]
|
|
91
|
-
)}
|
|
92
|
-
${callout('tip', 'For maximum performance, combine <code>serverTtl</code> for expensive database queries with a short <code>cache.maxAge</code> and a generous <code>cache.staleWhileRevalidate</code>. Users get fast responses; data stays reasonably fresh.')}
|
|
93
|
-
`,
|
|
94
|
-
}),
|
|
95
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
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 { accordion } from '../../../../src/ui/index.js'
|
|
5
|
-
|
|
6
|
-
const { prev, next } = prevNext('/components/accordion')
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
route: '/components/accordion',
|
|
10
|
-
meta: {
|
|
11
|
-
theme: 'light',
|
|
12
|
-
title: 'Accordion — Pulse Docs',
|
|
13
|
-
description: 'Accordion component for Pulse UI.',
|
|
14
|
-
styles: ['/pulse-ui.css', '/theme.css', '/docs.css'],
|
|
15
|
-
},
|
|
16
|
-
view: () => renderComponentPage({
|
|
17
|
-
currentHref: '/components/accordion',
|
|
18
|
-
prev,
|
|
19
|
-
next,
|
|
20
|
-
name: 'accordion',
|
|
21
|
-
description: 'Collapsible FAQ items built on native <code><details></code>/<code><summary></code> — no JavaScript required. The open/close animation is handled entirely by the browser.',
|
|
22
|
-
content: `
|
|
23
|
-
${demo(
|
|
24
|
-
accordion({
|
|
25
|
-
items: [
|
|
26
|
-
{ question: 'Is there a free plan?', answer: 'Yes — the free plan includes up to 3 pages and community support, with no credit card required.' },
|
|
27
|
-
{ question: 'Can I cancel anytime?', answer: 'Absolutely. There are no contracts or lock-in periods. Cancel from your account settings at any time.' },
|
|
28
|
-
{ question: 'Does it work on older devices?', answer: 'The app supports iOS 14+ and Android 8+, covering over 97% of active devices.' },
|
|
29
|
-
],
|
|
30
|
-
}),
|
|
31
|
-
`accordion({
|
|
32
|
-
items: [
|
|
33
|
-
{ question: 'Is there a free plan?', answer: 'Yes — up to 3 pages, no card required.' },
|
|
34
|
-
{ question: 'Can I cancel anytime?', answer: 'No contracts. Cancel from your account.' },
|
|
35
|
-
{ question: 'Works on older devices?', answer: 'iOS 14+ and Android 8+.' },
|
|
36
|
-
],
|
|
37
|
-
})`
|
|
38
|
-
)}
|
|
39
|
-
|
|
40
|
-
${table(
|
|
41
|
-
['Prop', 'Type', 'Default', 'Description'],
|
|
42
|
-
[
|
|
43
|
-
['<code>items</code>', 'array', '[]', '<code>{ question: string, answer: string }[]</code>'],
|
|
44
|
-
]
|
|
45
|
-
)}
|
|
46
|
-
`,
|
|
47
|
-
}),
|
|
48
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { renderComponentPage, demo } from '../../lib/component-page.js'
|
|
2
|
-
import { prevNext } from '../../lib/nav.js'
|
|
3
|
-
import { alert } from '../../../../src/ui/index.js'
|
|
4
|
-
|
|
5
|
-
const { prev, next } = prevNext('/components/alert')
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
route: '/components/alert',
|
|
9
|
-
meta: {
|
|
10
|
-
theme: 'light',
|
|
11
|
-
title: 'Alert — Pulse Docs',
|
|
12
|
-
description: 'Alert component for Pulse UI.',
|
|
13
|
-
styles: ['/pulse-ui.css', '/theme.css', '/docs.css'],
|
|
14
|
-
},
|
|
15
|
-
view: () => renderComponentPage({
|
|
16
|
-
currentHref: '/components/alert',
|
|
17
|
-
prev,
|
|
18
|
-
next,
|
|
19
|
-
name: 'alert',
|
|
20
|
-
description: '<code>error</code> and <code>warning</code> use <code>role="alert"</code> — screen readers announce them immediately. <code>info</code> and <code>success</code> use <code>role="status"</code> for a polite announcement.',
|
|
21
|
-
content: `
|
|
22
|
-
${demo(
|
|
23
|
-
alert({ variant: 'info', content: 'Your account is pending email verification.' }) +
|
|
24
|
-
alert({ variant: 'success', title: 'Saved', content: 'Your changes have been saved.' }) +
|
|
25
|
-
alert({ variant: 'warning', title: 'Heads up', content: 'This action cannot be undone.' }) +
|
|
26
|
-
alert({ variant: 'error', title: 'Failed', content: 'Something went wrong. Please try again.' }),
|
|
27
|
-
`alert({ variant: 'info', content: 'Your account is pending email verification.' })
|
|
28
|
-
alert({ variant: 'success', title: 'Saved', content: 'Your changes have been saved.' })
|
|
29
|
-
alert({ variant: 'warning', title: 'Heads up', content: 'This action cannot be undone.' })
|
|
30
|
-
alert({ variant: 'error', title: 'Failed', content: escHtml(server.error) })`,
|
|
31
|
-
{ col: true }
|
|
32
|
-
)}
|
|
33
|
-
`,
|
|
34
|
-
}),
|
|
35
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
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 { appBadge } from '../../../../src/ui/index.js'
|
|
5
|
-
|
|
6
|
-
const { prev, next } = prevNext('/components/app-badge')
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
route: '/components/app-badge',
|
|
10
|
-
meta: {
|
|
11
|
-
theme: 'light',
|
|
12
|
-
title: 'App Badge — Pulse Docs',
|
|
13
|
-
description: 'App Badge component for Pulse UI.',
|
|
14
|
-
styles: ['/pulse-ui.css', '/theme.css', '/docs.css'],
|
|
15
|
-
},
|
|
16
|
-
view: () => renderComponentPage({
|
|
17
|
-
currentHref: '/components/app-badge',
|
|
18
|
-
prev,
|
|
19
|
-
next,
|
|
20
|
-
name: 'appBadge',
|
|
21
|
-
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.',
|
|
22
|
-
content: `
|
|
23
|
-
${demo(
|
|
24
|
-
`<div style="display:flex;gap:.75rem;flex-wrap:wrap">` +
|
|
25
|
-
appBadge({ store: 'apple', href: '#' }) +
|
|
26
|
-
appBadge({ store: 'google', href: '#' }) +
|
|
27
|
-
`</div>`,
|
|
28
|
-
`appBadge({ store: 'apple', href: appStoreUrl })
|
|
29
|
-
appBadge({ store: 'google', href: playStoreUrl })`
|
|
30
|
-
)}
|
|
31
|
-
|
|
32
|
-
${table(
|
|
33
|
-
['Prop', 'Type', 'Default', 'Description'],
|
|
34
|
-
[
|
|
35
|
-
['<code>store</code>', 'string', "'apple'", "'apple' or 'google'"],
|
|
36
|
-
['<code>href</code>', 'string', "'#'", 'Link to the app store listing'],
|
|
37
|
-
]
|
|
38
|
-
)}
|
|
39
|
-
`,
|
|
40
|
-
}),
|
|
41
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { renderComponentPage, demo } from '../../lib/component-page.js'
|
|
2
|
-
import { prevNext } from '../../lib/nav.js'
|
|
3
|
-
import { avatar } from '../../../../src/ui/index.js'
|
|
4
|
-
|
|
5
|
-
const { prev, next } = prevNext('/components/avatar')
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
route: '/components/avatar',
|
|
9
|
-
meta: {
|
|
10
|
-
theme: 'light',
|
|
11
|
-
title: 'Avatar — Pulse Docs',
|
|
12
|
-
description: 'Avatar component for Pulse UI.',
|
|
13
|
-
styles: ['/pulse-ui.css', '/theme.css', '/docs.css'],
|
|
14
|
-
},
|
|
15
|
-
view: () => renderComponentPage({
|
|
16
|
-
currentHref: '/components/avatar',
|
|
17
|
-
prev,
|
|
18
|
-
next,
|
|
19
|
-
name: 'avatar',
|
|
20
|
-
description: 'When <code>src</code> is set, renders an <code><img></code> with <code>loading="lazy"</code>. Without <code>src</code>, shows initials derived from <code>alt</code>.',
|
|
21
|
-
content: `
|
|
22
|
-
${demo(
|
|
23
|
-
`<div style="display:flex;gap:1rem;align-items:center">` +
|
|
24
|
-
avatar({ alt: 'Alice Smith', size: 'sm' }) +
|
|
25
|
-
avatar({ alt: 'Bob Jones', size: 'md' }) +
|
|
26
|
-
avatar({ alt: 'Carol White', size: 'lg' }) +
|
|
27
|
-
avatar({ alt: 'Dan Brown', size: 'xl' }) +
|
|
28
|
-
`</div>`,
|
|
29
|
-
`avatar({ src: user.avatarUrl, alt: user.name, size: 'md' })
|
|
30
|
-
avatar({ alt: 'Alice Smith' }) // renders initials "AS"
|
|
31
|
-
avatar({ alt: 'Alice', initials: 'A' }) // explicit initials`
|
|
32
|
-
)}
|
|
33
|
-
`,
|
|
34
|
-
}),
|
|
35
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { renderComponentPage, demo } from '../../lib/component-page.js'
|
|
2
|
-
import { prevNext } from '../../lib/nav.js'
|
|
3
|
-
import { badge } from '../../../../src/ui/index.js'
|
|
4
|
-
|
|
5
|
-
const { prev, next } = prevNext('/components/badge')
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
route: '/components/badge',
|
|
9
|
-
meta: {
|
|
10
|
-
theme: 'light',
|
|
11
|
-
title: 'Badge — Pulse Docs',
|
|
12
|
-
description: 'Badge component for Pulse UI.',
|
|
13
|
-
styles: ['/pulse-ui.css', '/theme.css', '/docs.css'],
|
|
14
|
-
},
|
|
15
|
-
view: () => renderComponentPage({
|
|
16
|
-
currentHref: '/components/badge',
|
|
17
|
-
prev,
|
|
18
|
-
next,
|
|
19
|
-
name: 'badge',
|
|
20
|
-
description: 'Inline status and label indicator. Five semantic variants cover the most common states.',
|
|
21
|
-
content: `
|
|
22
|
-
${demo(
|
|
23
|
-
badge({ label: 'Default', variant: 'default' }) + ' ' +
|
|
24
|
-
badge({ label: 'Info', variant: 'info' }) + ' ' +
|
|
25
|
-
badge({ label: 'Success', variant: 'success' }) + ' ' +
|
|
26
|
-
badge({ label: 'Warning', variant: 'warning' }) + ' ' +
|
|
27
|
-
badge({ label: 'Error', variant: 'error' }),
|
|
28
|
-
`badge({ label: 'Default', variant: 'default' })
|
|
29
|
-
badge({ label: 'Info', variant: 'info' })
|
|
30
|
-
badge({ label: 'Success', variant: 'success' })
|
|
31
|
-
badge({ label: 'Warning', variant: 'warning' })
|
|
32
|
-
badge({ label: 'Error', variant: 'error' })`
|
|
33
|
-
)}
|
|
34
|
-
`,
|
|
35
|
-
}),
|
|
36
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
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 { breadcrumbs } from '../../../../src/ui/index.js'
|
|
5
|
-
|
|
6
|
-
const { prev, next } = prevNext('/components/breadcrumbs')
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
route: '/components/breadcrumbs',
|
|
10
|
-
meta: {
|
|
11
|
-
theme: 'light',
|
|
12
|
-
title: 'Breadcrumbs — Pulse Docs',
|
|
13
|
-
description: 'Accessible breadcrumb navigation component for Pulse UI.',
|
|
14
|
-
styles: ['/pulse-ui.css', '/theme.css', '/docs.css'],
|
|
15
|
-
},
|
|
16
|
-
view: () => renderComponentPage({
|
|
17
|
-
currentHref: '/components/breadcrumbs',
|
|
18
|
-
prev,
|
|
19
|
-
next,
|
|
20
|
-
name: 'breadcrumbs',
|
|
21
|
-
description: 'Accessible breadcrumb navigation. The current page item renders as a <code><span></code> with <code>aria-current="page"</code>; all preceding items render as links.',
|
|
22
|
-
content: `
|
|
23
|
-
|
|
24
|
-
<h2 class="doc-h2" id="basic">Basic</h2>
|
|
25
|
-
${demo(
|
|
26
|
-
breadcrumbs({
|
|
27
|
-
items: [
|
|
28
|
-
{ label: 'Home', href: '/' },
|
|
29
|
-
{ label: 'Products', href: '/products' },
|
|
30
|
-
{ label: 'Sneakers' },
|
|
31
|
-
],
|
|
32
|
-
}),
|
|
33
|
-
`breadcrumbs({
|
|
34
|
-
items: [
|
|
35
|
-
{ label: 'Home', href: '/' },
|
|
36
|
-
{ label: 'Products', href: '/products' },
|
|
37
|
-
{ label: 'Sneakers' },
|
|
38
|
-
],
|
|
39
|
-
})`
|
|
40
|
-
)}
|
|
41
|
-
|
|
42
|
-
<h2 class="doc-h2" id="longer">Longer trail</h2>
|
|
43
|
-
${demo(
|
|
44
|
-
breadcrumbs({
|
|
45
|
-
items: [
|
|
46
|
-
{ label: 'Home', href: '/' },
|
|
47
|
-
{ label: 'Shop', href: '/shop' },
|
|
48
|
-
{ label: 'Footwear', href: '/shop/footwear' },
|
|
49
|
-
{ label: 'Sneakers', href: '/shop/footwear/sneakers' },
|
|
50
|
-
{ label: 'Air Max 90' },
|
|
51
|
-
],
|
|
52
|
-
}),
|
|
53
|
-
`breadcrumbs({
|
|
54
|
-
items: [
|
|
55
|
-
{ label: 'Home', href: '/' },
|
|
56
|
-
{ label: 'Shop', href: '/shop' },
|
|
57
|
-
{ label: 'Footwear', href: '/shop/footwear' },
|
|
58
|
-
{ label: 'Sneakers', href: '/shop/footwear/sneakers' },
|
|
59
|
-
{ label: 'Air Max 90' },
|
|
60
|
-
],
|
|
61
|
-
})`
|
|
62
|
-
)}
|
|
63
|
-
|
|
64
|
-
<h2 class="doc-h2" id="separator">Custom separator</h2>
|
|
65
|
-
${demo(
|
|
66
|
-
breadcrumbs({
|
|
67
|
-
separator: '›',
|
|
68
|
-
items: [
|
|
69
|
-
{ label: 'Docs', href: '/docs' },
|
|
70
|
-
{ label: 'Components', href: '/docs/components' },
|
|
71
|
-
{ label: 'Breadcrumbs' },
|
|
72
|
-
],
|
|
73
|
-
}),
|
|
74
|
-
`breadcrumbs({
|
|
75
|
-
separator: '›',
|
|
76
|
-
items: [
|
|
77
|
-
{ label: 'Docs', href: '/docs' },
|
|
78
|
-
{ label: 'Components', href: '/docs/components' },
|
|
79
|
-
{ label: 'Breadcrumbs' },
|
|
80
|
-
],
|
|
81
|
-
})`
|
|
82
|
-
)}
|
|
83
|
-
|
|
84
|
-
${table(
|
|
85
|
-
['Prop', 'Type', 'Default', 'Description'],
|
|
86
|
-
[
|
|
87
|
-
['<code>items</code>', 'array', '[]', 'Array of <code>{ label, href }</code>. The last item should have no <code>href</code> — it becomes the current page.'],
|
|
88
|
-
['<code>separator</code>', 'string', "'/'", 'Character rendered between items'],
|
|
89
|
-
['<code>class</code>', 'string', '—', ''],
|
|
90
|
-
]
|
|
91
|
-
)}
|
|
92
|
-
`,
|
|
93
|
-
}),
|
|
94
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
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 { button } from '../../../../src/ui/index.js'
|
|
5
|
-
import { iconArrowRight, iconDownload, iconPlus, iconSend } from '../../../../src/ui/icons.js'
|
|
6
|
-
|
|
7
|
-
const { prev, next } = prevNext('/components/button')
|
|
8
|
-
|
|
9
|
-
export default {
|
|
10
|
-
route: '/components/button',
|
|
11
|
-
meta: {
|
|
12
|
-
theme: 'light',
|
|
13
|
-
title: 'Button — Pulse Docs',
|
|
14
|
-
description: 'Button component for Pulse UI.',
|
|
15
|
-
styles: ['/pulse-ui.css', '/theme.css', '/docs.css'],
|
|
16
|
-
},
|
|
17
|
-
view: () => renderComponentPage({
|
|
18
|
-
currentHref: '/components/button',
|
|
19
|
-
prev,
|
|
20
|
-
next,
|
|
21
|
-
name: 'button',
|
|
22
|
-
description: 'Renders as <code><button></code> by default. Pass <code>href</code> to get an <code><a></code> that looks identical. All four variants are shown below.',
|
|
23
|
-
content: `
|
|
24
|
-
${demo(
|
|
25
|
-
button({ label: 'Primary', variant: 'primary' }) +
|
|
26
|
-
button({ label: 'Secondary', variant: 'secondary' }) +
|
|
27
|
-
button({ label: 'Ghost', variant: 'ghost' }) +
|
|
28
|
-
button({ label: 'Danger', variant: 'danger' }),
|
|
29
|
-
`button({ label: 'Primary', variant: 'primary' })
|
|
30
|
-
button({ label: 'Secondary', variant: 'secondary' })
|
|
31
|
-
button({ label: 'Ghost', variant: 'ghost' })
|
|
32
|
-
button({ label: 'Danger', variant: 'danger' })`
|
|
33
|
-
)}
|
|
34
|
-
|
|
35
|
-
${demo(
|
|
36
|
-
button({ label: 'Small', size: 'sm' }) +
|
|
37
|
-
button({ label: 'Medium', size: 'md' }) +
|
|
38
|
-
button({ label: 'Large', size: 'lg' }),
|
|
39
|
-
`button({ label: 'Small', size: 'sm' })
|
|
40
|
-
button({ label: 'Medium', size: 'md' })
|
|
41
|
-
button({ label: 'Large', size: 'lg' })`
|
|
42
|
-
)}
|
|
43
|
-
|
|
44
|
-
${demo(
|
|
45
|
-
button({ label: 'Download', icon: iconDownload({ size: 14 }) }) +
|
|
46
|
-
button({ label: 'New item', icon: iconPlus({ size: 14 }), variant: 'secondary' }) +
|
|
47
|
-
button({ label: 'Continue', iconAfter: iconArrowRight({ size: 14 }) }) +
|
|
48
|
-
button({ label: 'Send', iconAfter: iconSend({ size: 14 }), variant: 'ghost' }),
|
|
49
|
-
`import { iconDownload, iconPlus, iconArrowRight, iconSend } from '@invisibleloop/pulse/ui'
|
|
50
|
-
|
|
51
|
-
button({ label: 'Download', icon: iconDownload({ size: 14 }) })
|
|
52
|
-
button({ label: 'New item', icon: iconPlus({ size: 14 }), variant: 'secondary' })
|
|
53
|
-
button({ label: 'Continue', iconAfter: iconArrowRight({ size: 14 }) })
|
|
54
|
-
button({ label: 'Send', iconAfter: iconSend({ size: 14 }), variant: 'ghost' })`
|
|
55
|
-
)}
|
|
56
|
-
|
|
57
|
-
${demo(
|
|
58
|
-
button({ label: 'Disabled', disabled: true }) +
|
|
59
|
-
button({ label: 'Link', href: '/docs' }) +
|
|
60
|
-
button({ label: 'Submit', type: 'submit', variant: 'primary' }),
|
|
61
|
-
`button({ label: 'Disabled', disabled: true })
|
|
62
|
-
button({ label: 'Link', href: '/docs' })
|
|
63
|
-
button({ label: 'Submit', type: 'submit', variant: 'primary' })`
|
|
64
|
-
)}
|
|
65
|
-
|
|
66
|
-
${table(
|
|
67
|
-
['Prop', 'Type', 'Default', 'Description'],
|
|
68
|
-
[
|
|
69
|
-
['<code>label</code>', 'string', '—', 'Visible text'],
|
|
70
|
-
['<code>variant</code>', 'string', 'primary', 'primary · secondary · ghost · danger'],
|
|
71
|
-
['<code>size</code>', 'string', 'md', 'sm · md · lg'],
|
|
72
|
-
['<code>href</code>', 'string', '—', 'Renders <code><a></code> instead of <code><button></code>'],
|
|
73
|
-
['<code>disabled</code>', 'boolean', 'false', ''],
|
|
74
|
-
['<code>type</code>', 'string', 'button', 'button · submit · reset'],
|
|
75
|
-
['<code>icon</code>', 'string', '—', 'SVG HTML prepended inside'],
|
|
76
|
-
['<code>iconAfter</code>','string', '—', 'SVG HTML appended inside'],
|
|
77
|
-
['<code>fullWidth</code>','boolean', 'false', ''],
|
|
78
|
-
['<code>class</code>', 'string', '—', 'Extra classes appended to the element'],
|
|
79
|
-
['<code>attrs</code>', 'object', '{}', 'Extra HTML attributes (button only)'],
|
|
80
|
-
]
|
|
81
|
-
)}
|
|
82
|
-
`,
|
|
83
|
-
}),
|
|
84
|
-
}
|