@invisibleloop/pulse 0.20.8 → 0.20.9

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.
@@ -852,42 +852,6 @@ hr.ui-divider {
852
852
  .ui-hero { padding: 5rem 1.5rem; text-align: center; }
853
853
  .ui-hero--left { text-align: left; }
854
854
  .ui-hero--sm { padding-top: 2.5rem; padding-bottom: 0; }
855
- .ui-hero--gradient,
856
- .ui-hero--gradient--purple {
857
- background:
858
- radial-gradient(ellipse 70% 80% at 75% 50%, #2d1b6e 0%, #1a0f45 45%, transparent 75%),
859
- radial-gradient(ellipse 60% 60% at 20% 80%, #1c1060 0%, transparent 65%),
860
- #0d0a1e;
861
- }
862
-
863
- .ui-hero--gradient--blue {
864
- background:
865
- radial-gradient(ellipse 70% 80% at 75% 50%, #0e2d6b 0%, #071840 45%, transparent 75%),
866
- radial-gradient(ellipse 60% 60% at 20% 80%, #0a1f5c 0%, transparent 65%),
867
- #060d1e;
868
- }
869
-
870
- .ui-hero--gradient--green {
871
- background:
872
- radial-gradient(ellipse 70% 80% at 75% 50%, #0d3d28 0%, #052218 45%, transparent 75%),
873
- radial-gradient(ellipse 60% 60% at 20% 80%, #083020 0%, transparent 65%),
874
- #020e09;
875
- }
876
-
877
- .ui-hero--gradient--rose {
878
- background:
879
- radial-gradient(ellipse 70% 80% at 75% 50%, #6b0e35 0%, #400720 45%, transparent 75%),
880
- radial-gradient(ellipse 60% 60% at 20% 80%, #5c0a2a 0%, transparent 65%),
881
- #1e0610;
882
- }
883
-
884
- .ui-hero--gradient--orange {
885
- background:
886
- radial-gradient(ellipse 70% 80% at 75% 50%, #6b2e0e 0%, #401807 45%, transparent 75%),
887
- radial-gradient(ellipse 60% 60% at 20% 80%, #5c2208 0%, transparent 65%),
888
- #1e0e04;
889
- }
890
-
891
855
  .ui-hero-inner { max-width: 720px; margin: 0 auto; }
892
856
  .ui-hero--left .ui-hero-inner { margin: 0; }
893
857
 
@@ -40,28 +40,28 @@ export default {
40
40
  card({
41
41
  flush: true,
42
42
  content: `
43
- <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;">
44
- <span style="font-size:3rem">🌄</span>
43
+ <div class="u-overflow-hidden" style="height:180px;border-radius:var(--ui-radius) var(--ui-radius) 0 0">
44
+ <img src="/img/heic1501a.jpg" alt="The Pillars of Creation in the Eagle Nebula, captured by the Hubble Space Telescope" style="width:100%;height:100%;object-fit:cover;display:block">
45
45
  </div>
46
46
  <div class="u-p-5">
47
- <p class="u-font-semibold u-mb-2" style="margin-top:0">Mountain retreat</p>
48
- <p class="u-text-muted u-text-sm" style="margin:0">A peaceful escape in the highlands. Three nights, all-inclusive.</p>
47
+ <p class="u-font-semibold u-mb-2" style="margin-top:0">Deep field</p>
48
+ <p class="u-text-muted u-text-sm" style="margin:0">The Pillars of Creation, imaged by the Hubble Space Telescope.</p>
49
49
  </div>
50
50
  `,
51
- footer: button({ label: 'Book now', href: '#', variant: 'primary', size: 'sm' }),
51
+ footer: button({ label: 'View gallery', href: '#', variant: 'primary', size: 'sm' }),
52
52
  }),
53
53
  `card({
54
54
  flush: true,
55
55
  content: \`
56
- <div class="u-rounded-md u-overflow-hidden" style="height:180px;background:...">
57
- <img src="/img/retreat.jpg" alt="Mountain retreat" style="width:100%;height:100%;object-fit:cover">
56
+ <div class="u-overflow-hidden" style="height:180px;border-radius:var(--ui-radius) var(--ui-radius) 0 0">
57
+ <img src="/img/nebula.jpg" alt="The Pillars of Creation in the Eagle Nebula" style="width:100%;height:100%;object-fit:cover">
58
58
  </div>
59
59
  <div class="u-p-5">
60
- <p class="u-font-semibold u-mb-2">Mountain retreat</p>
61
- <p class="u-text-muted u-text-sm">A peaceful escape in the highlands.</p>
60
+ <p class="u-font-semibold u-mb-2">Deep field</p>
61
+ <p class="u-text-muted u-text-sm">The Pillars of Creation, imaged by the Hubble Space Telescope.</p>
62
62
  </div>
63
63
  \`,
64
- footer: button({ label: 'Book now', href: '/book', variant: 'primary', size: 'sm' }),
64
+ footer: button({ label: 'View gallery', href: '/gallery', variant: 'primary', size: 'sm' }),
65
65
  })`
66
66
  )}
67
67
 
@@ -15,23 +15,7 @@ export default {
15
15
  },
16
16
  state: {},
17
17
  view: () => {
18
- const placeholderImg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 400" style="width:100%;height:auto;border-radius:var(--ui-radius,8px);display:block" role="img" aria-label="Placeholder image">
19
- <rect width="600" height="400" fill="#111116" rx="8"/>
20
- <rect x="24" y="24" width="552" height="32" rx="6" fill="#1a1a22"/>
21
- <circle cx="44" cy="40" r="6" fill="#ff5f57"/><circle cx="64" cy="40" r="6" fill="#febc2e"/><circle cx="84" cy="40" r="6" fill="#28c840"/>
22
- <rect x="24" y="72" width="552" height="200" rx="6" fill="#1a1a22"/>
23
- <rect x="40" y="92" width="200" height="12" rx="3" fill="#2a2a35"/>
24
- <rect x="40" y="116" width="300" height="8" rx="3" fill="#222228"/>
25
- <rect x="40" y="132" width="260" height="8" rx="3" fill="#222228"/>
26
- <rect x="40" y="148" width="280" height="8" rx="3" fill="#222228"/>
27
- <rect x="40" y="176" width="120" height="32" rx="6" fill="#9b8dff" opacity=".9"/>
28
- <rect x="24" y="288" width="264" height="88" rx="6" fill="#1a1a22"/>
29
- <rect x="312" y="288" width="264" height="88" rx="6" fill="#1a1a22"/>
30
- <rect x="40" y="304" width="100" height="8" rx="3" fill="#2a2a35"/>
31
- <rect x="40" y="320" width="140" height="6" rx="3" fill="#222228"/>
32
- <rect x="328" y="304" width="100" height="8" rx="3" fill="#2a2a35"/>
33
- <rect x="328" y="320" width="120" height="6" rx="3" fill="#222228"/>
34
- </svg>`
18
+ const placeholderImg = `<img src="/img/heic1501a.jpg" alt="The Pillars of Creation in the Eagle Nebula, captured by the Hubble Space Telescope" style="width:100%;height:100%;object-fit:cover;border-radius:var(--ui-radius,8px);display:block">`
35
19
  return renderComponentPage({
36
20
  currentHref: '/components/hero',
37
21
  prev,
@@ -93,18 +77,6 @@ export default {
93
77
  { bleed: true }
94
78
  )}
95
79
 
96
- ${demo(
97
- `<div style="display:flex;flex-direction:column;gap:0">` +
98
- hero({ eyebrow: 'Purple (default)', title: 'gradient: true', gradient: 'purple', size: 'sm' }) +
99
- hero({ eyebrow: 'Blue', title: "gradient: 'blue'", gradient: 'blue', size: 'sm' }) +
100
- hero({ eyebrow: 'Green', title: "gradient: 'green'", gradient: 'green', size: 'sm' }) +
101
- hero({ eyebrow: 'Rose', title: "gradient: 'rose'", gradient: 'rose', size: 'sm' }) +
102
- hero({ eyebrow: 'Orange', title: "gradient: 'orange'", gradient: 'orange', size: 'sm' }) +
103
- `</div>`,
104
- `hero({ title: 'Headline', gradient: 'purple' }) // or 'blue' | 'green' | 'rose' | 'orange'`,
105
- { bleed: true }
106
- )}
107
-
108
80
  ${demo(
109
81
  `<div style="display:flex;flex-direction:column;gap:0">` +
110
82
  hero({ eyebrow: 'Solid colour', title: 'background: color', background: '#0f172a', size: 'sm' }) +
@@ -142,8 +114,7 @@ hero({ title: 'Headline', background: 'linear-gradient(135deg, #1e1b4b, #312e81)
142
114
  ['<code>imageAlign</code>', 'string', "'right'", "'right' (text left) or 'left' (text right) — only applies when image is set"],
143
115
  ['<code>align</code>', 'string', "'center'", "'center' or 'left' — text alignment when no image"],
144
116
  ['<code>size</code>', 'string', "'md'", "'md' (5rem padding) or 'sm' (2.5rem top, no bottom) — use sm for inner-page headers"],
145
- ['<code>gradient</code>', "boolean | 'purple' | 'blue' | 'green' | 'rose' | 'orange'", 'false', 'Named gradient preset. true and \'purple\' are identical.'],
146
- ['<code>background</code>', 'string', '—', 'Any CSS background value — solid colour or custom gradient. Overrides gradient preset.'],
117
+ ['<code>background</code>', 'string', '—', 'Any CSS background value — solid colour or custom gradient.'],
147
118
  ]
148
119
  )}
149
120
  `,
@@ -24,31 +24,31 @@ export default {
24
24
  <h2 class="doc-h2" id="ratio">With aspect ratio</h2>
25
25
  <p>Set <code>ratio</code> to constrain the image to a fixed aspect ratio. The image fills the crop area with <code>object-fit: cover</code>.</p>
26
26
  ${demo(
27
- uiImage({ src: '/img/placeholder-landscape.svg', alt: 'Mountain landscape at dusk', ratio: '16/9' }),
28
- `uiImage({ src: '/img/photo.jpg', alt: 'Mountain landscape at dusk', ratio: '16/9' })`,
27
+ uiImage({ src: '/img/heic1501a.jpg', alt: 'The Pillars of Creation in the Eagle Nebula, captured by the Hubble Space Telescope', ratio: '16/9' }),
28
+ `uiImage({ src: '/img/nebula.jpg', alt: 'The Pillars of Creation in the Eagle Nebula', ratio: '16/9' })`,
29
29
  { col: true }
30
30
  )}
31
31
 
32
32
  <h2 class="doc-h2" id="rounded">Square and rounded</h2>
33
33
  ${demo(
34
- `<div style="max-width:200px;margin:0 auto">${uiImage({ src: '/img/placeholder-square.svg', alt: 'Profile photo', ratio: '1/1', rounded: true })}</div>`,
35
- `uiImage({ src: '/img/avatar.jpg', alt: 'Profile photo', ratio: '1/1', rounded: true })`,
34
+ `<div style="max-width:200px;margin:0 auto">${uiImage({ src: '/img/heic1501a.jpg', alt: 'The Pillars of Creation in the Eagle Nebula, captured by the Hubble Space Telescope', ratio: '1/1', rounded: true })}</div>`,
35
+ `uiImage({ src: '/img/nebula.jpg', alt: 'The Pillars of Creation in the Eagle Nebula', ratio: '1/1', rounded: true })`,
36
36
  { col: true }
37
37
  )}
38
38
 
39
39
  <h2 class="doc-h2" id="caption">With caption</h2>
40
40
  ${demo(
41
41
  uiImage({
42
- src: '/img/placeholder-tall.svg',
43
- alt: 'Aerial view of a coastal town',
42
+ src: '/img/heic1501a.jpg',
43
+ alt: 'The Pillars of Creation in the Eagle Nebula, captured by the Hubble Space Telescope',
44
44
  ratio: '4/3',
45
- caption: 'Aerial view of Porto, Portugal. Photo by João Silva.',
45
+ caption: 'The Pillars of Creation, Eagle Nebula. Photo: NASA, ESA, Hubble Heritage Team.',
46
46
  }),
47
47
  `uiImage({
48
- src: '/img/photo.jpg',
49
- alt: 'Aerial view of a coastal town',
48
+ src: '/img/nebula.jpg',
49
+ alt: 'The Pillars of Creation in the Eagle Nebula',
50
50
  ratio: '4/3',
51
- caption: 'Aerial view of Porto, Portugal. Photo by João Silva.',
51
+ caption: 'The Pillars of Creation, Eagle Nebula. Photo: NASA, ESA, Hubble Heritage Team.',
52
52
  })`,
53
53
  { col: true }
54
54
  )}
@@ -22,7 +22,7 @@ export default {
22
22
  content: `
23
23
  ${demo(
24
24
  media({
25
- image: `<div style="background:var(--ui-surface-2);border:1px solid var(--ui-border);border-radius:8px;aspect-ratio:16/9;display:flex;align-items:center;justify-content:center;color:var(--ui-muted);font-size:.875rem">Screenshot</div>`,
25
+ image: `<img src="/img/heic1501a.jpg" alt="The Pillars of Creation in the Eagle Nebula, captured by the Hubble Space Telescope" style="width:100%;height:100%;aspect-ratio:16/9;object-fit:cover;border-radius:8px;display:block">`,
26
26
  content: stack({ gap: 'md', content: '<h3 style="font-size:1.25rem;font-weight:700;color:var(--ui-text);margin:0">One-tap controls</h3><p style="color:var(--ui-muted);margin:0">Tap to flap. Chippy Bird takes seconds to learn and a lifetime to conquer.</p>' + button({ label: 'Download', href: '#' }) }),
27
27
  }),
28
28
  `media({
@@ -852,42 +852,6 @@ hr.ui-divider {
852
852
  .ui-hero { padding: 5rem 1.5rem; text-align: center; }
853
853
  .ui-hero--left { text-align: left; }
854
854
  .ui-hero--sm { padding-top: 2.5rem; padding-bottom: 0; }
855
- .ui-hero--gradient,
856
- .ui-hero--gradient--purple {
857
- background:
858
- radial-gradient(ellipse 70% 80% at 75% 50%, #2d1b6e 0%, #1a0f45 45%, transparent 75%),
859
- radial-gradient(ellipse 60% 60% at 20% 80%, #1c1060 0%, transparent 65%),
860
- #0d0a1e;
861
- }
862
-
863
- .ui-hero--gradient--blue {
864
- background:
865
- radial-gradient(ellipse 70% 80% at 75% 50%, #0e2d6b 0%, #071840 45%, transparent 75%),
866
- radial-gradient(ellipse 60% 60% at 20% 80%, #0a1f5c 0%, transparent 65%),
867
- #060d1e;
868
- }
869
-
870
- .ui-hero--gradient--green {
871
- background:
872
- radial-gradient(ellipse 70% 80% at 75% 50%, #0d3d28 0%, #052218 45%, transparent 75%),
873
- radial-gradient(ellipse 60% 60% at 20% 80%, #083020 0%, transparent 65%),
874
- #020e09;
875
- }
876
-
877
- .ui-hero--gradient--rose {
878
- background:
879
- radial-gradient(ellipse 70% 80% at 75% 50%, #6b0e35 0%, #400720 45%, transparent 75%),
880
- radial-gradient(ellipse 60% 60% at 20% 80%, #5c0a2a 0%, transparent 65%),
881
- #1e0610;
882
- }
883
-
884
- .ui-hero--gradient--orange {
885
- background:
886
- radial-gradient(ellipse 70% 80% at 75% 50%, #6b2e0e 0%, #401807 45%, transparent 75%),
887
- radial-gradient(ellipse 60% 60% at 20% 80%, #5c2208 0%, transparent 65%),
888
- #1e0e04;
889
- }
890
-
891
855
  .ui-hero-inner { max-width: 720px; margin: 0 auto; }
892
856
  .ui-hero--left .ui-hero-inner { margin: 0; }
893
857
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invisibleloop/pulse",
3
- "version": "0.20.8",
3
+ "version": "0.20.9",
4
4
  "type": "module",
5
5
  "description": "AI-first frontend framework. The spec is the source of truth.",
6
6
  "license": "MIT",
@@ -1 +1 @@
1
- 0.20.8
1
+ 0.20.9
@@ -852,42 +852,6 @@ hr.ui-divider {
852
852
  .ui-hero { padding: 5rem 1.5rem; text-align: center; }
853
853
  .ui-hero--left { text-align: left; }
854
854
  .ui-hero--sm { padding-top: 2.5rem; padding-bottom: 0; }
855
- .ui-hero--gradient,
856
- .ui-hero--gradient--purple {
857
- background:
858
- radial-gradient(ellipse 70% 80% at 75% 50%, #2d1b6e 0%, #1a0f45 45%, transparent 75%),
859
- radial-gradient(ellipse 60% 60% at 20% 80%, #1c1060 0%, transparent 65%),
860
- #0d0a1e;
861
- }
862
-
863
- .ui-hero--gradient--blue {
864
- background:
865
- radial-gradient(ellipse 70% 80% at 75% 50%, #0e2d6b 0%, #071840 45%, transparent 75%),
866
- radial-gradient(ellipse 60% 60% at 20% 80%, #0a1f5c 0%, transparent 65%),
867
- #060d1e;
868
- }
869
-
870
- .ui-hero--gradient--green {
871
- background:
872
- radial-gradient(ellipse 70% 80% at 75% 50%, #0d3d28 0%, #052218 45%, transparent 75%),
873
- radial-gradient(ellipse 60% 60% at 20% 80%, #083020 0%, transparent 65%),
874
- #020e09;
875
- }
876
-
877
- .ui-hero--gradient--rose {
878
- background:
879
- radial-gradient(ellipse 70% 80% at 75% 50%, #6b0e35 0%, #400720 45%, transparent 75%),
880
- radial-gradient(ellipse 60% 60% at 20% 80%, #5c0a2a 0%, transparent 65%),
881
- #1e0610;
882
- }
883
-
884
- .ui-hero--gradient--orange {
885
- background:
886
- radial-gradient(ellipse 70% 80% at 75% 50%, #6b2e0e 0%, #401807 45%, transparent 75%),
887
- radial-gradient(ellipse 60% 60% at 20% 80%, #5c2208 0%, transparent 65%),
888
- #1e0e04;
889
- }
890
-
891
855
  .ui-hero-inner { max-width: 720px; margin: 0 auto; }
892
856
  .ui-hero--left .ui-hero-inner { margin: 0; }
893
857
 
package/src/mcp/server.js CHANGED
@@ -1856,7 +1856,7 @@ export default {
1856
1856
  { label: 'Features', href: '#features' },
1857
1857
  { label: 'Pricing', href: '#pricing' },
1858
1858
  ], actions: button({ label: 'Get started', size: 'sm' }) })}
1859
- \${hero({ title: 'Your headline here', subtitle: 'Supporting copy that explains the value.', gradient: 'purple',
1859
+ \${hero({ title: 'Your headline here', subtitle: 'Supporting copy that explains the value.',
1860
1860
  actions: button({ label: 'Get started', size: 'lg' }) })}
1861
1861
  \${section({ id: 'features', content: container({ content: \`
1862
1862
  \${grid({ cols: 3, content:
package/src/ui/hero.js CHANGED
@@ -17,8 +17,7 @@
17
17
  * 'split' (default): 50/50 columns.
18
18
  * 'asymmetric': 60/40 text-heavy columns.
19
19
  * 'overlap': image fills the section background, text overlaid with dark gradient.
20
- * @param {boolean|'purple'|'blue'|'green'|'rose'|'orange'} opts.gradient
21
- * @param {string} opts.background - Arbitrary CSS background value — overrides gradient preset
20
+ * @param {string} opts.background - Arbitrary CSS background value
22
21
  * @param {string} opts.backgroundImage - CSS background-image value (url, gradient, etc) — enables full-bleed mode
23
22
  * @param {boolean|number} opts.overlay - Dark overlay opacity for backgroundImage mode (0–1, or true for 0.4 default)
24
23
  * @param {string} opts.eyebrowColor - Overrides eyebrow text colour
@@ -27,8 +26,7 @@
27
26
 
28
27
  import { escHtml as e } from '../html.js'
29
28
 
30
- const GRADIENT_PRESETS = new Set(['purple', 'blue', 'green', 'rose', 'orange'])
31
- const LAYOUTS = new Set(['split', 'asymmetric', 'overlap'])
29
+ const LAYOUTS = new Set(['split', 'asymmetric', 'overlap'])
32
30
 
33
31
  export function hero({
34
32
  eyebrow = '',
@@ -40,7 +38,6 @@ export function hero({
40
38
  align = 'center',
41
39
  size = 'md',
42
40
  layout = 'split',
43
- gradient = false,
44
41
  background = '',
45
42
  backgroundImage = '',
46
43
  overlay = false,
@@ -52,13 +49,6 @@ export function hero({
52
49
  const hasBackgroundImage = Boolean(backgroundImage)
53
50
  const safeLayout = (hasImage && LAYOUTS.has(layout)) ? layout : 'split'
54
51
 
55
- // Resolve gradient class
56
- const gradientClass = gradient
57
- ? (gradient === true || gradient === 'purple')
58
- ? 'ui-hero--gradient'
59
- : GRADIENT_PRESETS.has(gradient) ? `ui-hero--gradient--${gradient}` : ''
60
- : ''
61
-
62
52
  const classes = [
63
53
  'ui-hero',
64
54
  !hasImage && !hasBackgroundImage && align === 'left' && 'ui-hero--left',
@@ -66,7 +56,6 @@ export function hero({
66
56
  hasImage && safeLayout !== 'overlap' && imageAlign === 'left' && 'ui-hero--media-left',
67
57
  hasBackgroundImage && 'ui-hero--bg-image',
68
58
  size === 'sm' && 'ui-hero--sm',
69
- gradientClass,
70
59
  cls,
71
60
  ].filter(Boolean).join(' ')
72
61