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