camox 0.3.0 → 0.4.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 (76) hide show
  1. package/dist/components/AuthGate.js +2 -1
  2. package/dist/core/components/AddBlockControlBar.js +117 -44
  3. package/dist/core/components/lexical/InlineContentEditable.js +37 -17
  4. package/dist/core/components/lexical/InlineLexicalEditor.js +84 -25
  5. package/dist/core/components/lexical/SelectionBroadcaster.js +84 -47
  6. package/dist/core/components/lexical/SidebarLexicalEditor.js +54 -19
  7. package/dist/core/createBlock.js +1172 -414
  8. package/dist/core/createLayout.js +48 -16
  9. package/dist/core/hooks/useFieldSelection.js +24 -13
  10. package/dist/core/hooks/useIsEditable.js +8 -2
  11. package/dist/core/hooks/useOverlayMessage.js +51 -20
  12. package/dist/features/content/CamoxContent.js +239 -107
  13. package/dist/features/content/components/AssetCard.js +78 -16
  14. package/dist/features/content/components/AssetCardSkeleton.js +11 -4
  15. package/dist/features/content/components/ContentSidebar.js +15 -8
  16. package/dist/features/content/components/UploadDropZone.js +77 -34
  17. package/dist/features/content/components/UploadProgressDrawer.js +201 -58
  18. package/dist/features/metadata/sitemap.js +15 -0
  19. package/dist/features/preview/CamoxPreview.js +447 -179
  20. package/dist/features/preview/components/AddBlockSheet.js +344 -167
  21. package/dist/features/preview/components/AgentChatSheet.js +32 -10
  22. package/dist/features/preview/components/AssetFieldEditor.js +185 -50
  23. package/dist/features/preview/components/AssetLightbox.js +60 -33
  24. package/dist/features/preview/components/AssetPickerGrid.js +203 -71
  25. package/dist/features/preview/components/BlockActionsPopover.js +295 -218
  26. package/dist/features/preview/components/CreatePageSheet.js +3 -3
  27. package/dist/features/preview/components/DebouncedFieldEditor.js +80 -23
  28. package/dist/features/preview/components/EditPageSheet.js +241 -86
  29. package/dist/features/preview/components/ItemFieldsEditor.js +209 -115
  30. package/dist/features/preview/components/LinkFieldEditor.js +351 -153
  31. package/dist/features/preview/components/MultipleAssetFieldEditor.js +245 -92
  32. package/dist/features/preview/components/OverlayTracker.js +58 -23
  33. package/dist/features/preview/components/Overlays.js +85 -43
  34. package/dist/features/preview/components/PageContentSheet.js +18 -18
  35. package/dist/features/preview/components/PageLocationFieldset.js +229 -63
  36. package/dist/features/preview/components/PagePicker.js +27 -27
  37. package/dist/features/preview/components/PageTree.js +921 -319
  38. package/dist/features/preview/components/PeekedBlock.js +173 -63
  39. package/dist/features/preview/components/PreviewPanel.js +271 -148
  40. package/dist/features/preview/components/PreviewSideSheet.js +44 -11
  41. package/dist/features/preview/components/PreviewToolbar.js +262 -59
  42. package/dist/features/preview/components/RepeatableItemsList.js +187 -78
  43. package/dist/features/preview/components/ShikiMarkdown.js +46 -20
  44. package/dist/features/preview/components/TextFormatToolbar.js +81 -23
  45. package/dist/features/preview/components/UnlinkAssetButton.js +161 -40
  46. package/dist/features/preview/components/useUpdateBlockPosition.js +64 -47
  47. package/dist/features/preview/previewStore.d.ts +2 -2
  48. package/dist/features/provider/CamoxProvider.js +69 -21
  49. package/dist/features/provider/actionsStore.d.ts +2 -2
  50. package/dist/features/provider/components/CamoxAppContext.js +15 -5
  51. package/dist/features/provider/components/CommandPalette.js +199 -92
  52. package/dist/features/provider/useAdminShortcuts.js +80 -64
  53. package/dist/features/routes/pageRoute.js +8 -1
  54. package/dist/features/studio/CamoxStudio.js +45 -9
  55. package/dist/features/studio/components/EnvironmentMenu.js +47 -12
  56. package/dist/features/studio/components/Navbar.js +163 -65
  57. package/dist/features/studio/components/ProjectMenu.d.ts.map +1 -1
  58. package/dist/features/studio/components/ProjectMenu.js +284 -83
  59. package/dist/features/studio/components/UserButton.js +21 -6
  60. package/dist/features/studio/studioStore.d.ts +2 -2
  61. package/dist/features/studio/useTheme.js +128 -74
  62. package/dist/features/vite/definitionsSync.d.ts +7 -12
  63. package/dist/features/vite/definitionsSync.d.ts.map +1 -1
  64. package/dist/features/vite/definitionsSync.js +5 -16
  65. package/dist/features/vite/vite.d.ts +0 -3
  66. package/dist/features/vite/vite.d.ts.map +1 -1
  67. package/dist/features/vite/vite.js +1 -2
  68. package/dist/hooks/use-file-upload.js +11 -11
  69. package/dist/hooks/use-marquee-selection.js +121 -74
  70. package/dist/lib/auth.js +95 -51
  71. package/dist/lib/normalized-data.js +103 -30
  72. package/dist/lib/use-project-room.js +55 -22
  73. package/dist/studio.css +2 -2
  74. package/package.json +29 -26
  75. package/dist/lib/auth.d.ts +0 -2130
  76. package/dist/lib/auth.d.ts.map +0 -1
