slice-machine-ui 2.2.2-beta.1 → 2.2.2-beta.11
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/next.config.mjs +11 -1
- package/out/404.html +1 -1
- package/out/_next/static/chunks/18539003-7b839478e0b5720a.js +22 -0
- package/out/_next/static/chunks/{66-d37d30551288858b.js → 210-565d01ee9777d1a1.js} +2 -2
- package/out/_next/static/chunks/{212-cbaa35389c0aacf1.js → 212-b6a2b8d9d16ef3c5.js} +1 -1
- package/out/_next/static/chunks/448-a0de8b21d55d4da3.js +1 -0
- package/out/_next/static/chunks/{465-47a6d2a5f66f521e.js → 465-d5dd75edd8e6bb65.js} +1 -1
- package/out/_next/static/chunks/574-319271e279f042bc.js +1 -0
- package/out/_next/static/chunks/59b4e022-8e544a511d670317.js +1 -0
- package/out/_next/static/chunks/695-603bd96af31f4302.js +12 -0
- package/out/_next/static/chunks/{816-68d4db26c0adab2e.js → 816-17afd84d2642f4c4.js} +1 -1
- package/out/_next/static/chunks/f36c6662-1f3a854183168b10.js +1 -0
- package/out/_next/static/chunks/pages/_app-f7a7229e62fc765c.js +544 -0
- package/out/_next/static/chunks/pages/{changelog-d309ea186a0e56bf.js → changelog-1d15a7ef498f499a.js} +1 -1
- package/out/_next/static/chunks/pages/{changes-1bb1a7b784a22151.js → changes-0af2a1a5244418f9.js} +1 -1
- package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-74be2c0ac9c854c7.js → [customTypeId]-a6ff1618238b3510.js} +1 -1
- package/out/_next/static/chunks/pages/{index-785a0ab6e2a4fc27.js → index-2610e550d79c5bb1.js} +1 -1
- package/out/_next/static/chunks/pages/{labs-2e4f3a5f68e65b93.js → labs-240ba57bfdabe998.js} +1 -1
- package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-d35c87b9aaec445a.js → [pageTypeId]-c300f963db847451.js} +1 -1
- package/out/_next/static/chunks/pages/{settings-25eb02893ed871b7.js → settings-039476a9a63d25a1.js} +1 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/{simulator-b47a72d5e94bd946.js → simulator-cfc19e3e799745bb.js} +1 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-58e6cb0f278ea03c.js +1 -0
- package/out/_next/static/chunks/pages/{slices-cc44eeccd58d23a9.js → slices-9894ce968d74baf6.js} +1 -1
- package/out/_next/static/css/82c8c4f05b25d3af.css +1 -0
- package/out/_next/static/lnoCw12ueMqf698VD8pfN/_buildManifest.js +1 -0
- package/out/changelog.html +1 -1
- package/out/changes.html +1 -1
- package/out/custom-types/[customTypeId].html +1 -1
- package/out/custom-types.html +1 -1
- package/out/index.html +1 -1
- package/out/labs.html +1 -1
- package/out/page-types/[pageTypeId].html +1 -1
- package/out/settings.html +1 -1
- package/out/slices/[lib]/[sliceName]/[variation]/simulator.html +1 -1
- package/out/slices/[lib]/[sliceName]/[variation].html +1 -1
- package/out/slices.html +1 -1
- package/package.json +11 -10
- package/src/domain/fields.ts +223 -0
- package/src/features/builder/AddFieldDropdown.tsx +119 -0
- package/src/features/onboarding/OnboardingGuide.tsx +45 -0
- package/src/features/onboarding/OnboardingProgressStepper.tsx +71 -0
- package/src/features/onboarding/OnboardingProvider.tsx +82 -0
- package/src/features/onboarding/OnboardingStepDialog/OnboardingStepDialog.tsx +46 -0
- package/src/features/onboarding/OnboardingStepDialog/OnboardingStepDialogContent.tsx +38 -0
- package/src/features/onboarding/OnboardingStepDialog/index.ts +1 -0
- package/src/features/onboarding/content.tsx +115 -0
- package/src/features/onboarding/types.ts +32 -0
- package/src/features/onboarding/useOnboardingExperiment.ts +6 -0
- package/src/hooks/useNestedGroupExperiment.ts +8 -0
- package/src/hooks/usePersistedState.ts +20 -3
- package/src/legacy/components/ListItem/index.tsx +1 -1
- package/src/legacy/components/Navigation/index.tsx +2 -0
- package/src/legacy/lib/builders/CustomTypeBuilder/TabZone/index.tsx +22 -4
- package/src/legacy/lib/builders/SliceBuilder/FieldZones/index.tsx +23 -8
- package/src/legacy/lib/builders/SliceBuilder/VariationsList/index.tsx +5 -2
- package/src/legacy/lib/builders/SliceBuilder/index.tsx +1 -1
- package/src/legacy/lib/builders/common/EditModal/index.jsx +1 -1
- package/src/legacy/lib/builders/common/Zone/Card/components/Hints/index.tsx +8 -1
- package/src/legacy/lib/builders/common/Zone/Card/components/NewField.tsx +1 -1
- package/src/legacy/lib/builders/common/Zone/Card/index.jsx +3 -1
- package/src/legacy/lib/builders/common/Zone/components/ZoneEmptyState/ZoneEmptyState.tsx +4 -13
- package/src/legacy/lib/builders/common/Zone/index.jsx +26 -31
- package/src/legacy/lib/builders/utils/index.ts +8 -0
- package/src/legacy/lib/models/common/Group.ts +51 -28
- package/src/legacy/lib/models/common/widgets/Boolean/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/Color/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/ContentRelationship/index.ts +0 -2
- package/src/legacy/lib/models/common/widgets/Date/index.ts +0 -2
- package/src/legacy/lib/models/common/widgets/Embed/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/GeoPoint/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/Group/ListItem/index.jsx +46 -26
- package/src/legacy/lib/models/common/widgets/Group/createGroupWidget.ts +81 -0
- package/src/legacy/lib/models/common/widgets/Group/index.tsx +72 -0
- package/src/legacy/lib/models/common/widgets/Image/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/Link/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/LinkToMedia/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/NestedGroup/index.tsx +40 -0
- package/src/legacy/lib/models/common/widgets/Number/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/Select/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/StructuredText/index.ts +0 -2
- package/src/legacy/lib/models/common/widgets/Text/index.ts +0 -2
- package/src/legacy/lib/models/common/widgets/Timestamp/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/UID/index.ts +2 -4
- package/src/legacy/lib/models/common/widgets/Widget.ts +10 -3
- package/src/legacy/lib/models/common/widgets/groupWidgets.ts +7 -0
- package/src/legacy/lib/models/common/widgets/index.ts +7 -31
- package/src/legacy/lib/models/common/widgets/nonGroupWidgets.ts +33 -0
- package/test/lib/builders/buildersUtils.test.ts +1 -1
- package/test/lib/models/common/widgets/index.test.ts +1 -1
- package/tsconfig.json +0 -1
- package/out/_next/static/JGphUg6eFq0-W11Pa7cMU/_buildManifest.js +0 -1
- package/out/_next/static/chunks/18539003-eda642ad962ef598.js +0 -22
- package/out/_next/static/chunks/264-4bb6f3fb14863ef3.js +0 -1
- package/out/_next/static/chunks/574-6039c48fbc93b4a8.js +0 -1
- package/out/_next/static/chunks/59b4e022-7a3b5554b806349f.js +0 -1
- package/out/_next/static/chunks/756-1e44fe84bedc262b.js +0 -10
- package/out/_next/static/chunks/f36c6662-03bb5e9d9aa0b0aa.js +0 -1
- package/out/_next/static/chunks/pages/_app-05ac13d573829b68.js +0 -532
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-996e20b9b295a912.js +0 -1
- package/out/_next/static/css/b3bb731ce567d63f.css +0 -1
- package/src/legacy/lib/builders/common/SelectFieldTypeModal/FieldTypeCard.jsx +0 -51
- package/src/legacy/lib/builders/common/SelectFieldTypeModal/index.jsx +0 -84
- package/src/legacy/lib/models/common/widgets/Group/index.ts +0 -44
- package/src/legacy/lib/models/common/widgets/ctBuilderArray.ts +0 -20
- package/src/legacy/lib/models/common/widgets/groupBuilderArray.ts +0 -18
- package/src/legacy/lib/models/common/widgets/sliceBuilderArray.ts +0 -19
- package/src/legacy/lib/models/common/widgets/withGroup.ts +0 -2
- /package/out/_next/static/{JGphUg6eFq0-W11Pa7cMU → lnoCw12ueMqf698VD8pfN}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Dialog,
|
|
3
|
+
DialogActions,
|
|
4
|
+
DialogContent,
|
|
5
|
+
DialogHeader,
|
|
6
|
+
} from "@prismicio/editor-ui";
|
|
7
|
+
|
|
8
|
+
import { useOnboardingContext } from "@/features/onboarding/OnboardingProvider";
|
|
9
|
+
import { OnboardingStepDialogContent } from "@/features/onboarding/OnboardingStepDialog/OnboardingStepDialogContent";
|
|
10
|
+
import type { OnboardingStep } from "@/features/onboarding/types";
|
|
11
|
+
|
|
12
|
+
type OnboardingStepDialogProps = {
|
|
13
|
+
step: OnboardingStep;
|
|
14
|
+
isOpen: boolean;
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const OnboardingStepDialog = ({
|
|
19
|
+
step,
|
|
20
|
+
isOpen,
|
|
21
|
+
onClose,
|
|
22
|
+
}: OnboardingStepDialogProps) => {
|
|
23
|
+
const { toggleStepComplete, isStepComplete } = useOnboardingContext();
|
|
24
|
+
|
|
25
|
+
const markAsDone = () => {
|
|
26
|
+
if (!isOpen) return;
|
|
27
|
+
toggleStepComplete(step.id);
|
|
28
|
+
onClose();
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Dialog open={isOpen} onOpenChange={onClose}>
|
|
33
|
+
<DialogHeader title="Learn" />
|
|
34
|
+
<DialogContent>
|
|
35
|
+
<OnboardingStepDialogContent step={step} />
|
|
36
|
+
<DialogActions
|
|
37
|
+
ok={{
|
|
38
|
+
text: isStepComplete(step.id) ? "Undo step" : "Mark as done",
|
|
39
|
+
onClick: markAsDone,
|
|
40
|
+
}}
|
|
41
|
+
cancel={{ text: "Close" }}
|
|
42
|
+
/>
|
|
43
|
+
</DialogContent>
|
|
44
|
+
</Dialog>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Box, ScrollArea, Text, Video } from "@prismicio/editor-ui";
|
|
2
|
+
|
|
3
|
+
import { getOnboardingStepsContent } from "@/features/onboarding/content";
|
|
4
|
+
import { useOnboardingContext } from "@/features/onboarding/OnboardingProvider";
|
|
5
|
+
import { OnboardingStep } from "@/features/onboarding/types";
|
|
6
|
+
import { useRepositoryInformation } from "@/hooks/useRepositoryInformation";
|
|
7
|
+
|
|
8
|
+
type OnboardingStepDialogContentProps = {
|
|
9
|
+
step: OnboardingStep;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const OnboardingStepDialogContent = ({
|
|
13
|
+
step,
|
|
14
|
+
}: OnboardingStepDialogContentProps) => {
|
|
15
|
+
const { getStepIndex } = useOnboardingContext();
|
|
16
|
+
const { repositoryUrl } = useRepositoryInformation();
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
content: Content,
|
|
20
|
+
videoUrl,
|
|
21
|
+
title,
|
|
22
|
+
} = getOnboardingStepsContent({ repositoryUrl })[step.id];
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ScrollArea>
|
|
26
|
+
<Box as="article" flexDirection="column" padding={16} gap={16}>
|
|
27
|
+
<section>
|
|
28
|
+
<Text sx={{ marginBottom: 4 }} color="purple9" variant="bold">
|
|
29
|
+
Step {getStepIndex(step.id) + 1}
|
|
30
|
+
</Text>
|
|
31
|
+
<Text variant="h3">{title}</Text>
|
|
32
|
+
<Content />
|
|
33
|
+
</section>
|
|
34
|
+
<Video src={videoUrl} sizing="contain" autoPlay loop />
|
|
35
|
+
</Box>
|
|
36
|
+
</ScrollArea>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { OnboardingStepDialog } from "./OnboardingStepDialog";
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Text } from "@prismicio/editor-ui";
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
OnboardingStep,
|
|
5
|
+
OnboardingStepContentDefinition,
|
|
6
|
+
OnboardingStepType,
|
|
7
|
+
} from "@/features/onboarding/types";
|
|
8
|
+
|
|
9
|
+
export const onboardingSteps: OnboardingStep[] = [
|
|
10
|
+
{
|
|
11
|
+
id: "createPage",
|
|
12
|
+
title: "Create Your Page",
|
|
13
|
+
description: "Setup a new page.",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "codePage",
|
|
17
|
+
title: "Code your page",
|
|
18
|
+
description: "Build your page's structure",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "addSlice",
|
|
22
|
+
title: "Add a Slice",
|
|
23
|
+
description: "Insert reusable sections.",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "pushModels",
|
|
27
|
+
title: "Push Your Models",
|
|
28
|
+
description: "Deploy your models.",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "writeContent",
|
|
32
|
+
title: "Write Content",
|
|
33
|
+
description: "Add engaging content.",
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
type GetOnboardingStepsContentProps = {
|
|
38
|
+
repositoryUrl: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const getOnboardingStepsContent = ({
|
|
42
|
+
repositoryUrl,
|
|
43
|
+
}: GetOnboardingStepsContentProps): Record<
|
|
44
|
+
OnboardingStepType,
|
|
45
|
+
OnboardingStepContentDefinition
|
|
46
|
+
> => ({
|
|
47
|
+
createPage: {
|
|
48
|
+
videoUrl:
|
|
49
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/ADD_SLICE.mp4",
|
|
50
|
+
content: () => (
|
|
51
|
+
<Text>
|
|
52
|
+
Commodo irure ipsum exercitation consequat enim velit amet commodo.
|
|
53
|
+
Excepteur proident Lorem sunt enim amet tempor qui Lorem non non Lorem.
|
|
54
|
+
Ex sint elit ea. Proident veniam dolor cupidatat amet aute consectetur.
|
|
55
|
+
Non ad consectetur irure adipisicing aliquip. Ipsum nulla velit mollit
|
|
56
|
+
magna aliqua eu veniam. Commodo elit labore veniam nulla dolor aliqua
|
|
57
|
+
esse proident pariatur nostrud.
|
|
58
|
+
</Text>
|
|
59
|
+
),
|
|
60
|
+
},
|
|
61
|
+
codePage: {
|
|
62
|
+
videoUrl:
|
|
63
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/CODE_SNIP.mp4",
|
|
64
|
+
content: () => (
|
|
65
|
+
<Text>
|
|
66
|
+
Nulla consequat occaecat ut ut ex culpa veniam sunt nisi nisi. Velit
|
|
67
|
+
excepteur excepteur do anim incididunt in cillum ullamco occaecat minim
|
|
68
|
+
reprehenderit eu enim. Nulla irure est fugiat aliqua elit excepteur
|
|
69
|
+
labore ipsum occaecat eu minim duis non sit. Ea eu irure dolore duis
|
|
70
|
+
labore ad. Quis sunt eu commodo sit nisi ullamco qui aliqua nostrud
|
|
71
|
+
labore nostrud ut nostrud nostrud.
|
|
72
|
+
</Text>
|
|
73
|
+
),
|
|
74
|
+
},
|
|
75
|
+
addSlice: {
|
|
76
|
+
videoUrl:
|
|
77
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/PUSH.mp4",
|
|
78
|
+
content: () => (
|
|
79
|
+
<Text>
|
|
80
|
+
Minim anim velit laboris cupidatat cupidatat culpa labore sunt eiusmod.
|
|
81
|
+
Consequat culpa mollit enim dolore aliquip ex voluptate ex eiusmod
|
|
82
|
+
incididunt eu. Cillum magna cillum magna consectetur. Id aliquip
|
|
83
|
+
excepteur adipisicing officia excepteur et pariatur aliquip aliquip
|
|
84
|
+
laborum.
|
|
85
|
+
</Text>
|
|
86
|
+
),
|
|
87
|
+
},
|
|
88
|
+
pushModels: {
|
|
89
|
+
videoUrl:
|
|
90
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/PREVIEW.mp4",
|
|
91
|
+
content: () => (
|
|
92
|
+
<Text>
|
|
93
|
+
Ipsum aliqua do consequat eiusmod id. Reprehenderit consectetur sit
|
|
94
|
+
officia consequat velit non officia aliquip laboris incididunt cillum
|
|
95
|
+
proident incididunt. Ad quis laborum tempor dolor duis ea cillum aliqua
|
|
96
|
+
occaecat. Sunt reprehenderit fugiat et ullamco proident pariatur
|
|
97
|
+
deserunt minim. Irure enim nulla et ad ut id anim elit. Voluptate culpa
|
|
98
|
+
esse qui et reprehenderit aute est.
|
|
99
|
+
</Text>
|
|
100
|
+
),
|
|
101
|
+
},
|
|
102
|
+
writeContent: {
|
|
103
|
+
videoUrl:
|
|
104
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/WRITE.mp4",
|
|
105
|
+
content: () => (
|
|
106
|
+
<Text>
|
|
107
|
+
Open your{" "}
|
|
108
|
+
<Text href={repositoryUrl} underline>
|
|
109
|
+
Page Builder
|
|
110
|
+
</Text>
|
|
111
|
+
, create a page, add slices, save, and publish. Then, come back here.
|
|
112
|
+
</Text>
|
|
113
|
+
),
|
|
114
|
+
},
|
|
115
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const onboardingStepStatusesSchema = z.object({
|
|
4
|
+
createPage: z.boolean(),
|
|
5
|
+
codePage: z.boolean(),
|
|
6
|
+
addSlice: z.boolean(),
|
|
7
|
+
writeContent: z.boolean(),
|
|
8
|
+
pushModels: z.boolean(),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export type OnboardingStepStatuses = z.infer<
|
|
12
|
+
typeof onboardingStepStatusesSchema
|
|
13
|
+
>;
|
|
14
|
+
|
|
15
|
+
export type OnboardingStepType = keyof OnboardingStepStatuses;
|
|
16
|
+
|
|
17
|
+
export type OnboardingStep = {
|
|
18
|
+
id: OnboardingStepType;
|
|
19
|
+
title: string;
|
|
20
|
+
description: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type OnboardingStepContentDefinition = {
|
|
24
|
+
title?: string;
|
|
25
|
+
content: () => JSX.Element;
|
|
26
|
+
videoUrl: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type OnboardingStepContent = Record<
|
|
30
|
+
OnboardingStepType,
|
|
31
|
+
OnboardingStepContentDefinition
|
|
32
|
+
>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useExperimentVariant } from "@/hooks/useExperimentVariant";
|
|
2
|
+
|
|
3
|
+
type UseNestedGroupExperimentReturnType = { eligible: boolean };
|
|
4
|
+
|
|
5
|
+
export function useNestedGroupExperiment(): UseNestedGroupExperimentReturnType {
|
|
6
|
+
const variant = useExperimentVariant("slicemachine-nested-groups");
|
|
7
|
+
return { eligible: variant?.value === "on" };
|
|
8
|
+
}
|
|
@@ -1,20 +1,37 @@
|
|
|
1
1
|
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
|
2
|
+
import { ZodType, ZodTypeDef } from "zod";
|
|
2
3
|
|
|
3
4
|
type PersistedState<T> = [T, Dispatch<SetStateAction<T>>];
|
|
4
5
|
|
|
5
6
|
const SLICE_MACHINE_STORAGE_PREFIX = "slice-machine";
|
|
6
7
|
|
|
8
|
+
type UsePersistedStateOptions<T> = {
|
|
9
|
+
schema?: ZodType<T, ZodTypeDef, unknown>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function usePersistedState<T>(
|
|
13
|
+
key: string,
|
|
14
|
+
): PersistedState<T | undefined>;
|
|
7
15
|
export function usePersistedState<T>(
|
|
8
16
|
key: string,
|
|
9
17
|
defaultValue: T,
|
|
10
|
-
|
|
18
|
+
options?: UsePersistedStateOptions<T>,
|
|
19
|
+
): PersistedState<T>;
|
|
20
|
+
export function usePersistedState<T>(
|
|
21
|
+
key: string,
|
|
22
|
+
defaultValue?: T,
|
|
23
|
+
options?: UsePersistedStateOptions<T>,
|
|
24
|
+
): PersistedState<T | undefined> {
|
|
25
|
+
const { schema } = options ?? {};
|
|
11
26
|
const computedKey = `${SLICE_MACHINE_STORAGE_PREFIX}_${key}`;
|
|
12
27
|
|
|
13
|
-
const [value, setValue] = useState<T>(() => {
|
|
28
|
+
const [value, setValue] = useState<T | undefined>(() => {
|
|
14
29
|
try {
|
|
15
30
|
const value = localStorage.getItem(computedKey);
|
|
16
31
|
|
|
17
|
-
|
|
32
|
+
if (value == null) return defaultValue;
|
|
33
|
+
if (!schema) return JSON.parse(value) as T;
|
|
34
|
+
return schema.parse(JSON.parse(value));
|
|
18
35
|
} catch (error) {
|
|
19
36
|
console.warn(`Error reading localStorage key “${computedKey}”:`, error);
|
|
20
37
|
|
|
@@ -14,7 +14,7 @@ import Li from "../Li";
|
|
|
14
14
|
import SliceMachineIconButton from "../SliceMachineIconButton";
|
|
15
15
|
import ItemHeader from "./Header";
|
|
16
16
|
|
|
17
|
-
type Item<F extends TabField> = { key: string; value: F };
|
|
17
|
+
export type Item<F extends TabField> = { key: string; value: F };
|
|
18
18
|
|
|
19
19
|
interface ListItemProps<F extends TabField, S extends AnyObjectSchema> {
|
|
20
20
|
item: Item<F>;
|
|
@@ -17,6 +17,7 @@ import { ErrorBoundary } from "@/ErrorBoundary";
|
|
|
17
17
|
import { CUSTOM_TYPES_CONFIG } from "@/features/customTypes/customTypesConfig";
|
|
18
18
|
import { CUSTOM_TYPES_MESSAGES } from "@/features/customTypes/customTypesMessages";
|
|
19
19
|
import { MasterSliceLibraryPreviewModal } from "@/features/masterSliceLibrary/SliceLibraryPreviewModal";
|
|
20
|
+
import { OnboardingGuide } from "@/features/onboarding/OnboardingGuide";
|
|
20
21
|
import { useGitIntegrationExperiment } from "@/features/settings/git/useGitIntegrationExperiment";
|
|
21
22
|
import { useMarketingContent } from "@/hooks/useMarketingContent";
|
|
22
23
|
import { useRepositoryInformation } from "@/hooks/useRepositoryInformation";
|
|
@@ -123,6 +124,7 @@ const Navigation: FC = () => {
|
|
|
123
124
|
</ErrorBoundary>
|
|
124
125
|
|
|
125
126
|
<SideNavList position="bottom">
|
|
127
|
+
<OnboardingGuide />
|
|
126
128
|
{masterSliceLibrary !== undefined && (
|
|
127
129
|
<SideNavListItem>
|
|
128
130
|
<MasterSliceLibraryPreviewModal
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
TabFieldsModel,
|
|
31
31
|
TabSM,
|
|
32
32
|
} from "@/legacy/lib/models/common/CustomType";
|
|
33
|
-
import
|
|
33
|
+
import { Widgets } from "@/legacy/lib/models/common/widgets";
|
|
34
34
|
import type { AnyWidget } from "@/legacy/lib/models/common/widgets/Widget";
|
|
35
35
|
import {
|
|
36
36
|
ensureDnDDestination,
|
|
@@ -39,11 +39,30 @@ import {
|
|
|
39
39
|
import { transformKeyAccessor } from "@/legacy/lib/utils/str";
|
|
40
40
|
import { getContentTypeForTracking } from "@/utils/getContentTypeForTracking";
|
|
41
41
|
|
|
42
|
-
import * as Widgets from "../../../../lib/models/common/widgets/withGroup";
|
|
43
42
|
import EditModal from "../../common/EditModal";
|
|
44
43
|
import Zone from "../../common/Zone";
|
|
45
44
|
import SliceZone from "../SliceZone";
|
|
46
45
|
|
|
46
|
+
const widgetsArray = [
|
|
47
|
+
Widgets.UID,
|
|
48
|
+
Widgets.Image,
|
|
49
|
+
Widgets.Text,
|
|
50
|
+
Widgets.StructuredText,
|
|
51
|
+
Widgets.Link,
|
|
52
|
+
Widgets.Select,
|
|
53
|
+
Widgets.Boolean,
|
|
54
|
+
Widgets.Number,
|
|
55
|
+
Widgets.Color,
|
|
56
|
+
Widgets.Date,
|
|
57
|
+
Widgets.Embed,
|
|
58
|
+
Widgets.Timestamp,
|
|
59
|
+
Widgets.GeoPoint,
|
|
60
|
+
Widgets.ContentRelationship,
|
|
61
|
+
Widgets.LinkToMedia,
|
|
62
|
+
Widgets.Group,
|
|
63
|
+
Widgets.NestedGroup,
|
|
64
|
+
];
|
|
65
|
+
|
|
47
66
|
interface TabZoneProps {
|
|
48
67
|
tabId: string;
|
|
49
68
|
}
|
|
@@ -227,7 +246,7 @@ const TabZone: FC<TabZoneProps> = ({ tabId }) => {
|
|
|
227
246
|
poolOfFieldsToCheck={poolOfFields}
|
|
228
247
|
showHints={true}
|
|
229
248
|
EditModal={EditModal}
|
|
230
|
-
widgetsArray={
|
|
249
|
+
widgetsArray={widgetsArray}
|
|
231
250
|
onDeleteItem={onDeleteItem}
|
|
232
251
|
onSave={onSave}
|
|
233
252
|
onSaveNewField={onSaveNewField}
|
|
@@ -242,7 +261,6 @@ const TabZone: FC<TabZoneProps> = ({ tabId }) => {
|
|
|
242
261
|
}
|
|
243
262
|
testId="static-zone-content"
|
|
244
263
|
isRepeatableCustomType={customType.repeatable}
|
|
245
|
-
emptyStateActionTestId="add-Static-field"
|
|
246
264
|
/>
|
|
247
265
|
) : undefined}
|
|
248
266
|
|
|
@@ -27,9 +27,7 @@ import {
|
|
|
27
27
|
SlicePrimaryFieldSM,
|
|
28
28
|
WidgetsArea,
|
|
29
29
|
} from "@/legacy/lib/models/common/Slice";
|
|
30
|
-
import
|
|
31
|
-
import groupBuilderWidgetsArray from "@/legacy/lib/models/common/widgets/groupBuilderArray";
|
|
32
|
-
import sliceBuilderWidgetsArray from "@/legacy/lib/models/common/widgets/sliceBuilderArray";
|
|
30
|
+
import { Widgets } from "@/legacy/lib/models/common/widgets";
|
|
33
31
|
import { ensureDnDDestination } from "@/legacy/lib/utils";
|
|
34
32
|
import { transformKeyAccessor } from "@/legacy/lib/utils/str";
|
|
35
33
|
import { getContentTypeForTracking } from "@/utils/getContentTypeForTracking";
|
|
@@ -42,6 +40,25 @@ const dataTipText2 = `The repeatable zone is for a group<br/>
|
|
|
42
40
|
of fields that you want to be able to repeat an<br/>
|
|
43
41
|
indeterminate number of times, like FAQs`;
|
|
44
42
|
|
|
43
|
+
const itemsWidgetsArray = [
|
|
44
|
+
Widgets.Image,
|
|
45
|
+
Widgets.Text,
|
|
46
|
+
Widgets.StructuredText,
|
|
47
|
+
Widgets.Link,
|
|
48
|
+
Widgets.Select,
|
|
49
|
+
Widgets.Boolean,
|
|
50
|
+
Widgets.Number,
|
|
51
|
+
Widgets.Color,
|
|
52
|
+
Widgets.Date,
|
|
53
|
+
Widgets.Embed,
|
|
54
|
+
Widgets.Timestamp,
|
|
55
|
+
Widgets.GeoPoint,
|
|
56
|
+
Widgets.ContentRelationship,
|
|
57
|
+
Widgets.LinkToMedia,
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const primaryWidgetsArray = [Widgets.Group, ...itemsWidgetsArray];
|
|
61
|
+
|
|
45
62
|
const FieldZones: FC = () => {
|
|
46
63
|
const { slice, setSlice, variation } = useSliceState();
|
|
47
64
|
const [
|
|
@@ -110,7 +127,7 @@ const FieldZones: FC = () => {
|
|
|
110
127
|
label: string;
|
|
111
128
|
widgetTypeName: keyof typeof Widgets;
|
|
112
129
|
}) => {
|
|
113
|
-
const widget =
|
|
130
|
+
const widget = primaryWidgetsArray.find(
|
|
114
131
|
(sliceBuilderWidget) =>
|
|
115
132
|
sliceBuilderWidget.CUSTOM_NAME === widgetTypeName ||
|
|
116
133
|
sliceBuilderWidget.TYPE_NAME === widgetTypeName,
|
|
@@ -188,7 +205,7 @@ const FieldZones: FC = () => {
|
|
|
188
205
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
189
206
|
fields={variation.primary}
|
|
190
207
|
EditModal={EditModal}
|
|
191
|
-
widgetsArray={
|
|
208
|
+
widgetsArray={primaryWidgetsArray}
|
|
192
209
|
onDeleteItem={_onDeleteItem(WidgetsArea.Primary)}
|
|
193
210
|
onSave={_onSave(WidgetsArea.Primary)}
|
|
194
211
|
onSaveNewField={_onSaveNewField(WidgetsArea.Primary)}
|
|
@@ -206,7 +223,6 @@ const FieldZones: FC = () => {
|
|
|
206
223
|
testId="static-zone-content"
|
|
207
224
|
isRepeatableCustomType={undefined}
|
|
208
225
|
emptyStateHeading={undefined}
|
|
209
|
-
emptyStateActionTestId="add-Static-field"
|
|
210
226
|
/>
|
|
211
227
|
{hasItems ? (
|
|
212
228
|
<Zone
|
|
@@ -216,7 +232,7 @@ const FieldZones: FC = () => {
|
|
|
216
232
|
isRepeatable
|
|
217
233
|
title="Repeatable Zone"
|
|
218
234
|
dataTip={dataTipText2}
|
|
219
|
-
widgetsArray={
|
|
235
|
+
widgetsArray={itemsWidgetsArray}
|
|
220
236
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
221
237
|
fields={variation.items}
|
|
222
238
|
EditModal={EditModal}
|
|
@@ -235,7 +251,6 @@ const FieldZones: FC = () => {
|
|
|
235
251
|
testId="slice-repeatable-zone"
|
|
236
252
|
isRepeatableCustomType={undefined}
|
|
237
253
|
emptyStateHeading="No fields"
|
|
238
|
-
emptyStateActionTestId="add-Repeatable-field"
|
|
239
254
|
/>
|
|
240
255
|
) : null}
|
|
241
256
|
<Dialog
|
|
@@ -60,7 +60,9 @@ export const VariationsList: FC<VariationsListProps> = (props) => {
|
|
|
60
60
|
}}
|
|
61
61
|
startIcon="add"
|
|
62
62
|
color="grey"
|
|
63
|
-
|
|
63
|
+
>
|
|
64
|
+
Add a variation
|
|
65
|
+
</Button>
|
|
64
66
|
</Box>
|
|
65
67
|
<div
|
|
66
68
|
className={styles.hideScrollbar}
|
|
@@ -124,7 +126,7 @@ export const VariationsList: FC<VariationsListProps> = (props) => {
|
|
|
124
126
|
// `Gradient`.
|
|
125
127
|
sx={{ position: "relative" }}
|
|
126
128
|
>
|
|
127
|
-
Add a
|
|
129
|
+
Add a variation
|
|
128
130
|
</Button>
|
|
129
131
|
</Box>
|
|
130
132
|
</div>
|
|
@@ -203,6 +205,7 @@ export const SharedSliceCards = (props: SharedSliceCardsProps) => {
|
|
|
203
205
|
<>
|
|
204
206
|
{slice.model.variations.map((v) => (
|
|
205
207
|
<div
|
|
208
|
+
key={v.id}
|
|
206
209
|
style={
|
|
207
210
|
width !== undefined
|
|
208
211
|
? { ...defaultCardStyle, width }
|
|
@@ -20,7 +20,7 @@ import { VariationsList } from "./VariationsList";
|
|
|
20
20
|
|
|
21
21
|
export const SliceBuilder: FC = () => {
|
|
22
22
|
const { slice, actionQueueStatus } = useSliceState();
|
|
23
|
-
const horizontalScroll = useMediaQuery({ max: "
|
|
23
|
+
const horizontalScroll = useMediaQuery({ max: "large" });
|
|
24
24
|
|
|
25
25
|
const contentDisplayProps = horizontalScroll
|
|
26
26
|
? { gridTemplateRows: "304px 1fr" }
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
createInitialValues,
|
|
12
12
|
} from "@/legacy/lib/forms";
|
|
13
13
|
import { DeprecatedMockConfigMessage } from "@/legacy/lib/models/common/DeprecatedMockConfigMessage";
|
|
14
|
-
import
|
|
14
|
+
import { Widgets } from "@/legacy/lib/models/common/widgets";
|
|
15
15
|
import { removeProp } from "@/legacy/lib/utils";
|
|
16
16
|
|
|
17
17
|
import { findWidgetByConfigOrType } from "../../utils";
|
|
@@ -9,9 +9,15 @@ interface HintProps {
|
|
|
9
9
|
show: boolean;
|
|
10
10
|
item: Item;
|
|
11
11
|
renderHintBase: RenderHintBaseFN;
|
|
12
|
+
hintItemName?: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
const Hint: React.FC<HintProps> = ({
|
|
15
|
+
const Hint: React.FC<HintProps> = ({
|
|
16
|
+
show,
|
|
17
|
+
renderHintBase,
|
|
18
|
+
item,
|
|
19
|
+
hintItemName,
|
|
20
|
+
}) => {
|
|
15
21
|
const fieldPathString = renderHintBase({ item });
|
|
16
22
|
|
|
17
23
|
// TODO: Call `swr`'s global `mutate` function when something changes to clear the cache.
|
|
@@ -20,6 +26,7 @@ const Hint: React.FC<HintProps> = ({ show, renderHintBase, item }) => {
|
|
|
20
26
|
return await managerClient.snippets.readSnippets({
|
|
21
27
|
fieldPath: fieldPathString.split("."),
|
|
22
28
|
model: item.value,
|
|
29
|
+
itemName: hintItemName,
|
|
23
30
|
});
|
|
24
31
|
});
|
|
25
32
|
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
} from "@/legacy/lib/forms";
|
|
16
16
|
import { validateId } from "@/legacy/lib/forms/defaults";
|
|
17
17
|
import { InputType } from "@/legacy/lib/forms/fields";
|
|
18
|
+
import { Widgets } from "@/legacy/lib/models/common/widgets";
|
|
18
19
|
import { AnyWidget } from "@/legacy/lib/models/common/widgets/Widget";
|
|
19
|
-
import * as Widgets from "@/legacy/lib/models/common/widgets/withGroup";
|
|
20
20
|
import { slugify } from "@/legacy/lib/utils/str";
|
|
21
21
|
|
|
22
22
|
import { ErrorTooltip } from "./ErrorTooltip";
|
|
@@ -3,7 +3,7 @@ import { Box, Text } from "theme-ui";
|
|
|
3
3
|
|
|
4
4
|
import Li from "@/legacy/components/Li";
|
|
5
5
|
import ListItem from "@/legacy/components/ListItem";
|
|
6
|
-
import
|
|
6
|
+
import { Widgets } from "@/legacy/lib/models/common/widgets";
|
|
7
7
|
|
|
8
8
|
import { findWidgetByConfigOrType } from "../../../utils";
|
|
9
9
|
import Hint from "./components/Hints";
|
|
@@ -103,6 +103,8 @@ const FieldZone = ({
|
|
|
103
103
|
isRepeatable={isRepeatable}
|
|
104
104
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
105
105
|
renderHintBase={renderHintBase}
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
107
|
+
hintItemName={widget.hintItemName}
|
|
106
108
|
Widgets={Widgets}
|
|
107
109
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/strict-boolean-expressions
|
|
108
110
|
typeName={widget.CUSTOM_NAME || widget.TYPE_NAME}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Text } from "@prismicio/editor-ui";
|
|
2
2
|
import { FC, ReactNode } from "react";
|
|
3
3
|
|
|
4
4
|
import styles from "./ZoneEmptyState.module.css";
|
|
@@ -6,16 +6,14 @@ import styles from "./ZoneEmptyState.module.css";
|
|
|
6
6
|
type ZoneEmptyStateProps = {
|
|
7
7
|
zoneType: "custom type" | "page type" | "slice";
|
|
8
8
|
heading?: ReactNode;
|
|
9
|
-
|
|
10
|
-
actionTestId?: string;
|
|
9
|
+
action: ReactNode;
|
|
11
10
|
};
|
|
12
11
|
|
|
13
12
|
export const ZoneEmptyState: FC<ZoneEmptyStateProps> = (props) => {
|
|
14
13
|
const {
|
|
15
14
|
zoneType,
|
|
16
15
|
heading = `Your ${zoneType} has no fields yet`,
|
|
17
|
-
|
|
18
|
-
actionTestId,
|
|
16
|
+
action,
|
|
19
17
|
} = props;
|
|
20
18
|
|
|
21
19
|
return (
|
|
@@ -26,14 +24,7 @@ export const ZoneEmptyState: FC<ZoneEmptyStateProps> = (props) => {
|
|
|
26
24
|
A field is an input for content (e.g. text, images, links).
|
|
27
25
|
</Text>
|
|
28
26
|
</div>
|
|
29
|
-
|
|
30
|
-
color="grey"
|
|
31
|
-
onClick={() => onActionClick()}
|
|
32
|
-
data-testid={actionTestId}
|
|
33
|
-
startIcon="add"
|
|
34
|
-
>
|
|
35
|
-
Add a field
|
|
36
|
-
</Button>
|
|
27
|
+
{action}
|
|
37
28
|
</div>
|
|
38
29
|
);
|
|
39
30
|
};
|