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.
Files changed (97) hide show
  1. package/dist/components/PlatformLabel.js +62 -0
  2. package/dist/core/components/lexical/GradientNode.js +126 -0
  3. package/dist/core/components/lexical/InlineLexicalEditor.js +37 -56
  4. package/dist/core/components/lexical/InlineStylesPlugin.js +183 -0
  5. package/dist/core/components/lexical/SelectionBroadcaster.js +49 -46
  6. package/dist/core/components/lexical/SidebarLexicalEditor.js +197 -151
  7. package/dist/core/components/lexical/editorConfig.js +25 -7
  8. package/dist/core/components/lexical/selectTextLink.js +21 -0
  9. package/dist/core/createApp.d.ts +30 -17
  10. package/dist/core/createApp.js +14 -3
  11. package/dist/core/createBlock.d.ts +2 -2
  12. package/dist/core/createBlock.js +18 -15
  13. package/dist/core/createLayout.d.ts +48 -4
  14. package/dist/core/createLayout.js +51 -23
  15. package/dist/core/derivedRoutes.js +36 -0
  16. package/dist/core/editing/createEditableBlock.d.ts +9 -8
  17. package/dist/core/editing/createEditableBlock.js +167 -168
  18. package/dist/core/lib/lexicalReact.d.ts +1 -26
  19. package/dist/core/lib/lexicalReact.js +46 -60
  20. package/dist/core/lib/lexicalState.js +164 -81
  21. package/dist/core/lib/modifierFormats.js +4 -15
  22. package/dist/core/lib/textStyles.d.ts +27 -0
  23. package/dist/core/lib/textStyles.js +47 -0
  24. package/dist/features/navigation/navigation.d.ts +2 -0
  25. package/dist/features/navigation/navigation.js +51 -46
  26. package/dist/features/page/DerivedPageContent.js +61 -0
  27. package/dist/features/page/PublishedPageContent.js +52 -83
  28. package/dist/features/page/SharedLayoutContent.js +66 -0
  29. package/dist/features/preview/CamoxPreview.d.ts +16 -1
  30. package/dist/features/preview/CamoxPreview.js +242 -265
  31. package/dist/features/preview/DerivedPreview.js +137 -0
  32. package/dist/features/preview/EditablePageExperience.js +25 -8
  33. package/dist/features/preview/components/AddBlockSidebar.js +43 -33
  34. package/dist/features/preview/components/AssetLightbox.js +1 -1
  35. package/dist/features/preview/components/BlockThumbnail.js +192 -0
  36. package/dist/features/preview/components/CreatePageModal.js +123 -115
  37. package/dist/features/preview/components/DerivedLayoutDialog.js +100 -0
  38. package/dist/features/preview/components/DerivedLayoutSidebar.d.ts +5 -0
  39. package/dist/features/preview/components/DerivedLayoutSidebar.js +163 -0
  40. package/dist/features/preview/components/DerivedPageInfoSidebar.js +57 -0
  41. package/dist/features/preview/components/FieldToolbar.js +42 -20
  42. package/dist/features/preview/components/Frame.js +133 -140
  43. package/dist/features/preview/components/LeftSidebar.js +42 -38
  44. package/dist/features/preview/components/MobilePreviewDrawer.js +4 -4
  45. package/dist/features/preview/components/Overlays.js +57 -42
  46. package/dist/features/preview/components/PageInfoSidebar.js +63 -55
  47. package/dist/features/preview/components/PageNavigatorSidebar.js +34 -483
  48. package/dist/features/preview/components/PagePicker.js +205 -153
  49. package/dist/features/preview/components/PageTree.js +298 -206
  50. package/dist/features/preview/components/PreviewActivation.js +78 -0
  51. package/dist/features/preview/components/PreviewPanel.js +67 -35
  52. package/dist/features/preview/components/PreviewToolbar.js +218 -232
  53. package/dist/features/preview/components/PublicationRow.js +431 -0
  54. package/dist/features/preview/components/PublishDialog.js +180 -97
  55. package/dist/features/preview/components/RightSidebar.js +19 -34
  56. package/dist/features/preview/components/previewStyles.js +8 -0
  57. package/dist/features/preview/components/useUpdateBlockPosition.js +7 -13
  58. package/dist/features/preview/previewConstants.js +8 -0
  59. package/dist/features/preview/previewStore.js +0 -10
  60. package/dist/features/preview/publication.js +71 -0
  61. package/dist/features/provider/AuthenticatedCamoxProvider.js +2 -1
  62. package/dist/features/provider/CoreCamoxProvider.js +11 -2
  63. package/dist/features/provider/LocalhostPreviewProvider.js +6 -7
  64. package/dist/features/routes/pageRuntime.d.ts +10 -0
  65. package/dist/features/routes/pageRuntime.js +7 -9
  66. package/dist/features/runtime/PreviewDocumentContext.js +7 -0
  67. package/dist/features/runtime/RuntimeChrome.js +137 -0
  68. package/dist/features/runtime/SharedChromeContext.js +7 -0
  69. package/dist/features/runtime/navigationRequest.js +21 -0
  70. package/dist/features/runtime/navigationTarget.js +23 -0
  71. package/dist/features/runtime/pageApp.js +196 -121
  72. package/dist/features/runtime/pageNavigation.js +79 -130
  73. package/dist/features/runtime/runtime.d.ts +11 -0
  74. package/dist/features/runtime/runtime.js +183 -47
  75. package/dist/features/runtime/studioApp.d.ts +2 -11
  76. package/dist/features/runtime/studioApp.js +14 -177
  77. package/dist/features/studio/CamoxStudio.js +27 -13
  78. package/dist/features/studio/components/Navbar.js +80 -74
  79. package/dist/features/studio/studioTheme.js +25 -0
  80. package/dist/features/studio/useTheme.js +94 -109
  81. package/dist/features/vite/appGeneration.js +12 -3
  82. package/dist/features/vite/definitionsSync.js +4 -2
  83. package/dist/features/vite/layoutGeneration.js +38 -0
  84. package/dist/features/vite/runtimeDev.js +3 -1
  85. package/dist/lib/auth.js +15 -13
  86. package/dist/lib/normalized-data.js +4 -4
  87. package/dist/lib/platform.js +13 -0
  88. package/dist/lib/utils.js +90 -38
  89. package/dist/studio-overlays.css +5 -40
  90. package/dist/studio.css +1 -1
  91. package/package.json +8 -4
  92. package/skills/camox/SKILL.md +2 -0
  93. package/skills/camox/references/block-definitions.md +31 -12
  94. package/skills/camox/references/layout-definitions.md +2 -0
  95. package/dist/core/lib/modifiers.js +0 -24
  96. package/dist/features/preview/previewQueryFns.js +0 -23
  97. package/dist/features/runtime/studioNavigation.js +0 -120
