UNPKG

sanity-plugin-link-field

Version:
1 lines 26.9 kB
{"version":3,"file":"index.mjs","sources":["../src/helpers/requiredLinkField.ts","../src/components/CustomLinkInput.tsx","../src/components/LinkInput.tsx","../src/components/LinkTypeInput.tsx","../src/linkField.tsx"],"sourcesContent":["import type {CustomValidatorResult} from 'sanity'\n\nimport type {LinkValue} from '../types'\nimport {isCustomLink, isEmailLink, isExternalLink, isInternalLink, isPhoneLink} from './typeGuards'\n\n/**\n * Helper to create a required link field.\n */\nexport const requiredLinkField = (field: unknown): CustomValidatorResult => {\n const link = field as LinkValue\n\n if (!link || !link.type) {\n return 'Link is required'\n }\n\n if (isInternalLink(link) && !link.internalLink) {\n return {\n message: 'Link is required',\n path: 'internalLink',\n }\n }\n\n if (isExternalLink(link) && !link.url) {\n return {\n message: 'URL is required',\n path: 'url',\n }\n }\n\n if (isEmailLink(link) && !link.email) {\n return {\n message: 'E-mail is required',\n path: 'email',\n }\n }\n\n if (isPhoneLink(link) && !link.phone) {\n return {\n message: 'Phone is required',\n path: 'phone',\n }\n }\n\n if (isCustomLink(link) && !link.value) {\n return {\n message: 'Value is required',\n path: 'value',\n }\n }\n\n return true\n}\n","import {Select, Spinner} from '@sanity/ui'\nimport {useEffect, useState} from 'react'\nimport {SanityDocument, set, type StringInputProps, useFormValue, useWorkspace} from 'sanity'\nimport styled from 'styled-components'\n\nimport {CustomLinkType, CustomLinkTypeOptions, LinkValue} from '../types'\n\nconst OptionsSpinner = styled(Spinner)`\n margin-left: 0.5rem;\n`\n\n/**\n * Custom input component used for custom link types.\n * Renders a dropdown with the available options for the custom link type.\n */\nexport function CustomLinkInput(\n props: StringInputProps & {\n customLinkTypes: CustomLinkType[]\n },\n) {\n const workspace = useWorkspace()\n const document = useFormValue([]) as SanityDocument\n const linkValue = useFormValue(props.path.slice(0, -1)) as LinkValue | null\n const [options, setOptions] = useState<CustomLinkTypeOptions[] | null>(null)\n\n const customLinkType = props.customLinkTypes.find((type) => type.value === linkValue!.type)\n\n useEffect(() => {\n if (customLinkType) {\n if (Array.isArray(customLinkType?.options)) {\n setOptions(customLinkType.options)\n } else {\n customLinkType\n .options(document, props.path, workspace.currentUser)\n .then((options) => setOptions(options))\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [customLinkType, props.path, workspace.currentUser])\n\n return options ? (\n <Select\n onChange={(e) => {\n props.onChange(set(e.currentTarget.value || ''))\n }}\n >\n <>\n <option value=\"\" selected={props.value === ''} disabled hidden />\n {options.map((option) => (\n <option key={option.value} value={option.value} selected={props.value === option.value}>\n {option.title}\n </option>\n ))}\n </>\n </Select>\n ) : (\n <OptionsSpinner />\n )\n}\n","import {Box, Flex, Stack, Text} from '@sanity/ui'\nimport {type FieldMember, FormFieldValidationStatus, ObjectInputMember} from 'sanity'\nimport styled from 'styled-components'\n\nimport {isCustomLink} from '../helpers/typeGuards'\nimport {LinkInputProps} from '../types'\n\nconst ValidationErrorWrapper = styled(Box)`\n contain: size;\n margin-bottom: 6px;\n margin-left: auto;\n margin-right: 12px;\n`\n\nconst FullWidthStack = styled(Stack)`\n width: 100%;\n`\n\n/**\n * Custom input component for the link object.\n * Nicely renders the type and link fields next to each other, with the\n * description and any validation errors for the link field below them.\n *\n * The rest of the fields (\"blank\" and \"advanced\") are rendered as usual.\n */\nexport function LinkInput(props: LinkInputProps) {\n const [textField, typeField, linkField, ...otherFields] = props.members as FieldMember[]\n const {options} = props.schemaType\n\n const {\n field: {\n validation: linkFieldValidation,\n schemaType: {description: linkFieldDescription},\n },\n } = linkField\n\n const description =\n // If a custom link type is used, use its description if it has one.\n props.value && isCustomLink(props.value)\n ? props.customLinkTypes.find((type) => type.value === props.value?.type)?.description\n : // Fallback to the description of the current link type field.\n linkFieldDescription\n\n const renderProps = {\n renderAnnotation: props.renderAnnotation,\n renderBlock: props.renderBlock,\n renderField: props.renderField,\n renderInlineBlock: props.renderInlineBlock,\n renderInput: props.renderInput,\n renderItem: props.renderItem,\n renderPreview: props.renderPreview,\n }\n\n return (\n <Stack space={4}>\n {/* Render the text field if enabled */}\n {options?.enableText && (\n <ObjectInputMember\n member={{\n ...textField,\n field: {\n ...textField.field,\n schemaType: {\n ...textField.field.schemaType,\n title: options?.textLabel || textField.field.schemaType.title,\n },\n },\n }}\n {...renderProps}\n />\n )}\n\n <Stack space={3}>\n {/* Render a label for the link field if there's also a text field enabled. */}\n {/* If there's no text field, the label here is irrelevant */}\n {options?.enableText && (\n <Text as=\"label\" weight=\"medium\" size={1}>\n Link\n </Text>\n )}\n\n <Flex gap={2} align=\"flex-start\">\n {/* Render the type field (without its label) */}\n <ObjectInputMember\n member={{\n ...typeField,\n field: {\n ...typeField.field,\n schemaType: {\n ...typeField.field.schemaType,\n title: undefined,\n },\n },\n }}\n {...renderProps}\n />\n\n <FullWidthStack space={2}>\n {/* Render the input for the selected type of link (withouts its label) */}\n <ObjectInputMember\n member={{\n ...linkField,\n field: {\n ...linkField.field,\n schemaType: {\n ...linkField.field.schemaType,\n title: undefined,\n },\n },\n }}\n {...renderProps}\n />\n\n {/* Render any validation errors for the link field */}\n {linkFieldValidation.length > 0 && (\n <ValidationErrorWrapper>\n <FormFieldValidationStatus\n fontSize={1}\n placement=\"top\"\n validation={linkFieldValidation}\n />\n </ValidationErrorWrapper>\n )}\n </FullWidthStack>\n </Flex>\n\n {/* Render the description of the selected link field, if any */}\n {description && (\n <Text muted size={1}>\n {description}\n </Text>\n )}\n </Stack>\n\n {/* Render the rest of the fields as usual */}\n {otherFields.map((field) => (\n <ObjectInputMember key={field.key} member={field} {...renderProps} />\n ))}\n </Stack>\n )\n}\n","import {ChevronDownIcon} from '@sanity/icons'\nimport {Button, Menu, MenuButton, MenuItem} from '@sanity/ui'\nimport {AtSignIcon, GlobeIcon, LinkIcon, PhoneIcon} from 'lucide-react'\nimport {set, type StringInputProps} from 'sanity'\nimport styled from 'styled-components'\n\nimport {CustomLinkType, LinkFieldPluginOptions, LinkType} from '../types'\n\nconst defaultLinkTypes: LinkType[] = [\n {title: 'Internal', value: 'internal', icon: LinkIcon},\n {title: 'URL', value: 'external', icon: GlobeIcon},\n {title: 'Email', value: 'email', icon: AtSignIcon},\n {title: 'Phone', value: 'phone', icon: PhoneIcon},\n]\n\nconst LinkTypeButton = styled(Button)`\n height: 35px;\n\n svg.lucide {\n width: 1rem;\n height: 1rem;\n }\n`\n\nconst LinkTypeMenuItem = styled(MenuItem)`\n svg.lucide {\n width: 1rem;\n height: 1rem;\n }\n`\n\n/**\n * Custom input component for the \"type\" field on the link object.\n * Renders a button with an icon and a dropdown menu to select the link type.\n */\nexport function LinkTypeInput({\n value,\n onChange,\n customLinkTypes = [],\n linkableSchemaTypes,\n}: StringInputProps & {\n customLinkTypes?: CustomLinkType[]\n linkableSchemaTypes: LinkFieldPluginOptions['linkableSchemaTypes']\n}) {\n const linkTypes = [\n // Disable internal links if not enabled for any schema types\n ...defaultLinkTypes.filter(\n ({value}) => value !== 'internal' || linkableSchemaTypes?.length > 0,\n ),\n ...customLinkTypes,\n ]\n\n const selectedType = linkTypes.find((type) => type.value === value) || linkTypes[0]\n\n return (\n <MenuButton\n button={\n <LinkTypeButton\n type=\"button\"\n mode=\"ghost\"\n icon={selectedType.icon}\n iconRight={ChevronDownIcon}\n title=\"Select link type\"\n aria-label={`Select link type (currently: ${selectedType.title})`}\n />\n }\n id=\"link-type\"\n menu={\n <Menu>\n {linkTypes.map((type) => (\n <LinkTypeMenuItem\n key={type.value}\n text={type.title}\n icon={type.icon}\n onClick={() => {\n onChange(set(type.value))\n }}\n />\n ))}\n </Menu>\n }\n />\n )\n}\n","import {defineField, definePlugin, defineType, type ObjectInputProps} from 'sanity'\n\nimport {CustomLinkInput} from './components/CustomLinkInput'\nimport {LinkInput} from './components/LinkInput'\nimport {LinkTypeInput} from './components/LinkTypeInput'\nimport {isCustomLink} from './helpers/typeGuards'\nimport type {LinkFieldPluginOptions, LinkValue} from './types'\n\n/**\n * A plugin that adds a custom Link field for creating internal and external links,\n * as well as `mailto` and `tel`-links, all using the same intuitive UI.\n *\n * @param options - Options for the plugin. See {@link LinkFieldPluginOptions}\n *\n * @example Minimal example\n * ```ts\n * // sanity.config.ts\n * import { defineConfig } from 'sanity'\n * import { linkField } from 'sanity-plugin-link-field'\n *\n * export default defineConfig((\n * // ...\n * plugins: [\n * linkField()\n * ]\n * })\n *\n * // mySchema.ts\n * import { defineField, defineType } from 'sanity';\n *\n * export const mySchema = defineType({\n * // ...\n * fields: [\n * // ...\n * defineField({\n * name: 'link',\n * title: 'Link',\n * type: 'link'\n * }),\n * ]\n *});\n * ```\n */\nexport const linkField = definePlugin<LinkFieldPluginOptions | void>((opts) => {\n const {\n linkableSchemaTypes = ['page'],\n weakReferences = false,\n referenceFilterOptions,\n descriptions = {\n internal: 'Link to another page or document on the website.',\n external: 'Link to an absolute URL to a page on another website.',\n email: 'Link to send an e-mail to the given address.',\n phone: 'Link to call the given phone number.',\n advanced: 'Optional. Add anchor links and custom parameters.',\n parameters: 'Optional. Add custom parameters to the URL, such as UTM tags.',\n anchor: 'Optional. Add an anchor to link to a specific section on the page.',\n },\n enableLinkParameters = true,\n enableAnchorLinks = true,\n customLinkTypes = [],\n icon,\n preview,\n } = opts || {}\n\n const linkType = defineType({\n name: 'link',\n title: 'Link',\n type: 'object',\n icon,\n preview,\n fieldsets: [\n {\n name: 'advanced',\n title: 'Advanced',\n description: descriptions.advanced,\n options: {\n collapsible: true,\n collapsed: true,\n },\n },\n ],\n fields: [\n defineField({\n name: 'text',\n type: 'string',\n description: descriptions.text,\n }),\n\n defineField({\n name: 'type',\n type: 'string',\n initialValue: 'internal',\n validation: (Rule) => Rule.required(),\n components: {\n input: (props) => LinkTypeInput({customLinkTypes, linkableSchemaTypes, ...props}),\n },\n }),\n\n // Internal\n defineField({\n name: 'internalLink',\n type: 'reference',\n to: linkableSchemaTypes.map((type) => ({\n type,\n })),\n weak: weakReferences,\n options: {\n disableNew: true,\n ...referenceFilterOptions,\n },\n description: descriptions?.internal,\n hidden: ({parent}) => !!parent?.type && parent?.type !== 'internal',\n }),\n\n // External\n defineField({\n name: 'url',\n type: 'url',\n description: descriptions?.external,\n validation: (rule) =>\n rule.uri({\n allowRelative: true,\n scheme: ['https', 'http'],\n }),\n hidden: ({parent}) => parent?.type !== 'external',\n }),\n\n // E-mail\n defineField({\n name: 'email',\n type: 'email',\n description: descriptions?.email,\n hidden: ({parent}) => parent?.type !== 'email',\n }),\n\n // Phone\n defineField({\n name: 'phone',\n type: 'string',\n description: descriptions?.phone,\n validation: (rule) =>\n rule.custom((value, context) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (!value || (context.parent as any)?.type !== 'phone') {\n return true\n }\n\n return (\n (new RegExp(/^\\+?[0-9\\s-]*$/).test(value) &&\n !value.startsWith('-') &&\n !value.endsWith('-')) ||\n 'Must be a valid phone number'\n )\n }),\n hidden: ({parent}) => parent?.type !== 'phone',\n }),\n\n // Custom\n defineField({\n name: 'value',\n type: 'string',\n description: descriptions?.external,\n hidden: ({parent}) => !parent || !isCustomLink(parent as LinkValue),\n components: {\n input: (props) => CustomLinkInput({customLinkTypes, ...props}),\n },\n }),\n\n // New tab\n defineField({\n title: 'Open in new window',\n name: 'blank',\n type: 'boolean',\n initialValue: false,\n description: descriptions.blank,\n hidden: ({parent}) => parent?.type === 'email' || parent?.type === 'phone',\n }),\n\n // Parameters\n ...(enableLinkParameters || enableAnchorLinks\n ? [\n ...(enableLinkParameters\n ? [\n defineField({\n title: 'Parameters',\n name: 'parameters',\n type: 'string',\n description: descriptions.parameters,\n validation: (rule) =>\n rule.custom((value, context) => {\n if (\n !value ||\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (context.parent as any)?.type === 'email' ||\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (context.parent as any)?.type === 'phone'\n ) {\n return true\n }\n\n if (value.indexOf('?') !== 0) {\n return 'Must start with ?; eg. ?utm_source=example.com&utm_medium=referral'\n }\n\n if (value.length === 1) {\n return 'Must contain at least one parameter'\n }\n\n return true\n }),\n hidden: ({parent}) => parent?.type === 'email' || parent?.type === 'phone',\n fieldset: 'advanced',\n }),\n ]\n : []),\n\n // Anchor\n ...(enableAnchorLinks\n ? [\n defineField({\n title: 'Anchor',\n name: 'anchor',\n type: 'string',\n description: descriptions.anchor,\n validation: (rule) =>\n rule.custom((value, context) => {\n if (\n !value ||\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (context.parent as any)?.type === 'email' ||\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (context.parent as any)?.type === 'phone'\n ) {\n return true\n }\n\n if (value.indexOf('#') !== 0) {\n return 'Must start with #; eg. #page-section-1'\n }\n\n if (value.length === 1) {\n return 'Must contain at least one character'\n }\n\n return (\n new RegExp(/^([-?/:@._~!$&'()*+,;=a-zA-Z0-9]|%[0-9a-fA-F]{2})*$/).test(\n value.replace(/^#/, ''),\n ) || 'Invalid URL fragment'\n )\n }),\n hidden: ({parent}) => parent?.type === 'email' || parent?.type === 'phone',\n fieldset: 'advanced',\n }),\n ]\n : []),\n ]\n : []),\n ],\n components: {\n input: (props: ObjectInputProps) =>\n LinkInput({customLinkTypes, ...props, value: props.value as LinkValue}),\n },\n })\n\n return {\n name: 'link-field',\n schema: {\n types: [linkType],\n },\n }\n})\n"],"names":["options","linkField","_a","value"],"mappings":"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"}