@stacksjs/stx 0.2.152 → 0.2.154
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/animation.js +6 -6
- package/dist/app-shell.js +2 -1
- package/dist/browser-composables.d.ts +8 -0
- package/dist/build-id.d.ts +49 -0
- package/dist/build-id.js +20 -0
- package/dist/build-message.d.ts +10 -0
- package/dist/build-message.js +26 -0
- package/dist/builtins/attrs.js +6 -1
- package/dist/cli.js +1743 -1255
- package/dist/client-script-bundler.js +2 -4
- package/dist/client-script.d.ts +29 -0
- package/dist/client-script.js +142 -97
- package/dist/color-mode-boot.d.ts +46 -10
- package/dist/color-mode-boot.js +53 -13
- package/dist/component-client-factories.js +3 -2
- package/dist/component-renderer.js +10 -21
- package/dist/composables/index.d.ts +8 -1
- package/dist/composables/use-clipboard.d.ts +1 -5
- package/dist/composables/use-clipboard.js +57 -46
- package/dist/composables/use-color-mode.d.ts +19 -4
- package/dist/composables/use-color-mode.js +49 -28
- package/dist/composables/use-router.d.ts +28 -11
- package/dist/composables/use-router.js +63 -9
- package/dist/composables/use-storage.d.ts +14 -15
- package/dist/composables/use-storage.js +63 -2
- package/dist/config.js +22 -7
- package/dist/craft.js +1319 -841
- package/dist/dev-server/crosswind.js +8 -6
- package/dist/dev-server/serve-app.js +13 -7
- package/dist/dev-server/serve-markdown.js +4 -1
- package/dist/dev-server/serve-multi.js +32 -20
- package/dist/dev-server/types.d.ts +8 -1
- package/dist/document-shell.d.ts +120 -0
- package/dist/document-shell.js +161 -14
- package/dist/dynamic-components.js +123 -4
- package/dist/events.d.ts +26 -49
- package/dist/events.js +23 -9
- package/dist/expressions.d.ts +1 -1
- package/dist/expressions.js +3 -3
- package/dist/framework-composables.d.ts +41 -0
- package/dist/framework-composables.js +115 -0
- package/dist/head.js +5 -1
- package/dist/hot-reload.js +8 -2
- package/dist/includes.js +4 -4
- package/dist/index.d.ts +17 -0
- package/dist/index.js +9 -0
- package/dist/isolated-build.d.ts +12 -0
- package/dist/isolated-build.js +18 -0
- package/dist/plugin-system.d.ts +1 -1
- package/dist/process.js +46 -12
- package/dist/production-builder.js +3 -1
- package/dist/production-server.js +4 -1
- package/dist/prop-sentinels.d.ts +31 -0
- package/dist/prop-sentinels.js +7 -0
- package/dist/pwa.js +1258 -780
- package/dist/reactive.js +1 -1
- package/dist/reactivity.d.ts +0 -15
- package/dist/reactivity.js +15 -6
- package/dist/runtime-globals.d.ts +40 -2
- package/dist/runtime-globals.js +90 -0
- package/dist/runtime-injection.d.ts +51 -0
- package/dist/runtime-injection.js +13 -0
- package/dist/script-emit.d.ts +20 -0
- package/dist/script-emit.js +11 -0
- package/dist/script-validation.js +12 -7
- package/dist/signal-processing.js +25 -40
- package/dist/signals-api.d.ts +30 -0
- package/dist/signals-api.js +18 -0
- package/dist/signals.js +532 -85
- package/dist/site-builder/build.js +21 -7
- package/dist/site-builder/seo.js +19 -10
- package/dist/site-builder/theme.js +5 -4
- package/dist/site-builder/types.d.ts +1 -0
- package/dist/ssg.js +1255 -777
- package/dist/state-management.js +4 -1
- package/dist/store-loader.d.ts +0 -11
- package/dist/store-loader.js +27 -3
- package/dist/strict-lint.d.ts +9 -6
- package/dist/strict-lint.js +2 -21
- package/dist/stx.d.ts +125 -22
- package/dist/types/config-types.d.ts +1 -0
- package/dist/unresolved-identifiers.d.ts +50 -0
- package/dist/unresolved-identifiers.js +146 -0
- package/dist/utils.js +3 -3
- package/dist/variable-extractor.js +17 -1
- package/dist/x-element.js +1 -1
- package/package.json +5 -5
- package/stx.d.ts +125 -22
package/dist/animation.js
CHANGED
|
@@ -62,7 +62,7 @@ function generateTransitionCSS(type, options = {}) {
|
|
|
62
62
|
}
|
|
63
63
|
function generateMotionPreferencesScript() {
|
|
64
64
|
return `
|
|
65
|
-
<script data-stx-scoped>
|
|
65
|
+
<script data-stx-scoped data-stx-run="once">
|
|
66
66
|
// Motion preferences handling
|
|
67
67
|
(function() {
|
|
68
68
|
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
@@ -107,7 +107,7 @@ function hasAnimationDirectives(template) {
|
|
|
107
107
|
}
|
|
108
108
|
function generateIntersectionObserverScript(threshold = 0.1, rootMargin = "0px") {
|
|
109
109
|
return `
|
|
110
|
-
<script data-stx-scoped>
|
|
110
|
+
<script data-stx-scoped data-stx-run="always">
|
|
111
111
|
// Intersection Observer for scroll animations
|
|
112
112
|
(function() {
|
|
113
113
|
const initObserver = () => {
|
|
@@ -272,7 +272,7 @@ function generateBaseAnimationStyles() {
|
|
|
272
272
|
function generateAnimationGroup(groupName, elements, options = {}) {
|
|
273
273
|
const { staggerDelay = 50, sequence = !1 } = options;
|
|
274
274
|
return `
|
|
275
|
-
<script data-stx-scoped>
|
|
275
|
+
<script data-stx-scoped data-stx-run="always">
|
|
276
276
|
// Animation Group: ${groupName}
|
|
277
277
|
(function() {
|
|
278
278
|
const elements = ${JSON.stringify(elements)};
|
|
@@ -444,7 +444,7 @@ export const keyframeDirective = {
|
|
|
444
444
|
};
|
|
445
445
|
function generateStaggerScript(containerId, childSelector, baseDelay, staggerDelay, animationClass) {
|
|
446
446
|
return `
|
|
447
|
-
<script data-stx-scoped>
|
|
447
|
+
<script data-stx-scoped data-stx-run="always">
|
|
448
448
|
(function() {
|
|
449
449
|
const container = document.getElementById('${containerId}');
|
|
450
450
|
if (!container) return;
|
|
@@ -522,7 +522,7 @@ export const springDirective = {
|
|
|
522
522
|
export function createAnimationTimeline(entries) {
|
|
523
523
|
const _timelineId = `stx-timeline-${Math.random().toString(36).slice(2, 9)}`;
|
|
524
524
|
return `
|
|
525
|
-
<script data-stx-scoped>
|
|
525
|
+
<script data-stx-scoped data-stx-run="always">
|
|
526
526
|
(function() {
|
|
527
527
|
const timeline = ${JSON.stringify(entries)};
|
|
528
528
|
|
|
@@ -599,7 +599,7 @@ export function parseAnimationShorthand(shorthand) {
|
|
|
599
599
|
}
|
|
600
600
|
export function generateAnimationRuntime() {
|
|
601
601
|
return `
|
|
602
|
-
<script data-stx-scoped>
|
|
602
|
+
<script data-stx-scoped data-stx-run="once">
|
|
603
603
|
window.__stxAnimation = {
|
|
604
604
|
// Registry of animations
|
|
605
605
|
animations: new Map(),
|
package/dist/app-shell.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
var {require}=import.meta;import path from "node:path";
|
|
2
2
|
import { classifyAllScripts } from "./script-classifier.js";
|
|
3
|
+
import { startsDocument } from "./document-shell.js";
|
|
3
4
|
export { extractLayoutMetadata } from "stx-router/layout-metadata";
|
|
4
5
|
const PAGE_HEAD_MARKER = "stx-page-head:", PAGE_HEAD_MARKER_RE = /<!--stx-page-head:([A-Za-z0-9+/=]+)-->\n?/;
|
|
5
6
|
let _cachedRouterScript = null;
|
|
@@ -116,7 +117,7 @@ ${routerScript}
|
|
|
116
117
|
}
|
|
117
118
|
export function stripDocumentWrapper(html, options = {}) {
|
|
118
119
|
const trimmed = html.trim();
|
|
119
|
-
if (
|
|
120
|
+
if (!startsDocument(trimmed))
|
|
120
121
|
return html;
|
|
121
122
|
const headStyles = [], headMatch = trimmed.match(/<head\b[^>]*>([\s\S]*?)<\/head>/i);
|
|
122
123
|
if (headMatch) {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reactive localStorage with automatic serialization.
|
|
3
3
|
*
|
|
4
|
+
* @deprecated Returns `{ value, remove }` — a third shape for this name, and
|
|
5
|
+
* one the signals runtime cannot see. Use `useLocalStorage` from
|
|
6
|
+
* `@stacksjs/stx`, which returns a Signal (`s()` reads, `s.set(v)` writes) on
|
|
7
|
+
* every import path (stacksjs/stx#1797).
|
|
8
|
+
*
|
|
4
9
|
* @example
|
|
5
10
|
* ```typescript
|
|
6
11
|
* const theme = useLocalStorage('theme', 'dark')
|
|
@@ -12,6 +17,9 @@ export declare function useLocalStorage<T>(key: string, defaultValue: T): { valu
|
|
|
12
17
|
/**
|
|
13
18
|
* Reactive sessionStorage with automatic serialization.
|
|
14
19
|
*
|
|
20
|
+
* @deprecated See {@link useLocalStorage} above — use the Signal-returning
|
|
21
|
+
* version from `@stacksjs/stx` (stacksjs/stx#1797).
|
|
22
|
+
*
|
|
15
23
|
* @example
|
|
16
24
|
* ```typescript
|
|
17
25
|
* const token = useSessionStorage('auth_token', null)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The current process's build id.
|
|
3
|
+
*
|
|
4
|
+
* Stable for the lifetime of the process, which is the unit that matters: a
|
|
5
|
+
* `bun --watch` restart produces a new process and therefore a new id, while a
|
|
6
|
+
* production build stamps every page it renders with one value.
|
|
7
|
+
*
|
|
8
|
+
* `STX_BUILD_ID` overrides it, for deployments that render across several
|
|
9
|
+
* processes and need them to agree.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getBuildId(): string;
|
|
12
|
+
/** @internal test-only — force the id, or with `null` restore generation. */
|
|
13
|
+
export declare function __setBuildIdForTest(id: string | null): void;
|
|
14
|
+
/**
|
|
15
|
+
* Add `<meta name="stx-build">` to `<head>` if it isn't already there.
|
|
16
|
+
*
|
|
17
|
+
* Idempotent, and a no-op for output with no `<head>` — SPA fragments carry the
|
|
18
|
+
* id in a response header instead, since they have nowhere to put a meta.
|
|
19
|
+
*/
|
|
20
|
+
export declare function injectBuildId(html: string, buildId?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Per-process build identity, used to detect runtime/fragment skew
|
|
23
|
+
* (stacksjs/stx#1772).
|
|
24
|
+
*
|
|
25
|
+
* Under `bun --watch`, a loaded page holds the client runtime from build N. A
|
|
26
|
+
* file save restarts the server, and the next SPA navigation fetches a fragment
|
|
27
|
+
* rendered by build N+1. Fragments legitimately carry preserved `{{ }}`
|
|
28
|
+
* moustaches for client-side binding, so any drift in the scoped-script or
|
|
29
|
+
* binding format between the two builds leaves the OLD runtime unable to
|
|
30
|
+
* hydrate the NEW fragment: literal moustaches on screen, dead `:show`, stale
|
|
31
|
+
* canvas. It is sporadic and never reproduces from a clean boot, which is
|
|
32
|
+
* exactly its signature.
|
|
33
|
+
*
|
|
34
|
+
* Stamping the identity on both sides lets the router notice the mismatch and
|
|
35
|
+
* fall back to a full page navigation — the same thing Next and Vite's HMR
|
|
36
|
+
* clients do on a version mismatch. It does not fix format drift; it makes the
|
|
37
|
+
* whole class of skew symptoms impossible to observe.
|
|
38
|
+
*
|
|
39
|
+
* The comparison is deliberately conservative: the router only acts when BOTH
|
|
40
|
+
* sides are known. A missing id means "no information", never "mismatch".
|
|
41
|
+
* That keeps statically hosted output (no headers to send) and any consumer on
|
|
42
|
+
* an older server working exactly as before.
|
|
43
|
+
*
|
|
44
|
+
* @module build-id
|
|
45
|
+
*/
|
|
46
|
+
/** `<meta name="stx-build">` on every rendered page. */
|
|
47
|
+
export declare const BUILD_ID_META: 'stx-build';
|
|
48
|
+
/** Response header carrying the id that rendered an SPA fragment. */
|
|
49
|
+
export declare const BUILD_ID_HEADER: 'X-STX-Build';
|
package/dist/build-id.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const BUILD_ID_META = "stx-build", BUILD_ID_HEADER = "X-STX-Build";
|
|
2
|
+
let cached = null;
|
|
3
|
+
export function getBuildId() {
|
|
4
|
+
if (cached === null)
|
|
5
|
+
cached = process.env.STX_BUILD_ID || `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
6
|
+
return cached;
|
|
7
|
+
}
|
|
8
|
+
export function __setBuildIdForTest(id) {
|
|
9
|
+
cached = id;
|
|
10
|
+
}
|
|
11
|
+
export function injectBuildId(html, buildId = getBuildId()) {
|
|
12
|
+
if (html.includes(`name="${BUILD_ID_META}"`))
|
|
13
|
+
return html;
|
|
14
|
+
const headOpen = /<head\b[^>]*>/i.exec(html);
|
|
15
|
+
if (!headOpen)
|
|
16
|
+
return html;
|
|
17
|
+
const insertAt = headOpen.index + headOpen[0].length;
|
|
18
|
+
return `${html.slice(0, insertAt)}
|
|
19
|
+
<meta name="${BUILD_ID_META}" content="${buildId}">${html.slice(insertAt)}`;
|
|
20
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render a build failure as `path:line:column: message`, falling back to the
|
|
3
|
+
* plain message when no position is available.
|
|
4
|
+
*
|
|
5
|
+
* @param error whatever was thrown — BuildMessage, AggregateError, Error, or
|
|
6
|
+
* anything else
|
|
7
|
+
* @param sourcePath the real file being compiled. Preferred over the position's
|
|
8
|
+
* own `file`, which is a synthetic entry name on the transpiler path.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatBuildFailure(error: unknown, sourcePath?: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
function isBuildMessageLike(value) {
|
|
2
|
+
if (!value || typeof value !== "object")
|
|
3
|
+
return !1;
|
|
4
|
+
const candidate = value;
|
|
5
|
+
return typeof candidate.message === "string" && (candidate.name === "BuildMessage" || candidate.name === "ResolveMessage" || ("position" in candidate));
|
|
6
|
+
}
|
|
7
|
+
function unwrap(error) {
|
|
8
|
+
if (error && typeof error === "object" && Array.isArray(error.errors))
|
|
9
|
+
return error.errors;
|
|
10
|
+
return [error];
|
|
11
|
+
}
|
|
12
|
+
export function formatBuildFailure(error, sourcePath) {
|
|
13
|
+
const parts = [];
|
|
14
|
+
for (const item of unwrap(error)) {
|
|
15
|
+
if (isBuildMessageLike(item)) {
|
|
16
|
+
const position = item.position || void 0, file = sourcePath || position?.file, where = file ? `${file}${position?.line ? `:${position.line}${position.column ? `:${position.column}` : ""}` : ""}` : "", snippet = position?.lineText ? `
|
|
17
|
+
${position.lineText.trim()}` : "";
|
|
18
|
+
parts.push(where ? `${where}: ${item.message}${snippet}` : `${item.message}${snippet}`);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const message = item instanceof Error ? item.message : String(item);
|
|
22
|
+
parts.push(sourcePath ? `${sourcePath}: ${message}` : message);
|
|
23
|
+
}
|
|
24
|
+
return parts.join(`
|
|
25
|
+
`);
|
|
26
|
+
}
|
package/dist/builtins/attrs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { escapeAttr } from "./escape.js";
|
|
2
|
+
import { BOOLEAN_ATTRIBUTE_SENTINEL, stripControlChars } from "../prop-sentinels.js";
|
|
2
3
|
export function forwardStaticAttrs(props, consumed) {
|
|
3
4
|
const attrs = [];
|
|
4
5
|
for (const [key, value] of Object.entries(props.static)) {
|
|
@@ -10,7 +11,11 @@ export function forwardStaticAttrs(props, consumed) {
|
|
|
10
11
|
attrs.push(escapeAttr(name));
|
|
11
12
|
continue;
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
+
if (value === BOOLEAN_ATTRIBUTE_SENTINEL) {
|
|
15
|
+
attrs.push(escapeAttr(name));
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
attrs.push(`${escapeAttr(name)}="${escapeAttr(stripControlChars(String(value)))}"`);
|
|
14
19
|
}
|
|
15
20
|
return attrs;
|
|
16
21
|
}
|