camox 0.11.0 → 0.13.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.
@@ -10,7 +10,7 @@ import { LexicalComposer } from "@lexical/react/LexicalComposer";
10
10
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
11
11
  import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
12
12
  import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
13
- import { COMMAND_PRIORITY_LOW, KEY_ESCAPE_COMMAND } from "lexical";
13
+ import { COMMAND_PRIORITY_LOW, INSERT_LINE_BREAK_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND } from "lexical";
14
14
 
15
15
  //#region src/core/components/lexical/InlineLexicalEditor.tsx
16
16
  function ExternalStateSync(t0) {
@@ -89,6 +89,28 @@ function EscapeHandler() {
89
89
  React.useEffect(t0, t1);
90
90
  return null;
91
91
  }
92
+ function EnterAsLineBreakHandler() {
93
+ const $ = c(3);
94
+ const [editor] = useLexicalComposerContext();
95
+ let t0;
96
+ let t1;
97
+ if ($[0] !== editor) {
98
+ t0 = () => editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
99
+ event?.preventDefault();
100
+ editor.dispatchCommand(INSERT_LINE_BREAK_COMMAND, false);
101
+ return true;
102
+ }, COMMAND_PRIORITY_LOW);
103
+ t1 = [editor];
104
+ $[0] = editor;
105
+ $[1] = t0;
106
+ $[2] = t1;
107
+ } else {
108
+ t0 = $[1];
109
+ t1 = $[2];
110
+ }
111
+ React.useEffect(t0, t1);
112
+ return null;
113
+ }
92
114
  function FocusBlurHandler(t0) {
93
115
  const $ = c(5);
94
116
  const { onFocus, onBlur } = t0;
@@ -157,6 +179,7 @@ function InlineLexicalEditor({ initialState, externalState, onChange, onFocus, o
157
179
  /* @__PURE__ */ jsx(OnChangePlugin, { onChange: handleChange }),
158
180
  /* @__PURE__ */ jsx(ExternalStateSync, { externalState }),
159
181
  /* @__PURE__ */ jsx(EscapeHandler, {}),
182
+ /* @__PURE__ */ jsx(EnterAsLineBreakHandler, {}),
160
183
  /* @__PURE__ */ jsx(FocusBlurHandler, {
161
184
  onFocus: handleFocus,
162
185
  onBlur: handleBlur
@@ -8,9 +8,32 @@ import { LexicalComposer } from "@lexical/react/LexicalComposer";
8
8
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
9
9
  import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
10
10
  import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
11
+ import { COMMAND_PRIORITY_LOW, INSERT_LINE_BREAK_COMMAND, KEY_ENTER_COMMAND } from "lexical";
11
12
  import { ContentEditable } from "@lexical/react/LexicalContentEditable";
12
13
 
13
14
  //#region src/core/components/lexical/SidebarLexicalEditor.tsx
15
+ function EnterAsLineBreakHandler() {
16
+ const $ = c(3);
17
+ const [editor] = useLexicalComposerContext();
18
+ let t0;
19
+ let t1;
20
+ if ($[0] !== editor) {
21
+ t0 = () => editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
22
+ event?.preventDefault();
23
+ editor.dispatchCommand(INSERT_LINE_BREAK_COMMAND, false);
24
+ return true;
25
+ }, COMMAND_PRIORITY_LOW);
26
+ t1 = [editor];
27
+ $[0] = editor;
28
+ $[1] = t0;
29
+ $[2] = t1;
30
+ } else {
31
+ t0 = $[1];
32
+ t1 = $[2];
33
+ }
34
+ React.useEffect(t0, t1);
35
+ return null;
36
+ }
14
37
  function ExternalStateSync(t0) {
15
38
  const $ = c(5);
16
39
  const { value, isSyncingRef } = t0;
@@ -82,7 +105,8 @@ function SidebarLexicalEditor({ id, value, onChange, onFocus, onBlur }) {
82
105
  /* @__PURE__ */ jsx(ExternalStateSync, {
83
106
  value,
84
107
  isSyncingRef
85
- })
108
+ }),
109
+ /* @__PURE__ */ jsx(EnterAsLineBreakHandler, {})
86
110
  ]
87
111
  });
