stack-site-builder 1.17.2 → 1.17.4

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/CHANGELOG.md CHANGED
@@ -11,6 +11,29 @@ content schema, while a consuming site supplies only content, taxonomy data and
11
11
  config. Sites track the theme with `pnpm up stack-site-builder`, so each release
12
12
  here is a plain version bump they pull in.
13
13
 
14
+ ## [1.17.4] - 2026-07-22
15
+
16
+ ### Changed
17
+
18
+ - **Deck embeds are click-to-run** — 1.17.3 only paused demos you had merely
19
+ scrolled past; once you *interacted* with one, its (now heavier) loops kept
20
+ janking transitions while its slide was near the screen. Every slide iframe
21
+ now starts blank behind a themed "Run the demo" overlay (`slides.runEmbed`
22
+ UI string), loads only on click, and unloads back to the overlay as soon as
23
+ its slide leaves the screen — the deck never carries a live embed between
24
+ slides.
25
+
26
+ ## [1.17.3] - 2026-07-22
27
+
28
+ ### Fixed
29
+
30
+ - **Slide transitions degraded after passing embed slides** — interactive
31
+ demo iframes kept their animation loops running offscreen, janking every
32
+ later transition until a refresh. The deck now keeps only the on/near-
33
+ screen slides' iframes live (an IntersectionObserver with one viewport of
34
+ side margin stashes/restores `src`), so a revisited demo reloads fresh and
35
+ transitions stay smooth.
36
+
14
37
  ## [1.17.2] - 2026-07-22
15
38
 
16
39
  ### Fixed
@@ -254,6 +277,8 @@ catalog sites from a thin content-only repository.
254
277
  - **Standalone development setup** — a devcontainer and a minimal `playground/`
255
278
  consuming site for developing and previewing the theme on its own.
256
279
 
280
+ [1.17.4]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.17.3...v1.17.4
281
+ [1.17.3]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.17.2...v1.17.3
257
282
  [1.17.2]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.17.1...v1.17.2
258
283
  [1.17.1]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.17.0...v1.17.1
259
284
  [1.17.0]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.16.0...v1.17.0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stack-site-builder",
3
3
  "type": "module",
4
- "version": "1.17.2",
4
+ "version": "1.17.4",
5
5
  "license": "MIT",
6
6
  "description": "The engine behind the awesome-*-stack catalog sites: an Astro theme with the catalog/concepts/articles/slides/samples routes, components, styles and markdown pipeline. Sites provide content, taxonomy data and config.",
