stack-site-builder 1.17.3 → 1.17.5
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 +19 -0
- package/package.json +1 -1
- package/src/components/DeckView.astro +32 -15
- package/src/i18n/ui.ts +2 -0
- package/src/styles/global.css +37 -0
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,24 @@ 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
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **Table label columns wrapped** — in a wide table the first column got
|
|
29
|
+
squeezed to its minimum width, breaking short labels ("Part 1") onto two
|
|
30
|
+
lines. The first column of prose and slide tables no longer wraps.
|
|
31
|
+
|
|
14
32
|
## [1.17.3] - 2026-07-22
|
|
15
33
|
|
|
16
34
|
### Fixed
|
|
@@ -265,6 +283,7 @@ catalog sites from a thin content-only repository.
|
|
|
265
283
|
- **Standalone development setup** — a devcontainer and a minimal `playground/`
|
|
266
284
|
consuming site for developing and previewing the theme on its own.
|
|
267
285
|
|
|
286
|
+
[1.17.4]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.17.3...v1.17.4
|
|
268
287
|
[1.17.3]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.17.2...v1.17.3
|
|
269
288
|
[1.17.2]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.17.1...v1.17.2
|
|
270
289
|
[1.17.1]: https://github.com/CodeCompose7/stack-site-builder/compare/v1.17.0...v1.17.1
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stack-site-builder",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.17.
|
|
4
|
+
"version": "1.17.5",
|
|
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,31 +174,47 @@ const priv = entry.data.private;
|
|
|
173
174
|
const btnNext = document.querySelector<HTMLButtonElement>('[data-next]');
|
|
174
175
|
if (elTot) elTot.textContent = String(total);
|
|
175
176
|
|
|
176
|
-
// Heavy embeds (interactive demo iframes)
|
|
177
|
-
//
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
const
|
|
183
|
-
|
|
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
|
+
}
|
|
184
203
|
const io = new IntersectionObserver(
|
|
185
204
|
(entries) => {
|
|
186
205
|
for (const e of entries) {
|
|
206
|
+
if (e.isIntersecting) continue;
|
|
187
207
|
for (const f of Array.from(e.target.querySelectorAll<HTMLIFrameElement>('iframe'))) {
|
|
188
|
-
|
|
189
|
-
if (e.isIntersecting) {
|
|
190
|
-
if (!src && f.dataset.aasSrc) f.setAttribute('src', f.dataset.aasSrc);
|
|
191
|
-
} else if (src) {
|
|
192
|
-
f.dataset.aasSrc = src;
|
|
208
|
+
if (f.getAttribute('src')) {
|
|
193
209
|
f.removeAttribute('src');
|
|
210
|
+
f.closest('.aas-embed')?.classList.remove('running');
|
|
194
211
|
}
|
|
195
212
|
}
|
|
196
213
|
}
|
|
197
214
|
},
|
|
198
|
-
{ root: deck
|
|
215
|
+
{ root: deck },
|
|
199
216
|
);
|
|
200
|
-
|
|
217
|
+
slides.filter((s) => s.querySelector('iframe')).forEach((s) => io.observe(s));
|
|
201
218
|
}
|
|
202
219
|
|
|
203
220
|
let current = 0;
|
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': '이 샘플을 쓰는 곳',
|
package/src/styles/global.css
CHANGED
|
@@ -2355,3 +2355,40 @@ 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
|
+
}
|
|
2387
|
+
|
|
2388
|
+
/* Tables: keep the first (label) column on one line — a wide table otherwise
|
|
2389
|
+
squeezes short labels like "Part 1" into two rows. Applies to reading prose
|
|
2390
|
+
and slide-deck tables alike; label columns are short by convention. */
|
|
2391
|
+
.prose :where(table) :where(th, td):first-child,
|
|
2392
|
+
.aas-slide :where(table) :where(th, td):first-child {
|
|
2393
|
+
white-space: nowrap;
|
|
2394
|
+
}
|