@invisibleloop/pulse 0.20.4 → 0.20.6

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 (80) hide show
  1. package/.claude/pulse-checklist.md +1 -2
  2. package/.github/workflows/ci.yml +3 -0
  3. package/CLAUDE.md +1 -2
  4. package/docs/.claude/pulse-checklist.md +1 -2
  5. package/docs/public/coutumes.css +21 -44
  6. package/docs/public/docs.css +67 -0
  7. package/docs/public/pulse-ui.css +8 -1037
  8. package/docs/public/retrowheels.css +23 -0
  9. package/docs/public/shop.css +35 -1
  10. package/docs/public/sparkys.css +56 -23
  11. package/docs/server.js +0 -11
  12. package/docs/src/lib/nav.js +0 -11
  13. package/docs/src/pages/components/charts.js +2 -1
  14. package/docs/src/pages/components/grid.js +9 -5
  15. package/docs/src/pages/components.js +0 -4
  16. package/docs/src/pages/home.js +16 -1
  17. package/docs/src/pages/how-it-works.js +20 -14
  18. package/docs/src/pages/templates/coutumes.js +83 -72
  19. package/docs/src/pages/templates/mobile-app.js +36 -9
  20. package/docs/src/pages/templates/retrowheels.js +17 -4
  21. package/docs/src/pages/templates/shop.js +21 -10
  22. package/docs/src/pages/templates/sparkys.js +35 -20
  23. package/examples/.claude/pulse-checklist.md +1 -2
  24. package/examples/examples.test.js +4 -4
  25. package/examples/pricing.js +21 -3
  26. package/examples/public/pulse-ui.css +8 -1037
  27. package/examples/retrowheels.css +23 -0
  28. package/examples/retrowheels.js +17 -4
  29. package/package.json +5 -1
  30. package/public/.pulse-ui-version +1 -1
  31. package/public/pulse-ui.css +8 -1037
  32. package/src/agent/checklist.md +1 -2
  33. package/src/agent/guide-components.md +43 -67
  34. package/src/agent/guide-design-gallery.md +14 -14
  35. package/src/agent/guide-design-references.md +21 -21
  36. package/src/agent/guide-styles.md +2 -2
  37. package/src/agent/guide-templates.md +6 -6
  38. package/src/agent/identity.md +1 -1
  39. package/src/agent/workflow.md +1 -2
  40. package/src/mcp/server.js +31 -24
  41. package/src/ui/index.js +0 -27
  42. package/src/ui/ui.test.js +0 -137
  43. package/types/charts.d.ts +61 -0
  44. package/types/ui.d.ts +1 -129
  45. package/docs/src/pages/components/banner.js +0 -44
  46. package/docs/src/pages/components/carousel.js +0 -71
  47. package/docs/src/pages/components/code-window.js +0 -56
  48. package/docs/src/pages/components/decorate.js +0 -74
  49. package/docs/src/pages/components/gallery.js +0 -102
  50. package/docs/src/pages/components/list.js +0 -111
  51. package/docs/src/pages/components/marquee.js +0 -76
  52. package/docs/src/pages/components/photo-card.js +0 -74
  53. package/docs/src/pages/components/pricing.js +0 -67
  54. package/docs/src/pages/components/testimonial.js +0 -48
  55. package/docs/src/pages/components/timeline.js +0 -226
  56. package/src/ui/banner.js +0 -41
  57. package/src/ui/brand-statement.js +0 -58
  58. package/src/ui/carousel.js +0 -59
  59. package/src/ui/code-window.js +0 -39
  60. package/src/ui/colophon.js +0 -29
  61. package/src/ui/contact-row.js +0 -41
  62. package/src/ui/decorate.js +0 -55
  63. package/src/ui/display-heading.js +0 -44
  64. package/src/ui/drop-cap.js +0 -29
  65. package/src/ui/editorial-hero.js +0 -63
  66. package/src/ui/entry-list.js +0 -36
  67. package/src/ui/gallery.js +0 -60
  68. package/src/ui/image-pair.js +0 -72
  69. package/src/ui/list.js +0 -36
  70. package/src/ui/marquee.js +0 -48
  71. package/src/ui/photo-card.js +0 -44
  72. package/src/ui/pricing.js +0 -56
  73. package/src/ui/product-card.js +0 -65
  74. package/src/ui/section-label.js +0 -38
  75. package/src/ui/service-card.js +0 -47
  76. package/src/ui/stat-grid.js +0 -40
  77. package/src/ui/testimonial.js +0 -59
  78. package/src/ui/timeline.js +0 -72
  79. package/src/ui/top-strip.js +0 -47
  80. package/src/ui/trust-list.js +0 -46
