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
|
@@ -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,3 +1,5 @@
|
|
|
1
|
+
import { GroupFieldType } from "@prismicio/types-internal/lib/customtypes/widgets";
|
|
2
|
+
|
|
1
3
|
import { TabField } from "@/legacy/lib/models/common/CustomType";
|
|
2
4
|
|
|
3
5
|
interface Widgets {
|
|
@@ -21,6 +23,12 @@ export const findWidgetByConfigOrType = (
|
|
|
21
23
|
return widgets.Link;
|
|
22
24
|
}
|
|
23
25
|
}
|
|
26
|
+
// The Group & NestedGroup widgets share the "Group" type. They are never
|
|
27
|
+
// in the same widget group, so this will use whichever is provided. For example,
|
|
28
|
+
// in the custom list item for Group, we always pass NestedGroup as the Group widget.
|
|
29
|
+
if (type === GroupFieldType) {
|
|
30
|
+
return widgets.Group ?? widgets.NestedGroup;
|
|
31
|
+
}
|
|
24
32
|
|
|
25
33
|
return widgets[type];
|
|
26
34
|
};
|
|
@@ -1,32 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NestableWidget } from "@prismicio/types-internal/lib/customtypes";
|
|
2
|
+
import {
|
|
3
|
+
Group,
|
|
4
|
+
GroupFieldType,
|
|
5
|
+
} from "@prismicio/types-internal/lib/customtypes/widgets";
|
|
2
6
|
import { StringOrNull } from "@prismicio/types-internal/lib/validators";
|
|
3
7
|
import { getOrElseW } from "fp-ts/lib/Either";
|
|
4
8
|
import * as t from "io-ts";
|
|
5
9
|
|
|
6
10
|
import { FieldsSM } from "./Fields";
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
t.
|
|
10
|
-
label: StringOrNull,
|
|
11
|
-
repeat: t.boolean,
|
|
12
|
-
fields: FieldsSM,
|
|
13
|
-
}),
|
|
14
|
-
);
|
|
15
|
-
export type GroupConfig = t.TypeOf<typeof GroupConfig>;
|
|
16
|
-
|
|
17
|
-
export const GroupSM = t.exact(
|
|
18
|
-
t.intersection([
|
|
19
|
-
t.type({
|
|
20
|
-
type: t.literal("Group"),
|
|
21
|
-
}),
|
|
12
|
+
const createGroupConfig = <TFields extends t.Mixed>(fields: TFields) =>
|
|
13
|
+
t.exact(
|
|
22
14
|
t.partial({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
config: GroupConfig,
|
|
15
|
+
label: StringOrNull,
|
|
16
|
+
repeat: t.boolean,
|
|
17
|
+
fields,
|
|
27
18
|
}),
|
|
28
|
-
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const createGroupSM = <TFields extends t.Mixed>(fields: TFields) =>
|
|
22
|
+
t.exact(
|
|
23
|
+
t.intersection([
|
|
24
|
+
t.type({
|
|
25
|
+
type: t.literal("Group"),
|
|
26
|
+
}),
|
|
27
|
+
t.partial({
|
|
28
|
+
fieldset: StringOrNull,
|
|
29
|
+
icon: t.string,
|
|
30
|
+
description: t.string,
|
|
31
|
+
config: createGroupConfig(fields),
|
|
32
|
+
}),
|
|
33
|
+
]),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export const NestedGroupSM = createGroupSM(FieldsSM);
|
|
37
|
+
export type NestedGroupSM = t.TypeOf<typeof NestedGroupSM>;
|
|
38
|
+
|
|
39
|
+
const GroupFieldsSM = t.array(
|
|
40
|
+
t.type({
|
|
41
|
+
key: t.string,
|
|
42
|
+
value: t.union([NestableWidget, NestedGroupSM]),
|
|
43
|
+
}),
|
|
29
44
|
);
|
|
45
|
+
|
|
46
|
+
export const GroupSM = createGroupSM(GroupFieldsSM);
|
|
30
47
|
export type GroupSM = t.TypeOf<typeof GroupSM>;
|
|
31
48
|
|
|
32
49
|
export const Groups = {
|
|
@@ -34,10 +51,13 @@ export const Groups = {
|
|
|
34
51
|
const fields = (() => {
|
|
35
52
|
if (!group.config?.fields) return;
|
|
36
53
|
|
|
37
|
-
return group.config.fields.reduce(
|
|
38
|
-
(
|
|
39
|
-
|
|
40
|
-
|
|
54
|
+
return group.config.fields.reduce((acc, { key, value }) => {
|
|
55
|
+
if (value.type === GroupFieldType) {
|
|
56
|
+
return { ...acc, [key]: Groups.fromSM(value) };
|
|
57
|
+
} else {
|
|
58
|
+
return { ...acc, [key]: value };
|
|
59
|
+
}
|
|
60
|
+
}, {});
|
|
41
61
|
})();
|
|
42
62
|
|
|
43
63
|
return getOrElseW(() => {
|
|
@@ -58,10 +78,13 @@ export const Groups = {
|
|
|
58
78
|
if (!group.config?.fields) return;
|
|
59
79
|
|
|
60
80
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
61
|
-
return Object.entries(group.config?.fields || {}).map(([key, value]) =>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
81
|
+
return Object.entries(group.config?.fields || {}).map(([key, value]) => {
|
|
82
|
+
if (value.type === GroupFieldType) {
|
|
83
|
+
return { key, value: Groups.toSM(value) };
|
|
84
|
+
} else {
|
|
85
|
+
return { key, value };
|
|
86
|
+
}
|
|
87
|
+
});
|
|
65
88
|
})();
|
|
66
89
|
|
|
67
90
|
return getOrElseW(() => {
|
|
@@ -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> = {
|
|
@@ -1,32 +1,35 @@
|
|
|
1
|
+
import { GroupFieldType } from "@prismicio/types-internal/lib/customtypes/widgets";
|
|
1
2
|
import { Fragment, useState } from "react";
|
|
2
3
|
import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
|
3
4
|
import { flushSync } from "react-dom";
|
|
4
|
-
import { Box
|
|
5
|
+
import { Box } from "theme-ui";
|
|
5
6
|
|
|
6
7
|
import { telemetry } from "@/apiClient";
|
|
8
|
+
import { fields as allFields } from "@/domain/fields";
|
|
7
9
|
import {
|
|
8
10
|
addFieldToGroup,
|
|
9
11
|
deleteFieldFromGroup,
|
|
10
12
|
reorderFieldInGroup,
|
|
11
13
|
updateFieldInGroup,
|
|
12
14
|
} from "@/domain/group";
|
|
15
|
+
import { AddFieldDropdown } from "@/features/builder/AddFieldDropdown";
|
|
13
16
|
import ListItem from "@/legacy/components/ListItem";
|
|
14
17
|
import EditModal from "@/legacy/lib/builders/common/EditModal";
|
|
15
|
-
import SelectFieldTypeModal from "@/legacy/lib/builders/common/SelectFieldTypeModal";
|
|
16
18
|
import Hint from "@/legacy/lib/builders/common/Zone/Card/components/Hints";
|
|
17
19
|
import NewField from "@/legacy/lib/builders/common/Zone/Card/components/NewField";
|
|
18
20
|
import { findWidgetByConfigOrType } from "@/legacy/lib/builders/utils";
|
|
19
21
|
import { Groups } from "@/legacy/lib/models/common/Group";
|
|
20
|
-
import * as Widgets from "@/legacy/lib/models/common/widgets";
|
|
21
|
-
import groupBuilderWidgetsArray from "@/legacy/lib/models/common/widgets/groupBuilderArray";
|
|
22
22
|
import { ensureDnDDestination } from "@/legacy/lib/utils";
|
|
23
23
|
import { transformKeyAccessor } from "@/legacy/lib/utils/str";
|
|
24
24
|
import { getContentTypeForTracking } from "@/utils/getContentTypeForTracking";
|
|
25
25
|
|
|
26
26
|
/* eslint-disable */
|
|
27
|
-
const CustomListItem = ({
|
|
27
|
+
export const CustomListItem = ({
|
|
28
28
|
tabId,
|
|
29
29
|
widget,
|
|
30
|
+
Widgets,
|
|
31
|
+
widgetsArray,
|
|
32
|
+
hintBase,
|
|
30
33
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
31
34
|
parentSnapshot,
|
|
32
35
|
showHints,
|
|
@@ -37,14 +40,12 @@ const CustomListItem = ({
|
|
|
37
40
|
HintElement,
|
|
38
41
|
...rest
|
|
39
42
|
}) => {
|
|
40
|
-
const [selectMode, setSelectMode] = useState(false);
|
|
41
43
|
const [newFieldData, setNewFieldData] = useState(null);
|
|
42
44
|
const [editModalData, setEditModalData] = useState({ isOpen: false });
|
|
43
45
|
|
|
44
46
|
const onSelectFieldType = (widgetTypeName) => {
|
|
45
47
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
46
48
|
setNewFieldData({ widgetTypeName });
|
|
47
|
-
setSelectMode(false);
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
const onCancelNewField = () => {
|
|
@@ -86,7 +87,7 @@ const CustomListItem = ({
|
|
|
86
87
|
group: Groups.fromSM(groupItem.value),
|
|
87
88
|
previousFieldId: previousKey,
|
|
88
89
|
newFieldId: newKey,
|
|
89
|
-
field: value,
|
|
90
|
+
field: value.type === GroupFieldType ? Groups.fromSM(value) : value,
|
|
90
91
|
});
|
|
91
92
|
|
|
92
93
|
saveItem({
|
|
@@ -169,15 +170,28 @@ const CustomListItem = ({
|
|
|
169
170
|
{...rest}
|
|
170
171
|
HintElement={HintElement}
|
|
171
172
|
CustomEditElements={[
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
+
/>,
|
|
181
195
|
]}
|
|
182
196
|
children={
|
|
183
197
|
<Box sx={{ ml: 4 }}>
|
|
@@ -215,6 +229,8 @@ const CustomListItem = ({
|
|
|
215
229
|
key: item.key,
|
|
216
230
|
enterEditMode,
|
|
217
231
|
deleteItem: onDeleteItem,
|
|
232
|
+
saveItem: onSaveField,
|
|
233
|
+
showHints,
|
|
218
234
|
renderFieldAccessor: (key) =>
|
|
219
235
|
`item${transformKeyAccessor(item.key)}`,
|
|
220
236
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
|
|
@@ -232,13 +248,25 @@ const CustomListItem = ({
|
|
|
232
248
|
isRepeatable={isRepeatable}
|
|
233
249
|
renderHintBase={({ item }) =>
|
|
234
250
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access
|
|
235
|
-
|
|
251
|
+
`${hintBase}${transformKeyAccessor(item.key)}`
|
|
236
252
|
}
|
|
253
|
+
hintItemName={widget.hintItemName}
|
|
237
254
|
Widgets={Widgets}
|
|
238
255
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
239
256
|
typeName={widget.CUSTOM_NAME || widget.TYPE_NAME}
|
|
240
257
|
/>
|
|
241
258
|
);
|
|
259
|
+
|
|
260
|
+
if (widget.CustomListItem) {
|
|
261
|
+
const { CustomListItem } = widget;
|
|
262
|
+
return (
|
|
263
|
+
<CustomListItem
|
|
264
|
+
{...props}
|
|
265
|
+
HintElement={HintElement}
|
|
266
|
+
/>
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
242
270
|
return (
|
|
243
271
|
<ListItem {...props} HintElement={HintElement} />
|
|
244
272
|
);
|
|
@@ -266,12 +294,6 @@ const CustomListItem = ({
|
|
|
266
294
|
</Box>
|
|
267
295
|
}
|
|
268
296
|
/>
|
|
269
|
-
<SelectFieldTypeModal
|
|
270
|
-
data={{ isOpen: selectMode }}
|
|
271
|
-
close={() => setSelectMode(false)}
|
|
272
|
-
onSelect={onSelectFieldType}
|
|
273
|
-
widgetsArray={groupBuilderWidgetsArray}
|
|
274
|
-
/>
|
|
275
297
|
<EditModal
|
|
276
298
|
data={editModalData}
|
|
277
299
|
close={closeEditModal}
|
|
@@ -282,6 +304,4 @@ const CustomListItem = ({
|
|
|
282
304
|
</Fragment>
|
|
283
305
|
);
|
|
284
306
|
};
|
|
285
|
-
|
|
286
|
-
export default CustomListItem;
|
|
287
307
|
/* eslint-enable */
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { MdOutlineCreateNewFolder } from "react-icons/md";
|
|
2
|
+
import * as yup from "yup";
|
|
3
|
+
|
|
4
|
+
import { TabField } from "@/legacy/lib/models/common/CustomType";
|
|
5
|
+
import {
|
|
6
|
+
type GroupSM,
|
|
7
|
+
type NestedGroupSM,
|
|
8
|
+
} from "@/legacy/lib/models/common/Group";
|
|
9
|
+
import { type Widget } from "@/legacy/lib/models/common/widgets/Widget";
|
|
10
|
+
|
|
11
|
+
import { type GroupListItemProps } from ".";
|
|
12
|
+
import Form, { FormFields } from "./Form";
|
|
13
|
+
|
|
14
|
+
const Meta = {
|
|
15
|
+
icon: MdOutlineCreateNewFolder,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const createSchema = (typeRegex: RegExp) =>
|
|
19
|
+
yup.object().shape({
|
|
20
|
+
type: yup
|
|
21
|
+
.string()
|
|
22
|
+
.matches(typeRegex, { excludeEmptyString: true })
|
|
23
|
+
.required(),
|
|
24
|
+
config: yup.object().shape({
|
|
25
|
+
fields: yup.array(),
|
|
26
|
+
label: yup.string(),
|
|
27
|
+
placeholder: yup.string(),
|
|
28
|
+
repeat: yup.boolean().optional(),
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
export type SchemaType = ReturnType<typeof createSchema>;
|
|
32
|
+
|
|
33
|
+
type CreateGroupWidgetArgsBase<T extends TabField> = {
|
|
34
|
+
schemaTypeRegex: RegExp;
|
|
35
|
+
customListItem: (props: GroupListItemProps<T>) => JSX.Element;
|
|
36
|
+
hintItemName: string;
|
|
37
|
+
customName?: string;
|
|
38
|
+
};
|
|
39
|
+
type CreateTopGroupWidgetArgs = CreateGroupWidgetArgsBase<GroupSM>;
|
|
40
|
+
type CreateNestedGroupWidgetArgs = CreateGroupWidgetArgsBase<NestedGroupSM> & {
|
|
41
|
+
customName: "NestedGroup";
|
|
42
|
+
};
|
|
43
|
+
type CreateGroupWidgetArgs =
|
|
44
|
+
| CreateTopGroupWidgetArgs
|
|
45
|
+
| CreateNestedGroupWidgetArgs;
|
|
46
|
+
|
|
47
|
+
export function createGroupWidget(
|
|
48
|
+
args: CreateTopGroupWidgetArgs,
|
|
49
|
+
): Widget<GroupSM, SchemaType>;
|
|
50
|
+
|
|
51
|
+
export function createGroupWidget(
|
|
52
|
+
args: CreateNestedGroupWidgetArgs,
|
|
53
|
+
): Widget<NestedGroupSM, SchemaType>;
|
|
54
|
+
|
|
55
|
+
export function createGroupWidget({
|
|
56
|
+
schemaTypeRegex,
|
|
57
|
+
customListItem,
|
|
58
|
+
customName,
|
|
59
|
+
hintItemName,
|
|
60
|
+
}: CreateGroupWidgetArgs):
|
|
61
|
+
| Widget<GroupSM, SchemaType>
|
|
62
|
+
| Widget<NestedGroupSM, SchemaType> {
|
|
63
|
+
return {
|
|
64
|
+
Meta,
|
|
65
|
+
Form,
|
|
66
|
+
FormFields,
|
|
67
|
+
schema: createSchema(schemaTypeRegex),
|
|
68
|
+
create: (label: string) => ({
|
|
69
|
+
type: "Group",
|
|
70
|
+
config: {
|
|
71
|
+
label,
|
|
72
|
+
repeat: true,
|
|
73
|
+
fields: [],
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
CustomListItem: customListItem,
|
|
77
|
+
TYPE_NAME: "Group",
|
|
78
|
+
CUSTOM_NAME: customName,
|
|
79
|
+
hintItemName,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { type DroppableStateSnapshot } from "react-beautiful-dnd";
|
|
2
|
+
|
|
3
|
+
import { useNestedGroupExperiment } from "@/hooks/useNestedGroupExperiment";
|
|
4
|
+
import { type Item } from "@/legacy/components/ListItem";
|
|
5
|
+
import { type TabField } from "@/legacy/lib/models/common/CustomType";
|
|
6
|
+
import { type GroupSM } from "@/legacy/lib/models/common/Group";
|
|
7
|
+
import { Widgets } from "@/legacy/lib/models/common/widgets/groupWidgets";
|
|
8
|
+
import { type Widget } from "@/legacy/lib/models/common/widgets/Widget";
|
|
9
|
+
|
|
10
|
+
import { createGroupWidget, type SchemaType } from "./createGroupWidget";
|
|
11
|
+
import { CustomListItem } from "./ListItem";
|
|
12
|
+
|
|
13
|
+
const widgetsArray = [
|
|
14
|
+
Widgets.Image,
|
|
15
|
+
Widgets.Text,
|
|
16
|
+
Widgets.StructuredText,
|
|
17
|
+
Widgets.Link,
|
|
18
|
+
Widgets.Select,
|
|
19
|
+
Widgets.Boolean,
|
|
20
|
+
Widgets.Number,
|
|
21
|
+
Widgets.Color,
|
|
22
|
+
Widgets.Date,
|
|
23
|
+
Widgets.Embed,
|
|
24
|
+
Widgets.Timestamp,
|
|
25
|
+
Widgets.GeoPoint,
|
|
26
|
+
Widgets.ContentRelationship,
|
|
27
|
+
Widgets.LinkToMedia,
|
|
28
|
+
Widgets.NestedGroup,
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export interface GroupListItemProps<F extends TabField> {
|
|
32
|
+
tabId: string;
|
|
33
|
+
widget: Widget<F, SchemaType>;
|
|
34
|
+
parentSnapshot: DroppableStateSnapshot;
|
|
35
|
+
showHints: boolean;
|
|
36
|
+
isRepeatable: boolean;
|
|
37
|
+
item: Item<F>;
|
|
38
|
+
draggableId: string;
|
|
39
|
+
saveItem: ({
|
|
40
|
+
apiId,
|
|
41
|
+
newKey,
|
|
42
|
+
value,
|
|
43
|
+
}: {
|
|
44
|
+
apiId: string;
|
|
45
|
+
newKey: string;
|
|
46
|
+
value: F;
|
|
47
|
+
}) => void;
|
|
48
|
+
HintElement: JSX.Element;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const hintItemName = "item";
|
|
52
|
+
|
|
53
|
+
const GroupListItem = (props: GroupListItemProps<GroupSM>): JSX.Element => {
|
|
54
|
+
const nestedGroupExperiment = useNestedGroupExperiment();
|
|
55
|
+
const maybeFilteredWidgetsArray = nestedGroupExperiment.eligible
|
|
56
|
+
? widgetsArray
|
|
57
|
+
: widgetsArray.filter((widget) => widget.CUSTOM_NAME !== "NestedGroup");
|
|
58
|
+
return (
|
|
59
|
+
<CustomListItem
|
|
60
|
+
Widgets={Widgets}
|
|
61
|
+
widgetsArray={maybeFilteredWidgetsArray}
|
|
62
|
+
hintBase={hintItemName}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const GroupWidget = createGroupWidget({
|
|
69
|
+
schemaTypeRegex: /^Group$/,
|
|
70
|
+
customListItem: GroupListItem,
|
|
71
|
+
hintItemName,
|
|
72
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Image } from "@prismicio/types-internal/lib/customtypes/widgets/nestable";
|
|
2
|
-
import {
|
|
2
|
+
import { MdOutlineImage } from "react-icons/md";
|
|
3
3
|
import * as yup from "yup";
|
|
4
4
|
|
|
5
5
|
import { createValidationSchema } from "../../../../forms";
|
|
@@ -38,9 +38,7 @@ const schema = yup.object().shape({
|
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
const Meta = {
|
|
41
|
-
icon:
|
|
42
|
-
title: "Image",
|
|
43
|
-
description: "A responsive image field with constraints",
|
|
41
|
+
icon: MdOutlineImage,
|
|
44
42
|
};
|
|
45
43
|
|
|
46
44
|
export const ImageWidget: Widget<Image, typeof schema> = {
|