camox 0.42.0 → 0.44.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 (99) hide show
  1. package/bin/camox.mjs +9 -1
  2. package/dist/core/components/lexical/{GradientNode.js → HighlightNode.js} +34 -34
  3. package/dist/core/components/lexical/InlineLexicalEditor.js +14 -14
  4. package/dist/core/components/lexical/InlineStylesPlugin.js +25 -9
  5. package/dist/core/components/lexical/SelectionBroadcaster.js +7 -7
  6. package/dist/core/components/lexical/SidebarLexicalEditor.js +24 -24
  7. package/dist/core/components/lexical/TextLinkPopover.js +191 -208
  8. package/dist/core/components/lexical/editorConfig.js +2 -2
  9. package/dist/core/createApp.d.ts +31 -4
  10. package/dist/core/createApp.js +2 -1
  11. package/dist/core/createBlock.js +24 -10
  12. package/dist/core/createLayout.d.ts +16 -3
  13. package/dist/core/createLayout.js +15 -15
  14. package/dist/core/derivedRoutes.js +1 -1
  15. package/dist/core/dom.d.ts +17 -0
  16. package/dist/core/dom.js +22 -0
  17. package/dist/core/editing/createEditableBlock.d.ts +135 -1
  18. package/dist/core/editing/createEditableBlock.js +209 -74
  19. package/dist/core/lib/contentType.d.ts +5 -0
  20. package/dist/core/lib/contentType.js +11 -0
  21. package/dist/core/lib/fieldTypes.js +1 -0
  22. package/dist/core/lib/iconTypes.d.ts +13 -0
  23. package/dist/core/lib/icons.d.ts +6 -0
  24. package/dist/core/lib/icons.js +130 -0
  25. package/dist/core/lib/lexicalReact.js +4 -4
  26. package/dist/core/lib/lexicalState.js +8 -8
  27. package/dist/core/lib/modifierFormats.js +2 -2
  28. package/dist/core/lib/textLinks.js +5 -2
  29. package/dist/core/lib/textStyles.d.ts +3 -3
  30. package/dist/core/lib/textStyles.js +9 -14
  31. package/dist/core/pageDestinations.js +37 -0
  32. package/dist/features/content/components/AssetCard.js +104 -68
  33. package/dist/features/og/imageResponse.node.js +11 -9
  34. package/dist/features/preview/CamoxPreview.js +148 -146
  35. package/dist/features/preview/commentsEnabled.js +2 -2
  36. package/dist/features/preview/components/AddBlockSidebar.js +1 -1
  37. package/dist/features/preview/components/AssetLightbox.js +17 -6
  38. package/dist/features/preview/components/AttachedComments.js +224 -87
  39. package/dist/features/preview/components/BlockActionsPopover.js +1 -1
  40. package/dist/features/preview/components/CommentTargetQuote.js +22 -21
  41. package/dist/features/preview/components/CreatePageModal.js +4 -4
  42. package/dist/features/preview/components/DerivedLayoutDialog.js +36 -21
  43. package/dist/features/preview/components/DerivedLayoutSidebar.js +45 -26
  44. package/dist/features/preview/components/DerivedPageInfoSidebar.js +38 -26
  45. package/dist/features/preview/components/FieldOverlayStyles.js +29 -9
  46. package/dist/features/preview/components/FieldToolbar.js +12 -12
  47. package/dist/features/preview/components/IconFieldEditor.js +231 -0
  48. package/dist/features/preview/components/ItemFieldsEditor.js +21 -14
  49. package/dist/features/preview/components/LinkFieldEditor.js +212 -209
  50. package/dist/features/preview/components/OverlayTracker.js +1 -1
  51. package/dist/features/preview/components/PageEditorSidebar.js +1 -1
  52. package/dist/features/preview/components/PageInfoSidebar.js +28 -28
  53. package/dist/features/preview/components/PagePicker.js +46 -46
  54. package/dist/features/preview/components/PageTree.js +1 -1
  55. package/dist/features/preview/components/PreviewPanel.js +1 -1
  56. package/dist/features/preview/components/PreviewToolbar.js +224 -225
  57. package/dist/features/preview/components/PublicationRow.js +8 -4
  58. package/dist/features/preview/components/SendFeedbackDialog.js +83 -0
  59. package/dist/features/preview/components/useRepeatableItemActions.js +1 -1
  60. package/dist/features/preview/overlayHighlights.js +54 -0
  61. package/dist/features/preview/previewCommentsStore.js +54 -34
  62. package/dist/features/preview/previewSelection.js +28 -23
  63. package/dist/features/preview/publication.js +10 -0
  64. package/dist/features/preview/usePageComments.js +39 -0
  65. package/dist/features/provider/CoreCamoxProvider.js +38 -6
  66. package/dist/features/provider/LocalhostPreviewProvider.js +81 -45
  67. package/dist/features/provider/components/CommandPalette.js +35 -84
  68. package/dist/features/runtime/pageApp.js +32 -28
  69. package/dist/features/runtime/pageServer.js +4 -1
  70. package/dist/features/runtime/runtime.d.ts +2 -0
  71. package/dist/features/runtime/runtime.js +45 -21
  72. package/dist/features/studio/components/EnvironmentMenu.js +76 -63
  73. package/dist/features/studio/components/Navbar.js +53 -80
  74. package/dist/features/vite/auth.js +1 -50
  75. package/dist/features/vite/iconGeneration.js +16 -0
  76. package/dist/features/vite/layoutGeneration.js +7 -3
  77. package/dist/features/vite/vite.d.ts +4 -2
  78. package/dist/features/vite/vite.js +24 -3
  79. package/dist/hooks/use-page-destinations.js +53 -0
  80. package/dist/lib/auth.js +40 -20
  81. package/dist/lib/preview-handoff.js +13 -0
  82. package/dist/lib/queries.js +12 -1
  83. package/dist/lib/server-auth-cookie.js +21 -0
  84. package/dist/lib/use-project-room.js +5 -2
  85. package/dist/studio-overlays.css +19 -15
  86. package/dist/studio.css +1 -1
  87. package/package.json +9 -4
  88. package/skills/camox/SKILL.md +38 -9
  89. package/skills/camox/references/block-definitions.md +107 -286
  90. package/skills/camox/references/cli-common.md +16 -4
  91. package/skills/camox/references/cli-content.md +158 -0
  92. package/skills/camox/references/cli-environments.md +1 -1
  93. package/skills/camox/references/dom-integrations.md +93 -0
  94. package/skills/camox/references/field-styling.md +50 -0
  95. package/skills/camox/references/layout-definitions.md +33 -147
  96. package/skills/camox/references/routed-layouts.md +71 -0
  97. package/skills/camoxify/SKILL.md +66 -0
  98. package/skills/camox/references/cli-blocks.md +0 -78
  99. package/skills/camox/references/cli-pages.md +0 -53