@@ -1,59 +0,0 @@
1
- /**
2
- * Pulse UI — Testimonial
3
- *
4
- * A customer quote with optional star rating, avatar, and attribution.
5
- *
6
- * @param {object} opts
7
- * @param {string} opts.quote - The testimonial text
8
- * @param {string} opts.name - Author full name
9
- * @param {string} opts.role - Author role/company (e.g. "CEO at Acme")
10
- * @param {string} opts.src - Avatar image URL; falls back to initials when omitted
11
- * @param {string} opts.initials - Override auto-derived initials (useful for names containing & or unusual characters)
12
- * @param {number} opts.rating - Star rating 1–5; omit to hide stars
13
- * @param {string} opts.class
14
- */
15
-
16
- import { escHtml as e } from '../html.js'
17
-
18
- export function testimonial({
19
- quote = '',
20
- name = '',
21
- role = '',
22
- src = '',
23
- initials: initialsOverride = '',
24
- rating = 0,
25
- class: cls = '',
26
- } = {}) {
27
- const classes = ['ui-testimonial', cls].filter(Boolean).join(' ')
28
-
29
- const stars = rating > 0
30
- ? `<p class="ui-testimonial-rating" aria-label="${Math.round(rating)} out of 5 stars">${'★'.repeat(Math.min(5, Math.max(1, Math.round(rating))))}</p>`
31
- : ''
32
-
33
- // Filter to letter chars only so names like "Tomás & Ren Okabe" produce "TR" not "T&"
34
- const derivedInitials = name
35
- .split(/\s+/)
36
- .map(w => w.replace(/[^a-zA-ZÀ-ÿ]/g, ''))
37
- .filter(Boolean)
38
- .map(w => w[0])
39
- .join('')
40
- .slice(0, 2)
41
- .toUpperCase()
42
- const initials = initialsOverride || derivedInitials
43
-
44
- const avatarHtml = src
45
- ? `<img src="${e(src)}" alt="${e(name)}" class="ui-testimonial-avatar" loading="lazy" width="40" height="40">`
46
- : `<div class="ui-testimonial-avatar ui-testimonial-avatar--initials" aria-hidden="true">${e(initials)}</div>`
47
-
48
- return `<figure class="${e(classes)}">
49
- ${stars}
50
- <blockquote class="ui-testimonial-quote"><p>${e(quote)}</p></blockquote>
51
- <figcaption class="ui-testimonial-author">
52
- ${avatarHtml}
53
- <div class="ui-testimonial-meta">
54
- <p class="ui-testimonial-name">${e(name)}</p>
55
- ${role ? `<p class="ui-testimonial-role">${e(role)}</p>` : ''}
56
- </div>
57
- </figcaption>
58
- </figure>`
59
- }
@@ -1,72 +0,0 @@
1
- /**
2
- * Pulse UI — Timeline
3
- *
4
- * Ordered list of events or steps connected by a line.
5
- * Supports vertical (default) and horizontal orientations.
6
- * Each item accepts a raw HTML content slot — pass any component output.
7
- *
8
- * @param {object} opts
9
- * @param {'vertical'|'horizontal'} opts.direction - Orientation (default: 'vertical')
10
- * @param {Array} opts.items - Array of timelineItem option objects
11
- * @param {string} opts.content - Raw HTML alternative to opts.items (advanced)
12
- * @param {string} opts.class
13
- *
14
- * timelineItem:
15
- * @param {string} opts.dot - Raw HTML inside the dot — SVG icon or emoji
16
- * @param {'accent'|'success'|'warning'|'error'|'muted'} opts.dotColor
17
- * @param {string} opts.label - Timestamp or step label (escaped)
18
- * @param {string} opts.content - Raw HTML body — any component output
19
- */
20
-
21
- import { escHtml as e } from '../html.js'
22
-
23
- const DOT_COLORS = new Set(['accent', 'success', 'warning', 'error', 'muted'])
24
-
25
- export function timelineItem({
26
- dot = '',
27
- dotColor = 'accent',
28
- label = '',
29
- content = '',
30
- class: cls = '',
31
- } = {}) {
32
- if (!DOT_COLORS.has(dotColor)) dotColor = 'accent'
33
-
34
- const dotClasses = [
35
- 'ui-timeline-dot',
36
- `ui-timeline-dot--${dotColor}`,
37
- dot ? 'ui-timeline-dot--icon' : '',
38
- ].filter(Boolean).join(' ')
39
-
40
- const labelHtml = label
41
- ? `<span class="ui-timeline-label">${e(label)}</span>`
42
- : ''
43
-
44
- const itemClasses = ['ui-timeline-item', cls].filter(Boolean).join(' ')
45
-
46
- return `<li class="${itemClasses}">
47
- <div class="ui-timeline-side">
48
- <div class="ui-timeline-connector ui-timeline-connector--before"></div>
49
- <div class="${e(dotClasses)}" aria-hidden="true">${dot}</div>
50
- <div class="ui-timeline-connector ui-timeline-connector--after"></div>
51
- </div>
52
- <div class="ui-timeline-main">
53
- ${labelHtml}
54
- <div class="ui-timeline-body">${content}</div>
55
- </div>
56
- </li>`
57
- }
58
-
59
- export function timeline({
60
- direction = 'vertical',
61
- items = [],
62
- content = '',
63
- class: cls = '',
64
- } = {}) {
65
- if (direction !== 'horizontal') direction = 'vertical'
66
-
67
- const classes = ['ui-timeline', `ui-timeline--${direction}`, cls].filter(Boolean).join(' ')
68
-
69
- const itemsHtml = content || items.map(item => timelineItem(item)).join('')
70
-
71
- return `<ol class="${e(classes)}">${itemsHtml}</ol>`
72
- }
@@ -1,47 +0,0 @@
1
- /**
2
- * Pulse UI — TopStrip
3
- *
4
- * A slim utility bar that sits above the nav — phone numbers, trading hours,
5
- * social links, or any short announcements. Distinct from banner() which is
6
- * for promotional/dismissible messages.
7
- *
8
- * Two layout modes:
9
- * - left + right slots: `topStrip({ left: '...', right: '...' })`
10
- * - single content: `topStrip({ content: '...' })`
11
- *
12
- * @param {object} opts
13
- * @param {string} opts.content - Single centred content (overrides left/right)
14
- * @param {string} opts.left - Left-aligned slot
15
- * @param {string} opts.right - Right-aligned slot
16
- * @param {string} opts.background - CSS background value
17
- * @param {string} opts.color - Foreground/text colour
18
- * @param {string} opts.class
19
- */
20
-
21
- import { escHtml as e } from '../html.js'
22
-
23
- export function topStrip({
24
- content = '',
25
- left = '',
26
- right = '',
27
- background = '',
28
- color = '',
29
- class: cls = '',
30
- } = {}) {
31
- const classes = ['ui-top-strip', cls].filter(Boolean).join(' ')
32
-
33
- const styles = [
34
- background && `background:${background.replace(/"/g, "'")}`,
35
- color && `color:${color.replace(/"/g, "'")}`,
36
- ].filter(Boolean).join(';')
37
- const styleAttr = styles ? ` style="${styles}"` : ''
38
-
39
- if (content) {
40
- return `<div class="${e(classes)}"${styleAttr}><div class="ui-top-strip-content">${content}</div></div>`
41
- }
42
-
43
- return `<div class="${e(classes)}"${styleAttr}>
44
- ${left ? `<div class="ui-top-strip-left">${left}</div>` : ''}
45
- ${right ? `<div class="ui-top-strip-right">${right}</div>` : ''}
46
- </div>`
47
- }
@@ -1,46 +0,0 @@
1
- /**
2
- * Pulse UI — TrustList
3
- *
4
- * A compact row of trust/compliance badges — "Part P registered · NICEIC · £10m insured".
5
- * Each item gets a leading icon (default: check mark). Common on trades, services,
6
- * and professional-services sites.
7
- *
8
- * @param {object} opts
9
- * @param {string[]} opts.items - List of labels
10
- * @param {string} opts.icon - Raw HTML slot — icon shown before each item (default: ✓ check SVG)
11
- * @param {string} opts.color - Icon colour CSS value (default: inherits --ui-accent)
12
- * @param {'sm'|'md'} opts.size
13
- * @param {string} opts.class
14
- */
15
-
16
- import { escHtml as e } from '../html.js'
17
- import { iconCheck } from './icons.js'
18
-
19
- const SIZES = new Set(['sm', 'md'])
20
-
21
- export function trustList({
22
- items = [],
23
- icon = iconCheck({ size: 14 }),
24
- color = '',
25
- size = 'sm',
26
- class: cls = '',
27
- } = {}) {
28
- if (!SIZES.has(size)) size = 'sm'
29
-
30
- const classes = [
31
- 'ui-trust-list',
32
- size !== 'sm' && `ui-trust-list--${size}`,
33
- cls,
34
- ].filter(Boolean).join(' ')
35
-
36
- const iconStyle = color ? ` style="color:${color.replace(/"/g, "'")}"` : ''
37
-
38
- const itemsHtml = items.map(label =>
39
- `<li class="ui-trust-list-item">
40
- <span class="ui-trust-list-icon" aria-hidden="true"${iconStyle}>${icon}</span>
41
- <span>${e(label)}</span>
42
- </li>`
43
- ).join('')
44
-
45
- return `<ul class="${e(classes)}">${itemsHtml}</ul>`
46
- }