camox 0.32.0 → 0.33.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.
Files changed (58) hide show
  1. package/dist/core/createBlock.d.ts +1 -1
  2. package/dist/core/createBlock.js +88 -108
  3. package/dist/core/hooks/useIsEditable.js +6 -10
  4. package/dist/core/lib/fieldTypes.js +10 -219
  5. package/dist/features/agent-chat/components/AgentChatSidebar.js +172 -0
  6. package/dist/features/agent-chat/components/AgentChatThread.js +9 -9
  7. package/dist/features/preview/CamoxPreview.js +137 -729
  8. package/dist/features/preview/components/{AddBlockSheet.js → AddBlockSidebar.js} +121 -131
  9. package/dist/features/preview/components/AssetFieldEditor.js +107 -82
  10. package/dist/features/preview/components/AssetLightbox.js +4 -4
  11. package/dist/features/preview/components/AssetPickerModal.js +277 -0
  12. package/dist/features/preview/components/BlockActionsPopover.js +18 -24
  13. package/dist/features/preview/components/CreatePageModal.js +6 -6
  14. package/dist/features/preview/components/FieldToolbar.js +64 -127
  15. package/dist/features/preview/components/ItemFieldsEditor.js +98 -125
  16. package/dist/features/preview/components/LeftSidebar.js +64 -0
  17. package/dist/features/preview/components/LinkFieldEditor.js +1 -1
  18. package/dist/features/preview/components/MultipleAssetFieldEditor.js +94 -56
  19. package/dist/features/preview/components/OverlayTracker.js +15 -15
  20. package/dist/features/preview/components/Overlays.js +12 -12
  21. package/dist/features/preview/components/PageEditorSidebar.js +563 -0
  22. package/dist/features/preview/components/PageInfoSidebar.js +1453 -0
  23. package/dist/features/preview/components/PageNavigatorSidebar.js +590 -0
  24. package/dist/features/preview/components/PagePicker.js +3 -3
  25. package/dist/features/preview/components/PageStatusBadge.js +1 -1
  26. package/dist/features/preview/components/PageTree.js +204 -564
  27. package/dist/features/preview/components/PreviewPanel.js +123 -158
  28. package/dist/features/preview/components/PreviewToolbar.js +260 -256
  29. package/dist/features/preview/components/PublishDialog.js +2 -2
  30. package/dist/features/preview/components/RepeatableItemsList.js +2 -2
  31. package/dist/features/preview/components/RightSidebar.js +109 -0
  32. package/dist/features/preview/components/UnlinkAssetButton.js +2 -2
  33. package/dist/features/preview/components/useRepeatableItemActions.js +3 -138
  34. package/dist/features/preview/components/useUpdateBlockPosition.js +1 -1
  35. package/dist/features/preview/previewQueryFns.js +23 -0
  36. package/dist/features/preview/previewStore.js +46 -63
  37. package/dist/features/provider/CamoxProvider.js +255 -70
  38. package/dist/features/provider/useAdminShortcuts.js +5 -48
  39. package/dist/features/routes/pageRoute.js +1 -1
  40. package/dist/features/studio/CamoxStudio.js +6 -5
  41. package/dist/features/studio/components/EnvironmentMenu.js +2 -2
  42. package/dist/features/studio/components/Navbar.js +53 -71
  43. package/dist/features/studio/components/ProjectMenu.js +1 -1
  44. package/dist/features/studio/components/UserButton.js +1 -1
  45. package/dist/features/studio/routes.js +7 -0
  46. package/dist/features/studio/useTheme.js +67 -33
  47. package/dist/features/vite/routeGeneration.js +68 -66
  48. package/dist/hooks/use-file-upload.js +1 -1
  49. package/dist/lib/auth.js +23 -22
  50. package/dist/lib/utils.js +1 -1
  51. package/dist/studio-overlays.css +1 -1
  52. package/dist/studio.css +1 -1
  53. package/package.json +4 -4
  54. package/dist/features/agent-chat/components/AgentChatSheet.js +0 -207
  55. package/dist/features/preview/components/AssetPickerGrid.js +0 -236
  56. package/dist/features/preview/components/PageContentSheet.js +0 -608
  57. package/dist/features/preview/components/PageMetadataModal.js +0 -908
  58. package/dist/features/preview/components/PreviewSideSheet.js +0 -76
