camox 0.40.0 → 0.41.0
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/PlatformLabel.js +62 -0
- package/dist/core/components/lexical/GradientNode.js +126 -0
- package/dist/core/components/lexical/InlineLexicalEditor.js +37 -56
- package/dist/core/components/lexical/InlineStylesPlugin.js +183 -0
- package/dist/core/components/lexical/SelectionBroadcaster.js +49 -46
- package/dist/core/components/lexical/SidebarLexicalEditor.js +197 -151
- package/dist/core/components/lexical/editorConfig.js +25 -7
- package/dist/core/components/lexical/selectTextLink.js +21 -0
- package/dist/core/createApp.d.ts +30 -17
- package/dist/core/createApp.js +14 -3
- package/dist/core/createBlock.d.ts +2 -2
- package/dist/core/createBlock.js +18 -15
- package/dist/core/createLayout.d.ts +48 -4
- package/dist/core/createLayout.js +51 -23
- package/dist/core/derivedRoutes.js +36 -0
- package/dist/core/editing/createEditableBlock.d.ts +9 -8
- package/dist/core/editing/createEditableBlock.js +167 -168
- package/dist/core/lib/lexicalReact.d.ts +1 -26
- package/dist/core/lib/lexicalReact.js +46 -60
- package/dist/core/lib/lexicalState.js +164 -81
- package/dist/core/lib/modifierFormats.js +4 -15
- package/dist/core/lib/textStyles.d.ts +27 -0
- package/dist/core/lib/textStyles.js +47 -0
- package/dist/features/navigation/navigation.d.ts +2 -0
- package/dist/features/navigation/navigation.js +51 -46
- package/dist/features/page/DerivedPageContent.js +61 -0
- package/dist/features/page/PublishedPageContent.js +52 -83
- package/dist/features/page/SharedLayoutContent.js +66 -0
- package/dist/features/preview/CamoxPreview.d.ts +16 -1
- package/dist/features/preview/CamoxPreview.js +242 -265
- package/dist/features/preview/DerivedPreview.js +137 -0
- package/dist/features/preview/EditablePageExperience.js +25 -8
- package/dist/features/preview/components/AddBlockSidebar.js +43 -33
- package/dist/features/preview/components/AssetLightbox.js +1 -1
- package/dist/features/preview/components/BlockThumbnail.js +192 -0
- package/dist/features/preview/components/CreatePageModal.js +123 -115
- package/dist/features/preview/components/DerivedLayoutDialog.js +100 -0
- package/dist/features/preview/components/DerivedLayoutSidebar.d.ts +5 -0
- package/dist/features/preview/components/DerivedLayoutSidebar.js +163 -0
- package/dist/features/preview/components/DerivedPageInfoSidebar.js +57 -0
- package/dist/features/preview/components/FieldToolbar.js +42 -20
- package/dist/features/preview/components/Frame.js +133 -140
- package/dist/features/preview/components/LeftSidebar.js +42 -38
- package/dist/features/preview/components/MobilePreviewDrawer.js +4 -4
- package/dist/features/preview/components/Overlays.js +57 -42
- package/dist/features/preview/components/PageInfoSidebar.js +63 -55
- package/dist/features/preview/components/PageNavigatorSidebar.js +34 -483
- package/dist/features/preview/components/PagePicker.js +205 -153
- package/dist/features/preview/components/PageTree.js +298 -206
- package/dist/features/preview/components/PreviewActivation.js +78 -0
- package/dist/features/preview/components/PreviewPanel.js +67 -35
- package/dist/features/preview/components/PreviewToolbar.js +218 -232
- package/dist/features/preview/components/PublicationRow.js +431 -0
- package/dist/features/preview/components/PublishDialog.js +180 -97
- package/dist/features/preview/components/RightSidebar.js +19 -34
- package/dist/features/preview/components/previewStyles.js +8 -0
- package/dist/features/preview/components/useUpdateBlockPosition.js +7 -13
- package/dist/features/preview/previewConstants.js +8 -0
- package/dist/features/preview/previewStore.js +0 -10
- package/dist/features/preview/publication.js +71 -0
- package/dist/features/provider/AuthenticatedCamoxProvider.js +2 -1
- package/dist/features/provider/CoreCamoxProvider.js +11 -2
- package/dist/features/provider/LocalhostPreviewProvider.js +6 -7
- package/dist/features/routes/pageRuntime.d.ts +10 -0
- package/dist/features/routes/pageRuntime.js +7 -9
- package/dist/features/runtime/PreviewDocumentContext.js +7 -0
- package/dist/features/runtime/RuntimeChrome.js +137 -0
- package/dist/features/runtime/SharedChromeContext.js +7 -0
- package/dist/features/runtime/navigationRequest.js +21 -0
- package/dist/features/runtime/navigationTarget.js +23 -0
- package/dist/features/runtime/pageApp.js +196 -121
- package/dist/features/runtime/pageNavigation.js +79 -130
- package/dist/features/runtime/runtime.d.ts +11 -0
- package/dist/features/runtime/runtime.js +183 -47
- package/dist/features/runtime/studioApp.d.ts +2 -11
- package/dist/features/runtime/studioApp.js +14 -177
- package/dist/features/studio/CamoxStudio.js +27 -13
- package/dist/features/studio/components/Navbar.js +80 -74
- package/dist/features/studio/studioTheme.js +25 -0
- package/dist/features/studio/useTheme.js +94 -109
- package/dist/features/vite/appGeneration.js +12 -3
- package/dist/features/vite/definitionsSync.js +4 -2
- package/dist/features/vite/layoutGeneration.js +38 -0
- package/dist/features/vite/runtimeDev.js +3 -1
- package/dist/lib/auth.js +15 -13
- package/dist/lib/normalized-data.js +4 -4
- package/dist/lib/platform.js +13 -0
- package/dist/lib/utils.js +90 -38
- package/dist/studio-overlays.css +5 -40
- package/dist/studio.css +1 -1
- package/package.json +8 -4
- package/skills/camox/SKILL.md +2 -0
- package/skills/camox/references/block-definitions.md +31 -12
- package/skills/camox/references/layout-definitions.md +2 -0
- package/dist/core/lib/modifiers.js +0 -24
- package/dist/features/preview/previewQueryFns.js +0 -23
- package/dist/features/runtime/studioNavigation.js +0 -120
|
@@ -1,127 +1,112 @@
|
|
|
1
1
|
import { actionsStore } from "../provider/actionsStore.js";
|
|
2
|
+
import { STUDIO_THEME_STORAGE_KEY, bootstrapStudioTheme, readStudioTheme } from "./studioTheme.js";
|
|
2
3
|
import { c } from "react/compiler-runtime";
|
|
3
4
|
import * as React from "react";
|
|
4
5
|
|
|
5
6
|
//#region src/features/studio/useTheme.ts
|
|
6
7
|
let activeThemeOwnerCount = 0;
|
|
8
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
9
|
+
let preference;
|
|
7
10
|
function readStoredTheme() {
|
|
8
11
|
if (typeof window === "undefined") return "system";
|
|
9
|
-
return
|
|
12
|
+
return preference ?? readStudioTheme();
|
|
13
|
+
}
|
|
14
|
+
function subscribe(listener) {
|
|
15
|
+
listeners.add(listener);
|
|
16
|
+
return () => {
|
|
17
|
+
listeners.delete(listener);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function notify() {
|
|
21
|
+
listeners.forEach((listener) => listener());
|
|
22
|
+
}
|
|
23
|
+
function applyTheme(theme = readStoredTheme()) {
|
|
24
|
+
bootstrapStudioTheme(theme);
|
|
25
|
+
const resolved = document.documentElement.dataset.camoxStudioTheme;
|
|
26
|
+
document.body.classList.remove("light", "dark");
|
|
27
|
+
document.body.classList.add("camox-studio-theme", resolved);
|
|
28
|
+
document.body.dataset.camoxStudioTheme = resolved;
|
|
29
|
+
}
|
|
30
|
+
function setTheme(theme) {
|
|
31
|
+
preference = theme;
|
|
32
|
+
try {
|
|
33
|
+
localStorage.setItem(STUDIO_THEME_STORAGE_KEY, theme);
|
|
34
|
+
} catch {}
|
|
35
|
+
applyTheme(theme);
|
|
36
|
+
notify();
|
|
10
37
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Owns the studio theme: writes the active class onto `<html>` and persists
|
|
13
|
-
* changes to localStorage. Should only be mounted from the studio chrome —
|
|
14
|
-
* never from contexts that share `<html>` with the user's site.
|
|
15
|
-
*/
|
|
16
38
|
function useApplyTheme() {
|
|
17
|
-
const $ = c(
|
|
18
|
-
if ($[0] !== "
|
|
19
|
-
for (let $i = 0; $i <
|
|
20
|
-
$[0] = "
|
|
39
|
+
const $ = c(5);
|
|
40
|
+
if ($[0] !== "5860ae8e48f7dc27e488236def482df22f144de61ae2d86bfde82aeeea4f9874") {
|
|
41
|
+
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
42
|
+
$[0] = "5860ae8e48f7dc27e488236def482df22f144de61ae2d86bfde82aeeea4f9874";
|
|
21
43
|
}
|
|
22
|
-
const
|
|
23
|
-
const
|
|
44
|
+
const theme = React.useSyncExternalStore(subscribe, readStoredTheme, _temp2);
|
|
45
|
+
const resolvedTheme = React.useSyncExternalStore(subscribe, _temp3, _temp4);
|
|
24
46
|
let t0;
|
|
47
|
+
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
|
48
|
+
t0 = [];
|
|
49
|
+
$[1] = t0;
|
|
50
|
+
} else t0 = $[1];
|
|
51
|
+
React.useEffect(_temp7, t0);
|
|
25
52
|
let t1;
|
|
26
|
-
if ($[
|
|
27
|
-
|
|
28
|
-
const root = window.document.documentElement;
|
|
29
|
-
const body = window.document.body;
|
|
30
|
-
activeThemeOwnerCount = activeThemeOwnerCount + 1;
|
|
31
|
-
const applyTheme = (themeToApply) => {
|
|
32
|
-
setResolvedTheme(themeToApply);
|
|
33
|
-
root.classList.remove("light", "dark");
|
|
34
|
-
root.classList.add(themeToApply);
|
|
35
|
-
root.dataset.camoxStudioTheme = themeToApply;
|
|
36
|
-
body.classList.remove("light", "dark");
|
|
37
|
-
body.classList.add("camox-studio-theme", themeToApply);
|
|
38
|
-
body.dataset.camoxStudioTheme = themeToApply;
|
|
39
|
-
};
|
|
40
|
-
const resolveTheme = () => {
|
|
41
|
-
if (theme !== "system") return theme;
|
|
42
|
-
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
43
|
-
};
|
|
44
|
-
applyTheme(resolveTheme());
|
|
45
|
-
const observer = new MutationObserver(() => {
|
|
46
|
-
const themeToApply_0 = resolveTheme();
|
|
47
|
-
if (root.classList.contains(themeToApply_0) && body.classList.contains(themeToApply_0)) return;
|
|
48
|
-
applyTheme(themeToApply_0);
|
|
49
|
-
});
|
|
50
|
-
observer.observe(root, {
|
|
51
|
-
attributes: true,
|
|
52
|
-
attributeFilter: ["class"]
|
|
53
|
-
});
|
|
54
|
-
observer.observe(body, {
|
|
55
|
-
attributes: true,
|
|
56
|
-
attributeFilter: ["class"]
|
|
57
|
-
});
|
|
58
|
-
if (theme === "system") {
|
|
59
|
-
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
60
|
-
const updateSystemTheme = () => applyTheme(resolveTheme());
|
|
61
|
-
mediaQuery.addEventListener("change", updateSystemTheme);
|
|
62
|
-
return () => {
|
|
63
|
-
mediaQuery.removeEventListener("change", updateSystemTheme);
|
|
64
|
-
observer.disconnect();
|
|
65
|
-
activeThemeOwnerCount = activeThemeOwnerCount - 1;
|
|
66
|
-
if (activeThemeOwnerCount > 0) return;
|
|
67
|
-
root.classList.remove("light", "dark");
|
|
68
|
-
delete root.dataset.camoxStudioTheme;
|
|
69
|
-
body.classList.remove("camox-studio-theme", "light", "dark");
|
|
70
|
-
delete body.dataset.camoxStudioTheme;
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
return () => {
|
|
74
|
-
observer.disconnect();
|
|
75
|
-
activeThemeOwnerCount = activeThemeOwnerCount - 1;
|
|
76
|
-
if (activeThemeOwnerCount > 0) return;
|
|
77
|
-
root.classList.remove("light", "dark");
|
|
78
|
-
delete root.dataset.camoxStudioTheme;
|
|
79
|
-
body.classList.remove("camox-studio-theme", "light", "dark");
|
|
80
|
-
delete body.dataset.camoxStudioTheme;
|
|
81
|
-
};
|
|
82
|
-
};
|
|
83
|
-
t1 = [theme];
|
|
84
|
-
$[1] = theme;
|
|
85
|
-
$[2] = t0;
|
|
86
|
-
$[3] = t1;
|
|
87
|
-
} else {
|
|
88
|
-
t0 = $[2];
|
|
89
|
-
t1 = $[3];
|
|
90
|
-
}
|
|
91
|
-
React.useEffect(t0, t1);
|
|
92
|
-
let t2;
|
|
93
|
-
let t3;
|
|
94
|
-
if ($[4] !== theme) {
|
|
95
|
-
t2 = () => {
|
|
96
|
-
localStorage.setItem("theme", theme);
|
|
97
|
-
};
|
|
98
|
-
t3 = [theme];
|
|
99
|
-
$[4] = theme;
|
|
100
|
-
$[5] = t2;
|
|
101
|
-
$[6] = t3;
|
|
102
|
-
} else {
|
|
103
|
-
t2 = $[5];
|
|
104
|
-
t3 = $[6];
|
|
105
|
-
}
|
|
106
|
-
React.useEffect(t2, t3);
|
|
107
|
-
let t4;
|
|
108
|
-
if ($[7] !== resolvedTheme || $[8] !== theme) {
|
|
109
|
-
t4 = {
|
|
53
|
+
if ($[2] !== resolvedTheme || $[3] !== theme) {
|
|
54
|
+
t1 = {
|
|
110
55
|
theme,
|
|
111
56
|
resolvedTheme,
|
|
112
57
|
setTheme
|
|
113
58
|
};
|
|
114
|
-
$[
|
|
115
|
-
$[
|
|
116
|
-
$[
|
|
117
|
-
} else
|
|
118
|
-
return
|
|
59
|
+
$[2] = resolvedTheme;
|
|
60
|
+
$[3] = theme;
|
|
61
|
+
$[4] = t1;
|
|
62
|
+
} else t1 = $[4];
|
|
63
|
+
return t1;
|
|
64
|
+
}
|
|
65
|
+
function _temp7() {
|
|
66
|
+
const root = window.document.documentElement;
|
|
67
|
+
const body = window.document.body;
|
|
68
|
+
activeThemeOwnerCount = activeThemeOwnerCount + 1;
|
|
69
|
+
setTheme(readStoredTheme());
|
|
70
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
71
|
+
const updateSystemTheme = _temp5;
|
|
72
|
+
const onStorage = _temp6;
|
|
73
|
+
mediaQuery.addEventListener("change", updateSystemTheme);
|
|
74
|
+
window.addEventListener("storage", onStorage);
|
|
75
|
+
return () => {
|
|
76
|
+
mediaQuery.removeEventListener("change", updateSystemTheme);
|
|
77
|
+
window.removeEventListener("storage", onStorage);
|
|
78
|
+
activeThemeOwnerCount = activeThemeOwnerCount - 1;
|
|
79
|
+
if (activeThemeOwnerCount > 0) return;
|
|
80
|
+
root.classList.remove("light", "dark");
|
|
81
|
+
root.style.removeProperty("color-scheme");
|
|
82
|
+
delete root.dataset.camoxStudioTheme;
|
|
83
|
+
body.classList.remove("camox-studio-theme", "light", "dark");
|
|
84
|
+
delete body.dataset.camoxStudioTheme;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function _temp6(event) {
|
|
88
|
+
if (event.key !== "camox:studio:theme" && event.key !== null) return;
|
|
89
|
+
preference = void 0;
|
|
90
|
+
applyTheme();
|
|
91
|
+
notify();
|
|
92
|
+
}
|
|
93
|
+
function _temp5() {
|
|
94
|
+
if (readStoredTheme() === "system") setTheme("system");
|
|
95
|
+
}
|
|
96
|
+
function _temp4() {
|
|
97
|
+
return "light";
|
|
98
|
+
}
|
|
99
|
+
function _temp3() {
|
|
100
|
+
return document.documentElement.dataset.camoxStudioTheme === "dark" ? "dark" : "light";
|
|
101
|
+
}
|
|
102
|
+
function _temp2() {
|
|
103
|
+
return "system";
|
|
119
104
|
}
|
|
120
105
|
function useThemeActions() {
|
|
121
106
|
const $ = c(5);
|
|
122
|
-
if ($[0] !== "
|
|
107
|
+
if ($[0] !== "5860ae8e48f7dc27e488236def482df22f144de61ae2d86bfde82aeeea4f9874") {
|
|
123
108
|
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
124
|
-
$[0] = "
|
|
109
|
+
$[0] = "5860ae8e48f7dc27e488236def482df22f144de61ae2d86bfde82aeeea4f9874";
|
|
125
110
|
}
|
|
126
111
|
const { theme, setTheme } = useApplyTheme();
|
|
127
112
|
let t0;
|
|
@@ -138,9 +123,9 @@ function useThemeActions() {
|
|
|
138
123
|
"Color mode"
|
|
139
124
|
],
|
|
140
125
|
groupLabel: "Studio",
|
|
141
|
-
checkIfAvailable:
|
|
126
|
+
checkIfAvailable: _temp8,
|
|
142
127
|
hasChildren: true,
|
|
143
|
-
execute:
|
|
128
|
+
execute: _temp9
|
|
144
129
|
},
|
|
145
130
|
{
|
|
146
131
|
id: "switch-to-light-theme",
|
|
@@ -177,7 +162,7 @@ function useThemeActions() {
|
|
|
177
162
|
return () => {
|
|
178
163
|
actionsStore.send({
|
|
179
164
|
type: "unregisterManyActions",
|
|
180
|
-
ids: actions.map(
|
|
165
|
+
ids: actions.map(_temp0)
|
|
181
166
|
});
|
|
182
167
|
};
|
|
183
168
|
};
|
|
@@ -192,11 +177,11 @@ function useThemeActions() {
|
|
|
192
177
|
}
|
|
193
178
|
React.useEffect(t0, t1);
|
|
194
179
|
}
|
|
195
|
-
function
|
|
180
|
+
function _temp0(a) {
|
|
196
181
|
return a.id;
|
|
197
182
|
}
|
|
198
|
-
function
|
|
199
|
-
function
|
|
183
|
+
function _temp9() {}
|
|
184
|
+
function _temp8() {
|
|
200
185
|
return true;
|
|
201
186
|
}
|
|
202
187
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { writeIfChanged } from "./utils.js";
|
|
2
|
+
import { generateLayoutFiles } from "./layoutGeneration.js";
|
|
2
3
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
3
4
|
import { relative, resolve } from "node:path";
|
|
4
5
|
|
|
@@ -28,16 +29,16 @@ const blocks = [...Object.values(blockModules), ...Object.values(legacyBlockModu
|
|
|
28
29
|
);
|
|
29
30
|
|
|
30
31
|
// Auto-import all layouts from the first-class layouts directory
|
|
31
|
-
const layoutModules = import.meta.glob<{ layout
|
|
32
|
+
const layoutModules = import.meta.glob<{ layout?: Layout; Layout?: Layout }>(
|
|
32
33
|
'../layouts/*.{ts,tsx}',
|
|
33
34
|
{ eager: true },
|
|
34
35
|
);
|
|
35
|
-
const legacyLayoutModules = import.meta.glob<{ layout
|
|
36
|
+
const legacyLayoutModules = import.meta.glob<{ layout?: Layout; Layout?: Layout }>(
|
|
36
37
|
'./layouts/*.{ts,tsx}',
|
|
37
38
|
{ eager: true },
|
|
38
39
|
);
|
|
39
40
|
const layouts = [...Object.values(layoutModules), ...Object.values(legacyLayoutModules)].map(
|
|
40
|
-
(mod) => mod.layout
|
|
41
|
+
(mod) => (mod.Layout ?? mod.layout)!,
|
|
41
42
|
);
|
|
42
43
|
|
|
43
44
|
export const camoxApp = createApp({
|
|
@@ -53,9 +54,17 @@ function getAppFileEntries(appRoot) {
|
|
|
53
54
|
}];
|
|
54
55
|
}
|
|
55
56
|
function generateAppFile(appRoot) {
|
|
57
|
+
generateLayoutFiles(appRoot);
|
|
56
58
|
for (const entry of getAppFileEntries(appRoot)) writeIfChanged(entry.path, entry.content);
|
|
57
59
|
}
|
|
58
60
|
function watchAppFile(server, appRoot) {
|
|
61
|
+
for (const event of [
|
|
62
|
+
"add",
|
|
63
|
+
"change",
|
|
64
|
+
"unlink"
|
|
65
|
+
]) server.watcher.on(event, (path) => {
|
|
66
|
+
if (path.startsWith(resolve(appRoot, "src/layouts") + "/")) generateLayoutFiles(appRoot);
|
|
67
|
+
});
|
|
59
68
|
const entries = getAppFileEntries(appRoot);
|
|
60
69
|
const expectedByPath = new Map(entries.map((e) => [e.path, e.content]));
|
|
61
70
|
server.watcher.on("change", (changedPath) => {
|
|
@@ -32,7 +32,8 @@ async function syncDefinitionsToApi(options) {
|
|
|
32
32
|
settingsSchema: block._internal.settingsSchema,
|
|
33
33
|
defaultContent: block._internal.getInitialContent(),
|
|
34
34
|
defaultSettings: block._internal.getInitialSettings(),
|
|
35
|
-
layoutOnly: block._internal.layoutOnly || void 0
|
|
35
|
+
layoutOnly: block._internal.layoutOnly || void 0,
|
|
36
|
+
synced: block._internal.synced
|
|
36
37
|
}));
|
|
37
38
|
let environmentCreated = false;
|
|
38
39
|
let deletedDefinitionTypes = [];
|
|
@@ -186,7 +187,8 @@ async function syncDefinitions(server, options) {
|
|
|
186
187
|
settingsSchema: block._internal.settingsSchema,
|
|
187
188
|
defaultContent: block._internal.getInitialContent(),
|
|
188
189
|
defaultSettings: block._internal.getInitialSettings(),
|
|
189
|
-
layoutOnly: block._internal.layoutOnly || void 0
|
|
190
|
+
layoutOnly: block._internal.layoutOnly || void 0,
|
|
191
|
+
synced: block._internal.synced
|
|
190
192
|
});
|
|
191
193
|
} catch (error) {
|
|
192
194
|
throwIfSyncAuthError(error);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { writeIfChanged } from "./utils.js";
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { basename, resolve } from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/features/vite/layoutGeneration.ts
|
|
6
|
+
/** Keep file identities stable across moves without executing application modules. */
|
|
7
|
+
function generateLayoutFiles(appRoot) {
|
|
8
|
+
const directory = resolve(appRoot, "src/layouts");
|
|
9
|
+
if (!existsSync(directory)) return;
|
|
10
|
+
const declarations = [];
|
|
11
|
+
for (const file of readdirSync(directory).sort()) {
|
|
12
|
+
if (!/\.(ts|tsx)$/.test(file) || file.endsWith(".d.ts")) continue;
|
|
13
|
+
const id = basename(file).replace(/\.(ts|tsx)$/, "");
|
|
14
|
+
const path = resolve(directory, file);
|
|
15
|
+
let source = readFileSync(path, "utf8");
|
|
16
|
+
if (!source.trim()) source = `import { createLayout } from "camox/createLayout";
|
|
17
|
+
|
|
18
|
+
export const Layout = createLayout(${JSON.stringify(id)})({
|
|
19
|
+
kind: "curated",
|
|
20
|
+
title: ${JSON.stringify(id)},
|
|
21
|
+
description: "",
|
|
22
|
+
blocks: { before: [], after: [] },
|
|
23
|
+
buildMetaTitle: ({ pageMetaTitle }) => pageMetaTitle,
|
|
24
|
+
component: ({ children }) => <main><Layout.BeforeBlocks />{children}<Layout.AfterBlocks /></main>,
|
|
25
|
+
});
|
|
26
|
+
`;
|
|
27
|
+
source = source.replace(/(createLayout\(\s*)["'][^"']+["'](\s*\)\s*\()/g, `$1${JSON.stringify(id)}$2`);
|
|
28
|
+
writeIfChanged(path, source);
|
|
29
|
+
const segments = id.split(".");
|
|
30
|
+
const route = "/" + segments.map((segment) => segment.startsWith("$") ? `:${segment.slice(1)}` : segment).join("/");
|
|
31
|
+
const params = segments.filter((segment) => segment.startsWith("$")).map((segment) => `${JSON.stringify(segment.slice(1))}: string`).join("; ");
|
|
32
|
+
declarations.push(`${JSON.stringify(id)}: { route: ${JSON.stringify(route)}; params: { ${params} } };`);
|
|
33
|
+
}
|
|
34
|
+
writeIfChanged(resolve(appRoot, "src/camox/layouts.gen.d.ts"), `// Generated by Camox.\nimport "camox/createLayout";\ndeclare module "camox/createLayout" {\n interface LayoutFileRoutes {\n ${declarations.join("\n ")}\n }\n}\n`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
export { generateLayoutFiles };
|
|
@@ -79,7 +79,7 @@ const blocks = [...Object.values(rootBlockModules), ...Object.values(legacyBlock
|
|
|
79
79
|
.map((mod) => mod.block)
|
|
80
80
|
.filter(Boolean);
|
|
81
81
|
const layouts = [...Object.values(rootLayoutModules), ...Object.values(legacyLayoutModules)]
|
|
82
|
-
.map((mod) => mod.layout)
|
|
82
|
+
.map((mod) => mod.Layout ?? mod.layout)
|
|
83
83
|
.filter(Boolean);
|
|
84
84
|
|
|
85
85
|
export const camoxApp = createApp({ blocks, layouts });
|
|
@@ -146,6 +146,7 @@ function generateVirtualCamoxServer(runtimeBasePath) {
|
|
|
146
146
|
import { camoxApp } from "virtual:camox/app";
|
|
147
147
|
import { camoxDocument } from "virtual:camox/document";
|
|
148
148
|
import appStylesheetUrl from "virtual:camox/app-stylesheet-url";
|
|
149
|
+
import studioStylesheetUrl from "virtual:camox-studio-css";
|
|
149
150
|
import pageClientEntryUrl from "virtual:camox/page-client-url";
|
|
150
151
|
import studioClientEntryUrl from "virtual:camox/studio-client-url";
|
|
151
152
|
import { renderPage } from "virtual:camox/page-server";
|
|
@@ -165,6 +166,7 @@ export async function handleCamoxRequest(request) {
|
|
|
165
166
|
renderStudio,
|
|
166
167
|
runtimeBasePath: ${JSON.stringify(runtimeBasePath)},
|
|
167
168
|
stylesheetUrl: appStylesheetUrl,
|
|
169
|
+
studioStylesheetUrl,
|
|
168
170
|
});
|
|
169
171
|
}
|
|
170
172
|
`;
|
package/dist/lib/auth.js
CHANGED
|
@@ -217,9 +217,9 @@ function useProcessOtt(authClient) {
|
|
|
217
217
|
const AuthContext = React.createContext(null);
|
|
218
218
|
function useAuthContext() {
|
|
219
219
|
const $ = c(1);
|
|
220
|
-
if ($[0] !== "
|
|
220
|
+
if ($[0] !== "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b") {
|
|
221
221
|
for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
222
|
-
$[0] = "
|
|
222
|
+
$[0] = "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b";
|
|
223
223
|
}
|
|
224
224
|
const ctx = React.useContext(AuthContext);
|
|
225
225
|
if (!ctx) throw new Error("Missing CamoxProvider");
|
|
@@ -227,34 +227,36 @@ function useAuthContext() {
|
|
|
227
227
|
}
|
|
228
228
|
function useProjectSlug() {
|
|
229
229
|
const $ = c(1);
|
|
230
|
-
if ($[0] !== "
|
|
230
|
+
if ($[0] !== "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b") {
|
|
231
231
|
for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
232
|
-
$[0] = "
|
|
232
|
+
$[0] = "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b";
|
|
233
233
|
}
|
|
234
234
|
return useAuthContext().projectSlug;
|
|
235
235
|
}
|
|
236
|
+
const subscribeToHydration = () => () => {};
|
|
236
237
|
function useAuthState() {
|
|
237
|
-
const { authClient } = useAuthContext();
|
|
238
|
+
const { authClient, initialAuthenticated = false } = useAuthContext();
|
|
238
239
|
const { data: session, isPending } = authClient.useSession();
|
|
240
|
+
const useInitial = !React.useSyncExternalStore(subscribeToHydration, () => true, () => false) || isPending;
|
|
239
241
|
return {
|
|
240
|
-
isAuthenticated: !!session,
|
|
241
|
-
isLoading:
|
|
242
|
+
isAuthenticated: useInitial ? initialAuthenticated : !!session,
|
|
243
|
+
isLoading: useInitial && !initialAuthenticated
|
|
242
244
|
};
|
|
243
245
|
}
|
|
244
246
|
function useIsAuthenticated() {
|
|
245
247
|
const $ = c(1);
|
|
246
|
-
if ($[0] !== "
|
|
248
|
+
if ($[0] !== "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b") {
|
|
247
249
|
for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
248
|
-
$[0] = "
|
|
250
|
+
$[0] = "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b";
|
|
249
251
|
}
|
|
250
252
|
const { isAuthenticated } = useAuthState();
|
|
251
253
|
return isAuthenticated;
|
|
252
254
|
}
|
|
253
255
|
function useSignInRedirect(callbackHref) {
|
|
254
256
|
const $ = c(4);
|
|
255
|
-
if ($[0] !== "
|
|
257
|
+
if ($[0] !== "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b") {
|
|
256
258
|
for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
257
|
-
$[0] = "
|
|
259
|
+
$[0] = "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b";
|
|
258
260
|
}
|
|
259
261
|
const { authenticationUrl } = useAuthContext();
|
|
260
262
|
let t0;
|
|
@@ -276,9 +278,9 @@ function useSignInRedirect(callbackHref) {
|
|
|
276
278
|
*/
|
|
277
279
|
function useAuthActions() {
|
|
278
280
|
const $ = c(5);
|
|
279
|
-
if ($[0] !== "
|
|
281
|
+
if ($[0] !== "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b") {
|
|
280
282
|
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
281
|
-
$[0] = "
|
|
283
|
+
$[0] = "613abd4be0f81de0bf8df48c671a83e40c3e6ac86dab4c38ebcffe92268b614b";
|
|
282
284
|
}
|
|
283
285
|
const { authClient, authenticationUrl } = useAuthContext();
|
|
284
286
|
let t0;
|
|
@@ -11,9 +11,9 @@ const NormalizedDataContext = React.createContext({
|
|
|
11
11
|
});
|
|
12
12
|
const NormalizedDataProvider = (t0) => {
|
|
13
13
|
const $ = c(13);
|
|
14
|
-
if ($[0] !== "
|
|
14
|
+
if ($[0] !== "28aab7b25bd21e351d34503ab3d745344dc158d8c4a4ad7a8c63e2c8732703bb") {
|
|
15
15
|
for (let $i = 0; $i < 13; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
16
|
-
$[0] = "
|
|
16
|
+
$[0] = "28aab7b25bd21e351d34503ab3d745344dc158d8c4a4ad7a8c63e2c8732703bb";
|
|
17
17
|
}
|
|
18
18
|
const { files, repeatableItems, children } = t0;
|
|
19
19
|
let t1;
|
|
@@ -74,9 +74,9 @@ function useStableArray(next) {
|
|
|
74
74
|
}
|
|
75
75
|
function usePageBlocks(pageStructure, t0) {
|
|
76
76
|
const $ = c(37);
|
|
77
|
-
if ($[0] !== "
|
|
77
|
+
if ($[0] !== "28aab7b25bd21e351d34503ab3d745344dc158d8c4a4ad7a8c63e2c8732703bb") {
|
|
78
78
|
for (let $i = 0; $i < 37; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
79
|
-
$[0] = "
|
|
79
|
+
$[0] = "28aab7b25bd21e351d34503ab3d745344dc158d8c4a4ad7a8c63e2c8732703bb";
|
|
80
80
|
}
|
|
81
81
|
const source = t0 === void 0 ? "draft" : t0;
|
|
82
82
|
const blockIds = pageStructure.page.blockIds;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/lib/platform.ts
|
|
2
|
+
function bootstrapPlatform() {
|
|
3
|
+
document.documentElement.dataset.camoxPlatform = /Mac|iPhone|iPad|iPod/i.test(navigator.userAgent) ? "mac" : "other";
|
|
4
|
+
}
|
|
5
|
+
const PLATFORM_SCRIPT = `(${bootstrapPlatform.toString()})();`;
|
|
6
|
+
const PLATFORM_LABEL_CSS = `
|
|
7
|
+
.camox-platform-mac{display:none}
|
|
8
|
+
:root[data-camox-platform="mac"] .camox-platform-mac{display:inline}
|
|
9
|
+
:root[data-camox-platform="mac"] .camox-platform-other{display:none}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { PLATFORM_LABEL_CSS, PLATFORM_SCRIPT, bootstrapPlatform };
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PlatformLabel } from "../components/PlatformLabel.js";
|
|
2
|
+
import { c } from "react/compiler-runtime";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
4
|
import { Kbd } from "@camox/ui/kbd";
|
|
3
5
|
import { INPUT_BASE_STYLES, INPUT_FOCUS_STYLES, cn } from "@camox/ui/utils";
|
|
4
6
|
|
|
@@ -21,44 +23,94 @@ function checkIfInputFocused(document = window.document) {
|
|
|
21
23
|
*/
|
|
22
24
|
function formatShortcut(shortcut) {
|
|
23
25
|
if (!shortcut) return null;
|
|
24
|
-
|
|
25
|
-
const modifiers = [];
|
|
26
|
-
if (shortcut.withMeta) modifiers.push(isMac ? "⌘" : "Ctrl");
|
|
27
|
-
if (shortcut.withAlt) modifiers.push(isMac ? "⌥" : "Alt");
|
|
28
|
-
if (shortcut.withShift) modifiers.push(isMac ? "⇧" : "Shift");
|
|
29
|
-
const formattedKey = (() => {
|
|
30
|
-
if (shortcut.key === "Enter") return "↵";
|
|
31
|
-
if (shortcut.key === "Escape") return "Esc";
|
|
32
|
-
if (shortcut.key === "Backspace") return "⌫";
|
|
33
|
-
if (shortcut.key === "ArrowUp") return "↑";
|
|
34
|
-
if (shortcut.key === "ArrowDown") return "↓";
|
|
35
|
-
if (shortcut.key === "ArrowLeft") return "←";
|
|
36
|
-
if (shortcut.key === "ArrowRight") return "→";
|
|
37
|
-
return shortcut.key.toUpperCase();
|
|
38
|
-
})();
|
|
39
|
-
return /* @__PURE__ */ jsxs(Kbd, { children: [
|
|
40
|
-
modifiers.join(),
|
|
41
|
-
" ",
|
|
42
|
-
formattedKey
|
|
43
|
-
] });
|
|
26
|
+
return /* @__PURE__ */ jsx(Shortcut, { shortcut });
|
|
44
27
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
28
|
+
function Shortcut(t0) {
|
|
29
|
+
const $ = c(15);
|
|
30
|
+
if ($[0] !== "45dff80dbc1805709c694dadbd04b0216f01c3a1a826daf47b8bb5bac9e42d9a") {
|
|
31
|
+
for (let $i = 0; $i < 15; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
32
|
+
$[0] = "45dff80dbc1805709c694dadbd04b0216f01c3a1a826daf47b8bb5bac9e42d9a";
|
|
33
|
+
}
|
|
34
|
+
const { shortcut } = t0;
|
|
35
|
+
let t1;
|
|
36
|
+
bb0: {
|
|
37
|
+
if (shortcut.key === "Enter") {
|
|
38
|
+
t1 = "↵";
|
|
39
|
+
break bb0;
|
|
40
|
+
}
|
|
41
|
+
if (shortcut.key === "Escape") {
|
|
42
|
+
t1 = "Esc";
|
|
43
|
+
break bb0;
|
|
44
|
+
}
|
|
45
|
+
if (shortcut.key === "Backspace") {
|
|
46
|
+
t1 = "⌫";
|
|
47
|
+
break bb0;
|
|
48
|
+
}
|
|
49
|
+
if (shortcut.key === "ArrowUp") {
|
|
50
|
+
t1 = "↑";
|
|
51
|
+
break bb0;
|
|
52
|
+
}
|
|
53
|
+
if (shortcut.key === "ArrowDown") {
|
|
54
|
+
t1 = "↓";
|
|
55
|
+
break bb0;
|
|
56
|
+
}
|
|
57
|
+
if (shortcut.key === "ArrowLeft") {
|
|
58
|
+
t1 = "←";
|
|
59
|
+
break bb0;
|
|
60
|
+
}
|
|
61
|
+
if (shortcut.key === "ArrowRight") {
|
|
62
|
+
t1 = "→";
|
|
63
|
+
break bb0;
|
|
64
|
+
}
|
|
65
|
+
let t2;
|
|
66
|
+
if ($[1] !== shortcut.key) {
|
|
67
|
+
t2 = shortcut.key.toUpperCase();
|
|
68
|
+
$[1] = shortcut.key;
|
|
69
|
+
$[2] = t2;
|
|
70
|
+
} else t2 = $[2];
|
|
71
|
+
t1 = t2;
|
|
72
|
+
}
|
|
73
|
+
const formattedKey = t1;
|
|
74
|
+
let t2;
|
|
75
|
+
if ($[3] !== formattedKey || $[4] !== shortcut.withAlt || $[5] !== shortcut.withMeta || $[6] !== shortcut.withShift) {
|
|
76
|
+
t2 = (mac) => {
|
|
77
|
+
const modifiers = [];
|
|
78
|
+
if (shortcut.withMeta) modifiers.push(mac ? "⌘" : "Ctrl");
|
|
79
|
+
if (shortcut.withAlt) modifiers.push(mac ? "⌥" : "Alt");
|
|
80
|
+
if (shortcut.withShift) modifiers.push(mac ? "⇧" : "Shift");
|
|
81
|
+
return `${modifiers.join()} ${formattedKey}`.trim();
|
|
82
|
+
};
|
|
83
|
+
$[3] = formattedKey;
|
|
84
|
+
$[4] = shortcut.withAlt;
|
|
85
|
+
$[5] = shortcut.withMeta;
|
|
86
|
+
$[6] = shortcut.withShift;
|
|
87
|
+
$[7] = t2;
|
|
88
|
+
} else t2 = $[7];
|
|
89
|
+
const label = t2;
|
|
90
|
+
let t3;
|
|
91
|
+
if ($[8] !== label) {
|
|
92
|
+
t3 = label(true);
|
|
93
|
+
$[8] = label;
|
|
94
|
+
$[9] = t3;
|
|
95
|
+
} else t3 = $[9];
|
|
96
|
+
let t4;
|
|
97
|
+
if ($[10] !== label) {
|
|
98
|
+
t4 = label(false);
|
|
99
|
+
$[10] = label;
|
|
100
|
+
$[11] = t4;
|
|
101
|
+
} else t4 = $[11];
|
|
102
|
+
let t5;
|
|
103
|
+
if ($[12] !== t3 || $[13] !== t4) {
|
|
104
|
+
t5 = /* @__PURE__ */ jsx(Kbd, { children: /* @__PURE__ */ jsx(PlatformLabel, {
|
|
105
|
+
mac: t3,
|
|
106
|
+
other: t4
|
|
107
|
+
}) });
|
|
108
|
+
$[12] = t3;
|
|
109
|
+
$[13] = t4;
|
|
110
|
+
$[14] = t5;
|
|
111
|
+
} else t5 = $[14];
|
|
112
|
+
return t5;
|
|
61
113
|
}
|
|
62
114
|
|
|
63
115
|
//#endregion
|
|
64
|
-
export { INPUT_BASE_STYLES, INPUT_FOCUS_STYLES, checkIfInputFocused, cn, formatShortcut
|
|
116
|
+
export { INPUT_BASE_STYLES, INPUT_FOCUS_STYLES, checkIfInputFocused, cn, formatShortcut };
|