7
7
  "repository": {
@@ -64,6 +64,7 @@ const priv = entry.data.private;
64
64
  <main
65
65
  class:list={['aas-deck', themeClass]}
66
66
  data-deck
67
+ data-run-embed-label={t('slides.runEmbed')}
67
68
  data-transition={entry.data.transition}
68
69
  data-toc={String(entry.data.toc)}
69
70
  data-toc-level={String(entry.data.toc_level)}
@@ -173,6 +174,49 @@ const priv = entry.data.private;
173
174
  const btnNext = document.querySelector<HTMLButtonElement>('[data-next]');
174
175
  if (elTot) elTot.textContent = String(total);
175
176
 
177
+ // Heavy embeds (interactive demo iframes) jank slide transitions the
178
+ // moment they run — worse once the viewer has interacted with one. So
179
+ // embeds are click-to-run: each iframe starts blank behind a "run"
180
+ // overlay (src stashed), loads only when the viewer asks, and unloads
181
+ // back to the overlay as soon as its slide leaves the screen. The deck
182
+ // itself never carries a live embed between slides.
183
+ const runLabel = deck.dataset.runEmbedLabel || 'Run';
184
+ const embeds = Array.from(deck.querySelectorAll<HTMLIFrameElement>('.aas-slide iframe'));
185
+ if (embeds.length) {
186
+ for (const f of embeds) {
187
+ f.dataset.aasSrc = f.getAttribute('src') ?? '';
188
+ f.removeAttribute('src');
189
+ const wrap = document.createElement('div');
190
+ wrap.className = 'aas-embed';
191
+ f.parentNode?.insertBefore(wrap, f);
192
+ wrap.appendChild(f);
193
+ const btn = document.createElement('button');
194
+ btn.type = 'button';
195
+ btn.className = 'aas-embed-run';
196
+ btn.innerHTML = `<span aria-hidden="true">▶</span> ${runLabel}`;
197
+ btn.addEventListener('click', () => {
198
+ if (f.dataset.aasSrc) f.setAttribute('src', f.dataset.aasSrc);
199
+ wrap.classList.add('running');
200
+ });
201
+ wrap.appendChild(btn);
202
+ }
203
+ const io = new IntersectionObserver(
204
+ (entries) => {
205
+ for (const e of entries) {
206
+ if (e.isIntersecting) continue;
207
+ for (const f of Array.from(e.target.querySelectorAll<HTMLIFrameElement>('iframe'))) {
208
+ if (f.getAttribute('src')) {
209
+ f.removeAttribute('src');
210
+ f.closest('.aas-embed')?.classList.remove('running');
211
+ }
212
+ }
213
+ }
214
+ },
215
+ { root: deck },
216
+ );
217
+ slides.filter((s) => s.querySelector('iframe')).forEach((s) => io.observe(s));
218
+ }
219
+
176
220
  let current = 0;
177
221
  // Step reveal (fragments): each slide's `.aas-step` elements are revealed
178
222
  // one at a time. `shown[i]` = how many are currently visible.
package/src/i18n/ui.ts CHANGED
@@ -90,6 +90,7 @@ export const ui = {
90
90
  'slides.zoom': 'Enlarge',
91
91
  'slides.close': 'Close',
92
92
  'slides.overview': 'Overview',
93
+ 'slides.runEmbed': 'Run the demo',
93
94
  'sample.title': 'Samples',
94
95
  'sample.tagline':
95
96
  'The runnable mini-projects behind the catalog — download a folder and run it with Docker.',
@@ -253,6 +254,7 @@ export const ui = {
253
254
  'slides.zoom': '크게 보기',
254
255
  'slides.close': '닫기',
255
256
  'slides.overview': '한눈에 보기',
257
+ 'slides.runEmbed': '데모 실행',
256
258
  'sample.title': '샘플',
257
259
  'sample.tagline': '카탈로그 뒤의 실행 가능한 미니 프로젝트 — 폴더를 받아 Docker로 실행해 보세요.',
258
260
  'sample.usedBy': '이 샘플을 쓰는 곳',
@@ -2355,3 +2355,32 @@ summary {
2355
2355
  min-width: 3.5ch;
2356
2356
  text-align: center;
2357
2357
  }
2358
+
2359
+ /* Click-to-run embeds in slide decks (DeckView wraps each slide iframe): the
2360
+ frame stays blank behind this overlay until the viewer runs it; leaving the
2361
+ slide unloads the frame and brings the overlay back. */
2362
+ .aas-embed {
2363
+ position: relative;
2364
+ display: block;
2365
+ }
2366
+ .aas-embed .aas-embed-run {
2367
+ position: absolute;
2368
+ inset: 0;
2369
+ display: flex;
2370
+ align-items: center;
2371
+ justify-content: center;
2372
+ gap: 0.5rem;
2373
+ border: 1px dashed var(--aas-border);
2374
+ border-radius: 12px;
2375
+ background: var(--aas-panel);
2376
+ color: var(--aas-text);
2377
+ font-weight: 600;
2378
+ font-size: 1rem;
2379
+ cursor: pointer;
2380
+ }
2381
+ .aas-embed .aas-embed-run:hover {
2382
+ background: var(--aas-tint);
2383
+ }
2384
+ .aas-embed.running .aas-embed-run {
2385
+ display: none;
2386
+ }