@@ -6,6 +6,7 @@ import { useFileUpload } from "../../../hooks/use-file-upload.js";
6
6
  import { AssetLightbox } from "./AssetLightbox.js";
7
7
  import { AssetPickerGrid } from "./AssetPickerGrid.js";
8
8
  import { UnlinkAssetButton } from "./UnlinkAssetButton.js";
9
+ import { c } from "react/compiler-runtime";
9
10
  import { useQuery } from "@tanstack/react-query";
10
11
  import * as React from "react";
11
12
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -16,37 +17,110 @@ function assetLabel(isImage, multiple) {
16
17
  if (isImage) return multiple ? "images" : "image";
17
18
  return multiple ? "files" : "file";
18
19
  }
19
- var AssetActionButtons = ({ isImage, multiple, fileInputRef, onPickerOpen, onFilesSelected, uploads }) => /* @__PURE__ */ jsxs(Fragment, { children: [
20
- /* @__PURE__ */ jsxs(Button, {
21
- variant: "default",
22
- className: "mx-auto flex w-full",
23
- onClick: onPickerOpen,
24
- children: ["Select existing ", assetLabel(isImage, multiple)]
25
- }),
26
- /* @__PURE__ */ jsxs(Button, {
27
- variant: "secondary",
28
- className: "mx-auto flex w-full",
29
- onClick: () => fileInputRef.current?.click(),
30
- children: [/* @__PURE__ */ jsx(Upload, { className: "h-4 w-4" }), "Upload new"]
31
- }),
32
- /* @__PURE__ */ jsx("p", {
33
- className: "text-muted-foreground text-center text-xs",
34
- children: "Or drag anywhere to upload"
35
- }),
36
- /* @__PURE__ */ jsx("input", {
37
- type: "file",
38
- ref: fileInputRef,
39
- className: "hidden",
40
- accept: isImage ? "image/*" : "*/*",
41
- multiple,
42
- onChange: (e) => {
20
+ var AssetActionButtons = (t0) => {
21
+ const $ = c(26);
22
+ const { isImage, multiple, fileInputRef, onPickerOpen, onFilesSelected, uploads } = t0;
23
+ let t1;
24
+ if ($[0] !== isImage || $[1] !== multiple) {
25
+ t1 = assetLabel(isImage, multiple);
26
+ $[0] = isImage;
27
+ $[1] = multiple;
28
+ $[2] = t1;
29
+ } else t1 = $[2];
30
+ let t2;
31
+ if ($[3] !== onPickerOpen || $[4] !== t1) {
32
+ t2 = /* @__PURE__ */ jsxs(Button, {
33
+ variant: "default",
34
+ className: "mx-auto flex w-full",
35
+ onClick: onPickerOpen,
36
+ children: ["Select existing ", t1]
37
+ });
38
+ $[3] = onPickerOpen;
39
+ $[4] = t1;
40
+ $[5] = t2;
41
+ } else t2 = $[5];
42
+ let t3;
43
+ if ($[6] !== fileInputRef) {
44
+ t3 = () => fileInputRef.current?.click();
45
+ $[6] = fileInputRef;
46
+ $[7] = t3;
47
+ } else t3 = $[7];
48
+ let t4;
49
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
50
+ t4 = /* @__PURE__ */ jsx(Upload, { className: "h-4 w-4" });
51
+ $[8] = t4;
52
+ } else t4 = $[8];
53
+ let t5;
54
+ if ($[9] !== t3) {
55
+ t5 = /* @__PURE__ */ jsxs(Button, {
56
+ variant: "secondary",
57
+ className: "mx-auto flex w-full",
58
+ onClick: t3,
59
+ children: [t4, "Upload new"]
60
+ });
61
+ $[9] = t3;
62
+ $[10] = t5;
63
+ } else t5 = $[10];
64
+ let t6;
65
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
66
+ t6 = /* @__PURE__ */ jsx("p", {
67
+ className: "text-muted-foreground text-center text-xs",
68
+ children: "Or drag anywhere to upload"
69
+ });
70
+ $[11] = t6;
71
+ } else t6 = $[11];
72
+ const t7 = isImage ? "image/*" : "*/*";
73
+ let t8;
74
+ if ($[12] !== onFilesSelected) {
75
+ t8 = (e) => {
43
76
  if (e.target.files) onFilesSelected(e.target.files);
44
77
  e.target.value = "";
45
- }
46
- }),
47
- uploads.length > 0 && /* @__PURE__ */ jsx("div", { children: uploads.map((item) => /* @__PURE__ */ jsx(UploadItemRow, { item }, item.id)) })
48
- ] });
49
- var SingleAssetFieldEditor = ({ fieldName, assetType, currentData, onFieldChange }) => {
78
+ };
79
+ $[12] = onFilesSelected;
80
+ $[13] = t8;
81
+ } else t8 = $[13];
82
+ let t9;
83
+ if ($[14] !== fileInputRef || $[15] !== multiple || $[16] !== t7 || $[17] !== t8) {
84
+ t9 = /* @__PURE__ */ jsx("input", {
85
+ type: "file",
86
+ ref: fileInputRef,
87
+ className: "hidden",
88
+ accept: t7,
89
+ multiple,
90
+ onChange: t8
91
+ });
92
+ $[14] = fileInputRef;
93
+ $[15] = multiple;
94
+ $[16] = t7;
95
+ $[17] = t8;
96
+ $[18] = t9;
97
+ } else t9 = $[18];
98
+ let t10;
99
+ if ($[19] !== uploads) {
100
+ t10 = uploads.length > 0 && /* @__PURE__ */ jsx("div", { children: uploads.map(_temp) });
101
+ $[19] = uploads;
102
+ $[20] = t10;
103
+ } else t10 = $[20];
104
+ let t11;
105
+ if ($[21] !== t10 || $[22] !== t2 || $[23] !== t5 || $[24] !== t9) {
106
+ t11 = /* @__PURE__ */ jsxs(Fragment, { children: [
107
+ t2,
108
+ t5,
109
+ t6,
110
+ t9,
111
+ t10
112
+ ] });
113
+ $[21] = t10;
114
+ $[22] = t2;
115
+ $[23] = t5;
116
+ $[24] = t9;
117
+ $[25] = t11;
118
+ } else t11 = $[25];
119
+ return t11;
120
+ };
121
+ var SingleAssetFieldEditor = (t0) => {
122
+ const $ = c(28);
123
+ const { fieldName, assetType, currentData, onFieldChange } = t0;
50
124
  const asset = currentData[fieldName];
51
125
  const hasAsset = !!asset?.url;
52
126
  const [lightboxOpen, setLightboxOpen] = React.useState(false);
@@ -54,29 +128,63 @@ var SingleAssetFieldEditor = ({ fieldName, assetType, currentData, onFieldChange
54
128
  const isImage = assetType === "Image";
55
129
  const fileInputRef = React.useRef(null);
56
130
  const projectSlug = useProjectSlug();
57
- const { data: project } = useQuery(projectQueries.getBySlug(projectSlug));
58
- const { uploads, uploadFiles } = useFileUpload({
59
- projectId: project?.id,
60
- onFileCommitted: (result) => {
131
+ let t1;
132
+ if ($[0] !== projectSlug) {
133
+ t1 = projectQueries.getBySlug(projectSlug);
134
+ $[0] = projectSlug;
135
+ $[1] = t1;
136
+ } else t1 = $[1];
137
+ const { data: project } = useQuery(t1);
138
+ const t2 = project?.id;
139
+ let t3;
140
+ if ($[2] !== fieldName || $[3] !== onFieldChange) {
141
+ t3 = (result) => {
61
142
  onFieldChange(fieldName, { _fileId: Number(result.fileId) });
62
- }
63
- });
64
- const handleDrop = React.useCallback((files) => {
65
- const dt = new DataTransfer();
66
- dt.items.add(files[0]);
67
- uploadFiles(dt.files);
68
- }, [uploadFiles]);
69
- const handleSelectExisting = (file) => {
70
- onFieldChange(fieldName, { _fileId: file.id });
71
- setPickerOpen(false);
72
- };
73
- return /* @__PURE__ */ jsx(UploadDropZone, {
74
- onDrop: handleDrop,
75
- children: pickerOpen ? /* @__PURE__ */ jsx(AssetPickerGrid, {
143
+ };
144
+ $[2] = fieldName;
145
+ $[3] = onFieldChange;
146
+ $[4] = t3;
147
+ } else t3 = $[4];
148
+ let t4;
149
+ if ($[5] !== t2 || $[6] !== t3) {
150
+ t4 = {
151
+ projectId: t2,
152
+ onFileCommitted: t3
153
+ };
154
+ $[5] = t2;
155
+ $[6] = t3;
156
+ $[7] = t4;
157
+ } else t4 = $[7];
158
+ const { uploads, uploadFiles } = useFileUpload(t4);
159
+ let t5;
160
+ if ($[8] !== uploadFiles) {
161
+ t5 = (files) => {
162
+ const dt = new DataTransfer();
163
+ dt.items.add(files[0]);
164
+ uploadFiles(dt.files);
165
+ };
166
+ $[8] = uploadFiles;
167
+ $[9] = t5;
168
+ } else t5 = $[9];
169
+ const handleDrop = t5;
170
+ let t6;
171
+ if ($[10] !== fieldName || $[11] !== onFieldChange) {
172
+ t6 = (file) => {
173
+ onFieldChange(fieldName, { _fileId: file.id });
174
+ setPickerOpen(false);
175
+ };
176
+ $[10] = fieldName;
177
+ $[11] = onFieldChange;
178
+ $[12] = t6;
179
+ } else t6 = $[12];
180
+ const handleSelectExisting = t6;
181
+ let t7;
182
+ if ($[13] !== asset || $[14] !== assetType || $[15] !== fieldName || $[16] !== handleDrop || $[17] !== handleSelectExisting || $[18] !== hasAsset || $[19] !== isImage || $[20] !== lightboxOpen || $[21] !== onFieldChange || $[22] !== pickerOpen || $[23] !== uploads) {
183
+ t7 = pickerOpen ? /* @__PURE__ */ jsx(AssetPickerGrid, {
76
184
  assetType,
77
185
  mode: "single",
78
186
  onSelectSingle: handleSelectExisting,
79
- onSelectMultiple: () => {},
187
+ onSelectMultiple: _temp2,
80
188
  onClose: () => setPickerOpen(false)
81
189
  }) : /* @__PURE__ */ jsxs("div", {
82
190
  className: "space-y-4 px-4 py-4",
@@ -123,8 +231,35 @@ var SingleAssetFieldEditor = ({ fieldName, assetType, currentData, onFieldChange
123
231
  onFilesSelected: handleDrop,
124
232
  uploads
125
233
  })]
126
- })
127
- });
234
+ });
235
+ $[13] = asset;
236
+ $[14] = assetType;
237
+ $[15] = fieldName;
238
+ $[16] = handleDrop;
239
+ $[17] = handleSelectExisting;
240
+ $[18] = hasAsset;
241
+ $[19] = isImage;
242
+ $[20] = lightboxOpen;
243
+ $[21] = onFieldChange;
244
+ $[22] = pickerOpen;
245
+ $[23] = uploads;
246
+ $[24] = t7;
247
+ } else t7 = $[24];
248
+ let t8;
249
+ if ($[25] !== handleDrop || $[26] !== t7) {
250
+ t8 = /* @__PURE__ */ jsx(UploadDropZone, {
251
+ onDrop: handleDrop,
252
+ children: t7
253
+ });
254
+ $[25] = handleDrop;
255
+ $[26] = t7;
256
+ $[27] = t8;
257
+ } else t8 = $[27];
258
+ return t8;
128
259
  };
260
+ function _temp(item) {
261
+ return /* @__PURE__ */ jsx(UploadItemRow, { item }, item.id);
262
+ }
263
+ function _temp2() {}
129
264
  //#endregion
130
265
  export { AssetActionButtons, SingleAssetFieldEditor };
@@ -3,6 +3,7 @@ import { getApiUrl, getEnvironmentName } from "../../../lib/api-client.js";
3
3
  import { fileMutations, fileQueries } from "../../../lib/queries.js";
4
4
  import { DebouncedFieldEditor } from "./DebouncedFieldEditor.js";
5
5
  import { UploadDropZone } from "../../content/components/UploadDropZone.js";
6
+ import { c } from "react/compiler-runtime";
6
7
  import { Label } from "@camox/ui/label";
7
8
  import { toast } from "@camox/ui/toaster";
8
9
  import { useMutation, useQuery } from "@tanstack/react-query";
@@ -15,21 +16,47 @@ import { Switch } from "@camox/ui/switch";
15
16
  import { ButtonGroup } from "@camox/ui/button-group";
16
17
  import { Dialog, DialogContent, DialogTitle } from "@camox/ui/dialog";
17
18
  //#region src/features/preview/components/AssetLightbox.tsx
18
- function MetadataRow({ label, children }) {
19
- return /* @__PURE__ */ jsxs("div", {
20
- className: "flex items-baseline gap-2",
21
- children: [
22
- /* @__PURE__ */ jsx("span", {
23
- className: "shrink-0",
24
- children: label
25
- }),
26
- /* @__PURE__ */ jsx("span", { className: "border-border min-w-0 flex-1 border-b" }),
27
- /* @__PURE__ */ jsx("span", {
28
- className: "text-foreground shrink-0",
29
- children
30
- })
31
- ]
32
- });
19
+ function MetadataRow(t0) {
20
+ const $ = c(8);
21
+ const { label, children } = t0;
22
+ let t1;
23
+ if ($[0] !== label) {
24
+ t1 = /* @__PURE__ */ jsx("span", {
25
+ className: "shrink-0",
26
+ children: label
27
+ });
28
+ $[0] = label;
29
+ $[1] = t1;
30
+ } else t1 = $[1];
31
+ let t2;
32
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
33
+ t2 = /* @__PURE__ */ jsx("span", { className: "border-border min-w-0 flex-1 border-b" });
34
+ $[2] = t2;
35
+ } else t2 = $[2];
36
+ let t3;
37
+ if ($[3] !== children) {
38
+ t3 = /* @__PURE__ */ jsx("span", {
39
+ className: "text-foreground shrink-0",
40
+ children
41
+ });
42
+ $[3] = children;
43
+ $[4] = t3;
44
+ } else t3 = $[4];
45
+ let t4;
46
+ if ($[5] !== t1 || $[6] !== t3) {
47
+ t4 = /* @__PURE__ */ jsxs("div", {
48
+ className: "flex items-baseline gap-2",
49
+ children: [
50
+ t1,
51
+ t2,
52
+ t3
53
+ ]
54
+ });
55
+ $[5] = t1;
56
+ $[6] = t3;
57
+ $[7] = t4;
58
+ } else t4 = $[7];
59
+ return t4;
33
60
  }
34
61
  function formatRelativeTime(epochMs) {
35
62
  const now = Temporal.Now.instant();
@@ -109,20 +136,20 @@ var AssetLightbox = ({ open, onOpenChange, fileId }) => {
109
136
  }
110
137
  });
