slice-machine-ui 2.2.2-beta.8 → 2.3.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/out/404.html +1 -1
- package/out/_next/static/chunks/{18539003-4c4fdc1584f243b4.js → 18539003-afe9213a677bd9f0.js} +3 -3
- package/out/_next/static/chunks/212-b6a2b8d9d16ef3c5.js +1 -0
- package/out/_next/static/chunks/{210-565d01ee9777d1a1.js → 326-2d6d04d623de16c6.js} +2 -2
- package/out/_next/static/chunks/448-ae7b5e576a84b47d.js +1 -0
- package/out/_next/static/chunks/465-d5dd75edd8e6bb65.js +1 -0
- package/out/_next/static/chunks/574-a23212bd78e563de.js +1 -0
- package/out/_next/static/chunks/59b4e022-8e544a511d670317.js +1 -0
- package/out/_next/static/chunks/{756-0b198fb40a3e6ae2.js → 695-bfe7255199983590.js} +6 -4
- package/out/_next/static/chunks/816-17afd84d2642f4c4.js +1 -0
- package/out/_next/static/chunks/f36c6662-1f3a854183168b10.js +1 -0
- package/out/_next/static/chunks/pages/_app-07a2573662865a6b.js +547 -0
- package/out/_next/static/chunks/pages/changelog-1d15a7ef498f499a.js +1 -0
- package/out/_next/static/chunks/pages/changes-0af2a1a5244418f9.js +1 -0
- package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-a6ff1618238b3510.js → [customTypeId]-b714ad9814898d23.js} +1 -1
- package/out/_next/static/chunks/pages/index-2610e550d79c5bb1.js +1 -0
- package/out/_next/static/chunks/pages/labs-240ba57bfdabe998.js +1 -0
- package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-c300f963db847451.js → [pageTypeId]-aa881786f6e5aee2.js} +1 -1
- package/out/_next/static/chunks/pages/settings-039476a9a63d25a1.js +1 -0
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-cfc19e3e799745bb.js +1 -0
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-58e6cb0f278ea03c.js +1 -0
- package/out/_next/static/chunks/pages/slices-9894ce968d74baf6.js +1 -0
- package/out/_next/static/css/447984631bacb88c.css +1 -0
- package/out/_next/static/yi8ItcVBmEtxCSvLChc0b/_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 +9 -9
- package/src/domain/fields.ts +223 -0
- package/src/features/builder/AddFieldDropdown.tsx +122 -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 +99 -0
- package/src/features/onboarding/types.ts +32 -0
- package/src/features/onboarding/useOnboardingExperiment.ts +6 -0
- package/src/hooks/usePersistedState.ts +20 -3
- package/src/legacy/components/Navigation/index.tsx +2 -0
- package/src/legacy/lib/builders/CustomTypeBuilder/TabZone/index.tsx +9 -9
- package/src/legacy/lib/builders/SliceBuilder/FieldZones/index.tsx +7 -9
- package/src/legacy/lib/builders/SliceBuilder/VariationsList/index.tsx +1 -0
- 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/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 +25 -19
- package/src/legacy/lib/models/common/widgets/Group/createGroupWidget.ts +2 -4
- package/src/legacy/lib/models/common/widgets/Group/index.tsx +8 -8
- 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 +7 -7
- 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 +0 -2
- package/out/_next/static/8ioxR-A_Nfflu3QxG8paB/_buildManifest.js +0 -1
- package/out/_next/static/chunks/212-58a99ab312f8a03b.js +0 -1
- package/out/_next/static/chunks/448-7a6843206737d199.js +0 -1
- package/out/_next/static/chunks/465-695ac5fedef986eb.js +0 -1
- package/out/_next/static/chunks/574-dfeb0e6aa3079da1.js +0 -1
- package/out/_next/static/chunks/59b4e022-7a3b5554b806349f.js +0 -1
- package/out/_next/static/chunks/816-96fc9a79308019c7.js +0 -1
- package/out/_next/static/chunks/f36c6662-03bb5e9d9aa0b0aa.js +0 -1
- package/out/_next/static/chunks/pages/_app-0f7eec1bd89de90c.js +0 -536
- package/out/_next/static/chunks/pages/changelog-f0cd26a9ae095e9e.js +0 -1
- package/out/_next/static/chunks/pages/changes-1a57f90433a0b5e2.js +0 -1
- package/out/_next/static/chunks/pages/index-a0530bd55c7e1872.js +0 -1
- package/out/_next/static/chunks/pages/labs-7b0abeef69494aec.js +0 -1
- package/out/_next/static/chunks/pages/settings-f82286dde10f624c.js +0 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-453f946e8879c829.js +0 -1
- package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-b530a5e0ac9d0391.js +0 -1
- package/out/_next/static/chunks/pages/slices-7411822d74f1f6c1.js +0 -1
- package/out/_next/static/css/ebf74ed654df9202.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/out/_next/static/{8ioxR-A_Nfflu3QxG8paB → yi8ItcVBmEtxCSvLChc0b}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
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: "addSlice",
|
|
12
|
+
title: "Add Slices",
|
|
13
|
+
description: "Add slices to your page type.",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "codePage",
|
|
17
|
+
title: "Code your page",
|
|
18
|
+
description: "Build your page's structure",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "pushModels",
|
|
22
|
+
title: "Push Your Page",
|
|
23
|
+
description: "Push to your Page Builder.",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "createContent",
|
|
27
|
+
title: "Create content",
|
|
28
|
+
description: "Create engaging content.",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "renderPage",
|
|
32
|
+
title: "Render your page",
|
|
33
|
+
description: "Render your page on localhost.",
|
|
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
|
+
addSlice: {
|
|
48
|
+
videoUrl:
|
|
49
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/ADD_SLICE.mp4",
|
|
50
|
+
content: () => (
|
|
51
|
+
<Text>Use slice templates and add them to your page type.</Text>
|
|
52
|
+
),
|
|
53
|
+
},
|
|
54
|
+
codePage: {
|
|
55
|
+
videoUrl:
|
|
56
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/CODE_SNIP.mp4",
|
|
57
|
+
content: () => (
|
|
58
|
+
<Text>
|
|
59
|
+
If you don't already have a page component, copy-paste the page snippets
|
|
60
|
+
provided in your page type to create one.
|
|
61
|
+
</Text>
|
|
62
|
+
),
|
|
63
|
+
},
|
|
64
|
+
pushModels: {
|
|
65
|
+
videoUrl:
|
|
66
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/PUSH.mp4",
|
|
67
|
+
content: () => (
|
|
68
|
+
<Text>
|
|
69
|
+
You have just created some models, but you can't use them yet. First,
|
|
70
|
+
you must push them to the Page Builder. The Page Builder is where you
|
|
71
|
+
create content. Go head — push your models.
|
|
72
|
+
</Text>
|
|
73
|
+
),
|
|
74
|
+
},
|
|
75
|
+
createContent: {
|
|
76
|
+
videoUrl:
|
|
77
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/PREVIEW.mp4",
|
|
78
|
+
content: () => (
|
|
79
|
+
<Text>
|
|
80
|
+
Open your{" "}
|
|
81
|
+
<Text href={repositoryUrl} underline>
|
|
82
|
+
Page Builder
|
|
83
|
+
</Text>
|
|
84
|
+
, create a page, add slices, save, and publish. Then, come back here.
|
|
85
|
+
</Text>
|
|
86
|
+
),
|
|
87
|
+
},
|
|
88
|
+
renderPage: {
|
|
89
|
+
videoUrl:
|
|
90
|
+
"https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/WRITE.mp4",
|
|
91
|
+
content: () => (
|
|
92
|
+
<Text>
|
|
93
|
+
To render the page, run your project in your terminal and visit the page
|
|
94
|
+
on localhost (e.g.{" "}
|
|
95
|
+
<Text component="code">localhost:3000/example-page</Text>).
|
|
96
|
+
</Text>
|
|
97
|
+
),
|
|
98
|
+
},
|
|
99
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const onboardingStepStatusesSchema = z.object({
|
|
4
|
+
addSlice: z.boolean(),
|
|
5
|
+
codePage: z.boolean(),
|
|
6
|
+
pushModels: z.boolean(),
|
|
7
|
+
createContent: z.boolean(),
|
|
8
|
+
renderPage: 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
|
+
>;
|
|
@@ -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
|
|
|
@@ -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
|
|
@@ -45,21 +45,22 @@ import SliceZone from "../SliceZone";
|
|
|
45
45
|
|
|
46
46
|
const widgetsArray = [
|
|
47
47
|
Widgets.UID,
|
|
48
|
-
Widgets.Group,
|
|
49
|
-
Widgets.StructuredText,
|
|
50
48
|
Widgets.Image,
|
|
49
|
+
Widgets.Text,
|
|
50
|
+
Widgets.StructuredText,
|
|
51
51
|
Widgets.Link,
|
|
52
|
-
Widgets.LinkToMedia,
|
|
53
|
-
Widgets.ContentRelationship,
|
|
54
52
|
Widgets.Select,
|
|
55
53
|
Widgets.Boolean,
|
|
54
|
+
Widgets.Number,
|
|
55
|
+
Widgets.Color,
|
|
56
56
|
Widgets.Date,
|
|
57
|
-
Widgets.Timestamp,
|
|
58
57
|
Widgets.Embed,
|
|
59
|
-
Widgets.
|
|
58
|
+
Widgets.Timestamp,
|
|
60
59
|
Widgets.GeoPoint,
|
|
61
|
-
Widgets.
|
|
62
|
-
Widgets.
|
|
60
|
+
Widgets.ContentRelationship,
|
|
61
|
+
Widgets.LinkToMedia,
|
|
62
|
+
Widgets.Group,
|
|
63
|
+
Widgets.NestedGroup,
|
|
63
64
|
];
|
|
64
65
|
|
|
65
66
|
interface TabZoneProps {
|
|
@@ -260,7 +261,6 @@ const TabZone: FC<TabZoneProps> = ({ tabId }) => {
|
|
|
260
261
|
}
|
|
261
262
|
testId="static-zone-content"
|
|
262
263
|
isRepeatableCustomType={customType.repeatable}
|
|
263
|
-
emptyStateActionTestId="add-Static-field"
|
|
264
264
|
/>
|
|
265
265
|
) : undefined}
|
|
266
266
|
|
|
@@ -41,20 +41,20 @@ const dataTipText2 = `The repeatable zone is for a group<br/>
|
|
|
41
41
|
indeterminate number of times, like FAQs`;
|
|
42
42
|
|
|
43
43
|
const itemsWidgetsArray = [
|
|
44
|
-
Widgets.StructuredText,
|
|
45
44
|
Widgets.Image,
|
|
45
|
+
Widgets.Text,
|
|
46
|
+
Widgets.StructuredText,
|
|
46
47
|
Widgets.Link,
|
|
47
|
-
Widgets.LinkToMedia,
|
|
48
|
-
Widgets.ContentRelationship,
|
|
49
48
|
Widgets.Select,
|
|
50
49
|
Widgets.Boolean,
|
|
50
|
+
Widgets.Number,
|
|
51
|
+
Widgets.Color,
|
|
51
52
|
Widgets.Date,
|
|
52
|
-
Widgets.Timestamp,
|
|
53
53
|
Widgets.Embed,
|
|
54
|
-
Widgets.
|
|
54
|
+
Widgets.Timestamp,
|
|
55
55
|
Widgets.GeoPoint,
|
|
56
|
-
Widgets.
|
|
57
|
-
Widgets.
|
|
56
|
+
Widgets.ContentRelationship,
|
|
57
|
+
Widgets.LinkToMedia,
|
|
58
58
|
];
|
|
59
59
|
|
|
60
60
|
const primaryWidgetsArray = [Widgets.Group, ...itemsWidgetsArray];
|
|
@@ -223,7 +223,6 @@ const FieldZones: FC = () => {
|
|
|
223
223
|
testId="static-zone-content"
|
|
224
224
|
isRepeatableCustomType={undefined}
|
|
225
225
|
emptyStateHeading={undefined}
|
|
226
|
-
emptyStateActionTestId="add-Static-field"
|
|
227
226
|
/>
|
|
228
227
|
{hasItems ? (
|
|
229
228
|
<Zone
|
|
@@ -252,7 +251,6 @@ const FieldZones: FC = () => {
|
|
|
252
251
|
testId="slice-repeatable-zone"
|
|
253
252
|
isRepeatableCustomType={undefined}
|
|
254
253
|
emptyStateHeading="No fields"
|
|
255
|
-
emptyStateActionTestId="add-Repeatable-field"
|
|
256
254
|
/>
|
|
257
255
|
) : null}
|
|
258
256
|
<Dialog
|
|
@@ -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
|
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Switch, Text } from "@prismicio/editor-ui";
|
|
2
2
|
import { array, arrayOf, bool, func, object, shape, string } from "prop-types";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { BaseStyles } from "theme-ui";
|
|
5
5
|
|
|
6
6
|
import { telemetry } from "@/apiClient";
|
|
7
7
|
import { ListHeader } from "@/components/List";
|
|
8
|
+
import { fields as allFields } from "@/domain/fields";
|
|
9
|
+
import { AddFieldDropdown } from "@/features/builder/AddFieldDropdown";
|
|
8
10
|
import { getContentTypeForTracking } from "@/utils/getContentTypeForTracking";
|
|
9
11
|
|
|
10
|
-
import SelectFieldTypeModal from "../SelectFieldTypeModal";
|
|
11
12
|
import Card from "./Card";
|
|
12
13
|
import NewField from "./Card/components/NewField";
|
|
13
14
|
import { ZoneEmptyState } from "./components/ZoneEmptyState";
|
|
@@ -32,7 +33,6 @@ const Zone = ({
|
|
|
32
33
|
testId,
|
|
33
34
|
isRepeatableCustomType,
|
|
34
35
|
emptyStateHeading,
|
|
35
|
-
emptyStateActionTestId,
|
|
36
36
|
}) => {
|
|
37
37
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
38
38
|
const widgetsArrayWithCondUid = (() => {
|
|
@@ -50,7 +50,6 @@ const Zone = ({
|
|
|
50
50
|
|
|
51
51
|
const [showHints, setShowHints] = useState(false);
|
|
52
52
|
const [editModalData, setEditModalData] = useState({ isOpen: false });
|
|
53
|
-
const [selectModalData, setSelectModalData] = useState({ isOpen: false });
|
|
54
53
|
const [newFieldData, setNewFieldData] = useState(null);
|
|
55
54
|
|
|
56
55
|
/** @param {[string, import("@prismicio/types-internal/lib/customtypes").NestableWidget]} field */
|
|
@@ -68,22 +67,38 @@ const Zone = ({
|
|
|
68
67
|
contentType: getContentTypeForTracking(window.location.pathname),
|
|
69
68
|
});
|
|
70
69
|
};
|
|
71
|
-
const enterSelectMode = () => {
|
|
72
|
-
setSelectModalData({ isOpen: true });
|
|
73
|
-
};
|
|
74
70
|
|
|
75
71
|
const closeEditModal = () => {
|
|
76
72
|
setEditModalData({ isOpen: false });
|
|
77
73
|
};
|
|
78
|
-
const closeSelectModal = () => setSelectModalData({ isOpen: false });
|
|
79
74
|
|
|
80
75
|
const onSelectFieldType = (widgetTypeName) => {
|
|
81
76
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-assignment
|
|
82
77
|
setNewFieldData({ widgetTypeName, fields });
|
|
83
|
-
setSelectModalData({ isOpen: false });
|
|
84
78
|
};
|
|
85
79
|
|
|
86
80
|
const onCancelNewField = () => setNewFieldData(null);
|
|
81
|
+
const addFieldDropdown = (
|
|
82
|
+
<AddFieldDropdown
|
|
83
|
+
disabled={newFieldData !== null}
|
|
84
|
+
onSelectField={onSelectFieldType}
|
|
85
|
+
fields={
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
87
|
+
widgetsArrayWithCondUid.filter(Boolean).map((widget) => {
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
89
|
+
const { TYPE_NAME, CUSTOM_NAME } = widget;
|
|
90
|
+
return allFields.find(
|
|
91
|
+
(f) =>
|
|
92
|
+
f.type === TYPE_NAME &&
|
|
93
|
+
(CUSTOM_NAME === undefined || f.variant === CUSTOM_NAME),
|
|
94
|
+
);
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
triggerDataTestId={
|
|
98
|
+
Boolean(isRepeatable) ? "add-field-in-items" : undefined
|
|
99
|
+
}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
87
102
|
|
|
88
103
|
return (
|
|
89
104
|
<>
|
|
@@ -103,18 +118,7 @@ const Zone = ({
|
|
|
103
118
|
style={{ flexShrink: 0 }}
|
|
104
119
|
data-testid="code-snippets-switch"
|
|
105
120
|
/>
|
|
106
|
-
|
|
107
|
-
data-testid={`add-${
|
|
108
|
-
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
109
|
-
isRepeatable ? "Repeatable" : "Static"
|
|
110
|
-
}-field`}
|
|
111
|
-
onClick={enterSelectMode}
|
|
112
|
-
startIcon="add"
|
|
113
|
-
color="grey"
|
|
114
|
-
disabled={newFieldData !== null}
|
|
115
|
-
>
|
|
116
|
-
Add a field
|
|
117
|
-
</Button>
|
|
121
|
+
{addFieldDropdown}
|
|
118
122
|
</>
|
|
119
123
|
) : undefined
|
|
120
124
|
}
|
|
@@ -129,9 +133,8 @@ const Zone = ({
|
|
|
129
133
|
zoneType={getResolvedZoneType(zoneType, zoneTypeFormat)}
|
|
130
134
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
131
135
|
heading={emptyStateHeading}
|
|
132
|
-
onActionClick={() => enterSelectMode()}
|
|
133
136
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
134
|
-
|
|
137
|
+
action={addFieldDropdown}
|
|
135
138
|
/>
|
|
136
139
|
) : // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/strict-boolean-expressions
|
|
137
140
|
fields.length > 0 || newFieldData ? (
|
|
@@ -153,7 +156,6 @@ const Zone = ({
|
|
|
153
156
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-assignment
|
|
154
157
|
renderHintBase={renderHintBase}
|
|
155
158
|
enterEditMode={enterEditMode}
|
|
156
|
-
enterSelectMode={enterSelectMode}
|
|
157
159
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
158
160
|
onDragEnd={onDragEnd}
|
|
159
161
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
@@ -194,13 +196,6 @@ const Zone = ({
|
|
|
194
196
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
195
197
|
zoneType={zoneType}
|
|
196
198
|
/>
|
|
197
|
-
<SelectFieldTypeModal
|
|
198
|
-
data={selectModalData}
|
|
199
|
-
close={closeSelectModal}
|
|
200
|
-
onSelect={onSelectFieldType}
|
|
201
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
202
|
-
widgetsArray={widgetsArrayWithCondUid}
|
|
203
|
-
/>
|
|
204
199
|
</>
|
|
205
200
|
);
|
|
206
201
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BooleanField } from "@prismicio/types-internal/lib/customtypes/widgets/nestable";
|
|
2
|
-
import {
|
|
2
|
+
import { MdOutlineToggleOff } from "react-icons/md";
|
|
3
3
|
import * as yup from "yup";
|
|
4
4
|
|
|
5
5
|
import { createValidationSchema } from "../../../../forms";
|
|
@@ -18,9 +18,7 @@ import { removeProp } from "../../../../utils";
|
|
|
18
18
|
import { Widget } from "../Widget";
|
|
19
19
|
|
|
20
20
|
const Meta = {
|
|
21
|
-
icon:
|
|
22
|
-
title: "Boolean",
|
|
23
|
-
description: "An input that is either true or false",
|
|
21
|
+
icon: MdOutlineToggleOff,
|
|
24
22
|
};
|
|
25
23
|
|
|
26
24
|
const FormFields = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Color } from "@prismicio/types-internal/lib/customtypes/widgets/nestable";
|
|
2
|
-
import {
|
|
2
|
+
import { MdOutlineColorLens } from "react-icons/md";
|
|
3
3
|
|
|
4
4
|
import { createDefaultWidgetValues } from "../../../../utils";
|
|
5
5
|
import { Widget } from "../Widget";
|
|
@@ -12,9 +12,7 @@ import { Widget } from "../Widget";
|
|
|
12
12
|
} */
|
|
13
13
|
|
|
14
14
|
const Meta = {
|
|
15
|
-
icon:
|
|
16
|
-
title: "Color",
|
|
17
|
-
description: "A color picker",
|
|
15
|
+
icon: MdOutlineColorLens,
|
|
18
16
|
};
|
|
19
17
|
|
|
20
18
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
@@ -25,8 +25,6 @@ import Form, { FormFields } from "./Form";
|
|
|
25
25
|
|
|
26
26
|
const Meta = {
|
|
27
27
|
icon: MdSettingsEthernet,
|
|
28
|
-
title: "Content Relationship",
|
|
29
|
-
description: "Define content relations & internal links",
|
|
30
28
|
};
|
|
31
29
|
|
|
32
30
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Embed } from "@prismicio/types-internal/lib/customtypes/widgets/nestable";
|
|
2
|
-
import {
|
|
2
|
+
import { MdCode } from "react-icons/md";
|
|
3
3
|
|
|
4
4
|
import { createDefaultWidgetValues } from "../../../../utils";
|
|
5
5
|
import { Widget } from "../Widget";
|
|
@@ -16,9 +16,7 @@ import { Widget } from "../Widget";
|
|
|
16
16
|
const { FormFields, schema } = createDefaultWidgetValues("Embed");
|
|
17
17
|
|
|
18
18
|
const Meta = {
|
|
19
|
-
icon:
|
|
20
|
-
title: "Embed",
|
|
21
|
-
description: "Embed videos, songs, tweets, slides, …",
|
|
19
|
+
icon: MdCode,
|
|
22
20
|
};
|
|
23
21
|
|
|
24
22
|
export const EmbedWidget: Widget<Embed, typeof schema> = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GeoPoint } from "@prismicio/types-internal/lib/customtypes/widgets/nestable";
|
|
2
|
-
import {
|
|
2
|
+
import { MdOutlinePlace } from "react-icons/md";
|
|
3
3
|
import * as yup from "yup";
|
|
4
4
|
|
|
5
5
|
import { DefaultFields } from "../../../../forms/defaults";
|
|
@@ -36,9 +36,7 @@ const schema = yup.object().shape({
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
const Meta = {
|
|
39
|
-
icon:
|
|
40
|
-
title: "GeoPoint",
|
|
41
|
-
description: "A field for storing geo-coordinates",
|
|
39
|
+
icon: MdOutlinePlace,
|
|
42
40
|
};
|
|
43
41
|
|
|
44
42
|
export const GeoPointWidget: Widget<GeoPoint, typeof schema> = {
|
|
@@ -2,18 +2,19 @@ import { GroupFieldType } from "@prismicio/types-internal/lib/customtypes/widget
|
|
|
2
2
|
import { Fragment, useState } from "react";
|
|
3
3
|
import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
|
4
4
|
import { flushSync } from "react-dom";
|
|
5
|
-
import { Box
|
|
5
|
+
import { Box } from "theme-ui";
|
|
6
6
|
|
|
7
7
|
import { telemetry } from "@/apiClient";
|
|
8
|
+
import { fields as allFields } from "@/domain/fields";
|
|
8
9
|
import {
|
|
9
10
|
addFieldToGroup,
|
|
10
11
|
deleteFieldFromGroup,
|
|
11
12
|
reorderFieldInGroup,
|
|
12
13
|
updateFieldInGroup,
|
|
13
14
|
} from "@/domain/group";
|
|
15
|
+
import { AddFieldDropdown } from "@/features/builder/AddFieldDropdown";
|
|
14
16
|
import ListItem from "@/legacy/components/ListItem";
|
|
15
17
|
import EditModal from "@/legacy/lib/builders/common/EditModal";
|
|
16
|
-
import SelectFieldTypeModal from "@/legacy/lib/builders/common/SelectFieldTypeModal";
|
|
17
18
|
import Hint from "@/legacy/lib/builders/common/Zone/Card/components/Hints";
|
|
18
19
|
import NewField from "@/legacy/lib/builders/common/Zone/Card/components/NewField";
|
|
19
20
|
import { findWidgetByConfigOrType } from "@/legacy/lib/builders/utils";
|
|
@@ -39,14 +40,12 @@ export const CustomListItem = ({
|
|
|
39
40
|
HintElement,
|
|
40
41
|
...rest
|
|
41
42
|
}) => {
|
|
42
|
-
const [selectMode, setSelectMode] = useState(false);
|
|
43
43
|
const [newFieldData, setNewFieldData] = useState(null);
|
|
44
44
|
const [editModalData, setEditModalData] = useState({ isOpen: false });
|
|
45
45
|
|
|
46
46
|
const onSelectFieldType = (widgetTypeName) => {
|
|
47
47
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
48
48
|
setNewFieldData({ widgetTypeName });
|
|
49
|
-
setSelectMode(false);
|
|
50
49
|
};
|
|
51
50
|
|
|
52
51
|
const onCancelNewField = () => {
|
|
@@ -171,15 +170,28 @@ export const CustomListItem = ({
|
|
|
171
170
|
{...rest}
|
|
172
171
|
HintElement={HintElement}
|
|
173
172
|
CustomEditElements={[
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
173
|
+
<AddFieldDropdown
|
|
174
|
+
key="add-field-dropdown"
|
|
175
|
+
disabled={newFieldData !== null}
|
|
176
|
+
onSelectField={onSelectFieldType}
|
|
177
|
+
fields={widgetsArray.filter(Boolean).map((widget) => {
|
|
178
|
+
const { TYPE_NAME, CUSTOM_NAME } = widget;
|
|
179
|
+
|
|
180
|
+
const field = allFields.find(
|
|
181
|
+
(f) =>
|
|
182
|
+
f.type === TYPE_NAME &&
|
|
183
|
+
(CUSTOM_NAME === undefined || f.variant === CUSTOM_NAME),
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
if (!field) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`Field not found for widget: ${TYPE_NAME} - ${CUSTOM_NAME}`,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return field;
|
|
193
|
+
})}
|
|
194
|
+
/>,
|
|
183
195
|
]}
|
|
184
196
|
children={
|
|
185
197
|
<Box sx={{ ml: 4 }}>
|
|
@@ -282,12 +294,6 @@ export const CustomListItem = ({
|
|
|
282
294
|
</Box>
|
|
283
295
|
}
|
|
284
296
|
/>
|
|
285
|
-
<SelectFieldTypeModal
|
|
286
|
-
data={{ isOpen: selectMode }}
|
|
287
|
-
close={() => setSelectMode(false)}
|
|
288
|
-
onSelect={onSelectFieldType}
|
|
289
|
-
widgetsArray={widgetsArray}
|
|
290
|
-
/>
|
|
291
297
|
<EditModal
|
|
292
298
|
data={editModalData}
|
|
293
299
|
close={closeEditModal}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MdOutlineCreateNewFolder } from "react-icons/md";
|
|
2
2
|
import * as yup from "yup";
|
|
3
3
|
|
|
4
4
|
import { TabField } from "@/legacy/lib/models/common/CustomType";
|
|
@@ -12,9 +12,7 @@ import { type GroupListItemProps } from ".";
|
|
|
12
12
|
import Form, { FormFields } from "./Form";
|
|
13
13
|
|
|
14
14
|
const Meta = {
|
|
15
|
-
icon:
|
|
16
|
-
title: "Group",
|
|
17
|
-
description: "A repeatable set of fields",
|
|
15
|
+
icon: MdOutlineCreateNewFolder,
|
|
18
16
|
};
|
|
19
17
|
|
|
20
18
|
const createSchema = (typeRegex: RegExp) =>
|