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.
- package/bin/camox.mjs +9 -1
- package/dist/core/components/lexical/{GradientNode.js → HighlightNode.js} +34 -34
- package/dist/core/components/lexical/InlineLexicalEditor.js +14 -14
- package/dist/core/components/lexical/InlineStylesPlugin.js +25 -9
- package/dist/core/components/lexical/SelectionBroadcaster.js +7 -7
- package/dist/core/components/lexical/SidebarLexicalEditor.js +24 -24
- package/dist/core/components/lexical/TextLinkPopover.js +191 -208
- package/dist/core/components/lexical/editorConfig.js +2 -2
- package/dist/core/createApp.d.ts +31 -4
- package/dist/core/createApp.js +2 -1
- package/dist/core/createBlock.js +24 -10
- package/dist/core/createLayout.d.ts +16 -3
- package/dist/core/createLayout.js +15 -15
- package/dist/core/derivedRoutes.js +1 -1
- package/dist/core/dom.d.ts +17 -0
- package/dist/core/dom.js +22 -0
- package/dist/core/editing/createEditableBlock.d.ts +135 -1
- package/dist/core/editing/createEditableBlock.js +209 -74
- package/dist/core/lib/contentType.d.ts +5 -0
- package/dist/core/lib/contentType.js +11 -0
- package/dist/core/lib/fieldTypes.js +1 -0
- package/dist/core/lib/iconTypes.d.ts +13 -0
- package/dist/core/lib/icons.d.ts +6 -0
- package/dist/core/lib/icons.js +130 -0
- package/dist/core/lib/lexicalReact.js +4 -4
- package/dist/core/lib/lexicalState.js +8 -8
- package/dist/core/lib/modifierFormats.js +2 -2
- package/dist/core/lib/textLinks.js +5 -2
- package/dist/core/lib/textStyles.d.ts +3 -3
- package/dist/core/lib/textStyles.js +9 -14
- package/dist/core/pageDestinations.js +37 -0
- package/dist/features/content/components/AssetCard.js +104 -68
- package/dist/features/og/imageResponse.node.js +11 -9
- package/dist/features/preview/CamoxPreview.js +148 -146
- package/dist/features/preview/commentsEnabled.js +2 -2
- package/dist/features/preview/components/AddBlockSidebar.js +1 -1
- package/dist/features/preview/components/AssetLightbox.js +17 -6
- package/dist/features/preview/components/AttachedComments.js +224 -87
- package/dist/features/preview/components/BlockActionsPopover.js +1 -1
- package/dist/features/preview/components/CommentTargetQuote.js +22 -21
- package/dist/features/preview/components/CreatePageModal.js +4 -4
- package/dist/features/preview/components/DerivedLayoutDialog.js +36 -21
- package/dist/features/preview/components/DerivedLayoutSidebar.js +45 -26
- package/dist/features/preview/components/DerivedPageInfoSidebar.js +38 -26
- package/dist/features/preview/components/FieldOverlayStyles.js +29 -9
- package/dist/features/preview/components/FieldToolbar.js +12 -12
- package/dist/features/preview/components/IconFieldEditor.js +231 -0
- package/dist/features/preview/components/ItemFieldsEditor.js +21 -14
- package/dist/features/preview/components/LinkFieldEditor.js +212 -209
- package/dist/features/preview/components/OverlayTracker.js +1 -1
- package/dist/features/preview/components/PageEditorSidebar.js +1 -1
- package/dist/features/preview/components/PageInfoSidebar.js +28 -28
- package/dist/features/preview/components/PagePicker.js +46 -46
- package/dist/features/preview/components/PageTree.js +1 -1
- package/dist/features/preview/components/PreviewPanel.js +1 -1
- package/dist/features/preview/components/PreviewToolbar.js +224 -225
- package/dist/features/preview/components/PublicationRow.js +8 -4
- package/dist/features/preview/components/SendFeedbackDialog.js +83 -0
- package/dist/features/preview/components/useRepeatableItemActions.js +1 -1
- package/dist/features/preview/overlayHighlights.js +54 -0
- package/dist/features/preview/previewCommentsStore.js +54 -34
- package/dist/features/preview/previewSelection.js +28 -23
- package/dist/features/preview/publication.js +10 -0
- package/dist/features/preview/usePageComments.js +39 -0
- package/dist/features/provider/CoreCamoxProvider.js +38 -6
- package/dist/features/provider/LocalhostPreviewProvider.js +81 -45
- package/dist/features/provider/components/CommandPalette.js +35 -84
- package/dist/features/runtime/pageApp.js +32 -28
- package/dist/features/runtime/pageServer.js +4 -1
- package/dist/features/runtime/runtime.d.ts +2 -0
- package/dist/features/runtime/runtime.js +45 -21
- package/dist/features/studio/components/EnvironmentMenu.js +76 -63
- package/dist/features/studio/components/Navbar.js +53 -80
- package/dist/features/vite/auth.js +1 -50
- package/dist/features/vite/iconGeneration.js +16 -0
- package/dist/features/vite/layoutGeneration.js +7 -3
- package/dist/features/vite/vite.d.ts +4 -2
- package/dist/features/vite/vite.js +24 -3
- package/dist/hooks/use-page-destinations.js +53 -0
- package/dist/lib/auth.js +40 -20
- package/dist/lib/preview-handoff.js +13 -0
- package/dist/lib/queries.js +12 -1
- package/dist/lib/server-auth-cookie.js +21 -0
- package/dist/lib/use-project-room.js +5 -2
- package/dist/studio-overlays.css +19 -15
- package/dist/studio.css +1 -1
- package/package.json +9 -4
- package/skills/camox/SKILL.md +38 -9
- package/skills/camox/references/block-definitions.md +107 -286
- package/skills/camox/references/cli-common.md +16 -4
- package/skills/camox/references/cli-content.md +158 -0
- package/skills/camox/references/cli-environments.md +1 -1
- package/skills/camox/references/dom-integrations.md +93 -0
- package/skills/camox/references/field-styling.md +50 -0
- package/skills/camox/references/layout-definitions.md +33 -147
- package/skills/camox/references/routed-layouts.md +71 -0
- package/skills/camoxify/SKILL.md +66 -0
- package/skills/camox/references/cli-blocks.md +0 -78
- 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(
|
|
20
|
-
if ($[0] !== "
|
|
21
|
-
for (let $i = 0; $i <
|
|
22
|
-
$[0] = "
|
|
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)
|
|
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
|
|
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
|
-
|
|
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 ($[
|
|
142
|
-
t13 = /* @__PURE__ */
|
|
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,
|
|
162
|
+
children: [t11, t16]
|
|
145
163
|
});
|
|
146
|
-
$[
|
|
147
|
-
$[
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
$[
|
|
154
|
-
$[
|
|
155
|
-
|
|
156
|
-
|
|
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(
|
|
9
|
-
if ($[0] !== "
|
|
10
|
-
for (let $i = 0; $i <
|
|
11
|
-
$[0] = "
|
|
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
|
|
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
|
-
|
|
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 ($[
|
|
38
|
-
t4 = /* @__PURE__ */
|
|
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: [
|
|
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
|
-
$[
|
|
51
|
-
$[
|
|
52
|
-
|
|
53
|
-
|
|
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(
|
|
8
|
-
if ($[0] !== "
|
|
9
|
-
for (let $i = 0; $i <
|
|
10
|
-
$[0] = "
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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 {
|
|
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: "
|
|
36
|
-
flag: FORMAT_FLAGS.
|
|
37
|
-
icon:
|
|
38
|
-
label: "
|
|
39
|
-
shortcut:
|
|
35
|
+
key: "strikethrough",
|
|
36
|
+
flag: FORMAT_FLAGS.strikethrough,
|
|
37
|
+
icon: Strikethrough,
|
|
38
|
+
label: "Strikethrough",
|
|
39
|
+
shortcut: null
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
|
-
key: "
|
|
43
|
-
flag: FORMAT_FLAGS.
|
|
44
|
-
icon:
|
|
45
|
-
label: "
|
|
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] !== "
|
|
51
|
+
if ($[0] !== "d1e889a3597708ac2bc6872804f1131756eb2e3aa358ca08ef83b3491906d96a") {
|
|
52
52
|
for (let $i = 0; $i < 28; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
53
|
-
$[0] = "
|
|
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] !== "
|
|
39
|
+
if ($[0] !== "75fc5969a4033b113dd269f700cf2eca07d78852485b78d36d0f7631827b7b66") {
|
|
39
40
|
for (let $i = 0; $i < 28; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
40
|
-
$[0] = "
|
|
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] !== "
|
|
144
|
+
if ($[0] !== "75fc5969a4033b113dd269f700cf2eca07d78852485b78d36d0f7631827b7b66") {
|
|
144
145
|
for (let $i = 0; $i < 46; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
145
|
-
$[0] = "
|
|
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: (
|
|
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: (
|
|
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((
|
|
359
|
-
value:
|
|
360
|
-
children: field_0.enumLabels?.[
|
|
361
|
-
},
|
|
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: (
|
|
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
|
|
429
|
-
const count = Array.isArray(
|
|
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;
|