111
138
  if (!uploadRes.ok) throw new Error(`Upload failed: ${uploadRes.status}`);
112
- setUploadState((prev) => prev ? {
113
- ...prev,
139
+ setUploadState((prev_0) => prev_0 ? {
140
+ ...prev_0,
114
141
  status: "committing",
115
142
  progress: 100
116
- } : prev);
143
+ } : prev_0);
117
144
  const { id: newFileId } = await uploadRes.json();
118
145
  await replaceFile.mutateAsync({
119
146
  id: fileId,
120
147
  newFileId
121
148
  });
122
- setUploadState((prev) => prev ? {
123
- ...prev,
149
+ setUploadState((prev_1) => prev_1 ? {
150
+ ...prev_1,
124
151
  status: "complete"
125
- } : prev);
152
+ } : prev_1);
126
153
  toast.success("File replaced");
127
154
  setTimeout(() => {
128
155
  setUploadState(null);
@@ -191,18 +218,18 @@ var AssetLightbox = ({ open, onOpenChange, fileId }) => {
191
218
  ref: containerRef,
192
219
  className: `checkered absolute inset-0 ${zoomed ? "overflow-auto" : "flex items-center justify-center overflow-hidden p-6"}`,
193
220
  onClick: (e) => {
194
- const img = containerRef.current?.querySelector("img");
195
- if (!img) return;
221
+ const img_0 = containerRef.current?.querySelector("img");
222
+ if (!img_0) return;
196
223
  if (!zoomed) {
197
- const rect = img.getBoundingClientRect();
224
+ const rect = img_0.getBoundingClientRect();
198
225
  clickFractionRef.current = {
199
226
  x: (e.clientX - rect.left) / rect.width,
200
227
  y: (e.clientY - rect.top) / rect.height
201
228
  };
202
- const container = containerRef.current;
203
- const scaleForWidth = container.clientWidth * 2.5 / img.clientWidth;
204
- const scaleForHeight = container.clientHeight * 2.5 / img.clientHeight;
205
- setZoomedWidth(img.clientWidth * Math.max(scaleForWidth, scaleForHeight));
229
+ const container_0 = containerRef.current;
230
+ const scaleForWidth = container_0.clientWidth * 2.5 / img_0.clientWidth;
231
+ const scaleForHeight = container_0.clientHeight * 2.5 / img_0.clientHeight;
232
+ setZoomedWidth(img_0.clientWidth * Math.max(scaleForWidth, scaleForHeight));
206
233
  setZoomed(true);
207
234
  } else {
208
235
  setZoomed(false);
@@ -339,9 +366,9 @@ var AssetLightbox = ({ open, onOpenChange, fileId }) => {
339
366
  initialValue: file.alt,
340
367
  disabled: file.aiMetadataEnabled !== false,
341
368
  rows: 2,
342
- onSave: (value) => setAlt.mutate({
369
+ onSave: (value_0) => setAlt.mutate({
343
370
  id: fileId,
344
- alt: value
371
+ alt: value_0
345
372
  })
346
373
  }),
347
374
  /* @__PURE__ */ jsxs("div", {
@@ -378,9 +405,9 @@ var AssetLightbox = ({ open, onOpenChange, fileId }) => {
378
405
  type: "file",
379
406
  className: "hidden",
380
407
  accept: isImage ? "image/*" : "*/*",
381
- onChange: (e) => {
382
- if (e.target.files) handleReplaceDrop(e.target.files);
383
- e.target.value = "";
408
+ onChange: (e_0) => {
409
+ if (e_0.target.files) handleReplaceDrop(e_0.target.files);
410
+ e_0.target.value = "";
384
411
  }
385
412
  }),
386
413
  /* @__PURE__ */ jsx(Button, {