@@ -0,0 +1,137 @@
1
+ import { useIsAuthenticated, useProjectSlug } from "../../lib/auth.js";
2
+ import { getApiClient } from "../../lib/api-client.js";
3
+ import { seedBlockCaches } from "../../lib/normalized-data.js";
4
+ import { previewStore } from "./previewStore.js";
5
+ import { PreviewShell } from "./CamoxPreview.js";
6
+ import { DerivedPageContent } from "../page/DerivedPageContent.js";
7
+ import { c } from "react/compiler-runtime";
8
+ import { useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
9
+ import { jsx } from "react/jsx-runtime";
10
+ import { useSelector } from "@xstate/store-react";
11
+ import { queryKeys } from "@camox/api-contract/query-keys";
12
+
13
+ //#region src/features/preview/DerivedPreview.tsx
14
+ function DerivedPreview(props) {
15
+ const $ = c(5);
16
+ if ($[0] !== "261aac3044f545b5b17e0449fc914e6311b0108f3d16c419141b242a12b10dbe") {
17
+ for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
18
+ $[0] = "261aac3044f545b5b17e0449fc914e6311b0108f3d16c419141b242a12b10dbe";
19
+ }
20
+ if (!useIsAuthenticated()) {
21
+ let t0;
22
+ if ($[1] !== props) {
23
+ t0 = /* @__PURE__ */ jsx(DerivedPageContent, { ...props });
24
+ $[1] = props;
25
+ $[2] = t0;
26
+ } else t0 = $[2];
27
+ return t0;
28
+ }
29
+ let t0;
30
+ if ($[3] !== props) {
31
+ t0 = /* @__PURE__ */ jsx(AuthenticatedDerivedPreview, { ...props });
32
+ $[3] = props;
33
+ $[4] = t0;
34
+ } else t0 = $[4];
35
+ return t0;
36
+ }
37
+ function AuthenticatedDerivedPreview(t0) {
38
+ const $ = c(26);
39
+ if ($[0] !== "261aac3044f545b5b17e0449fc914e6311b0108f3d16c419141b242a12b10dbe") {
40
+ for (let $i = 0; $i < 26; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
41
+ $[0] = "261aac3044f545b5b17e0449fc914e6311b0108f3d16c419141b242a12b10dbe";
42
+ }
43
+ const { camoxApp, derived, source } = t0;
44
+ const previewSource = useSelector(previewStore, _temp);
45
+ const projectSlug = useProjectSlug();
46
+ const queryClient = useQueryClient();
47
+ let t1;
48
+ if ($[1] !== derived.layout.id || $[2] !== previewSource || $[3] !== projectSlug) {
49
+ t1 = [
50
+ ...queryKeys.layouts.all,
51
+ "get",
52
+ projectSlug,
53
+ derived.layout.id,
54
+ previewSource
55
+ ];
56
+ $[1] = derived.layout.id;
57
+ $[2] = previewSource;
58
+ $[3] = projectSlug;
59
+ $[4] = t1;
60
+ } else t1 = $[4];
61
+ let t2;
62
+ if ($[5] !== derived.layoutId || $[6] !== previewSource || $[7] !== projectSlug || $[8] !== queryClient) {
63
+ t2 = async () => {
64
+ const result = await getApiClient().layouts.get({
65
+ projectSlug,
66
+ layoutId: derived.layoutId,
67
+ source: previewSource
68
+ });
69
+ seedBlockCaches(queryClient, result, previewSource);
70
+ return result.layout;
71
+ };
72
+ $[5] = derived.layoutId;
73
+ $[6] = previewSource;
74
+ $[7] = projectSlug;
75
+ $[8] = queryClient;
76
+ $[9] = t2;
77
+ } else t2 = $[9];
78
+ const t3 = previewSource === source ? derived.layout : void 0;
79
+ let t4;
80
+ if ($[10] !== t1 || $[11] !== t2 || $[12] !== t3) {
81
+ t4 = {
82
+ queryKey: t1,
83
+ queryFn: t2,
84
+ initialData: t3,
85
+ staleTime: 0
86
+ };
87
+ $[10] = t1;
88
+ $[11] = t2;
89
+ $[12] = t3;
90
+ $[13] = t4;
91
+ } else t4 = $[13];
92
+ const { data: layout } = useSuspenseQuery(t4);
93
+ const t5 = layout.livePublishedCheckpointId != null;
94
+ let t6;
95
+ if ($[14] !== derived || $[15] !== layout) {
96
+ t6 = {
97
+ ...derived,
98
+ layout
99
+ };
100
+ $[14] = derived;
101
+ $[15] = layout;
102
+ $[16] = t6;
103
+ } else t6 = $[16];
104
+ let t7;
105
+ if ($[17] !== camoxApp || $[18] !== previewSource || $[19] !== t6) {
106
+ t7 = /* @__PURE__ */ jsx(DerivedPageContent, {
107
+ camoxApp,
108
+ derived: t6,
109
+ source: previewSource
110
+ });
111
+ $[17] = camoxApp;
112
+ $[18] = previewSource;
113
+ $[19] = t6;
114
+ $[20] = t7;
115
+ } else t7 = $[20];
116
+ let t8;
117
+ if ($[21] !== derived.layoutId || $[22] !== layout || $[23] !== t5 || $[24] !== t7) {
118
+ t8 = /* @__PURE__ */ jsx(PreviewShell, {
119
+ hasLiveVersion: t5,
120
+ derivedLayoutId: derived.layoutId,
121
+ derivedLayout: layout,
122
+ children: t7
123
+ });
124
+ $[21] = derived.layoutId;
125
+ $[22] = layout;
126
+ $[23] = t5;
127
+ $[24] = t7;
128
+ $[25] = t8;
129
+ } else t8 = $[25];
130
+ return t8;
131
+ }
132
+ function _temp(state) {
133
+ return state.context.previewSource;
134
+ }
135
+
136
+ //#endregion
137
+ export { DerivedPreview };
@@ -1,22 +1,39 @@
1
+ import { STUDIO_CONTENT_PATH } from "../studio/routes.js";
1
2
  import { CamoxPreview, PageContent } from "./CamoxPreview.js";
3
+ import { CamoxContent } from "../content/CamoxContent.js";
2
4
  import { AuthenticatedCamoxProvider } from "../provider/AuthenticatedCamoxProvider.js";
5
+ import { CamoxStudio } from "../studio/CamoxStudio.js";
3
6
  import { CompleteBlockEditingRuntimeProvider } from "../../core/editing/CompleteBlockEditingRuntime.js";
7
+ import { DerivedPreview } from "./DerivedPreview.js";
4
8
  import "./EditablePageContent.js";
5
9
  import { c } from "react/compiler-runtime";
6
10
  import { jsx } from "react/jsx-runtime";
7
11
 
8
12
  //#region src/features/preview/EditablePageExperience.tsx
9
13
  function EditablePageExperience(t0) {
10
- const $ = c(2);
11
- if ($[0] !== "62fa8b2b4207f6a9197bd7473308418337b4719a942b8cb83f05f5f584c962c9") {
12
- for (let $i = 0; $i < 2; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
13
- $[0] = "62fa8b2b4207f6a9197bd7473308418337b4719a942b8cb83f05f5f584c962c9";
14
+ const $ = c(7);
15
+ if ($[0] !== "3e64bef83d2f73cbe404213f4d6ec47e2fdb910abb8eeca9c10b0045de454f73") {
16
+ for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
17
+ $[0] = "3e64bef83d2f73cbe404213f4d6ec47e2fdb910abb8eeca9c10b0045de454f73";
14
18
  }
19
+ const { camoxApp, input } = t0;
15
20
  let t1;
16
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
17
- t1 = /* @__PURE__ */ jsx(AuthenticatedCamoxProvider, { children: /* @__PURE__ */ jsx(CompleteBlockEditingRuntimeProvider, { children: /* @__PURE__ */ jsx(CamoxPreview, { children: /* @__PURE__ */ jsx(PageContent, {}) }) }) });
18
- $[1] = t1;
19
- } else t1 = $[1];
21
+ if ($[1] !== camoxApp || $[2] !== input.derived || $[3] !== input.pathname || $[4] !== input.routeKind || $[5] !== input.source) {
22
+ t1 = /* @__PURE__ */ jsx(AuthenticatedCamoxProvider, { children: /* @__PURE__ */ jsx(CompleteBlockEditingRuntimeProvider, { children: input.routeKind ? /* @__PURE__ */ jsx(CamoxStudio, { children: input.pathname === STUDIO_CONTENT_PATH ? /* @__PURE__ */ jsx(CamoxContent, {}) : /* @__PURE__ */ jsx("div", {
23
+ className: "text-muted-foreground p-6 text-sm",
24
+ children: "Studio page not found"
25
+ }) }) : input.derived ? /* @__PURE__ */ jsx(DerivedPreview, {
26
+ camoxApp,
27
+ derived: input.derived,
28
+ source: input.source
29
+ }) : /* @__PURE__ */ jsx(CamoxPreview, { children: /* @__PURE__ */ jsx(PageContent, {}) }) }) });
30
+ $[1] = camoxApp;
31
+ $[2] = input.derived;
32
+ $[3] = input.pathname;
33
+ $[4] = input.routeKind;
34
+ $[5] = input.source;
35
+ $[6] = t1;
36
+ } else t1 = $[6];
20
37
  return t1;
21
38
  }
22
39
 
@@ -6,6 +6,7 @@ import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
6
6
  import { trackClientEvent } from "../../../lib/telemetry-client.js";
7
7
  import { previewStore } from "../previewStore.js";
8
8
  import { useRequireDraftSource } from "../../../core/hooks/useRequireDraftSource.js";
9
+ import { BlockThumbnail } from "./BlockThumbnail.js";
9
10
  import { usePreviewedPage } from "../CamoxPreview.js";
10
11
  import { c } from "react/compiler-runtime";
11
12
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
@@ -16,20 +17,20 @@ import { useSelector } from "@xstate/store-react";
16
17
  import { queryKeys } from "@camox/api-contract/query-keys";
17
18
  import { Button } from "@camox/ui/button";
18
19
  import { ArrowLeft } from "lucide-react";
19
- import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@camox/ui/command";
20
+ import { Badge } from "@camox/ui/badge";
20
21
  import { PanelContent } from "@camox/ui/panel";
22
+ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@camox/ui/command";
21
23
 
22
24
  //#region src/features/preview/components/AddBlockSidebar.tsx
23
25
  const AddBlockSidebar = () => {
24
26
  const $ = c(58);
25
- if ($[0] !== "e90c6519081e1159c7b7b2dea03fb3f0a6ad85218cb70141acd0c7462b3c8ff5") {
27
+ if ($[0] !== "0a9bbf9c6eddd22fc242436657c914b17db692a3ab0e958a7f9451a343536838") {
26
28
  for (let $i = 0; $i < 58; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
27
- $[0] = "e90c6519081e1159c7b7b2dea03fb3f0a6ad85218cb70141acd0c7462b3c8ff5";
29
+ $[0] = "0a9bbf9c6eddd22fc242436657c914b17db692a3ab0e958a7f9451a343536838";
28
30
  }
29
31
  const [highlightedValue, setHighlightedValue] = React.useState("");
30
32
  const queryClient = useQueryClient();
31
33
  const { pathname } = useLocation();
32
- const pagePathname = useSelector(previewStore, _temp) ?? pathname;
33
34
  const requireDraft = useRequireDraftSource();
34
35
  let t0;
35
36
  if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
@@ -37,15 +38,15 @@ const AddBlockSidebar = () => {
37
38
  $[1] = t0;
38
39
  } else t0 = $[1];
39
40
  let t1;
40
- if ($[2] !== pagePathname || $[3] !== queryClient) {
41
+ if ($[2] !== pathname || $[3] !== queryClient) {
41
42
  t1 = {
42
43
  ...t0,
43
44
  onMutate: (variables) => {
44
- const pageQueryKey = queryKeys.pages.getByPath(pagePathname, "draft");
45
+ const pageQueryKey = queryKeys.pages.getByPath(pathname, "draft");
45
46
  const previousPage = queryClient.getQueryData(pageQueryKey);
46
47
  if (!previousPage) return {};
47
48
  const blockIds = previousPage.page.blockIds;
48
- const pageBlocks = blockIds.map((id) => queryClient.getQueryData(queryKeys.blocks.get(id, "draft"))?.block).filter(_temp2);
49
+ const pageBlocks = blockIds.map((id) => queryClient.getQueryData(queryKeys.blocks.get(id, "draft"))?.block).filter(_temp);
49
50
  const { afterPosition } = variables;
50
51
  let position;
51
52
  if (afterPosition == null) {
@@ -101,14 +102,14 @@ const AddBlockSidebar = () => {
101
102
  };
102
103
  },
103
104
  onError: (_error, _variables, context) => {
104
- if (context?.previousPage) queryClient.setQueryData(queryKeys.pages.getByPath(pagePathname, "draft"), context.previousPage);
105
+ if (context?.previousPage) queryClient.setQueryData(queryKeys.pages.getByPath(pathname, "draft"), context.previousPage);
105
106
  if (context?.optimisticId) queryClient.removeQueries({ queryKey: queryKeys.blocks.get(context.optimisticId, "draft") });
106
107
  },
107
108
  onSettled: () => {
108
- queryClient.invalidateQueries({ queryKey: queryKeys.pages.getByPath(pagePathname, "draft") });
109
+ queryClient.invalidateQueries({ queryKey: queryKeys.pages.getByPath(pathname, "draft") });
109
110
  }
110
111
  };
111
- $[2] = pagePathname;
112
+ $[2] = pathname;
112
113
  $[3] = queryClient;
113
114
  $[4] = t1;
114
115
  } else t1 = $[4];
@@ -121,7 +122,7 @@ const AddBlockSidebar = () => {
121
122
  $[6] = t2;
122
123
  } else t2 = $[6];
123
124
  const { data: project } = useQuery(t2);
124
- const availableBlocks = useCamoxApp().getBlocks().filter(_temp3);
125
+ const availableBlocks = useCamoxApp().getBlocks().filter(_temp2);
125
126
  const page = usePreviewedPage();
126
127
  const { pageBlocks: pageBlocks_0 } = usePageBlocks(page);
127
128
  let t3;
@@ -165,8 +166,8 @@ const AddBlockSidebar = () => {
165
166
  $[16] = t8;
166
167
  } else t8 = $[16];
167
168
  const pageCounts = t8;
168
- const peekedBlockPosition = useSelector(previewStore, _temp4);
169
- const addBlockSource = useSelector(previewStore, _temp5);
169
+ const peekedBlockPosition = useSelector(previewStore, _temp3);
170
+ const addBlockSource = useSelector(previewStore, _temp4);
170
171
  let t9;
171
172
  if ($[17] !== addBlockSource || $[18] !== createBlock || $[19] !== page || $[20] !== pageBlocks_0 || $[21] !== peekedBlockPosition || $[22] !== requireDraft) {
172
173
  t9 = async (block_0) => {
@@ -242,7 +243,7 @@ const AddBlockSidebar = () => {
242
243
  children: /* @__PURE__ */ jsxs(Button, {
243
244
  variant: "ghost",
244
245
  className: "w-full justify-start",
245
- onClick: _temp6,
246
+ onClick: _temp5,
246
247
  children: [/* @__PURE__ */ jsx(ArrowLeft, { className: "text-muted-foreground" }), "Add new block"]
247
248
  })
248
249
  });
@@ -252,7 +253,7 @@ const AddBlockSidebar = () => {
252
253
  const t13 = "flex grow basis-0 flex-col overflow-auto px-2 py-2";
253
254
  const T1 = Command;
254
255
  const t14 = "overflow-visible rounded-none! bg-transparent! p-0!";
255
- const t15 = _temp7;
256
+ const t15 = _temp6;
256
257
  let t16;
257
258
  if ($[31] === Symbol.for("react.memo_cache_sentinel")) {
258
259
  t16 = /* @__PURE__ */ jsx(CommandInput, {
@@ -279,19 +280,31 @@ const AddBlockSidebar = () => {
279
280
  } else t20 = $[34];
280
281
  let t21;
281
282
  if ($[35] !== displayCount || $[36] !== handleAddBlock) {
282
- t21 = (block_3) => /* @__PURE__ */ jsx(CommandItem, {
283
+ t21 = (block_3) => /* @__PURE__ */ jsxs(CommandItem, {
283
284
  value: block_3._internal.title,
285
+ keywords: [block_3._internal.description ?? ""],
286
+ hideCheck: true,
284
287
  onSelect: () => {
285
288
  handleAddBlock(block_3);
286
289
  },
287
- className: "group flex items-center justify-between gap-2",
288
- children: /* @__PURE__ */ jsxs("div", {
289
- className: "flex-1",
290
- children: [/* @__PURE__ */ jsx("span", { children: block_3._internal.title }), /* @__PURE__ */ jsx("span", {
291
- className: "text-muted-foreground block",
290
+ className: "group bg-card data-[selected=true]:border-primary data-[selected=true]:after:border-primary mb-3 flex flex-col items-stretch gap-0 overflow-hidden rounded-lg border p-0 after:pointer-events-none after:absolute after:inset-0 after:z-10 after:rounded-[inherit] last:mb-0 data-[selected=true]:after:border",
291
+ children: [/* @__PURE__ */ jsx(BlockThumbnail, { block: block_3 }), /* @__PURE__ */ jsxs("div", {
292
+ className: "border-border flex flex-col gap-1 border-t px-3 py-2",
293
+ children: [/* @__PURE__ */ jsxs("div", {
294
+ className: "flex items-center justify-between gap-2",
295
+ children: [/* @__PURE__ */ jsx("span", {
296
+ className: "min-w-0 leading-5 font-medium",
297
+ children: block_3._internal.title
298
+ }), block_3._internal.synced && /* @__PURE__ */ jsx(Badge, {
299
+ variant: "secondary",
300
+ size: "sm",
301
+ children: "Synced"
302
+ })]
303
+ }), /* @__PURE__ */ jsx("span", {
304
+ className: "text-muted-foreground text-xs leading-4",
292
305
  children: displayCount(block_3._internal.id)
293
306
  })]
294
- })
307
+ })]
295
308
  }, block_3._internal.id);
296
309
  $[35] = displayCount;
297
310
  $[36] = handleAddBlock;
@@ -355,25 +368,22 @@ const AddBlockSidebar = () => {
355
368
  } else t27 = $[57];
356
369
  return t27;
357
370
  };
358
- function _temp(state) {
359
- return state.context.peekedPagePathname;
360
- }
361
- function _temp2(b) {
371
+ function _temp(b) {
362
372
  return b != null;
363
373
  }
364
- function _temp3(b_1) {
374
+ function _temp2(b_1) {
365
375
  return !b_1._internal.layoutOnly;
366
376
  }
367
- function _temp4(state_0) {
368
- return state_0.context.peekedBlockPosition;
377
+ function _temp3(state) {
378
+ return state.context.peekedBlockPosition;
369
379
  }
370
- function _temp5(state_1) {
371
- return state_1.context.addBlockSource;
380
+ function _temp4(state_0) {
381
+ return state_0.context.addBlockSource;
372
382
  }
373
- function _temp6() {
383
+ function _temp5() {
374
384
  return previewStore.send({ type: "closeAddBlockSidebar" });
375
385
  }
376
- function _temp7(e) {
386
+ function _temp6(e) {
377
387
  if (e.key === "Escape") previewStore.send({ type: "closeAddBlockSidebar" });
378
388
  }
379
389
 
@@ -15,8 +15,8 @@ import { Check, Download, FileIcon, Info, Link, Loader2, Trash2, X } from "lucid
15
15
  import { toast } from "@camox/ui/toaster";
16
16
  import { Dialog, DialogContent, DialogTitle } from "@camox/ui/dialog";
17
17
  import { Label } from "@camox/ui/label";
18
- import { ButtonGroup } from "@camox/ui/button-group";
19
18
  import { Tooltip, TooltipContent, TooltipTrigger } from "@camox/ui/tooltip";
19
+ import { ButtonGroup } from "@camox/ui/button-group";
20
20
  import { Switch } from "@camox/ui/switch";
21
21
 
22
22
  //#region src/features/preview/components/AssetLightbox.tsx
@@ -0,0 +1,192 @@
1
+ import { NormalizedDataProvider } from "../../../lib/normalized-data.js";
2
+ import { BlockErrorBoundary } from "./BlockErrorBoundary.js";
3
+ import { previewStore } from "../previewStore.js";
4
+ import { EMPTY_PREVIEW_DOCUMENT, isSiteStyle } from "./previewStyles.js";
5
+ import { FrameContext } from "./Frame.js";
6
+ import { c } from "react/compiler-runtime";
7
+ import * as React from "react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { useSelector } from "@xstate/store-react";
10
+ import { createPortal } from "react-dom";
11
+
12
+ //#region src/features/preview/components/BlockThumbnail.tsx
13
+ const VIEWPORT_WIDTH = 1200;
14
+ const VIEWPORT_HEIGHT = 800;
15
+ const ThumbnailFrame = ({ block, width }) => {
16
+ const sourceFrame = useSelector(previewStore, (state) => state.context.iframeElement);
17
+ const [frame, setFrame] = React.useState(null);
18
+ const [root, setRoot] = React.useState(null);
19
+ const [content, setContent] = React.useState(null);
20
+ const [contentHeight, setContentHeight] = React.useState(VIEWPORT_HEIGHT);
21
+ const bundle = React.useMemo(() => block._internal.getPeekBundle(), [block]);
22
+ const initialize = React.useCallback(() => {
23
+ const doc = frame?.contentDocument;
24
+ const mount = doc?.querySelector("[data-camox-preview-root]");
25
+ if (!doc || !mount) return;
26
+ const source = sourceFrame?.contentDocument ?? document;
27
+ doc.head.replaceChildren();
28
+ const base = doc.createElement("base");
29
+ base.href = source.baseURI;
30
+ doc.head.appendChild(base);
31
+ source.querySelectorAll("style, link[rel=\"stylesheet\"]").forEach((style) => {
32
+ if (isSiteStyle(style)) doc.head.appendChild(style.cloneNode(true));
33
+ });
34
+ if (source !== document) for (const [from, to] of [
35
+ [source.documentElement, doc.documentElement],
36
+ [source.body, doc.body],
37
+ [source.querySelector("[data-camox-preview-root]"), mount]
38
+ ]) {
39
+ if (!from || !to) continue;
40
+ for (const attribute of Array.from(from.attributes)) if (!attribute.name.startsWith("on")) to.setAttribute(attribute.name, attribute.value);
41
+ }
42
+ const reset = doc.createElement("style");
43
+ reset.textContent = `
44
+ html, body { margin: 0 !important; overflow: hidden !important; }
45
+ *, *::before, *::after {
46
+ animation: none !important;
47
+ transition: none !important;
48
+ caret-color: transparent !important;
49
+ }
50
+ `;
51
+ doc.head.appendChild(reset);
52
+ doc.body.inert = true;
53
+ setRoot(mount);
54
+ }, [frame, sourceFrame]);
55
+ React.useEffect(() => {
56
+ initialize();
57
+ }, [initialize]);
58
+ React.useEffect(() => {
59
+ if (!content) return;
60
+ const observer = new ResizeObserver(() => {
61
+ setContentHeight(content.getBoundingClientRect().height);
62
+ });
63
+ observer.observe(content);
64
+ return () => observer.disconnect();
65
+ }, [content]);
66
+ return /* @__PURE__ */ jsxs("div", {
67
+ className: "relative max-h-full w-full shrink-0 overflow-hidden",
68
+ style: { height: contentHeight * width / VIEWPORT_WIDTH },
69
+ children: [/* @__PURE__ */ jsx("iframe", {
70
+ ref: setFrame,
71
+ title: `${block._internal.title} preview`,
72
+ srcDoc: EMPTY_PREVIEW_DOCUMENT,
73
+ onLoad: initialize,
74
+ tabIndex: -1,
75
+ className: "pointer-events-none absolute top-0 left-0 origin-top-left border-0",
76
+ style: {
77
+ width: VIEWPORT_WIDTH,
78
+ height: VIEWPORT_HEIGHT,
79
+ transform: `scale(${width / VIEWPORT_WIDTH})`
80
+ }
81
+ }), root && createPortal(/* @__PURE__ */ jsx(FrameContext.Provider, {
82
+ value: {
83
+ window: frame?.contentWindow ?? null,
84
+ iframeElement: frame
85
+ },
86
+ children: /* @__PURE__ */ jsx("div", {
87
+ ref: setContent,
88
+ style: { display: "flow-root" },
89
+ children: /* @__PURE__ */ jsx(BlockErrorBoundary, {
90
+ blockId: 0,
91
+ blockType: block._internal.id,
92
+ children: /* @__PURE__ */ jsx(React.Suspense, {
93
+ fallback: null,
94
+ children: /* @__PURE__ */ jsx(NormalizedDataProvider, {
95
+ files: bundle.files,
96
+ repeatableItems: bundle.repeatableItems,
97
+ children: /* @__PURE__ */ jsx(block._internal.Component, {
98
+ blockData: {
99
+ _id: 0,
100
+ type: block._internal.id,
101
+ content: bundle.block.content,
102
+ settings: bundle.block.settings,
103
+ position: ""
104
+ },
105
+ mode: "peek"
106
+ })
107
+ })
108
+ })
109
+ })
110
+ })
111
+ }), root)]
112
+ });
113
+ };
114
+ const BlockThumbnail = (t0) => {
115
+ const $ = c(13);
116
+ if ($[0] !== "150232a0d21c91d8fa59376f05913c9b4e2cabef4981a57296ed2c5c473bef0b") {
117
+ for (let $i = 0; $i < 13; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
118
+ $[0] = "150232a0d21c91d8fa59376f05913c9b4e2cabef4981a57296ed2c5c473bef0b";
119
+ }
120
+ const { block } = t0;
121
+ const ref = React.useRef(null);
122
+ const [isVisible, setIsVisible] = React.useState(false);
123
+ const [width, setWidth] = React.useState(0);
124
+ const checkerSize = 8 * (1 + width / VIEWPORT_WIDTH);
125
+ let t1;
126
+ let t2;
127
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
128
+ t1 = () => {
129
+ const element = ref.current;
130
+ if (!element) return;
131
+ const intersectionObserver = new IntersectionObserver((t3) => {
132
+ const [entry] = t3;
133
+ setIsVisible(entry.isIntersecting);
134
+ });
135
+ const resizeObserver = new ResizeObserver((t4) => {
136
+ const [entry_0] = t4;
137
+ setWidth(entry_0.contentRect.width);
138
+ });
139
+ intersectionObserver.observe(element);
140
+ resizeObserver.observe(element);
141
+ return () => {
142
+ intersectionObserver.disconnect();
143
+ resizeObserver.disconnect();
144
+ };
145
+ };
146
+ t2 = [];
147
+ $[1] = t1;
148
+ $[2] = t2;
149
+ } else {
150
+ t1 = $[1];
151
+ t2 = $[2];
152
+ }
153
+ React.useEffect(t1, t2);
154
+ let t3;
155
+ if ($[3] !== checkerSize || $[4] !== width) {
156
+ t3 = width > 0 ? {
157
+ backgroundSize: `${checkerSize * 2}px ${checkerSize * 2}px`,
158
+ backgroundPosition: `0 0, 0 ${checkerSize}px, ${checkerSize}px ${-checkerSize}px, ${-checkerSize}px 0`
159
+ } : void 0;
160
+ $[3] = checkerSize;
161
+ $[4] = width;
162
+ $[5] = t3;
163
+ } else t3 = $[5];
164
+ let t4;
165
+ if ($[6] !== block || $[7] !== isVisible || $[8] !== width) {
166
+ t4 = isVisible && width > 0 && /* @__PURE__ */ jsx(ThumbnailFrame, {
167
+ block,
168
+ width
169
+ });
170
+ $[6] = block;
171
+ $[7] = isVisible;
172
+ $[8] = width;
173
+ $[9] = t4;
174
+ } else t4 = $[9];
175
+ let t5;
176
+ if ($[10] !== t3 || $[11] !== t4) {
177
+ t5 = /* @__PURE__ */ jsx("div", {
178
+ ref,
179
+ className: "checkered pointer-events-none relative flex h-28 w-full items-center overflow-hidden",
180
+ style: t3,
181
+ "aria-hidden": "true",
182
+ children: t4
183
+ });
184
+ $[10] = t3;
185
+ $[11] = t4;
186
+ $[12] = t5;
187
+ } else t5 = $[12];
188
+ return t5;
189
+ };
190
+
191
+ //#endregion
192
+ export { BlockThumbnail };