@sanity/personalization-plugin 2.1.0-growthbook.1 → 2.2.0-growthbook.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/dist/index.mjs CHANGED
@@ -9,7 +9,12 @@ import { GiSoapExperiment } from "react-icons/gi";
9
9
  import { useSecrets, SettingsView } from "@sanity/studio-secrets";
10
10
  const CONFIG_DEFAULT = {
11
11
  fields: [],
12
- apiVersion: "2024-11-07"
12
+ apiVersion: "2024-11-07",
13
+ experimentNameOverride: "experiment",
14
+ variantNameOverride: "variant",
15
+ variantId: "variantId",
16
+ variantArrayName: "variants",
17
+ experimentId: "experimentId"
13
18
  }, ExperimentContext = createContext({
14
19
  ...CONFIG_DEFAULT,
15
20
  experiments: [],
@@ -33,18 +38,18 @@ function ExperimentProvider(props) {
33
38
  return /* @__PURE__ */ jsx(ExperimentContext.Provider, { value: context, children: props.renderDefault(props) });
34
39
  }
35
40
  const ArrayInput = (props) => {
36
- const fieldPath = props.path.slice(0, -1), experimentId = useFormValue([...fieldPath, "experimentId"]), { experiments } = useExperimentContext(), { onItemAppend, objectName } = props, handleClick = useCallback(
41
+ const fieldPath = props.path.slice(0, -1), { onItemAppend, variantName, variantId, experimentId } = props, experimentValue = useFormValue([...fieldPath, experimentId]), { experiments } = useExperimentContext(), handleClick = useCallback(
37
42
  async (variant) => {
38
43
  const item = {
39
44
  _key: uuid(),
40
- variantId: variant.id,
41
- experimentId,
42
- _type: objectName
45
+ [variantId]: variant.id,
46
+ [experimentId]: experimentValue,
47
+ _type: variantName
43
48
  };
44
49
  onItemAppend(item);
45
50
  },
46
- [experimentId, objectName, onItemAppend]
47
- ), filteredVariants = experiments.find((option) => option.id === experimentId)?.variants || [], usedVariants = props.value?.map((variant) => variant.variantId);
51
+ [variantId, experimentId, experimentValue, variantName, onItemAppend]
52
+ ), filteredVariants = experiments.find((option) => option.id === experimentValue)?.variants || [], usedVariants = (props.value || [])?.map((variant) => variant[variantId]);
48
53
  return /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
49
54
  props.renderDefault({ ...props, arrayFunctions: () => null }),
50
55
  /* @__PURE__ */ jsx(Inline, { space: 1, children: filteredVariants.map((variant) => /* @__PURE__ */ jsx(
@@ -55,7 +60,7 @@ const ArrayInput = (props) => {
55
60
  disabled: usedVariants?.includes(variant.id),
56
61
  onClick: () => handleClick(variant)
57
62
  },
58
- `${experimentId}-${variant.id}`
63
+ `${experimentValue}-${variant.id}`
59
64
  )) })
60
65
  ] });
