@sanity/personalization-plugin 2.4.1 → 2.5.0-field-level-personalization.1
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/README.md +107 -5
- package/dist/_chunks-cjs/fieldExperiments.js +507 -0
- package/dist/_chunks-cjs/fieldExperiments.js.map +1 -0
- package/dist/_chunks-es/fieldExperiments.mjs +511 -0
- package/dist/_chunks-es/fieldExperiments.mjs.map +1 -0
- package/dist/growthbook/index.js +3 -3
- package/dist/growthbook/index.js.map +1 -1
- package/dist/growthbook/index.mjs +1 -1
- package/dist/index.d.mts +33 -12
- package/dist/index.d.ts +33 -12
- package/dist/index.js +158 -277
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +160 -277
- package/dist/index.mjs.map +1 -1
- package/package.json +20 -20
- package/src/components/ArrayItem.tsx +9 -0
- package/src/components/Select.tsx +1 -1
- package/src/components/{Array.tsx → experiment/Array.tsx} +2 -2
- package/src/components/{ExperimentContext.tsx → experiment/Context.tsx} +2 -2
- package/src/components/{ExperimentField.tsx → experiment/Field.tsx} +11 -8
- package/src/components/{ExperimentInput.tsx → experiment/Input.tsx} +4 -4
- package/src/components/{VariantInput.tsx → experiment/VariantInput.tsx} +2 -1
- package/src/components/{VariantPreview.tsx → experiment/VariantPreview.tsx} +2 -2
- package/src/components/experiment/index.ts +6 -0
- package/src/components/personalization/Array.tsx +59 -0
- package/src/components/personalization/Context.tsx +61 -0
- package/src/components/personalization/Field.tsx +134 -0
- package/src/components/personalization/SegmentInput.tsx +19 -0
- package/src/components/personalization/SegmentPreview.tsx +71 -0
- package/src/components/personalization/index.ts +5 -0
- package/src/fieldExperiments.tsx +44 -12
- package/src/fieldPersonalization.tsx +254 -0
- package/src/index.ts +1 -0
- package/src/types.ts +20 -2
- package/src/utils/clearChildGroups.ts +33 -0
package/dist/index.mjs
CHANGED
|
@@ -1,105 +1,82 @@
|
|
|
1
|
+
import { clearChildrenGroups, CloseIcon, flattenSchemaType, ArrayItem } from "./_chunks-es/fieldExperiments.mjs";
|
|
2
|
+
import { fieldLevelExperiments } from "./_chunks-es/fieldExperiments.mjs";
|
|
1
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useClient, useWorkspace,
|
|
3
|
-
import { Stack, Inline, Button
|
|
4
|
+
import { useClient, useWorkspace, defineDocumentFieldAction, set, unset, useFormValue, isReference, isImage, definePlugin, isObjectInputProps, defineType, defineField } from "sanity";
|
|
5
|
+
import { Stack, Inline, Button } from "@sanity/ui";
|
|
4
6
|
import { uuid } from "@sanity/uuid";
|
|
5
|
-
import { createContext, useMemo, useContext, useCallback,
|
|
7
|
+
import { createContext, useMemo, useContext, useCallback, useState, useEffect } from "react";
|
|
6
8
|
import equal from "fast-deep-equal";
|
|
7
9
|
import { suspend } from "suspend-react";
|
|
8
|
-
import {
|
|
10
|
+
import { IoMdPeople } from "react-icons/io";
|
|
9
11
|
const CONFIG_DEFAULT = {
|
|
10
12
|
fields: [],
|
|
11
13
|
apiVersion: "2024-11-07",
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}, ExperimentContext = createContext({
|
|
14
|
+
personalizationNameOverride: "personalization",
|
|
15
|
+
segmentNameOverride: "segment",
|
|
16
|
+
segmentId: "segmentId",
|
|
17
|
+
segmentArrayName: "segments"
|
|
18
|
+
}, PersonalizationContext = createContext({
|
|
18
19
|
...CONFIG_DEFAULT,
|
|
19
|
-
|
|
20
|
+
segments: []
|
|
20
21
|
});
|
|
21
|
-
function
|
|
22
|
-
return useContext(
|
|
22
|
+
function usePersonalizationContext() {
|
|
23
|
+
return useContext(PersonalizationContext);
|
|
23
24
|
}
|
|
24
|
-
function
|
|
25
|
-
const {
|
|
25
|
+
function PersonalizationProvider(props) {
|
|
26
|
+
const { personalizationFieldPluginConfig } = props, client = useClient({ apiVersion: personalizationFieldPluginConfig.apiVersion }), workspace = useWorkspace(), segments = Array.isArray(personalizationFieldPluginConfig.segments) ? personalizationFieldPluginConfig.segments : suspend(
|
|
26
27
|
// eslint-disable-next-line require-await
|
|
27
|
-
async () => typeof
|
|
28
|
+
async () => typeof personalizationFieldPluginConfig.segments == "function" ? personalizationFieldPluginConfig.segments(client) : personalizationFieldPluginConfig.segments,
|
|
28
29
|
[workspace],
|
|
29
30
|
{ equal }
|
|
30
31
|
), context = useMemo(
|
|
31
|
-
() => ({ ...
|
|
32
|
-
[
|
|
32
|
+
() => ({ ...personalizationFieldPluginConfig, segments }),
|
|
33
|
+
[personalizationFieldPluginConfig, segments]
|
|
33
34
|
);
|
|
34
|
-
return /* @__PURE__ */ jsx(
|
|
35
|
+
return /* @__PURE__ */ jsx(PersonalizationContext.Provider, { value: context, children: props.renderDefault(props) });
|
|
35
36
|
}
|
|
36
37
|
const ArrayInput = (props) => {
|
|
37
|
-
const
|
|
38
|
-
async (
|
|
38
|
+
const { onItemAppend, segmentName, segmentId } = props, { segments } = usePersonalizationContext(), handleClick = useCallback(
|
|
39
|
+
async (segment) => {
|
|
39
40
|
const item = {
|
|
40
41
|
_key: uuid(),
|
|
41
|
-
[
|
|
42
|
-
|
|
43
|
-
_type: variantName
|
|
42
|
+
[segmentId]: segment.id,
|
|
43
|
+
_type: segmentName
|
|
44
44
|
};
|
|
45
45
|
onItemAppend(item);
|
|
46
46
|
},
|
|
47
|
-
[
|
|
48
|
-
),
|
|
47
|
+
[segmentId, segmentName, onItemAppend]
|
|
48
|
+
), usedSegments = (props.value || [])?.map((segment) => segment[segmentId]);
|
|
49
49
|
return /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
|
|
50
50
|
props.renderDefault({ ...props, arrayFunctions: () => null }),
|
|
51
|
-
/* @__PURE__ */ jsx(Inline, { space: 1, children:
|
|
51
|
+
/* @__PURE__ */ jsx(Inline, { space: 1, children: segments.map((segment) => /* @__PURE__ */ jsx(
|
|
52
52
|
Button,
|
|
53
53
|
{
|
|
54
|
-
text: `Add ${
|
|
54
|
+
text: `Add ${segment.label}`,
|
|
55
55
|
mode: "ghost",
|
|
56
|
-
disabled:
|
|
57
|
-
onClick: () => handleClick(
|
|
56
|
+
disabled: usedSegments?.includes(segment.id),
|
|
57
|
+
onClick: () => handleClick(segment)
|
|
58
58
|
},
|
|
59
|
-
`${
|
|
59
|
+
`${segment.id}`
|
|
60
60
|
)) })
|
|
61
61
|
] });
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
"svg",
|
|
65
|
-
{
|
|
66
|
-
"data-sanity-icon": "close",
|
|
67
|
-
width: "1em",
|
|
68
|
-
height: "1em",
|
|
69
|
-
viewBox: "0 0 25 25",
|
|
70
|
-
fill: "none",
|
|
71
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
72
|
-
...props,
|
|
73
|
-
ref,
|
|
74
|
-
children: /* @__PURE__ */ jsx(
|
|
75
|
-
"path",
|
|
76
|
-
{
|
|
77
|
-
d: "M18 7L7 18M7 7L18 18",
|
|
78
|
-
stroke: "currentColor",
|
|
79
|
-
strokeWidth: 1.2,
|
|
80
|
-
strokeLinejoin: "round"
|
|
81
|
-
}
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
}), useAddExperimentAction = (props) => {
|
|
86
|
-
const { onChange, active, experimentNameOverride } = props, handleAddAction = useCallback(() => {
|
|
62
|
+
}, useAddExperimentAction = (props) => {
|
|
63
|
+
const { onChange, active, personalizationNameOverride } = props, handleAddAction = useCallback(() => {
|
|
87
64
|
onChange([set(!active, ["active"])]);
|
|
88
65
|
}, [onChange, active]);
|
|
89
66
|
return {
|
|
90
|
-
title: `Add ${
|
|
67
|
+
title: `Add ${personalizationNameOverride}`,
|
|
91
68
|
type: "action",
|
|
92
|
-
icon:
|
|
69
|
+
icon: IoMdPeople,
|
|
93
70
|
onAction: handleAddAction,
|
|
94
71
|
renderAsButton: !0
|
|
95
72
|
};
|
|
96
73
|
}, useRemoveExperimentAction = (props) => {
|
|
97
|
-
const { onChange, active,
|
|
98
|
-
const activeId = ["active"],
|
|
99
|
-
onChange([set(!active, activeId), unset(
|
|
100
|
-
}, [onChange, active,
|
|
74
|
+
const { onChange, active, personalizationNameOverride, segmentNameOverride } = props, handleClearAction = useCallback(() => {
|
|
75
|
+
const activeId = ["active"], segments = [`${segmentNameOverride}s`];
|
|
76
|
+
onChange([set(!active, activeId), unset(segments)]);
|
|
77
|
+
}, [onChange, active, segmentNameOverride]);
|
|
101
78
|
return {
|
|
102
|
-
title: `Remove ${
|
|
79
|
+
title: `Remove ${personalizationNameOverride}`,
|
|
103
80
|
type: "action",
|
|
104
81
|
icon: CloseIcon,
|
|
105
82
|
onAction: handleClearAction,
|
|
@@ -109,112 +86,57 @@ const ArrayInput = (props) => {
|
|
|
109
86
|
onChange,
|
|
110
87
|
inputId,
|
|
111
88
|
active,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
variantNameOverride
|
|
89
|
+
personalizationNameOverride,
|
|
90
|
+
segmentNameOverride
|
|
115
91
|
}) => {
|
|
116
92
|
const removeAction = defineDocumentFieldAction({
|
|
117
|
-
name: `Remove ${
|
|
93
|
+
name: `Remove ${personalizationNameOverride}`,
|
|
118
94
|
useAction: (props) => useRemoveExperimentAction({
|
|
119
95
|
active: !0,
|
|
120
96
|
onChange,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
variantNameOverride
|
|
97
|
+
personalizationNameOverride,
|
|
98
|
+
segmentNameOverride
|
|
124
99
|
})
|
|
125
100
|
}), addAction = defineDocumentFieldAction({
|
|
126
|
-
name: `Add ${
|
|
101
|
+
name: `Add ${personalizationNameOverride}`,
|
|
127
102
|
useAction: (props) => useAddExperimentAction({
|
|
128
103
|
active: !1,
|
|
129
104
|
onChange,
|
|
130
|
-
|
|
105
|
+
personalizationNameOverride
|
|
131
106
|
})
|
|
132
107
|
});
|
|
133
108
|
return active ? removeAction : addAction;
|
|
134
|
-
},
|
|
135
|
-
const { onChange } = props.inputProps, { inputId,
|
|
109
|
+
}, Field = (props) => {
|
|
110
|
+
const { onChange } = props.inputProps, { inputId, personalizationNameOverride, segmentNameOverride } = props, active = props.value?.active, actionProps = useMemo(
|
|
136
111
|
() => ({
|
|
137
112
|
onChange,
|
|
138
113
|
inputId,
|
|
139
114
|
active,
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
variantNameOverride
|
|
115
|
+
personalizationNameOverride,
|
|
116
|
+
segmentNameOverride
|
|
143
117
|
}),
|
|
144
|
-
[onChange, inputId, active,
|
|
118
|
+
[onChange, inputId, active, personalizationNameOverride, segmentNameOverride]
|
|
145
119
|
), memoizedActions = useMemo(() => {
|
|
146
120
|
const oldActions = props.actions || [];
|
|
147
121
|
return [createActions(actionProps), ...oldActions];
|
|
148
|
-
}, [actionProps, props.actions]),
|
|
149
|
-
()
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
)
|
|
155
|
-
return props.renderDefault(withActionProps);
|
|
156
|
-
}, Select = (props) => {
|
|
157
|
-
const {
|
|
158
|
-
value,
|
|
159
|
-
// Current field value
|
|
160
|
-
onChange,
|
|
161
|
-
// Method to handle patch events,
|
|
162
|
-
elementProps,
|
|
163
|
-
listOptions,
|
|
164
|
-
handleChange
|
|
165
|
-
} = props;
|
|
166
|
-
return /* @__PURE__ */ jsxs(
|
|
167
|
-
Select$1,
|
|
168
|
-
{
|
|
169
|
-
...elementProps,
|
|
170
|
-
fontSize: 2,
|
|
171
|
-
padding: 3,
|
|
172
|
-
space: [3, 3, 4],
|
|
173
|
-
value: value || "",
|
|
174
|
-
onChange: (event) => handleChange(event, onChange),
|
|
175
|
-
children: [
|
|
176
|
-
/* @__PURE__ */ jsx("option", { value: "", children: "Select an option..." }),
|
|
177
|
-
listOptions.map(({ value: optionValue, title }) => /* @__PURE__ */ jsx("option", { value: optionValue, children: title }, optionValue))
|
|
178
|
-
]
|
|
179
|
-
}
|
|
180
|
-
);
|
|
181
|
-
}, formatlistOptions = (experiments) => experiments.map((experiment) => ({
|
|
182
|
-
title: experiment.label,
|
|
183
|
-
value: experiment.id
|
|
184
|
-
})), ExperimentInput = (props) => {
|
|
185
|
-
const { experiments } = useExperimentContext(), id = useFormValue(["_id"]), additionalChangePath = useMemo(
|
|
186
|
-
() => [...props.path.slice(0, -1), `${props.variantNameOverride}s`],
|
|
187
|
-
[props.variantNameOverride, props.path]
|
|
188
|
-
), subValues = useFormValue(additionalChangePath), { patch } = useDocumentOperation(getPublishedId(id), props.schemaType.name), handleChange = useCallback(
|
|
189
|
-
(event, onChange) => {
|
|
190
|
-
const inputValue = event.currentTarget.value;
|
|
191
|
-
if (onChange(inputValue ? set(inputValue) : unset()), subValues) {
|
|
192
|
-
const patchEvent = {
|
|
193
|
-
unset: [additionalChangePath.join(".")]
|
|
194
|
-
};
|
|
195
|
-
patch.execute([patchEvent]);
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
[patch, subValues, additionalChangePath]
|
|
199
|
-
);
|
|
200
|
-
return experiments.length ? /* @__PURE__ */ jsx(Select, { ...props, listOptions: formatlistOptions(experiments), handleChange }) : /* @__PURE__ */ jsx(Card, { padding: [3, 3, 4], radius: 2, shadow: 1, tone: "caution", children: /* @__PURE__ */ jsxs(Text, { align: "center", size: [2, 2, 3], children: [
|
|
201
|
-
"There are no defined ",
|
|
202
|
-
props.experimentNameOverride,
|
|
203
|
-
"s"
|
|
204
|
-
] }) });
|
|
205
|
-
}, VariantInput = (props) => {
|
|
206
|
-
const defaultValue = useFormValue([props.path[0], "default"]), handleClick = () => {
|
|
122
|
+
}, [actionProps, props.actions]), enhancedProps = useMemo(() => ({
|
|
123
|
+
...clearChildrenGroups(props),
|
|
124
|
+
actions: memoizedActions
|
|
125
|
+
}), [props, memoizedActions]);
|
|
126
|
+
return props.renderDefault(enhancedProps);
|
|
127
|
+
}, SegmentInput = (props) => {
|
|
128
|
+
const personalizationPath = props.path.slice(0, -2), defaultValue = useFormValue([...personalizationPath, "default"]), handleClick = () => {
|
|
207
129
|
props.onChange(set(defaultValue, ["value"]));
|
|
208
130
|
};
|
|
209
131
|
return /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
|
|
210
132
|
props.renderDefault(props),
|
|
211
133
|
/* @__PURE__ */ jsx(Inline, { space: 1, children: /* @__PURE__ */ jsx(Button, { text: "Copy default", mode: "ghost", onClick: () => handleClick() }) })
|
|
212
134
|
] });
|
|
213
|
-
},
|
|
214
|
-
const [subtitle, setSubtitle] = useState(void 0), [title, setTitle] = useState(void 0), [media, setMedia] = useState(void 0), client = useClient({ apiVersion: "2025-01-01" }), {
|
|
135
|
+
}, SegmentPreview = (props) => {
|
|
136
|
+
const [subtitle, setSubtitle] = useState(void 0), [title, setTitle] = useState(void 0), [media, setMedia] = useState(void 0), client = useClient({ apiVersion: "2025-01-01" }), { segments } = usePersonalizationContext(), { segment, value } = props, selectedSegment = segments.find((segmentItem) => segmentItem.id === segment);
|
|
215
137
|
useEffect(() => {
|
|
216
138
|
(async () => {
|
|
217
|
-
if (setTitle(`${
|
|
139
|
+
if (setTitle(`${selectedSegment?.label}`), typeof value == "string")
|
|
218
140
|
return setSubtitle(value);
|
|
219
141
|
if (isReference(value)) {
|
|
220
142
|
const doc = await client.getDocument(value._ref), referenceType = (props.schemaType.fields.find((field) => field.name === "value")?.type).to.find((field) => field.type?.name === doc?._type), selectFields = {}, previewFields = referenceType?.preview?.select || {};
|
|
@@ -227,7 +149,7 @@ const ArrayInput = (props) => {
|
|
|
227
149
|
}
|
|
228
150
|
return isImage(value) && setMedia(value), "";
|
|
229
151
|
})();
|
|
230
|
-
}, [value, client,
|
|
152
|
+
}, [value, client, selectedSegment?.label, props.schemaType]);
|
|
231
153
|
const previewProps = {
|
|
232
154
|
...props,
|
|
233
155
|
title,
|
|
@@ -235,64 +157,59 @@ const ArrayInput = (props) => {
|
|
|
235
157
|
media
|
|
236
158
|
};
|
|
237
159
|
return props.renderDefault(previewProps);
|
|
238
|
-
}
|
|
239
|
-
function flattenSchemaType(schemaType) {
|
|
240
|
-
return isDocumentSchemaType(schemaType) ? extractInnerFields(schemaType.fields, [], 5) : (console.error("Schema type is not a document"), []);
|
|
241
|
-
}
|
|
242
|
-
function extractInnerFields(fields, path, maxDepth) {
|
|
243
|
-
return path.length >= maxDepth ? [] : fields.reduce((acc, field) => {
|
|
244
|
-
const thisFieldWithPath = { path: [...path, field.name], ...field };
|
|
245
|
-
if (field.type.jsonType === "object") {
|
|
246
|
-
const innerFields = extractInnerFields(field.type.fields, [...path, field.name], maxDepth);
|
|
247
|
-
return [...acc, thisFieldWithPath, ...innerFields];
|
|
248
|
-
} else if (field.type.jsonType === "array") {
|
|
249
|
-
const innerFields = (field.type.of || []).reduce((arrayAcc, arrayType) => {
|
|
250
|
-
if ("fields" in arrayType) {
|
|
251
|
-
const typeFields = extractInnerFields(arrayType.fields, [...path, field.name], maxDepth);
|
|
252
|
-
return [...arrayAcc, ...typeFields];
|
|
253
|
-
}
|
|
254
|
-
return arrayAcc;
|
|
255
|
-
}, []);
|
|
256
|
-
return [...acc, thisFieldWithPath, ...innerFields];
|
|
257
|
-
}
|
|
258
|
-
return [...acc, thisFieldWithPath];
|
|
259
|
-
}, []);
|
|
260
|
-
}
|
|
261
|
-
const createExperimentType = ({
|
|
160
|
+
}, createPersonalizationType = ({
|
|
262
161
|
field,
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
experimentId
|
|
162
|
+
personalizationNameOverride,
|
|
163
|
+
segmentNameOverride,
|
|
164
|
+
segmentId,
|
|
165
|
+
segmentArrayName
|
|
268
166
|
}) => {
|
|
269
|
-
const typeName = typeof field == "string" ? field : field.name, usedName = String(typeName[0]).toUpperCase() + String(typeName).slice(1),
|
|
167
|
+
const typeName = typeof field == "string" ? field : field.name, usedName = String(typeName[0]).toUpperCase() + String(typeName).slice(1), segmentName = `${segmentNameOverride}${usedName}`;
|
|
270
168
|
return defineType({
|
|
271
|
-
name: `${
|
|
169
|
+
name: `${personalizationNameOverride}${usedName}`,
|
|
272
170
|
type: "object",
|
|
171
|
+
groups: [
|
|
172
|
+
{
|
|
173
|
+
name: "default",
|
|
174
|
+
title: "Default",
|
|
175
|
+
hidden: ({ parent }) => !Array.isArray(parent)
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "personalization",
|
|
179
|
+
title: "Personalization options",
|
|
180
|
+
hidden: ({ parent }) => !Array.isArray(parent)
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "all-fields",
|
|
184
|
+
title: "All fields",
|
|
185
|
+
hidden: ({ parent }) => Array.isArray(parent)
|
|
186
|
+
}
|
|
187
|
+
],
|
|
273
188
|
components: {
|
|
274
189
|
field: (props) => /* @__PURE__ */ jsx(
|
|
275
|
-
|
|
190
|
+
Field,
|
|
276
191
|
{
|
|
277
192
|
...props,
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
variantNameOverride
|
|
193
|
+
personalizationNameOverride,
|
|
194
|
+
segmentNameOverride
|
|
281
195
|
}
|
|
282
|
-
)
|
|
196
|
+
),
|
|
197
|
+
item: ArrayItem
|
|
283
198
|
},
|
|
284
199
|
fields: [
|
|
285
200
|
typeof field == "string" ? (
|
|
286
201
|
// Define a simple field if all we have is the name as a string
|
|
287
202
|
defineField({
|
|
288
203
|
name: "default",
|
|
289
|
-
type: field
|
|
204
|
+
type: field,
|
|
205
|
+
group: "default"
|
|
290
206
|
})
|
|
291
207
|
) : (
|
|
292
208
|
// Pass in the configured options, but overwrite the name
|
|
293
209
|
{
|
|
294
210
|
...field,
|
|
295
|
-
name: "default"
|
|
211
|
+
name: "default",
|
|
212
|
+
group: "default"
|
|
296
213
|
}
|
|
297
214
|
),
|
|
298
215
|
defineField({
|
|
@@ -302,84 +219,54 @@ const createExperimentType = ({
|
|
|
302
219
|
initialValue: !1
|
|
303
220
|
}),
|
|
304
221
|
defineField({
|
|
305
|
-
name:
|
|
306
|
-
type: "string",
|
|
307
|
-
components: {
|
|
308
|
-
input: (props) => /* @__PURE__ */ jsx(
|
|
309
|
-
ExperimentInput,
|
|
310
|
-
{
|
|
311
|
-
...props,
|
|
312
|
-
experimentNameOverride,
|
|
313
|
-
variantNameOverride
|
|
314
|
-
}
|
|
315
|
-
)
|
|
316
|
-
},
|
|
317
|
-
hidden: ({ parent }) => !parent?.active
|
|
318
|
-
}),
|
|
319
|
-
defineField({
|
|
320
|
-
name: variantArrayName,
|
|
222
|
+
name: segmentArrayName,
|
|
321
223
|
type: "array",
|
|
322
|
-
hidden: ({ parent }) => !parent?.
|
|
224
|
+
hidden: ({ parent }) => !parent?.active,
|
|
225
|
+
group: "personalization",
|
|
323
226
|
components: {
|
|
324
|
-
input: (props) => /* @__PURE__ */ jsx(
|
|
325
|
-
ArrayInput,
|
|
326
|
-
{
|
|
327
|
-
...props,
|
|
328
|
-
variantName,
|
|
329
|
-
variantId,
|
|
330
|
-
experimentId
|
|
331
|
-
}
|
|
332
|
-
)
|
|
227
|
+
input: (props) => /* @__PURE__ */ jsx(ArrayInput, { ...props, segmentName, segmentId })
|
|
333
228
|
},
|
|
334
229
|
of: [
|
|
335
230
|
defineField({
|
|
336
|
-
name:
|
|
337
|
-
type:
|
|
231
|
+
name: segmentName,
|
|
232
|
+
type: segmentName
|
|
338
233
|
})
|
|
339
234
|
]
|
|
340
235
|
})
|
|
341
236
|
],
|
|
342
237
|
preview: {
|
|
343
238
|
select: {
|
|
344
|
-
base: "default"
|
|
345
|
-
experiment: experimentId
|
|
239
|
+
base: "default"
|
|
346
240
|
},
|
|
347
|
-
prepare: ({ base
|
|
348
|
-
const title = base?.title || base?.name ||
|
|
241
|
+
prepare: ({ base }) => {
|
|
242
|
+
const title = base?.title || base?.name || typeof base == "string" ? base : "", media = base?.image || base?.photo || base?.media || "";
|
|
349
243
|
return {
|
|
350
|
-
title
|
|
351
|
-
subtitle: title ? experimentTitle : "",
|
|
244
|
+
title,
|
|
352
245
|
media
|
|
353
246
|
};
|
|
354
247
|
}
|
|
355
248
|
}
|
|
356
249
|
});
|
|
357
|
-
},
|
|
250
|
+
}, createSegmentType = ({
|
|
358
251
|
field,
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
experimentId
|
|
252
|
+
segmentNameOverride,
|
|
253
|
+
segmentId
|
|
362
254
|
}) => {
|
|
363
255
|
const typeName = typeof field == "string" ? field : field.name, usedName = String(typeName[0]).toUpperCase() + String(typeName).slice(1);
|
|
364
256
|
return defineType({
|
|
365
|
-
name: `${
|
|
366
|
-
title: `${
|
|
257
|
+
name: `${segmentNameOverride}${usedName}`,
|
|
258
|
+
title: `${segmentNameOverride} array ${usedName}`,
|
|
367
259
|
type: "object",
|
|
368
260
|
components: {
|
|
369
|
-
preview:
|
|
370
|
-
input:
|
|
261
|
+
preview: SegmentPreview,
|
|
262
|
+
input: SegmentInput
|
|
371
263
|
},
|
|
372
264
|
fields: [
|
|
373
265
|
{
|
|
374
266
|
type: "string",
|
|
375
|
-
name:
|
|
267
|
+
name: segmentId,
|
|
376
268
|
readOnly: !0
|
|
377
269
|
},
|
|
378
|
-
{
|
|
379
|
-
type: "string",
|
|
380
|
-
name: experimentId,
|
|
381
|
-
hidden: !0
|
|
382
|
-
},
|
|
383
270
|
typeof field == "string" ? (
|
|
384
271
|
// Define a simple field if all we have is the name as a string
|
|
385
272
|
defineField({
|
|
@@ -398,71 +285,67 @@ const createExperimentType = ({
|
|
|
398
285
|
],
|
|
399
286
|
preview: {
|
|
400
287
|
select: {
|
|
401
|
-
|
|
402
|
-
experiment: experimentId,
|
|
288
|
+
segment: segmentId,
|
|
403
289
|
value: "value"
|
|
404
290
|
}
|
|
405
291
|
}
|
|
406
292
|
});
|
|
407
293
|
}, fieldSchema = ({
|
|
408
294
|
fields,
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
experimentId
|
|
295
|
+
personalizationNameOverride,
|
|
296
|
+
segmentNameOverride,
|
|
297
|
+
segmentId,
|
|
298
|
+
segmentArrayName
|
|
414
299
|
}) => [
|
|
300
|
+
...fields.map((field) => createSegmentType({ field, segmentNameOverride, segmentId })),
|
|
415
301
|
...fields.map(
|
|
416
|
-
(field) =>
|
|
417
|
-
),
|
|
418
|
-
...fields.map(
|
|
419
|
-
(field) => createExperimentType({
|
|
302
|
+
(field) => createPersonalizationType({
|
|
420
303
|
field,
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
experimentId
|
|
304
|
+
personalizationNameOverride,
|
|
305
|
+
segmentNameOverride,
|
|
306
|
+
segmentId,
|
|
307
|
+
segmentArrayName
|
|
426
308
|
})
|
|
427
309
|
)
|
|
428
|
-
],
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
|
|
310
|
+
], fieldLevelPersonalization = definePlugin(
|
|
311
|
+
(config) => {
|
|
312
|
+
const pluginConfig = { ...CONFIG_DEFAULT, ...config }, { fields, personalizationNameOverride, segmentNameOverride } = pluginConfig, segmentArrayName = `${segmentNameOverride}s`, segmentId = `${segmentNameOverride}Id`;
|
|
313
|
+
return {
|
|
314
|
+
name: "sanity-personalistaion-plugin-field-level-personalization",
|
|
315
|
+
schema: {
|
|
316
|
+
types: fieldSchema({
|
|
317
|
+
fields,
|
|
318
|
+
personalizationNameOverride,
|
|
319
|
+
segmentNameOverride,
|
|
320
|
+
segmentId,
|
|
321
|
+
segmentArrayName
|
|
322
|
+
})
|
|
323
|
+
},
|
|
324
|
+
form: {
|
|
325
|
+
components: {
|
|
326
|
+
input: (props) => {
|
|
327
|
+
if (!(props.id === "root" && isObjectInputProps(props)) || !flattenSchemaType(props.schemaType).some(
|
|
328
|
+
(field) => field.type.name.startsWith(personalizationNameOverride) || field.name.startsWith(personalizationNameOverride)
|
|
329
|
+
))
|
|
330
|
+
return props.renderDefault(props);
|
|
331
|
+
const providerProps = {
|
|
332
|
+
...props,
|
|
333
|
+
personalizationFieldPluginConfig: {
|
|
334
|
+
...pluginConfig,
|
|
335
|
+
segmentId,
|
|
336
|
+
segmentArrayName
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
return PersonalizationProvider(providerProps);
|
|
340
|
+
}
|
|
459
341
|
}
|
|
460
342
|
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
);
|
|
464
346
|
export {
|
|
465
347
|
fieldLevelExperiments,
|
|
348
|
+
fieldLevelPersonalization,
|
|
466
349
|
flattenSchemaType
|
|
467
350
|
};
|
|
468
351
|
//# sourceMappingURL=index.mjs.map
|