@madebywild/sanity-link-field 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/input.tsx","../src/preview.tsx","../src/types.tsx","../src/index.tsx"],"sourcesContent":["import { useFieldMember } from \"@madebywild/sanity-utils\";\nimport { AsyncAutocomplete } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport { Box, Card, Stack, Text } from \"@sanity/ui\";\nimport * as changeCase from \"change-case\";\nimport * as React from \"react\";\nimport type { ObjectInputProps, ObjectMember, Reference } from \"sanity\";\nimport { MemberField, set, unset, useClient } from \"sanity\";\nimport type { FieldOptions } from \"./types\";\n\nfunction FieldInput(props: ObjectInputProps) {\n const options = props.schemaType.options as FieldOptions | undefined;\n\n return (\n <Stack space={4}>\n {props.members.map((member: ObjectMember) => {\n if (member.kind !== \"field\") return null;\n if (options?.noCustomText && member.name === \"customText\") return null;\n return <MemberField key={member.key} member={member} {...props} />;\n })}\n </Stack>\n );\n}\n\nconst SectionsQuery = `\n *[_id == $pageId && defined(pageBuilder.sectionsArray)][0]{\n \"sections\": array::compact(pageBuilder.sectionsArray[]{\n \"value\": _key,\n \"label\": coalesce(sectionSettings.sectionTitle, _type),\n }),\n }.sections\n`;\n\nfunction InternalLinkInput(props: ObjectInputProps) {\n const linkFieldMember = useFieldMember(props.members, \"link\");\n\n const selectedLink = props.value?.link as Reference | undefined;\n const selectedSection = props.value?.sectionTarget as string | undefined;\n\n // Reset sectionTarget if link is removed.\n React.useEffect(() => {\n if (!selectedLink?._ref && selectedSection !== undefined) {\n props.onChange(unset([\"sectionTarget\"]));\n }\n }, [selectedLink, selectedSection, props.onChange]);\n\n const client = useClient({ apiVersion: \"2025-10-21\" });\n\n const fetchSections = React.useCallback(() => {\n if (!selectedLink?._ref) return [];\n return client.fetch(SectionsQuery, { pageId: selectedLink._ref }).catch(() => []);\n }, [client, selectedLink, SectionsQuery]);\n\n return (\n <Stack space={2}>\n {linkFieldMember && <MemberField member={linkFieldMember} {...props} />}\n <AsyncAutocomplete\n placeholder=\"Select section\"\n noOptionsPlaceholder=\"No sections found\"\n listItems={fetchSections}\n value={selectedSection}\n renderValue={(value, opt) => {\n return opt?.label ? changeCase.capitalCase(opt.label) : value;\n }}\n onChange={(value) => {\n const next = value ? set(value, [\"sectionTarget\"]) : unset([\"sectionTarget\"]);\n return props.onChange(next);\n }}\n renderOption={({ label, value }) => {\n return (\n <Card as=\"button\">\n <Box flex={1} padding={3}>\n <Text size={2}>{changeCase.capitalCase(label ?? value)}</Text>\n </Box>\n </Card>\n );\n }}\n />\n </Stack>\n );\n}\n\nexport { FieldInput, InternalLinkInput };\n","import type { LinkKind } from \"./types\";\n\n/** @public */\nexport function buildLinkPreview({\n kind,\n email,\n phone,\n fileName,\n customText,\n internalUri,\n externalUrl,\n internalTitle,\n}: {\n kind?: string;\n email?: string;\n phone?: string;\n fileName?: string;\n customText?: string;\n externalUrl?: string;\n internalUri?: string;\n internalTitle?: string;\n}) {\n switch (kind as keyof typeof LinkKind) {\n case \"internal\": {\n return {\n title: customText ?? internalTitle ?? \"Internal Link\",\n subtitle: internalUri,\n media: () => <>📄</>,\n };\n }\n case \"external\":\n return {\n title: customText ?? \"External Link\",\n subtitle: externalUrl,\n media: () => <>🌍</>,\n };\n case \"email\":\n return {\n title: customText ?? \"Email Link\",\n subtitle: email,\n media: () => <>📧</>,\n };\n case \"phone\":\n return {\n title: customText ?? \"Phone Link\",\n subtitle: phone,\n media: () => <>☎️</>,\n };\n case \"file\":\n return {\n title: customText ?? \"File Link\",\n subtitle: fileName,\n media: () => <>📃</>,\n };\n default:\n return {\n title: customText ?? \"Empty Link\",\n media: () => <>⛓️‍💥</>,\n };\n }\n}\n","import type { ListItem } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport type { ObjectOptions, ReferenceTo, StringDefinition } from \"sanity\";\n\n/** @public */\nexport const typeName = \"wild.link\" as const;\n\n/** @public */\nexport const LinkKind = {\n internal: \"internal\",\n external: \"external\",\n email: \"email\",\n phone: \"phone\",\n file: \"file\",\n} as const;\n\n/** @public */\nexport type SectionQueryResult = ListItem[];\n\n/** @public */\nexport type PluginConfig = {\n weakReferences?: boolean;\n internalLinkSchemaTypes: ReferenceTo;\n};\n\n/** @public */\nexport type FieldOptions = ObjectOptions & {\n noCustomText?: boolean;\n};\n\n// Add the custom field definition to Sanity's intrinsic definitions\n// so that type checking works correctly when using this field type.\ndeclare module \"sanity\" {\n export interface IntrinsicDefinitions {\n [typeName]: Omit<StringDefinition, \"type\" | \"fields\"> & {\n type: typeof typeName;\n };\n }\n}\n","import { requiredIf, visibleIf } from \"@madebywild/sanity-utils\";\nimport { defineField, definePlugin, defineType } from \"sanity\";\nimport { FieldInput, InternalLinkInput } from \"./input\";\nimport { buildLinkPreview } from \"./preview\";\nimport { type FieldOptions, LinkKind, type PluginConfig, type SectionQueryResult, typeName } from \"./types\";\n\nconst visibleIfKind = visibleIf(\"kind\");\nconst requiredIfKind = requiredIf(\"kind\");\n\n/** @public */\nconst wildSanityLinkFieldPlugin = definePlugin<PluginConfig>((config) => {\n return {\n name: \"@madebywild/sanity-link-field\",\n schema: {\n types: [\n defineType({\n name: typeName,\n type: \"object\",\n title: \"Link\",\n description: \"Link to an internal page, external URL and more.\",\n icon: () => <>🔗</>,\n components: {\n input: (props) => <FieldInput {...props} />,\n },\n fields: [\n defineField({\n name: \"kind\",\n type: \"string\",\n title: \"Link Kind\",\n description: \"Select the kind of link.\",\n validation: (R) => R.required().error(\"Select a link kind.\"),\n options: {\n layout: \"radio\",\n direction: \"horizontal\",\n list: [\n { title: \"📄 Internal\", value: LinkKind.internal },\n { title: \"🌍 External\", value: LinkKind.external },\n { title: \"📧 Email\", value: LinkKind.email },\n { title: \"☎️ Phone\", value: LinkKind.phone },\n { title: \"📃 File\", value: LinkKind.file },\n ],\n },\n }),\n defineField({\n name: LinkKind.external,\n type: \"url\",\n title: \"External Link\",\n ...visibleIfKind(LinkKind.external),\n ...requiredIfKind(LinkKind.external),\n }),\n defineField({\n name: LinkKind.email,\n type: \"string\",\n title: \"Email\",\n ...visibleIfKind(LinkKind.email),\n ...requiredIfKind(LinkKind.email),\n }),\n defineField({\n name: LinkKind.phone,\n type: \"string\",\n title: \"Phone\",\n ...visibleIfKind(LinkKind.phone),\n ...requiredIfKind(LinkKind.phone),\n }),\n defineField({\n name: LinkKind.file,\n type: \"file\",\n title: \"File\",\n ...visibleIfKind(LinkKind.file),\n ...requiredIfKind(LinkKind.file),\n }),\n defineField({\n name: LinkKind.internal,\n type: \"object\",\n ...visibleIfKind(LinkKind.internal),\n ...requiredIfKind(LinkKind.internal),\n options: { collapsed: false, collapsible: false },\n components: {\n field: (props) => <>{props.children}</>,\n input: (props) => <InternalLinkInput {...props} />,\n },\n fields: [\n defineField({\n type: \"reference\",\n name: \"link\",\n title: \"Internal Link\",\n description: \"Select a page and an optional section target.\",\n weak: config.weakReferences ?? true,\n to: config.internalLinkSchemaTypes,\n options: {\n disableNew: true,\n },\n }),\n defineField({\n type: \"string\",\n name: \"sectionTarget\",\n title: \"Section Target\",\n }),\n ],\n }),\n defineField({\n name: \"customText\",\n type: \"string\",\n title: \"Custom text\",\n description: \"Will take precedence over inferred text.\",\n }),\n defineField({\n name: \"canDownload\",\n type: \"boolean\",\n title: \"Downloadable\",\n initialValue: true,\n description: \"The file will be downloaded when the link is clicked.\",\n options: { layout: \"switch\" },\n ...visibleIfKind(LinkKind.file),\n ...requiredIfKind(LinkKind.file),\n }),\n defineField({\n name: \"openInNewTab\",\n type: \"boolean\",\n title: \"Open in new tab\",\n description: \"Open the link in a new tab.\",\n initialValue: false,\n options: { layout: \"switch\" },\n ...visibleIfKind([LinkKind.external, LinkKind.internal]),\n }),\n ],\n preview: {\n select: {\n kind: \"kind\",\n email: \"email\",\n phone: \"phone\",\n customText: \"customText\",\n fileName: \"file.asset.originalFilename\",\n externalUrl: \"external\",\n internalUri: \"internal.uri.current\",\n internalTitle: \"internal.title\",\n },\n prepare: (props) => {\n return buildLinkPreview(props);\n },\n },\n }),\n ],\n },\n };\n});\n\nexport {\n wildSanityLinkFieldPlugin,\n typeName,\n LinkKind,\n buildLinkPreview,\n type PluginConfig,\n type FieldOptions,\n type SectionQueryResult,\n};\n"],"names":["jsx","Stack","MemberField","useFieldMember","React","unset","useClient","jsxs","AsyncAutocomplete","changeCase","set","Card","Box","Text","Fragment","visibleIf","requiredIf","definePlugin","defineType","defineField"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/input.tsx","../src/preview.tsx","../src/types.tsx","../src/index.tsx"],"sourcesContent":["import { useFieldMember } from \"@madebywild/sanity-utils\";\nimport { AsyncAutocomplete } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport { Box, Card, Stack, Text } from \"@sanity/ui\";\nimport * as changeCase from \"change-case\";\nimport * as React from \"react\";\nimport type { ObjectInputProps, ObjectMember, Reference } from \"sanity\";\nimport { MemberField, set, unset, useClient } from \"sanity\";\nimport type { FieldOptions } from \"./types\";\n\nfunction FieldInput(props: ObjectInputProps) {\n const options = props.schemaType.options as FieldOptions | undefined;\n\n return (\n <Stack space={4}>\n {props.members.map((member: ObjectMember) => {\n if (member.kind !== \"field\") return null;\n if (options?.noCustomText && member.name === \"customText\") return null;\n return <MemberField key={member.key} member={member} {...props} />;\n })}\n </Stack>\n );\n}\n\nconst SectionsQuery = `\n *[_id == $pageId && defined(pageBuilder.sectionsArray)][0]{\n \"sections\": array::compact(pageBuilder.sectionsArray[]{\n \"value\": _key,\n \"label\": coalesce(sectionSettings.sectionTitle, _type),\n }),\n }.sections\n`;\n\nfunction InternalLinkInput(props: ObjectInputProps) {\n const linkFieldMember = useFieldMember(props.members, \"link\");\n\n const selectedLink = props.value?.link as Reference | undefined;\n const selectedSection = props.value?.sectionTarget as string | undefined;\n\n // Reset sectionTarget if link is removed.\n React.useEffect(() => {\n if (!selectedLink?._ref && selectedSection !== undefined) {\n props.onChange(unset([\"sectionTarget\"]));\n }\n }, [selectedLink, selectedSection, props.onChange]);\n\n const client = useClient({ apiVersion: \"2025-10-21\" });\n\n const fetchSections = React.useCallback(() => {\n if (!selectedLink?._ref) return [];\n return client.fetch(SectionsQuery, { pageId: selectedLink._ref }).catch(() => []);\n }, [client, selectedLink, SectionsQuery]);\n\n return (\n <Stack space={2}>\n {linkFieldMember && <MemberField member={linkFieldMember} {...props} />}\n <AsyncAutocomplete\n placeholder=\"Select section\"\n noOptionsPlaceholder=\"No sections found\"\n listItems={fetchSections}\n value={selectedSection}\n renderValue={(value, opt) => {\n return opt?.label ? changeCase.capitalCase(opt.label) : value;\n }}\n onChange={(value) => {\n const next = value ? set(value, [\"sectionTarget\"]) : unset([\"sectionTarget\"]);\n return props.onChange(next);\n }}\n renderOption={({ label, value }) => {\n return (\n <Card as=\"button\">\n <Box flex={1} padding={3}>\n <Text size={2}>{changeCase.capitalCase(label ?? value)}</Text>\n </Box>\n </Card>\n );\n }}\n />\n </Stack>\n );\n}\n\nexport { FieldInput, InternalLinkInput };\n","import type { LinkKind } from \"./types\";\n\n/** @public */\nexport function buildLinkPreview({\n kind,\n email,\n phone,\n fileName,\n customText,\n internalUri,\n externalUrl,\n internalTitle,\n}: {\n kind?: string;\n email?: string;\n phone?: string;\n fileName?: string;\n customText?: string;\n externalUrl?: string;\n internalUri?: string;\n internalTitle?: string;\n}) {\n switch (kind as keyof typeof LinkKind) {\n case \"internal\": {\n return {\n title: customText ?? internalTitle ?? \"Internal Link\",\n subtitle: internalUri,\n media: () => <>📄</>,\n };\n }\n case \"external\":\n return {\n title: customText ?? \"External Link\",\n subtitle: externalUrl,\n media: () => <>🌍</>,\n };\n case \"email\":\n return {\n title: customText ?? \"Email Link\",\n subtitle: email,\n media: () => <>📧</>,\n };\n case \"phone\":\n return {\n title: customText ?? \"Phone Link\",\n subtitle: phone,\n media: () => <>☎️</>,\n };\n case \"file\":\n return {\n title: customText ?? \"File Link\",\n subtitle: fileName,\n media: () => <>📃</>,\n };\n default:\n return {\n title: customText ?? \"Empty Link\",\n media: () => <>⛓️‍💥</>,\n };\n }\n}\n","import type { ListItem } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport type { ObjectDefinition, ObjectOptions, ReferenceTo } from \"sanity\";\n\n/** @public */\nexport const typeName = \"wild.link\" as const;\n\n/** @public */\nexport const LinkKind = {\n internal: \"internal\",\n external: \"external\",\n email: \"email\",\n phone: \"phone\",\n file: \"file\",\n} as const;\n\n/** @public */\nexport type SectionQueryResult = ListItem[];\n\n/** @public */\nexport type PluginConfig = {\n weakReferences?: boolean;\n internalLinkSchemaTypes: ReferenceTo;\n};\n\n/** @public */\nexport type FieldOptions = ObjectOptions & {\n noCustomText?: boolean;\n};\n\n// Add the custom field definition to Sanity's intrinsic definitions\n// so that type checking works correctly when using this field type.\ndeclare module \"sanity\" {\n export interface IntrinsicDefinitions {\n [typeName]: Omit<ObjectDefinition, \"type\" | \"fields\" | \"options\"> & {\n type: typeof typeName;\n options?: FieldOptions;\n };\n }\n}\n","import { requiredIf, visibleIf } from \"@madebywild/sanity-utils\";\nimport { defineField, definePlugin, defineType } from \"sanity\";\nimport { FieldInput, InternalLinkInput } from \"./input\";\nimport { buildLinkPreview } from \"./preview\";\nimport { type FieldOptions, LinkKind, type PluginConfig, type SectionQueryResult, typeName } from \"./types\";\n\nconst visibleIfKind = visibleIf(\"kind\");\nconst requiredIfKind = requiredIf(\"kind\");\n\n/** @public */\nconst wildSanityLinkFieldPlugin = definePlugin<PluginConfig>((config) => {\n return {\n name: \"@madebywild/sanity-link-field\",\n schema: {\n types: [\n defineType({\n name: typeName,\n type: \"object\",\n title: \"Link\",\n description: \"Link to an internal page, external URL and more.\",\n icon: () => <>🔗</>,\n components: {\n input: (props) => <FieldInput {...props} />,\n },\n fields: [\n defineField({\n name: \"kind\",\n type: \"string\",\n title: \"Link Kind\",\n description: \"Select the kind of link.\",\n validation: (R) => R.required().error(\"Select a link kind.\"),\n options: {\n layout: \"radio\",\n direction: \"horizontal\",\n list: [\n { title: \"📄 Internal\", value: LinkKind.internal },\n { title: \"🌍 External\", value: LinkKind.external },\n { title: \"📧 Email\", value: LinkKind.email },\n { title: \"☎️ Phone\", value: LinkKind.phone },\n { title: \"📃 File\", value: LinkKind.file },\n ],\n },\n }),\n defineField({\n name: LinkKind.external,\n type: \"url\",\n title: \"External Link\",\n ...visibleIfKind(LinkKind.external),\n ...requiredIfKind(LinkKind.external),\n }),\n defineField({\n name: LinkKind.email,\n type: \"string\",\n title: \"Email\",\n ...visibleIfKind(LinkKind.email),\n ...requiredIfKind(LinkKind.email),\n }),\n defineField({\n name: LinkKind.phone,\n type: \"string\",\n title: \"Phone\",\n ...visibleIfKind(LinkKind.phone),\n ...requiredIfKind(LinkKind.phone),\n }),\n defineField({\n name: LinkKind.file,\n type: \"file\",\n title: \"File\",\n ...visibleIfKind(LinkKind.file),\n ...requiredIfKind(LinkKind.file),\n }),\n defineField({\n name: LinkKind.internal,\n type: \"object\",\n ...visibleIfKind(LinkKind.internal),\n ...requiredIfKind(LinkKind.internal),\n options: { collapsed: false, collapsible: false },\n components: {\n field: (props) => <>{props.children}</>,\n input: (props) => <InternalLinkInput {...props} />,\n },\n fields: [\n defineField({\n type: \"reference\",\n name: \"link\",\n title: \"Internal Link\",\n description: \"Select a page and an optional section target.\",\n weak: config.weakReferences ?? true,\n to: config.internalLinkSchemaTypes,\n options: {\n disableNew: true,\n },\n }),\n defineField({\n type: \"string\",\n name: \"sectionTarget\",\n title: \"Section Target\",\n }),\n ],\n }),\n defineField({\n name: \"customText\",\n type: \"string\",\n title: \"Custom text\",\n description: \"Will take precedence over inferred text.\",\n }),\n defineField({\n name: \"canDownload\",\n type: \"boolean\",\n title: \"Downloadable\",\n initialValue: true,\n description: \"The file will be downloaded when the link is clicked.\",\n options: { layout: \"switch\" },\n ...visibleIfKind(LinkKind.file),\n ...requiredIfKind(LinkKind.file),\n }),\n defineField({\n name: \"openInNewTab\",\n type: \"boolean\",\n title: \"Open in new tab\",\n description: \"Open the link in a new tab.\",\n initialValue: false,\n options: { layout: \"switch\" },\n ...visibleIfKind([LinkKind.external, LinkKind.internal]),\n }),\n ],\n preview: {\n select: {\n kind: \"kind\",\n email: \"email\",\n phone: \"phone\",\n customText: \"customText\",\n fileName: \"file.asset.originalFilename\",\n externalUrl: \"external\",\n internalUri: \"internal.uri.current\",\n internalTitle: \"internal.title\",\n },\n prepare: (props) => {\n return buildLinkPreview(props);\n },\n },\n }),\n ],\n },\n };\n});\n\nexport {\n wildSanityLinkFieldPlugin,\n typeName,\n LinkKind,\n buildLinkPreview,\n type PluginConfig,\n type FieldOptions,\n type SectionQueryResult,\n};\n"],"names":["jsx","Stack","MemberField","useFieldMember","React","unset","useClient","jsxs","AsyncAutocomplete","changeCase","set","Card","Box","Text","Fragment","visibleIf","requiredIf","definePlugin","defineType","defineField"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as sanity0 from "sanity";
2
- import { ObjectOptions, ReferenceTo, StringDefinition } from "sanity";
2
+ import { ObjectDefinition, ObjectOptions, ReferenceTo } from "sanity";
3
3
  import * as react1 from "react";
4
4
  /** @public */
5
5
  declare function buildLinkPreview({
@@ -58,8 +58,9 @@ type FieldOptions = ObjectOptions & {
58
58
  };
59
59
  declare module "sanity" {
60
60
  interface IntrinsicDefinitions {
61
- [typeName]: Omit<StringDefinition, "type" | "fields"> & {
61
+ [typeName]: Omit<ObjectDefinition, "type" | "fields" | "options"> & {
62
62
  type: typeof typeName;
63
+ options?: FieldOptions;
63
64
  };
64
65
  }
65
66
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as sanity0 from "sanity";
2
- import { ObjectOptions, ReferenceTo, StringDefinition } from "sanity";
2
+ import { ObjectDefinition, ObjectOptions, ReferenceTo } from "sanity";
3
3
  import * as react1 from "react";
4
4
  /** @public */
5
5
  declare function buildLinkPreview({
@@ -58,8 +58,9 @@ type FieldOptions = ObjectOptions & {
58
58
  };
59
59
  declare module "sanity" {
60
60
  interface IntrinsicDefinitions {
61
- [typeName]: Omit<StringDefinition, "type" | "fields"> & {
61
+ [typeName]: Omit<ObjectDefinition, "type" | "fields" | "options"> & {
62
62
  type: typeof typeName;
63
+ options?: FieldOptions;
63
64
  };
64
65
  }
65
66
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/input.tsx","../src/preview.tsx","../src/types.tsx","../src/index.tsx"],"sourcesContent":["import { useFieldMember } from \"@madebywild/sanity-utils\";\nimport { AsyncAutocomplete } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport { Box, Card, Stack, Text } from \"@sanity/ui\";\nimport * as changeCase from \"change-case\";\nimport * as React from \"react\";\nimport type { ObjectInputProps, ObjectMember, Reference } from \"sanity\";\nimport { MemberField, set, unset, useClient } from \"sanity\";\nimport type { FieldOptions } from \"./types\";\n\nfunction FieldInput(props: ObjectInputProps) {\n const options = props.schemaType.options as FieldOptions | undefined;\n\n return (\n <Stack space={4}>\n {props.members.map((member: ObjectMember) => {\n if (member.kind !== \"field\") return null;\n if (options?.noCustomText && member.name === \"customText\") return null;\n return <MemberField key={member.key} member={member} {...props} />;\n })}\n </Stack>\n );\n}\n\nconst SectionsQuery = `\n *[_id == $pageId && defined(pageBuilder.sectionsArray)][0]{\n \"sections\": array::compact(pageBuilder.sectionsArray[]{\n \"value\": _key,\n \"label\": coalesce(sectionSettings.sectionTitle, _type),\n }),\n }.sections\n`;\n\nfunction InternalLinkInput(props: ObjectInputProps) {\n const linkFieldMember = useFieldMember(props.members, \"link\");\n\n const selectedLink = props.value?.link as Reference | undefined;\n const selectedSection = props.value?.sectionTarget as string | undefined;\n\n // Reset sectionTarget if link is removed.\n React.useEffect(() => {\n if (!selectedLink?._ref && selectedSection !== undefined) {\n props.onChange(unset([\"sectionTarget\"]));\n }\n }, [selectedLink, selectedSection, props.onChange]);\n\n const client = useClient({ apiVersion: \"2025-10-21\" });\n\n const fetchSections = React.useCallback(() => {\n if (!selectedLink?._ref) return [];\n return client.fetch(SectionsQuery, { pageId: selectedLink._ref }).catch(() => []);\n }, [client, selectedLink, SectionsQuery]);\n\n return (\n <Stack space={2}>\n {linkFieldMember && <MemberField member={linkFieldMember} {...props} />}\n <AsyncAutocomplete\n placeholder=\"Select section\"\n noOptionsPlaceholder=\"No sections found\"\n listItems={fetchSections}\n value={selectedSection}\n renderValue={(value, opt) => {\n return opt?.label ? changeCase.capitalCase(opt.label) : value;\n }}\n onChange={(value) => {\n const next = value ? set(value, [\"sectionTarget\"]) : unset([\"sectionTarget\"]);\n return props.onChange(next);\n }}\n renderOption={({ label, value }) => {\n return (\n <Card as=\"button\">\n <Box flex={1} padding={3}>\n <Text size={2}>{changeCase.capitalCase(label ?? value)}</Text>\n </Box>\n </Card>\n );\n }}\n />\n </Stack>\n );\n}\n\nexport { FieldInput, InternalLinkInput };\n","import type { LinkKind } from \"./types\";\n\n/** @public */\nexport function buildLinkPreview({\n kind,\n email,\n phone,\n fileName,\n customText,\n internalUri,\n externalUrl,\n internalTitle,\n}: {\n kind?: string;\n email?: string;\n phone?: string;\n fileName?: string;\n customText?: string;\n externalUrl?: string;\n internalUri?: string;\n internalTitle?: string;\n}) {\n switch (kind as keyof typeof LinkKind) {\n case \"internal\": {\n return {\n title: customText ?? internalTitle ?? \"Internal Link\",\n subtitle: internalUri,\n media: () => <>📄</>,\n };\n }\n case \"external\":\n return {\n title: customText ?? \"External Link\",\n subtitle: externalUrl,\n media: () => <>🌍</>,\n };\n case \"email\":\n return {\n title: customText ?? \"Email Link\",\n subtitle: email,\n media: () => <>📧</>,\n };\n case \"phone\":\n return {\n title: customText ?? \"Phone Link\",\n subtitle: phone,\n media: () => <>☎️</>,\n };\n case \"file\":\n return {\n title: customText ?? \"File Link\",\n subtitle: fileName,\n media: () => <>📃</>,\n };\n default:\n return {\n title: customText ?? \"Empty Link\",\n media: () => <>⛓️‍💥</>,\n };\n }\n}\n","import type { ListItem } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport type { ObjectOptions, ReferenceTo, StringDefinition } from \"sanity\";\n\n/** @public */\nexport const typeName = \"wild.link\" as const;\n\n/** @public */\nexport const LinkKind = {\n internal: \"internal\",\n external: \"external\",\n email: \"email\",\n phone: \"phone\",\n file: \"file\",\n} as const;\n\n/** @public */\nexport type SectionQueryResult = ListItem[];\n\n/** @public */\nexport type PluginConfig = {\n weakReferences?: boolean;\n internalLinkSchemaTypes: ReferenceTo;\n};\n\n/** @public */\nexport type FieldOptions = ObjectOptions & {\n noCustomText?: boolean;\n};\n\n// Add the custom field definition to Sanity's intrinsic definitions\n// so that type checking works correctly when using this field type.\ndeclare module \"sanity\" {\n export interface IntrinsicDefinitions {\n [typeName]: Omit<StringDefinition, \"type\" | \"fields\"> & {\n type: typeof typeName;\n };\n }\n}\n","import { requiredIf, visibleIf } from \"@madebywild/sanity-utils\";\nimport { defineField, definePlugin, defineType } from \"sanity\";\nimport { FieldInput, InternalLinkInput } from \"./input\";\nimport { buildLinkPreview } from \"./preview\";\nimport { type FieldOptions, LinkKind, type PluginConfig, type SectionQueryResult, typeName } from \"./types\";\n\nconst visibleIfKind = visibleIf(\"kind\");\nconst requiredIfKind = requiredIf(\"kind\");\n\n/** @public */\nconst wildSanityLinkFieldPlugin = definePlugin<PluginConfig>((config) => {\n return {\n name: \"@madebywild/sanity-link-field\",\n schema: {\n types: [\n defineType({\n name: typeName,\n type: \"object\",\n title: \"Link\",\n description: \"Link to an internal page, external URL and more.\",\n icon: () => <>🔗</>,\n components: {\n input: (props) => <FieldInput {...props} />,\n },\n fields: [\n defineField({\n name: \"kind\",\n type: \"string\",\n title: \"Link Kind\",\n description: \"Select the kind of link.\",\n validation: (R) => R.required().error(\"Select a link kind.\"),\n options: {\n layout: \"radio\",\n direction: \"horizontal\",\n list: [\n { title: \"📄 Internal\", value: LinkKind.internal },\n { title: \"🌍 External\", value: LinkKind.external },\n { title: \"📧 Email\", value: LinkKind.email },\n { title: \"☎️ Phone\", value: LinkKind.phone },\n { title: \"📃 File\", value: LinkKind.file },\n ],\n },\n }),\n defineField({\n name: LinkKind.external,\n type: \"url\",\n title: \"External Link\",\n ...visibleIfKind(LinkKind.external),\n ...requiredIfKind(LinkKind.external),\n }),\n defineField({\n name: LinkKind.email,\n type: \"string\",\n title: \"Email\",\n ...visibleIfKind(LinkKind.email),\n ...requiredIfKind(LinkKind.email),\n }),\n defineField({\n name: LinkKind.phone,\n type: \"string\",\n title: \"Phone\",\n ...visibleIfKind(LinkKind.phone),\n ...requiredIfKind(LinkKind.phone),\n }),\n defineField({\n name: LinkKind.file,\n type: \"file\",\n title: \"File\",\n ...visibleIfKind(LinkKind.file),\n ...requiredIfKind(LinkKind.file),\n }),\n defineField({\n name: LinkKind.internal,\n type: \"object\",\n ...visibleIfKind(LinkKind.internal),\n ...requiredIfKind(LinkKind.internal),\n options: { collapsed: false, collapsible: false },\n components: {\n field: (props) => <>{props.children}</>,\n input: (props) => <InternalLinkInput {...props} />,\n },\n fields: [\n defineField({\n type: \"reference\",\n name: \"link\",\n title: \"Internal Link\",\n description: \"Select a page and an optional section target.\",\n weak: config.weakReferences ?? true,\n to: config.internalLinkSchemaTypes,\n options: {\n disableNew: true,\n },\n }),\n defineField({\n type: \"string\",\n name: \"sectionTarget\",\n title: \"Section Target\",\n }),\n ],\n }),\n defineField({\n name: \"customText\",\n type: \"string\",\n title: \"Custom text\",\n description: \"Will take precedence over inferred text.\",\n }),\n defineField({\n name: \"canDownload\",\n type: \"boolean\",\n title: \"Downloadable\",\n initialValue: true,\n description: \"The file will be downloaded when the link is clicked.\",\n options: { layout: \"switch\" },\n ...visibleIfKind(LinkKind.file),\n ...requiredIfKind(LinkKind.file),\n }),\n defineField({\n name: \"openInNewTab\",\n type: \"boolean\",\n title: \"Open in new tab\",\n description: \"Open the link in a new tab.\",\n initialValue: false,\n options: { layout: \"switch\" },\n ...visibleIfKind([LinkKind.external, LinkKind.internal]),\n }),\n ],\n preview: {\n select: {\n kind: \"kind\",\n email: \"email\",\n phone: \"phone\",\n customText: \"customText\",\n fileName: \"file.asset.originalFilename\",\n externalUrl: \"external\",\n internalUri: \"internal.uri.current\",\n internalTitle: \"internal.title\",\n },\n prepare: (props) => {\n return buildLinkPreview(props);\n },\n },\n }),\n ],\n },\n };\n});\n\nexport {\n wildSanityLinkFieldPlugin,\n typeName,\n LinkKind,\n buildLinkPreview,\n type PluginConfig,\n type FieldOptions,\n type SectionQueryResult,\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/input.tsx","../src/preview.tsx","../src/types.tsx","../src/index.tsx"],"sourcesContent":["import { useFieldMember } from \"@madebywild/sanity-utils\";\nimport { AsyncAutocomplete } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport { Box, Card, Stack, Text } from \"@sanity/ui\";\nimport * as changeCase from \"change-case\";\nimport * as React from \"react\";\nimport type { ObjectInputProps, ObjectMember, Reference } from \"sanity\";\nimport { MemberField, set, unset, useClient } from \"sanity\";\nimport type { FieldOptions } from \"./types\";\n\nfunction FieldInput(props: ObjectInputProps) {\n const options = props.schemaType.options as FieldOptions | undefined;\n\n return (\n <Stack space={4}>\n {props.members.map((member: ObjectMember) => {\n if (member.kind !== \"field\") return null;\n if (options?.noCustomText && member.name === \"customText\") return null;\n return <MemberField key={member.key} member={member} {...props} />;\n })}\n </Stack>\n );\n}\n\nconst SectionsQuery = `\n *[_id == $pageId && defined(pageBuilder.sectionsArray)][0]{\n \"sections\": array::compact(pageBuilder.sectionsArray[]{\n \"value\": _key,\n \"label\": coalesce(sectionSettings.sectionTitle, _type),\n }),\n }.sections\n`;\n\nfunction InternalLinkInput(props: ObjectInputProps) {\n const linkFieldMember = useFieldMember(props.members, \"link\");\n\n const selectedLink = props.value?.link as Reference | undefined;\n const selectedSection = props.value?.sectionTarget as string | undefined;\n\n // Reset sectionTarget if link is removed.\n React.useEffect(() => {\n if (!selectedLink?._ref && selectedSection !== undefined) {\n props.onChange(unset([\"sectionTarget\"]));\n }\n }, [selectedLink, selectedSection, props.onChange]);\n\n const client = useClient({ apiVersion: \"2025-10-21\" });\n\n const fetchSections = React.useCallback(() => {\n if (!selectedLink?._ref) return [];\n return client.fetch(SectionsQuery, { pageId: selectedLink._ref }).catch(() => []);\n }, [client, selectedLink, SectionsQuery]);\n\n return (\n <Stack space={2}>\n {linkFieldMember && <MemberField member={linkFieldMember} {...props} />}\n <AsyncAutocomplete\n placeholder=\"Select section\"\n noOptionsPlaceholder=\"No sections found\"\n listItems={fetchSections}\n value={selectedSection}\n renderValue={(value, opt) => {\n return opt?.label ? changeCase.capitalCase(opt.label) : value;\n }}\n onChange={(value) => {\n const next = value ? set(value, [\"sectionTarget\"]) : unset([\"sectionTarget\"]);\n return props.onChange(next);\n }}\n renderOption={({ label, value }) => {\n return (\n <Card as=\"button\">\n <Box flex={1} padding={3}>\n <Text size={2}>{changeCase.capitalCase(label ?? value)}</Text>\n </Box>\n </Card>\n );\n }}\n />\n </Stack>\n );\n}\n\nexport { FieldInput, InternalLinkInput };\n","import type { LinkKind } from \"./types\";\n\n/** @public */\nexport function buildLinkPreview({\n kind,\n email,\n phone,\n fileName,\n customText,\n internalUri,\n externalUrl,\n internalTitle,\n}: {\n kind?: string;\n email?: string;\n phone?: string;\n fileName?: string;\n customText?: string;\n externalUrl?: string;\n internalUri?: string;\n internalTitle?: string;\n}) {\n switch (kind as keyof typeof LinkKind) {\n case \"internal\": {\n return {\n title: customText ?? internalTitle ?? \"Internal Link\",\n subtitle: internalUri,\n media: () => <>📄</>,\n };\n }\n case \"external\":\n return {\n title: customText ?? \"External Link\",\n subtitle: externalUrl,\n media: () => <>🌍</>,\n };\n case \"email\":\n return {\n title: customText ?? \"Email Link\",\n subtitle: email,\n media: () => <>📧</>,\n };\n case \"phone\":\n return {\n title: customText ?? \"Phone Link\",\n subtitle: phone,\n media: () => <>☎️</>,\n };\n case \"file\":\n return {\n title: customText ?? \"File Link\",\n subtitle: fileName,\n media: () => <>📃</>,\n };\n default:\n return {\n title: customText ?? \"Empty Link\",\n media: () => <>⛓️‍💥</>,\n };\n }\n}\n","import type { ListItem } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport type { ObjectDefinition, ObjectOptions, ReferenceTo } from \"sanity\";\n\n/** @public */\nexport const typeName = \"wild.link\" as const;\n\n/** @public */\nexport const LinkKind = {\n internal: \"internal\",\n external: \"external\",\n email: \"email\",\n phone: \"phone\",\n file: \"file\",\n} as const;\n\n/** @public */\nexport type SectionQueryResult = ListItem[];\n\n/** @public */\nexport type PluginConfig = {\n weakReferences?: boolean;\n internalLinkSchemaTypes: ReferenceTo;\n};\n\n/** @public */\nexport type FieldOptions = ObjectOptions & {\n noCustomText?: boolean;\n};\n\n// Add the custom field definition to Sanity's intrinsic definitions\n// so that type checking works correctly when using this field type.\ndeclare module \"sanity\" {\n export interface IntrinsicDefinitions {\n [typeName]: Omit<ObjectDefinition, \"type\" | \"fields\" | \"options\"> & {\n type: typeof typeName;\n options?: FieldOptions;\n };\n }\n}\n","import { requiredIf, visibleIf } from \"@madebywild/sanity-utils\";\nimport { defineField, definePlugin, defineType } from \"sanity\";\nimport { FieldInput, InternalLinkInput } from \"./input\";\nimport { buildLinkPreview } from \"./preview\";\nimport { type FieldOptions, LinkKind, type PluginConfig, type SectionQueryResult, typeName } from \"./types\";\n\nconst visibleIfKind = visibleIf(\"kind\");\nconst requiredIfKind = requiredIf(\"kind\");\n\n/** @public */\nconst wildSanityLinkFieldPlugin = definePlugin<PluginConfig>((config) => {\n return {\n name: \"@madebywild/sanity-link-field\",\n schema: {\n types: [\n defineType({\n name: typeName,\n type: \"object\",\n title: \"Link\",\n description: \"Link to an internal page, external URL and more.\",\n icon: () => <>🔗</>,\n components: {\n input: (props) => <FieldInput {...props} />,\n },\n fields: [\n defineField({\n name: \"kind\",\n type: \"string\",\n title: \"Link Kind\",\n description: \"Select the kind of link.\",\n validation: (R) => R.required().error(\"Select a link kind.\"),\n options: {\n layout: \"radio\",\n direction: \"horizontal\",\n list: [\n { title: \"📄 Internal\", value: LinkKind.internal },\n { title: \"🌍 External\", value: LinkKind.external },\n { title: \"📧 Email\", value: LinkKind.email },\n { title: \"☎️ Phone\", value: LinkKind.phone },\n { title: \"📃 File\", value: LinkKind.file },\n ],\n },\n }),\n defineField({\n name: LinkKind.external,\n type: \"url\",\n title: \"External Link\",\n ...visibleIfKind(LinkKind.external),\n ...requiredIfKind(LinkKind.external),\n }),\n defineField({\n name: LinkKind.email,\n type: \"string\",\n title: \"Email\",\n ...visibleIfKind(LinkKind.email),\n ...requiredIfKind(LinkKind.email),\n }),\n defineField({\n name: LinkKind.phone,\n type: \"string\",\n title: \"Phone\",\n ...visibleIfKind(LinkKind.phone),\n ...requiredIfKind(LinkKind.phone),\n }),\n defineField({\n name: LinkKind.file,\n type: \"file\",\n title: \"File\",\n ...visibleIfKind(LinkKind.file),\n ...requiredIfKind(LinkKind.file),\n }),\n defineField({\n name: LinkKind.internal,\n type: \"object\",\n ...visibleIfKind(LinkKind.internal),\n ...requiredIfKind(LinkKind.internal),\n options: { collapsed: false, collapsible: false },\n components: {\n field: (props) => <>{props.children}</>,\n input: (props) => <InternalLinkInput {...props} />,\n },\n fields: [\n defineField({\n type: \"reference\",\n name: \"link\",\n title: \"Internal Link\",\n description: \"Select a page and an optional section target.\",\n weak: config.weakReferences ?? true,\n to: config.internalLinkSchemaTypes,\n options: {\n disableNew: true,\n },\n }),\n defineField({\n type: \"string\",\n name: \"sectionTarget\",\n title: \"Section Target\",\n }),\n ],\n }),\n defineField({\n name: \"customText\",\n type: \"string\",\n title: \"Custom text\",\n description: \"Will take precedence over inferred text.\",\n }),\n defineField({\n name: \"canDownload\",\n type: \"boolean\",\n title: \"Downloadable\",\n initialValue: true,\n description: \"The file will be downloaded when the link is clicked.\",\n options: { layout: \"switch\" },\n ...visibleIfKind(LinkKind.file),\n ...requiredIfKind(LinkKind.file),\n }),\n defineField({\n name: \"openInNewTab\",\n type: \"boolean\",\n title: \"Open in new tab\",\n description: \"Open the link in a new tab.\",\n initialValue: false,\n options: { layout: \"switch\" },\n ...visibleIfKind([LinkKind.external, LinkKind.internal]),\n }),\n ],\n preview: {\n select: {\n kind: \"kind\",\n email: \"email\",\n phone: \"phone\",\n customText: \"customText\",\n fileName: \"file.asset.originalFilename\",\n externalUrl: \"external\",\n internalUri: \"internal.uri.current\",\n internalTitle: \"internal.title\",\n },\n prepare: (props) => {\n return buildLinkPreview(props);\n },\n },\n }),\n ],\n },\n };\n});\n\nexport {\n wildSanityLinkFieldPlugin,\n typeName,\n LinkKind,\n buildLinkPreview,\n type PluginConfig,\n type FieldOptions,\n type SectionQueryResult,\n};\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madebywild/sanity-link-field",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "UNLICENSED",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "change-case": "^5.4.4",
25
- "@madebywild/sanity-utils": "0.2.2"
25
+ "@madebywild/sanity-utils": "0.2.3"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "@sanity/ui": "^3.1",
package/src/types.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ListItem } from "@madebywild/sanity-utils/async-autocomplete";
2
- import type { ObjectOptions, ReferenceTo, StringDefinition } from "sanity";
2
+ import type { ObjectDefinition, ObjectOptions, ReferenceTo } from "sanity";
3
3
 
4
4
  /** @public */
5
5
  export const typeName = "wild.link" as const;
@@ -31,8 +31,9 @@ export type FieldOptions = ObjectOptions & {
31
31
  // so that type checking works correctly when using this field type.
32
32
  declare module "sanity" {
33
33
  export interface IntrinsicDefinitions {
34
- [typeName]: Omit<StringDefinition, "type" | "fields"> & {
34
+ [typeName]: Omit<ObjectDefinition, "type" | "fields" | "options"> & {
35
35
  type: typeof typeName;
36
+ options?: FieldOptions;
36
37
  };
37
38
  }
38
39
  }