61
66
  }, AccessDeniedIcon = forwardRef(function(props, ref) {
@@ -6405,41 +6410,75 @@ const icons = {
6405
6410
  });
6406
6411
  Icon.displayName = "ForwardRef(Icon)";
6407
6412
  const useAddExperimentAction = (props) => {
6408
- const patchActiveEvent = useMemo(() => set(!0, ["active"]), []), handleAction = useCallback(() => {
6409
- props.onChange([patchActiveEvent]);
6410
- }, [patchActiveEvent, props]);
6413
+ const { onChange, active, experimentNameOverride } = props, handleAddAction = useCallback(() => {
6414
+ onChange([set(!active, ["active"])]);
6415
+ }, [onChange, active]);
6411
6416
  return {
6412
- title: "Add experiment",
6417
+ title: `Add ${experimentNameOverride}`,
6413
6418
  type: "action",
6414
6419
  icon: GiSoapExperiment,
6415
- onAction: handleAction,
6420
+ onAction: handleAddAction,
6416
6421
  renderAsButton: !0
6417
6422
  };
6418
6423
  }, useRemoveExperimentAction = (props) => {
6419
- const patchActiveEvent = useMemo(() => set(!1, ["active"]), []), patchClearEvent = useMemo(() => {
6420
- const experimentId = ["experimentId"], variants = ["variants"];
6421
- return [unset(experimentId), unset(variants)];
6422
- }, []), handleAction = useCallback(() => {
6423
- props.onChange([patchActiveEvent, ...patchClearEvent]);
6424
- }, [patchActiveEvent, patchClearEvent, props]);
6424
+ const { onChange, active, experimentId, experimentNameOverride, variantNameOverride } = props, handleClearAction = useCallback(() => {
6425
+ const activeId = ["active"], experiment = [experimentId], variants = [`${variantNameOverride}s`];
6426
+ onChange([set(!active, activeId), unset(experiment), unset(variants)]);
6427
+ }, [onChange, active, experimentId, variantNameOverride]);
6425
6428
  return {
6426
- title: "Remove experiment",
6429
+ title: `Remove ${experimentNameOverride}`,
6427
6430
  type: "action",
6428
6431
  icon: CloseIcon,
6429
- onAction: handleAction,
6432
+ onAction: handleClearAction,
6430
6433
  renderAsButton: !0
6431
6434
  };
6432
- }, newActions = ({ onChange, inputId, active }) => active ? defineDocumentFieldAction({
6433
- name: "Experiment",
6434
- useAction: (props) => useRemoveExperimentAction({ ...props, onChange, inputId })
6435
- }) : defineDocumentFieldAction({
6436
- name: "Experiment",
6437
- useAction: (props) => useAddExperimentAction({ ...props, onChange, inputId })
6438
- }), ExperimentField = (props) => {
6439
- const { onChange } = props.inputProps, { inputId } = props, active = props.value?.active, oldActions = props.actions || [], withActionProps = {
6440
- ...props,
6441
- actions: [newActions({ onChange, inputId, active }), ...oldActions]
6442
- };
6435
+ }, createActions = ({
6436
+ onChange,
6437
+ inputId,
6438
+ active,
6439
+ experimentNameOverride,
6440
+ experimentId,
6441
+ variantNameOverride
6442
+ }) => {
6443
+ const removeAction = defineDocumentFieldAction({
6444
+ name: `Remove ${experimentNameOverride}`,
6445
+ useAction: (props) => useRemoveExperimentAction({
6446
+ active: !0,
6447
+ onChange,
6448
+ experimentNameOverride,
6449
+ experimentId,
6450
+ variantNameOverride
6451
+ })
6452
+ }), addAction = defineDocumentFieldAction({
6453
+ name: `Add ${experimentNameOverride}`,
6454
+ useAction: (props) => useAddExperimentAction({
6455
+ active: !1,
6456
+ onChange,
6457
+ experimentNameOverride
6458
+ })
6459
+ });
6460
+ return active ? removeAction : addAction;
6461
+ }, ExperimentField = (props) => {
6462
+ const { onChange } = props.inputProps, { inputId, experimentNameOverride, experimentId, variantNameOverride } = props, active = props.value?.active, actionProps = useMemo(
6463
+ () => ({
6464
+ onChange,
6465
+ inputId,
6466
+ active,
6467
+ experimentNameOverride,
6468
+ experimentId,
6469
+ variantNameOverride
6470
+ }),
6471
+ [onChange, inputId, active, experimentNameOverride, experimentId, variantNameOverride]
6472
+ ), memoizedActions = useMemo(() => {
6473
+ const oldActions = props.actions || [];
6474
+ return [createActions(actionProps), ...oldActions];
6475
+ }, [actionProps, props.actions]), withActionProps = useMemo(
6476
+ () => ({
6477
+ ...props,
6478
+ actions: memoizedActions
6479
+ }),
6480
+ [props, memoizedActions]
6481
+ );
6443
6482
  return props.renderDefault(withActionProps);
6444
6483
  }, Select = (props) => {
6445
6484
  const {
@@ -6470,7 +6509,10 @@ const useAddExperimentAction = (props) => {
6470
6509
  title: experiment.label,
6471
6510
  value: experiment.id
6472
6511
  })), ExperimentInput = (props) => {
6473
- const { experiments } = useExperimentContext(), id = useFormValue(["_id"]), aditionalChangePath = useMemo(() => [...props.path.slice(0, -1), "variants"], [props.path]), subValues = useFormValue(aditionalChangePath), { patch } = useDocumentOperation(id.replace("drafts.", ""), props.schemaType.name), handleChange = useCallback(
6512
+ const { experiments } = useExperimentContext(), id = useFormValue(["_id"]), aditionalChangePath = useMemo(
6513
+ () => [...props.path.slice(0, -1), `${props.variantNameOverride}s`],
6514
+ [props.variantNameOverride, props.path]
6515
+ ), subValues = useFormValue(aditionalChangePath), { patch } = useDocumentOperation(id.replace("drafts.", ""), props.schemaType.name), handleChange = useCallback(
6474
6516
  (event, onChange) => {
6475
6517
  const inputValue = event.currentTarget.value;
6476
6518
  if (onChange(inputValue ? set(inputValue) : unset()), subValues) {
@@ -6483,6 +6525,14 @@ const useAddExperimentAction = (props) => {
6483
6525
  [patch, subValues, aditionalChangePath]
6484
6526
  );
6485
6527
  return experiments.length ? /* @__PURE__ */ jsx(Select, { ...props, listOptions: formatlistOptions(experiments), handleChange }) : /* @__PURE__ */ jsx(Fragment, {});
6528
+ }, VariantInput = (props) => {
6529
+ const defaultValue = useFormValue([props.path[0], "default"]), handleClick = () => {
6530
+ props.onChange(set(defaultValue, ["value"]));
6531
+ };
6532
+ return /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
6533
+ props.renderDefault(props),
6534
+ /* @__PURE__ */ jsx(Inline, { space: 1, children: /* @__PURE__ */ jsx(Button, { text: "Copy default", mode: "ghost", onClick: () => handleClick() }) })
6535
+ ] });
6486
6536
  }, VariantPreview = (props) => {
6487
6537
  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);
6488
6538
  useEffect(() => {
@@ -6530,15 +6580,28 @@ function extractInnerFields(fields, path, maxDepth) {
6530
6580
  return [...acc, thisFieldWithPath];
6531
6581
  }, []);
6532
6582
  }
6533
- const createFieldType = ({
6534
- field
6583
+ const createExperimentType = ({
6584
+ field,
6585
+ experimentNameOverride,
6586
+ variantNameOverride,
6587
+ variantId,
6588
+ variantArrayName,
6589
+ experimentId
6535
6590
  }) => {
6536
- const typeName = typeof field == "string" ? field : field.name, usedName = String(typeName[0]).toUpperCase() + String(typeName).slice(1), objectName = `variant${usedName}`;
6591
+ const typeName = typeof field == "string" ? field : field.name, usedName = String(typeName[0]).toUpperCase() + String(typeName).slice(1), variantName = `${variantNameOverride}${usedName}`;
6537
6592
  return defineType({
6538
- name: `experiment${usedName}`,
6593
+ name: `${experimentNameOverride}${usedName}`,
6539
6594
  type: "object",
6540
6595
  components: {
6541
- field: ExperimentField
6596
+ field: (props) => /* @__PURE__ */ jsx(
6597
+ ExperimentField,
6598
+ {
6599
+ ...props,
6600
+ experimentId,
6601
+ experimentNameOverride,
6602
+ variantNameOverride
6603
+ }
6604
+ )
6542
6605
  },
6543
6606
  fields: [
6544
6607
  typeof field == "string" ? (
@@ -6560,94 +6623,140 @@ const createFieldType = ({
6560
6623
  hidden: !0
6561
6624
  }),
6562
6625
  defineField({
6563
- title: "Experiment",
6564
- name: "experimentId",
6626
+ name: experimentId,
6565
6627
  type: "string",
6566
6628
  components: {
6567
- input: ExperimentInput
6629
+ input: (props) => /* @__PURE__ */ jsx(ExperimentInput, { ...props, variantNameOverride })
6568
6630
  },
6569
6631
  hidden: ({ parent }) => !parent?.active
6570
6632
  }),
6571
6633
  defineField({
6572
- name: "variants",
6634
+ name: variantArrayName,
6573
6635
  type: "array",
6574
- hidden: ({ parent }) => !parent?.experimentId,
6636
+ hidden: ({ parent }) => !parent?.[experimentId],
6575
6637
  components: {
6576
- input: (props) => /* @__PURE__ */ jsx(ArrayInput, { ...props, objectName })
6638
+ input: (props) => /* @__PURE__ */ jsx(
6639
+ ArrayInput,
6640
+ {
6641
+ ...props,
6642
+ variantName,
6643
+ variantId,
6644
+ experimentId
6645
+ }
6646
+ )
6577
6647
  },
6578
6648
  of: [
6579
6649
  defineField({
6580
- name: objectName,
6581
- type: objectName
6650
+ name: variantName,
6651
+ type: variantName
6582
6652
  })
6583
6653
  ]
6584
6654
  })
6585
6655
  ]
6586
6656
  });
6587
- }, createFieldObjectType = ({
6588
- field
6657
+ }, createVariantType = ({
6658
+ field,
6659
+ variantNameOverride,
6660
+ variantId,
6661
+ experimentId
6589
6662
  }) => {
6590
6663
  const typeName = typeof field == "string" ? field : field.name, usedName = String(typeName[0]).toUpperCase() + String(typeName).slice(1);
6591
6664
  return defineType({
6592
- name: `variant${usedName}`,
6593
- title: `Experiment array ${usedName}`,
6665
+ name: `${variantNameOverride}${usedName}`,
6666
+ title: `${variantNameOverride} array ${usedName}`,
6594
6667
  type: "object",
6595
6668
  components: {
6596
- preview: VariantPreview
6669
+ preview: VariantPreview,
6670
+ input: VariantInput
6597
6671
  },
6598
6672
  fields: [
6599
6673
  {
6600
6674
  type: "string",
6601
- name: "variantId",
6675
+ name: variantId,
6602
6676
  readOnly: !0
6603
6677
  },
6604
6678
  {
6605
6679
  type: "string",
6606
- name: "experimentId",
6680
+ name: experimentId,
6607
6681
  hidden: !0
6608
6682
  },
6609
6683
  typeof field == "string" ? (
6610
6684
  // Define a simple field if all we have is the name as a string
6611
6685
  defineField({
6612
6686
  name: "value",
6613
- type: field,
6614
- hidden: ({ parent }) => !parent?.variantId
6687
+ type: field
6688
+ // hidden: ({parent}) => !parent?.[`${objectNameOverride}Id`],
6615
6689
  })
6616
6690
  ) : (
6617
6691
  // Pass in the configured options, but overwrite the name
6618
6692
  {
6619
6693
  ...field,
6620
- name: "value",
6621
- hidden: ({ parent }) => !parent?.variantId
6694
+ name: "value"
6695
+ // hidden: ({parent}) => !parent?.[`${objectNameOverride}Id`],
6622
6696
  }
6623
6697
  )
6624
6698
  ],
6625
6699
  preview: {
6626
6700
  select: {
6627
- variant: "variantId",
6628
- experiment: "experimentId",
6701
+ variant: variantId,
6702
+ experiment: experimentId,
6629
6703
  value: "value"
6630
6704
  }
6631
6705
  }
6632
6706
  });
6633
- }, fieldSchema = ({ fields, experiments }) => [
6634
- ...fields.map((field) => createFieldObjectType({ field })),
6635
- ...fields.map((field) => createFieldType({ field }))
6707
+ }, fieldSchema = ({
6708
+ fields,
6709
+ experimentNameOverride,
6710
+ variantNameOverride,
6711
+ variantId,
6712
+ variantArrayName,
6713
+ experimentId
6714
+ }) => [
6715
+ ...fields.map(
6716
+ (field) => createVariantType({ field, variantNameOverride, variantId, experimentId })
6717
+ ),
6718
+ ...fields.map(
6719
+ (field) => createExperimentType({
6720
+ field,
6721
+ experimentNameOverride,
6722
+ variantNameOverride,
6723
+ variantId,
6724
+ variantArrayName,
6725
+ experimentId
6726
+ })
6727
+ )
6636
6728
  ], fieldLevelExperiments = definePlugin((config) => {
6637
- const pluginConfig = { ...CONFIG_DEFAULT, ...config }, { fields, experiments } = pluginConfig;
6729
+ const pluginConfig = { ...CONFIG_DEFAULT, ...config }, { fields, experimentNameOverride, variantNameOverride } = pluginConfig, experimentId = `${experimentNameOverride}Id`, variantArrayName = `${variantNameOverride}s`, variantId = `${variantNameOverride}Id`;
6638
6730
  return {
6639
6731
  name: "sanity-personalistaion-plugin-field-level-experiments",
6640
6732
  schema: {
6641
- types: fieldSchema({ fields, experiments })
6733
+ types: fieldSchema({
6734
+ fields,
6735
+ experimentNameOverride,
6736
+ variantNameOverride,
6737
+ variantId,
6738
+ variantArrayName,
6739
+ experimentId
6740
+ })
6642
6741
  },
6643
6742
  form: {
6644
6743
  components: {
6645
6744
  input: (props) => {
6646
6745
  if (!(props.id === "root" && isObjectInputProps(props)) || !flattenSchemaType(props.schemaType).map(
6647
6746
  (field) => field.type.name
6648
- ).some((name) => name.startsWith("experiment")))
6747
+ ).some(
6748
+ (name) => name.startsWith(experimentNameOverride)
6749
+ ))
6649
6750
  return props.renderDefault(props);
6650
- const providerProps = { ...props, experimentFieldPluginConfig: pluginConfig };
6751
+ const providerProps = {
6752
+ ...props,
6753
+ experimentFieldPluginConfig: {
6754
+ ...pluginConfig,
6755
+ variantId,
6756
+ variantArrayName,
6757
+ experimentId
6758
+ }
6759
+ };
6651
6760
  return ExperimentProvider(providerProps);
6652
6761
  }
6653
6762
  }