@sanity/personalization-plugin
3.1.63.1.7
~
Modified (5 files)
Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
{
"name": "@sanity/personalization-plugin",
- "version": "3.1.6",
+ "version": "3.1.7",
"description": "Plugin to help with personalization, a/b testing when using Sanity",
"keywords": [
"sanity",
"sanity-plugin"
@@ -28,25 +28,25 @@
"./launchDarkly": "./dist/launchDarkly/index.js",
"./package.json": "./package.json"
},
"dependencies": {
- "@sanity/icons": "^5.2.1",
- "@sanity/ui": "^4.0.7",
+ "@sanity/icons": "^5.2.2",
+ "@sanity/studio-secrets": "^4.0.20",
+ "@sanity/ui": "^4.2.7",
"@sanity/uuid": "^3.0.3",
"dequal": "^2.0.3",
"react-icons": "^5.7.0",
- "suspend-react": "^0.1.3",
- "@sanity/studio-secrets": "^4.0.19"
+ "suspend-react": "^0.1.3"
},
"devDependencies": {
"@sanity/tsconfig": "^2.2.1",
"@sanity/tsdown-config": "^0.27.1",
- "@types/react": "^19.2.18",
- "@types/react-dom": "^19.2.4",
+ "@types/react": "^19.3.0",
+ "@types/react-dom": "^19.3.0",
"oxc-transform-react": "^0.147.0",
- "react": "^19.2.8",
- "react-dom": "^19.2.8",
- "sanity": "^6.11.0",
+ "react": "^19.3.0",
+ "react-dom": "^19.3.0",
+ "sanity": "^6.16.0",
"tsdown": "^0.22.14"
},
"peerDependencies": {
"react": "^19.2", Index: package/dist/fieldExperiments-DmD8mnlU.js.map
===================================================================
--- package/dist/fieldExperiments-DmD8mnlU.js.map
+++ package/dist/fieldExperiments-DmD8mnlU.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"fieldExperiments-DmD8mnlU.js","names":["() => {\n if (!active) {\n onChange(set(true, ['active']))\n }\n }","[active, onChange]","props.renderDefault(props)","props.renderDefault","{apiVersion: experimentFieldPluginConfig.apiVersion}","apiVersion","Array.isArray(experimentFieldPluginConfig.experiments)\n ? experimentFieldPluginConfig.experiments\n : suspend(\n async () => {\n if (typeof experimentFieldPluginConfig.experiments === 'function') {\n return experimentFieldPluginConfig.experiments(client)\n }\n return experimentFieldPluginConfig.experiments\n },\n [workspace, 'field-level-experiments'],\n {equal},\n )","experimentFieldPluginConfig.experiments","{...experimentFieldPluginConfig, experiments}","useMemo(\n () => ({...experimentFieldPluginConfig, experiments}),\n [experimentFieldPluginConfig, experiments],\n )","props.renderDefault(props)","props.renderDefault","<ExperimentContext.Provider value={context}>\n {props.renderDefault(props)}\n </ExperimentContext.Provider>","ExperimentContext.Provider","useFormValue","[...fieldPath, experimentId]","props.path","async (variant: VariantType) => {\n const item = {\n _key: uuid(),\n [variantId]: variant.id,\n [experimentId]: experimentValue,\n _type: variantName,\n }\n\n // Patch the document\n onItemAppend(item)\n }","useCallback(\n async (variant: VariantType) => {\n const item = {\n _key: uuid(),\n [variantId]: variant.id,\n [experimentId]: experimentValue,\n _type: variantName,\n }\n\n // Patch the document\n onItemAppend(item)\n },\n [variantId, experimentId, experimentValue, variantName, onItemAppend],\n )","Inline","Stack","1","filteredVariants.map((variant) => {\n return (\n <Button\n key={`${experimentValue}-${variant.id}`}\n text={`Add ${variant.label}`}\n mode=\"ghost\"\n disabled={usedVariants?.includes(variant.id)}\n onClick={() => handleClick(variant)}\n />\n )\n })","3","props.renderDefault({...props, arrayFunctions: () => null})","props.value","(props.value as Value[]) || []","value","variant","() => null","<Inline gap={1}>\n {filteredVariants.map((variant) => {\n return (\n <Button\n key={`${experimentValue}-${variant.id}`}\n text={`Add ${variant.label}`}\n mode=\"ghost\"\n disabled={usedVariants?.includes(variant.id)}\n onClick={() => handleClick(variant)}\n />\n )\n })}\n </Inline>","<Stack gap={3}>\n {props.renderDefault({...props, arrayFunctions: () => null})}\n\n <Inline gap={1}>\n {filteredVariants.map((variant) => {\n return (\n <Button\n key={`${experimentValue}-${variant.id}`}\n text={`Add ${variant.label}`}\n mode=\"ghost\"\n disabled={usedVariants?.includes(variant.id)}\n onClick={() => handleClick(variant)}\n />\n )\n })}\n </Inline>\n </Stack>","() => {\n onChange([set(!active, ['active'])])\n }","useCallback(() => {\n onChange([set(!active, ['active'])])\n }, [onChange, active])","{\n title: `Add ${experimentNameOverride}`,\n type: 'action',\n icon: GiSoapExperiment,\n onAction: handleAddAction,\n renderAsButton: true,\n }","`Add ${experimentNameOverride}`","() => {\n const activeId = ['active']\n const experiment = [experimentId]\n const variants = [`${variantNameOverride}s`]\n onChange([set(!active, activeId), unset(experiment), unset(variants)])\n }","useCallback(() => {\n const activeId = ['active']\n const experiment = [experimentId]\n const variants = [`${variantNameOverride}s`]\n onChange([set(!active, activeId), unset(experiment), unset(variants)])\n }, [onChange, active, experimentId, variantNameOverride])","{\n title: `Remove ${experimentNameOverride}`,\n type: 'action',\n icon: CloseIcon,\n onAction: handleClearAction,\n renderAsButton: true,\n }","`Remove ${experimentNameOverride}`","{\n onChange,\n inputId,\n active,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n }","useMemo(\n () => ({\n onChange,\n inputId,\n active,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n }),\n [onChange, inputId, active, experimentNameOverride, experimentId, variantNameOverride],\n )","props.actions || []","actions","createActions(actionProps)","[createActions(actionProps), ...oldActions]","useMemo(() => {\n const oldActions = props.actions || []\n return [createActions(actionProps), ...oldActions]\n }, [actionProps, props.actions])","clearChildrenGroups(props)","{\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }","useMemo(() => {\n const propsWithClearedGroups = clearChildrenGroups(props)\n return {\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }\n }, [props, memoizedActions])","props.renderDefault(enhancedProps)","renderDefault","[3, 3, 4]","(event) => handleChange(event, onChange)","<option value={''}>{'Select an option...'}</option>","listOptions.map(({value: optionValue, title}) => (\n <option key={optionValue} value={optionValue}>\n {title}\n </option>\n ))","({value: optionValue, title}) => (\n <option key={optionValue} value={optionValue}>\n {title}\n </option>\n )","<SanitySelect\n {...elementProps}\n fontSize={2}\n padding={3}\n gap={[3, 3, 4]}\n value={value || ''} // Current field value\n onChange={(event) => handleChange(event, onChange)} // A function to call when the input value changes\n >\n <option value={''}>{'Select an option...'}</option>\n {listOptions.map(({value: optionValue, title}) => (\n <option key={optionValue} value={optionValue}>\n {title}\n </option>\n ))}\n </SanitySelect>","value || ''","{value: optionValue, title}","['_id']","[...props.path.slice(0, -1), `${props.variantNameOverride}s`]","path","variantNameOverride","useMemo(\n () => [...props.path.slice(0, -1), `${props.variantNameOverride}s`],\n [props.variantNameOverride, props.path],\n )","getPublishedId(id)","(\n event: ChangeEvent<HTMLSelectElement>,\n onChange: (patchchange: FormPatch | FormPatch[] | PatchEvent) => void,\n ) => {\n const inputValue = event.currentTarget.value\n\n if (inputValue) {\n onChange(set(inputValue))\n } else {\n onChange(unset())\n }\n\n if (subValues) {\n const patchEvent = {\n unset: [additionalChangePath.join('.')],\n }\n patch.execute([patchEvent])\n }\n }","useCallback(\n (\n event: ChangeEvent<HTMLSelectElement>,\n onChange: (patchchange: FormPatch | FormPatch[] | PatchEvent) => void,\n ) => {\n const inputValue = event.currentTarget.value\n\n if (inputValue) {\n onChange(set(inputValue))\n } else {\n onChange(unset())\n }\n\n if (subValues) {\n const patchEvent = {\n unset: [additionalChangePath.join('.')],\n }\n patch.execute([patchEvent])\n }\n },\n [patch, subValues, additionalChangePath],\n )","[3, 3, 4]","[2, 2, 3]","<Card padding={[3, 3, 4]} radius={2} shadow={1} tone=\"caution\">\n <Text align=\"center\" size={[2, 2, 3]}>\n There are no defined {props.experimentNameOverride}s\n </Text>\n </Card>","experimentNameOverride","formatlistOptions(experiments)","<Select {...props} listOptions={formatlistOptions(experiments)} handleChange={handleChange} />","useFormValue","[...experimentPath, 'default']","path","() => {\n props.onChange(set(defaultValue, ['value']))\n }","props.renderDefault(props)","props.renderDefault","<Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>","<Stack gap={3}>\n {props.renderDefault(props)}\n\n <Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>\n </Stack>","{apiVersion}","selectedExperiment?.variants.find((variantItem) => {\n return variantItem.id === variant\n })","(experimentItem) => {\n return experimentItem.id === experiment\n }","() => {\n const getSubtitle = async () => {\n setTitle(\n selectedExperiment?.label && selectedVariant?.label\n ? `${selectedExperiment.label} - ${selectedVariant.label}`\n : selectedExperiment?.label || selectedVariant?.label,\n )\n if (typeof value === 'string') {\n return setSubtitle(value)\n }\n if (isReference(value)) {\n const doc = await client.getDocument(value._ref)\n const type = props.schemaType as ObjectSchemaType\n const valueField = type.fields.find((field) => field.name === 'value') as ObjectSchemaType\n const referenceField = valueField?.type as ReferenceSchemaType\n const referenceType = referenceField.to.find((field) => field.type?.name === doc?._type)\n\n const selectFields = {} as Record<string, unknown>\n const previewFields = referenceType?.preview?.select || {}\n Object.keys(previewFields).forEach((key) => {\n const valueKey = referenceType?.preview?.select?.[key]\n selectFields[key] =\n valueKey && doc\n ? valueKey.split('.').reduce((acc: any, index) => acc?.[index], doc)\n : undefined\n })\n\n const previewContent = referenceType?.preview?.prepare?.(selectFields)\n setMedia(previewContent?.media || selectFields['media'])\n return setSubtitle(previewContent?.title || (selectFields['title'] as string))\n }\n if (isImage(value)) {\n setMedia(value)\n }\n return ''\n }\n void getSubtitle()\n }","schemaType","selectedExperiment?.label","selectedVariant?.label","(field) => field.name === 'value'","field","(acc: any, index) => acc?.[index]","[value, client, selectedExperiment?.label, selectedVariant?.label, props.schemaType]","props.renderDefault(previewProps)"],"sources":["../src/components/ArrayItem.tsx","../src/components/experiment/Context.tsx","../src/components/experiment/Array.tsx","../src/utils/clearChildGroups.ts","../src/components/experiment/Field.tsx","../src/components/Select.tsx","../src/components/experiment/Input.tsx","../src/components/experiment/VariantInput.tsx","../src/components/experiment/VariantPreview.tsx","../src/utils/flattenSchemaType.ts","../src/fieldExperiments.tsx"],"sourcesContent":["import {useEffect} from 'react'\nimport {type ObjectItem, type ObjectItemProps, set} from 'sanity'\n\nexport const ArrayItem = (props: ObjectItemProps) => {\n const {active} = props.value as ObjectItem & {active: boolean}\n const {onChange} = props.inputProps\n\n useEffect(() => {\n if (!active) {\n onChange(set(true, ['active']))\n }\n }, [active, onChange])\n\n return props.renderDefault(props)\n}\n","import {dequal as equal} from 'dequal/lite'\nimport {createContext, useContext, useMemo} from 'react'\nimport {type ObjectInputProps, useClient, useWorkspace} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport type {ExperimentContextProps, ExperimentFieldPluginConfig} from '../../types'\n\n// This provider makes the plugin config available to all components in the document form\n// But with experiments resolved\n\nexport const CONFIG_DEFAULT = {\n fields: [],\n apiVersion: '2024-11-07',\n experimentNameOverride: 'experiment',\n variantNameOverride: 'variant',\n variantId: 'variantId',\n variantArrayName: 'variants',\n experimentId: 'experimentId',\n}\n\nconst ExperimentContext = createContext<ExperimentContextProps>({\n ...CONFIG_DEFAULT,\n experiments: [],\n})\n\nexport function useExperimentContext() {\n return useContext(ExperimentContext)\n}\n\ntype ExperimentProps = ObjectInputProps & {\n experimentFieldPluginConfig: Required<ExperimentFieldPluginConfig>\n}\n\nexport function ExperimentProvider(props: ExperimentProps) {\n const {experimentFieldPluginConfig} = props\n\n const client = useClient({apiVersion: experimentFieldPluginConfig.apiVersion})\n const workspace = useWorkspace()\n\n // Fetch or return experiments\n const experiments = Array.isArray(experimentFieldPluginConfig.experiments)\n ? experimentFieldPluginConfig.experiments\n : suspend(\n async () => {\n if (typeof experimentFieldPluginConfig.experiments === 'function') {\n return experimentFieldPluginConfig.experiments(client)\n }\n return experimentFieldPluginConfig.experiments\n },\n [workspace, 'field-level-experiments'],\n {equal},\n )\n\n const context = useMemo(\n () => ({...experimentFieldPluginConfig, experiments}),\n [experimentFieldPluginConfig, experiments],\n )\n\n return (\n <ExperimentContext.Provider value={context}>\n {props.renderDefault(props)}\n </ExperimentContext.Provider>\n )\n}\n","import {Button, Inline, Stack} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {useCallback} from 'react'\nimport {useFormValue} from 'sanity'\n\nimport type {ArrayInputProps, VariantType} from '../../types'\nimport {useExperimentContext} from './Context'\n\nexport const ArrayInput = (props: ArrayInputProps) => {\n const fieldPath = props.path.slice(0, -1)\n const {onItemAppend, variantName, variantId, experimentId} = props\n const experimentValue = useFormValue([...fieldPath, experimentId])\n\n const {experiments} = useExperimentContext()\n\n const handleClick = useCallback(\n async (variant: VariantType) => {\n const item = {\n _key: uuid(),\n [variantId]: variant.id,\n [experimentId]: experimentValue,\n _type: variantName,\n }\n\n // Patch the document\n onItemAppend(item)\n },\n [variantId, experimentId, experimentValue, variantName, onItemAppend],\n )\n\n const filteredVariants =\n experiments.find((option) => {\n return option.id === experimentValue\n })?.variants || []\n\n type Value = {\n value?: unknown\n [key: string]: unknown\n variantId: string\n _key: string\n _type: string\n }\n\n // there is probably some better was of getting the type of this?\n const values = (props.value as Value[]) || []\n\n const usedVariants = values?.map((variant) => variant[variantId])\n\n return (\n <Stack gap={3}>\n {props.renderDefault({...props, arrayFunctions: () => null})}\n\n <Inline gap={1}>\n {filteredVariants.map((variant) => {\n return (\n <Button\n key={`${experimentValue}-${variant.id}`}\n text={`Add ${variant.label}`}\n mode=\"ghost\"\n disabled={usedVariants?.includes(variant.id)}\n onClick={() => handleClick(variant)}\n />\n )\n })}\n </Inline>\n </Stack>\n )\n}\n","import type {ObjectFieldProps} from 'sanity'\n\n/**\n * Safely updates deeply nested children props to clear groups array\n * This prevents field grouping UI conflicts in personalization mode\n */\nexport const clearChildrenGroups = (props: ObjectFieldProps): ObjectFieldProps => {\n // Type assertion is needed here because Sanity's ObjectFieldProps children\n // typing doesn't account for the nested structure we need to manipulate\n const children = props.children as any\n\n if (!children || typeof children !== 'object' || !children.props) {\n return props\n }\n\n const innerChild = children.props.children\n if (\n !innerChild ||\n typeof innerChild !== 'object' ||\n Array.isArray(innerChild) ||\n !('props' in innerChild)\n ) {\n return props\n }\n\n return {\n ...props,\n children: {\n ...children,\n props: {\n ...children.props,\n children: {\n ...innerChild,\n props: {\n ...innerChild.props,\n groups: [],\n },\n },\n },\n },\n }\n}\n","import {CloseIcon} from '@sanity/icons/Close'\nimport {useCallback, useMemo} from 'react'\nimport {GiSoapExperiment} from 'react-icons/gi'\nimport {\n defineDocumentFieldAction,\n type DocumentFieldActionItem,\n type DocumentFieldActionProps,\n type FormPatch,\n type ObjectFieldProps,\n type PatchEvent,\n set,\n unset,\n} from 'sanity'\n\nimport {clearChildrenGroups} from '../../utils/clearChildGroups'\n\ntype PatchStuff = {onChange: (patch: FormPatch | FormPatch[] | PatchEvent) => void; inputId: string}\n\nconst useAddExperimentAction = (\n props: DocumentFieldActionProps &\n PatchStuff & {experimentNameOverride: string; experimentId: string; active: boolean},\n): DocumentFieldActionItem => {\n const {onChange, active, experimentNameOverride} = props\n\n const handleAddAction = useCallback(() => {\n onChange([set(!active, ['active'])])\n }, [onChange, active])\n\n return {\n title: `Add ${experimentNameOverride}`,\n type: 'action',\n icon: GiSoapExperiment,\n onAction: handleAddAction,\n renderAsButton: true,\n }\n}\n\nconst useRemoveExperimentAction = (\n props: DocumentFieldActionProps &\n PatchStuff & {\n experimentNameOverride: string\n experimentId: string\n active: boolean\n variantNameOverride: string\n },\n): DocumentFieldActionItem => {\n const {onChange, active, experimentId, experimentNameOverride, variantNameOverride} = props\n const handleClearAction = useCallback(() => {\n const activeId = ['active']\n const experiment = [experimentId]\n const variants = [`${variantNameOverride}s`]\n onChange([set(!active, activeId), unset(experiment), unset(variants)])\n }, [onChange, active, experimentId, variantNameOverride])\n\n return {\n title: `Remove ${experimentNameOverride}`,\n type: 'action',\n icon: CloseIcon,\n onAction: handleClearAction,\n renderAsButton: true,\n }\n}\n\nconst createActions = ({\n onChange,\n inputId,\n active,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n}: PatchStuff & {\n active?: boolean\n experimentNameOverride: string\n experimentId: string\n variantNameOverride: string\n}) => {\n const removeAction = defineDocumentFieldAction({\n name: `Remove ${experimentNameOverride}`,\n useAction: (props) =>\n useRemoveExperimentAction({\n ...props,\n active: true,\n onChange,\n inputId,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n }),\n })\n const addAction = defineDocumentFieldAction({\n name: `Add ${experimentNameOverride}`,\n useAction: (props) =>\n useAddExperimentAction({\n ...props,\n active: false,\n onChange,\n inputId,\n experimentNameOverride,\n experimentId,\n }),\n })\n return active ? removeAction : addAction\n}\n\nexport const Field = (\n props: ObjectFieldProps & {\n experimentNameOverride: string\n experimentId: string\n variantNameOverride: string\n },\n) => {\n const {onChange} = props.inputProps\n const {inputId, experimentNameOverride, experimentId, variantNameOverride} = props\n const active = props.value?.['active'] as boolean | undefined\n\n const actionProps = useMemo(\n () => ({\n onChange,\n inputId,\n active,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n }),\n [onChange, inputId, active, experimentNameOverride, experimentId, variantNameOverride],\n )\n\n const memoizedActions = useMemo(() => {\n const oldActions = props.actions || []\n return [createActions(actionProps), ...oldActions]\n }, [actionProps, props.actions])\n\n const enhancedProps = useMemo(() => {\n const propsWithClearedGroups = clearChildrenGroups(props)\n return {\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }\n }, [props, memoizedActions])\n\n return props.renderDefault(enhancedProps)\n}\n","import {Select as SanitySelect} from '@sanity/ui'\nimport type {ChangeEvent} from 'react'\nimport type {FormPatch, PatchEvent, StringInputProps} from 'sanity'\n\nimport type {SelectOption} from './experiment/Input'\n\nexport const Select = (\n props: StringInputProps & {\n listOptions: SelectOption[]\n handleChange: (\n event: ChangeEvent<HTMLSelectElement>,\n onChange: (patch: FormPatch | FormPatch[] | PatchEvent) => void,\n ) => void\n },\n) => {\n const {\n value, // Current field value\n onChange, // Method to handle patch events,\n elementProps,\n listOptions,\n handleChange,\n } = props\n\n return (\n <SanitySelect\n {...elementProps}\n fontSize={2}\n padding={3}\n gap={[3, 3, 4]}\n value={value || ''} // Current field value\n onChange={(event) => handleChange(event, onChange)} // A function to call when the input value changes\n >\n <option value={''}>{'Select an option...'}</option>\n {listOptions.map(({value: optionValue, title}) => (\n <option key={optionValue} value={optionValue}>\n {title}\n </option>\n ))}\n </SanitySelect>\n )\n}\n","import {Card, Text} from '@sanity/ui'\nimport {type ChangeEvent, useCallback, useMemo} from 'react'\nimport {\n type FormPatch,\n getPublishedId,\n type PatchEvent,\n set,\n type StringInputProps,\n unset,\n useDocumentOperation,\n useFormValue,\n} from 'sanity'\n\nimport type {ExperimentType} from '../..'\nimport {Select} from '../Select'\nimport {useExperimentContext} from './Context'\n\nexport type SelectOption = {title: string; value: string}\nconst formatlistOptions = (experiments: ExperimentType[]): SelectOption[] =>\n experiments.map((experiment) => ({\n title: experiment.label,\n value: experiment.id,\n }))\n\nexport const Input = (\n props: StringInputProps & {variantNameOverride: string; experimentNameOverride: string},\n) => {\n const {experiments} = useExperimentContext()\n\n const id = useFormValue(['_id']) as string\n const additionalChangePath = useMemo(\n () => [...props.path.slice(0, -1), `${props.variantNameOverride}s`],\n [props.variantNameOverride, props.path],\n )\n const subValues = useFormValue(additionalChangePath)\n\n const {patch} = useDocumentOperation(getPublishedId(id), props.schemaType.name)\n\n const handleChange = useCallback(\n (\n event: ChangeEvent<HTMLSelectElement>,\n onChange: (patchchange: FormPatch | FormPatch[] | PatchEvent) => void,\n ) => {\n const inputValue = event.currentTarget.value\n\n if (inputValue) {\n onChange(set(inputValue))\n } else {\n onChange(unset())\n }\n\n if (subValues) {\n const patchEvent = {\n unset: [additionalChangePath.join('.')],\n }\n patch.execute([patchEvent])\n }\n },\n [patch, subValues, additionalChangePath],\n )\n\n if (!experiments.length)\n return (\n <Card padding={[3, 3, 4]} radius={2} shadow={1} tone=\"caution\">\n <Text align=\"center\" size={[2, 2, 3]}>\n There are no defined {props.experimentNameOverride}s\n </Text>\n </Card>\n )\n\n return (\n <Select {...props} listOptions={formatlistOptions(experiments)} handleChange={handleChange} />\n )\n}\n","import {Button, Inline, Stack} from '@sanity/ui'\nimport {type ObjectInputProps, set, useFormValue} from 'sanity'\n\nexport const VariantInput = (props: ObjectInputProps) => {\n const experimentPath = props.path.slice(0, -2)\n const defaultValue = useFormValue([...experimentPath, 'default'])\n const handleClick = () => {\n props.onChange(set(defaultValue, ['value']))\n }\n return (\n <Stack gap={3}>\n {props.renderDefault(props)}\n\n <Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>\n </Stack>\n )\n}\n","import {useEffect, useState} from 'react'\nimport {\n isImage,\n isReference,\n type ObjectSchemaType,\n type PreviewProps,\n type ReferenceSchemaType,\n useClient,\n} from 'sanity'\n\nimport type {VariantPreviewProps} from '../../types'\nimport {useExperimentContext} from './Context'\n\nexport const VariantPreview = (props: PreviewProps) => {\n const [subtitle, setSubtitle] = useState<string | undefined>(undefined)\n const [title, setTitle] = useState<string | undefined>(undefined)\n const [media, setMedia] = useState<any>(undefined)\n const {experiments, apiVersion} = useExperimentContext()\n const client = useClient({apiVersion})\n\n const {experiment, variant, value} = props as VariantPreviewProps\n\n const selectedExperiment = experiments.find((experimentItem) => {\n return experimentItem.id === experiment\n })\n\n const selectedVariant = selectedExperiment?.variants.find((variantItem) => {\n return variantItem.id === variant\n })\n\n useEffect(() => {\n const getSubtitle = async () => {\n setTitle(\n selectedExperiment?.label && selectedVariant?.label\n ? `${selectedExperiment.label} - ${selectedVariant.label}`\n : selectedExperiment?.label || selectedVariant?.label,\n )\n if (typeof value === 'string') {\n return setSubtitle(value)\n }\n if (isReference(value)) {\n const doc = await client.getDocument(value._ref)\n const type = props.schemaType as ObjectSchemaType\n const valueField = type.fields.find((field) => field.name === 'value') as ObjectSchemaType\n const referenceField = valueField?.type as ReferenceSchemaType\n const referenceType = referenceField.to.find((field) => field.type?.name === doc?._type)\n\n const selectFields = {} as Record<string, unknown>\n const previewFields = referenceType?.preview?.select || {}\n Object.keys(previewFields).forEach((key) => {\n const valueKey = referenceType?.preview?.select?.[key]\n selectFields[key] =\n valueKey && doc\n ? valueKey.split('.').reduce((acc: any, index) => acc?.[index], doc)\n : undefined\n })\n\n const previewContent = referenceType?.preview?.prepare?.(selectFields)\n setMedia(previewContent?.media || selectFields['media'])\n return setSubtitle(previewContent?.title || (selectFields['title'] as string))\n }\n if (isImage(value)) {\n setMedia(value)\n }\n return ''\n }\n void getSubtitle()\n }, [value, client, selectedExperiment?.label, selectedVariant?.label, props.schemaType])\n\n const previewProps = {\n ...props,\n title: title,\n subtitle: subtitle,\n media: media,\n }\n\n return props.renderDefault(previewProps)\n}\n","import {isDocumentSchemaType, type ObjectField, type Path, type SchemaType} from 'sanity'\n\nimport type {ObjectFieldWithPath} from '../types'\n\n/**\n * Flattens a document's schema type into a flat array of fields and includes their path\n */\nexport function flattenSchemaType(schemaType: SchemaType): ObjectFieldWithPath[] {\n if (!isDocumentSchemaType(schemaType)) {\n console.error(`Schema type is not a document`)\n return []\n }\n\n return extractInnerFields(schemaType.fields, [], 5)\n}\n\nfunction extractInnerFields(\n fields: ObjectField[],\n path: Path,\n maxDepth: number,\n): ObjectFieldWithPath[] {\n if (path.length >= maxDepth) {\n return []\n }\n\n const result: ObjectFieldWithPath[] = []\n\n for (const field of fields) {\n result.push({path: [...path, field.name], ...field})\n\n if (field.type.jsonType === 'object') {\n result.push(...extractInnerFields(field.type.fields, [...path, field.name], maxDepth))\n } else if (field.type.jsonType === 'array') {\n // Handle array types by checking each possible type in the array\n const arrayTypes = field.type.of || []\n for (const arrayType of arrayTypes) {\n if ('fields' in arrayType) {\n result.push(...extractInnerFields(arrayType.fields, [...path, field.name], maxDepth))\n }\n }\n }\n }\n\n return result\n}\n","import {\n type ArrayOfObjectsInputProps,\n defineField,\n definePlugin,\n defineType,\n type FieldDefinition,\n isObjectInputProps,\n} from 'sanity'\n\nimport {ArrayItem} from './components/ArrayItem'\nimport {\n ArrayInput,\n CONFIG_DEFAULT,\n ExperimentProvider,\n Field,\n Input,\n VariantInput,\n VariantPreview,\n} from './components/experiment'\nimport type {ExperimentFieldPluginConfig} from './types'\nimport {flattenSchemaType} from './utils/flattenSchemaType'\n\nconst createExperimentType = ({\n field,\n experimentNameOverride,\n variantNameOverride,\n variantId,\n variantArrayName,\n experimentId,\n}: {\n field: string | FieldDefinition\n experimentNameOverride: string\n variantNameOverride: string\n variantId: string\n variantArrayName: string\n experimentId: string\n}) => {\n const typeName = typeof field === `string` ? field : field.name\n const usedName = String(typeName[0]).toUpperCase() + typeName.slice(1)\n const variantName = `${variantNameOverride}${usedName}`\n\n return defineType({\n name: `${experimentNameOverride}${usedName}`,\n type: 'object',\n groups: [\n {\n name: 'default',\n title: 'Default',\n hidden: ({parent}) => {\n return !Array.isArray(parent)\n },\n },\n {\n name: 'experiments',\n title: 'Experiments',\n hidden: ({parent}) => {\n return !Array.isArray(parent)\n },\n },\n {\n name: 'all-fields',\n title: 'All fields',\n hidden: ({parent}) => {\n return Array.isArray(parent)\n },\n },\n ],\n components: {\n field: (props) => (\n <Field\n {...props}\n experimentId={experimentId}\n experimentNameOverride={experimentNameOverride}\n variantNameOverride={variantNameOverride}\n />\n ),\n item: ArrayItem,\n },\n fields: [\n typeof field === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'default',\n type: field,\n group: 'default',\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...field,\n name: 'default',\n group: 'default',\n },\n defineField({\n name: 'active',\n type: 'boolean',\n hidden: true,\n initialValue: false,\n }),\n defineField({\n name: experimentId,\n type: 'string',\n group: 'experiments',\n components: {\n input: (props) => (\n <Input\n {...props}\n experimentNameOverride={experimentNameOverride}\n variantNameOverride={variantNameOverride}\n />\n ),\n },\n hidden: ({parent}) => {\n return !parent?.active\n },\n }),\n defineField({\n name: variantArrayName,\n type: 'array',\n group: 'experiments',\n hidden: ({parent}) => {\n return !parent?.[experimentId]\n },\n components: {\n input: (props: ArrayOfObjectsInputProps) => (\n <ArrayInput\n {...props}\n variantName={variantName}\n variantId={variantId}\n experimentId={experimentId}\n />\n ),\n },\n of: [\n defineField({\n name: variantName,\n type: variantName,\n }),\n ],\n }),\n ],\n preview: {\n select: {\n base: 'default',\n experiment: experimentId,\n },\n prepare: ({base, experiment}) => {\n const title =\n typeof base === 'string'\n ? base\n : base && typeof base === 'object'\n ? base.title || base.name || ''\n : ''\n const experimentTitle = experiment ? `Experiment: ${experiment}` : ''\n const media =\n base && typeof base === 'object' ? base.image || base.photo || base.media || '' : ''\n return {\n title: title || experimentTitle,\n subtitle: title ? experimentTitle : '',\n media,\n }\n },\n },\n })\n}\n\nconst createVariantType = ({\n field,\n variantNameOverride,\n variantId,\n experimentId,\n}: {\n field: string | FieldDefinition\n variantNameOverride: string\n variantId: string\n experimentId: string\n}) => {\n const typeName = typeof field === `string` ? field : field.name\n const usedName = String(typeName[0]).toUpperCase() + typeName.slice(1)\n return defineType({\n name: `${variantNameOverride}${usedName}`,\n title: `${variantNameOverride} array ${usedName}`,\n type: 'object',\n components: {\n preview: VariantPreview,\n input: VariantInput,\n },\n fields: [\n {\n type: 'string',\n name: variantId,\n readOnly: true,\n },\n {\n type: 'string',\n name: experimentId,\n hidden: true,\n },\n typeof field === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'value',\n type: field,\n // hidden: ({parent}) => !parent?.[`${objectNameOverride}Id`],\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...field,\n name: 'value',\n // hidden: ({parent}) => !parent?.[`${objectNameOverride}Id`],\n },\n ],\n preview: {\n select: {\n variant: variantId,\n experiment: experimentId,\n value: 'value',\n },\n },\n })\n}\n\nconst fieldSchema = ({\n fields,\n experimentNameOverride,\n variantNameOverride,\n variantId,\n variantArrayName,\n experimentId,\n}: Required<Omit<ExperimentFieldPluginConfig, 'apiVersion' | 'experiments'>>) => {\n return [\n ...fields.map((field) =>\n createVariantType({field, variantNameOverride, variantId, experimentId}),\n ),\n ...fields.map((field) =>\n createExperimentType({\n field,\n experimentNameOverride,\n variantNameOverride,\n variantId,\n variantArrayName,\n experimentId,\n }),\n ),\n ]\n}\n\nexport const fieldLevelExperiments = definePlugin<ExperimentFieldPluginConfig>((config) => {\n const pluginConfig = {...CONFIG_DEFAULT, ...config}\n const {fields, experimentNameOverride, variantNameOverride} = pluginConfig\n\n const experimentId = `${experimentNameOverride}Id`\n const variantArrayName = `${variantNameOverride}s`\n const variantId = `${variantNameOverride}Id`\n\n const fieldSchemaConfig = fieldSchema({\n fields,\n experimentNameOverride,\n variantNameOverride,\n variantId,\n variantArrayName,\n experimentId,\n })\n return {\n name: 'sanity-personalization-plugin-field-level-experiments',\n schema: {\n types: fieldSchemaConfig,\n },\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFields = flattenSchemaType(props.schemaType)\n const hasExperiment = flatFields.some(\n (field) =>\n field.type.name.startsWith(experimentNameOverride) ||\n field.name.startsWith(experimentNameOverride),\n )\n\n if (!hasExperiment) {\n return props.renderDefault(props)\n }\n\n const providerProps = {\n ...props,\n experimentFieldPluginConfig: {\n ...pluginConfig,\n variantId,\n variantArrayName,\n experimentId,\n },\n }\n return <ExperimentProvider {...providerProps} />\n },\n },\n },\n }\n})\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"fieldExperiments-DmD8mnlU.js","names":["() => {\n if (!active) {\n onChange(set(true, ['active']))\n }\n }","[active, onChange]","props.renderDefault(props)","props.renderDefault","_c","{apiVersion: experimentFieldPluginConfig.apiVersion}","apiVersion","Array.isArray(experimentFieldPluginConfig.experiments)\n ? experimentFieldPluginConfig.experiments\n : suspend(\n async () => {\n if (typeof experimentFieldPluginConfig.experiments === 'function') {\n return experimentFieldPluginConfig.experiments(client)\n }\n return experimentFieldPluginConfig.experiments\n },\n [workspace, 'field-level-experiments'],\n {equal},\n )","experimentFieldPluginConfig.experiments","{...experimentFieldPluginConfig, experiments}","useMemo(\n () => ({...experimentFieldPluginConfig, experiments}),\n [experimentFieldPluginConfig, experiments],\n )","props.renderDefault(props)","props.renderDefault","<ExperimentContext.Provider value={context}>\n {props.renderDefault(props)}\n </ExperimentContext.Provider>","ExperimentContext.Provider","_c","useFormValue","[...fieldPath, experimentId]","props.path","async (variant: VariantType) => {\n const item = {\n _key: uuid(),\n [variantId]: variant.id,\n [experimentId]: experimentValue,\n _type: variantName,\n }\n\n // Patch the document\n onItemAppend(item)\n }","useCallback(\n async (variant: VariantType) => {\n const item = {\n _key: uuid(),\n [variantId]: variant.id,\n [experimentId]: experimentValue,\n _type: variantName,\n }\n\n // Patch the document\n onItemAppend(item)\n },\n [variantId, experimentId, experimentValue, variantName, onItemAppend],\n )","Inline","Stack","1","filteredVariants.map((variant) => {\n return (\n <Button\n key={`${experimentValue}-${variant.id}`}\n text={`Add ${variant.label}`}\n mode=\"ghost\"\n disabled={usedVariants?.includes(variant.id)}\n onClick={() => handleClick(variant)}\n />\n )\n })","3","props.renderDefault({...props, arrayFunctions: () => null})","props.value","(props.value as Value[]) || []","value","variant","() => null","<Inline gap={1}>\n {filteredVariants.map((variant) => {\n return (\n <Button\n key={`${experimentValue}-${variant.id}`}\n text={`Add ${variant.label}`}\n mode=\"ghost\"\n disabled={usedVariants?.includes(variant.id)}\n onClick={() => handleClick(variant)}\n />\n )\n })}\n </Inline>","<Stack gap={3}>\n {props.renderDefault({...props, arrayFunctions: () => null})}\n\n <Inline gap={1}>\n {filteredVariants.map((variant) => {\n return (\n <Button\n key={`${experimentValue}-${variant.id}`}\n text={`Add ${variant.label}`}\n mode=\"ghost\"\n disabled={usedVariants?.includes(variant.id)}\n onClick={() => handleClick(variant)}\n />\n )\n })}\n </Inline>\n </Stack>","_c","values","_temp","() => {\n onChange([set(!active, ['active'])])\n }","useCallback(() => {\n onChange([set(!active, ['active'])])\n }, [onChange, active])","{\n title: `Add ${experimentNameOverride}`,\n type: 'action',\n icon: GiSoapExperiment,\n onAction: handleAddAction,\n renderAsButton: true,\n }","`Add ${experimentNameOverride}`","() => {\n const activeId = ['active']\n const experiment = [experimentId]\n const variants = [`${variantNameOverride}s`]\n onChange([set(!active, activeId), unset(experiment), unset(variants)])\n }","useCallback(() => {\n const activeId = ['active']\n const experiment = [experimentId]\n const variants = [`${variantNameOverride}s`]\n onChange([set(!active, activeId), unset(experiment), unset(variants)])\n }, [onChange, active, experimentId, variantNameOverride])","{\n title: `Remove ${experimentNameOverride}`,\n type: 'action',\n icon: CloseIcon,\n onAction: handleClearAction,\n renderAsButton: true,\n }","`Remove ${experimentNameOverride}`","{\n onChange,\n inputId,\n active,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n }","useMemo(\n () => ({\n onChange,\n inputId,\n active,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n }),\n [onChange, inputId, active, experimentNameOverride, experimentId, variantNameOverride],\n )","props.actions || []","actions","createActions(actionProps)","[createActions(actionProps), ...oldActions]","useMemo(() => {\n const oldActions = props.actions || []\n return [createActions(actionProps), ...oldActions]\n }, [actionProps, props.actions])","clearChildrenGroups(props)","{\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }","useMemo(() => {\n const propsWithClearedGroups = clearChildrenGroups(props)\n return {\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }\n }, [props, memoizedActions])","props.renderDefault(enhancedProps)","renderDefault","_c","[3, 3, 4]","(event) => handleChange(event, onChange)","<option value={''}>{'Select an option...'}</option>","listOptions.map(({value: optionValue, title}) => (\n <option key={optionValue} value={optionValue}>\n {title}\n </option>\n ))","({value: optionValue, title}) => (\n <option key={optionValue} value={optionValue}>\n {title}\n </option>\n )","<SanitySelect\n {...elementProps}\n fontSize={2}\n padding={3}\n gap={[3, 3, 4]}\n value={value || ''} // Current field value\n onChange={(event) => handleChange(event, onChange)} // A function to call when the input value changes\n >\n <option value={''}>{'Select an option...'}</option>\n {listOptions.map(({value: optionValue, title}) => (\n <option key={optionValue} value={optionValue}>\n {title}\n </option>\n ))}\n </SanitySelect>","value || ''","{value: optionValue, title}","Select","_c","_temp","SanitySelect","['_id']","[...props.path.slice(0, -1), `${props.variantNameOverride}s`]","path","variantNameOverride","useMemo(\n () => [...props.path.slice(0, -1), `${props.variantNameOverride}s`],\n [props.variantNameOverride, props.path],\n )","getPublishedId(id)","(\n event: ChangeEvent<HTMLSelectElement>,\n onChange: (patchchange: FormPatch | FormPatch[] | PatchEvent) => void,\n ) => {\n const inputValue = event.currentTarget.value\n\n if (inputValue) {\n onChange(set(inputValue))\n } else {\n onChange(unset())\n }\n\n if (subValues) {\n const patchEvent = {\n unset: [additionalChangePath.join('.')],\n }\n patch.execute([patchEvent])\n }\n }","useCallback(\n (\n event: ChangeEvent<HTMLSelectElement>,\n onChange: (patchchange: FormPatch | FormPatch[] | PatchEvent) => void,\n ) => {\n const inputValue = event.currentTarget.value\n\n if (inputValue) {\n onChange(set(inputValue))\n } else {\n onChange(unset())\n }\n\n if (subValues) {\n const patchEvent = {\n unset: [additionalChangePath.join('.')],\n }\n patch.execute([patchEvent])\n }\n },\n [patch, subValues, additionalChangePath],\n )","[3, 3, 4]","[2, 2, 3]","<Card padding={[3, 3, 4]} radius={2} shadow={1} tone=\"caution\">\n <Text align=\"center\" size={[2, 2, 3]}>\n There are no defined {props.experimentNameOverride}s\n </Text>\n </Card>","experimentNameOverride","formatlistOptions(experiments)","<Select {...props} listOptions={formatlistOptions(experiments)} handleChange={handleChange} />","_c","Select","useFormValue","[...experimentPath, 'default']","path","() => {\n props.onChange(set(defaultValue, ['value']))\n }","props.renderDefault(props)","props.renderDefault","<Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>","<Stack gap={3}>\n {props.renderDefault(props)}\n\n <Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>\n </Stack>","_c","{apiVersion}","selectedExperiment?.variants.find((variantItem) => {\n return variantItem.id === variant\n })","(experimentItem) => {\n return experimentItem.id === experiment\n }","() => {\n const getSubtitle = async () => {\n setTitle(\n selectedExperiment?.label && selectedVariant?.label\n ? `${selectedExperiment.label} - ${selectedVariant.label}`\n : selectedExperiment?.label || selectedVariant?.label,\n )\n if (typeof value === 'string') {\n return setSubtitle(value)\n }\n if (isReference(value)) {\n const doc = await client.getDocument(value._ref)\n const type = props.schemaType as ObjectSchemaType\n const valueField = type.fields.find((field) => field.name === 'value') as ObjectSchemaType\n const referenceField = valueField?.type as ReferenceSchemaType\n const referenceType = referenceField.to.find((field) => field.type?.name === doc?._type)\n\n const selectFields = {} as Record<string, unknown>\n const previewFields = referenceType?.preview?.select || {}\n Object.keys(previewFields).forEach((key) => {\n const valueKey = referenceType?.preview?.select?.[key]\n selectFields[key] =\n valueKey && doc\n ? valueKey.split('.').reduce((acc: any, index) => acc?.[index], doc)\n : undefined\n })\n\n const previewContent = referenceType?.preview?.prepare?.(selectFields)\n setMedia(previewContent?.media || selectFields['media'])\n return setSubtitle(previewContent?.title || (selectFields['title'] as string))\n }\n if (isImage(value)) {\n setMedia(value)\n }\n return ''\n }\n void getSubtitle()\n }","schemaType","selectedExperiment?.label","selectedVariant?.label","(field) => field.name === 'value'","field","(acc: any, index) => acc?.[index]","[value, client, selectedExperiment?.label, selectedVariant?.label, props.schemaType]","props.renderDefault(previewProps)","_c","\"active\"","\"media\"","\"title\""],"sources":["../src/components/ArrayItem.tsx","../src/components/experiment/Context.tsx","../src/components/experiment/Array.tsx","../src/utils/clearChildGroups.ts","../src/components/experiment/Field.tsx","../src/components/Select.tsx","../src/components/experiment/Input.tsx","../src/components/experiment/VariantInput.tsx","../src/components/experiment/VariantPreview.tsx","../src/utils/flattenSchemaType.ts","../src/fieldExperiments.tsx"],"sourcesContent":["import {useEffect} from 'react'\nimport {type ObjectItem, type ObjectItemProps, set} from 'sanity'\n\nexport const ArrayItem = (props: ObjectItemProps) => {\n const {active} = props.value as ObjectItem & {active: boolean}\n const {onChange} = props.inputProps\n\n useEffect(() => {\n if (!active) {\n onChange(set(true, ['active']))\n }\n }, [active, onChange])\n\n return props.renderDefault(props)\n}\n","import {dequal as equal} from 'dequal/lite'\nimport {createContext, useContext, useMemo} from 'react'\nimport {type ObjectInputProps, useClient, useWorkspace} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport type {ExperimentContextProps, ExperimentFieldPluginConfig} from '../../types'\n\n// This provider makes the plugin config available to all components in the document form\n// But with experiments resolved\n\nexport const CONFIG_DEFAULT = {\n fields: [],\n apiVersion: '2024-11-07',\n experimentNameOverride: 'experiment',\n variantNameOverride: 'variant',\n variantId: 'variantId',\n variantArrayName: 'variants',\n experimentId: 'experimentId',\n}\n\nconst ExperimentContext = createContext<ExperimentContextProps>({\n ...CONFIG_DEFAULT,\n experiments: [],\n})\n\nexport function useExperimentContext() {\n return useContext(ExperimentContext)\n}\n\ntype ExperimentProps = ObjectInputProps & {\n experimentFieldPluginConfig: Required<ExperimentFieldPluginConfig>\n}\n\nexport function ExperimentProvider(props: ExperimentProps) {\n const {experimentFieldPluginConfig} = props\n\n const client = useClient({apiVersion: experimentFieldPluginConfig.apiVersion})\n const workspace = useWorkspace()\n\n // Fetch or return experiments\n const experiments = Array.isArray(experimentFieldPluginConfig.experiments)\n ? experimentFieldPluginConfig.experiments\n : suspend(\n async () => {\n if (typeof experimentFieldPluginConfig.experiments === 'function') {\n return experimentFieldPluginConfig.experiments(client)\n }\n return experimentFieldPluginConfig.experiments\n },\n [workspace, 'field-level-experiments'],\n {equal},\n )\n\n const context = useMemo(\n () => ({...experimentFieldPluginConfig, experiments}),\n [experimentFieldPluginConfig, experiments],\n )\n\n return (\n <ExperimentContext.Provider value={context}>\n {props.renderDefault(props)}\n </ExperimentContext.Provider>\n )\n}\n","import {Button, Inline, Stack} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {useCallback} from 'react'\nimport {useFormValue} from 'sanity'\n\nimport type {ArrayInputProps, VariantType} from '../../types'\nimport {useExperimentContext} from './Context'\n\nexport const ArrayInput = (props: ArrayInputProps) => {\n const fieldPath = props.path.slice(0, -1)\n const {onItemAppend, variantName, variantId, experimentId} = props\n const experimentValue = useFormValue([...fieldPath, experimentId])\n\n const {experiments} = useExperimentContext()\n\n const handleClick = useCallback(\n async (variant: VariantType) => {\n const item = {\n _key: uuid(),\n [variantId]: variant.id,\n [experimentId]: experimentValue,\n _type: variantName,\n }\n\n // Patch the document\n onItemAppend(item)\n },\n [variantId, experimentId, experimentValue, variantName, onItemAppend],\n )\n\n const filteredVariants =\n experiments.find((option) => {\n return option.id === experimentValue\n })?.variants || []\n\n type Value = {\n value?: unknown\n [key: string]: unknown\n variantId: string\n _key: string\n _type: string\n }\n\n // there is probably some better was of getting the type of this?\n const values = (props.value as Value[]) || []\n\n const usedVariants = values?.map((variant) => variant[variantId])\n\n return (\n <Stack gap={3}>\n {props.renderDefault({...props, arrayFunctions: () => null})}\n\n <Inline gap={1}>\n {filteredVariants.map((variant) => {\n return (\n <Button\n key={`${experimentValue}-${variant.id}`}\n text={`Add ${variant.label}`}\n mode=\"ghost\"\n disabled={usedVariants?.includes(variant.id)}\n onClick={() => handleClick(variant)}\n />\n )\n })}\n </Inline>\n </Stack>\n )\n}\n","import type {ObjectFieldProps} from 'sanity'\n\n/**\n * Safely updates deeply nested children props to clear groups array\n * This prevents field grouping UI conflicts in personalization mode\n */\nexport const clearChildrenGroups = (props: ObjectFieldProps): ObjectFieldProps => {\n // Type assertion is needed here because Sanity's ObjectFieldProps children\n // typing doesn't account for the nested structure we need to manipulate\n const children = props.children as any\n\n if (!children || typeof children !== 'object' || !children.props) {\n return props\n }\n\n const innerChild = children.props.children\n if (\n !innerChild ||\n typeof innerChild !== 'object' ||\n Array.isArray(innerChild) ||\n !('props' in innerChild)\n ) {\n return props\n }\n\n return {\n ...props,\n children: {\n ...children,\n props: {\n ...children.props,\n children: {\n ...innerChild,\n props: {\n ...innerChild.props,\n groups: [],\n },\n },\n },\n },\n }\n}\n","import {CloseIcon} from '@sanity/icons/Close'\nimport {useCallback, useMemo} from 'react'\nimport {GiSoapExperiment} from 'react-icons/gi'\nimport {\n defineDocumentFieldAction,\n type DocumentFieldActionItem,\n type DocumentFieldActionProps,\n type FormPatch,\n type ObjectFieldProps,\n type PatchEvent,\n set,\n unset,\n} from 'sanity'\n\nimport {clearChildrenGroups} from '../../utils/clearChildGroups'\n\ntype PatchStuff = {onChange: (patch: FormPatch | FormPatch[] | PatchEvent) => void; inputId: string}\n\nconst useAddExperimentAction = (\n props: DocumentFieldActionProps &\n PatchStuff & {experimentNameOverride: string; experimentId: string; active: boolean},\n): DocumentFieldActionItem => {\n const {onChange, active, experimentNameOverride} = props\n\n const handleAddAction = useCallback(() => {\n onChange([set(!active, ['active'])])\n }, [onChange, active])\n\n return {\n title: `Add ${experimentNameOverride}`,\n type: 'action',\n icon: GiSoapExperiment,\n onAction: handleAddAction,\n renderAsButton: true,\n }\n}\n\nconst useRemoveExperimentAction = (\n props: DocumentFieldActionProps &\n PatchStuff & {\n experimentNameOverride: string\n experimentId: string\n active: boolean\n variantNameOverride: string\n },\n): DocumentFieldActionItem => {\n const {onChange, active, experimentId, experimentNameOverride, variantNameOverride} = props\n const handleClearAction = useCallback(() => {\n const activeId = ['active']\n const experiment = [experimentId]\n const variants = [`${variantNameOverride}s`]\n onChange([set(!active, activeId), unset(experiment), unset(variants)])\n }, [onChange, active, experimentId, variantNameOverride])\n\n return {\n title: `Remove ${experimentNameOverride}`,\n type: 'action',\n icon: CloseIcon,\n onAction: handleClearAction,\n renderAsButton: true,\n }\n}\n\nconst createActions = ({\n onChange,\n inputId,\n active,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n}: PatchStuff & {\n active?: boolean\n experimentNameOverride: string\n experimentId: string\n variantNameOverride: string\n}) => {\n const removeAction = defineDocumentFieldAction({\n name: `Remove ${experimentNameOverride}`,\n useAction: (props) =>\n useRemoveExperimentAction({\n ...props,\n active: true,\n onChange,\n inputId,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n }),\n })\n const addAction = defineDocumentFieldAction({\n name: `Add ${experimentNameOverride}`,\n useAction: (props) =>\n useAddExperimentAction({\n ...props,\n active: false,\n onChange,\n inputId,\n experimentNameOverride,\n experimentId,\n }),\n })\n return active ? removeAction : addAction\n}\n\nexport const Field = (\n props: ObjectFieldProps & {\n experimentNameOverride: string\n experimentId: string\n variantNameOverride: string\n },\n) => {\n const {onChange} = props.inputProps\n const {inputId, experimentNameOverride, experimentId, variantNameOverride} = props\n const active = props.value?.['active'] as boolean | undefined\n\n const actionProps = useMemo(\n () => ({\n onChange,\n inputId,\n active,\n experimentNameOverride,\n experimentId,\n variantNameOverride,\n }),\n [onChange, inputId, active, experimentNameOverride, experimentId, variantNameOverride],\n )\n\n const memoizedActions = useMemo(() => {\n const oldActions = props.actions || []\n return [createActions(actionProps), ...oldActions]\n }, [actionProps, props.actions])\n\n const enhancedProps = useMemo(() => {\n const propsWithClearedGroups = clearChildrenGroups(props)\n return {\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }\n }, [props, memoizedActions])\n\n return props.renderDefault(enhancedProps)\n}\n","import {Select as SanitySelect} from '@sanity/ui'\nimport type {ChangeEvent} from 'react'\nimport type {FormPatch, PatchEvent, StringInputProps} from 'sanity'\n\nimport type {SelectOption} from './experiment/Input'\n\nexport const Select = (\n props: StringInputProps & {\n listOptions: SelectOption[]\n handleChange: (\n event: ChangeEvent<HTMLSelectElement>,\n onChange: (patch: FormPatch | FormPatch[] | PatchEvent) => void,\n ) => void\n },\n) => {\n const {\n value, // Current field value\n onChange, // Method to handle patch events,\n elementProps,\n listOptions,\n handleChange,\n } = props\n\n return (\n <SanitySelect\n {...elementProps}\n fontSize={2}\n padding={3}\n gap={[3, 3, 4]}\n value={value || ''} // Current field value\n onChange={(event) => handleChange(event, onChange)} // A function to call when the input value changes\n >\n <option value={''}>{'Select an option...'}</option>\n {listOptions.map(({value: optionValue, title}) => (\n <option key={optionValue} value={optionValue}>\n {title}\n </option>\n ))}\n </SanitySelect>\n )\n}\n","import {Card, Text} from '@sanity/ui'\nimport {type ChangeEvent, useCallback, useMemo} from 'react'\nimport {\n type FormPatch,\n getPublishedId,\n type PatchEvent,\n set,\n type StringInputProps,\n unset,\n useDocumentOperation,\n useFormValue,\n} from 'sanity'\n\nimport type {ExperimentType} from '../..'\nimport {Select} from '../Select'\nimport {useExperimentContext} from './Context'\n\nexport type SelectOption = {title: string; value: string}\nconst formatlistOptions = (experiments: ExperimentType[]): SelectOption[] =>\n experiments.map((experiment) => ({\n title: experiment.label,\n value: experiment.id,\n }))\n\nexport const Input = (\n props: StringInputProps & {variantNameOverride: string; experimentNameOverride: string},\n) => {\n const {experiments} = useExperimentContext()\n\n const id = useFormValue(['_id']) as string\n const additionalChangePath = useMemo(\n () => [...props.path.slice(0, -1), `${props.variantNameOverride}s`],\n [props.variantNameOverride, props.path],\n )\n const subValues = useFormValue(additionalChangePath)\n\n const {patch} = useDocumentOperation(getPublishedId(id), props.schemaType.name)\n\n const handleChange = useCallback(\n (\n event: ChangeEvent<HTMLSelectElement>,\n onChange: (patchchange: FormPatch | FormPatch[] | PatchEvent) => void,\n ) => {\n const inputValue = event.currentTarget.value\n\n if (inputValue) {\n onChange(set(inputValue))\n } else {\n onChange(unset())\n }\n\n if (subValues) {\n const patchEvent = {\n unset: [additionalChangePath.join('.')],\n }\n patch.execute([patchEvent])\n }\n },\n [patch, subValues, additionalChangePath],\n )\n\n if (!experiments.length)\n return (\n <Card padding={[3, 3, 4]} radius={2} shadow={1} tone=\"caution\">\n <Text align=\"center\" size={[2, 2, 3]}>\n There are no defined {props.experimentNameOverride}s\n </Text>\n </Card>\n )\n\n return (\n <Select {...props} listOptions={formatlistOptions(experiments)} handleChange={handleChange} />\n )\n}\n","import {Button, Inline, Stack} from '@sanity/ui'\nimport {type ObjectInputProps, set, useFormValue} from 'sanity'\n\nexport const VariantInput = (props: ObjectInputProps) => {\n const experimentPath = props.path.slice(0, -2)\n const defaultValue = useFormValue([...experimentPath, 'default'])\n const handleClick = () => {\n props.onChange(set(defaultValue, ['value']))\n }\n return (\n <Stack gap={3}>\n {props.renderDefault(props)}\n\n <Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>\n </Stack>\n )\n}\n","import {useEffect, useState} from 'react'\nimport {\n isImage,\n isReference,\n type ObjectSchemaType,\n type PreviewProps,\n type ReferenceSchemaType,\n useClient,\n} from 'sanity'\n\nimport type {VariantPreviewProps} from '../../types'\nimport {useExperimentContext} from './Context'\n\nexport const VariantPreview = (props: PreviewProps) => {\n const [subtitle, setSubtitle] = useState<string | undefined>(undefined)\n const [title, setTitle] = useState<string | undefined>(undefined)\n const [media, setMedia] = useState<any>(undefined)\n const {experiments, apiVersion} = useExperimentContext()\n const client = useClient({apiVersion})\n\n const {experiment, variant, value} = props as VariantPreviewProps\n\n const selectedExperiment = experiments.find((experimentItem) => {\n return experimentItem.id === experiment\n })\n\n const selectedVariant = selectedExperiment?.variants.find((variantItem) => {\n return variantItem.id === variant\n })\n\n useEffect(() => {\n const getSubtitle = async () => {\n setTitle(\n selectedExperiment?.label && selectedVariant?.label\n ? `${selectedExperiment.label} - ${selectedVariant.label}`\n : selectedExperiment?.label || selectedVariant?.label,\n )\n if (typeof value === 'string') {\n return setSubtitle(value)\n }\n if (isReference(value)) {\n const doc = await client.getDocument(value._ref)\n const type = props.schemaType as ObjectSchemaType\n const valueField = type.fields.find((field) => field.name === 'value') as ObjectSchemaType\n const referenceField = valueField?.type as ReferenceSchemaType\n const referenceType = referenceField.to.find((field) => field.type?.name === doc?._type)\n\n const selectFields = {} as Record<string, unknown>\n const previewFields = referenceType?.preview?.select || {}\n Object.keys(previewFields).forEach((key) => {\n const valueKey = referenceType?.preview?.select?.[key]\n selectFields[key] =\n valueKey && doc\n ? valueKey.split('.').reduce((acc: any, index) => acc?.[index], doc)\n : undefined\n })\n\n const previewContent = referenceType?.preview?.prepare?.(selectFields)\n setMedia(previewContent?.media || selectFields['media'])\n return setSubtitle(previewContent?.title || (selectFields['title'] as string))\n }\n if (isImage(value)) {\n setMedia(value)\n }\n return ''\n }\n void getSubtitle()\n }, [value, client, selectedExperiment?.label, selectedVariant?.label, props.schemaType])\n\n const previewProps = {\n ...props,\n title: title,\n subtitle: subtitle,\n media: media,\n }\n\n return props.renderDefault(previewProps)\n}\n","import {isDocumentSchemaType, type ObjectField, type Path, type SchemaType} from 'sanity'\n\nimport type {ObjectFieldWithPath} from '../types'\n\n/**\n * Flattens a document's schema type into a flat array of fields and includes their path\n */\nexport function flattenSchemaType(schemaType: SchemaType): ObjectFieldWithPath[] {\n if (!isDocumentSchemaType(schemaType)) {\n console.error(`Schema type is not a document`)\n return []\n }\n\n return extractInnerFields(schemaType.fields, [], 5)\n}\n\nfunction extractInnerFields(\n fields: ObjectField[],\n path: Path,\n maxDepth: number,\n): ObjectFieldWithPath[] {\n if (path.length >= maxDepth) {\n return []\n }\n\n const result: ObjectFieldWithPath[] = []\n\n for (const field of fields) {\n result.push({path: [...path, field.name], ...field})\n\n if (field.type.jsonType === 'object') {\n result.push(...extractInnerFields(field.type.fields, [...path, field.name], maxDepth))\n } else if (field.type.jsonType === 'array') {\n // Handle array types by checking each possible type in the array\n const arrayTypes = field.type.of || []\n for (const arrayType of arrayTypes) {\n if ('fields' in arrayType) {\n result.push(...extractInnerFields(arrayType.fields, [...path, field.name], maxDepth))\n }\n }\n }\n }\n\n return result\n}\n","import {\n type ArrayOfObjectsInputProps,\n defineField,\n definePlugin,\n defineType,\n type FieldDefinition,\n isObjectInputProps,\n} from 'sanity'\n\nimport {ArrayItem} from './components/ArrayItem'\nimport {\n ArrayInput,\n CONFIG_DEFAULT,\n ExperimentProvider,\n Field,\n Input,\n VariantInput,\n VariantPreview,\n} from './components/experiment'\nimport type {ExperimentFieldPluginConfig} from './types'\nimport {flattenSchemaType} from './utils/flattenSchemaType'\n\nconst createExperimentType = ({\n field,\n experimentNameOverride,\n variantNameOverride,\n variantId,\n variantArrayName,\n experimentId,\n}: {\n field: string | FieldDefinition\n experimentNameOverride: string\n variantNameOverride: string\n variantId: string\n variantArrayName: string\n experimentId: string\n}) => {\n const typeName = typeof field === `string` ? field : field.name\n const usedName = String(typeName[0]).toUpperCase() + typeName.slice(1)\n const variantName = `${variantNameOverride}${usedName}`\n\n return defineType({\n name: `${experimentNameOverride}${usedName}`,\n type: 'object',\n groups: [\n {\n name: 'default',\n title: 'Default',\n hidden: ({parent}) => {\n return !Array.isArray(parent)\n },\n },\n {\n name: 'experiments',\n title: 'Experiments',\n hidden: ({parent}) => {\n return !Array.isArray(parent)\n },\n },\n {\n name: 'all-fields',\n title: 'All fields',\n hidden: ({parent}) => {\n return Array.isArray(parent)\n },\n },\n ],\n components: {\n field: (props) => (\n <Field\n {...props}\n experimentId={experimentId}\n experimentNameOverride={experimentNameOverride}\n variantNameOverride={variantNameOverride}\n />\n ),\n item: ArrayItem,\n },\n fields: [\n typeof field === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'default',\n type: field,\n group: 'default',\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...field,\n name: 'default',\n group: 'default',\n },\n defineField({\n name: 'active',\n type: 'boolean',\n hidden: true,\n initialValue: false,\n }),\n defineField({\n name: experimentId,\n type: 'string',\n group: 'experiments',\n components: {\n input: (props) => (\n <Input\n {...props}\n experimentNameOverride={experimentNameOverride}\n variantNameOverride={variantNameOverride}\n />\n ),\n },\n hidden: ({parent}) => {\n return !parent?.active\n },\n }),\n defineField({\n name: variantArrayName,\n type: 'array',\n group: 'experiments',\n hidden: ({parent}) => {\n return !parent?.[experimentId]\n },\n components: {\n input: (props: ArrayOfObjectsInputProps) => (\n <ArrayInput\n {...props}\n variantName={variantName}\n variantId={variantId}\n experimentId={experimentId}\n />\n ),\n },\n of: [\n defineField({\n name: variantName,\n type: variantName,\n }),\n ],\n }),\n ],\n preview: {\n select: {\n base: 'default',\n experiment: experimentId,\n },\n prepare: ({base, experiment}) => {\n const title =\n typeof base === 'string'\n ? base\n : base && typeof base === 'object'\n ? base.title || base.name || ''\n : ''\n const experimentTitle = experiment ? `Experiment: ${experiment}` : ''\n const media =\n base && typeof base === 'object' ? base.image || base.photo || base.media || '' : ''\n return {\n title: title || experimentTitle,\n subtitle: title ? experimentTitle : '',\n media,\n }\n },\n },\n })\n}\n\nconst createVariantType = ({\n field,\n variantNameOverride,\n variantId,\n experimentId,\n}: {\n field: string | FieldDefinition\n variantNameOverride: string\n variantId: string\n experimentId: string\n}) => {\n const typeName = typeof field === `string` ? field : field.name\n const usedName = String(typeName[0]).toUpperCase() + typeName.slice(1)\n return defineType({\n name: `${variantNameOverride}${usedName}`,\n title: `${variantNameOverride} array ${usedName}`,\n type: 'object',\n components: {\n preview: VariantPreview,\n input: VariantInput,\n },\n fields: [\n {\n type: 'string',\n name: variantId,\n readOnly: true,\n },\n {\n type: 'string',\n name: experimentId,\n hidden: true,\n },\n typeof field === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'value',\n type: field,\n // hidden: ({parent}) => !parent?.[`${objectNameOverride}Id`],\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...field,\n name: 'value',\n // hidden: ({parent}) => !parent?.[`${objectNameOverride}Id`],\n },\n ],\n preview: {\n select: {\n variant: variantId,\n experiment: experimentId,\n value: 'value',\n },\n },\n })\n}\n\nconst fieldSchema = ({\n fields,\n experimentNameOverride,\n variantNameOverride,\n variantId,\n variantArrayName,\n experimentId,\n}: Required<Omit<ExperimentFieldPluginConfig, 'apiVersion' | 'experiments'>>) => {\n return [\n ...fields.map((field) =>\n createVariantType({field, variantNameOverride, variantId, experimentId}),\n ),\n ...fields.map((field) =>\n createExperimentType({\n field,\n experimentNameOverride,\n variantNameOverride,\n variantId,\n variantArrayName,\n experimentId,\n }),\n ),\n ]\n}\n\nexport const fieldLevelExperiments = definePlugin<ExperimentFieldPluginConfig>((config) => {\n const pluginConfig = {...CONFIG_DEFAULT, ...config}\n const {fields, experimentNameOverride, variantNameOverride} = pluginConfig\n\n const experimentId = `${experimentNameOverride}Id`\n const variantArrayName = `${variantNameOverride}s`\n const variantId = `${variantNameOverride}Id`\n\n const fieldSchemaConfig = fieldSchema({\n fields,\n experimentNameOverride,\n variantNameOverride,\n variantId,\n variantArrayName,\n experimentId,\n })\n return {\n name: 'sanity-personalization-plugin-field-level-experiments',\n schema: {\n types: fieldSchemaConfig,\n },\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFields = flattenSchemaType(props.schemaType)\n const hasExperiment = flatFields.some(\n (field) =>\n field.type.name.startsWith(experimentNameOverride) ||\n field.name.startsWith(experimentNameOverride),\n )\n\n if (!hasExperiment) {\n return props.renderDefault(props)\n }\n\n const providerProps = {\n ...props,\n experimentFieldPluginConfig: {\n ...pluginConfig,\n variantId,\n variantArrayName,\n experimentId,\n },\n }\n return <ExperimentProvider {...providerProps} />\n },\n },\n },\n }\n})\n"],"mappings":"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"}
\ No newline at end of file Index: package/dist/growthbook/index.js.map
===================================================================
--- package/dist/growthbook/index.js.map
+++ package/dist/growthbook/index.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.js","names":["() => {\n if (loading) return undefined\n if (!secrets && !loading) {\n setSecret(undefined)\n // oxlint-disable-next-line react/set-state-in-effect\n return setShowSettings(true)\n }\n setSecret(secrets.apiKey)\n return setShowSettings(false)\n }","[secrets, loading, setSecret]","props.renderDefault(props)","props.renderDefault","<SettingsView\n title={'Growthbook secret'}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />","<>\n <SettingsView\n title={'Growthbook secret'}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />\n {props.renderDefault(props)}\n </>","{...growthbookFieldPluginConfig, secret, setSecret}","useMemo(\n () => ({...growthbookFieldPluginConfig, secret, setSecret}),\n [growthbookFieldPluginConfig, secret, setSecret],\n )","<Secrets {...props} />","<GrowthbookContext.Provider value={context}>\n <Secrets {...props} />\n </GrowthbookContext.Provider>","GrowthbookContext.Provider"],"sources":["../../src/growthbook/Components/Secrets.tsx","../../src/growthbook/Components/GrowthbookContext.tsx","../../src/growthbook/utils.ts","../../src/growthbook/index.ts"],"sourcesContent":["import {SettingsView, useSecrets} from '@sanity/studio-secrets'\nimport {useEffect, useState} from 'react'\nimport type {ObjectInputProps} from 'sanity'\n\nimport {useGrowthbookContext} from './GrowthbookContext'\n\nexport const namespace = 'growthbook'\nexport const apiKeyName = 'apiKey'\n\nconst pluginConfigKeys = [\n {\n key: apiKeyName,\n title: 'Your secret API key',\n },\n]\n\nexport const Secrets = (props: ObjectInputProps) => {\n const {secrets, loading} = useSecrets(namespace) as {secrets: {apiKey: string}; loading: boolean}\n const {setSecret} = useGrowthbookContext()\n const [showSettings, setShowSettings] = useState<boolean>(false)\n\n useEffect(() => {\n if (loading) return undefined\n if (!secrets && !loading) {\n setSecret(undefined)\n // oxlint-disable-next-line react/set-state-in-effect\n return setShowSettings(true)\n }\n setSecret(secrets.apiKey)\n return setShowSettings(false)\n }, [secrets, loading, setSecret])\n\n if (!showSettings) {\n return props.renderDefault(props)\n }\n return (\n <>\n <SettingsView\n title={'Growthbook secret'}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />\n {props.renderDefault(props)}\n </>\n )\n}\n","import {createContext, useContext, useMemo, useState} from 'react'\nimport type {ObjectInputProps} from 'sanity'\n\nimport type {GrowthbookContextProps, GrowthbookExperimentFieldPluginConfig} from '../types'\nimport {Secrets} from './Secrets'\n\nexport const GROWTHBOOK_CONFIG_DEFAULT = {\n baseUrl: 'https://api.growthbook.io/api/v1',\n}\n\nconst GrowthbookContext = createContext<GrowthbookContextProps>({\n setSecret: () => undefined,\n secret: undefined,\n})\n\nexport function useGrowthbookContext() {\n return useContext(GrowthbookContext)\n}\n\ntype GrowthbookProps = ObjectInputProps & {\n growthbookFieldPluginConfig: GrowthbookExperimentFieldPluginConfig\n}\n\nexport function GrowthbookProvider(props: GrowthbookProps) {\n const {growthbookFieldPluginConfig} = props\n const [secret, setSecret] = useState<string | undefined>()\n\n const context = useMemo(\n () => ({...growthbookFieldPluginConfig, secret, setSecret}),\n [growthbookFieldPluginConfig, secret, setSecret],\n )\n\n return (\n <GrowthbookContext.Provider value={context}>\n <Secrets {...props} />\n </GrowthbookContext.Provider>\n )\n}\n","import type {SanityClient} from 'sanity'\n\nimport type {ExperimentType, GrowthbookFeature, VariantType} from '../types'\nimport {apiKeyName, namespace} from './Components/Secrets'\nimport type {GrowthbookExperimentFieldPluginConfig} from './types'\n\nconst getBooleanConversion = (value: string) => {\n // control is false\n if (value === 'true') {\n return 'variant'\n } else if (value === 'false') {\n return 'control'\n }\n return value\n}\n\nexport const getExperiments = async ({\n client,\n environment,\n baseUrl,\n project,\n convertBooleans,\n tags,\n}: Omit<GrowthbookExperimentFieldPluginConfig, 'fields' | 'baseUrl'> & {\n client: SanityClient\n baseUrl: string\n}): Promise<ExperimentType[]> => {\n const query = `*[_id == 'secrets.${namespace}'][0].secrets.${apiKeyName}`\n\n const secret = await client.fetch(query) // secret is stored in the content lake using @sanity/studio-secrets\n if (!secret) return []\n\n const featureExperiments: ExperimentType[] = []\n let hasMore = true\n let offset = 0\n const url = new URL(`${baseUrl}/features`)\n if (project) {\n url.searchParams.set('projectId', project)\n }\n\n while (hasMore) {\n url.searchParams.set('offset', offset.toString())\n const response = await fetch(url, {\n headers: {\n Authorization: `Bearer ${secret}`,\n },\n })\n\n const {features, hasMore: responseHasMore, nextOffset} = await response.json()\n\n hasMore = responseHasMore\n offset = nextOffset\n if (!features) continue\n\n features.forEach((feature: GrowthbookFeature) => {\n if (feature.archived) {\n return undefined\n }\n if (tags && feature.tags && !feature.tags.some((tag) => tags.includes(tag))) {\n return undefined\n }\n\n const experiments = feature.environments[environment]?.rules.filter(\n (experiment) => experiment.type === 'experiment-ref' || experiment.type === 'experiment',\n )\n\n if (!experiments) {\n return undefined\n }\n\n const variations: VariantType[] = []\n const uniqueValues = new Set<string>()\n\n experiments.forEach((experiment) => {\n experiment?.variations.forEach((variant) => {\n const value = convertBooleans ? getBooleanConversion(variant.value) : variant.value\n if (!uniqueValues.has(value)) {\n uniqueValues.add(value)\n variations.push({\n id: value,\n label: value,\n })\n }\n })\n })\n const value = {id: feature.id, label: feature.id, variants: variations}\n\n featureExperiments.push(value)\n return undefined\n })\n }\n const sortedFeatureExperiments = featureExperiments.sort((a, b) => a.id.localeCompare(b.id))\n return sortedFeatureExperiments\n}\n","import '@sanity/ui/styles.css'\nimport {definePlugin, isObjectInputProps} from 'sanity'\n\nimport {fieldLevelExperiments as baseFieldLevelExperiments} from '../fieldExperiments'\nimport {flattenSchemaType} from '../utils/flattenSchemaType'\nimport {GROWTHBOOK_CONFIG_DEFAULT, GrowthbookProvider} from './Components/GrowthbookContext'\nimport type {GrowthbookExperimentFieldPluginConfig} from './types'\nimport {getExperiments} from './utils'\n\nexport const fieldLevelExperiments = definePlugin<GrowthbookExperimentFieldPluginConfig>(\n (config) => {\n const pluginConfig = {...GROWTHBOOK_CONFIG_DEFAULT, ...config}\n const {fields, environment, project, convertBooleans, baseUrl, tags} = pluginConfig\n return {\n name: 'sanity-growthbook-personalization-plugin-field-level-experiments',\n plugins: [\n baseFieldLevelExperiments({\n fields,\n experiments: (client) =>\n getExperiments({client, environment, baseUrl, project, convertBooleans, tags}),\n }),\n ],\n\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFieldTypeNames = flattenSchemaType(props.schemaType).map(\n (field) => field.type.name,\n )\n\n const hasExperiment = flatFieldTypeNames.some((name) => name.startsWith('experiment'))\n\n if (!hasExperiment) {\n return props.renderDefault(props)\n }\n\n const providerProps = {\n ...props,\n growthbookFieldPluginConfig: {\n ...pluginConfig,\n },\n }\n return GrowthbookProvider(providerProps)\n },\n },\n },\n }\n },\n)\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["() => {\n if (loading) return undefined\n if (!secrets && !loading) {\n setSecret(undefined)\n // oxlint-disable-next-line react/set-state-in-effect\n return setShowSettings(true)\n }\n setSecret(secrets.apiKey)\n return setShowSettings(false)\n }","[secrets, loading, setSecret]","props.renderDefault(props)","props.renderDefault","<SettingsView\n title={'Growthbook secret'}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />","<>\n <SettingsView\n title={'Growthbook secret'}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />\n {props.renderDefault(props)}\n </>","_c","_Fragment","{...growthbookFieldPluginConfig, secret, setSecret}","useMemo(\n () => ({...growthbookFieldPluginConfig, secret, setSecret}),\n [growthbookFieldPluginConfig, secret, setSecret],\n )","<Secrets {...props} />","<GrowthbookContext.Provider value={context}>\n <Secrets {...props} />\n </GrowthbookContext.Provider>","GrowthbookContext.Provider","_c","baseFieldLevelExperiments"],"sources":["../../src/growthbook/Components/Secrets.tsx","../../src/growthbook/Components/GrowthbookContext.tsx","../../src/growthbook/utils.ts","../../src/growthbook/index.ts"],"sourcesContent":["import {SettingsView, useSecrets} from '@sanity/studio-secrets'\nimport {useEffect, useState} from 'react'\nimport type {ObjectInputProps} from 'sanity'\n\nimport {useGrowthbookContext} from './GrowthbookContext'\n\nexport const namespace = 'growthbook'\nexport const apiKeyName = 'apiKey'\n\nconst pluginConfigKeys = [\n {\n key: apiKeyName,\n title: 'Your secret API key',\n },\n]\n\nexport const Secrets = (props: ObjectInputProps) => {\n const {secrets, loading} = useSecrets(namespace) as {secrets: {apiKey: string}; loading: boolean}\n const {setSecret} = useGrowthbookContext()\n const [showSettings, setShowSettings] = useState<boolean>(false)\n\n useEffect(() => {\n if (loading) return undefined\n if (!secrets && !loading) {\n setSecret(undefined)\n // oxlint-disable-next-line react/set-state-in-effect\n return setShowSettings(true)\n }\n setSecret(secrets.apiKey)\n return setShowSettings(false)\n }, [secrets, loading, setSecret])\n\n if (!showSettings) {\n return props.renderDefault(props)\n }\n return (\n <>\n <SettingsView\n title={'Growthbook secret'}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />\n {props.renderDefault(props)}\n </>\n )\n}\n","import {createContext, useContext, useMemo, useState} from 'react'\nimport type {ObjectInputProps} from 'sanity'\n\nimport type {GrowthbookContextProps, GrowthbookExperimentFieldPluginConfig} from '../types'\nimport {Secrets} from './Secrets'\n\nexport const GROWTHBOOK_CONFIG_DEFAULT = {\n baseUrl: 'https://api.growthbook.io/api/v1',\n}\n\nconst GrowthbookContext = createContext<GrowthbookContextProps>({\n setSecret: () => undefined,\n secret: undefined,\n})\n\nexport function useGrowthbookContext() {\n return useContext(GrowthbookContext)\n}\n\ntype GrowthbookProps = ObjectInputProps & {\n growthbookFieldPluginConfig: GrowthbookExperimentFieldPluginConfig\n}\n\nexport function GrowthbookProvider(props: GrowthbookProps) {\n const {growthbookFieldPluginConfig} = props\n const [secret, setSecret] = useState<string | undefined>()\n\n const context = useMemo(\n () => ({...growthbookFieldPluginConfig, secret, setSecret}),\n [growthbookFieldPluginConfig, secret, setSecret],\n )\n\n return (\n <GrowthbookContext.Provider value={context}>\n <Secrets {...props} />\n </GrowthbookContext.Provider>\n )\n}\n","import type {SanityClient} from 'sanity'\n\nimport type {ExperimentType, GrowthbookFeature, VariantType} from '../types'\nimport {apiKeyName, namespace} from './Components/Secrets'\nimport type {GrowthbookExperimentFieldPluginConfig} from './types'\n\nconst getBooleanConversion = (value: string) => {\n // control is false\n if (value === 'true') {\n return 'variant'\n } else if (value === 'false') {\n return 'control'\n }\n return value\n}\n\nexport const getExperiments = async ({\n client,\n environment,\n baseUrl,\n project,\n convertBooleans,\n tags,\n}: Omit<GrowthbookExperimentFieldPluginConfig, 'fields' | 'baseUrl'> & {\n client: SanityClient\n baseUrl: string\n}): Promise<ExperimentType[]> => {\n const query = `*[_id == 'secrets.${namespace}'][0].secrets.${apiKeyName}`\n\n const secret = await client.fetch(query) // secret is stored in the content lake using @sanity/studio-secrets\n if (!secret) return []\n\n const featureExperiments: ExperimentType[] = []\n let hasMore = true\n let offset = 0\n const url = new URL(`${baseUrl}/features`)\n if (project) {\n url.searchParams.set('projectId', project)\n }\n\n while (hasMore) {\n url.searchParams.set('offset', offset.toString())\n const response = await fetch(url, {\n headers: {\n Authorization: `Bearer ${secret}`,\n },\n })\n\n const {features, hasMore: responseHasMore, nextOffset} = await response.json()\n\n hasMore = responseHasMore\n offset = nextOffset\n if (!features) continue\n\n features.forEach((feature: GrowthbookFeature) => {\n if (feature.archived) {\n return undefined\n }\n if (tags && feature.tags && !feature.tags.some((tag) => tags.includes(tag))) {\n return undefined\n }\n\n const experiments = feature.environments[environment]?.rules.filter(\n (experiment) => experiment.type === 'experiment-ref' || experiment.type === 'experiment',\n )\n\n if (!experiments) {\n return undefined\n }\n\n const variations: VariantType[] = []\n const uniqueValues = new Set<string>()\n\n experiments.forEach((experiment) => {\n experiment?.variations.forEach((variant) => {\n const value = convertBooleans ? getBooleanConversion(variant.value) : variant.value\n if (!uniqueValues.has(value)) {\n uniqueValues.add(value)\n variations.push({\n id: value,\n label: value,\n })\n }\n })\n })\n const value = {id: feature.id, label: feature.id, variants: variations}\n\n featureExperiments.push(value)\n return undefined\n })\n }\n const sortedFeatureExperiments = featureExperiments.sort((a, b) => a.id.localeCompare(b.id))\n return sortedFeatureExperiments\n}\n","import '@sanity/ui/styles.css'\nimport {definePlugin, isObjectInputProps} from 'sanity'\n\nimport {fieldLevelExperiments as baseFieldLevelExperiments} from '../fieldExperiments'\nimport {flattenSchemaType} from '../utils/flattenSchemaType'\nimport {GROWTHBOOK_CONFIG_DEFAULT, GrowthbookProvider} from './Components/GrowthbookContext'\nimport type {GrowthbookExperimentFieldPluginConfig} from './types'\nimport {getExperiments} from './utils'\n\nexport const fieldLevelExperiments = definePlugin<GrowthbookExperimentFieldPluginConfig>(\n (config) => {\n const pluginConfig = {...GROWTHBOOK_CONFIG_DEFAULT, ...config}\n const {fields, environment, project, convertBooleans, baseUrl, tags} = pluginConfig\n return {\n name: 'sanity-growthbook-personalization-plugin-field-level-experiments',\n plugins: [\n baseFieldLevelExperiments({\n fields,\n experiments: (client) =>\n getExperiments({client, environment, baseUrl, project, convertBooleans, tags}),\n }),\n ],\n\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFieldTypeNames = flattenSchemaType(props.schemaType).map(\n (field) => field.type.name,\n )\n\n const hasExperiment = flatFieldTypeNames.some((name) => name.startsWith('experiment'))\n\n if (!hasExperiment) {\n return props.renderDefault(props)\n }\n\n const providerProps = {\n ...props,\n growthbookFieldPluginConfig: {\n ...pluginConfig,\n },\n }\n return GrowthbookProvider(providerProps)\n },\n },\n },\n }\n },\n)\n"],"mappings":"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"}
\ No newline at end of file Index: package/dist/index.js.map
===================================================================
--- package/dist/index.js.map
+++ package/dist/index.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.js","names":["{apiVersion: personalizationFieldPluginConfig.apiVersion}","apiVersion","Array.isArray(personalizationFieldPluginConfig.segments)\n ? personalizationFieldPluginConfig.segments\n : suspend(\n async () => {\n if (typeof personalizationFieldPluginConfig.segments === 'function') {\n return personalizationFieldPluginConfig.segments(client)\n }\n return personalizationFieldPluginConfig.segments\n },\n [workspace, 'field-level-personalization'],\n {equal},\n )","personalizationFieldPluginConfig.segments","{...personalizationFieldPluginConfig, segments}","useMemo(\n () => ({...personalizationFieldPluginConfig, segments}),\n [personalizationFieldPluginConfig, segments],\n )","props.renderDefault(props)","props.renderDefault","<PersonalizationContext.Provider value={context}>\n {props.renderDefault(props)}\n </PersonalizationContext.Provider>","PersonalizationContext.Provider","async (segment: VariantType) => {\n const item = {\n _key: uuid(),\n [segmentId]: segment.id,\n _type: segmentName,\n }\n\n // Patch the document\n onItemAppend(item)\n }","useCallback(\n async (segment: VariantType) => {\n const item = {\n _key: uuid(),\n [segmentId]: segment.id,\n _type: segmentName,\n }\n\n // Patch the document\n onItemAppend(item)\n },\n [segmentId, segmentName, onItemAppend],\n )","(props.value as Value[]) || []","value","Inline","Stack","1","segments.map((segment) => {\n return (\n <Button\n key={segment.id}\n text={`Add ${segment.label}`}\n mode=\"ghost\"\n disabled={usedSegments?.includes(segment.id)}\n onClick={() => handleClick(segment)}\n />\n )\n })","3","props.renderDefault({...props, arrayFunctions: () => null})","values?.map","segment","() => null","<Inline gap={1}>\n {segments.map((segment) => {\n return (\n <Button\n key={segment.id}\n text={`Add ${segment.label}`}\n mode=\"ghost\"\n disabled={usedSegments?.includes(segment.id)}\n onClick={() => handleClick(segment)}\n />\n )\n })}\n </Inline>","<Stack gap={3}>\n {props.renderDefault({...props, arrayFunctions: () => null})}\n\n <Inline gap={1}>\n {segments.map((segment) => {\n return (\n <Button\n key={segment.id}\n text={`Add ${segment.label}`}\n mode=\"ghost\"\n disabled={usedSegments?.includes(segment.id)}\n onClick={() => handleClick(segment)}\n />\n )\n })}\n </Inline>\n </Stack>","() => {\n onChange([set(!active, ['active'])])\n }","useCallback(() => {\n onChange([set(!active, ['active'])])\n }, [onChange, active])","{\n title: `Add ${personalizationNameOverride}`,\n type: 'action',\n icon: IoMdPeople,\n onAction: handleAddAction,\n renderAsButton: true,\n }","`Add ${personalizationNameOverride}`","() => {\n const activeId = ['active']\n const segments = [`${segmentNameOverride}s`]\n onChange([set(!active, activeId), unset(segments)])\n }","useCallback(() => {\n const activeId = ['active']\n const segments = [`${segmentNameOverride}s`]\n onChange([set(!active, activeId), unset(segments)])\n }, [onChange, active, segmentNameOverride])","{\n title: `Remove ${personalizationNameOverride}`,\n type: 'action',\n icon: CloseIcon,\n onAction: handleClearAction,\n renderAsButton: true,\n }","`Remove ${personalizationNameOverride}`","{\n onChange,\n inputId,\n active,\n personalizationNameOverride,\n segmentNameOverride,\n }","useMemo(\n () => ({\n onChange,\n inputId,\n active,\n personalizationNameOverride,\n segmentNameOverride,\n }),\n [onChange, inputId, active, personalizationNameOverride, segmentNameOverride],\n )","props.actions || []","actions","createActions(actionProps)","[createActions(actionProps), ...oldActions]","useMemo(() => {\n const oldActions = props.actions || []\n return [createActions(actionProps), ...oldActions]\n }, [actionProps, props.actions])","clearChildrenGroups(props)","{\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }","useMemo(() => {\n const propsWithClearedGroups = clearChildrenGroups(props)\n return {\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }\n }, [props, memoizedActions])","props.renderDefault(enhancedProps)","renderDefault","useFormValue","[...personalizationPath, 'default']","path","() => {\n props.onChange(set(defaultValue, ['value']))\n }","props.renderDefault(props)","props.renderDefault","<Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>","<Stack gap={3}>\n {props.renderDefault(props)}\n\n <Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>\n </Stack>","{apiVersion}","segments.find((segmentItem) => {\n return segmentItem.id === segment\n })","(segmentItem) => {\n return segmentItem.id === segment\n }","() => {\n const getSubtitle = async () => {\n setTitle(selectedSegment?.label)\n if (typeof value === 'string') {\n return setSubtitle(value)\n }\n if (isReference(value)) {\n const doc = await client.getDocument(value._ref)\n const type = props.schemaType as ObjectSchemaType\n const valueField = type.fields.find((field) => field.name === 'value') as ObjectSchemaType\n const referenceField = valueField?.type as ReferenceSchemaType\n const referenceType = referenceField.to.find((field) => field.type?.name === doc?._type)\n\n const selectFields = {} as Record<string, unknown>\n const previewFields = referenceType?.preview?.select || {}\n Object.keys(previewFields).forEach((key) => {\n const valueKey = referenceType?.preview?.select?.[key]\n selectFields[key] =\n valueKey && doc\n ? valueKey.split('.').reduce((acc: any, index) => acc?.[index], doc)\n : undefined\n })\n\n const previewContent = referenceType?.preview?.prepare?.(selectFields)\n setMedia(previewContent?.media || selectFields['media'])\n return setSubtitle(previewContent?.title || (selectFields['title'] as string))\n }\n if (isImage(value)) {\n setMedia(value)\n }\n return ''\n }\n void getSubtitle()\n }","schemaType","label","(field) => field.name === 'value'","field","(acc: any, index) => acc?.[index]","[value, client, selectedSegment?.label, props.schemaType]","selectedSegment?.label","props.renderDefault(previewProps)"],"sources":["../src/components/personalization/Context.tsx","../src/components/personalization/Array.tsx","../src/components/personalization/Field.tsx","../src/components/personalization/SegmentInput.tsx","../src/components/personalization/SegmentPreview.tsx","../src/fieldPersonalization.tsx"],"sourcesContent":["import {dequal as equal} from 'dequal/lite'\nimport {createContext, useContext, useMemo} from 'react'\nimport {type ObjectInputProps, useClient, useWorkspace} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport type {PersonalizationContextProps, PersonalizationFieldPluginConfig} from '../../types'\n\n// This provider makes the plugin config available to all components in the document form\n// But with segments resolved\n\nexport const CONFIG_DEFAULT = {\n fields: [],\n apiVersion: '2024-11-07',\n personalizationNameOverride: 'personalization',\n segmentNameOverride: 'segment',\n segmentId: 'segmentId',\n segmentArrayName: 'segments',\n}\n\nconst PersonalizationContext = createContext<PersonalizationContextProps>({\n ...CONFIG_DEFAULT,\n segments: [],\n})\n\nexport function usePersonalizationContext() {\n return useContext(PersonalizationContext)\n}\n\ntype PersonalizationProps = ObjectInputProps & {\n personalizationFieldPluginConfig: Required<PersonalizationFieldPluginConfig>\n}\n\nexport function PersonalizationProvider(props: PersonalizationProps) {\n const {personalizationFieldPluginConfig} = props\n\n const client = useClient({apiVersion: personalizationFieldPluginConfig.apiVersion})\n const workspace = useWorkspace()\n\n // Fetch or return segments\n const segments = Array.isArray(personalizationFieldPluginConfig.segments)\n ? personalizationFieldPluginConfig.segments\n : suspend(\n async () => {\n if (typeof personalizationFieldPluginConfig.segments === 'function') {\n return personalizationFieldPluginConfig.segments(client)\n }\n return personalizationFieldPluginConfig.segments\n },\n [workspace, 'field-level-personalization'],\n {equal},\n )\n\n const context = useMemo(\n () => ({...personalizationFieldPluginConfig, segments}),\n [personalizationFieldPluginConfig, segments],\n )\n\n return (\n <PersonalizationContext.Provider value={context}>\n {props.renderDefault(props)}\n </PersonalizationContext.Provider>\n )\n}\n","import {Button, Inline, Stack} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {useCallback} from 'react'\n\nimport type {PersonalizationArrayInputProps, VariantType} from '../../types'\nimport {usePersonalizationContext} from './Context'\n\nexport const ArrayInput = (props: PersonalizationArrayInputProps) => {\n const {onItemAppend, segmentName, segmentId} = props\n\n const {segments} = usePersonalizationContext()\n\n const handleClick = useCallback(\n async (segment: VariantType) => {\n const item = {\n _key: uuid(),\n [segmentId]: segment.id,\n _type: segmentName,\n }\n\n // Patch the document\n onItemAppend(item)\n },\n [segmentId, segmentName, onItemAppend],\n )\n\n type Value = {\n value?: unknown\n [key: string]: unknown\n segmentId: string\n _key: string\n _type: string\n }\n\n const values = (props.value as Value[]) || []\n\n const usedSegments = values?.map((segment) => segment[segmentId])\n\n return (\n <Stack gap={3}>\n {props.renderDefault({...props, arrayFunctions: () => null})}\n\n <Inline gap={1}>\n {segments.map((segment) => {\n return (\n <Button\n key={segment.id}\n text={`Add ${segment.label}`}\n mode=\"ghost\"\n disabled={usedSegments?.includes(segment.id)}\n onClick={() => handleClick(segment)}\n />\n )\n })}\n </Inline>\n </Stack>\n )\n}\n","import {CloseIcon} from '@sanity/icons/Close'\nimport {useCallback, useMemo} from 'react'\nimport {IoMdPeople} from 'react-icons/io'\nimport {\n defineDocumentFieldAction,\n type DocumentFieldActionItem,\n type DocumentFieldActionProps,\n type FormPatch,\n type ObjectFieldProps,\n type PatchEvent,\n set,\n unset,\n} from 'sanity'\n\nimport {clearChildrenGroups} from '../../utils/clearChildGroups'\n\ntype PatchStuff = {onChange: (patch: FormPatch | FormPatch[] | PatchEvent) => void; inputId: string}\n\nconst useAddPersonalizationAction = (\n props: DocumentFieldActionProps &\n PatchStuff & {personalizationNameOverride: string; active: boolean},\n): DocumentFieldActionItem => {\n const {onChange, active, personalizationNameOverride} = props\n\n const handleAddAction = useCallback(() => {\n onChange([set(!active, ['active'])])\n }, [onChange, active])\n\n return {\n title: `Add ${personalizationNameOverride}`,\n type: 'action',\n icon: IoMdPeople,\n onAction: handleAddAction,\n renderAsButton: true,\n }\n}\n\nconst useRemovePersonalizationAction = (\n props: DocumentFieldActionProps &\n PatchStuff & {\n personalizationNameOverride: string\n active: boolean\n segmentNameOverride: string\n },\n): DocumentFieldActionItem => {\n const {onChange, active, personalizationNameOverride, segmentNameOverride} = props\n const handleClearAction = useCallback(() => {\n const activeId = ['active']\n const segments = [`${segmentNameOverride}s`]\n onChange([set(!active, activeId), unset(segments)])\n }, [onChange, active, segmentNameOverride])\n\n return {\n title: `Remove ${personalizationNameOverride}`,\n type: 'action',\n icon: CloseIcon,\n onAction: handleClearAction,\n renderAsButton: true,\n }\n}\n\nconst createActions = ({\n onChange,\n inputId,\n active,\n personalizationNameOverride,\n segmentNameOverride,\n}: PatchStuff & {\n active?: boolean\n personalizationNameOverride: string\n segmentNameOverride: string\n}) => {\n const removeAction = defineDocumentFieldAction({\n name: `Remove ${personalizationNameOverride}`,\n useAction: (props) =>\n useRemovePersonalizationAction({\n ...props,\n active: true,\n onChange,\n inputId,\n personalizationNameOverride,\n segmentNameOverride,\n }),\n })\n const addAction = defineDocumentFieldAction({\n name: `Add ${personalizationNameOverride}`,\n useAction: (props) =>\n useAddPersonalizationAction({\n ...props,\n active: false,\n onChange,\n inputId,\n personalizationNameOverride,\n }),\n })\n return active ? removeAction : addAction\n}\n\nexport const Field = (\n props: ObjectFieldProps & {\n personalizationNameOverride: string\n segmentNameOverride: string\n },\n) => {\n const {onChange} = props.inputProps\n const {inputId, personalizationNameOverride, segmentNameOverride} = props\n const active = props.value?.['active'] as boolean | undefined\n\n const actionProps = useMemo(\n () => ({\n onChange,\n inputId,\n active,\n personalizationNameOverride,\n segmentNameOverride,\n }),\n [onChange, inputId, active, personalizationNameOverride, segmentNameOverride],\n )\n\n const memoizedActions = useMemo(() => {\n const oldActions = props.actions || []\n return [createActions(actionProps), ...oldActions]\n }, [actionProps, props.actions])\n\n const enhancedProps = useMemo(() => {\n const propsWithClearedGroups = clearChildrenGroups(props)\n return {\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }\n }, [props, memoizedActions])\n\n return props.renderDefault(enhancedProps)\n}\n","import {Button, Inline, Stack} from '@sanity/ui'\nimport {type ObjectInputProps, set, useFormValue} from 'sanity'\n\nexport const SegmentInput = (props: ObjectInputProps) => {\n const personalizationPath = props.path.slice(0, -2)\n const defaultValue = useFormValue([...personalizationPath, 'default'])\n const handleClick = () => {\n props.onChange(set(defaultValue, ['value']))\n }\n return (\n <Stack gap={3}>\n {props.renderDefault(props)}\n\n <Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>\n </Stack>\n )\n}\n","import {useEffect, useState} from 'react'\nimport {\n isImage,\n isReference,\n type ObjectSchemaType,\n type PreviewProps,\n type ReferenceSchemaType,\n useClient,\n} from 'sanity'\n\nimport type {VariantPreviewProps} from '../../types'\nimport {usePersonalizationContext} from './Context'\n\nexport const SegmentPreview = (props: PreviewProps) => {\n const [subtitle, setSubtitle] = useState<string | undefined>(undefined)\n const [title, setTitle] = useState<string | undefined>(undefined)\n const [media, setMedia] = useState<any>(undefined)\n const {segments, apiVersion} = usePersonalizationContext()\n const client = useClient({apiVersion})\n\n const {segment, value} = props as VariantPreviewProps\n\n const selectedSegment = segments.find((segmentItem) => {\n return segmentItem.id === segment\n })\n\n useEffect(() => {\n const getSubtitle = async () => {\n setTitle(selectedSegment?.label)\n if (typeof value === 'string') {\n return setSubtitle(value)\n }\n if (isReference(value)) {\n const doc = await client.getDocument(value._ref)\n const type = props.schemaType as ObjectSchemaType\n const valueField = type.fields.find((field) => field.name === 'value') as ObjectSchemaType\n const referenceField = valueField?.type as ReferenceSchemaType\n const referenceType = referenceField.to.find((field) => field.type?.name === doc?._type)\n\n const selectFields = {} as Record<string, unknown>\n const previewFields = referenceType?.preview?.select || {}\n Object.keys(previewFields).forEach((key) => {\n const valueKey = referenceType?.preview?.select?.[key]\n selectFields[key] =\n valueKey && doc\n ? valueKey.split('.').reduce((acc: any, index) => acc?.[index], doc)\n : undefined\n })\n\n const previewContent = referenceType?.preview?.prepare?.(selectFields)\n setMedia(previewContent?.media || selectFields['media'])\n return setSubtitle(previewContent?.title || (selectFields['title'] as string))\n }\n if (isImage(value)) {\n setMedia(value)\n }\n return ''\n }\n void getSubtitle()\n }, [value, client, selectedSegment?.label, props.schemaType])\n\n const previewProps = {\n ...props,\n title: title,\n subtitle: subtitle,\n media: media,\n }\n\n return props.renderDefault(previewProps)\n}\n","import {\n type ArrayOfObjectsInputProps,\n defineField,\n definePlugin,\n defineType,\n type FieldDefinition,\n isObjectInputProps,\n} from 'sanity'\n\nimport {ArrayItem} from './components/ArrayItem'\nimport {\n ArrayInput,\n CONFIG_DEFAULT,\n Field,\n PersonalizationProvider,\n SegmentInput,\n SegmentPreview,\n} from './components/personalization'\nimport type {PersonalizationFieldPluginConfig} from './types'\nimport {flattenSchemaType} from './utils/flattenSchemaType'\n\nconst createPersonalizationType = ({\n field,\n personalizationNameOverride,\n segmentNameOverride,\n segmentId,\n segmentArrayName,\n}: {\n field: string | FieldDefinition\n personalizationNameOverride: string\n segmentNameOverride: string\n segmentId: string\n segmentArrayName: string\n}) => {\n const typeName = typeof field === `string` ? field : field.name\n const usedName = String(typeName[0]).toUpperCase() + typeName.slice(1)\n const segmentName = `${segmentNameOverride}${usedName}`\n\n return defineType({\n name: `${personalizationNameOverride}${usedName}`,\n type: 'object',\n groups: [\n {\n name: 'default',\n title: 'Default',\n hidden: ({parent}) => {\n return !Array.isArray(parent)\n },\n },\n {\n name: 'personalization',\n title: 'Personalization options',\n hidden: ({parent}) => {\n return !Array.isArray(parent)\n },\n },\n {\n name: 'all-fields',\n title: 'All fields',\n hidden: ({parent}) => {\n return Array.isArray(parent)\n },\n },\n ],\n components: {\n field: (props) => (\n <Field\n {...props}\n personalizationNameOverride={personalizationNameOverride}\n segmentNameOverride={segmentNameOverride}\n />\n ),\n item: ArrayItem,\n },\n fields: [\n typeof field === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'default',\n type: field,\n group: 'default',\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...field,\n name: 'default',\n group: 'default',\n },\n defineField({\n name: 'active',\n type: 'boolean',\n hidden: true,\n initialValue: false,\n }),\n defineField({\n name: segmentArrayName,\n type: 'array',\n hidden: ({parent}) => {\n return !parent?.active\n },\n group: 'personalization',\n components: {\n input: (props: ArrayOfObjectsInputProps) => (\n <ArrayInput {...props} segmentName={segmentName} segmentId={segmentId} />\n ),\n },\n of: [\n defineField({\n name: segmentName,\n type: segmentName,\n }),\n ],\n }),\n ],\n preview: {\n select: {\n base: 'default',\n },\n prepare: ({base}) => {\n const title =\n typeof base === 'string'\n ? base\n : base && typeof base === 'object'\n ? base.title || base.name || ''\n : ''\n const media =\n base && typeof base === 'object' ? base.image || base.photo || base.media || '' : ''\n return {\n title,\n media,\n }\n },\n },\n })\n}\n\nconst createSegmentType = ({\n field,\n segmentNameOverride,\n segmentId,\n}: {\n field: string | FieldDefinition\n segmentNameOverride: string\n segmentId: string\n}) => {\n const typeName = typeof field === `string` ? field : field.name\n const usedName = String(typeName[0]).toUpperCase() + typeName.slice(1)\n return defineType({\n name: `${segmentNameOverride}${usedName}`,\n title: `${segmentNameOverride} array ${usedName}`,\n type: 'object',\n components: {\n preview: SegmentPreview,\n input: SegmentInput,\n },\n fields: [\n {\n type: 'string',\n name: segmentId,\n readOnly: true,\n },\n typeof field === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'value',\n type: field,\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...field,\n name: 'value',\n },\n ],\n preview: {\n select: {\n segment: segmentId,\n value: 'value',\n },\n },\n })\n}\n\nconst fieldSchema = ({\n fields,\n personalizationNameOverride,\n segmentNameOverride,\n segmentId,\n segmentArrayName,\n}: Required<Omit<PersonalizationFieldPluginConfig, 'apiVersion' | 'segments'>>) => {\n return [\n ...fields.map((field) => createSegmentType({field, segmentNameOverride, segmentId})),\n ...fields.map((field) =>\n createPersonalizationType({\n field,\n personalizationNameOverride,\n segmentNameOverride,\n segmentId,\n segmentArrayName,\n }),\n ),\n ]\n}\n\nexport const fieldLevelPersonalization = definePlugin<PersonalizationFieldPluginConfig>(\n (config) => {\n const pluginConfig = {...CONFIG_DEFAULT, ...config}\n const {fields, personalizationNameOverride, segmentNameOverride} = pluginConfig\n\n const segmentArrayName = `${segmentNameOverride}s`\n const segmentId = `${segmentNameOverride}Id`\n\n const fieldSchemaConfig = fieldSchema({\n fields,\n personalizationNameOverride,\n segmentNameOverride,\n segmentId,\n segmentArrayName,\n })\n return {\n name: 'sanity-personalization-plugin-field-level-personalization',\n schema: {\n types: fieldSchemaConfig,\n },\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFields = flattenSchemaType(props.schemaType)\n const hasPersonalization = flatFields.some(\n (field) =>\n field.type.name.startsWith(personalizationNameOverride) ||\n field.name.startsWith(personalizationNameOverride),\n )\n\n if (!hasPersonalization) {\n return props.renderDefault(props)\n }\n\n const providerProps = {\n ...props,\n personalizationFieldPluginConfig: {\n ...pluginConfig,\n segmentId,\n segmentArrayName,\n },\n }\n return <PersonalizationProvider {...providerProps} />\n },\n },\n },\n }\n },\n)\n"],"mappings":";;;;;;;;;;;;AAUA,MAAa,iBAAiB;CAC5B,QAAQ,CAAC;CACT,YAAY;CACZ,6BAA6B;CAC7B,qBAAqB;CACrB,WAAW;CACX,kBAAkB;AACpB,GAEM,yBAAyB,cAA2C;CACxE,GAAG;CACH,UAAU,CAAC;AACb,CAAC;AAED,SAAgB,4BAA4B;CAC1C,OAAO,WAAW,sBAAsB;AAC1C;AAMA,SAAgB,wBAAwB,OAA6B;gBAC7D,EAAC,qCAAoC,OAElBA;CAA8CC,AAAAA,EAAAA,OAAAA,iCAAAA,0BAA9C,KAAA,EAAC,YAAY,iCAAiC,WAAU,GAAVA,EAAAA,KAAAA,iCAAAA;CAAvE,IAAM,SAAS,UAAUD,EAAyD,GAC5E,YAAY,aAAa,GAGdE;CAK0C,AAAA,EAAA,OAAA,UAAA,EAAA,OAL5BC,oCAAAA,EAAAA,OASxB,aATU,KAAA,MAAM,QAAQ,iCAAiC,QAAQ,IACpE,iCAAiC,WACjC,QACE,YACM,OAAO,iCAAiC,YAAa,aAChD,iCAAiC,SAAS,MAAM,IAElD,iCAAiC,UAE1C,CAAC,WAAW,6BAA6B,GACzC,EAAC,OAAA,OAAK,CACR,GANuD,EAAA,KAAA,QAL5BA,EAAAA,KAAAA,kCASxB,EAAA,KAAA;CATP,IAAM,WAAWD,IAcRE;CAAI,AAAA,EAAA,OAAA,oCAAA,EAAA,OAAkC,YAAtC,KAAA;EAAC,GAAG;EAAkC;CAAQ,GAA1C,EAAA,KAAA,kCAAkC,EAAA,KAAA;CAD/C,IAAM,UAAUC,IAOXC;gCAAM,KAAA,MAAA,cAAc,KAAK,GAAzBC,EAAAA,KAAAA;CADHC,IAAAA;CADF,OAC0C,EAAA,QAAA,WAAA,EAAA,QACrCF,MADH,KAAA,oBAACG,uBAAAA,UAAD;EAAiC,OAAO;EACrCH,UAAAA;CAC8B,CAAA,GAFO,EAAA,MAAA,SACrCA,EAAAA,MAAAA,8BADHE;AAIJ;ACvDA,MAAa,cAAc,UAA0C;gBAC7D,EAAC,cAAc,aAAa,cAAa,OAEzC,EAAC,aAAY,0BAA0B,GAG3CE;CAQE,AAAA,EAAA,OAAA,gBAAA,EAAA,OALG,aAAA,EAAA,OACM,eAJX,KAAA,OAAO,YAAyB;EAC9B,IAAM,OAAO;GACX,MAAM,KAAK;IACV,YAAY,QAAQ;GACrB,OAAO;EACT;EAGA,aAAa,IAAI;CACnB,GADE,EAAA,KAAA,cALG,EAAA,KAAA,WACM,EAAA,KAAA;CALb,IAAM,cAAcC,IAsBLC;CAAOC,AAAAA,EAAAA,OAAAA,MAAAA,qBAAP,KAAC,MAAM,SAAqB,CAAC,GAAtBA,EAAAA,KAAAA,MAAAA;CAAtB,IAAM,SAASD,IAQVE,IAHFC,IAGcC,IACVC,IAJOC,IACTC;CAUsB,IAAA,EAAA,OAAA,eAAA,EAAA,OAVE,SAAA,EAAA,OAJyB,aAAA,EAAA,OAO/C,YAAA,EAAA,QAPcC,QAAAA;EAArB,IAAM,eAAe,QAAQ,KAAK,cAAYC,UAAQ,UAAU;EAG7D,KAAA,OAAW,KAAA,GACe,EAAA,QAAA,sBAAxB,KAAA,MAAM,cAAc;GAAC,GAAG;GAAO,gBAAgBC;EAAU,CAAC,GAAlC,EAAA,MAAA,oBAExB,KAAA,QAAY,KAAA,GACV,KAAA,SAAS,KAAK,cAEX,oBAAC,QAAD;GAEE,MAAM,OAAOD,UAAQ;GACrB,MAAK;GACL,UAAU,cAAc,SAASA,UAAQ,EAAE;GAC3C,eAAe,YAAYA,SAAO;EACnC,GALMA,UAAQ,EAKd,CAEJ,GAHoB,EAAA,KAAA,aAVE,EAAA,KAAA,OAJyB,EAAA,KAAA,WAO/C,EAAA,KAAA,UAPcD,EAAAA,MAAAA;;CAMjBG,IAAAA;CAACT,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAAYE,MAAAA,EAAAA,QACVC,MADH,KAAA,oBAACH,IAAD;EAAQ,KAAKE;EACVC,UAAAA;CAWK,CAAA,GAZPH,EAAAA,MAAAA,IAAYE,EAAAA,MAAAA,IACVC,EAAAA,MAAAA;CAJLO,IAAAA;CADF,OACGT,EAAAA,QAAAA,MAAAA,EAAAA,QAAWG,MAAAA,EAAAA,QACTC,MAAAA,EAAAA,QAEDI,MAHF,KAAA,qBAACR,IAAD;EAAO,KAAKG;EAAZ,UAAA,CACGC,IAEDI,EAaK;KAhBNR,EAAAA,MAAAA,IAAWG,EAAAA,MAAAA,IACTC,EAAAA,MAAAA,IAEDI,EAAAA,MAAAA,8BAHFC;AAkBJ;AAjBsD,SAAA,UAAA;CAAM,OAAA;;ACtB5D,MAAM,+BACJ,UAE4B;eACtB,EAAC,UAAU,QAAQ,gCAA+B,OAEpBC;CACnB,AAAA,EAAA,OAAA,UAAA,EAAA,OAAf,YADkC,WAAM;EACxC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;CACrC,GADiB,EAAA,KAAA,QAAf,EAAA,KAAA;CADF,IAAM,kBAAkBC,IAKf,KAAA,OAAO,+BADTC;CAAP,OAIY,EAAA,OAAA,mBAAA,EAAA,OAHHC,MADF,KAAA;EACL,OAAOA;EACP,MAAM;EACN,MAAM;EACN,UAAU;EACV,gBAAgB;CAClB,GAFY,EAAA,KAAA,iBAHHA,EAAAA,KAAAA,4BADFD;AAOT,GAEM,kCACJ,UAM4B;eACtB,EAAC,UAAU,QAAQ,6BAA6B,wBAAuB,OACvCE;CAGrB,AAAA,EAAA,OAAA,UAAA,EAAA,OAAf,YAAA,EAAA,OADqB,uBAFe,WAAM;EAC1C,IAAM,WAAW,CAAC,QAAQ,GACpB,WAAW,CAAC,GAAG,oBAAoB,EAAE;EAC3C,SAAS,CAAC,IAAI,CAAC,QAAQ,QAAQ,GAAG,MAAM,QAAQ,CAAC,CAAC;CACpD,GADiB,EAAA,KAAA,QAAf,EAAA,KAAA,UADqB,EAAA,KAAA;CAFvB,IAAM,oBAAoBC,IAOjB,KAAA,UAAU,+BADZC;CAAP,OAIY,EAAA,OAAA,qBAAA,EAAA,OAHHC,MADF,KAAA;EACL,OAAOA;EACP,MAAM;EACN,MAAM;EACN,UAAU;EACV,gBAAgB;CAClB,GAFY,EAAA,KAAA,mBAHHA,EAAAA,KAAAA,4BADFD;AAOT,GAEM,iBAAiB,EACrB,UACA,SACA,QACA,6BACA,0BAKI;CACJ,IAAM,eAAe,0BAA0B;EAC7C,MAAM,UAAU;EAChB,YAAY,UACV,+BAA+B;GAC7B,GAAG;GACH,QAAQ;GACR;GACA;GACA;GACA;EACF,CAAC;CACL,CAAC,GACK,YAAY,0BAA0B;EAC1C,MAAM,OAAO;EACb,YAAY,UACV,4BAA4B;GAC1B,GAAG;GACH,QAAQ;GACR;GACA;GACA;EACF,CAAC;CACL,CAAC;CACD,OAAO,SAAS,eAAe;AACjC,GAEa,SACX,UAIG;gBACG,EAAC,aAAY,MAAM,YACnB,EAAC,SAAS,6BAA6B,wBAAuB,OAC9D,SAAS,MAAM,OAAQ,QAGpBE;CAGL,AAAA,EAAA,OAAA,UAAA,EAAA,OADA,WAAA,EAAA,OADA,YAAA,EAAA,OAGA,+BAAA,EAAA,OACA,uBALK,KAAA;EACL;EACA;EACA;EACA;EACA;CACF,GAHE,EAAA,KAAA,QADA,EAAA,KAAA,SADA,EAAA,KAAA,UAGA,EAAA,KAAA,6BACA,EAAA,KAAA;CANJ,IAAM,cAAcC,IAYCC;CAAMC,AAAAA,EAAAA,OAAAA,MAAAA,uBAAN,KAAA,MAAM,WAAW,CAAC,GAAZA,EAAAA,KAAAA,MAAAA;CAAzB,IAAM,aAAaD,IACXE;CAAc,AAAA,EAAA,OAAA,2BAAd,KAAA,cAAc,WAAW,GAAX,EAAA,KAAA;CAAfC,IAAAA;CAAgC,AAAA,EAAA,QAAA,cAAA,EAAA,QAA/BD,MAAD,KAAA,CAACA,IAA4B,GAAG,UAAU,GAAV,EAAA,MAAA,YAA/BA,EAAAA,MAAAA;CAFV,IAAM,kBAAkBE,IAMSC;CAAoB,AAAA,EAAA,QAAA,sBAApB,KAAA,oBAAoB,KAAK,GAAL,EAAA,MAAA;CAAnD,IAAM,yBAAyBA,IACxBC;CAEI,AAAA,EAAA,QAAA,mBAAA,EAAA,QADN,0BADE,KAAA;EACL,GAAG;EACH,SAAS;CACX,GADW,EAAA,MAAA,iBADN,EAAA,MAAA;CAHP,IAAM,gBAAgBC,IAQfC;CAAP,OAA2B,EAAA,QAAA,iBAAA,EAAA,QAAdC,MAAAA,iBAAN,KAAA,MAAM,cAAc,aAAa,GAAb,EAAA,MAAA,eAAdA,EAAAA,MAAAA,MAAAA,yCAAND;AACT,GClIa,gBAAgB,UAA4B;gBAElCE,IAAaC;CADAC,IAAAA,EAAAA,OAAAA,MAAAA,MAAAA;EAAlC,IAAM,sBAAsB,MAAM,KAAK,MAAM,GAAG,EAAE;EAC7B,KAAA,cAAa,KAAA,CAAC,GAAG,qBAAqB,SAAS,GADlCA,EAAAA,KAAAA,MAAAA;;CAClC,IAAM,eAAeF,GAAaC,EAAmC,GACjDE;CACC,AAAA,EAAA,OAAA,gBAAA,EAAA,OAAnB,SADkB,WAAM;EACxB,MAAM,SAAS,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;CAC7C,GADqB,EAAA,KAAA,cAAnB,EAAA,KAAA;CADF,IAAM,cAAcA,IAKfC;+BAAM,KAAA,MAAA,cAAc,KAAK,GAAzBC,EAAAA,KAAAA;CAEDC,IAAAA;CAC0D,AAAA,EAAA,OAAA,2BAD1D,KAAA,oBAAC,QAAD;EAAQ,KAAK;EACX,UAAA,oBAAC,QAAD;GAAQ,MAAK;GAAe,MAAK;GAAQ,eAAe,YAAY;EAAI,CAAA;CAClE,CAAA,GADkD,EAAA,KAAA;CAJ5DC,IAAAA;CADF,OAEKH,EAAAA,QAAAA,MAAAA,EAAAA,QAEDE,MAHF,KAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACGF,IAEDE,EAGK;KALJF,EAAAA,MAAAA,IAEDE,EAAAA,MAAAA,8BAHFC;AAQJ,GCLa,kBAAkB,UAAwB;gBAC/C,CAAC,UAAU,eAAe,SAA6B,KAAA,CAAS,GAChE,CAAC,OAAO,YAAY,SAA6B,KAAA,CAAS,GAC1D,CAAC,OAAO,YAAY,SAAc,KAAA,CAAS,GAC3C,EAAC,UAAU,eAAc,0BAA0B,GAChCC;CAAC,AAAA,EAAA,OAAA,0BAAD,KAAA,EAAC,WAAU,GAAV,EAAA,KAAA;CAA1B,IAAM,SAAS,UAAUA,EAAY,GAE/B,EAAC,SAAS,UAAS,OAEDC;CACI,IAAA,EAAA,OAAA,WAAA,EAAA,OADJ,UAAA;EAAcC,IAAAA;EACV,EAAA,OAAA,uBADU,MAAC,gBAC9B,YAAY,OAAO,qCADJ,KAAA,SAAS,KAAKA,EAErC,GAD2B,EAAA,KAAA,SADJ,EAAA,KAAA;;CAAxB,IAAM,kBAAkBD,IAIdE;CAOc,AAAA,EAAA,OAAA,UAAA,EAAA,OACCC,MAAAA,cAAAA,EAAAA,OANKC,iBAAAA,SAAAA,EAAAA,QACf,SAHL,WAAM;EACd,IAAM,cAAc,YAAY;GAE9B,IADA,SAAS,iBAAiB,KAAK,GAC3B,OAAO,SAAU,UACnB,OAAO,YAAY,KAAK;GAE1B,IAAI,YAAY,KAAK,GAAG;IACtB,IAAM,MAAM,MAAM,OAAO,YAAY,MAAM,IAAI,GAIzC,iBAHO,MAAM,WACK,OAAO,KAAKC,KACb,CAAA,EAAY,KAAA,CACE,GAAG,MAAM,YAAUC,QAAM,MAAM,SAAS,KAAK,KAAK,GAEjF,eAAe,CAAC,GAChB,gBAAgB,eAAe,SAAS,UAAU,CAAC;IACzD,OAAO,KAAK,aAAa,CAAC,CAAC,SAAS,QAAQ;KAC1C,IAAM,WAAW,eAAe,SAAS,SAAS;KAClD,aAAa,OACX,YAAY,MACR,SAAS,MAAM,GAAG,CAAC,CAAC,OAAOC,QAAmC,GAAG,IACjE,KAAA;IACR,CAAC;IAED,IAAM,iBAAiB,eAAe,SAAS,UAAU,YAAY;IAErE,OADA,SAAS,gBAAgB,SAAS,aAAa,KAAQ,GAChD,YAAY,gBAAgB,SAAU,aAAa,KAAmB;GAC/E;GAIA,OAHI,QAAQ,KAAK,KACf,SAAS,KAAK,GAET;EACT;EACK,YAAY;CACnB,GA1BwB,EAAA,KAAA,QACCJ,EAAAA,KAAAA,MAAAA,YANKC,EAAAA,KAAAA,iBAAAA,OACf,EAAA,MAAA;CA8BI,IAAA,KAAA,iBAAiB,OAAjCI;CAjCH,AAiCW,EAAA,QAAA,UAAA,EAAA,QAAsCL,MAAAA,cAAAA,EAAAA,QAA9BM,MAAAA,EAAAA,QAAf,SAAD,KAAA;EAAC;EAAO;EAAQA;EAAwB,MAAM;CAAU,GAAhD,EAAA,MAAA,QAAsCN,EAAAA,MAAAA,MAAAA,YAA9BM,EAAAA,MAAAA,IAAf,EAAA,MAAA,iCAjCJ,UAAUP,IAiCPM,EAAyD;CASrDE,IAAAA;CAHE,IAAA,EAAA,QAAA,SAAA,EAAA,QAHJ,SAAA,EAAA,QAEO,YAAA,EAAA,QADH,OAAA;EAFT,IAAM,eAAe;GACnB,GAAG;GACI;GACG;GACH;EACT;EAEO,KAAA,MAAM,cAAc,YAAY,GAH9B,EAAA,MAAA,OAHJ,EAAA,MAAA,OAEO,EAAA,MAAA,UADH,EAAA,MAAA;;CAKT,OAAOA;AACT;AAlC4C,SAAA,MAAC,OAAA;CAAU,OAAA,MAAM,SAAS;;AAU3B,SAAA,OAAC,KAAU,OAAA;CAAU,OAAA,MAAM;;ACxBtE,MAAM,6BAA6B,EACjC,OACA,6BACA,qBACA,WACA,uBAOI;CACJ,IAAM,WAAW,OAAO,SAAU,WAAW,QAAQ,MAAM,MACrD,WAAW,OAAO,SAAS,EAAE,CAAC,CAAC,YAAY,IAAI,SAAS,MAAM,CAAC,GAC/D,cAAc,GAAG,sBAAsB;CAE7C,OAAO,WAAW;EAChB,MAAM,GAAG,8BAA8B;EACvC,MAAM;EACN,QAAQ;GACN;IACE,MAAM;IACN,OAAO;IACP,SAAS,EAAC,aACD,CAAC,MAAM,QAAQ,MAAM;GAEhC;GACA;IACE,MAAM;IACN,OAAO;IACP,SAAS,EAAC,aACD,CAAC,MAAM,QAAQ,MAAM;GAEhC;GACA;IACE,MAAM;IACN,OAAO;IACP,SAAS,EAAC,aACD,MAAM,QAAQ,MAAM;GAE/B;EACF;EACA,YAAY;GACV,QAAQ,UACN,oBAAC,OAAD;IACE,GAAI;IACyB;IACR;GACtB,CAAA;GAEH,MAAM;EACR;EACA,QAAQ;GACN,OAAO,SAAU,WAEb,YAAY;IACV,MAAM;IACN,MAAM;IACN,OAAO;GACT,CAAC,IAED;IACE,GAAG;IACH,MAAM;IACN,OAAO;GACT;GACJ,YAAY;IACV,MAAM;IACN,MAAM;IACN,QAAQ;IACR,cAAc;GAChB,CAAC;GACD,YAAY;IACV,MAAM;IACN,MAAM;IACN,SAAS,EAAC,aACD,CAAC,QAAQ;IAElB,OAAO;IACP,YAAY,EACV,QAAQ,UACN,oBAAC,YAAD;KAAY,GAAI;KAAoB;KAAwB;IAAY,CAAA,EAE5E;IACA,IAAI,CACF,YAAY;KACV,MAAM;KACN,MAAM;IACR,CAAC,CACH;GACF,CAAC;EACH;EACA,SAAS;GACP,QAAQ,EACN,MAAM,UACR;GACA,UAAU,EAAC,YASF;IACL,OARA,OAAO,QAAS,WACZ,OACA,QAAQ,OAAO,QAAS,aACtB,KAAK,SAAS,KAAK,SACnB;IAKN,OAHA,QAAQ,OAAO,QAAS,aAAW,KAAK,SAAS,KAAK,SAAS,KAAK,UAAc;GAIpF;EAEJ;CACF,CAAC;AACH,GAEM,qBAAqB,EACzB,OACA,qBACA,gBAKI;CACJ,IAAM,WAAW,OAAO,SAAU,WAAW,QAAQ,MAAM,MACrD,WAAW,OAAO,SAAS,EAAE,CAAC,CAAC,YAAY,IAAI,SAAS,MAAM,CAAC;CACrE,OAAO,WAAW;EAChB,MAAM,GAAG,sBAAsB;EAC/B,OAAO,GAAG,oBAAoB,SAAS;EACvC,MAAM;EACN,YAAY;GACV,SAAS;GACT,OAAO;EACT;EACA,QAAQ,CACN;GACE,MAAM;GACN,MAAM;GACN,UAAU;EACZ,GACA,OAAO,SAAU,WAEb,YAAY;GACV,MAAM;GACN,MAAM;EACR,CAAC,IAED;GACE,GAAG;GACH,MAAM;EACR,CACN;EACA,SAAS,EACP,QAAQ;GACN,SAAS;GACT,OAAO;EACT,EACF;CACF,CAAC;AACH,GAEM,eAAe,EACnB,QACA,6BACA,qBACA,WACA,uBAEO,CACL,GAAG,OAAO,KAAK,UAAU,kBAAkB;CAAC;CAAO;CAAqB;AAAS,CAAC,CAAC,GACnF,GAAG,OAAO,KAAK,UACb,0BAA0B;CACxB;CACA;CACA;CACA;CACA;AACF,CAAC,CACH,CACF,GAGW,4BAA4B,cACtC,WAAW;CACV,IAAM,eAAe;EAAC,GAAG;EAAgB,GAAG;CAAM,GAC5C,EAAC,QAAQ,6BAA6B,wBAAuB,cAE7D,mBAAmB,GAAG,oBAAoB,IAC1C,YAAY,GAAG,oBAAoB;CASzC,OAAO;EACL,MAAM;EACN,QAAQ,EACN,OAVsB,YAAY;GACpC;GACA;GACA;GACA;GACA;EACF,CAIW,EACT;EACA,MAAM,EACJ,YAAY,EACV,QAAQ,UAAU;GAchB,IAXI,EAFgB,MAAM,OAAO,UAAU,mBAAmB,KAAK,MAa/D,CAPe,kBAAkB,MAAM,UAChB,CAAA,CAAW,MACnC,UACC,MAAM,KAAK,KAAK,WAAW,2BAA2B,KACtD,MAAM,KAAK,WAAW,2BAA2B,CAGhD,GACH,OAAO,MAAM,cAAc,KAAK;GAGlC,IAAM,gBAAgB;IACpB,GAAG;IACH,kCAAkC;KAChC,GAAG;KACH;KACA;IACF;GACF;GACA,OAAO,oBAAC,yBAAD,EAAyB,GAAI,cAAgB,CAAA;EACtD,EACF,EACF;CACF;AACF,CACF"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["{apiVersion: personalizationFieldPluginConfig.apiVersion}","apiVersion","Array.isArray(personalizationFieldPluginConfig.segments)\n ? personalizationFieldPluginConfig.segments\n : suspend(\n async () => {\n if (typeof personalizationFieldPluginConfig.segments === 'function') {\n return personalizationFieldPluginConfig.segments(client)\n }\n return personalizationFieldPluginConfig.segments\n },\n [workspace, 'field-level-personalization'],\n {equal},\n )","personalizationFieldPluginConfig.segments","{...personalizationFieldPluginConfig, segments}","useMemo(\n () => ({...personalizationFieldPluginConfig, segments}),\n [personalizationFieldPluginConfig, segments],\n )","props.renderDefault(props)","props.renderDefault","<PersonalizationContext.Provider value={context}>\n {props.renderDefault(props)}\n </PersonalizationContext.Provider>","PersonalizationContext.Provider","_c","async (segment: VariantType) => {\n const item = {\n _key: uuid(),\n [segmentId]: segment.id,\n _type: segmentName,\n }\n\n // Patch the document\n onItemAppend(item)\n }","useCallback(\n async (segment: VariantType) => {\n const item = {\n _key: uuid(),\n [segmentId]: segment.id,\n _type: segmentName,\n }\n\n // Patch the document\n onItemAppend(item)\n },\n [segmentId, segmentName, onItemAppend],\n )","(props.value as Value[]) || []","value","Inline","Stack","1","segments.map((segment) => {\n return (\n <Button\n key={segment.id}\n text={`Add ${segment.label}`}\n mode=\"ghost\"\n disabled={usedSegments?.includes(segment.id)}\n onClick={() => handleClick(segment)}\n />\n )\n })","3","props.renderDefault({...props, arrayFunctions: () => null})","values?.map","segment","() => null","<Inline gap={1}>\n {segments.map((segment) => {\n return (\n <Button\n key={segment.id}\n text={`Add ${segment.label}`}\n mode=\"ghost\"\n disabled={usedSegments?.includes(segment.id)}\n onClick={() => handleClick(segment)}\n />\n )\n })}\n </Inline>","<Stack gap={3}>\n {props.renderDefault({...props, arrayFunctions: () => null})}\n\n <Inline gap={1}>\n {segments.map((segment) => {\n return (\n <Button\n key={segment.id}\n text={`Add ${segment.label}`}\n mode=\"ghost\"\n disabled={usedSegments?.includes(segment.id)}\n onClick={() => handleClick(segment)}\n />\n )\n })}\n </Inline>\n </Stack>","_c","_temp","() => {\n onChange([set(!active, ['active'])])\n }","useCallback(() => {\n onChange([set(!active, ['active'])])\n }, [onChange, active])","{\n title: `Add ${personalizationNameOverride}`,\n type: 'action',\n icon: IoMdPeople,\n onAction: handleAddAction,\n renderAsButton: true,\n }","`Add ${personalizationNameOverride}`","() => {\n const activeId = ['active']\n const segments = [`${segmentNameOverride}s`]\n onChange([set(!active, activeId), unset(segments)])\n }","useCallback(() => {\n const activeId = ['active']\n const segments = [`${segmentNameOverride}s`]\n onChange([set(!active, activeId), unset(segments)])\n }, [onChange, active, segmentNameOverride])","{\n title: `Remove ${personalizationNameOverride}`,\n type: 'action',\n icon: CloseIcon,\n onAction: handleClearAction,\n renderAsButton: true,\n }","`Remove ${personalizationNameOverride}`","{\n onChange,\n inputId,\n active,\n personalizationNameOverride,\n segmentNameOverride,\n }","useMemo(\n () => ({\n onChange,\n inputId,\n active,\n personalizationNameOverride,\n segmentNameOverride,\n }),\n [onChange, inputId, active, personalizationNameOverride, segmentNameOverride],\n )","props.actions || []","actions","createActions(actionProps)","[createActions(actionProps), ...oldActions]","useMemo(() => {\n const oldActions = props.actions || []\n return [createActions(actionProps), ...oldActions]\n }, [actionProps, props.actions])","clearChildrenGroups(props)","{\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }","useMemo(() => {\n const propsWithClearedGroups = clearChildrenGroups(props)\n return {\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }\n }, [props, memoizedActions])","props.renderDefault(enhancedProps)","renderDefault","_c","useFormValue","[...personalizationPath, 'default']","path","() => {\n props.onChange(set(defaultValue, ['value']))\n }","props.renderDefault(props)","props.renderDefault","<Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>","<Stack gap={3}>\n {props.renderDefault(props)}\n\n <Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>\n </Stack>","_c","{apiVersion}","segments.find((segmentItem) => {\n return segmentItem.id === segment\n })","(segmentItem) => {\n return segmentItem.id === segment\n }","() => {\n const getSubtitle = async () => {\n setTitle(selectedSegment?.label)\n if (typeof value === 'string') {\n return setSubtitle(value)\n }\n if (isReference(value)) {\n const doc = await client.getDocument(value._ref)\n const type = props.schemaType as ObjectSchemaType\n const valueField = type.fields.find((field) => field.name === 'value') as ObjectSchemaType\n const referenceField = valueField?.type as ReferenceSchemaType\n const referenceType = referenceField.to.find((field) => field.type?.name === doc?._type)\n\n const selectFields = {} as Record<string, unknown>\n const previewFields = referenceType?.preview?.select || {}\n Object.keys(previewFields).forEach((key) => {\n const valueKey = referenceType?.preview?.select?.[key]\n selectFields[key] =\n valueKey && doc\n ? valueKey.split('.').reduce((acc: any, index) => acc?.[index], doc)\n : undefined\n })\n\n const previewContent = referenceType?.preview?.prepare?.(selectFields)\n setMedia(previewContent?.media || selectFields['media'])\n return setSubtitle(previewContent?.title || (selectFields['title'] as string))\n }\n if (isImage(value)) {\n setMedia(value)\n }\n return ''\n }\n void getSubtitle()\n }","schemaType","label","(field) => field.name === 'value'","field","(acc: any, index) => acc?.[index]","[value, client, selectedSegment?.label, props.schemaType]","selectedSegment?.label","props.renderDefault(previewProps)","_c","\"active\"","\"media\"","\"title\""],"sources":["../src/components/personalization/Context.tsx","../src/components/personalization/Array.tsx","../src/components/personalization/Field.tsx","../src/components/personalization/SegmentInput.tsx","../src/components/personalization/SegmentPreview.tsx","../src/fieldPersonalization.tsx"],"sourcesContent":["import {dequal as equal} from 'dequal/lite'\nimport {createContext, useContext, useMemo} from 'react'\nimport {type ObjectInputProps, useClient, useWorkspace} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport type {PersonalizationContextProps, PersonalizationFieldPluginConfig} from '../../types'\n\n// This provider makes the plugin config available to all components in the document form\n// But with segments resolved\n\nexport const CONFIG_DEFAULT = {\n fields: [],\n apiVersion: '2024-11-07',\n personalizationNameOverride: 'personalization',\n segmentNameOverride: 'segment',\n segmentId: 'segmentId',\n segmentArrayName: 'segments',\n}\n\nconst PersonalizationContext = createContext<PersonalizationContextProps>({\n ...CONFIG_DEFAULT,\n segments: [],\n})\n\nexport function usePersonalizationContext() {\n return useContext(PersonalizationContext)\n}\n\ntype PersonalizationProps = ObjectInputProps & {\n personalizationFieldPluginConfig: Required<PersonalizationFieldPluginConfig>\n}\n\nexport function PersonalizationProvider(props: PersonalizationProps) {\n const {personalizationFieldPluginConfig} = props\n\n const client = useClient({apiVersion: personalizationFieldPluginConfig.apiVersion})\n const workspace = useWorkspace()\n\n // Fetch or return segments\n const segments = Array.isArray(personalizationFieldPluginConfig.segments)\n ? personalizationFieldPluginConfig.segments\n : suspend(\n async () => {\n if (typeof personalizationFieldPluginConfig.segments === 'function') {\n return personalizationFieldPluginConfig.segments(client)\n }\n return personalizationFieldPluginConfig.segments\n },\n [workspace, 'field-level-personalization'],\n {equal},\n )\n\n const context = useMemo(\n () => ({...personalizationFieldPluginConfig, segments}),\n [personalizationFieldPluginConfig, segments],\n )\n\n return (\n <PersonalizationContext.Provider value={context}>\n {props.renderDefault(props)}\n </PersonalizationContext.Provider>\n )\n}\n","import {Button, Inline, Stack} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {useCallback} from 'react'\n\nimport type {PersonalizationArrayInputProps, VariantType} from '../../types'\nimport {usePersonalizationContext} from './Context'\n\nexport const ArrayInput = (props: PersonalizationArrayInputProps) => {\n const {onItemAppend, segmentName, segmentId} = props\n\n const {segments} = usePersonalizationContext()\n\n const handleClick = useCallback(\n async (segment: VariantType) => {\n const item = {\n _key: uuid(),\n [segmentId]: segment.id,\n _type: segmentName,\n }\n\n // Patch the document\n onItemAppend(item)\n },\n [segmentId, segmentName, onItemAppend],\n )\n\n type Value = {\n value?: unknown\n [key: string]: unknown\n segmentId: string\n _key: string\n _type: string\n }\n\n const values = (props.value as Value[]) || []\n\n const usedSegments = values?.map((segment) => segment[segmentId])\n\n return (\n <Stack gap={3}>\n {props.renderDefault({...props, arrayFunctions: () => null})}\n\n <Inline gap={1}>\n {segments.map((segment) => {\n return (\n <Button\n key={segment.id}\n text={`Add ${segment.label}`}\n mode=\"ghost\"\n disabled={usedSegments?.includes(segment.id)}\n onClick={() => handleClick(segment)}\n />\n )\n })}\n </Inline>\n </Stack>\n )\n}\n","import {CloseIcon} from '@sanity/icons/Close'\nimport {useCallback, useMemo} from 'react'\nimport {IoMdPeople} from 'react-icons/io'\nimport {\n defineDocumentFieldAction,\n type DocumentFieldActionItem,\n type DocumentFieldActionProps,\n type FormPatch,\n type ObjectFieldProps,\n type PatchEvent,\n set,\n unset,\n} from 'sanity'\n\nimport {clearChildrenGroups} from '../../utils/clearChildGroups'\n\ntype PatchStuff = {onChange: (patch: FormPatch | FormPatch[] | PatchEvent) => void; inputId: string}\n\nconst useAddPersonalizationAction = (\n props: DocumentFieldActionProps &\n PatchStuff & {personalizationNameOverride: string; active: boolean},\n): DocumentFieldActionItem => {\n const {onChange, active, personalizationNameOverride} = props\n\n const handleAddAction = useCallback(() => {\n onChange([set(!active, ['active'])])\n }, [onChange, active])\n\n return {\n title: `Add ${personalizationNameOverride}`,\n type: 'action',\n icon: IoMdPeople,\n onAction: handleAddAction,\n renderAsButton: true,\n }\n}\n\nconst useRemovePersonalizationAction = (\n props: DocumentFieldActionProps &\n PatchStuff & {\n personalizationNameOverride: string\n active: boolean\n segmentNameOverride: string\n },\n): DocumentFieldActionItem => {\n const {onChange, active, personalizationNameOverride, segmentNameOverride} = props\n const handleClearAction = useCallback(() => {\n const activeId = ['active']\n const segments = [`${segmentNameOverride}s`]\n onChange([set(!active, activeId), unset(segments)])\n }, [onChange, active, segmentNameOverride])\n\n return {\n title: `Remove ${personalizationNameOverride}`,\n type: 'action',\n icon: CloseIcon,\n onAction: handleClearAction,\n renderAsButton: true,\n }\n}\n\nconst createActions = ({\n onChange,\n inputId,\n active,\n personalizationNameOverride,\n segmentNameOverride,\n}: PatchStuff & {\n active?: boolean\n personalizationNameOverride: string\n segmentNameOverride: string\n}) => {\n const removeAction = defineDocumentFieldAction({\n name: `Remove ${personalizationNameOverride}`,\n useAction: (props) =>\n useRemovePersonalizationAction({\n ...props,\n active: true,\n onChange,\n inputId,\n personalizationNameOverride,\n segmentNameOverride,\n }),\n })\n const addAction = defineDocumentFieldAction({\n name: `Add ${personalizationNameOverride}`,\n useAction: (props) =>\n useAddPersonalizationAction({\n ...props,\n active: false,\n onChange,\n inputId,\n personalizationNameOverride,\n }),\n })\n return active ? removeAction : addAction\n}\n\nexport const Field = (\n props: ObjectFieldProps & {\n personalizationNameOverride: string\n segmentNameOverride: string\n },\n) => {\n const {onChange} = props.inputProps\n const {inputId, personalizationNameOverride, segmentNameOverride} = props\n const active = props.value?.['active'] as boolean | undefined\n\n const actionProps = useMemo(\n () => ({\n onChange,\n inputId,\n active,\n personalizationNameOverride,\n segmentNameOverride,\n }),\n [onChange, inputId, active, personalizationNameOverride, segmentNameOverride],\n )\n\n const memoizedActions = useMemo(() => {\n const oldActions = props.actions || []\n return [createActions(actionProps), ...oldActions]\n }, [actionProps, props.actions])\n\n const enhancedProps = useMemo(() => {\n const propsWithClearedGroups = clearChildrenGroups(props)\n return {\n ...propsWithClearedGroups,\n actions: memoizedActions,\n }\n }, [props, memoizedActions])\n\n return props.renderDefault(enhancedProps)\n}\n","import {Button, Inline, Stack} from '@sanity/ui'\nimport {type ObjectInputProps, set, useFormValue} from 'sanity'\n\nexport const SegmentInput = (props: ObjectInputProps) => {\n const personalizationPath = props.path.slice(0, -2)\n const defaultValue = useFormValue([...personalizationPath, 'default'])\n const handleClick = () => {\n props.onChange(set(defaultValue, ['value']))\n }\n return (\n <Stack gap={3}>\n {props.renderDefault(props)}\n\n <Inline gap={1}>\n <Button text=\"Copy default\" mode=\"ghost\" onClick={() => handleClick()} />\n </Inline>\n </Stack>\n )\n}\n","import {useEffect, useState} from 'react'\nimport {\n isImage,\n isReference,\n type ObjectSchemaType,\n type PreviewProps,\n type ReferenceSchemaType,\n useClient,\n} from 'sanity'\n\nimport type {VariantPreviewProps} from '../../types'\nimport {usePersonalizationContext} from './Context'\n\nexport const SegmentPreview = (props: PreviewProps) => {\n const [subtitle, setSubtitle] = useState<string | undefined>(undefined)\n const [title, setTitle] = useState<string | undefined>(undefined)\n const [media, setMedia] = useState<any>(undefined)\n const {segments, apiVersion} = usePersonalizationContext()\n const client = useClient({apiVersion})\n\n const {segment, value} = props as VariantPreviewProps\n\n const selectedSegment = segments.find((segmentItem) => {\n return segmentItem.id === segment\n })\n\n useEffect(() => {\n const getSubtitle = async () => {\n setTitle(selectedSegment?.label)\n if (typeof value === 'string') {\n return setSubtitle(value)\n }\n if (isReference(value)) {\n const doc = await client.getDocument(value._ref)\n const type = props.schemaType as ObjectSchemaType\n const valueField = type.fields.find((field) => field.name === 'value') as ObjectSchemaType\n const referenceField = valueField?.type as ReferenceSchemaType\n const referenceType = referenceField.to.find((field) => field.type?.name === doc?._type)\n\n const selectFields = {} as Record<string, unknown>\n const previewFields = referenceType?.preview?.select || {}\n Object.keys(previewFields).forEach((key) => {\n const valueKey = referenceType?.preview?.select?.[key]\n selectFields[key] =\n valueKey && doc\n ? valueKey.split('.').reduce((acc: any, index) => acc?.[index], doc)\n : undefined\n })\n\n const previewContent = referenceType?.preview?.prepare?.(selectFields)\n setMedia(previewContent?.media || selectFields['media'])\n return setSubtitle(previewContent?.title || (selectFields['title'] as string))\n }\n if (isImage(value)) {\n setMedia(value)\n }\n return ''\n }\n void getSubtitle()\n }, [value, client, selectedSegment?.label, props.schemaType])\n\n const previewProps = {\n ...props,\n title: title,\n subtitle: subtitle,\n media: media,\n }\n\n return props.renderDefault(previewProps)\n}\n","import {\n type ArrayOfObjectsInputProps,\n defineField,\n definePlugin,\n defineType,\n type FieldDefinition,\n isObjectInputProps,\n} from 'sanity'\n\nimport {ArrayItem} from './components/ArrayItem'\nimport {\n ArrayInput,\n CONFIG_DEFAULT,\n Field,\n PersonalizationProvider,\n SegmentInput,\n SegmentPreview,\n} from './components/personalization'\nimport type {PersonalizationFieldPluginConfig} from './types'\nimport {flattenSchemaType} from './utils/flattenSchemaType'\n\nconst createPersonalizationType = ({\n field,\n personalizationNameOverride,\n segmentNameOverride,\n segmentId,\n segmentArrayName,\n}: {\n field: string | FieldDefinition\n personalizationNameOverride: string\n segmentNameOverride: string\n segmentId: string\n segmentArrayName: string\n}) => {\n const typeName = typeof field === `string` ? field : field.name\n const usedName = String(typeName[0]).toUpperCase() + typeName.slice(1)\n const segmentName = `${segmentNameOverride}${usedName}`\n\n return defineType({\n name: `${personalizationNameOverride}${usedName}`,\n type: 'object',\n groups: [\n {\n name: 'default',\n title: 'Default',\n hidden: ({parent}) => {\n return !Array.isArray(parent)\n },\n },\n {\n name: 'personalization',\n title: 'Personalization options',\n hidden: ({parent}) => {\n return !Array.isArray(parent)\n },\n },\n {\n name: 'all-fields',\n title: 'All fields',\n hidden: ({parent}) => {\n return Array.isArray(parent)\n },\n },\n ],\n components: {\n field: (props) => (\n <Field\n {...props}\n personalizationNameOverride={personalizationNameOverride}\n segmentNameOverride={segmentNameOverride}\n />\n ),\n item: ArrayItem,\n },\n fields: [\n typeof field === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'default',\n type: field,\n group: 'default',\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...field,\n name: 'default',\n group: 'default',\n },\n defineField({\n name: 'active',\n type: 'boolean',\n hidden: true,\n initialValue: false,\n }),\n defineField({\n name: segmentArrayName,\n type: 'array',\n hidden: ({parent}) => {\n return !parent?.active\n },\n group: 'personalization',\n components: {\n input: (props: ArrayOfObjectsInputProps) => (\n <ArrayInput {...props} segmentName={segmentName} segmentId={segmentId} />\n ),\n },\n of: [\n defineField({\n name: segmentName,\n type: segmentName,\n }),\n ],\n }),\n ],\n preview: {\n select: {\n base: 'default',\n },\n prepare: ({base}) => {\n const title =\n typeof base === 'string'\n ? base\n : base && typeof base === 'object'\n ? base.title || base.name || ''\n : ''\n const media =\n base && typeof base === 'object' ? base.image || base.photo || base.media || '' : ''\n return {\n title,\n media,\n }\n },\n },\n })\n}\n\nconst createSegmentType = ({\n field,\n segmentNameOverride,\n segmentId,\n}: {\n field: string | FieldDefinition\n segmentNameOverride: string\n segmentId: string\n}) => {\n const typeName = typeof field === `string` ? field : field.name\n const usedName = String(typeName[0]).toUpperCase() + typeName.slice(1)\n return defineType({\n name: `${segmentNameOverride}${usedName}`,\n title: `${segmentNameOverride} array ${usedName}`,\n type: 'object',\n components: {\n preview: SegmentPreview,\n input: SegmentInput,\n },\n fields: [\n {\n type: 'string',\n name: segmentId,\n readOnly: true,\n },\n typeof field === `string`\n ? // Define a simple field if all we have is the name as a string\n defineField({\n name: 'value',\n type: field,\n })\n : // Pass in the configured options, but overwrite the name\n {\n ...field,\n name: 'value',\n },\n ],\n preview: {\n select: {\n segment: segmentId,\n value: 'value',\n },\n },\n })\n}\n\nconst fieldSchema = ({\n fields,\n personalizationNameOverride,\n segmentNameOverride,\n segmentId,\n segmentArrayName,\n}: Required<Omit<PersonalizationFieldPluginConfig, 'apiVersion' | 'segments'>>) => {\n return [\n ...fields.map((field) => createSegmentType({field, segmentNameOverride, segmentId})),\n ...fields.map((field) =>\n createPersonalizationType({\n field,\n personalizationNameOverride,\n segmentNameOverride,\n segmentId,\n segmentArrayName,\n }),\n ),\n ]\n}\n\nexport const fieldLevelPersonalization = definePlugin<PersonalizationFieldPluginConfig>(\n (config) => {\n const pluginConfig = {...CONFIG_DEFAULT, ...config}\n const {fields, personalizationNameOverride, segmentNameOverride} = pluginConfig\n\n const segmentArrayName = `${segmentNameOverride}s`\n const segmentId = `${segmentNameOverride}Id`\n\n const fieldSchemaConfig = fieldSchema({\n fields,\n personalizationNameOverride,\n segmentNameOverride,\n segmentId,\n segmentArrayName,\n })\n return {\n name: 'sanity-personalization-plugin-field-level-personalization',\n schema: {\n types: fieldSchemaConfig,\n },\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFields = flattenSchemaType(props.schemaType)\n const hasPersonalization = flatFields.some(\n (field) =>\n field.type.name.startsWith(personalizationNameOverride) ||\n field.name.startsWith(personalizationNameOverride),\n )\n\n if (!hasPersonalization) {\n return props.renderDefault(props)\n }\n\n const providerProps = {\n ...props,\n personalizationFieldPluginConfig: {\n ...pluginConfig,\n segmentId,\n segmentArrayName,\n },\n }\n return <PersonalizationProvider {...providerProps} />\n },\n },\n },\n }\n },\n)\n"],"mappings":"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"}
\ No newline at end of file Index: package/dist/launchDarkly/index.js.map
===================================================================
--- package/dist/launchDarkly/index.js.map
+++ package/dist/launchDarkly/index.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.js","names":["() => {\n if (loading) return undefined\n if (!secrets && !loading) {\n setSecret(undefined)\n // oxlint-disable-next-line react/set-state-in-effect\n return setShowSettings(true)\n }\n setSecret(secrets.apiKey)\n return setShowSettings(false)\n }","[secrets, loading, setSecret]","props.renderDefault(props)","props.renderDefault","<SettingsView\n title={`${namespace} api key`}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />","<>\n <SettingsView\n title={`${namespace} api key`}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />\n {props.renderDefault(props)}\n </>","{...launchDarklyFieldPluginConfig, secret, setSecret}","useMemo(\n () => ({...launchDarklyFieldPluginConfig, secret, setSecret}),\n [launchDarklyFieldPluginConfig, secret, setSecret],\n )","<Secrets {...props} />","<LaunchDarklyContext.Provider value={context}>\n <Secrets {...props} />\n </LaunchDarklyContext.Provider>","LaunchDarklyContext.Provider"],"sources":["../../src/launchDarkly/components/Secrets.tsx","../../src/launchDarkly/components/LaunchDarklyContext.tsx","../../src/launchDarkly/utils.ts","../../src/launchDarkly/index.ts"],"sourcesContent":["import {SettingsView, useSecrets} from '@sanity/studio-secrets'\nimport {useEffect, useState} from 'react'\nimport type {ObjectInputProps} from 'sanity'\n\nimport {useLaunchDarklyContext} from './LaunchDarklyContext'\n\nconst namespace = 'launchdarkly'\nconst pluginConfigKeys = [\n {\n key: 'apiKey',\n title: 'Your secret API key',\n },\n]\n\nexport const Secrets = (props: ObjectInputProps) => {\n const {secrets, loading} = useSecrets(namespace) as {secrets: {apiKey: string}; loading: boolean}\n const {setSecret} = useLaunchDarklyContext()\n const [showSettings, setShowSettings] = useState<boolean>(false)\n\n useEffect(() => {\n if (loading) return undefined\n if (!secrets && !loading) {\n setSecret(undefined)\n // oxlint-disable-next-line react/set-state-in-effect\n return setShowSettings(true)\n }\n setSecret(secrets.apiKey)\n return setShowSettings(false)\n }, [secrets, loading, setSecret])\n\n if (!showSettings) {\n return props.renderDefault(props)\n }\n return (\n <>\n <SettingsView\n title={`${namespace} api key`}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />\n {props.renderDefault(props)}\n </>\n )\n}\n","import {createContext, useContext, useMemo, useState} from 'react'\nimport type {ObjectInputProps} from 'sanity'\n\nimport type {LaunchDarklyContextProps, LaunchDarklyFieldLevelConfig} from '../types'\nimport {Secrets} from './Secrets'\n\nexport const LAUNCHDARKLY_CONFIG_DEFAULT = {}\n\nconst LaunchDarklyContext = createContext<LaunchDarklyContextProps>({\n setSecret: () => undefined,\n secret: undefined,\n})\n\nexport function useLaunchDarklyContext() {\n return useContext(LaunchDarklyContext)\n}\n\ntype LaunchDarklyProps = ObjectInputProps & {\n launchDarklyFieldPluginConfig: LaunchDarklyFieldLevelConfig\n}\n\nexport function LaunchDarklyProvider(props: LaunchDarklyProps) {\n const {launchDarklyFieldPluginConfig} = props\n const [secret, setSecret] = useState<string | undefined>()\n\n const context = useMemo(\n () => ({...launchDarklyFieldPluginConfig, secret, setSecret}),\n [launchDarklyFieldPluginConfig, secret, setSecret],\n )\n\n return (\n <LaunchDarklyContext.Provider value={context}>\n <Secrets {...props} />\n </LaunchDarklyContext.Provider>\n )\n}\n","import type {SanityClient} from 'sanity'\n\nimport type {ExperimentType} from '../types'\nimport type {LaunchDarklyFieldLevelConfig, LaunchDarklyFlagItem} from './types'\n\nexport const getExperiments = async ({\n client,\n projectKey,\n tags,\n}: Omit<LaunchDarklyFieldLevelConfig, 'fields'> & {client: SanityClient}): Promise<\n ExperimentType[]\n> => {\n const query = `*[_id == 'secrets.launchdarkly'][0].secrets.apiKey`\n\n const secret = await client.fetch(query) // secret is stored in the content lake using @sanity/studio-secrets\n if (!secret) return []\n\n const url = new URL(`https://app.launchdarkly.com/api/v2/flags/${projectKey}`)\n\n if (tags) {\n url.searchParams.set('filter', `tags:${tags.join('+')}`)\n }\n\n const featureExperiments: ExperimentType[] = []\n let hasMore = true\n let offset = 0\n const limit = 10\n\n while (hasMore) {\n url.searchParams.set('offset', offset.toString())\n url.searchParams.set('limit', limit.toString())\n const responseFlags = await fetch(url, {\n headers: {\n Authorization: secret,\n },\n })\n\n const {items} = await responseFlags.json()\n const experiments = items.map((flag: LaunchDarklyFlagItem) => ({\n id: flag.key,\n label: flag.name,\n variants: flag.variations.map((variation) => ({\n id: variation.value.toString(),\n label: variation.name ?? variation.value.toString(),\n })),\n }))\n featureExperiments.push(...experiments)\n if (items.length === limit) {\n offset += limit\n } else {\n hasMore = false\n }\n }\n\n return featureExperiments\n}\n","import '@sanity/ui/styles.css'\nimport {definePlugin, isObjectInputProps} from 'sanity'\n\nimport {fieldLevelExperiments as baseFieldLevelExperiments} from '../fieldExperiments'\nimport {flattenSchemaType} from '../utils/flattenSchemaType'\nimport {LAUNCHDARKLY_CONFIG_DEFAULT, LaunchDarklyProvider} from './components/LaunchDarklyContext'\nimport type {LaunchDarklyFieldLevelConfig} from './types'\nimport {getExperiments} from './utils'\n\nexport const fieldLevelExperiments = definePlugin<LaunchDarklyFieldLevelConfig>((config) => {\n const pluginConfig = {...LAUNCHDARKLY_CONFIG_DEFAULT, ...config}\n const {fields, projectKey, tags} = pluginConfig\n return {\n name: 'sanity-launchdarkly-personalization-plugin-field-level-experiments',\n plugins: [\n baseFieldLevelExperiments({\n fields,\n experiments: (client) => getExperiments({client, projectKey, tags}),\n experimentNameOverride: 'flag',\n }),\n ],\n\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFieldTypeNames = flattenSchemaType(props.schemaType).map(\n (field) => field.type.name,\n )\n\n const hasExperiment = flatFieldTypeNames.some((name) => name.startsWith('flag'))\n\n if (!hasExperiment) {\n return props.renderDefault(props)\n }\n\n const providerProps = {\n ...props,\n launchDarklyFieldPluginConfig: {\n ...pluginConfig,\n },\n }\n return LaunchDarklyProvider(providerProps)\n },\n },\n },\n }\n})\n"],"mappings":";;;;;;;AAMA,MAAM,YAAY,gBACZ,mBAAmB,CACvB;CACE,KAAK;CACL,OAAO;AACT,CACF,GAEa,WAAW,UAA4B;gBAC5C,EAAC,SAAS,YAAW,WAAW,SAAS,GACzC,EAAC,cAAa,uBAAuB,GACrC,CAAC,cAAc,mBAAmB,SAAkB,EAAK,GAErDA,IASPC;CAEH,IAVM,EAAA,OAAA,WAAA,EAAA,OACC,WAAA,EAAA,OACH,aAHM,WAAM;EACV,cAOJ,OANI,CAAC,WAAW,CAAC,WACf,UAAU,KAAA,CAAS,GAEZ,gBAAgB,EAAI,MAE7B,UAAU,QAAQ,MAAM,GACjB,gBAAgB,EAAK;CAC9B,GAAG,KAAA;EAAC;EAAS;EAAS;CAAS,GARzB,EAAA,KAAA,SACC,EAAA,KAAA,SACH,EAAA,KAAA,2DAHJ,UAAUD,IASPC,EAA6B,GAE5B,CAAC,cAAc;EACVC,IAAAA;EAAP,qCAAa,KAAA,MAAA,cAAc,KAAK,GAAzBC,EAAAA,KAAAA,mBAAAD;CACT;CAGIE,IAAAA;qDAAC,KAAA,oBAAA,cAAD;EACE,OAAO,GAAG,UAAU;EACT;EACX,MAAM;EACN,eAAe;GACb,gBAAgB,EAAK;EACvB;CACD,CAAA;CACAF,IAAAA;+BAAM,KAAA,MAAA,cAAc,KAAK,GAAzBC,EAAAA,KAAAA;CATHE,IAAAA;CADF,OAUKH,EAAAA,QAAAA,mBATH,KAAA,qBAAA,UAAA,EAAA,UAAA,CACEE,IAQCF,EACD,EAAA,CAAA,GADCA,EAAAA,MAAAA,iBATHG;AAYJ,GCxCa,8BAA8B,CAAC,GAEtC,sBAAsB,cAAwC;CAClE,iBAAiB,KAAA;CACjB,QAAQ,KAAA;AACV,CAAC;AAED,SAAgB,yBAAyB;CACvC,OAAO,WAAW,mBAAmB;AACvC;AAMA,SAAgB,qBAAqB,OAA0B;eACvD,EAAC,kCAAiC,OAClC,CAAC,QAAQ,aAAa,SAA6B,GAGhDC;CAAI,AAAA,EAAA,OAAA,iCAAA,EAAA,OAA+B,UAAnC,KAAA;EAAC,GAAG;EAA+B;EAAQ;CAAS,GAAhD,EAAA,KAAA,+BAA+B,EAAA,KAAA;CAD5C,IAAM,UAAUC,IAOZC;CAAa,AAAA,EAAA,OAAA,qBAAb,KAAA,oBAAC,SAAD,EAAS,GAAI,MAAQ,CAAA,GAAR,EAAA,KAAA;CADfC,IAAAA;CADF,OACuC,EAAA,OAAA,WAAA,EAAA,OACnCD,MADF,KAAA,oBAACE,oBAAAA,UAAD;EAA8B,OAAO;EACnCF,UAAAA;CAC4B,CAAA,GAFO,EAAA,KAAA,SACnCA,EAAAA,KAAAA,4BADFC;AAIJ;AC9BA,MAAa,iBAAiB,OAAO,EACnC,QACA,YACA,WAGG;CAGH,IAAM,SAAS,MAAM,OAAO,MAAM,oDAAK;CACvC,IAAI,CAAC,QAAQ,OAAO,CAAC;CAErB,IAAM,MAAM,IAAI,IAAI,6CAA6C,YAAY;CAE7E,AAAI,QACF,IAAI,aAAa,IAAI,UAAU,QAAQ,KAAK,KAAK,GAAG,GAAG;CAGzD,IAAM,qBAAuC,CAAC,GAC1C,UAAU,IACV,SAAS;CAGb,OAAO,UAAS;EAEd,AADA,IAAI,aAAa,IAAI,UAAU,OAAO,SAAS,CAAC,GAChD,IAAI,aAAa,IAAI,SAAS,IAAgB;EAO9C,IAAM,EAAC,UAAS,OAAM,MANM,MAAM,KAAK,EACrC,SAAS,EACP,eAAe,OACjB,EACF,CAAC,EAAA,CAEmC,KAAK,GACnC,cAAc,MAAM,KAAK,UAAgC;GAC7D,IAAI,KAAK;GACT,OAAO,KAAK;GACZ,UAAU,KAAK,WAAW,KAAK,eAAe;IAC5C,IAAI,UAAU,MAAM,SAAS;IAC7B,OAAO,UAAU,QAAQ,UAAU,MAAM,SAAS;GACpD,EAAE;EACJ,EAAE;EAEF,AADA,mBAAmB,KAAK,GAAG,WAAW,GAClC,MAAM,WAAW,KACnB,UAAU,KAEV,UAAU;CAEd;CAEA,OAAO;AACT,GC9Ca,wBAAwB,cAA4C,WAAW;CAC1F,IAAM,eAAe;EAAC,GAAG;EAA6B,GAAG;CAAM,GACzD,EAAC,QAAQ,YAAY,SAAQ;CACnC,OAAO;EACL,MAAM;EACN,SAAS,CACP,wBAA0B;GACxB;GACA,cAAc,WAAW,eAAe;IAAC;IAAQ;IAAY;GAAI,CAAC;GAClE,wBAAwB;EAC1B,CAAC,CACH;EAEA,MAAM,EACJ,YAAY,EACV,QAAQ,UAGF,EAFgB,MAAM,OAAO,UAAU,mBAAmB,KAAK,MAY/D,CANuB,kBAAkB,MAAM,UAAU,CAAC,CAAC,KAC5D,UAAU,MAAM,KAAK,IAGF,CAAA,CAAmB,MAAM,SAAS,KAAK,WAAW,MAAM,CAEzE,IACI,MAAM,cAAc,KAAK,IAS3B,qBAAqB;GAL1B,GAAG;GACH,+BAA+B,EAC7B,GAAG,aACL;EAE0B,CAAa,EAE7C,EACF;CACF;AACF,CAAC"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["() => {\n if (loading) return undefined\n if (!secrets && !loading) {\n setSecret(undefined)\n // oxlint-disable-next-line react/set-state-in-effect\n return setShowSettings(true)\n }\n setSecret(secrets.apiKey)\n return setShowSettings(false)\n }","[secrets, loading, setSecret]","props.renderDefault(props)","props.renderDefault","<SettingsView\n title={`${namespace} api key`}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />","<>\n <SettingsView\n title={`${namespace} api key`}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />\n {props.renderDefault(props)}\n </>","_c","_Fragment","{...launchDarklyFieldPluginConfig, secret, setSecret}","useMemo(\n () => ({...launchDarklyFieldPluginConfig, secret, setSecret}),\n [launchDarklyFieldPluginConfig, secret, setSecret],\n )","<Secrets {...props} />","<LaunchDarklyContext.Provider value={context}>\n <Secrets {...props} />\n </LaunchDarklyContext.Provider>","LaunchDarklyContext.Provider","_c","baseFieldLevelExperiments"],"sources":["../../src/launchDarkly/components/Secrets.tsx","../../src/launchDarkly/components/LaunchDarklyContext.tsx","../../src/launchDarkly/utils.ts","../../src/launchDarkly/index.ts"],"sourcesContent":["import {SettingsView, useSecrets} from '@sanity/studio-secrets'\nimport {useEffect, useState} from 'react'\nimport type {ObjectInputProps} from 'sanity'\n\nimport {useLaunchDarklyContext} from './LaunchDarklyContext'\n\nconst namespace = 'launchdarkly'\nconst pluginConfigKeys = [\n {\n key: 'apiKey',\n title: 'Your secret API key',\n },\n]\n\nexport const Secrets = (props: ObjectInputProps) => {\n const {secrets, loading} = useSecrets(namespace) as {secrets: {apiKey: string}; loading: boolean}\n const {setSecret} = useLaunchDarklyContext()\n const [showSettings, setShowSettings] = useState<boolean>(false)\n\n useEffect(() => {\n if (loading) return undefined\n if (!secrets && !loading) {\n setSecret(undefined)\n // oxlint-disable-next-line react/set-state-in-effect\n return setShowSettings(true)\n }\n setSecret(secrets.apiKey)\n return setShowSettings(false)\n }, [secrets, loading, setSecret])\n\n if (!showSettings) {\n return props.renderDefault(props)\n }\n return (\n <>\n <SettingsView\n title={`${namespace} api key`}\n namespace={namespace}\n keys={pluginConfigKeys}\n onClose={() => {\n setShowSettings(false)\n }}\n />\n {props.renderDefault(props)}\n </>\n )\n}\n","import {createContext, useContext, useMemo, useState} from 'react'\nimport type {ObjectInputProps} from 'sanity'\n\nimport type {LaunchDarklyContextProps, LaunchDarklyFieldLevelConfig} from '../types'\nimport {Secrets} from './Secrets'\n\nexport const LAUNCHDARKLY_CONFIG_DEFAULT = {}\n\nconst LaunchDarklyContext = createContext<LaunchDarklyContextProps>({\n setSecret: () => undefined,\n secret: undefined,\n})\n\nexport function useLaunchDarklyContext() {\n return useContext(LaunchDarklyContext)\n}\n\ntype LaunchDarklyProps = ObjectInputProps & {\n launchDarklyFieldPluginConfig: LaunchDarklyFieldLevelConfig\n}\n\nexport function LaunchDarklyProvider(props: LaunchDarklyProps) {\n const {launchDarklyFieldPluginConfig} = props\n const [secret, setSecret] = useState<string | undefined>()\n\n const context = useMemo(\n () => ({...launchDarklyFieldPluginConfig, secret, setSecret}),\n [launchDarklyFieldPluginConfig, secret, setSecret],\n )\n\n return (\n <LaunchDarklyContext.Provider value={context}>\n <Secrets {...props} />\n </LaunchDarklyContext.Provider>\n )\n}\n","import type {SanityClient} from 'sanity'\n\nimport type {ExperimentType} from '../types'\nimport type {LaunchDarklyFieldLevelConfig, LaunchDarklyFlagItem} from './types'\n\nexport const getExperiments = async ({\n client,\n projectKey,\n tags,\n}: Omit<LaunchDarklyFieldLevelConfig, 'fields'> & {client: SanityClient}): Promise<\n ExperimentType[]\n> => {\n const query = `*[_id == 'secrets.launchdarkly'][0].secrets.apiKey`\n\n const secret = await client.fetch(query) // secret is stored in the content lake using @sanity/studio-secrets\n if (!secret) return []\n\n const url = new URL(`https://app.launchdarkly.com/api/v2/flags/${projectKey}`)\n\n if (tags) {\n url.searchParams.set('filter', `tags:${tags.join('+')}`)\n }\n\n const featureExperiments: ExperimentType[] = []\n let hasMore = true\n let offset = 0\n const limit = 10\n\n while (hasMore) {\n url.searchParams.set('offset', offset.toString())\n url.searchParams.set('limit', limit.toString())\n const responseFlags = await fetch(url, {\n headers: {\n Authorization: secret,\n },\n })\n\n const {items} = await responseFlags.json()\n const experiments = items.map((flag: LaunchDarklyFlagItem) => ({\n id: flag.key,\n label: flag.name,\n variants: flag.variations.map((variation) => ({\n id: variation.value.toString(),\n label: variation.name ?? variation.value.toString(),\n })),\n }))\n featureExperiments.push(...experiments)\n if (items.length === limit) {\n offset += limit\n } else {\n hasMore = false\n }\n }\n\n return featureExperiments\n}\n","import '@sanity/ui/styles.css'\nimport {definePlugin, isObjectInputProps} from 'sanity'\n\nimport {fieldLevelExperiments as baseFieldLevelExperiments} from '../fieldExperiments'\nimport {flattenSchemaType} from '../utils/flattenSchemaType'\nimport {LAUNCHDARKLY_CONFIG_DEFAULT, LaunchDarklyProvider} from './components/LaunchDarklyContext'\nimport type {LaunchDarklyFieldLevelConfig} from './types'\nimport {getExperiments} from './utils'\n\nexport const fieldLevelExperiments = definePlugin<LaunchDarklyFieldLevelConfig>((config) => {\n const pluginConfig = {...LAUNCHDARKLY_CONFIG_DEFAULT, ...config}\n const {fields, projectKey, tags} = pluginConfig\n return {\n name: 'sanity-launchdarkly-personalization-plugin-field-level-experiments',\n plugins: [\n baseFieldLevelExperiments({\n fields,\n experiments: (client) => getExperiments({client, projectKey, tags}),\n experimentNameOverride: 'flag',\n }),\n ],\n\n form: {\n components: {\n input: (props) => {\n const isRootInput = props.id === 'root' && isObjectInputProps(props)\n\n if (!isRootInput) {\n return props.renderDefault(props)\n }\n\n const flatFieldTypeNames = flattenSchemaType(props.schemaType).map(\n (field) => field.type.name,\n )\n\n const hasExperiment = flatFieldTypeNames.some((name) => name.startsWith('flag'))\n\n if (!hasExperiment) {\n return props.renderDefault(props)\n }\n\n const providerProps = {\n ...props,\n launchDarklyFieldPluginConfig: {\n ...pluginConfig,\n },\n }\n return LaunchDarklyProvider(providerProps)\n },\n },\n },\n }\n})\n"],"mappings":"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"}
\ No newline at end of file