@sanity/language-filter 2.31.2-performance-opts.9 → 3.0.0-v3-studio.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,43 +1,89 @@
1
1
  {
2
2
  "name": "@sanity/language-filter",
3
- "version": "2.31.2-performance-opts.9+580febbe51",
3
+ "version": "3.0.0-v3-studio.2",
4
4
  "description": "A Sanity plugin that supports filtering localized fields by language",
5
- "main": "index.js",
6
- "scripts": {
7
- "clean": "rimraf lib dest"
8
- },
9
- "keywords": [
10
- "sanity",
11
- "cms",
12
- "headless",
13
- "realtime",
14
- "content",
15
- "language-filter"
5
+ "author": "Sanity.io <hello@sanity.io>",
6
+ "license": "MIT",
7
+ "source": "./src/index.ts",
8
+ "main": "./lib/cjs/index.js",
9
+ "module": "./lib/esm/index.js",
10
+ "types": "./lib/types/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "require": "./lib/cjs/index.js",
14
+ "default": "./lib/esm/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "src",
19
+ "lib",
20
+ "v2-incompatible.js",
21
+ "sanity.json"
16
22
  ],
23
+ "scripts": {
24
+ "clean": "rimraf lib",
25
+ "lint": "eslint .",
26
+ "prebuild": "npm run clean && plugin-kit verify-package --silent",
27
+ "build": "parcel build --no-cache",
28
+ "watch": "parcel watch",
29
+ "test": "jest",
30
+ "link-watch": "plugin-kit link-watch",
31
+ "prepublishOnly": "npm run build",
32
+ "prepare": "husky install"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+ssh://git@github.com/sanity-io/language-filter.git"
37
+ },
38
+ "engines": {
39
+ "node": ">=14.0.0"
40
+ },
17
41
  "dependencies": {
18
42
  "@sanity/icons": "^1.3.4",
19
- "@sanity/types": "2.31.2-performance-opts.9+580febbe51",
20
- "@sanity/ui": "^0.37.21",
21
- "lodash": "^4.17.15",
22
- "rxjs": "^6.5.3"
43
+ "@sanity/incompatible-plugin": "^1.0.0",
44
+ "@sanity/ui": "^0.38.0",
45
+ "@sanity/util": "3.0.0-dev-preview.15"
46
+ },
47
+ "devDependencies": {
48
+ "@babel/preset-env": "^7.18.10",
49
+ "@babel/preset-react": "^7.18.6",
50
+ "@commitlint/cli": "^17.1.2",
51
+ "@commitlint/config-conventional": "^17.1.0",
52
+ "@parcel/packager-ts": "^2.7.0",
53
+ "@parcel/transformer-typescript-types": "^2.7.0",
54
+ "@sanity/plugin-kit": "^1.0.1",
55
+ "@sanity/semantic-release-preset": "^2.0.1",
56
+ "@types/jest": "^28.1.8",
57
+ "@typescript-eslint/eslint-plugin": "^5.35.1",
58
+ "@typescript-eslint/parser": "^5.35.1",
59
+ "eslint": "8.22.0",
60
+ "eslint-config-prettier": "^8.5.0",
61
+ "eslint-config-sanity": "^6.0.0",
62
+ "eslint-plugin-prettier": "^4.2.1",
63
+ "eslint-plugin-react": "^7.31.1",
64
+ "eslint-plugin-react-hooks": "^4.6.0",
65
+ "husky": "^8.0.1",
66
+ "jest": "^28.1.3",
67
+ "lint-staged": "^13.0.3",
68
+ "parcel": "^2.7.0",
69
+ "prettier": "^2.7.1",
70
+ "react": "^17.0.0 || ^18.0.0",
71
+ "rimraf": "^3.0.2",
72
+ "sanity": "3.0.0-dev-preview.15",
73
+ "ts-jest": "^28.0.8",
74
+ "typescript": "4.7.4"
23
75
  },
24
76
  "peerDependencies": {
25
- "prop-types": "^15.3",
26
- "react": "^16.9 || ^17"
77
+ "react": "^17.0.0 || ^18.0.0",
78
+ "sanity": "dev-preview"
27
79
  },
28
- "author": "Sanity.io <hello@sanity.io>",
29
- "license": "MIT",
30
80
  "bugs": {
31
- "url": "https://github.com/sanity-io/sanity/issues"
32
- },
33
- "homepage": "https://www.sanity.io/",
34
- "repository": {
35
- "type": "git",
36
- "url": "git+https://github.com/sanity-io/sanity.git",
37
- "directory": "packages/@sanity/language-filter"
38
- },
39
- "publishConfig": {
40
- "access": "public"
81
+ "url": "https://github.com/sanity-io/language-filter/issues"
41
82
  },
42
- "gitHead": "580febbe519250bafddafd3fa688fa469b0686a3"
83
+ "homepage": "https://github.com/sanity-io/language-filter#readme",
84
+ "sanityPlugin": {
85
+ "verifyPackage": {
86
+ "babelConfig": false
87
+ }
88
+ }
43
89
  }
