@stacksjs/stx 0.2.153 → 0.2.155
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 +1 -27
- 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 +1481 -1231
- package/dist/client-script-bundler.js +2 -4
- package/dist/client-script.d.ts +29 -0
- package/dist/client-script.js +140 -95
- package/dist/color-mode-boot.d.ts +31 -0
- package/dist/color-mode-boot.js +41 -5
- package/dist/component-renderer.js +10 -21
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/use-clipboard.d.ts +1 -5
- package/dist/composables/use-clipboard.js +57 -46
- package/dist/composables/use-color-mode.js +13 -5
- package/dist/composables/use-router.d.ts +28 -11
- package/dist/composables/use-router.js +63 -9
- package/dist/config.js +22 -7
- package/dist/craft.js +1029 -789
- package/dist/dev-server/crosswind.js +8 -6
- package/dist/dev-server/serve-app.js +4 -2
- package/dist/dev-server/serve-markdown.js +4 -1
- package/dist/dev-server/serve-multi.js +32 -20
- package/dist/document-shell.d.ts +65 -0
- package/dist/document-shell.js +59 -12
- 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/hot-reload.js +8 -2
- package/dist/includes.js +2 -2
- 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 +40 -10
- 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 +966 -726
- 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 +258 -47
- 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 +986 -746
- 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 +111 -16
- 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 +111 -16
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { onDestroy } from "../signals-api.js";
|
|
1
2
|
export function useClipboard(options = {}) {
|
|
2
3
|
const { timeout = 1500 } = options, subscribers = new Set;
|
|
3
4
|
let currentText = "", copied = !1, copiedTimeout = null;
|
|
@@ -8,42 +9,17 @@ export function useClipboard(options = {}) {
|
|
|
8
9
|
} catch (e) {
|
|
9
10
|
console.error("[useClipboard] Subscriber error:", e);
|
|
10
11
|
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
get text() {
|
|
14
|
-
return currentText;
|
|
15
|
-
},
|
|
16
|
-
get isSupported() {
|
|
17
|
-
return isSupported;
|
|
18
|
-
},
|
|
19
|
-
get copied() {
|
|
20
|
-
return copied;
|
|
21
|
-
},
|
|
22
|
-
copy: async (text) => {
|
|
23
|
-
if (!isSupported)
|
|
24
|
-
try {
|
|
25
|
-
const textarea = document.createElement("textarea");
|
|
26
|
-
textarea.value = text;
|
|
27
|
-
textarea.style.position = "fixed";
|
|
28
|
-
textarea.style.opacity = "0";
|
|
29
|
-
document.body.appendChild(textarea);
|
|
30
|
-
textarea.select();
|
|
31
|
-
document.execCommand("copy");
|
|
32
|
-
document.body.removeChild(textarea);
|
|
33
|
-
currentText = text;
|
|
34
|
-
copied = !0;
|
|
35
|
-
notify(text);
|
|
36
|
-
if (copiedTimeout)
|
|
37
|
-
clearTimeout(copiedTimeout);
|
|
38
|
-
copiedTimeout = setTimeout(() => {
|
|
39
|
-
copied = !1;
|
|
40
|
-
}, timeout);
|
|
41
|
-
return !0;
|
|
42
|
-
} catch {
|
|
43
|
-
return !1;
|
|
44
|
-
}
|
|
12
|
+
}, copy = async (text) => {
|
|
13
|
+
if (!isSupported)
|
|
45
14
|
try {
|
|
46
|
-
|
|
15
|
+
const textarea = document.createElement("textarea");
|
|
16
|
+
textarea.value = text;
|
|
17
|
+
textarea.style.position = "fixed";
|
|
18
|
+
textarea.style.opacity = "0";
|
|
19
|
+
document.body.appendChild(textarea);
|
|
20
|
+
textarea.select();
|
|
21
|
+
document.execCommand("copy");
|
|
22
|
+
document.body.removeChild(textarea);
|
|
47
23
|
currentText = text;
|
|
48
24
|
copied = !0;
|
|
49
25
|
notify(text);
|
|
@@ -51,27 +27,62 @@ export function useClipboard(options = {}) {
|
|
|
51
27
|
clearTimeout(copiedTimeout);
|
|
52
28
|
copiedTimeout = setTimeout(() => {
|
|
53
29
|
copied = !1;
|
|
30
|
+
notify(currentText);
|
|
54
31
|
}, timeout);
|
|
55
32
|
return !0;
|
|
56
33
|
} catch {
|
|
57
34
|
return !1;
|
|
58
35
|
}
|
|
36
|
+
try {
|
|
37
|
+
await navigator.clipboard.writeText(text);
|
|
38
|
+
currentText = text;
|
|
39
|
+
copied = !0;
|
|
40
|
+
notify(text);
|
|
41
|
+
if (copiedTimeout)
|
|
42
|
+
clearTimeout(copiedTimeout);
|
|
43
|
+
copiedTimeout = setTimeout(() => {
|
|
44
|
+
copied = !1;
|
|
45
|
+
notify(currentText);
|
|
46
|
+
}, timeout);
|
|
47
|
+
return !0;
|
|
48
|
+
} catch {
|
|
49
|
+
return !1;
|
|
50
|
+
}
|
|
51
|
+
}, read = async () => {
|
|
52
|
+
if (!isSupported)
|
|
53
|
+
return "";
|
|
54
|
+
try {
|
|
55
|
+
const text = await navigator.clipboard.readText();
|
|
56
|
+
currentText = text;
|
|
57
|
+
return text;
|
|
58
|
+
} catch {
|
|
59
|
+
return "";
|
|
60
|
+
}
|
|
61
|
+
}, stop = () => {
|
|
62
|
+
if (copiedTimeout) {
|
|
63
|
+
clearTimeout(copiedTimeout);
|
|
64
|
+
copiedTimeout = null;
|
|
65
|
+
}
|
|
66
|
+
subscribers.clear();
|
|
67
|
+
};
|
|
68
|
+
onDestroy(stop);
|
|
69
|
+
return {
|
|
70
|
+
get text() {
|
|
71
|
+
return currentText;
|
|
59
72
|
},
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return "";
|
|
63
|
-
try {
|
|
64
|
-
const text = await navigator.clipboard.readText();
|
|
65
|
-
currentText = text;
|
|
66
|
-
return text;
|
|
67
|
-
} catch {
|
|
68
|
-
return "";
|
|
69
|
-
}
|
|
73
|
+
get isSupported() {
|
|
74
|
+
return isSupported;
|
|
70
75
|
},
|
|
76
|
+
get copied() {
|
|
77
|
+
return copied;
|
|
78
|
+
},
|
|
79
|
+
copy,
|
|
80
|
+
read,
|
|
71
81
|
subscribe: (callback) => {
|
|
72
82
|
subscribers.add(callback);
|
|
73
83
|
return () => subscribers.delete(callback);
|
|
74
|
-
}
|
|
84
|
+
},
|
|
85
|
+
stop
|
|
75
86
|
};
|
|
76
87
|
}
|
|
77
88
|
export async function copyToClipboard(text) {
|
|
@@ -7,11 +7,19 @@ export function normalizeColorMode(value) {
|
|
|
7
7
|
return null;
|
|
8
8
|
}
|
|
9
9
|
export function useColorMode(options = {}) {
|
|
10
|
-
const boot = typeof window < "u" ? window.__STX_COLOR_MODE__ : null
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const boot = typeof window < "u" ? window.__STX_COLOR_MODE__ : null;
|
|
11
|
+
function pick(fromOptions, fromBoot, fallback) {
|
|
12
|
+
if (fromOptions !== void 0)
|
|
13
|
+
return fromOptions;
|
|
14
|
+
if (boot && typeof boot === "object" && fromBoot !== void 0)
|
|
15
|
+
return fromBoot;
|
|
16
|
+
return fallback;
|
|
17
|
+
}
|
|
18
|
+
const {
|
|
19
|
+
storageKey = pick(void 0, boot?.storageKey, "stx-color-mode"),
|
|
20
|
+
initialMode = pick(void 0, boot?.initialMode, "auto"),
|
|
21
|
+
darkClass = pick(void 0, boot?.darkClass, "dark"),
|
|
22
|
+
attribute = pick(void 0, boot?.attribute, null),
|
|
15
23
|
autoValue: autoValueOption = boot?.autoValue,
|
|
16
24
|
disableTransitions = !0
|
|
17
25
|
} = options;
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Navigate to a URL. Uses stxRouter if available, otherwise falls back to
|
|
2
|
+
* Navigate to a URL. Uses stxRouter if available, otherwise falls back to a
|
|
3
|
+
* full document load.
|
|
4
|
+
*
|
|
5
|
+
* Kept in step with the client runtime's `navigate` (#1807), which used to take
|
|
6
|
+
* a bare `forceReload` boolean while the shipped declaration promised
|
|
7
|
+
* `{ replace }` — so `navigate(url, { replace: true })` type-checked and then
|
|
8
|
+
* did a full load that PUSHED a history entry.
|
|
3
9
|
*
|
|
4
10
|
* @example
|
|
5
11
|
* ```ts
|
|
6
12
|
* navigate('/about')
|
|
7
|
-
* navigate('
|
|
13
|
+
* navigate('/dashboard', { replace: true })
|
|
14
|
+
* navigate('/legacy', { reload: true })
|
|
8
15
|
* ```
|
|
9
16
|
*/
|
|
10
|
-
export declare function navigate(url: string): void;
|
|
17
|
+
export declare function navigate(url: string, options?: NavigateOptions | boolean): void;
|
|
11
18
|
/**
|
|
12
19
|
* Go back in browser history.
|
|
13
20
|
*/
|
|
@@ -42,12 +49,6 @@ export declare function setRouteParams(params: Record<string, string>): void;
|
|
|
42
49
|
* ```
|
|
43
50
|
*/
|
|
44
51
|
export declare function useSearchParams(): SearchParamsRef;
|
|
45
|
-
/**
|
|
46
|
-
* useRouter - Navigation composable for STX applications
|
|
47
|
-
*
|
|
48
|
-
* Provides clean APIs for navigation without raw `window.location` or `window.history`.
|
|
49
|
-
* These are server-safe stubs; the actual runtime implementations live in signals.ts.
|
|
50
|
-
*/
|
|
51
52
|
export declare interface RouteInfo {
|
|
52
53
|
path: string
|
|
53
54
|
fullPath: string
|
|
@@ -55,9 +56,25 @@ export declare interface RouteInfo {
|
|
|
55
56
|
query: Record<string, string>
|
|
56
57
|
params: Record<string, string>
|
|
57
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* How a search-param mutation is written to session history.
|
|
61
|
+
*
|
|
62
|
+
* Spelled `{ replace }` to match `navigate()`, which already takes it — before
|
|
63
|
+
* this the two halves of the routing API disagreed on whether replacing was
|
|
64
|
+
* expressible at all.
|
|
65
|
+
*/
|
|
66
|
+
export declare interface SearchParamsCommitOptions {
|
|
67
|
+
replace?: boolean
|
|
68
|
+
}
|
|
58
69
|
export declare interface SearchParamsRef {
|
|
59
70
|
data: { (): Record<string, string>, set: (v: Record<string, string>) => void }
|
|
60
71
|
get: (key: string) => string | undefined
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
has: (key: string) => boolean
|
|
73
|
+
set: (key: string, value: string, options?: SearchParamsCommitOptions) => void
|
|
74
|
+
delete: (key: string, options?: SearchParamsCommitOptions) => void
|
|
75
|
+
setAll: (obj: Record<string, string>, options?: SearchParamsCommitOptions) => void
|
|
76
|
+
}
|
|
77
|
+
export declare interface NavigateOptions {
|
|
78
|
+
replace?: boolean
|
|
79
|
+
reload?: boolean
|
|
63
80
|
}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { state } from "../signals-api.js";
|
|
2
|
+
export function navigate(url, options) {
|
|
3
|
+
if (typeof window > "u")
|
|
4
|
+
return;
|
|
5
|
+
const opts = options && typeof options === "object" ? options : { reload: !!options }, router = window.stxRouter;
|
|
6
|
+
if (!opts.reload && router?.navigate) {
|
|
7
|
+
router.navigate(url, { replace: !!opts.replace });
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (opts.replace)
|
|
11
|
+
window.location.replace(url);
|
|
12
|
+
else
|
|
13
|
+
window.location.href = url;
|
|
7
14
|
}
|
|
8
15
|
export function goBack() {
|
|
9
16
|
if (typeof window < "u")
|
|
@@ -45,7 +52,54 @@ export function setRouteParams(params) {
|
|
|
45
52
|
window.stx.setRouteParams(params);
|
|
46
53
|
}
|
|
47
54
|
export function useSearchParams() {
|
|
48
|
-
|
|
49
|
-
return;
|
|
50
|
-
|
|
55
|
+
if (typeof window < "u" && window.stx?.useSearchParams)
|
|
56
|
+
return window.stx.useSearchParams();
|
|
57
|
+
if (typeof window > "u")
|
|
58
|
+
return {
|
|
59
|
+
data: Object.assign(() => ({}), { set: () => {} }),
|
|
60
|
+
get: () => {
|
|
61
|
+
return;
|
|
62
|
+
},
|
|
63
|
+
has: () => !1,
|
|
64
|
+
set: () => {},
|
|
65
|
+
delete: () => {},
|
|
66
|
+
setAll: () => {}
|
|
67
|
+
};
|
|
68
|
+
const read = () => {
|
|
69
|
+
const out = {};
|
|
70
|
+
new URLSearchParams(window.location.search).forEach((v, k) => {
|
|
71
|
+
out[k] = v;
|
|
72
|
+
});
|
|
73
|
+
return out;
|
|
74
|
+
}, data = state(read()), sync = () => data.set(read());
|
|
75
|
+
window.addEventListener("popstate", sync);
|
|
76
|
+
window.addEventListener("stx:navigate", sync);
|
|
77
|
+
const commit = (url, options) => {
|
|
78
|
+
if (!!(options && typeof options === "object" && options.replace))
|
|
79
|
+
window.history.replaceState({}, "", url);
|
|
80
|
+
else
|
|
81
|
+
window.history.pushState({}, "", url);
|
|
82
|
+
sync();
|
|
83
|
+
}, has = (key) => Object.prototype.hasOwnProperty.call(data(), key);
|
|
84
|
+
return {
|
|
85
|
+
data,
|
|
86
|
+
get: (key) => has(key) ? data()[key] : void 0,
|
|
87
|
+
has,
|
|
88
|
+
set: (key, value, options) => {
|
|
89
|
+
const url = new URL(window.location.href);
|
|
90
|
+
url.searchParams.set(key, value);
|
|
91
|
+
commit(url, options);
|
|
92
|
+
},
|
|
93
|
+
delete: (key, options) => {
|
|
94
|
+
const url = new URL(window.location.href);
|
|
95
|
+
url.searchParams.delete(key);
|
|
96
|
+
commit(url, options);
|
|
97
|
+
},
|
|
98
|
+
setAll: (obj, options) => {
|
|
99
|
+
const url = new URL(window.location.href);
|
|
100
|
+
for (const [k, v] of Object.entries(obj))
|
|
101
|
+
url.searchParams.set(k, v);
|
|
102
|
+
commit(url, options);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
51
105
|
}
|
package/dist/config.js
CHANGED
|
@@ -103,7 +103,7 @@ export const defaultConfig = {
|
|
|
103
103
|
},
|
|
104
104
|
router: {
|
|
105
105
|
enabled: !0,
|
|
106
|
-
container: "
|
|
106
|
+
container: "main",
|
|
107
107
|
linkSelector: "a[href]",
|
|
108
108
|
viewTransitions: !0,
|
|
109
109
|
scrollToTop: !0,
|
|
@@ -360,18 +360,31 @@ export const defaultConfig = {
|
|
|
360
360
|
verbose: !1
|
|
361
361
|
}
|
|
362
362
|
};
|
|
363
|
-
function resolveStxRoot(configRoot, configPagesDir) {
|
|
363
|
+
function resolveStxRoot(configRoot, configPagesDir, cwd) {
|
|
364
364
|
const defaultPagesDir = configPagesDir || "pages";
|
|
365
365
|
if (configRoot)
|
|
366
366
|
return { root: configRoot, pagesDir: defaultPagesDir };
|
|
367
|
-
const
|
|
367
|
+
const base = cwd || process.cwd(), resourcesViews = path.join(base, "resources", "views"), resourcesLayouts = path.join(base, "resources", "layouts");
|
|
368
368
|
if (fs.existsSync(resourcesViews) && fs.existsSync(resourcesLayouts))
|
|
369
369
|
return { root: "resources", pagesDir: "views" };
|
|
370
|
-
const resourcesViewsPages = path.join(
|
|
370
|
+
const resourcesViewsPages = path.join(base, "resources", "views", "pages");
|
|
371
371
|
if (fs.existsSync(resourcesViewsPages))
|
|
372
372
|
return { root: "resources/views", pagesDir: defaultPagesDir };
|
|
373
373
|
return { root: ".", pagesDir: defaultPagesDir };
|
|
374
374
|
}
|
|
375
|
+
function warnMissingDirs(loaded, cwd) {
|
|
376
|
+
const keys = ["componentsDir", "layoutsDir", "partialsDir"];
|
|
377
|
+
for (const key of keys) {
|
|
378
|
+
const value = loaded[key];
|
|
379
|
+
if (typeof value !== "string" || !value)
|
|
380
|
+
continue;
|
|
381
|
+
const abs = path.isAbsolute(value) ? value : path.join(cwd, value);
|
|
382
|
+
if (fs.existsSync(abs))
|
|
383
|
+
continue;
|
|
384
|
+
const prefixed = !!loaded.root && loaded.root !== ".";
|
|
385
|
+
console.warn(`[stx] ${String(key)} resolves to "${abs}", which does not exist. Configured as "${value}"` + (prefixed ? ` and prefixed with root "${loaded.root}" \u2014 a value that already includes the root gets it twice.` : "."));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
375
388
|
function applyStateDir(loaded) {
|
|
376
389
|
setStateDir(loaded.stateDir);
|
|
377
390
|
loaded.stateDir = stateDirName();
|
|
@@ -405,7 +418,7 @@ export async function loadStxConfig(cwd) {
|
|
|
405
418
|
verbose: !1
|
|
406
419
|
})).config;
|
|
407
420
|
applyStateDir(loaded);
|
|
408
|
-
const resolved = resolveStxRoot(loaded.root, loaded.pagesDir);
|
|
421
|
+
const resolved = resolveStxRoot(loaded.root, loaded.pagesDir, effectiveCwd);
|
|
409
422
|
loaded.root = resolved.root;
|
|
410
423
|
loaded.pagesDir = resolved.pagesDir;
|
|
411
424
|
if (loaded.root && loaded.root !== ".") {
|
|
@@ -417,6 +430,7 @@ export async function loadStxConfig(cwd) {
|
|
|
417
430
|
if (loaded.layoutsDir && !path.isAbsolute(loaded.layoutsDir))
|
|
418
431
|
loaded.layoutsDir = path.join(rootPrefix, loaded.layoutsDir);
|
|
419
432
|
}
|
|
433
|
+
warnMissingDirs(loaded, effectiveCwd);
|
|
420
434
|
if (loaded.plugins && loaded.plugins.length > 0) {
|
|
421
435
|
const { pluginManager } = await import("./plugin-system.js"), pluginComponentDirs = [], pluginPageDirs = [];
|
|
422
436
|
for (const pluginEntry of loaded.plugins) {
|
|
@@ -434,8 +448,9 @@ export async function loadStxConfig(cwd) {
|
|
|
434
448
|
const plugin = pluginModule.default || pluginModule;
|
|
435
449
|
pluginManager.register(plugin, loaded);
|
|
436
450
|
if (plugin.components) {
|
|
437
|
-
const
|
|
438
|
-
|
|
451
|
+
const dirs = Array.isArray(plugin.components) ? plugin.components : [plugin.components];
|
|
452
|
+
for (const entry of dirs)
|
|
453
|
+
pluginComponentDirs.push(path.resolve(pluginDir, entry));
|
|
439
454
|
}
|
|
440
455
|
if (plugin.pages) {
|
|
441
456
|
const dir = path.resolve(pluginDir, plugin.pages), prefix = pluginOptions.path || "/";
|