@@ -1,7 +1,7 @@
1
1
  import { useProjectSlug } from "../../../lib/auth.js";
2
2
  import { usePageBlocks } from "../../../lib/normalized-data.js";
3
- import { layoutQueries, projectQueries } from "../../../lib/queries.js";
4
3
  import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
4
+ import { layoutQueries, projectQueries } from "../../../lib/queries.js";
5
5
  import { previewStore, selectPreviewSource } from "../previewStore.js";
6
6
  import { PagePicker } from "./PagePicker.js";
7
7
  import { LayoutBlockItem } from "./PageTree.js";
@@ -16,10 +16,10 @@ import { PanelContent, PanelHeader } from "@camox/ui/panel";
16
16
  //#region src/features/preview/components/DerivedLayoutSidebar.tsx
17
17
  const EMPTY_PAGE = { blockIds: [] };
18
18
  function DerivedLayoutSidebar(t0) {
19
- const $ = c(32);
20
- if ($[0] !== "2c7da8bd37fd1558e1c31149d4435d439cdd1425cb374116d681960617531266") {
21
- for (let $i = 0; $i < 32; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
22
- $[0] = "2c7da8bd37fd1558e1c31149d4435d439cdd1425cb374116d681960617531266";
19
+ const $ = c(39);
20
+ if ($[0] !== "c2b47a0ded5e80952966193136846d2771f48746af4a761ba4e0ef778f954b27") {
21
+ for (let $i = 0; $i < 39; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
22
+ $[0] = "c2b47a0ded5e80952966193136846d2771f48746af4a761ba4e0ef778f954b27";
23
23
  }
24
24
  const { layout } = t0;
25
25
  const source = useSelector(previewStore, selectPreviewSource);
@@ -36,12 +36,14 @@ function DerivedLayoutSidebar(t0) {
36
36
  const app = useCamoxApp();
37
37
  let t2;
38
38
  if ($[3] !== app || $[4] !== layout.layoutId) {
39
- t2 = app.getLayoutById(layout.layoutId)?._internal.title ?? layout.layoutId;
39
+ t2 = app.getLayoutById(layout.layoutId);
40
40
  $[3] = app;
41
41
  $[4] = layout.layoutId;
42
42
  $[5] = t2;
43
43
  } else t2 = $[5];
44
- const layoutName = t2;
44
+ const definition = t2;
45
+ const layoutName = definition?._internal.title ?? layout.layoutId;
46
+ const singleton = definition?._internal.kind === "singleton";
45
47
  const projectSlug = useProjectSlug();
46
48
  let t3;
47
49
  if ($[6] !== projectSlug) {
@@ -132,28 +134,45 @@ function DerivedLayoutSidebar(t0) {
132
134
  $[24] = layoutName;
133
135
  $[25] = t11;
134
136
  } else t11 = $[25];
135
- let t12;
136
- if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
137
- t12 = /* @__PURE__ */ jsxs(Alert, { children: [/* @__PURE__ */ jsx(AlertTitle, { children: "Shared layout blocks" }), /* @__PURE__ */ jsx(AlertDescription, { children: "Changes apply to every page using this layout. The generated page content is managed outside the studio." })] });
138
- $[26] = t12;
139
- } else t12 = $[26];
137
+ const t12 = singleton ? "Code-owned page" : "Shared layout blocks";
140
138
  let t13;
141
- if ($[27] !== t11) {
142
- t13 = /* @__PURE__ */ jsxs(PanelContent, {
139
+ if ($[26] !== t12) {
140
+ t13 = /* @__PURE__ */ jsx(AlertTitle, { children: t12 });
141
+ $[26] = t12;
142
+ $[27] = t13;
143
+ } else t13 = $[27];
144
+ const t14 = singleton ? "Edit and publish this page’s blocks here. Its URL and structure are defined in code. Synced blocks share content with their other instances." : "Changes apply to every page using this layout. The generated page content is managed outside the studio.";
145
+ let t15;
146
+ if ($[28] !== t14) {
147
+ t15 = /* @__PURE__ */ jsx(AlertDescription, { children: t14 });
148
+ $[28] = t14;
149
+ $[29] = t15;
150
+ } else t15 = $[29];
151
+ let t16;
152
+ if ($[30] !== t13 || $[31] !== t15) {
153
+ t16 = /* @__PURE__ */ jsxs(Alert, { children: [t13, t15] });
154
+ $[30] = t13;
155
+ $[31] = t15;
156
+ $[32] = t16;
157
+ } else t16 = $[32];
158
+ let t17;
159
+ if ($[33] !== t11 || $[34] !== t16) {
160
+ t17 = /* @__PURE__ */ jsxs(PanelContent, {
143
161
  className: "flex grow basis-0 flex-col gap-4 overflow-auto p-2",
144
- children: [t11, t12]
162
+ children: [t11, t16]
145
163
  });
146
- $[27] = t11;
147
- $[28] = t13;
148
- } else t13 = $[28];
149
- let t14;
150
- if ($[29] !== t10 || $[30] !== t13) {
151
- t14 = /* @__PURE__ */ jsxs(Fragment, { children: [t10, t13] });
152
- $[29] = t10;
153
- $[30] = t13;
154
- $[31] = t14;
155
- } else t14 = $[31];
156
- return t14;
164
+ $[33] = t11;
165
+ $[34] = t16;
166
+ $[35] = t17;
167
+ } else t17 = $[35];
168
+ let t18;
169
+ if ($[36] !== t10 || $[37] !== t17) {
170
+ t18 = /* @__PURE__ */ jsxs(Fragment, { children: [t10, t17] });
171
+ $[36] = t10;
172
+ $[37] = t17;
173
+ $[38] = t18;
174
+ } else t18 = $[38];
175
+ return t18;
157
176
  }
158
177
 
159
178
  //#endregion
@@ -1,14 +1,14 @@
1
1
  import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
2
2
  import { c } from "react/compiler-runtime";
3
- import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
4
  import { Alert, AlertDescription, AlertTitle } from "@camox/ui/alert";
5
5
 
6
6
  //#region src/features/preview/components/DerivedPageInfoSidebar.tsx
7
7
  function DerivedPageInfoSidebar(t0) {
8
- const $ = c(8);
9
- if ($[0] !== "188f548de856db3a863c0d74a6e937ddbe5a25be65cd852330ec33162eb56ebf") {
10
- for (let $i = 0; $i < 8; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
11
- $[0] = "188f548de856db3a863c0d74a6e937ddbe5a25be65cd852330ec33162eb56ebf";
8
+ const $ = c(13);
9
+ if ($[0] !== "4055e1683cf89ee8b21c17d486a36f5d2dcf14d6cea02195afa4565d830e71cf") {
10
+ for (let $i = 0; $i < 13; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
11
+ $[0] = "4055e1683cf89ee8b21c17d486a36f5d2dcf14d6cea02195afa4565d830e71cf";
12
12
  }
13
13
  const { layoutId } = t0;
14
14
  const camoxApp = useCamoxApp();
@@ -19,7 +19,9 @@ function DerivedPageInfoSidebar(t0) {
19
19
  $[2] = layoutId;
20
20
  $[3] = t1;
21
21
  } else t1 = $[3];
22
- const layoutName = t1?._internal.title ?? layoutId;
22
+ const layout = t1;
23
+ const layoutName = layout?._internal.title ?? layoutId;
24
+ const singleton = layout?._internal.kind === "singleton";
23
25
  let t2;
24
26
  if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
25
27
  t2 = /* @__PURE__ */ jsx("p", {
@@ -28,29 +30,39 @@ function DerivedPageInfoSidebar(t0) {
28
30
  });
29
31
  $[4] = t2;
30
32
  } else t2 = $[4];
31
- let t3;
32
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
33
- t3 = /* @__PURE__ */ jsx(AlertTitle, { children: "Derived page" });
34
- $[5] = t3;
35
- } else t3 = $[5];
33
+ const t3 = singleton ? "Singleton page" : "Derived page";
36
34
  let t4;
37
- if ($[6] !== layoutName) {
38
- t4 = /* @__PURE__ */ jsxs("div", {
35
+ if ($[5] !== t3) {
36
+ t4 = /* @__PURE__ */ jsx(AlertTitle, { children: t3 });
37
+ $[5] = t3;
38
+ $[6] = t4;
39
+ } else t4 = $[6];
40
+ let t5;
41
+ if ($[7] !== layoutName || $[8] !== singleton) {
42
+ t5 = /* @__PURE__ */ jsx(AlertDescription, { children: singleton ? /* @__PURE__ */ jsx(Fragment, { children: "This page and its URL are defined in code. Select a block in the preview to edit its content. The page cannot be deleted or moved in Studio." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
43
+ "This page is generated using the",
44
+ " ",
45
+ /* @__PURE__ */ jsx("strong", {
46
+ className: "font-semibold italic",
47
+ children: layoutName
48
+ }),
49
+ " layout. Select a shared block in the preview to edit it."
50
+ ] }) });
51
+ $[7] = layoutName;
52
+ $[8] = singleton;
53
+ $[9] = t5;
54
+ } else t5 = $[9];
55
+ let t6;
56
+ if ($[10] !== t4 || $[11] !== t5) {
57
+ t6 = /* @__PURE__ */ jsxs("div", {
39
58
  className: "flex-1 space-y-4 p-2 pt-4",
40
- children: [t2, /* @__PURE__ */ jsxs(Alert, { children: [t3, /* @__PURE__ */ jsxs(AlertDescription, { children: [
41
- "This page is generated using the",
42
- " ",
43
- /* @__PURE__ */ jsx("strong", {
44
- className: "font-semibold italic",
45
- children: layoutName
46
- }),
47
- " layout. Select a shared block in the preview to edit it."
48
- ] })] })]
59
+ children: [t2, /* @__PURE__ */ jsxs(Alert, { children: [t4, t5] })]
49
60
  });
50
- $[6] = layoutName;
51
- $[7] = t4;
52
- } else t4 = $[7];
53
- return t4;
61
+ $[10] = t4;
62
+ $[11] = t5;
63
+ $[12] = t6;
64
+ } else t6 = $[12];
65
+ return t6;
54
66
  }
55
67
 
56
68
  //#endregion
@@ -1,20 +1,40 @@
1
+ import { observeOverlayHighlights } from "../overlayHighlights.js";
2
+ import { useFrame } from "./Frame.js";
1
3
  import { c } from "react/compiler-runtime";
4
+ import { useLayoutEffect } from "react";
2
5
  import { jsx } from "react/jsx-runtime";
3
6
  import overlayStyles from "virtual:camox-overlay-css";
4
7
 
5
8
  //#region src/features/preview/components/FieldOverlayStyles.tsx
6
9
  const FieldOverlayStyles = () => {
7
- const $ = c(2);
8
- if ($[0] !== "83d25ec6adf4086440810b5b8470ed59a6027bd66aa8eceb3fd93db084e20139") {
9
- for (let $i = 0; $i < 2; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
10
- $[0] = "83d25ec6adf4086440810b5b8470ed59a6027bd66aa8eceb3fd93db084e20139";
10
+ const $ = c(5);
11
+ if ($[0] !== "1aef50f61b41fbdb91f283373fd928447f799905d1774e36dd8b81214d12c471") {
12
+ for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
13
+ $[0] = "1aef50f61b41fbdb91f283373fd928447f799905d1774e36dd8b81214d12c471";
11
14
  }
15
+ const { window } = useFrame();
12
16
  let t0;
13
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
14
- t0 = /* @__PURE__ */ jsx("style", { children: overlayStyles });
15
- $[1] = t0;
16
- } else t0 = $[1];
17
- return t0;
17
+ let t1;
18
+ if ($[1] !== window) {
19
+ t0 = () => {
20
+ if (!window) return;
21
+ return observeOverlayHighlights(window.document);
22
+ };
23
+ t1 = [window];
24
+ $[1] = window;
25
+ $[2] = t0;
26
+ $[3] = t1;
27
+ } else {
28
+ t0 = $[2];
29
+ t1 = $[3];
30
+ }
31
+ useLayoutEffect(t0, t1);
32
+ let t2;
33
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
34
+ t2 = /* @__PURE__ */ jsx("style", { children: overlayStyles });
35
+ $[4] = t2;
36
+ } else t2 = $[4];
37
+ return t2;
18
38
  };
19
39
 
20
40
  //#endregion
@@ -9,7 +9,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { useSelector } from "@xstate/store-react";
10
10
  import { Kbd } from "@camox/ui/kbd";
11
11
  import { Button } from "@camox/ui/button";
12
- import { Blend, Bold, Italic, Underline } from "lucide-react";
12
+ import { Bold, Highlighter, Italic, Strikethrough } from "lucide-react";
13
13
  import * as Tooltip$1 from "@camox/ui/tooltip";
14
14
  import { ButtonGroup } from "@camox/ui/button-group";
15
15
  import { FloatingToolbar } from "@camox/ui/floating-toolbar";
@@ -32,25 +32,25 @@ const FORMAT_BUTTONS = [
32
32
  shortcut: "⌘ I"
33
33
  },
34
34
  {
35
- key: "underline",
36
- flag: FORMAT_FLAGS.underline,
37
- icon: Underline,
38
- label: "Underline",
39
- shortcut: "⌘ U"
35
+ key: "strikethrough",
36
+ flag: FORMAT_FLAGS.strikethrough,
37
+ icon: Strikethrough,
38
+ label: "Strikethrough",
39
+ shortcut: null
40
40
  },
41
41
  {
42
- key: "gradient",
43
- flag: FORMAT_FLAGS.gradient,
44
- icon: Blend,
45
- label: "Gradient",
42
+ key: "highlight",
43
+ flag: FORMAT_FLAGS.highlight,
44
+ icon: Highlighter,
45
+ label: "Highlight",
46
46
  shortcut: null
47
47
  }
48
48
  ];
49
49
  const FieldToolbar = () => {
50
50
  const $ = c(28);
51
- if ($[0] !== "62fc88dbf76bce176e1b9d35a550f78886d467e61d1692885683da9874bf34dd") {
51
+ if ($[0] !== "d1e889a3597708ac2bc6872804f1131756eb2e3aa358ca08ef83b3491906d96a") {
52
52
  for (let $i = 0; $i < 28; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
53
- $[0] = "62fc88dbf76bce176e1b9d35a550f78886d467e61d1692885683da9874bf34dd";
53
+ $[0] = "d1e889a3597708ac2bc6872804f1131756eb2e3aa358ca08ef83b3491906d96a";
54
54
  }
55
55
  const iframeElement = useSelector(previewStore, _temp);
56
56
  const [hasSelection, setHasSelection] = React.useState(false);
@@ -0,0 +1,231 @@
1
+ import { IconSvg } from "../../../core/lib/icons.js";
2
+ import { c } from "react/compiler-runtime";
3
+ import { useEffect, useMemo, useRef, useState } from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Button } from "@camox/ui/button";
6
+ import { ChevronsUpDown, SearchIcon } from "lucide-react";
7
+ import { Popover, PopoverContent, PopoverTrigger } from "@camox/ui/popover";
8
+ import { InputGroup, InputGroupAddon, InputGroupInput } from "@camox/ui/input-group";
9
+ import { commandFilter } from "@camox/ui/command";
10
+ import { Combobox } from "@base-ui/react/combobox";
11
+ import { defaultRangeExtractor, useVirtualizer } from "@tanstack/react-virtual";
12
+
13
+ //#region src/features/preview/components/IconFieldEditor.tsx
14
+ const COLUMNS = 7;
15
+ const ROW_HEIGHT = 44;
16
+ function IconPicker({ value, ids, onSelect }) {
17
+ "use no memo";
18
+ const scrollRef = useRef(null);
19
+ const [ready, setReady] = useState(false);
20
+ useEffect(() => setReady(true), []);
21
+ const [search, setSearch] = useState("");
22
+ const [activeId, setActiveId] = useState(value);
23
+ const filteredIds = useMemo(() => {
24
+ const query = search.trim();
25
+ if (!query) return ids;
26
+ return ids.map((id) => ({
27
+ id,
28
+ score: commandFilter(id, query)
29
+ })).filter(({ score }) => score > 0).sort((a, b) => b.score - a.score).map(({ id: id_0 }) => id_0);
30
+ }, [ids, search]);
31
+ const activeIndex = Math.max(0, filteredIds.indexOf(activeId));
32
+ const activeRow = Math.floor(activeIndex / COLUMNS);
33
+ const virtualizer = useVirtualizer({
34
+ count: Math.ceil(filteredIds.length / COLUMNS),
35
+ getScrollElement: () => scrollRef.current,
36
+ estimateSize: () => ROW_HEIGHT,
37
+ overscan: 2,
38
+ initialOffset: () => activeRow * ROW_HEIGHT,
39
+ rangeExtractor: (range) => [...new Set([...defaultRangeExtractor(range), activeRow])].sort((a_0, b_0) => a_0 - b_0)
40
+ });
41
+ return /* @__PURE__ */ jsx(Combobox.Root, {
42
+ inline: true,
43
+ open: ready,
44
+ grid: true,
45
+ virtualized: true,
46
+ autoHighlight: true,
47
+ loopFocus: false,
48
+ items: ids,
49
+ filteredItems: filteredIds,
50
+ value,
51
+ inputValue: search,
52
+ onInputValueChange: (nextSearch) => {
53
+ setSearch(nextSearch);
54
+ setActiveId("");
55
+ virtualizer.scrollToOffset(0);
56
+ },
57
+ onItemHighlighted: (id_1, { index, reason }) => {
58
+ setActiveId(id_1 ?? "");
59
+ if (index < 0 || reason === "pointer") return;
60
+ virtualizer.scrollToIndex(Math.floor(index / COLUMNS), { align: "auto" });
61
+ },
62
+ children: /* @__PURE__ */ jsxs("div", {
63
+ className: "flex flex-col gap-1 p-1",
64
+ children: [/* @__PURE__ */ jsx("div", {
65
+ className: "p-1 pb-0",
66
+ children: /* @__PURE__ */ jsxs(InputGroup, {
67
+ className: "border-input/30 bg-input/30 h-8 rounded-lg shadow-none",
68
+ children: [/* @__PURE__ */ jsx(Combobox.Input, {
69
+ render: /* @__PURE__ */ jsx(InputGroupInput, {}),
70
+ "aria-label": "Search icons",
71
+ placeholder: "Search icons…"
72
+ }), /* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(SearchIcon, { className: "size-4" }) })]
73
+ })
74
+ }), /* @__PURE__ */ jsxs("div", {
75
+ className: "p-1",
76
+ children: [/* @__PURE__ */ jsx(Combobox.List, {
77
+ ref: scrollRef,
78
+ "aria-rowcount": Math.ceil(filteredIds.length / COLUMNS),
79
+ "aria-colcount": COLUMNS,
80
+ "aria-label": "Choose icon",
81
+ className: "no-scrollbar max-h-72 overflow-x-hidden overflow-y-auto",
82
+ children: /* @__PURE__ */ jsx("div", {
83
+ className: "relative",
84
+ style: { height: virtualizer.getTotalSize() },
85
+ children: virtualizer.getVirtualItems().map((row) => /* @__PURE__ */ jsx(Combobox.Row, {
86
+ "aria-rowindex": row.index + 1,
87
+ className: "absolute top-0 left-0 grid w-full grid-cols-7 gap-1",
88
+ style: {
89
+ height: ROW_HEIGHT - 4,
90
+ transform: `translateY(${row.start}px)`
91
+ },
92
+ children: filteredIds.slice(row.index * COLUMNS, (row.index + 1) * COLUMNS).map((id_2, column) => {
93
+ const index_0 = row.index * COLUMNS + column;
94
+ return /* @__PURE__ */ jsx(Combobox.Item, {
95
+ value: id_2,
96
+ index: index_0,
97
+ "aria-colindex": column + 1,
98
+ onClick: () => onSelect(id_2),
99
+ title: id_2,
100
+ "aria-label": id_2,
101
+ className: "text-muted-foreground data-highlighted:bg-accent data-highlighted:text-accent-foreground data-selected:bg-accent data-selected:text-accent-foreground flex cursor-default items-center justify-center rounded-sm p-2 outline-none",
102
+ children: /* @__PURE__ */ jsx(IconSvg, {
103
+ iconId: id_2,
104
+ className: "size-5"
105
+ })
106
+ }, id_2);
107
+ })
108
+ }, row.key))
109
+ })
110
+ }), !filteredIds.length && /* @__PURE__ */ jsx("div", {
111
+ role: "status",
112
+ className: "py-6 text-center text-sm",
113
+ children: "No matching icons."
114
+ })]
115
+ })]
116
+ })
117
+ });
118
+ }
119
+ function IconFieldEditor(t0) {
120
+ const $ = c(25);
121
+ if ($[0] !== "06a7f09856913d7ee595c1cdc9745a723a0630fd9b9973c23b1dc93d15da4da5") {
122
+ for (let $i = 0; $i < 25; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
123
+ $[0] = "06a7f09856913d7ee595c1cdc9745a723a0630fd9b9973c23b1dc93d15da4da5";
124
+ }
125
+ const { value, ids, onChange } = t0;
126
+ const [open, setOpen] = useState(false);
127
+ let t1;
128
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
129
+ t1 = /* @__PURE__ */ jsx(Button, {
130
+ variant: "outline",
131
+ role: "combobox",
132
+ "aria-label": "Choose icon",
133
+ className: "w-full justify-between"
134
+ });
135
+ $[1] = t1;
136
+ } else t1 = $[1];
137
+ let t2;
138
+ if ($[2] !== value) {
139
+ t2 = /* @__PURE__ */ jsx(IconSvg, {
140
+ iconId: value,
141
+ className: "size-4 shrink-0"
142
+ });
143
+ $[2] = value;
144
+ $[3] = t2;
145
+ } else t2 = $[3];
146
+ let t3;
147
+ if ($[4] !== value) {
148
+ t3 = value.split(":")[1] ?? value;
149
+ $[4] = value;
150
+ $[5] = t3;
151
+ } else t3 = $[5];
152
+ let t4;
153
+ if ($[6] !== t3) {
154
+ t4 = /* @__PURE__ */ jsx("span", {
155
+ className: "truncate",
156
+ children: t3
157
+ });
158
+ $[6] = t3;
159
+ $[7] = t4;
160
+ } else t4 = $[7];
161
+ let t5;
162
+ if ($[8] !== t2 || $[9] !== t4) {
163
+ t5 = /* @__PURE__ */ jsxs("span", {
164
+ className: "flex min-w-0 items-center gap-2",
165
+ children: [t2, t4]
166
+ });
167
+ $[8] = t2;
168
+ $[9] = t4;
169
+ $[10] = t5;
170
+ } else t5 = $[10];
171
+ let t6;
172
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
173
+ t6 = /* @__PURE__ */ jsx(ChevronsUpDown, { className: "size-4 shrink-0 opacity-50" });
174
+ $[11] = t6;
175
+ } else t6 = $[11];
176
+ let t7;
177
+ if ($[12] !== t5) {
178
+ t7 = /* @__PURE__ */ jsxs(PopoverTrigger, {
179
+ render: t1,
180
+ children: [t5, t6]
181
+ });
182
+ $[12] = t5;
183
+ $[13] = t7;
184
+ } else t7 = $[13];
185
+ let t8;
186
+ if ($[14] !== ids || $[15] !== onChange || $[16] !== open || $[17] !== value) {
187
+ t8 = open && /* @__PURE__ */ jsx(IconPicker, {
188
+ value,
189
+ ids,
190
+ onSelect: (id) => {
191
+ onChange(id);
192
+ setOpen(false);
193
+ }
194
+ });
195
+ $[14] = ids;
196
+ $[15] = onChange;
197
+ $[16] = open;
198
+ $[17] = value;
199
+ $[18] = t8;
200
+ } else t8 = $[18];
201
+ let t9;
202
+ if ($[19] !== t8) {
203
+ t9 = /* @__PURE__ */ jsx(PopoverContent, {
204
+ align: "start",
205
+ side: "bottom",
206
+ className: "w-80 p-0",
207
+ children: t8
208
+ });
209
+ $[19] = t8;
210
+ $[20] = t9;
211
+ } else t9 = $[20];
212
+ let t10;
213
+ if ($[21] !== open || $[22] !== t7 || $[23] !== t9) {
214
+ t10 = /* @__PURE__ */ jsx("div", {
215
+ className: "flex flex-col",
216
+ children: /* @__PURE__ */ jsxs(Popover, {
217
+ open,
218
+ onOpenChange: setOpen,
219
+ children: [t7, t9]
220
+ })
221
+ });
222
+ $[21] = open;
223
+ $[22] = t7;
224
+ $[23] = t9;
225
+ $[24] = t10;
226
+ } else t10 = $[24];
227
+ return t10;
228
+ }
229
+
230
+ //#endregion
231
+ export { IconFieldEditor };
@@ -2,6 +2,7 @@ import { isFileMarker, isItemMarker, resolveFileMarker } from "../../../lib/norm
2
2
  import { lexicalStateToPlainText } from "../../../core/lib/lexicalState.js";
3
3
  import { previewStore } from "../previewStore.js";
4
4
  import { SidebarLexicalEditor } from "../../../core/components/lexical/SidebarLexicalEditor.js";
5
+ import { IconFieldEditor } from "./IconFieldEditor.js";
5
6
  import { RepeatableItemsList } from "./RepeatableItemsList.js";
6
7
  import { c } from "react/compiler-runtime";
7
8
  import * as React from "react";
@@ -35,9 +36,9 @@ const getSchemaFieldsInOrder = (schema) => {
35
36
  };
36
37
  const DrillRow = (t0) => {
37
38
  const $ = c(28);
38
- if ($[0] !== "b2eb497558ebaf4700b0ba067f5c7a528445a839255d88cef77056524cd2971c") {
39
+ if ($[0] !== "75fc5969a4033b113dd269f700cf2eca07d78852485b78d36d0f7631827b7b66") {
39
40
  for (let $i = 0; $i < 28; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
40
- $[0] = "b2eb497558ebaf4700b0ba067f5c7a528445a839255d88cef77056524cd2971c";
41
+ $[0] = "75fc5969a4033b113dd269f700cf2eca07d78852485b78d36d0f7631827b7b66";
41
42
  }
42
43
  const { label, preview, Icon, onClick, hover, postToIframe } = t0;
43
44
  let t1;
@@ -140,9 +141,9 @@ const DrillRow = (t0) => {
140
141
  };
141
142
  const ItemFieldsEditor = (t0) => {
142
143
  const $ = c(46);
143
- if ($[0] !== "b2eb497558ebaf4700b0ba067f5c7a528445a839255d88cef77056524cd2971c") {
144
+ if ($[0] !== "75fc5969a4033b113dd269f700cf2eca07d78852485b78d36d0f7631827b7b66") {
144
145
  for (let $i = 0; $i < 46; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
145
- $[0] = "b2eb497558ebaf4700b0ba067f5c7a528445a839255d88cef77056524cd2971c";
146
+ $[0] = "75fc5969a4033b113dd269f700cf2eca07d78852485b78d36d0f7631827b7b66";
146
147
  }
147
148
  const { selectedFieldName, schema, data, blockId, itemId, onFieldChange, postToIframe, filesMap, itemsMap, fieldIdPrefix } = t0;
148
149
  let t1;
@@ -314,7 +315,8 @@ const ItemFieldsEditor = (t0) => {
314
315
  "Embed",
315
316
  "Repeater",
316
317
  "Enum",
317
- "Boolean"
318
+ "Boolean",
319
+ "Icon"
318
320
  ].includes(field_0.fieldType)) {
319
321
  const value_0 = data[field_0.name];
320
322
  return /* @__PURE__ */ jsx(DrillRow, {
@@ -333,6 +335,11 @@ const ItemFieldsEditor = (t0) => {
333
335
  postToIframe
334
336
  }, field_0.name);
335
337
  }
338
+ if (field_0.fieldType === "Icon") return /* @__PURE__ */ jsx(IconFieldEditor, {
339
+ value: String(data[field_0.name] ?? schema?.properties?.[field_0.name]?.default ?? ""),
340
+ ids: field_0.enumValues ?? [],
341
+ onChange: (value_1) => onFieldChange(field_0.name, value_1)
342
+ }, field_0.name);
336
343
  if (field_0.fieldType === "Boolean") return /* @__PURE__ */ jsxs("div", {
337
344
  className: "flex items-center justify-between",
338
345
  children: [/* @__PURE__ */ jsx(Label, {
@@ -341,7 +348,7 @@ const ItemFieldsEditor = (t0) => {
341
348
  }), /* @__PURE__ */ jsx(Switch, {
342
349
  id: getFieldElementId(field_0.name),
343
350
  checked: Boolean(data[field_0.name]),
344
- onCheckedChange: (value_1) => onFieldChange(field_0.name, value_1)
351
+ onCheckedChange: (value_2) => onFieldChange(field_0.name, value_2)
345
352
  })]
346
353
  }, field_0.name);
347
354
  if (field_0.fieldType === "Enum") return /* @__PURE__ */ jsxs("div", {
@@ -351,14 +358,14 @@ const ItemFieldsEditor = (t0) => {
351
358
  children: label
352
359
  }), /* @__PURE__ */ jsxs(Select, {
353
360
  value: typeof data[field_0.name] === "string" ? data[field_0.name] : "",
354
- onValueChange: (value_2) => onFieldChange(field_0.name, value_2),
361
+ onValueChange: (value_3) => onFieldChange(field_0.name, value_3),
355
362
  children: [/* @__PURE__ */ jsx(SelectTrigger, {
356
363
  id: getFieldElementId(field_0.name),
357
364
  children: /* @__PURE__ */ jsx(SelectValue, {})
358
- }), /* @__PURE__ */ jsx(SelectContent, { children: field_0.enumValues?.map((value_3) => /* @__PURE__ */ jsx(SelectItem, {
359
- value: value_3,
360
- children: field_0.enumLabels?.[value_3] ?? value_3
361
- }, value_3)) })]
365
+ }), /* @__PURE__ */ jsx(SelectContent, { children: field_0.enumValues?.map((value_4) => /* @__PURE__ */ jsx(SelectItem, {
366
+ value: value_4,
367
+ children: field_0.enumLabels?.[value_4] ?? value_4
368
+ }, value_4)) })]
362
369
  })]
363
370
  }, field_0.name);
364
371
  if (field_0.fieldType === "String") return /* @__PURE__ */ jsx(form.Field, {
@@ -379,7 +386,7 @@ const ItemFieldsEditor = (t0) => {
379
386
  }), /* @__PURE__ */ jsx(SidebarLexicalEditor, {
380
387
  id: getFieldElementId(field_0.name),
381
388
  value: fieldApi_0.state.value,
382
- onChange: (value_4) => handleScalarChange(field_0.name, value_4, fieldApi_0),
389
+ onChange: (value_5) => handleScalarChange(field_0.name, value_5, fieldApi_0),
383
390
  onFocus: () => handleFieldFocus(field_0.name, field_0.fieldType),
384
391
  onBlur: () => handleFieldBlur(field_0.name)
385
392
  })]
@@ -425,8 +432,8 @@ const ItemFieldsEditor = (t0) => {
425
432
  }, field_0.name);
426
433
  }
427
434
  if (field_0.fieldType === "ImageList" || field_0.fieldType === "FileList") {
428
- const value_5 = data[field_0.name];
429
- const count = Array.isArray(value_5) ? value_5.length : 0;
435
+ const value_6 = data[field_0.name];
436
+ const count = Array.isArray(value_6) ? value_6.length : 0;
430
437
  const isImage = field_0.fieldType === "ImageList";
431
438
  const noun = isImage ? "image" : "file";
432
439
  let preview_1;