@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.
Files changed (88) hide show
  1. package/dist/animation.js +6 -6
  2. package/dist/app-shell.js +2 -1
  3. package/dist/browser-composables.d.ts +8 -0
  4. package/dist/build-id.d.ts +49 -0
  5. package/dist/build-id.js +20 -0
  6. package/dist/build-message.d.ts +10 -0
  7. package/dist/build-message.js +26 -0
  8. package/dist/builtins/attrs.js +6 -1
  9. package/dist/cli.js +1743 -1255
  10. package/dist/client-script-bundler.js +2 -4
  11. package/dist/client-script.d.ts +29 -0
  12. package/dist/client-script.js +142 -97
  13. package/dist/color-mode-boot.d.ts +46 -10
  14. package/dist/color-mode-boot.js +53 -13
  15. package/dist/component-client-factories.js +3 -2
  16. package/dist/component-renderer.js +10 -21
  17. package/dist/composables/index.d.ts +8 -1
  18. package/dist/composables/use-clipboard.d.ts +1 -5
  19. package/dist/composables/use-clipboard.js +57 -46
  20. package/dist/composables/use-color-mode.d.ts +19 -4
  21. package/dist/composables/use-color-mode.js +49 -28
  22. package/dist/composables/use-router.d.ts +28 -11
  23. package/dist/composables/use-router.js +63 -9
  24. package/dist/composables/use-storage.d.ts +14 -15
  25. package/dist/composables/use-storage.js +63 -2
  26. package/dist/config.js +22 -7
  27. package/dist/craft.js +1319 -841
  28. package/dist/dev-server/crosswind.js +8 -6
  29. package/dist/dev-server/serve-app.js +13 -7
  30. package/dist/dev-server/serve-markdown.js +4 -1
  31. package/dist/dev-server/serve-multi.js +32 -20
  32. package/dist/dev-server/types.d.ts +8 -1
  33. package/dist/document-shell.d.ts +120 -0
  34. package/dist/document-shell.js +161 -14
  35. package/dist/dynamic-components.js +123 -4
  36. package/dist/events.d.ts +26 -49
  37. package/dist/events.js +23 -9
  38. package/dist/expressions.d.ts +1 -1
  39. package/dist/expressions.js +3 -3
  40. package/dist/framework-composables.d.ts +41 -0
  41. package/dist/framework-composables.js +115 -0
  42. package/dist/head.js +5 -1
  43. package/dist/hot-reload.js +8 -2
  44. package/dist/includes.js +4 -4
  45. package/dist/index.d.ts +17 -0
  46. package/dist/index.js +9 -0
  47. package/dist/isolated-build.d.ts +12 -0
  48. package/dist/isolated-build.js +18 -0
  49. package/dist/plugin-system.d.ts +1 -1
  50. package/dist/process.js +46 -12
  51. package/dist/production-builder.js +3 -1
  52. package/dist/production-server.js +4 -1
  53. package/dist/prop-sentinels.d.ts +31 -0
  54. package/dist/prop-sentinels.js +7 -0
  55. package/dist/pwa.js +1258 -780
  56. package/dist/reactive.js +1 -1
  57. package/dist/reactivity.d.ts +0 -15
  58. package/dist/reactivity.js +15 -6
  59. package/dist/runtime-globals.d.ts +40 -2
  60. package/dist/runtime-globals.js +90 -0
  61. package/dist/runtime-injection.d.ts +51 -0
  62. package/dist/runtime-injection.js +13 -0
  63. package/dist/script-emit.d.ts +20 -0
  64. package/dist/script-emit.js +11 -0
  65. package/dist/script-validation.js +12 -7
  66. package/dist/signal-processing.js +25 -40
  67. package/dist/signals-api.d.ts +30 -0
  68. package/dist/signals-api.js +18 -0
  69. package/dist/signals.js +532 -85
  70. package/dist/site-builder/build.js +21 -7
  71. package/dist/site-builder/seo.js +19 -10
  72. package/dist/site-builder/theme.js +5 -4
  73. package/dist/site-builder/types.d.ts +1 -0
  74. package/dist/ssg.js +1255 -777
  75. package/dist/state-management.js +4 -1
  76. package/dist/store-loader.d.ts +0 -11
  77. package/dist/store-loader.js +27 -3
  78. package/dist/strict-lint.d.ts +9 -6
  79. package/dist/strict-lint.js +2 -21
  80. package/dist/stx.d.ts +125 -22
  81. package/dist/types/config-types.d.ts +1 -0
  82. package/dist/unresolved-identifiers.d.ts +50 -0
  83. package/dist/unresolved-identifiers.js +146 -0
  84. package/dist/utils.js +3 -3
  85. package/dist/variable-extractor.js +17 -1
  86. package/dist/x-element.js +1 -1
  87. package/package.json +5 -5
  88. 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 (!/<!DOCTYPE\b/i.test(trimmed) && !/^<html[\s>]/i.test(trimmed))
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';
@@ -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
+ }
@@ -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
- attrs.push(`${escapeAttr(name)}="${escapeAttr(value)}"`);
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
  }