@treeseed/core 0.8.8 → 0.8.10
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/dist/components/SiteTitle.astro +2 -2
- package/dist/components/content/ContentStatusLegend.astro +4 -4
- package/dist/components/docs/BookFontControls.astro +9 -9
- package/dist/components/docs/DesktopSidebarToggle.astro +8 -8
- package/dist/components/docs/Footer.astro +7 -91
- package/dist/components/docs/Header.astro +9 -2
- package/dist/components/docs/PageTitle.astro +1 -1
- package/dist/components/docs/ThemeSelect.astro +3 -1
- package/dist/components/forms/ContactForm.astro +21 -21
- package/dist/components/forms/FooterSubscribeForm.astro +9 -9
- package/dist/components/site/BookList.astro +7 -7
- package/dist/components/site/CTASection.astro +4 -4
- package/dist/components/site/ChronicleList.astro +6 -6
- package/dist/components/site/Hero.astro +3 -3
- package/dist/components/site/PathCard.astro +5 -5
- package/dist/components/site/ProfileList.astro +5 -5
- package/dist/components/site/RouteNotFound.astro +6 -6
- package/dist/components/site/SectionIntro.astro +3 -3
- package/dist/components/site/StageBanner.astro +2 -2
- package/dist/components/site/TrustCallout.astro +3 -3
- package/dist/components/ui/data/ActionList.astro +51 -0
- package/dist/components/ui/data/Badge.astro +19 -0
- package/dist/components/ui/data/DataTable.astro +51 -0
- package/dist/components/ui/data/KeyValueList.astro +28 -0
- package/dist/components/ui/data/MetricCard.astro +25 -0
- package/dist/components/ui/data/MetricGrid.astro +27 -0
- package/dist/components/ui/data/StatusPill.astro +20 -0
- package/dist/components/ui/forms/Button.astro +52 -0
- package/dist/components/ui/forms/Field.astro +39 -0
- package/dist/components/ui/forms/FormActions.astro +12 -0
- package/dist/components/ui/forms/PasswordMeter.astro +80 -0
- package/dist/components/ui/forms/RadioGroup.astro +55 -0
- package/dist/components/ui/forms/Select.astro +44 -0
- package/dist/components/ui/forms/TextInput.astro +58 -0
- package/dist/components/ui/forms/Textarea.astro +45 -0
- package/dist/components/ui/layout/PageHeader.astro +45 -0
- package/dist/components/ui/shell/AppShell.astro +112 -0
- package/dist/components/ui/shell/BottomNav.astro +35 -0
- package/dist/components/ui/shell/ProjectHeader.astro +66 -0
- package/dist/components/ui/shell/PublicFooter.astro +39 -0
- package/dist/components/ui/shell/PublicShell.astro +179 -0
- package/dist/components/ui/shell/RailNav.astro +35 -0
- package/dist/components/ui/shell/TopBar.astro +52 -0
- package/dist/components/ui/surface/Card.astro +46 -0
- package/dist/components/ui/surface/EmptyState.astro +45 -0
- package/dist/components/ui/surface/Panel.astro +54 -0
- package/dist/components/ui/theme/ThemeMenu.astro +32 -0
- package/dist/components/ui/theme/ThemePreviewSwatch.astro +18 -0
- package/dist/components/ui/theme/ThemeScript.astro +111 -0
- package/dist/components/ui/theme/ThemeSelector.astro +202 -0
- package/dist/components/ui/types.js +0 -0
- package/dist/dev-watch.d.ts +6 -2
- package/dist/dev-watch.js +12 -3
- package/dist/dev.d.ts +10 -2
- package/dist/dev.js +352 -68
- package/dist/layouts/AuthoredEntryLayout.astro +27 -27
- package/dist/layouts/BookLayout.astro +10 -10
- package/dist/layouts/ContentLayout.astro +4 -4
- package/dist/layouts/MainLayout.astro +66 -193
- package/dist/layouts/NoteLayout.astro +6 -6
- package/dist/layouts/ProfileLayout.astro +17 -17
- package/dist/middleware/starlightRouteData.js +20 -14
- package/dist/pages/404.astro +8 -8
- package/dist/pages/[slug].astro +1 -1
- package/dist/pages/books/[slug].astro +5 -5
- package/dist/pages/contact.astro +4 -4
- package/dist/pages/docs-runtime/[...slug].astro +12 -12
- package/dist/pages/docs-runtime/index.astro +13 -13
- package/dist/pages/index.astro +28 -28
- package/dist/pages/ui/index.astro +216 -0
- package/dist/scripts/dev-platform.js +7 -1
- package/dist/site.js +53 -5
- package/dist/styles/app-shell.css +597 -0
- package/dist/styles/forms.css +258 -0
- package/dist/styles/global.css +125 -120
- package/dist/styles/prose.css +11 -11
- package/dist/styles/theme.css +177 -0
- package/dist/styles/tokens.css +62 -22
- package/dist/styles/ui.css +551 -0
- package/dist/utils/color-schemes/cedar.js +53 -0
- package/dist/utils/color-schemes/fern.js +53 -0
- package/dist/utils/color-schemes/index.js +13 -0
- package/dist/utils/color-schemes/lichen.js +53 -0
- package/dist/utils/color-schemes/shared.js +33 -0
- package/dist/utils/color-schemes/tidepool.js +53 -0
- package/dist/utils/content-status.js +5 -5
- package/dist/utils/site-config.js +2 -2
- package/dist/utils/starlight-nav.js +13 -7
- package/dist/utils/theme.js +133 -41
- package/package.json +36 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Button from '../forms/Button.astro';
|
|
3
|
+
import type { ButtonAction, Tone } from '../types.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
eyebrow?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
tone?: Tone;
|
|
10
|
+
actions?: ButtonAction[];
|
|
11
|
+
class?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
eyebrow,
|
|
16
|
+
title,
|
|
17
|
+
description,
|
|
18
|
+
tone = 'default',
|
|
19
|
+
actions = [],
|
|
20
|
+
class: className,
|
|
21
|
+
} = Astro.props as Props;
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<section class:list={['ts-panel', className]} data-tone={tone}>
|
|
25
|
+
{eyebrow || title || description || actions.length > 0 || Astro.slots.has('actions') ? (
|
|
26
|
+
<header class="ts-panel__header">
|
|
27
|
+
<div class="ts-panel__heading">
|
|
28
|
+
{eyebrow ? <p class="ts-panel__eyebrow">{eyebrow}</p> : null}
|
|
29
|
+
{title ? <h2 class="ts-panel__title">{title}</h2> : null}
|
|
30
|
+
{description ? <p class="ts-panel__description">{description}</p> : null}
|
|
31
|
+
</div>
|
|
32
|
+
{actions.length > 0 || Astro.slots.has('actions') ? (
|
|
33
|
+
<div class="ts-panel__actions">
|
|
34
|
+
{actions.map((action) => (
|
|
35
|
+
<Button
|
|
36
|
+
href={action.href}
|
|
37
|
+
type={action.type}
|
|
38
|
+
variant={action.variant ?? 'secondary'}
|
|
39
|
+
ariaLabel={action.ariaLabel}
|
|
40
|
+
disabled={action.disabled}
|
|
41
|
+
size="sm"
|
|
42
|
+
>
|
|
43
|
+
{action.label}
|
|
44
|
+
</Button>
|
|
45
|
+
))}
|
|
46
|
+
<slot name="actions" />
|
|
47
|
+
</div>
|
|
48
|
+
) : null}
|
|
49
|
+
</header>
|
|
50
|
+
) : null}
|
|
51
|
+
<div class="ts-panel__body">
|
|
52
|
+
<slot />
|
|
53
|
+
</div>
|
|
54
|
+
</section>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
import ThemeSelector from './ThemeSelector.astro';
|
|
3
|
+
import type { ThemePreference } from '../../../utils/theme.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
selectedScheme?: ThemePreference['scheme'];
|
|
7
|
+
selectedMode?: ThemePreference['mode'];
|
|
8
|
+
label?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
selectedScheme,
|
|
13
|
+
selectedMode,
|
|
14
|
+
label = 'Appearance',
|
|
15
|
+
} = Astro.props as Props;
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<details class="ts-theme-menu" data-ts-theme-menu>
|
|
19
|
+
<summary class="ts-theme-menu__trigger" aria-label={label} title={label}>
|
|
20
|
+
<svg aria-hidden="true" viewBox="0 0 24 24" focusable="false">
|
|
21
|
+
<path d="M12 3.25a8.75 8.75 0 0 0 0 17.5h1.1a2.05 2.05 0 0 0 1.46-3.49 0.55 0.55 0 0 1 .39-.94h1.45a4.35 4.35 0 0 0 4.35-4.35A8.72 8.72 0 0 0 12 3.25Zm-4.1 9.1a1.35 1.35 0 1 1 0-2.7 1.35 1.35 0 0 1 0 2.7Zm2.3-4.1a1.35 1.35 0 1 1 0-2.7 1.35 1.35 0 0 1 0 2.7Zm3.9 0a1.35 1.35 0 1 1 0-2.7 1.35 1.35 0 0 1 0 2.7Zm2.6 4.1a1.35 1.35 0 1 1 0-2.7 1.35 1.35 0 0 1 0 2.7Z" />
|
|
22
|
+
</svg>
|
|
23
|
+
</summary>
|
|
24
|
+
<div class="ts-theme-menu__panel">
|
|
25
|
+
<ThemeSelector
|
|
26
|
+
label={label}
|
|
27
|
+
selectedScheme={selectedScheme}
|
|
28
|
+
selectedMode={selectedMode}
|
|
29
|
+
compact={false}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
</details>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
swatches: string[];
|
|
4
|
+
label?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { swatches, label = 'Color scheme preview' } = Astro.props as Props;
|
|
8
|
+
const visibleSwatches = swatches.slice(0, 4);
|
|
9
|
+
const swatchStyle = visibleSwatches
|
|
10
|
+
.map((swatch, index) => `--ts-preview-swatch-${index + 1}: ${swatch}`)
|
|
11
|
+
.join('; ');
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<span class="ts-theme-swatch" style={swatchStyle} role="img" aria-label={label}>
|
|
15
|
+
{visibleSwatches.map((_, index) => (
|
|
16
|
+
<span class="ts-theme-swatch__dot" data-swatch-index={index + 1} aria-hidden="true"></span>
|
|
17
|
+
))}
|
|
18
|
+
</span>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
buildTreeseedThemeCss,
|
|
4
|
+
getBuiltInColorSchemes,
|
|
5
|
+
normalizeThemePreference,
|
|
6
|
+
type ThemePreference,
|
|
7
|
+
} from '../../../utils/theme.js';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
defaultScheme?: ThemePreference['scheme'];
|
|
11
|
+
defaultMode?: ThemePreference['mode'];
|
|
12
|
+
includeCss?: boolean;
|
|
13
|
+
preferDefaultPreference?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const preference = normalizeThemePreference({
|
|
17
|
+
scheme: (Astro.props as Props).defaultScheme,
|
|
18
|
+
mode: (Astro.props as Props).defaultMode,
|
|
19
|
+
});
|
|
20
|
+
const { includeCss = true, preferDefaultPreference = false } = Astro.props as Props;
|
|
21
|
+
const builtInSchemeIds = getBuiltInColorSchemes().map((scheme) => scheme.id);
|
|
22
|
+
const themeCss = buildTreeseedThemeCss();
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
{includeCss ? <style is:inline set:html={themeCss}></style> : null}
|
|
26
|
+
|
|
27
|
+
<script
|
|
28
|
+
is:inline
|
|
29
|
+
define:vars={{
|
|
30
|
+
builtInSchemeIds,
|
|
31
|
+
defaultScheme: preference.scheme,
|
|
32
|
+
defaultMode: preference.mode,
|
|
33
|
+
preferDefaultPreference,
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
(() => {
|
|
37
|
+
const schemeKey = 'treeseed_color_scheme';
|
|
38
|
+
const modeKey = 'treeseed_theme_mode';
|
|
39
|
+
const modes = new Set(['light', 'dark', 'system']);
|
|
40
|
+
const schemes = new Set(builtInSchemeIds);
|
|
41
|
+
const root = document.documentElement;
|
|
42
|
+
|
|
43
|
+
function readCookie(name) {
|
|
44
|
+
const pair = document.cookie
|
|
45
|
+
.split('; ')
|
|
46
|
+
.find((entry) => entry.startsWith(`${name}=`));
|
|
47
|
+
return pair ? decodeURIComponent(pair.slice(name.length + 1)) : '';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function readStored(name) {
|
|
51
|
+
try {
|
|
52
|
+
return window.sessionStorage.getItem(name) || window.localStorage.getItem(name) || '';
|
|
53
|
+
} catch {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function cookie(name, value) {
|
|
59
|
+
const secure = window.location.protocol === 'https:' ? '; Secure' : '';
|
|
60
|
+
document.cookie = `${name}=${encodeURIComponent(value)}; Max-Age=${60 * 60 * 24 * 365}; Path=/; SameSite=Lax${secure}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function store(name, value) {
|
|
64
|
+
try {
|
|
65
|
+
window.sessionStorage.setItem(name, value);
|
|
66
|
+
} catch {
|
|
67
|
+
// Session storage can be disabled; local storage/cookies still carry the preference.
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
window.localStorage.setItem(name, value);
|
|
71
|
+
} catch {
|
|
72
|
+
// Local storage can be disabled; cookies still carry the preference for SSR.
|
|
73
|
+
}
|
|
74
|
+
cookie(name, value);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function resolveScheme(value) {
|
|
78
|
+
return schemes.has(value) ? value : defaultScheme;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function resolveMode(value) {
|
|
82
|
+
return modes.has(value) ? value : defaultMode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function resolveRenderedMode(mode) {
|
|
86
|
+
if (mode !== 'system') return mode;
|
|
87
|
+
return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const storedScheme = readCookie(schemeKey) || readStored(schemeKey);
|
|
91
|
+
const storedModeValue = readCookie(modeKey) || readStored(modeKey);
|
|
92
|
+
const scheme = preferDefaultPreference ? resolveScheme(defaultScheme) : resolveScheme(storedScheme || defaultScheme);
|
|
93
|
+
const storedMode = preferDefaultPreference ? resolveMode(defaultMode) : resolveMode(storedModeValue || defaultMode);
|
|
94
|
+
const renderedMode = resolveRenderedMode(storedMode);
|
|
95
|
+
|
|
96
|
+
root.dataset.tsScheme = scheme;
|
|
97
|
+
root.dataset.tsMode = renderedMode;
|
|
98
|
+
if (storedMode === 'system') {
|
|
99
|
+
root.dataset.tsModeSource = 'system';
|
|
100
|
+
} else {
|
|
101
|
+
delete root.dataset.tsModeSource;
|
|
102
|
+
}
|
|
103
|
+
store(schemeKey, scheme);
|
|
104
|
+
store(modeKey, storedMode);
|
|
105
|
+
window.matchMedia?.('(prefers-color-scheme: dark)').addEventListener?.('change', () => {
|
|
106
|
+
if (root.dataset.tsModeSource === 'system') {
|
|
107
|
+
root.dataset.tsMode = resolveRenderedMode('system');
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
})();
|
|
111
|
+
</script>
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
getBuiltInColorSchemes,
|
|
4
|
+
normalizeThemePreference,
|
|
5
|
+
type ThemePreference,
|
|
6
|
+
} from '../../../utils/theme.js';
|
|
7
|
+
import ThemePreviewSwatch from './ThemePreviewSwatch.astro';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
label?: string;
|
|
11
|
+
selectedScheme?: ThemePreference['scheme'];
|
|
12
|
+
selectedMode?: ThemePreference['mode'];
|
|
13
|
+
includeHiddenFields?: boolean;
|
|
14
|
+
schemeFieldName?: string;
|
|
15
|
+
modeFieldName?: string;
|
|
16
|
+
compact?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
label = 'Appearance',
|
|
21
|
+
selectedScheme,
|
|
22
|
+
selectedMode,
|
|
23
|
+
includeHiddenFields = false,
|
|
24
|
+
schemeFieldName = 'colorScheme',
|
|
25
|
+
modeFieldName = 'themeMode',
|
|
26
|
+
compact = true,
|
|
27
|
+
} = Astro.props as Props;
|
|
28
|
+
|
|
29
|
+
const schemes = getBuiltInColorSchemes();
|
|
30
|
+
const preference = normalizeThemePreference({ scheme: selectedScheme, mode: selectedMode });
|
|
31
|
+
const activeScheme = schemes.find((scheme) => scheme.id === preference.scheme) ?? schemes[0];
|
|
32
|
+
const initialSwatches = preference.mode === 'dark'
|
|
33
|
+
? activeScheme.modeSwatches.dark
|
|
34
|
+
: activeScheme.modeSwatches.light;
|
|
35
|
+
const modes = [
|
|
36
|
+
{ value: 'system', label: 'System' },
|
|
37
|
+
{ value: 'light', label: 'Light' },
|
|
38
|
+
{ value: 'dark', label: 'Dark' },
|
|
39
|
+
];
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
<div
|
|
43
|
+
class:list={['ts-theme-selector', compact && 'ts-theme-selector--compact']}
|
|
44
|
+
data-ts-theme-selector
|
|
45
|
+
data-selected-scheme={preference.scheme}
|
|
46
|
+
data-selected-mode={preference.mode}
|
|
47
|
+
data-scheme-field={schemeFieldName}
|
|
48
|
+
data-mode-field={modeFieldName}
|
|
49
|
+
>
|
|
50
|
+
<div class="ts-theme-selector__summary">
|
|
51
|
+
<ThemePreviewSwatch swatches={initialSwatches} label={`${activeScheme.name} preview`} />
|
|
52
|
+
<span class="ts-theme-selector__label">
|
|
53
|
+
<span>{label}</span>
|
|
54
|
+
<small data-ts-theme-preview-label>{activeScheme.name} · {preference.mode}</small>
|
|
55
|
+
</span>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="ts-theme-selector__controls">
|
|
58
|
+
<label class="ts-theme-selector__field">
|
|
59
|
+
<span>Color scheme</span>
|
|
60
|
+
<select data-ts-theme-scheme-select aria-label="Color scheme">
|
|
61
|
+
{schemes.map((scheme) => (
|
|
62
|
+
<option value={scheme.id} selected={scheme.id === preference.scheme}>
|
|
63
|
+
{scheme.name}
|
|
64
|
+
</option>
|
|
65
|
+
))}
|
|
66
|
+
</select>
|
|
67
|
+
</label>
|
|
68
|
+
<label class="ts-theme-selector__field">
|
|
69
|
+
<span>Mode</span>
|
|
70
|
+
<select data-ts-theme-mode-select aria-label="Theme mode">
|
|
71
|
+
{modes.map((mode) => (
|
|
72
|
+
<option value={mode.value} selected={mode.value === preference.mode}>
|
|
73
|
+
{mode.label}
|
|
74
|
+
</option>
|
|
75
|
+
))}
|
|
76
|
+
</select>
|
|
77
|
+
</label>
|
|
78
|
+
</div>
|
|
79
|
+
{includeHiddenFields ? (
|
|
80
|
+
<>
|
|
81
|
+
<input type="hidden" name={schemeFieldName} value={preference.scheme} data-ts-theme-scheme-field />
|
|
82
|
+
<input type="hidden" name={modeFieldName} value={preference.mode} data-ts-theme-mode-field />
|
|
83
|
+
</>
|
|
84
|
+
) : null}
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<script is:inline define:vars={{ schemes }}>
|
|
88
|
+
(() => {
|
|
89
|
+
const schemeKey = 'treeseed_color_scheme';
|
|
90
|
+
const modeKey = 'treeseed_theme_mode';
|
|
91
|
+
const maxAge = 60 * 60 * 24 * 365;
|
|
92
|
+
const modeValues = new Set(['light', 'dark', 'system']);
|
|
93
|
+
const schemeValues = new Set(schemes.map((scheme) => scheme.id));
|
|
94
|
+
const schemeMap = new Map(schemes.map((scheme) => [scheme.id, scheme]));
|
|
95
|
+
const media = window.matchMedia?.('(prefers-color-scheme: dark)');
|
|
96
|
+
|
|
97
|
+
function cookie(name, value) {
|
|
98
|
+
const secure = window.location.protocol === 'https:' ? '; Secure' : '';
|
|
99
|
+
document.cookie = `${name}=${encodeURIComponent(value)}; Max-Age=${maxAge}; Path=/; SameSite=Lax${secure}`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function store(name, value) {
|
|
103
|
+
try {
|
|
104
|
+
window.sessionStorage.setItem(name, value);
|
|
105
|
+
} catch {
|
|
106
|
+
// Session storage can be disabled; local storage/cookies still carry the preference.
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
window.localStorage.setItem(name, value);
|
|
110
|
+
} catch {
|
|
111
|
+
// Storage can be disabled; cookies still carry the preference for SSR.
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function renderedMode(mode) {
|
|
116
|
+
if (mode !== 'system') return mode;
|
|
117
|
+
return media?.matches ? 'dark' : 'light';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function applyTheme(scheme, mode, persist = true) {
|
|
121
|
+
const root = document.documentElement;
|
|
122
|
+
const safeScheme = schemeValues.has(scheme) ? scheme : 'fern';
|
|
123
|
+
const safeMode = modeValues.has(mode) ? mode : 'system';
|
|
124
|
+
root.dataset.tsScheme = safeScheme;
|
|
125
|
+
root.dataset.tsMode = renderedMode(safeMode);
|
|
126
|
+
if (safeMode === 'system') {
|
|
127
|
+
root.dataset.tsModeSource = 'system';
|
|
128
|
+
} else {
|
|
129
|
+
delete root.dataset.tsModeSource;
|
|
130
|
+
}
|
|
131
|
+
if (persist) {
|
|
132
|
+
cookie(schemeKey, safeScheme);
|
|
133
|
+
cookie(modeKey, safeMode);
|
|
134
|
+
store(schemeKey, safeScheme);
|
|
135
|
+
store(modeKey, safeMode);
|
|
136
|
+
}
|
|
137
|
+
window.dispatchEvent(new CustomEvent('treeseed:theme-change', {
|
|
138
|
+
detail: { scheme: safeScheme, mode: safeMode, renderedMode: renderedMode(safeMode) },
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function modeSwatches(scheme, mode) {
|
|
143
|
+
const rendered = renderedMode(mode);
|
|
144
|
+
return scheme.modeSwatches?.[rendered] || scheme.swatches || [];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function updateSwatch(selector, schemeId, mode) {
|
|
148
|
+
const scheme = schemeMap.get(schemeId);
|
|
149
|
+
const swatch = selector.querySelector('.ts-theme-swatch');
|
|
150
|
+
const previewLabel = selector.querySelector('[data-ts-theme-preview-label]');
|
|
151
|
+
if (!scheme || !swatch) return;
|
|
152
|
+
swatch.setAttribute('aria-label', `${scheme.name} preview`);
|
|
153
|
+
modeSwatches(scheme, mode).slice(0, 4).forEach((value, index) => {
|
|
154
|
+
swatch.style.setProperty(`--ts-preview-swatch-${index + 1}`, value);
|
|
155
|
+
});
|
|
156
|
+
if (previewLabel) {
|
|
157
|
+
previewLabel.textContent = `${scheme.name} · ${mode === 'system' ? `System ${renderedMode(mode)}` : mode}`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function currentPreference() {
|
|
162
|
+
const root = document.documentElement;
|
|
163
|
+
const scheme = schemeValues.has(root.dataset.tsScheme) ? root.dataset.tsScheme : '';
|
|
164
|
+
const mode = root.dataset.tsModeSource === 'system' ? 'system' : root.dataset.tsMode;
|
|
165
|
+
return {
|
|
166
|
+
scheme,
|
|
167
|
+
mode: modeValues.has(mode) ? mode : '',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function bind(selector) {
|
|
172
|
+
const schemeSelect = selector.querySelector('[data-ts-theme-scheme-select]');
|
|
173
|
+
const modeSelect = selector.querySelector('[data-ts-theme-mode-select]');
|
|
174
|
+
const schemeField = selector.querySelector('[data-ts-theme-scheme-field]');
|
|
175
|
+
const modeField = selector.querySelector('[data-ts-theme-mode-field]');
|
|
176
|
+
if (!(schemeSelect instanceof HTMLSelectElement) || !(modeSelect instanceof HTMLSelectElement)) return;
|
|
177
|
+
|
|
178
|
+
const activePreference = currentPreference();
|
|
179
|
+
if (activePreference.scheme) schemeSelect.value = activePreference.scheme;
|
|
180
|
+
if (activePreference.mode) modeSelect.value = activePreference.mode;
|
|
181
|
+
|
|
182
|
+
function sync(persist = true) {
|
|
183
|
+
const scheme = schemeSelect.value;
|
|
184
|
+
const mode = modeSelect.value;
|
|
185
|
+
if (schemeField instanceof HTMLInputElement) schemeField.value = scheme;
|
|
186
|
+
if (modeField instanceof HTMLInputElement) modeField.value = mode;
|
|
187
|
+
updateSwatch(selector, scheme, mode);
|
|
188
|
+
applyTheme(scheme, mode, persist);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
schemeSelect.addEventListener('change', () => sync(true));
|
|
192
|
+
modeSelect.addEventListener('change', () => sync(true));
|
|
193
|
+
sync(false);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
document.querySelectorAll('[data-ts-theme-selector]').forEach(bind);
|
|
197
|
+
media?.addEventListener?.('change', () => {
|
|
198
|
+
const mode = document.documentElement.dataset.tsModeSource === 'system' ? 'system' : document.documentElement.dataset.tsMode;
|
|
199
|
+
applyTheme(document.documentElement.dataset.tsScheme || 'fern', mode || 'system', false);
|
|
200
|
+
});
|
|
201
|
+
})();
|
|
202
|
+
</script>
|
|
File without changes
|
package/dist/dev-watch.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
export type TreeseedDevWatchEntry = {
|
|
2
|
-
kind: 'tenant' | '
|
|
2
|
+
kind: 'tenant' | 'core' | 'sdk' | 'agent' | 'cli';
|
|
3
3
|
root: string;
|
|
4
|
+
restartRequired?: boolean;
|
|
4
5
|
};
|
|
5
6
|
export type TreeseedDevWatchChange = {
|
|
6
7
|
changedPaths: string[];
|
|
7
8
|
tenantChanged: boolean;
|
|
8
9
|
tenantApiChanged: boolean;
|
|
9
|
-
|
|
10
|
+
coreChanged: boolean;
|
|
10
11
|
sdkChanged: boolean;
|
|
12
|
+
agentChanged: boolean;
|
|
13
|
+
cliChanged: boolean;
|
|
14
|
+
commandImplementationChanged: boolean;
|
|
11
15
|
};
|
|
12
16
|
export type TreeseedDevWatchController = {
|
|
13
17
|
stop: () => void;
|
package/dist/dev-watch.js
CHANGED
|
@@ -95,11 +95,20 @@ function classifyChanges(changedPaths, watchEntries) {
|
|
|
95
95
|
sdkChanged: changedPaths.some(
|
|
96
96
|
(filePath) => watchEntries.some((entry) => entry.kind === "sdk" && matchesEntry(filePath, entry))
|
|
97
97
|
),
|
|
98
|
-
|
|
99
|
-
(filePath) => watchEntries.some((entry) => entry.kind === "
|
|
98
|
+
coreChanged: changedPaths.some(
|
|
99
|
+
(filePath) => watchEntries.some((entry) => entry.kind === "core" && matchesEntry(filePath, entry))
|
|
100
|
+
),
|
|
101
|
+
agentChanged: changedPaths.some(
|
|
102
|
+
(filePath) => watchEntries.some((entry) => entry.kind === "agent" && matchesEntry(filePath, entry))
|
|
103
|
+
),
|
|
104
|
+
cliChanged: changedPaths.some(
|
|
105
|
+
(filePath) => watchEntries.some((entry) => entry.kind === "cli" && matchesEntry(filePath, entry))
|
|
100
106
|
),
|
|
101
107
|
tenantChanged,
|
|
102
|
-
tenantApiChanged: tenantChanged && changedPaths.some(isTenantApiInput)
|
|
108
|
+
tenantApiChanged: tenantChanged && changedPaths.some(isTenantApiInput),
|
|
109
|
+
commandImplementationChanged: changedPaths.some(
|
|
110
|
+
(filePath) => watchEntries.some((entry) => entry.restartRequired === true && matchesEntry(filePath, entry))
|
|
111
|
+
)
|
|
103
112
|
};
|
|
104
113
|
}
|
|
105
114
|
function startPollingWatch({ watchEntries, onChange }) {
|
package/dist/dev.d.ts
CHANGED
|
@@ -8,12 +8,13 @@ export declare const TREESEED_DEFAULT_API_PORT = 3000;
|
|
|
8
8
|
export declare const TREESEED_DEFAULT_LOCAL_SMTP_HOST = "127.0.0.1";
|
|
9
9
|
export declare const TREESEED_DEFAULT_LOCAL_SMTP_PORT = 1025;
|
|
10
10
|
export declare const TREESEED_DEFAULT_MAILPIT_UI_PORT = 8025;
|
|
11
|
-
export type TreeseedIntegratedDevSurface = 'integrated' | 'web';
|
|
11
|
+
export type TreeseedIntegratedDevSurface = 'integrated' | 'web' | 'api' | 'manager' | 'worker' | 'agents' | 'services';
|
|
12
12
|
export type TreeseedIntegratedDevSetupMode = 'auto' | 'check' | 'off';
|
|
13
13
|
export type TreeseedIntegratedDevFeedbackMode = 'live' | 'restart' | 'off';
|
|
14
14
|
export type TreeseedIntegratedDevOpenMode = 'auto' | 'on' | 'off';
|
|
15
15
|
export type TreeseedLocalRuntimeMode = 'auto' | 'provider' | 'local';
|
|
16
16
|
export type TreeseedSelectedLocalRuntime = 'astro-local' | 'cloudflare-wrangler-local' | 'node-local';
|
|
17
|
+
export type TreeseedIntegratedDevCommandId = 'web' | 'api' | 'manager' | 'worker' | 'agents';
|
|
17
18
|
export type TreeseedLocalRuntimeSelection = {
|
|
18
19
|
requested: TreeseedLocalRuntimeMode;
|
|
19
20
|
selected: TreeseedSelectedLocalRuntime;
|
|
@@ -44,7 +45,7 @@ export type TreeseedIntegratedDevOptions = {
|
|
|
44
45
|
shutdownGraceMs?: number;
|
|
45
46
|
};
|
|
46
47
|
export type TreeseedIntegratedDevCommand = {
|
|
47
|
-
id:
|
|
48
|
+
id: TreeseedIntegratedDevCommandId;
|
|
48
49
|
label: string;
|
|
49
50
|
command: string;
|
|
50
51
|
args: string[];
|
|
@@ -96,6 +97,13 @@ export type TreeseedIntegratedDevPlan = {
|
|
|
96
97
|
watchEntries: TreeseedIntegratedDevWatchEntry[];
|
|
97
98
|
commands: TreeseedIntegratedDevCommand[];
|
|
98
99
|
localRuntimes: Record<string, TreeseedLocalRuntimeSelection>;
|
|
100
|
+
restartPolicy: {
|
|
101
|
+
initialBackoffMs: number;
|
|
102
|
+
maxBackoffMs: number;
|
|
103
|
+
setupRetryBackoffMs: number;
|
|
104
|
+
commandImplementationChangesRequireRestart: boolean;
|
|
105
|
+
agentChanges: 'defer';
|
|
106
|
+
};
|
|
99
107
|
reset: TreeseedIntegratedDevResetPlan | null;
|
|
100
108
|
};
|
|
101
109
|
type SpawnLike = (command: string, args: string[], options: SpawnOptions) => ChildProcess;
|