@@ -1,17 +1,17 @@
1
- import { useIsPreviewSheetOpen } from "../../preview/components/PreviewSideSheet.js";
2
1
  import { actionsStore } from "../../provider/actionsStore.js";
3
2
  import { useProjectSlug } from "../../../lib/auth.js";
4
3
  import { pageQueries, projectQueries } from "../../../lib/queries.js";
5
4
  import { cn } from "../../../lib/utils.js";
5
+ import { STUDIO_CONTENT_PATH } from "../routes.js";
6
6
  import { studioStore } from "../studioStore.js";
7
7
  import { EnvironmentMenu } from "./EnvironmentMenu.js";
8
8
  import { ProjectMenu } from "./ProjectMenu.js";
9
9
  import { UserButton } from "./UserButton.js";
10
10
  import { c } from "react/compiler-runtime";
11
- import { Kbd } from "@camox/ui/kbd";
12
11
  import { useQuery } from "@tanstack/react-query";
13
12
  import { Link, useLocation, useNavigate } from "@tanstack/react-router";
14
13
  import * as React from "react";
14
+ import { Kbd } from "@camox/ui/kbd";
15
15
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
16
  import { Button } from "@camox/ui/button";
17
17
  import { Database, Globe, SearchIcon } from "lucide-react";
@@ -24,7 +24,7 @@ const links = [{
24
24
  icon: "Globe",
25
25
  aliases: ["Preview", "Website"]
26
26
  }, {
27
- to: "/cmx-studio/content",
27
+ to: STUDIO_CONTENT_PATH,
28
28
  title: "Content",
29
29
  children: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Database, { className: "h-4 w-4" }), "Content"] }),
30
30
  icon: "FileText",
@@ -35,10 +35,10 @@ const links = [{
35
35
  ]
36
36
  }];
