stack-site-builder 1.19.3 → 1.19.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 +21 -0
- package/package.json +1 -1
- package/src/components/CardsHome.astro +6 -2
- package/src/components/ProductLanding.astro +1 -1
- package/src/components/ProductsIndex.astro +1 -1
- package/src/content.ts +3 -0
- package/src/layouts/BaseLayout.astro +20 -7
- package/src/lib/home.ts +4 -0
- package/src/styles/global.css +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,27 @@ 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.19.5] - 2026-07-24
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **`iconInvert` for dark mode** — black line-art icons (e.g. Tabler-style
|
|
19
|
+
SVGs) vanished on the dark card background. Home cards and the home hero
|
|
20
|
+
(`iconInvert: true` in `site.home`), and product entries (`iconInvert`
|
|
21
|
+
frontmatter — applies on the products index and the landing hero) can now
|
|
22
|
+
flag an icon to be color-inverted when the dark theme is active.
|
|
23
|
+
|
|
24
|
+
## [1.19.4] - 2026-07-24
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **Header no longer flickers on navigation** — the member login control used
|
|
29
|
+
to render `hidden` and only appear after a runtime `/aas-auth.json` fetch,
|
|
30
|
+
shifting the whole right-side icon row on every page load. Whether login
|
|
31
|
+
users are configured is a build-time fact (`AAS_PRIVATE_*` env), so the
|
|
32
|
+
control now renders in its final state; the fetch only wires the login form,
|
|
33
|
+
and is skipped entirely on sites without private users.
|
|
34
|
+
|
|
14
35
|
## [1.19.3] - 2026-07-23
|
|
15
36
|
|
|
16
37
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stack-site-builder",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.19.
|
|
4
|
+
"version": "1.19.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": {
|
|
@@ -29,7 +29,7 @@ const resolveHref = (href: string, external?: boolean) =>
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
31
|
<section class="py-14 text-center">
|
|
32
|
-
{h?.hero?.icon && <img src={withBase(h.hero.icon)} alt="" class=
|
|
32
|
+
{h?.hero?.icon && <img src={withBase(h.hero.icon)} alt="" class:list={['mx-auto h-20 w-20 rounded-[22%] object-contain', h.hero.iconInvert && 'aas-icon-invert']} />}
|
|
33
33
|
<h1 class="mt-5 text-4xl font-bold tracking-tight sm:text-5xl">{heroTitle}</h1>
|
|
34
34
|
<p class="mx-auto mt-4 max-w-2xl text-xl text-[var(--aas-muted)]" set:html={heroSubtitle} />
|
|
35
35
|
</section>
|
|
@@ -50,7 +50,11 @@ const resolveHref = (href: string, external?: boolean) =>
|
|
|
50
50
|
<img
|
|
51
51
|
src={withBase(c.icon)}
|
|
52
52
|
alt=""
|
|
53
|
-
class:list={[
|
|
53
|
+
class:list={[
|
|
54
|
+
'h-20 w-20 shrink-0 object-contain',
|
|
55
|
+
c.rounded ? 'rounded-[22%]' : 'rounded-xl',
|
|
56
|
+
c.iconInvert && 'aas-icon-invert',
|
|
57
|
+
]}
|
|
54
58
|
loading="lazy"
|
|
55
59
|
/>
|
|
56
60
|
)}
|
|
@@ -47,7 +47,7 @@ const altBg = (i: number) => i % 2 === 1;
|
|
|
47
47
|
]}
|
|
48
48
|
>
|
|
49
49
|
<div class="mx-auto max-w-[75rem] px-5">
|
|
50
|
-
{d.icon && <img src={withBase(d.icon)} alt="" class=
|
|
50
|
+
{d.icon && <img src={withBase(d.icon)} alt="" class:list={['mx-auto h-24 w-24 rounded-[22%] object-contain', d.iconInvert && 'aas-icon-invert']} />}
|
|
51
51
|
<h1 class="mt-6 text-4xl font-bold tracking-tight sm:text-5xl">{d.title}</h1>
|
|
52
52
|
{d.subtitle && <p class="mt-3 text-xl text-[var(--aas-muted)]" set:html={d.subtitle} />}
|
|
53
53
|
{
|
|
@@ -54,7 +54,7 @@ const sections = productTree.roots
|
|
|
54
54
|
class="aas-lift flex items-center gap-6 rounded-3xl border border-[var(--aas-border)] bg-[var(--aas-panel)] p-6 no-underline"
|
|
55
55
|
>
|
|
56
56
|
{a.data.icon && (
|
|
57
|
-
<img src={withBase(a.data.icon)} alt="" class=
|
|
57
|
+
<img src={withBase(a.data.icon)} alt="" class:list={['h-20 w-20 shrink-0 rounded-[22%] object-contain', a.data.iconInvert && 'aas-icon-invert']} loading="lazy" />
|
|
58
58
|
)}
|
|
59
59
|
<span class="min-w-0">
|
|
60
60
|
<span class="block text-xl font-semibold text-[var(--aas-text)]">{a.data.title}</span>
|
package/src/content.ts
CHANGED
|
@@ -430,6 +430,9 @@ export function defineAasCollections({
|
|
|
430
430
|
// ---- hero ----
|
|
431
431
|
subtitle: z.string().optional(),
|
|
432
432
|
icon: z.string().optional(), // app icon (public/ path)
|
|
433
|
+
// Invert the icon in dark mode — for black line-art icons that would
|
|
434
|
+
// otherwise vanish on the dark card background.
|
|
435
|
+
iconInvert: z.boolean().default(false),
|
|
433
436
|
// Free-form key a site can target from its CSS (`.aas-hero-bg-<key>`)
|
|
434
437
|
// for a custom hero background.
|
|
435
438
|
heroBg: z.string().optional(),
|
|
@@ -11,6 +11,19 @@ import { getNavProducts, getTopProducts, productSlugOf } from '../lib/products';
|
|
|
11
11
|
import { homeTemplate } from '../lib/home';
|
|
12
12
|
import { sectionEnabled, type SectionKey } from '../lib/sections';
|
|
13
13
|
import { siteIcons } from '../lib/icons';
|
|
14
|
+
import { privateClientData } from '../lib/private';
|
|
15
|
+
|
|
16
|
+
// Whether the site has login users configured is a build-time fact (AAS_PRIVATE_*
|
|
17
|
+
// env), so the header login control renders in its final state instead of being
|
|
18
|
+
// revealed after a runtime fetch — a late reveal shifted the whole icon row on
|
|
19
|
+
// every navigation.
|
|
20
|
+
let authEnabled = false;
|
|
21
|
+
try {
|
|
22
|
+
privateClientData();
|
|
23
|
+
authEnabled = true;
|
|
24
|
+
} catch {
|
|
25
|
+
/* no private env — control stays hidden */
|
|
26
|
+
}
|
|
14
27
|
|
|
15
28
|
interface Props {
|
|
16
29
|
title: string;
|
|
@@ -272,9 +285,9 @@ const navItems = allNavItems.filter((item) => !item.section || sectionEnabled(it
|
|
|
272
285
|
))
|
|
273
286
|
}
|
|
274
287
|
</div>
|
|
275
|
-
{/* Member login/logout for private content —
|
|
276
|
-
|
|
277
|
-
<details class="aas-menu relative" data-auth hidden>
|
|
288
|
+
{/* Member login/logout for private content — rendered only when the
|
|
289
|
+
build has login users configured, so the header never reflows. */}
|
|
290
|
+
<details class="aas-menu relative" data-auth hidden={!authEnabled}>
|
|
278
291
|
<summary
|
|
279
292
|
class="flex cursor-pointer list-none items-center rounded-lg border border-[var(--aas-border)] px-2.5 py-1 text-[var(--aas-text)] select-none"
|
|
280
293
|
aria-label={t('private.login')}
|
|
@@ -391,17 +404,17 @@ const navItems = allNavItems.filter((item) => !item.section || sectionEnabled(it
|
|
|
391
404
|
type AuthData,
|
|
392
405
|
} from '../lib/private-client';
|
|
393
406
|
|
|
394
|
-
// Header member login/logout:
|
|
395
|
-
//
|
|
407
|
+
// Header member login/logout: visibility is decided at build time (the
|
|
408
|
+
// control renders hidden on sites without login users) — the fetch only
|
|
409
|
+
// wires the login form with the user table from /aas-auth.json.
|
|
396
410
|
const authCtrl = document.querySelector<HTMLDetailsElement>('[data-auth]');
|
|
397
|
-
if (authCtrl) {
|
|
411
|
+
if (authCtrl && !authCtrl.hidden) {
|
|
398
412
|
(async () => {
|
|
399
413
|
try {
|
|
400
414
|
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
|
|
401
415
|
const res = await fetch(`${base}/aas-auth.json`);
|
|
402
416
|
const data = (await res.json()) as { enabled: boolean } & AuthData;
|
|
403
417
|
if (!data.enabled) return;
|
|
404
|
-
authCtrl.hidden = false;
|
|
405
418
|
const form = authCtrl.querySelector<HTMLFormElement>('[data-auth-form]')!;
|
|
406
419
|
const logoutBtn = authCtrl.querySelector<HTMLButtonElement>('[data-auth-logout]')!;
|
|
407
420
|
const errorEl = authCtrl.querySelector<HTMLElement>('[data-auth-error]')!;
|
package/src/lib/home.ts
CHANGED
|
@@ -24,6 +24,9 @@ export interface HomeCard {
|
|
|
24
24
|
description?: Localized;
|
|
25
25
|
icon?: string; // public/ path
|
|
26
26
|
rounded?: boolean; // app-icon style rounding for the icon
|
|
27
|
+
/** Invert the icon in dark mode — for black line-art icons that would
|
|
28
|
+
* otherwise vanish on the dark card background. */
|
|
29
|
+
iconInvert?: boolean;
|
|
27
30
|
tags?: string[] | Record<string, string[]>;
|
|
28
31
|
}
|
|
29
32
|
|
|
@@ -31,6 +34,7 @@ export interface HomeConfig {
|
|
|
31
34
|
template: 'cards';
|
|
32
35
|
hero?: {
|
|
33
36
|
icon?: string; // public/ path, shown above the title
|
|
37
|
+
iconInvert?: boolean; // invert the icon in dark mode (black line art)
|
|
34
38
|
title?: Localized; // defaults to site.name
|
|
35
39
|
subtitle?: Localized; // defaults to the site.tagline UI string
|
|
36
40
|
};
|
package/src/styles/global.css
CHANGED
|
@@ -179,6 +179,12 @@ html {
|
|
|
179
179
|
:root[data-theme='dark'] .aas-deprecated {
|
|
180
180
|
color: #fbbf24;
|
|
181
181
|
}
|
|
182
|
+
/* Icons flagged `iconInvert` (home cards, products) are black line art that
|
|
183
|
+
would vanish on the dark card background — flip them to white in dark. */
|
|
184
|
+
:root[data-theme='dark'] .aas-icon-invert {
|
|
185
|
+
filter: invert(1);
|
|
186
|
+
}
|
|
187
|
+
|
|
182
188
|
/* "No updates in 1+ year" — same amber warning weight as deprecated. */
|
|
183
189
|
.aas-stale {
|
|
184
190
|
background: color-mix(in srgb, #d97706 16%, transparent);
|