package/sanity.json CHANGED
@@ -1,16 +1,8 @@
1
1
  {
2
- "paths": {
3
- "source": "./src",
4
- "compiled": "./lib"
5
- },
6
2
  "parts": [
7
3
  {
8
- "implements": "part:@sanity/desk-tool/filter-fields-fn",
9
- "path": "filter-fields"
10
- },
11
- {
12
- "implements": "part:@sanity/desk-tool/language-select-component",
13
- "path": "SelectLanguageProvider"
4
+ "implements": "part:@sanity/base/sanity-root",
5
+ "path": "./v2-incompatible.js"
14
6
  }
15
7
  ]
16
8
  }
@@ -0,0 +1,30 @@
1
+ import React, {createContext, PropsWithChildren, useContext, useMemo} from 'react'
2
+ import {LanguageFilterConfig} from './types'
3
+
4
+ export interface LanguageFilterContextValue {
5
+ // eslint-disable-next-line react/require-default-props
6
+ options: LanguageFilterConfig
7
+ // eslint-disable-next-line react/require-default-props
8
+ enabled: boolean
9
+ }
10
+
11
+ const LanguageFilterContext = createContext<LanguageFilterContextValue | undefined>(undefined)
12
+
13
+ export function LanguageFilterProvider({
14
+ options,
15
+ enabled,
16
+ children,
17
+ }: PropsWithChildren<
18
+ Omit<LanguageFilterContextValue, 'selectedLanguageIds' | 'setSelectedLanguageIds'>
19
+ >) {
20
+ const value = useMemo(() => ({options, enabled}), [options, enabled])
21
+ return <LanguageFilterContext.Provider value={value}>{children}</LanguageFilterContext.Provider>
22
+ }
23
+
24
+ export function useLanguageFilterContext() {
25
+ const value = useContext(LanguageFilterContext)
26
+ if (!value) {
27
+ throw new Error('LanguageFilterContext is missing')
28
+ }
29
+ return value
30
+ }
@@ -0,0 +1,147 @@
1
+ import {Box, Button, Card, Checkbox, Flex, Popover, Stack, Text, useClickOutside} from '@sanity/ui'
2
+ import React, {FormEvent, useCallback, useState} from 'react'
3
+ import {usePaneLanguages} from './usePaneLanguages'
4
+ import {LanguageFilterConfig} from './types'
5
+
6
+ export interface LanguageFilterMenuButtonProps {
7
+ options: LanguageFilterConfig
8
+ onSelectedIdsChange: (ids: string[]) => void
9
+ }
10
+
11
+ export function LanguageFilterMenuButton(props: LanguageFilterMenuButtonProps) {
12
+ const {options, onSelectedIdsChange} = props
13
+
14
+ const defaultLanguages = options.supportedLanguages.filter((l) =>
15
+ options.defaultLanguages?.includes(l.id)
16
+ )
17
+
18
+ const languageOptions = options.supportedLanguages.filter(
19
+ (l) => !options.defaultLanguages?.includes(l.id)
20
+ )
21
+ const [open, setOpen] = useState(false)
22
+ const {activeLanguages, allSelected, selectAll, selectNone, toggleLanguage} = usePaneLanguages({
23
+ options,
24
+ onSelectedIdsChange,
25
+ })
26
+ const [button, setButton] = useState<HTMLElement | null>(null)
27
+ const [popover, setPopover] = useState<HTMLElement | null>(null)
28
+
29
+ const handleToggleAll = useCallback(
30
+ (event: FormEvent<HTMLInputElement>) => {
31
+ const checked = event.currentTarget.checked
32
+
33
+ if (checked) {
34
+ selectAll()
35
+ } else {
36
+ selectNone()
37
+ }
38
+ },
39
+ [selectAll, selectNone]
40
+ )
41
+
42
+ const handleClick = useCallback(() => setOpen((o) => !o), [])
43
+
44
+ const handleClickOutside = useCallback(() => setOpen(false), [])
45
+
46
+ useClickOutside(handleClickOutside, [button, popover])
47
+
48
+ const content = (
49
+ <Box overflow="auto" padding={1}>
50
+ {defaultLanguages.length > 0 && (
51
+ <Card radius={2}>
52
+ <Stack padding={2} space={3}>
53
+ <Box paddingBottom={2}>
54
+ <Text size={1} weight="semibold">
55
+ Default language{defaultLanguages.length > 1 && <>s</>}
56
+ </Text>
57
+ </Box>
58
+
59
+ {defaultLanguages.map((l) => (
60
+ <Text key={l.id}>{l.title}</Text>
61
+ ))}
62
+ </Stack>
63
+ </Card>
64
+ )}
65
+
66
+ <Stack marginTop={3} padding={2} space={2}>
67
+ <Box paddingBottom={2}>
68
+ <Text size={1} weight="semibold">
69
+ Show translations
70
+ </Text>
71
+ </Box>
72
+
73
+ <Card as="label">
74
+ <Flex align="center" gap={2}>
75
+ <Checkbox checked={allSelected} name="_allSelected" onChange={handleToggleAll} />
76
+ <Box flex={1}>
77
+ <Text muted={!allSelected} weight="semibold">
78
+ All translations
79
+ </Text>
80
+ </Box>
81
+ </Flex>
82
+ </Card>
83
+
84
+ {languageOptions.map((lang) => (
85
+ <LanguageFilterOption
86
+ id={lang.id}
87
+ key={lang.id}
88
+ onToggle={toggleLanguage}
89
+ selected={activeLanguages.includes(lang.id)}
90
+ title={lang.title}
91
+ />
92
+ ))}
93
+ </Stack>
94
+ </Box>
95
+ )
96
+
97
+ const langCount = options.supportedLanguages.length
98
+ return (
99
+ <Popover content={content} open={open} portal ref={setPopover}>
100
+ <Button
101
+ text={
102
+ <Flex gap={1}>
103
+ <Box>Filter languages:</Box>
104
+ <Flex gap={1} justify="space-around">
105
+ <Flex
106
+ style={{width: `${Math.floor(Math.log10(langCount) + 1)}ch`}}
107
+ justify="flex-end"
108
+ >
109
+ {activeLanguages.length}
110
+ </Flex>
111
+ <Box>/</Box>
112
+ <Box>{langCount}</Box>
113
+ </Flex>
114
+ </Flex>
115
+ }
116
+ mode="bleed"
117
+ onClick={handleClick}
118
+ ref={setButton}
119
+ selected={open}
120
+ />
121
+ </Popover>
122
+ )
123
+ }
124
+
125
+ function LanguageFilterOption(props: {
126
+ id: string
127
+ onToggle: (id: string) => void
128
+ selected: boolean
129
+ title: string
130
+ }) {
131
+ const {id, onToggle, selected, title} = props
132
+
133
+ const handleChange = useCallback(() => {
134
+ onToggle(id)
135
+ }, [id, onToggle])
136
+
137
+ return (
138
+ <Card as="label">
139
+ <Flex align="center" gap={2}>
140
+ <Checkbox checked={selected} name={`language-${id}`} onChange={handleChange} />
141
+ <Box flex={1}>
142
+ <Text muted={!selected}>{title}</Text>
143
+ </Box>
144
+ </Flex>
145
+ </Card>
146
+ )
147
+ }
@@ -0,0 +1,91 @@
1
+ import React, {useEffect, useMemo} from 'react'
2
+ import {ObjectInputProps, ObjectMember, RenderInputCallback} from 'sanity'
3
+ import {LanguageFilterConfig} from './types'
4
+ import {defaultFilterField} from './filterField'
5
+ import {useLanguageFilterContext} from './LanguageFilterContext'
6
+ import {useSelectedLanguageIds} from './useSelectedLanguageIds'
7
+
8
+ export type LanguageFilterObjectInputProps = {
9
+ options: LanguageFilterConfig
10
+ next: RenderInputCallback
11
+ /**
12
+ * We need a way to communicate state changes between the pane menu and input components.
13
+ * LanguageFilter button lives outside the input-render tree, so Context is out.
14
+ * This is a workaround for that.
15
+ */
16
+ subscribeSelectedIds: (callback: (ids: string[]) => void) => () => void
17
+ } & ObjectInputProps
18
+
19
+ export function LanguageFilterObjectInput(
20
+ props: ObjectInputProps & {
21
+ next: RenderInputCallback
22
+ subscribeSelectedIds: (callback: (ids: string[]) => void) => () => void
23
+ }
24
+ ) {
25
+ const {options, enabled} = useLanguageFilterContext()
26
+ const {next, subscribeSelectedIds, ...restProps} = props
27
+ if (!enabled || !options) {
28
+ return <>{next(restProps)}</>
29
+ }
30
+ return (
31
+ <FilteredObjectInput
32
+ {...restProps}
33
+ next={next}
34
+ options={options}
35
+ subscribeSelectedIds={subscribeSelectedIds}
36
+ />
37
+ )
38
+ }
39
+
40
+ function FilteredObjectInput(props: LanguageFilterObjectInputProps) {
41
+ const {
42
+ members: membersProp,
43
+ options,
44
+ schemaType,
45
+ next,
46
+ subscribeSelectedIds,
47
+ ...restProps
48
+ } = props
49
+ const [selectedIds, setSelectedIds] = useSelectedLanguageIds(options)
50
+
51
+ useEffect(() => {
52
+ const unsubscribe = subscribeSelectedIds(setSelectedIds)
53
+ return () => unsubscribe()
54
+ }, [subscribeSelectedIds, setSelectedIds])
55
+
56
+ const activeLanguages = useMemo(
57
+ () => [...(options.defaultLanguages ?? []), ...selectedIds],
58
+ [options.defaultLanguages, selectedIds]
59
+ )
60
+
61
+ const filterField = options.filterField ?? defaultFilterField
62
+
63
+ const members: ObjectMember[] = useMemo(() => {
64
+ return membersProp
65
+ .filter((member) => {
66
+ return (
67
+ (member.kind === 'field' && filterField(schemaType, member, activeLanguages)) ||
68
+ member.kind === 'fieldSet'
69
+ )
70
+ })
71
+ .map((member) => {
72
+ if (member.kind === 'fieldSet') {
73
+ return {
74
+ ...member,
75
+ fieldSet: {
76
+ ...member.fieldSet,
77
+ members: member.fieldSet.members.filter((fieldsetMember) => {
78
+ return (
79
+ fieldsetMember.kind === 'field' &&
80
+ filterField(schemaType, fieldsetMember, activeLanguages)
81
+ )
82
+ }),
83
+ },
84
+ }
85
+ }
86
+ return member
87
+ })
88
+ }, [schemaType, membersProp, filterField, activeLanguages])
89
+
90
+ return <>{next({...restProps, members, schemaType})}</>
91
+ }
@@ -0,0 +1,91 @@
1
+ import {defaultFilterField, isLanguageFilterEnabled} from './filterField'
2
+ import {FieldMember, ObjectSchemaType} from 'sanity'
3
+
4
+ describe('filterField', () => {
5
+ describe('isLanguageFilterEnabled', () => {
6
+ const docType: ObjectSchemaType = {
7
+ name: 'some-doc',
8
+ jsonType: 'object',
9
+ fields: [],
10
+ type: {
11
+ name: 'document',
12
+ jsonType: 'object',
13
+ fields: [],
14
+ },
15
+ }
16
+ it('should be enabled when documentTypes is missing', () => {
17
+ const enabled = isLanguageFilterEnabled(docType, {supportedLanguages: []})
18
+ expect(enabled).toBeTruthy()
19
+ })
20
+
21
+ it('should be disabled when documentTypes is missing and options.languageFilter: false', () => {
22
+ const enabled = isLanguageFilterEnabled(
23
+ {...docType, options: {languageFilter: false}},
24
+ {supportedLanguages: []}
25
+ )
26
+ expect(enabled).toBeFalsy()
27
+ })
28
+
29
+ it('should be enabled when documentTypes is contains doc-type name', () => {
30
+ const enabled = isLanguageFilterEnabled(
31
+ {...docType, options: {languageFilter: false}},
32
+ {supportedLanguages: [], documentTypes: [docType.name]}
33
+ )
34
+ expect(enabled).toBeTruthy()
35
+ })
36
+
37
+ it('should be enabled when documentTypes does not contain doc-type name, but options.languageFilter: true', () => {
38
+ const enabled = isLanguageFilterEnabled(
39
+ {...docType, options: {languageFilter: true}},
40
+ {supportedLanguages: [], documentTypes: []}
41
+ )
42
+ expect(enabled).toBeTruthy()
43
+ })
44
+ })
45
+
46
+ describe('defaultFilterField', () => {
47
+ const localePrefixedObject: ObjectSchemaType = {
48
+ name: 'locale_parent',
49
+ jsonType: 'object',
50
+ fields: [],
51
+ }
52
+ const member: FieldMember = {
53
+ name: 'nb',
54
+ key: 'nb',
55
+ collapsed: undefined,
56
+ collapsible: undefined,
57
+ kind: 'field',
58
+ open: true,
59
+ index: 0,
60
+ field: {
61
+ schemaType: {name: 'string', jsonType: 'string'},
62
+ level: 1,
63
+ id: 'nb',
64
+ path: [],
65
+ validation: [],
66
+ presence: [],
67
+ changed: false,
68
+ value: undefined,
69
+ },
70
+ }
71
+
72
+ it('should filter -> true for nb field inside local-prefixed object', () => {
73
+ const result = defaultFilterField(localePrefixedObject, member, ['nb'])
74
+ expect(result).toBeTruthy()
75
+ })
76
+
77
+ it('should filter -> false for unselected field inside local-prefixed object', () => {
78
+ const result = defaultFilterField(localePrefixedObject, member, ['other'])
79
+ expect(result).toBeFalsy()
80
+ })
81
+
82
+ it('should filter -> true for nb field inside non-prefixed object', () => {
83
+ const result = defaultFilterField(
84
+ {...localePrefixedObject, name: 'not-start-with-locale-field'},
85
+ member,
86
+ ['nb']
87
+ )
88
+ expect(result).toBeTruthy()
89
+ })
90
+ })
91
+ })
@@ -0,0 +1,34 @@
1
+ import type {SchemaType} from 'sanity'
2
+ import {FilterFieldFunction, LanguageFilterConfig, LanguageFilterSchema} from './types'
3
+
4
+ export const defaultFilterField: FilterFieldFunction = (
5
+ enclosingType,
6
+ field,
7
+ selectedLanguageIds
8
+ ) => !enclosingType.name.startsWith('locale') || selectedLanguageIds.includes(field.name)
9
+
10
+ export function isLanguageFilterEnabled(
11
+ schemaType: SchemaType | undefined,
12
+ options: LanguageFilterConfig
13
+ ): boolean {
14
+ const schemaFilter =
15
+ isDocument(schemaType) && (schemaType as LanguageFilterSchema)?.options?.languageFilter
16
+ const defaultEnabled = !options.documentTypes
17
+
18
+ return !!(
19
+ (defaultEnabled && schemaFilter !== false) ||
20
+ (!defaultEnabled && schemaFilter) ||
21
+ (schemaType && options.documentTypes?.includes(schemaType.name))
22
+ )
23
+ }
24
+
25
+ function isDocument(schemaType?: SchemaType) {
26
+ return schemaType?.jsonType === 'object' && getRootType(schemaType).name === 'document'
27
+ }
28
+
29
+ function getRootType(schema: SchemaType): SchemaType {
30
+ if (schema.type) {
31
+ return getRootType(schema.type)
32
+ }
33
+ return schema
34
+ }
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Plugin function
3
+ */
4
+ export {languageFilter} from './plugin'
5
+
6
+ export {defaultFilterField, isLanguageFilterEnabled} from './filterField'
7
+
8
+ export type {
9
+ LanguageFilterConfig,
10
+ LanguageFilterSchema,
11
+ LanguageFilterOptions,
12
+ FilterFieldFunction,
13
+ Language,
14
+ } from './types'
@@ -0,0 +1,32 @@
1
+ export type LanguageSubscription = (ids: string[]) => void
2
+ export type Unsubscribe = () => void
3
+ export type LanguageSubscribe = (subscription: LanguageSubscription) => Unsubscribe
4
+
5
+ export interface SelectedLanguageIdsBus {
6
+ onSelectedIdsChange: (ids: string[]) => void
7
+ subscribeSelectedIds: LanguageSubscribe
8
+ }
9
+
10
+ /**
11
+ * We need a way to communicate state changes between the pane menu and input components.
12
+ * LanguageFilter button lives outside the input-render tree, so Context is out.
13
+ * This is a workaround for that.
14
+ */
15
+ export function createSelectedLanguageIdsBus(): SelectedLanguageIdsBus {
16
+ const subs: LanguageSubscription[] = []
17
+
18
+ const onSelectedIdsChange = (ids: string[]) => {
19
+ subs.forEach((s) => s(ids))
20
+ }
21
+ const subscribeSelectedIds = (subscription: LanguageSubscription) => {
22
+ subs.push(subscription)
23
+ return () => {
24
+ subs.splice(subs.indexOf(subscription), 1)
25
+ }
26
+ }
27
+
28
+ return {
29
+ onSelectedIdsChange,
30
+ subscribeSelectedIds,
31
+ }
32
+ }
package/src/plugin.tsx ADDED
@@ -0,0 +1,86 @@
1
+ import React from 'react'
2
+ import {_DocumentLanguageFilterComponent, createPlugin, ObjectInputProps} from 'sanity'
3
+ import {LanguageFilterObjectInput} from './LanguageFilterObjectInput'
4
+ import {LanguageFilterMenuButton} from './LanguageFilterMenuButton'
5
+ import {LanguageFilterConfig} from './types'
6
+ import {isLanguageFilterEnabled} from './filterField'
7
+ import {LanguageFilterProvider} from './LanguageFilterContext'
8
+ import {createSelectedLanguageIdsBus} from './languageSubscription'
9
+
10
+ /**
11
+ * ## Usage in sanity.config.ts (or .js)
12
+ *
13
+ * ```
14
+ * import {createConfig} from 'sanity'
15
+ * import {languageFilter} from '@sanity/language-filter'
16
+ *
17
+ * export const createConfig({
18
+ * /...
19
+ * plugins: [
20
+ * languageFilter({
21
+ * supportedLanguages: [
22
+ * {id: 'nb', title: 'Norwegian (Bokmål)'},
23
+ * {id: 'nn', title: 'Norwegian (Nynorsk)'},
24
+ * {id: 'en', title: 'English'},
25
+ * {id: 'es', title: 'Spanish'},
26
+ * {id: 'arb', title: 'Arabic'},
27
+ * {id: 'pt', title: 'Portuguese'},
28
+ * //...
29
+ * ],
30
+ * // Select Norwegian (Bokmål) by default
31
+ * defaultLanguages: ['nb'],
32
+ * // Only show language filter for document type `page` (schemaType.name)
33
+ * // Can also enable via document-options: options.languageFilter: true
34
+ * documentTypes: ['page'],
35
+ * // default filter function shown
36
+ * filterField: (enclosingType, field, selectedLanguageIds) =>
37
+ * !enclosingType.name.startsWith('locale') || selectedLanguageIds.includes(field.name),
38
+ * })
39
+ * ]
40
+ * })
41
+ * ```
42
+ */
43
+ export const languageFilter = createPlugin<LanguageFilterConfig>((options) => {
44
+ const {onSelectedIdsChange, subscribeSelectedIds} = createSelectedLanguageIdsBus()
45
+
46
+ const RenderLanguageFilter: _DocumentLanguageFilterComponent = () => {
47
+ return <LanguageFilterMenuButton options={options} onSelectedIdsChange={onSelectedIdsChange} />
48
+ }
49
+
50
+ return {
51
+ name: '@sanity/language-filter',
52
+ document: {
53
+ unstable_languageFilter: (prev, {schemaType, schema}) => {
54
+ if (isLanguageFilterEnabled(schema.get(schemaType), options)) {
55
+ return [...prev, RenderLanguageFilter]
56
+ }
57
+ return prev
58
+ },
59
+ },
60
+
61
+ form: {
62
+ renderInput(props, next) {
63
+ const enabled = isLanguageFilterEnabled(props.schemaType, options)
64
+ // will only be considered enabled for document, so this is only done once
65
+ if (enabled) {
66
+ return (
67
+ <LanguageFilterProvider enabled={enabled} options={options}>
68
+ {next(props)}
69
+ </LanguageFilterProvider>
70
+ )
71
+ }
72
+ if (props.schemaType.jsonType === 'object') {
73
+ return (
74
+ <LanguageFilterObjectInput
75
+ {...(props as ObjectInputProps)}
76
+ next={next}
77
+ subscribeSelectedIds={subscribeSelectedIds}
78
+ />
79
+ )
80
+ }
81
+
82
+ return undefined
83
+ },
84
+ },
85
+ }
86
+ })