37
37
  const Navbar = () => {
38
- const $ = c(24);
39
- if ($[0] !== "bee8f3d13dbb280b2de1a82d82a4017e5a4d40d4e5868be00fe289eb0c74361f") {
40
- for (let $i = 0; $i < 24; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
41
- $[0] = "bee8f3d13dbb280b2de1a82d82a4017e5a4d40d4e5868be00fe289eb0c74361f";
38
+ const $ = c(19);
39
+ if ($[0] !== "eea0214bb845c9520caf17dd35f6ab89aaf76f8bfb610142be4d515eefd136f8") {
40
+ for (let $i = 0; $i < 19; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
41
+ $[0] = "eea0214bb845c9520caf17dd35f6ab89aaf76f8bfb610142be4d515eefd136f8";
42
42
  }
43
43
  const projectSlug = useProjectSlug();
44
44
  let t0;
@@ -68,75 +68,62 @@ const Navbar = () => {
68
68
  const { data: pages } = useQuery(t3);
69
69
  const isMac = navigator.userAgent.toUpperCase().indexOf("MAC") >= 0;
70
70
  const { pathname } = useLocation();
71
- const t4 = useIsPreviewSheetOpen() ? "opacity-100" : "opacity-0";
72
- let t5;
73
- if ($[8] !== t4) {
74
- t5 = cn("absolute top-0 left-0 w-full h-[calc(100%+2px)] bg-black/66 transition-opacity z-10 will-change-auto pointer-events-none", t4);
75
- $[8] = t4;
76
- $[9] = t5;
77
- } else t5 = $[9];
78
- let t6;
79
- if ($[10] !== t5) {
80
- t6 = /* @__PURE__ */ jsx("div", { className: t5 });
81
- $[10] = t5;
82
- $[11] = t6;
83
- } else t6 = $[11];
84
- let t7;
85
- if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
86
- t7 = /* @__PURE__ */ jsxs("div", {
71
+ let t4;
72
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
73
+ t4 = /* @__PURE__ */ jsxs("div", {
87
74
  className: "flew-row flex gap-1",
88
75
  children: [/* @__PURE__ */ jsx(ProjectMenu, {}), /* @__PURE__ */ jsx(EnvironmentMenu, {})]
89
76
  });
90
- $[12] = t7;
91
- } else t7 = $[12];
92
- let t8;
93
- if ($[13] !== pages || $[14] !== pathname) {
94
- t8 = links.map((link, index) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Link, {
77
+ $[8] = t4;
78
+ } else t4 = $[8];
79
+ let t5;
80
+ if ($[9] !== pages || $[10] !== pathname) {
81
+ t5 = links.map((link, index) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Link, {
95
82
  to: link.to,
96
83
  className: cn("flex gap-2 items-center rounded-md px-4 py-2 text-sm font-medium", "hover:bg-accent hover:text-accent-foreground outline-none transition-[color,box-shadow] focus-visible:ring-ring/50 focus-visible:ring-[3px] focus-visible:outline-1", pages?.some((page) => page.fullPath === pathname) && index === 0 ? "bg-accent hover:bg-accent text-accent-foreground" : "text-muted-foreground"),
97
84
  activeProps: { className: "bg-accent hover:bg-accent text-accent-foreground!" },
98
85
  children: link.children
99
86
  }) }, link.to));
100
- $[13] = pages;
101
- $[14] = pathname;
102
- $[15] = t8;
103
- } else t8 = $[15];
104
- let t9;
105
- if ($[16] !== t8) {
106
- t9 = /* @__PURE__ */ jsxs("div", {
87
+ $[9] = pages;
88
+ $[10] = pathname;
89
+ $[11] = t5;
90
+ } else t5 = $[11];
91
+ let t6;
92
+ if ($[12] !== t5) {
93
+ t6 = /* @__PURE__ */ jsxs("div", {
107
94
  className: "flex flex-row gap-2",
108
- children: [t7, /* @__PURE__ */ jsx("ul", {
95
+ children: [t4, /* @__PURE__ */ jsx("ul", {
109
96
  className: "flex items-center gap-1",
110
- children: t8
97
+ children: t5
111
98
  })]
112
99
  });
113
- $[16] = t8;
114
- $[17] = t9;
115
- } else t9 = $[17];
116
- let t10;
117
- let t11;
118
- if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
119
- t10 = /* @__PURE__ */ jsx(SearchIcon, { className: "text-muted-foreground size-4" });
120
- t11 = /* @__PURE__ */ jsx("span", {
100
+ $[12] = t5;
101
+ $[13] = t6;
102
+ } else t6 = $[13];
103
+ let t7;
104
+ let t8;
105
+ if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
106
+ t7 = /* @__PURE__ */ jsx(SearchIcon, { className: "text-muted-foreground size-4" });
107
+ t8 = /* @__PURE__ */ jsx("span", {
121
108
  className: "text-muted-foreground",
122
109
  children: "Quick find"
123
110
  });
124
- $[18] = t10;
125
- $[19] = t11;
111
+ $[14] = t7;
112
+ $[15] = t8;
126
113
  } else {
127
- t10 = $[18];
128
- t11 = $[19];
114
+ t7 = $[14];
115
+ t8 = $[15];
129
116
  }
130
- let t12;
131
- if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
132
- t12 = /* @__PURE__ */ jsxs("div", {
117
+ let t9;
118
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
119
+ t9 = /* @__PURE__ */ jsxs("div", {
133
120
  className: "flex items-center gap-2",
134
121
  children: [/* @__PURE__ */ jsxs(Button, {
135
122
  variant: "outline",
136
123
  onClick: _temp,
137
124
  children: [
138
- t10,
139
- t11,
125
+ t7,
126
+ t8,
140
127
  /* @__PURE__ */ jsxs(Kbd, {
141
128
  className: "ml-4",
142
129
  children: [isMac ? "⌘" : "Ctrl", " K"]
@@ -144,29 +131,24 @@ const Navbar = () => {
144
131
  ]
145
132
  }), /* @__PURE__ */ jsx(UserButton, {})]
146
133
  });
147
- $[20] = t12;
148
- } else t12 = $[20];
149
- let t13;
150
- if ($[21] !== t6 || $[22] !== t9) {
151
- t13 = /* @__PURE__ */ jsxs("nav", {
134
+ $[16] = t9;
135
+ } else t9 = $[16];
136
+ let t10;
137
+ if ($[17] !== t6) {
138
+ t10 = /* @__PURE__ */ jsxs("nav", {
152
139
  className: "relative flex items-center justify-between gap-4 border-b-2 bg-transparent px-2 py-2",
153
- children: [
154
- t6,
155
- t9,
156
- t12
157
- ]
140
+ children: [t6, t9]
158
141
  });
159
- $[21] = t6;
160
- $[22] = t9;
161
- $[23] = t13;
162
- } else t13 = $[23];
163
- return t13;
142
+ $[17] = t6;
143
+ $[18] = t10;
144
+ } else t10 = $[18];
145
+ return t10;
164
146
  };
165
147
  function useNavbarActions() {
166
148
  const $ = c(4);
167
- if ($[0] !== "bee8f3d13dbb280b2de1a82d82a4017e5a4d40d4e5868be00fe289eb0c74361f") {
149
+ if ($[0] !== "eea0214bb845c9520caf17dd35f6ab89aaf76f8bfb610142be4d515eefd136f8") {
168
150
  for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
169
- $[0] = "bee8f3d13dbb280b2de1a82d82a4017e5a4d40d4e5868be00fe289eb0c74361f";
151
+ $[0] = "eea0214bb845c9520caf17dd35f6ab89aaf76f8bfb610142be4d515eefd136f8";
170
152
  }
171
153
  const navigate = useNavigate();
172
154
  let t0;
@@ -6,8 +6,8 @@ import { Link } from "@tanstack/react-router";
6
6
  import * as React from "react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { Button } from "@camox/ui/button";
9
- import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@camox/ui/dropdown-menu";
10
9
  import { ChevronDown, Globe, Info, Settings, Users } from "lucide-react";
10
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@camox/ui/dropdown-menu";
11
11
  import { Skeleton } from "@camox/ui/skeleton";
12
12
 
13
13
  //#region src/features/studio/components/ProjectMenu.tsx
@@ -3,8 +3,8 @@ import { useApplyTheme } from "../useTheme.js";
3
3
  import { c } from "react/compiler-runtime";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { Button } from "@camox/ui/button";
6
- import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@camox/ui/dropdown-menu";
7
6
  import { Check, LogOut, Monitor, Moon, Settings, Sun, User } from "lucide-react";
7
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@camox/ui/dropdown-menu";
8
8
  import { Avatar, AvatarFallback, AvatarImage } from "@camox/ui/avatar";
9
9
 
10
10
  //#region src/features/studio/components/UserButton.tsx
@@ -0,0 +1,7 @@
1
+ //#region src/features/studio/routes.ts
2
+ const STUDIO_ROUTE_SEGMENT = "camox";
3
+ const STUDIO_BASE_PATH = `/${STUDIO_ROUTE_SEGMENT}`;
4
+ const STUDIO_CONTENT_PATH = `${STUDIO_BASE_PATH}/content`;
5
+
6
+ //#endregion
7
+ export { STUDIO_BASE_PATH, STUDIO_CONTENT_PATH, STUDIO_ROUTE_SEGMENT };
@@ -3,6 +3,7 @@ import { c } from "react/compiler-runtime";
3
3
  import * as React from "react";
4
4
 
5
5
  //#region src/features/studio/useTheme.ts
6
+ let activeThemeOwnerCount = 0;
6
7
  function readStoredTheme() {
7
8
  if (typeof window === "undefined") return "system";
8
9
  return localStorage.getItem("theme") || "system";
@@ -15,9 +16,9 @@ function readStoredTheme() {
15
16
  */
16
17
  function useThemeValue() {
17
18
  const $ = c(3);
18
- if ($[0] !== "fcb6efcbb121aaf74422b01742d77a7520178fc0fe001e78c2f3645c95a1fa7e") {
19
+ if ($[0] !== "da3935c3f496f05138d1e012522f8d34be97b470fa5c8f37185df49127eab10f") {
19
20
  for (let $i = 0; $i < 3; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
20
- $[0] = "fcb6efcbb121aaf74422b01742d77a7520178fc0fe001e78c2f3645c95a1fa7e";
21
+ $[0] = "da3935c3f496f05138d1e012522f8d34be97b470fa5c8f37185df49127eab10f";
21
22
  }
22
23
  const [theme] = React.useState(readStoredTheme);
23
24
  let t0;
@@ -34,34 +35,70 @@ function useThemeValue() {
34
35
  * never from contexts that share `<html>` with the user's site.
35
36
  */
36
37
  function useApplyTheme() {
37
- const $ = c(9);
38
- if ($[0] !== "fcb6efcbb121aaf74422b01742d77a7520178fc0fe001e78c2f3645c95a1fa7e") {
39
- for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
40
- $[0] = "fcb6efcbb121aaf74422b01742d77a7520178fc0fe001e78c2f3645c95a1fa7e";
38
+ const $ = c(10);
39
+ if ($[0] !== "da3935c3f496f05138d1e012522f8d34be97b470fa5c8f37185df49127eab10f") {
40
+ for (let $i = 0; $i < 10; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
41
+ $[0] = "da3935c3f496f05138d1e012522f8d34be97b470fa5c8f37185df49127eab10f";
41
42
  }
42
43
  const [theme, setTheme] = React.useState(readStoredTheme);
43
- const applyTheme = _temp;
44
+ const [resolvedTheme, setResolvedTheme] = React.useState("light");
44
45
  let t0;
45
46
  let t1;
46
47
  if ($[1] !== theme) {
47
48
  t0 = () => {
48
- const root_0 = window.document.documentElement;
49
- root_0.classList.remove("light", "dark");
49
+ const root = window.document.documentElement;
50
+ const body = window.document.body;
51
+ activeThemeOwnerCount = activeThemeOwnerCount + 1;
52
+ const applyTheme = (themeToApply) => {
53
+ setResolvedTheme(themeToApply);
54
+ root.classList.remove("light", "dark");
55
+ root.classList.add(themeToApply);
56
+ root.dataset.camoxStudioTheme = themeToApply;
57
+ body.classList.remove("light", "dark");
58
+ body.classList.add("camox-studio-theme", themeToApply);
59
+ body.dataset.camoxStudioTheme = themeToApply;
60
+ };
61
+ const resolveTheme = () => {
62
+ if (theme !== "system") return theme;
63
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
64
+ };
65
+ applyTheme(resolveTheme());
66
+ const observer = new MutationObserver(() => {
67
+ const themeToApply_0 = resolveTheme();
68
+ if (root.classList.contains(themeToApply_0) && body.classList.contains(themeToApply_0)) return;
69
+ applyTheme(themeToApply_0);
70
+ });
71
+ observer.observe(root, {
72
+ attributes: true,
73
+ attributeFilter: ["class"]
74
+ });
75
+ observer.observe(body, {
76
+ attributes: true,
77
+ attributeFilter: ["class"]
78
+ });
50
79
  if (theme === "system") {
51
80
  const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
52
- const updateSystemTheme = () => {
53
- applyTheme(mediaQuery.matches ? "dark" : "light");
54
- };
55
- updateSystemTheme();
81
+ const updateSystemTheme = () => applyTheme(resolveTheme());
56
82
  mediaQuery.addEventListener("change", updateSystemTheme);
57
83
  return () => {
58
84
  mediaQuery.removeEventListener("change", updateSystemTheme);
59
- root_0.classList.remove("light", "dark");
85
+ observer.disconnect();
86
+ activeThemeOwnerCount = activeThemeOwnerCount - 1;
87
+ if (activeThemeOwnerCount > 0) return;
88
+ root.classList.remove("light", "dark");
89
+ delete root.dataset.camoxStudioTheme;
90
+ body.classList.remove("camox-studio-theme", "light", "dark");
91
+ delete body.dataset.camoxStudioTheme;
60
92
  };
61
93
  }
62
- root_0.classList.add(theme);
63
94
  return () => {
64
- root_0.classList.remove("light", "dark");
95
+ observer.disconnect();
96
+ activeThemeOwnerCount = activeThemeOwnerCount - 1;
97
+ if (activeThemeOwnerCount > 0) return;
98
+ root.classList.remove("light", "dark");
99
+ delete root.dataset.camoxStudioTheme;
100
+ body.classList.remove("camox-studio-theme", "light", "dark");
101
+ delete body.dataset.camoxStudioTheme;
65
102
  };
66
103
  };
67
104
  t1 = [theme];
@@ -89,26 +126,23 @@ function useApplyTheme() {
89
126
  }
90
127
  React.useEffect(t2, t3);
91
128
  let t4;
92
- if ($[7] !== theme) {
129
+ if ($[7] !== resolvedTheme || $[8] !== theme) {
93
130
  t4 = {
94
131
  theme,
132
+ resolvedTheme,
95
133
  setTheme
96
134
  };
97
- $[7] = theme;
98
- $[8] = t4;
99
- } else t4 = $[8];
135
+ $[7] = resolvedTheme;
136
+ $[8] = theme;
137
+ $[9] = t4;
138
+ } else t4 = $[9];
100
139
  return t4;
101
140
  }
102
- function _temp(themeToApply) {
103
- const root = window.document.documentElement;
104
- root.classList.remove("light", "dark");
105
- root.classList.add(themeToApply);
106
- }
107
141
  function useThemeActions() {
108
142
  const $ = c(5);
109
- if ($[0] !== "fcb6efcbb121aaf74422b01742d77a7520178fc0fe001e78c2f3645c95a1fa7e") {
143
+ if ($[0] !== "da3935c3f496f05138d1e012522f8d34be97b470fa5c8f37185df49127eab10f") {
110
144
  for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
111
- $[0] = "fcb6efcbb121aaf74422b01742d77a7520178fc0fe001e78c2f3645c95a1fa7e";
145
+ $[0] = "da3935c3f496f05138d1e012522f8d34be97b470fa5c8f37185df49127eab10f";
112
146
  }
113
147
  const { theme, setTheme } = useApplyTheme();
114
148
  let t0;
@@ -125,9 +159,9 @@ function useThemeActions() {
125
159
  "Color mode"
126
160
  ],
127
161
  groupLabel: "Studio",
128
- checkIfAvailable: _temp2,
162
+ checkIfAvailable: _temp,
129
163
  hasChildren: true,
130
- execute: _temp3
164
+ execute: _temp2
131
165
  },
132
166
  {
133
167
  id: "switch-to-light-theme",
@@ -164,7 +198,7 @@ function useThemeActions() {
164
198
  return () => {
165
199
  actionsStore.send({
166
200
  type: "unregisterManyActions",
167
- ids: actions.map(_temp4)
201
+ ids: actions.map(_temp3)
168
202
  });
169
203
  };
170
204
  };
@@ -179,11 +213,11 @@ function useThemeActions() {
179
213
  }
180
214
  React.useEffect(t0, t1);
181
215
  }
182
- function _temp4(a) {
216
+ function _temp3(a) {
183
217
  return a.id;
184
218
  }
185
- function _temp3() {}
186
- function _temp2() {
219
+ function _temp2() {}
220
+ function _temp() {
187
221
  return true;
188
222
  }
189
223
 
@@ -1,5 +1,6 @@
1
+ import { STUDIO_ROUTE_SEGMENT } from "../studio/routes.js";
1
2
  import { writeIfChanged } from "./utils.js";
2
- import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
3
4
  import { relative, resolve } from "node:path";
4
5
 
5
6
  //#region src/features/vite/routeGeneration.ts
@@ -15,25 +16,7 @@ const HEADER = `/* =============================================================
15
16
  // @ts-nocheck
16
17
 
17
18
  `;
18
- function generateCamoxLayout(authenticationUrl) {
19
- return HEADER + `import { Outlet, createFileRoute } from "@tanstack/react-router";
20
- import { CamoxProvider } from "camox/CamoxProvider";
21
- import { camoxApp } from "@/camox/app";
22
-
23
- export const Route = createFileRoute("/_camox")({
24
- component: CamoxPathlessLayout,
25
- });
26
-
27
- function CamoxPathlessLayout() {
28
- return (
29
- <CamoxProvider camoxApp={camoxApp} authenticationUrl="${authenticationUrl}" apiUrl={__CAMOX_API_URL__} projectSlug={__CAMOX_PROJECT_SLUG__} environmentName={__CAMOX_ENVIRONMENT_NAME__}>
30
- <Outlet />
31
- </CamoxProvider>
32
- );
33
- }
34
- `;
35
- }
36
- function generatePageRoute() {
19
+ function generatePageRoute(authenticationUrl) {
37
20
  return HEADER + `import { createFileRoute } from "@tanstack/react-router";
38
21
  import {
39
22
  createMarkdownMiddleware,
@@ -41,21 +24,30 @@ import {
41
24
  createPageHead,
42
25
  PageRouteComponent,
43
26
  } from "camox/_internal/pageRoute";
27
+ import { CamoxProvider } from "camox/CamoxProvider";
44
28
  import { camoxApp } from "@/camox/app";
45
29
 
46
30
  const markdownMiddleware = createMarkdownMiddleware(__CAMOX_API_URL__, __CAMOX_PROJECT_SLUG__, __CAMOX_ENVIRONMENT_NAME__);
47
31
  const loader = createPageLoader(__CAMOX_API_URL__, __CAMOX_PROJECT_SLUG__, __CAMOX_ENVIRONMENT_NAME__);
48
32
  const head = createPageHead(camoxApp);
49
33
 
50
- export const Route = createFileRoute("/_camox/$")({
34
+ export const Route = createFileRoute("/(camox)/(_preview)/$")({
51
35
  server: {
52
36
  middleware: [markdownMiddleware],
53
37
  },
54
- component: PageRouteComponent,
38
+ component: RouteComponent,
55
39
  notFoundComponent: () => <div>No Camox page on this path</div>,
56
40
  loader,
57
41
  head,
58
42
  });
43
+
44
+ function RouteComponent() {
45
+ return (
46
+ <CamoxProvider camoxApp={camoxApp} authenticationUrl="${authenticationUrl}" apiUrl={__CAMOX_API_URL__} projectSlug={__CAMOX_PROJECT_SLUG__} environmentName={__CAMOX_ENVIRONMENT_NAME__}>
47
+ <PageRouteComponent />
48
+ </CamoxProvider>
49
+ );
50
+ }
59
51
  `;
60
52
  }
61
53
  function generateOgRoute() {
@@ -63,51 +55,40 @@ function generateOgRoute() {
63
55
  import { createOgHandler } from "camox/_internal/ogRoute";
64
56
  import { camoxApp } from "@/camox/app";
65
57
 
66
- export const Route = createFileRoute("/_camox/og")({
58
+ export const Route = createFileRoute("/(camox)/(_preview)/og")({
67
59
  server: {
68
60
  handlers: createOgHandler(camoxApp),
69
61
  },
70
62
  });
71
63
  `;
72
64
  }
73
- function generateCmxRedirect() {
74
- return HEADER + `import { createFileRoute, redirect } from "@tanstack/react-router";
75
-
76
- export const Route = createFileRoute("/_camox/cmx")({
77
- component: RouteComponent,
78
- loader: () => {
79
- throw redirect({ to: "/cmx-studio" });
80
- },
81
- });
82
-
83
- function RouteComponent() {
84
- return null;
85
- }
86
- `;
87
- }
88
- function generateCmxStudio() {
65
+ function generateCamoxStudio(authenticationUrl) {
89
66
  return HEADER + `import { Outlet, createFileRoute } from "@tanstack/react-router";
67
+ import { CamoxProvider } from "camox/CamoxProvider";
90
68
  import { CamoxStudio } from "camox/CamoxStudio";
69
+ import { camoxApp } from "@/camox/app";
91
70
 
92
- export const Route = createFileRoute("/_camox/cmx-studio")({
71
+ export const Route = createFileRoute("/(camox)/(_studio)/${STUDIO_ROUTE_SEGMENT}")({
93
72
  component: RouteComponent,
94
73
  notFoundComponent: () => <div>Studio page not found</div>,
95
74
  });
96
75
 
97
76
  function RouteComponent() {
98
77
  return (
99
- <CamoxStudio>
100
- <Outlet />
101
- </CamoxStudio>
78
+ <CamoxProvider camoxApp={camoxApp} authenticationUrl="${authenticationUrl}" apiUrl={__CAMOX_API_URL__} projectSlug={__CAMOX_PROJECT_SLUG__} environmentName={__CAMOX_ENVIRONMENT_NAME__}>
79
+ <CamoxStudio>
80
+ <Outlet />
81
+ </CamoxStudio>
82
+ </CamoxProvider>
102
83
  );
103
84
  }
104
85
  `;
105
86
  }
106
- function generateCmxStudioCatchAll() {
87
+ function generateCamoxStudioCatchAll() {
107
88
  return HEADER + `import { Outlet, createFileRoute } from "@tanstack/react-router";
108
89
  import { CamoxStudio } from "camox/CamoxStudio";
109
90
 
110
- export const Route = createFileRoute("/_camox/cmx-studio/$")({
91
+ export const Route = createFileRoute("/(camox)/(_studio)/${STUDIO_ROUTE_SEGMENT}/$")({
111
92
  component: RouteComponent,
112
93
  notFoundComponent: () => <div>Studio page not found</div>,
113
94
  });
@@ -121,11 +102,11 @@ function RouteComponent() {
121
102
  }
122
103
  `;
123
104
  }
124
- function generateCmxStudioContent() {
105
+ function generateCamoxStudioContent() {
125
106
  return HEADER + `import { createFileRoute } from "@tanstack/react-router";
126
107
  import { CamoxContent } from "camox/CamoxContent";
127
108
 
128
- export const Route = createFileRoute("/_camox/cmx-studio/content")({
109
+ export const Route = createFileRoute("/(camox)/(_studio)/${STUDIO_ROUTE_SEGMENT}/content")({
129
110
  component: RouteComponent,
130
111
  });
131
112
 
@@ -135,40 +116,61 @@ function RouteComponent() {
135
116
  `;
136
117
  }
137
118
  function getRouteFileEntries({ routesDir, authenticationUrl }) {
138
- const camoxDir = resolve(routesDir, "_camox");
119
+ const groupDir = resolve(routesDir, "(camox)");
120
+ const previewDir = resolve(groupDir, "(_preview)");
121
+ const studioDir = resolve(groupDir, "(_studio)");
139
122
  return [
140
123
  {
141
- path: resolve(routesDir, "_camox.tsx"),
142
- content: generateCamoxLayout(authenticationUrl)
143
- },
144
- {
145
- path: resolve(camoxDir, "$.tsx"),
146
- content: generatePageRoute()
124
+ path: resolve(previewDir, "$.tsx"),
125
+ content: generatePageRoute(authenticationUrl)
147
126
  },
148
127
  {
149
- path: resolve(camoxDir, "og.tsx"),
128
+ path: resolve(previewDir, "og.tsx"),
150
129
  content: generateOgRoute()
151
130
  },
152
131
  {
153
- path: resolve(camoxDir, "cmx.tsx"),
154
- content: generateCmxRedirect()
132
+ path: resolve(studioDir, `${STUDIO_ROUTE_SEGMENT}.tsx`),
133
+ content: generateCamoxStudio(authenticationUrl)
155
134
  },
156
135
  {
157
- path: resolve(camoxDir, "cmx-studio.tsx"),
158
- content: generateCmxStudio()
136
+ path: resolve(studioDir, `${STUDIO_ROUTE_SEGMENT}.$.tsx`),
137
+ content: generateCamoxStudioCatchAll()
159
138
  },
160
139
  {
161
- path: resolve(camoxDir, "cmx-studio.$.tsx"),
162
- content: generateCmxStudioCatchAll()
163
- },
164
- {
165
- path: resolve(camoxDir, "cmx-studio.content.tsx"),
166
- content: generateCmxStudioContent()
140
+ path: resolve(studioDir, `${STUDIO_ROUTE_SEGMENT}.content.tsx`),
141
+ content: generateCamoxStudioContent()
167
142
  }
168
143
  ];
169
144
  }
145
+ function removeObsoleteRouteFiles(routesDir) {
146
+ const camoxDir = resolve(routesDir, "_camox");
147
+ const studioDir = resolve(routesDir, "(camox)", "(_studio)");
148
+ const obsoletePaths = [
149
+ resolve(routesDir, "_camox.tsx"),
150
+ resolve(camoxDir, "cmx.tsx"),
151
+ resolve(camoxDir, "$.tsx"),
152
+ resolve(camoxDir, "og.tsx"),
153
+ resolve(camoxDir, "cmx-studio.tsx"),
154
+ resolve(camoxDir, "cmx-studio.$.tsx"),
155
+ resolve(camoxDir, "cmx-studio.content.tsx"),
156
+ resolve(studioDir, "cmx.tsx"),
157
+ resolve(studioDir, "cmx-studio.tsx"),
158
+ resolve(studioDir, "cmx-studio.$.tsx"),
159
+ resolve(studioDir, "cmx-studio.content.tsx")
160
+ ];
161
+ for (const filePath of obsoletePaths) try {
162
+ if (!readFileSync(filePath, "utf-8").startsWith(HEADER)) continue;
163
+ unlinkSync(filePath);
164
+ } catch (error) {
165
+ if (error.code === "ENOENT") continue;
166
+ throw error;
167
+ }
168
+ }
170
169
  function generateRouteFiles(options) {
171
- mkdirSync(resolve(options.routesDir, "_camox"), { recursive: true });
170
+ const groupDir = resolve(options.routesDir, "(camox)");
171
+ mkdirSync(resolve(groupDir, "(_preview)"), { recursive: true });
172
+ mkdirSync(resolve(groupDir, "(_studio)"), { recursive: true });
173
+ removeObsoleteRouteFiles(options.routesDir);
172
174
  for (const entry of getRouteFileEntries(options)) writeIfChanged(entry.path, entry.content);
173
175
  }
174
176
  function watchRouteFiles(options) {
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
- import { trackClientEvent } from "../lib/telemetry-client.js";
4
3
  import { getAuthCookieHeader } from "../lib/auth.js";
5
4
  import { getApiUrl, getEnvironmentName } from "../lib/api-client.js";
5
+ import { trackClientEvent } from "../lib/telemetry-client.js";
6
6
  import { useCallback, useRef, useState } from "react";
7
7
 
8
8
  //#region src/hooks/use-file-upload.ts