88
112
  }
@@ -26,8 +26,11 @@ interface CreateBlockOptions<TSchemaShape extends Record<string, TSchema> = Reco
26
26
  * content: {
27
27
  * title: Type.String({ default: 'Hello' }),
28
28
  * items: Type.RepeatableItem({
29
- * name: Type.String({ default: 'Item' })
30
- * }, { minItems: 1, maxItems: 10 })
29
+ * content: { name: Type.String({ default: 'Item' }) },
30
+ * minItems: 1,
31
+ * maxItems: 10,
32
+ * toMarkdown: (c) => [c.name],
33
+ * })
31
34
  * }
32
35
  */
33
36
  content: TSchemaShape;
@@ -93,15 +93,18 @@ declare const Type$1: {
93
93
  *
94
94
  * @example
95
95
  * Type.RepeatableItem({
96
- * title: Type.String({ default: 'Item' }),
97
- * description: Type.String({ default: 'Description' })
98
- * }, {
96
+ * content: {
97
+ * title: Type.String({ default: 'Item' }),
98
+ * description: Type.String({ default: 'Description' }),
99
+ * },
99
100
  * minItems: 1,
100
101
  * maxItems: 10,
101
- * title: 'Items'
102
+ * title: 'Items',
103
+ * toMarkdown: (c) => [`### ${c.title}`, c.description],
102
104
  * })
103
105
  */
104
- RepeatableItem: <T extends Record<string, TSchema>>(shape: T, options: {
106
+ RepeatableItem: <T extends Record<string, TSchema>>(options: {
107
+ content: T;
105
108
  minItems: number;
106
109
  maxItems: number;
107
110
  title?: string;
@@ -96,9 +96,9 @@ const Type$1 = {
96
96
  fieldType: "String"
97
97
  });
98
98
  },
99
- RepeatableItem: (shape, options) => {
99
+ RepeatableItem: (options) => {
100
100
  if (options.minItems < 1) throw new Error("RepeatableItem requires minItems to be at least 1");
101
- const objectSchema = Type.Object(shape);
101
+ const objectSchema = Type.Object(options.content);
102
102
  const defaultItem = {};
103
103
  for (const [key, prop] of Object.entries(objectSchema.properties)) if ("default" in prop) defaultItem[key] = prop.default;
104
104
  const defaultArray = Array(options.minItems).fill(null).map(() => ({ ...defaultItem }));
@@ -14,8 +14,14 @@ function markdownToReactNodes(value) {
14
14
  let lastIndex = 0;
15
15
  let match;
16
16
  let key = 0;
17
+ const pushWithLineBreaks = (text) => {
18
+ text.split("\n").forEach((line, i) => {
19
+ if (i > 0) parts.push(/* @__PURE__ */ jsx("br", {}, key++));
20
+ if (line) parts.push(line);
21
+ });
22
+ };
17
23
  while ((match = regex.exec(value)) !== null) {
18
- if (match.index > lastIndex) parts.push(value.slice(lastIndex, match.index));
24
+ if (match.index > lastIndex) pushWithLineBreaks(value.slice(lastIndex, match.index));
19
25
  const stars = match[1].length;
20
26
  const content = match[2];
21
27
  if (stars === 3) parts.push(/* @__PURE__ */ jsx("strong", { children: /* @__PURE__ */ jsx("em", { children: content }) }, key++));
@@ -23,7 +29,7 @@ function markdownToReactNodes(value) {
23
29
  else parts.push(/* @__PURE__ */ jsx("em", { children: content }, key++));
24
30
  lastIndex = match.index + match[0].length;
25
31
  }
26
- if (lastIndex < value.length) parts.push(value.slice(lastIndex));
32
+ if (lastIndex < value.length) pushWithLineBreaks(value.slice(lastIndex));
27
33
  if (parts.length === 0) return value;
28
34
  return /* @__PURE__ */ jsx(Fragment, { children: parts });
29
35
  }
@@ -38,7 +38,7 @@ function extractMarkdown(node) {
38
38
  function markdownToLexicalState(markdown) {
39
39
  return { root: {
40
40
  children: markdown.split(/\n\n+/).map((para) => ({
41
- children: parseInlineMarkdown(para),
41
+ children: parseParagraphWithLineBreaks(para),
42
42
  direction: "ltr",
43
43
  format: "",
44
44
  indent: 0,
@@ -54,6 +54,18 @@ function markdownToLexicalState(markdown) {
54
54
  version: 1
55
55
  } };
56
56
  }
57
+ function parseParagraphWithLineBreaks(para) {
58
+ const lines = para.split("\n");
59
+ const nodes = [];
60
+ lines.forEach((line, index) => {
61
+ if (index > 0) nodes.push({
62
+ type: "linebreak",
63
+ version: 1
64
+ });
65
+ nodes.push(...parseInlineMarkdown(line));
66
+ });
67
+ return nodes;
68
+ }
57
69
  function parseInlineMarkdown(text) {
58
70
  const segments = [];
59
71
  const regex = /(\*{1,3})((?:(?!\1).)+)\1/g;
@@ -306,7 +306,7 @@ const CamoxPreview = (t0) => {
306
306
  const actions = [
307
307
  {
308
308
  id: "enter-presentation-mode",
309
- label: "Enter presentation mode",
309
+ label: "Hide Camox Studio",
310
310
  groupLabel: "Preview",
311
311
  checkIfAvailable: () => isAuthenticated && !isPresentationMode,
312
312
  execute: _temp4,
@@ -317,12 +317,12 @@ const CamoxPreview = (t0) => {
317
317
  },
318
318
  {
319
319
  id: "exit-presentation-mode",
320
- label: "Exit presentation mode",
320
+ label: "",
321
321
  groupLabel: "Preview",
322
322
  checkIfAvailable: () => isAuthenticated && isPresentationMode,
323
323
  execute: _temp5,
324
324
  shortcut: {
325
- key: "Escape",
325
+ key: "Enter",
326
326
  withMeta: true
327
327
  }
328
328
  },
@@ -305,7 +305,7 @@ const SearchEnginePreview = (t0) => {
305
305
  children: [t1, /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
306
306
  delay: 50,
307
307
  render: /* @__PURE__ */ jsx(Info, { className: "text-muted-foreground size-3.5" })
308
- }), /* @__PURE__ */ jsx(TooltipContent, { children: "Titles are cropped after 60 characters and descriptions after 155, like Google typically does." })] })]
308
+ }), /* @__PURE__ */ jsx(TooltipContent, { children: "Titles are cropped after 60 characters and descriptions after 155, like on Google Search results." })] })]
309
309
  });
310
310
  $[1] = t2;
311
311
  } else t2 = $[1];
@@ -1,6 +1,6 @@
1
1
  import { previewStore } from "../previewStore.js";
2
2
  import { useIsPreviewSheetOpen } from "./PreviewSideSheet.js";
3
- import { cn } from "../../../lib/utils.js";
3
+ import { cn, formatShortcut } from "../../../lib/utils.js";
4
4
  import { isOverlayMessage } from "../overlayMessages.js";
5
5
  import { FORMAT_FLAGS } from "../../../core/lib/modifierFormats.js";
6
6
  import { c } from "react/compiler-runtime";
@@ -8,13 +8,14 @@ import { Kbd } from "@camox/ui/kbd";
8
8
  import { useSelector } from "@xstate/store/react";
9
9
  import * as React from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
+ import { Button } from "@camox/ui/button";
11
12
  import * as Tooltip$1 from "@camox/ui/tooltip";
12
13
  import { Bold, Italic } from "lucide-react";
13
14
  import { ButtonGroup } from "@camox/ui/button-group";
14
15
  import { FloatingToolbar } from "@camox/ui/floating-toolbar";
15
16
  import { Toggle } from "@camox/ui/toggle";
16
17
 
17
- //#region src/features/preview/components/TextFormatToolbar.tsx
18
+ //#region src/features/preview/components/FieldToolbar.tsx
18
19
  const FORMAT_BUTTONS = [{
19
20
  key: "bold",
20
21
  flag: FORMAT_FLAGS.bold,
@@ -28,9 +29,10 @@ const FORMAT_BUTTONS = [{
28
29
  label: "Italic",
29
30
  shortcut: "⌘ I"
30
31
  }];
31
- const TextFormatToolbar = () => {
32
- const $ = c(15);
32
+ const FieldToolbar = () => {
33
+ const $ = c(19);
33
34
  const iframeElement = useSelector(previewStore, _temp);
35
+ const selection = useSelector(previewStore, _temp2);
34
36
  const isAnySideSheetOpen = useIsPreviewSheetOpen();
35
37
  const [hasSelection, setHasSelection] = React.useState(false);
36
38
  const [activeFormats, setActiveFormats] = React.useState(0);
@@ -67,25 +69,53 @@ const TextFormatToolbar = () => {
67
69
  $[3] = t2;
68
70
  } else t2 = $[3];
69
71
  const sendFormat = t2;
70
- const t3 = hasSelection && !isAnySideSheetOpen ? "opacity-100 translate-y-0" : "opacity-0 pointer-events-none translate-y-2";
71
- let t4;
72
- if ($[4] !== t3) {
73
- t4 = cn("bottom-17 gap-2", t3);
74
- $[4] = t3;
75
- $[5] = t4;
76
- } else t4 = $[5];
72
+ const isVisible = (selection?.type === "block-field" || selection?.type === "item-field") && !isAnySideSheetOpen;
73
+ let t3;
74
+ if ($[4] !== selection) {
75
+ t3 = () => {
76
+ if (!selection) return;
77
+ previewStore.send({
78
+ type: "openBlockContentSheet",
79
+ blockId: selection.blockId
80
+ });
81
+ };
82
+ $[4] = selection;
83
+ $[5] = t3;
84
+ } else t3 = $[5];
85
+ const handleEditInForm = t3;
86
+ const t4 = isVisible ? "opacity-100 translate-y-0" : "opacity-0 pointer-events-none translate-y-2";
77
87
  let t5;
78
- if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
79
- t5 = /* @__PURE__ */ jsx("span", {
80
- className: "text-muted-foreground text-sm",
81
- children: "Selected text"
82
- });
83
- $[6] = t5;
84
- } else t5 = $[6];
88
+ if ($[6] !== t4) {
89
+ t5 = cn("bottom-17 gap-2", t4);
90
+ $[6] = t4;
91
+ $[7] = t5;
92
+ } else t5 = $[7];
85
93
  let t6;
86
- if ($[7] !== activeFormats || $[8] !== sendFormat) {
87
- t6 = FORMAT_BUTTONS.map((t7) => {
88
- const { key, flag, icon: Icon, label, shortcut } = t7;
94
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
95
+ t6 = /* @__PURE__ */ jsx(Kbd, {
96
+ className: "ml-2",
97
+ children: formatShortcut({
98
+ key: "j",
99
+ withAlt: true
100
+ })
101
+ });
102
+ $[8] = t6;
103
+ } else t6 = $[8];
104
+ let t7;
105
+ if ($[9] !== handleEditInForm) {
106
+ t7 = /* @__PURE__ */ jsxs(Button, {
107
+ variant: "ghost",
108
+ size: "sm",
109
+ onClick: handleEditInForm,
110
+ children: ["Edit in form ", t6]
111
+ });
112
+ $[9] = handleEditInForm;
113
+ $[10] = t7;
114
+ } else t7 = $[10];
115
+ let t8;
116
+ if ($[11] !== activeFormats || $[12] !== hasSelection || $[13] !== sendFormat) {
117
+ t8 = hasSelection && /* @__PURE__ */ jsx(ButtonGroup, { children: FORMAT_BUTTONS.map((t9) => {
118
+ const { key, flag, icon: Icon, label, shortcut } = t9;
89
119
  const isActive = !!(activeFormats & flag);
90
120
  return /* @__PURE__ */ jsxs(Tooltip$1.Tooltip, { children: [/* @__PURE__ */ jsx(Tooltip$1.TooltipTrigger, {
91
121
  render: /* @__PURE__ */ jsx(Toggle, {
@@ -100,36 +130,35 @@ const TextFormatToolbar = () => {
100
130
  " ",
101
131
  /* @__PURE__ */ jsx(Kbd, { children: shortcut })
102
132
  ] })] }, key);
103
- });
104
- $[7] = activeFormats;
105
- $[8] = sendFormat;
106
- $[9] = t6;
107
- } else t6 = $[9];
108
- let t7;
109
- if ($[10] !== t6) {
110
- t7 = /* @__PURE__ */ jsx(ButtonGroup, { children: t6 });
111
- $[10] = t6;
112
- $[11] = t7;
113
- } else t7 = $[11];
114
- let t8;
115
- if ($[12] !== t4 || $[13] !== t7) {
116
- t8 = /* @__PURE__ */ jsxs(FloatingToolbar, {
117
- onMouseDown: _temp2,
118
- className: t4,
119
- children: [t5, t7]
120
- });
121
- $[12] = t4;
122
- $[13] = t7;
133
+ }) });
134
+ $[11] = activeFormats;
135
+ $[12] = hasSelection;
136
+ $[13] = sendFormat;
123
137
  $[14] = t8;
124
138
  } else t8 = $[14];
125
- return t8;
139
+ let t9;
140
+ if ($[15] !== t5 || $[16] !== t7 || $[17] !== t8) {
141
+ t9 = /* @__PURE__ */ jsxs(FloatingToolbar, {
142
+ onMouseDown: _temp3,
143
+ className: t5,
144
+ children: [t7, t8]
145
+ });
146
+ $[15] = t5;
147
+ $[16] = t7;
148
+ $[17] = t8;
149
+ $[18] = t9;
150
+ } else t9 = $[18];
151
+ return t9;
126
152
  };
127
153
  function _temp(state) {
128
154
  return state.context.iframeElement;
129
155
  }
130
- function _temp2(e) {
156
+ function _temp2(state_0) {
157
+ return state_0.context.selection;
158
+ }
159
+ function _temp3(e) {
131
160
  return e.preventDefault();
132
161
  }
133
162
 
134
163
  //#endregion
135
- export { TextFormatToolbar };
164
+ export { FieldToolbar };
@@ -196,16 +196,15 @@ const PageContentSheet = () => {
196
196
  }, [autoFocusFieldName, fieldIdPrefix]);
197
197
  React.useEffect(() => {
198
198
  const action = {
199
- id: "open-content-sheet",
200
- label: isOpen ? "Close content sheet" : "Open content sheet",
199
+ id: "toggle-content-sheet",
200
+ label: isOpen ? "Close form" : "Open in form",
201
201
  groupLabel: "Preview",
202
202
  shortcut: {
203
203
  key: "j",
204
- withMeta: true
204
+ withAlt: true
205
205
  },
206
- checkIfAvailable: () => isOpen || !!blockId,
206
+ checkIfAvailable: () => blockId != null,
207
207
  execute: () => {
208
- if (!blockId) return;
209
208
  previewStore.send({ type: "toggleContentSheet" });
210
209
  }
211
210
  };
@@ -325,47 +324,8 @@ const PageContentSheet = () => {
325
324
  }), /* @__PURE__ */ jsxs("div", {
326
325
  className: "flex-1 overflow-auto",
327
326
  children: [
328
- isViewingAsset && assetFieldName && isMultipleAsset && /* @__PURE__ */ jsx(MultipleAssetFieldEditor, {
329
- fieldName: assetFieldName,
330
- assetType,
331
- currentData,
332
- onFieldChange: activeFieldChangeHandler
333
- }),
334
- isViewingAsset && assetFieldName && !isMultipleAsset && /* @__PURE__ */ jsx(SingleAssetFieldEditor, {
335
- fieldName: assetFieldName,
336
- assetType,
337
- currentData,
338
- onFieldChange: activeFieldChangeHandler
339
- }),
340
- !isViewingAsset && isViewingLink && linkFieldName && /* @__PURE__ */ jsx("div", {
341
- className: "px-4 py-4",
342
- children: /* @__PURE__ */ jsx(LinkFieldEditor, {
343
- fieldName: linkFieldName,
344
- linkValue: currentData[linkFieldName] ?? {
345
- type: "external",
346
- text: "",
347
- href: "",
348
- newTab: false
349
- },
350
- onSave: (fieldName_1, value_3) => {
351
- activeFieldChangeHandler(fieldName_1, value_3);
352
- }
353
- })
354
- }),
355
- !isViewingAsset && !isViewingLink && /* @__PURE__ */ jsx(ItemFieldsEditor, {
356
- schema: currentSchema,
357
- data: currentData,
358
- blockId: block.id,
359
- itemId: currentItemId ?? void 0,
360
- onFieldChange: activeFieldChangeHandler,
361
- postToIframe,
362
- filesMap,
363
- itemsMap,
364
- fieldIdPrefix,
365
- autoFocusFieldName
366
- }, currentItemId ?? `block-${block.id}`),
367
327
  currentItemId == null && !fieldHasOwnView && settingsFields.length > 0 && /* @__PURE__ */ jsxs("div", {
368
- className: "border-border space-y-4 border-t px-4 py-4",
328
+ className: "border-border space-y-4 border-b px-4 py-4",
369
329
  children: [/* @__PURE__ */ jsx(Label, {
370
330
  className: "text-muted-foreground",
371
331
  children: "Settings"
@@ -373,14 +333,14 @@ const PageContentSheet = () => {
373
333
  const label = field.label ?? formatFieldName(field.name);
374
334
  const settingsValues = block.settings ?? {};
375
335
  if (field.fieldType === "Enum") {
376
- const value_4 = settingsValues[field.name] ?? (blockDef._internal.settingsSchema?.properties?.[field.name])?.default ?? "";
336
+ const value_3 = settingsValues[field.name] ?? (blockDef._internal.settingsSchema?.properties?.[field.name])?.default ?? "";
377
337
  return /* @__PURE__ */ jsxs("div", {
378
338
  className: "space-y-2",
379
339
  children: [/* @__PURE__ */ jsx(Label, {
380
340
  htmlFor: `setting-${field.name}`,
381
341
  children: label
382
342
  }), /* @__PURE__ */ jsxs(Select, {
383
- value: value_4,
343
+ value: value_3,
384
344
  onValueChange: (newValue) => {
385
345
  updateSettings.mutate({
386
346
  id: block.id,
@@ -418,7 +378,46 @@ const PageContentSheet = () => {
418
378
  }
419
379
  return null;
420
380
  })]
421
- })
381
+ }),
382
+ isViewingAsset && assetFieldName && isMultipleAsset && /* @__PURE__ */ jsx(MultipleAssetFieldEditor, {
383
+ fieldName: assetFieldName,
384
+ assetType,
385
+ currentData,
386
+ onFieldChange: activeFieldChangeHandler
387
+ }),
388
+ isViewingAsset && assetFieldName && !isMultipleAsset && /* @__PURE__ */ jsx(SingleAssetFieldEditor, {
389
+ fieldName: assetFieldName,
390
+ assetType,
391
+ currentData,
392
+ onFieldChange: activeFieldChangeHandler
393
+ }),
394
+ !isViewingAsset && isViewingLink && linkFieldName && /* @__PURE__ */ jsx("div", {
395
+ className: "px-4 py-4",
396
+ children: /* @__PURE__ */ jsx(LinkFieldEditor, {
397
+ fieldName: linkFieldName,
398
+ linkValue: currentData[linkFieldName] ?? {
399
+ type: "external",
400
+ text: "",
401
+ href: "",
402
+ newTab: false
403
+ },
404
+ onSave: (fieldName_1, value_4) => {
405
+ activeFieldChangeHandler(fieldName_1, value_4);
406
+ }
407
+ })
408
+ }),
409
+ !isViewingAsset && !isViewingLink && /* @__PURE__ */ jsx(ItemFieldsEditor, {
410
+ schema: currentSchema,
411
+ data: currentData,
412
+ blockId: block.id,
413
+ itemId: currentItemId ?? void 0,
414
+ onFieldChange: activeFieldChangeHandler,
415
+ postToIframe,
416
+ filesMap,
417
+ itemsMap,
418
+ fieldIdPrefix,
419
+ autoFocusFieldName
420
+ }, currentItemId ?? `block-${block.id}`)
422
421
  ]
423
422
  })]
424
423
  });
@@ -88,7 +88,7 @@ const PeekedBlock = (t0) => {
88
88
  if (e.propertyName !== "grid-template-rows" || e.target !== e.currentTarget) return;
89
89
  if (isExpanded) {
90
90
  peekedBlockRef.current?.scrollIntoView({
91
- behavior: "instant",
91
+ behavior: "smooth",
92
92
  block: "start"
93
93
  });
94
94
  return;
@@ -5,10 +5,10 @@ import { checkIfInputFocused } from "../../../lib/utils.js";
5
5
  import { Frame, useFrame } from "./Frame.js";
6
6
  import { useBlockActionsShortcuts } from "./BlockActionsPopover.js";
7
7
  import { FieldOverlayStyles } from "./FieldOverlayStyles.js";
8
+ import { FieldToolbar } from "./FieldToolbar.js";
8
9
  import { Overlays } from "./Overlays.js";
9
10
  import { OverlayTracker } from "./OverlayTracker.js";
10
11
  import { PreviewToolbar } from "./PreviewToolbar.js";
11
- import { TextFormatToolbar } from "./TextFormatToolbar.js";
12
12
  import { c } from "react/compiler-runtime";
13
13
  import { useSelector } from "@xstate/store/react";
14
14
  import * as React from "react";
@@ -245,7 +245,7 @@ const PreviewPanel = (t0) => {
245
245
  children
246
246
  }), /* @__PURE__ */ jsx(Overlays, { iframeElement })]
247
247
  }),
248
- /* @__PURE__ */ jsx(TextFormatToolbar, {}),
248
+ /* @__PURE__ */ jsx(FieldToolbar, {}),
249
249
  /* @__PURE__ */ jsx(PreviewToolbar, {})
250
250
  ]
251
251
  }) : /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -255,7 +255,7 @@ const PreviewPanel = (t0) => {
255
255
  children
256
256
  }),
257
257
  /* @__PURE__ */ jsx(Overlays, { iframeElement }),
258
- /* @__PURE__ */ jsx(TextFormatToolbar, {}),
258
+ /* @__PURE__ */ jsx(FieldToolbar, {}),
259
259
  /* @__PURE__ */ jsx(PreviewToolbar, {})
260
260
  ] });
261
261
  $[8] = children;
@@ -197,7 +197,7 @@ const PreviewToolbar = () => {
197
197
  } else t27 = $[44];
198
198
  let t28;
199
199
  if ($[45] !== t27) {
200
- t28 = /* @__PURE__ */ jsxs(Tooltip$1.TooltipContent, { children: ["Hide all Camox UI ", t27] });
200
+ t28 = /* @__PURE__ */ jsxs(Tooltip$1.TooltipContent, { children: ["Hide Camox Studio ", t27] });
201
201
  $[45] = t27;
202
202
  $[46] = t28;
203
203
  } else t28 = $[46];
@@ -43,18 +43,15 @@ const previewStore = createStore({
43
43
  enterPresentationMode: (context, _, enqueue) => {
44
44
  if (context.isPresentationMode) return context;
45
45
  enqueue.effect(() => {
46
- toast("Entering presentation mode. Press ⌘ + Escape to restore admin interface", { duration: 4e3 });
46
+ toast("Press ⌘ + Enter to restore Camox Studio", { duration: 2500 });
47
47
  });
48
48
  return {
49
49
  ...context,
50
50
  isPresentationMode: true
51
51
  };
52
52
  },
53
- exitPresentationMode: (context, _, enqueue) => {
53
+ exitPresentationMode: (context) => {
54
54
  if (!context.isPresentationMode) return context;
55
- enqueue.effect(() => {
56
- toast("Leaving presentation mode");
57
- });
58
55
  return {
59
56
  ...context,
60
57
  isPresentationMode: false
@@ -62,7 +62,7 @@ const AuthenticatedCamoxProvider = (t0) => {
62
62
  return t4;
63
63
  };
64
64
  const UnauthenticatedCamoxProvider = (t0) => {
65
- const $ = c(11);
65
+ const $ = c(16);
66
66
  const { children } = t0;
67
67
  const signInRedirect = useSignInRedirect();
68
68
  const { authenticationUrl } = useAuthContext();
@@ -70,7 +70,7 @@ const UnauthenticatedCamoxProvider = (t0) => {
70
70
  if ($[0] !== signInRedirect) {
71
71
  t1 = () => {
72
72
  const handleKeyDown = (event) => {
73
- if ((event.metaKey || event.ctrlKey) && event.key === "Escape") {
73
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
74
74
  event.preventDefault();
75
75
  signInRedirect();
76
76
  }
@@ -112,25 +112,39 @@ const UnauthenticatedCamoxProvider = (t0) => {
112
112
  t4 = $[7];
113
113
  }
114
114
  React.useEffect(t3, t4);
115
+ const { theme } = useTheme();
115
116
  let t5;
116
117
  if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
117
- t5 = /* @__PURE__ */ jsx(Toaster, {
118
- theme: "light",
119
- position: "bottom-right",
120
- offset: { bottom: "1rem" }
121
- });
118
+ t5 = { bottom: "1rem" };
122
119
  $[8] = t5;
123
120
  } else t5 = $[8];
124
121
  let t6;
125
- if ($[9] !== children) {
126
- t6 = /* @__PURE__ */ jsxs(Fragment, { children: [t5, /* @__PURE__ */ jsx("div", {
127
- className: "bg-background min-h-screen",
128
- children
129
- })] });
130
- $[9] = children;
122
+ if ($[9] !== theme) {
123
+ t6 = /* @__PURE__ */ jsx(Toaster, {
124
+ theme,
125
+ position: "bottom-right",
126
+ offset: t5
127
+ });
128
+ $[9] = theme;
131
129
  $[10] = t6;
132
130
  } else t6 = $[10];
133
- return t6;
131
+ let t7;
132
+ if ($[11] !== children) {
133
+ t7 = /* @__PURE__ */ jsx("div", {
134
+ className: "bg-background min-h-screen",
135
+ children
136
+ });
137
+ $[11] = children;
138
+ $[12] = t7;
139
+ } else t7 = $[12];
140
+ let t8;
141
+ if ($[13] !== t6 || $[14] !== t7) {
142
+ t8 = /* @__PURE__ */ jsxs(Fragment, { children: [t6, t7] });
143
+ $[13] = t6;
144
+ $[14] = t7;
145
+ $[15] = t8;
146
+ } else t8 = $[15];
147
+ return t8;
134
148
  };
135
149
  function CamoxProvider({ children, camoxApp, authenticationUrl, apiUrl, projectSlug, environmentName }) {
136
150
  const authClient = React.useMemo(() => createCamoxAuthClient(apiUrl), [apiUrl]);