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

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,178 +0,0 @@
1
- import React, {useState, useCallback} from 'react'
2
- import {Button, Checkbox, Flex, Box, Text, Stack, Popover, useClickOutside} from '@sanity/ui'
3
- import {ChevronDownIcon} from '@sanity/icons'
4
-
5
- const ACTION_LABEL = 'Filter languages'
6
- interface LanguageOption {
7
- title: string
8
- id: string
9
- }
10
-
11
- interface Props {
12
- languages: LanguageOption[]
13
- currentDocumentType?: string
14
- defaultLanguages?: string[]
15
- documentTypes?: string[]
16
- selected: string[]
17
- onChange: (ids: string[]) => void
18
- }
19
-
20
- const STYLES_TOGGLE = {flex: 1}
21
- const STYLES_CHECKBOX = {display: 'block'}
22
-
23
- const SelectLanguage = ({
24
- currentDocumentType,
25
- selected,
26
- languages,
27
- defaultLanguages,
28
- documentTypes,
29
- onChange,
30
- }: Props) => {
31
- const [triggerRef, setTriggerRef] = React.useState<HTMLButtonElement | null>(null)
32
- const [popoverRef, setPopoverRef] = React.useState<HTMLElement | null>(null)
33
- const [isOpen, setIsOpen] = useState(false)
34
- const allIsSelected = languages.length === selected.length
35
-
36
- const handleKeyUp = useCallback((e) => {
37
- if (e.key === 'Escape') {
38
- handleClose()
39
- }
40
- }, [])
41
-
42
- const handleOpen = () => {
43
- setIsOpen((prev) => !prev)
44
- }
45
-
46
- const handleClose = () => {
47
- setIsOpen(false)
48
- }
49
-
50
- const selectLang = (langId: string) => {
51
- onChange(selected.concat(langId))
52
- }
53
-
54
- const unselectLang = (langId: string) => {
55
- onChange(selected.filter((id) => id !== langId))
56
- }
57
-
58
- const isDefaultLang = (langId: string) => {
59
- return defaultLanguages && defaultLanguages.includes(langId)
60
- }
61
-
62
- const isValidDocumentType = () => {
63
- return documentTypes && currentDocumentType ? documentTypes.includes(currentDocumentType) : true
64
- }
65
-
66
- const handleSelectAll = () => {
67
- onChange(languages.map((language) => language.id))
68
- }
69
- const handleSelectNone = () => {
70
- onChange([])
71
- }
72
-
73
- const handleLangCheckboxChange = (event: React.FormEvent<HTMLInputElement>) => {
74
- const id = event.currentTarget.getAttribute('data-lang-id')
75
- const checked = event.currentTarget.checked
76
-
77
- if (!id) {
78
- return
79
- }
80
-
81
- if (checked) {
82
- selectLang(id)
83
- } else {
84
- unselectLang(id)
85
- }
86
- }
87
-
88
- useClickOutside(() => {
89
- handleClose()
90
- }, [popoverRef, triggerRef])
91
-
92
- if (!isValidDocumentType()) {
93
- return <></>
94
- }
95
-
96
- const content = (
97
- <Box overflow="auto" sizing="border" onKeyUp={handleKeyUp}>
98
- <Flex padding={2}>
99
- <Button
100
- type="button"
101
- mode="ghost"
102
- tone="default"
103
- onClick={allIsSelected ? handleSelectNone : handleSelectAll}
104
- paddingX={3}
105
- paddingY={2}
106
- autoFocus
107
- style={STYLES_TOGGLE}
108
- >
109
- Select {allIsSelected ? 'none' : 'all'}
110
- </Button>
111
- </Flex>
112
- <Box padding={3} paddingX={2}>
113
- <Stack as="ul" space={3}>
114
- {languages.map((lang) => {
115
- const label = lang.title + (isDefaultLang(lang.id) ? ' (Default)' : '')
116
- const languageId = `language-${lang.id}`
117
- return (
118
- <Flex as="li" align="center" key={lang.id}>
119
- <Checkbox
120
- id={languageId}
121
- style={STYLES_CHECKBOX}
122
- onChange={handleLangCheckboxChange}
123
- data-lang-id={lang.id}
124
- checked={selected.includes(lang.id)}
125
- disabled={isDefaultLang(lang.id)}
126
- />
127
- <Box flex={1} paddingLeft={3}>
128
- <Text>
129
- <label htmlFor={languageId} style={STYLES_CHECKBOX}>
130
- {label}
131
- </label>
132
- </Text>
133
- </Box>
134
- </Flex>
135
- )
136
- })}
137
- </Stack>
138
- </Box>
139
- </Box>
140
- )
141
-
142
- return (
143
- <>
144
- <Button
145
- fontSize={1}
146
- iconRight={ChevronDownIcon}
147
- mode="bleed"
148
- ref={setTriggerRef}
149
- onClick={handleOpen}
150
- padding={2}
151
- title={
152
- allIsSelected
153
- ? 'Filter language fields'
154
- : 'Displaying fields only for the selected languages'
155
- }
156
- selected={isOpen}
157
- text={
158
- <>
159
- {ACTION_LABEL} ({`${selected.length}/${languages.length}`})
160
- </>
161
- }
162
- />
163
- <Popover
164
- content={content}
165
- open={isOpen}
166
- placement="bottom"
167
- ref={setPopoverRef}
168
- referenceElement={triggerRef}
169
- tone="default"
170
- constrainSize
171
- autoFocus
172
- portal
173
- />
174
- </>
175
- )
176
- }
177
-
178
- export default SelectLanguage
@@ -1,70 +0,0 @@
1
- // @todo: remove the following line when part imports has been removed from this file
2
- ///<reference types="@sanity/types/parts" />
3
-
4
- import React, {useRef, useEffect, useState, useMemo} from 'react'
5
- import config from 'part:@sanity/language-filter/config'
6
- import {SchemaType} from '@sanity/types'
7
- import {Subscription} from 'rxjs'
8
- import languageFilterImplementations from 'all:part:@sanity/desk-tool/language-select-component'
9
- import {selectedLanguages$, setLangs} from './datastore'
10
- import SelectLanguage from './SelectLanguage'
11
-
12
- interface Props {
13
- schemaType?: SchemaType
14
- }
15
-
16
- const SelectLanguageProvider = ({schemaType}: Props) => {
17
- const subscriptionRef$ = useRef<Subscription | null>(null)
18
- const [selected, setSelected] = useState<string[]>([])
19
- const [currentDocumentType, setCurrentDocumentType] = useState<string | undefined>()
20
- const shouldShow = useMemo(() => {
21
- const {documentTypes} = config
22
- return !!(documentTypes && schemaType?.name && documentTypes.includes(schemaType.name))
23
- }, [schemaType])
24
- const FallbackImplementation = useMemo(() => {
25
- if (languageFilterImplementations && Array.isArray(languageFilterImplementations)) {
26
- return (
27
- languageFilterImplementations?.filter(
28
- (component) => SelectLanguageProvider !== component
29
- )?.[0] ?? null
30
- )
31
- }
32
- return null
33
- }, [])
34
-
35
- useEffect(() => {
36
- setCurrentDocumentType(schemaType?.name)
37
- }, [schemaType])
38
-
39
- useEffect(() => {
40
- subscriptionRef$.current = selectedLanguages$.subscribe((selectedLangs: string[]) => {
41
- setSelected(selectedLangs)
42
- })
43
- return () => {
44
- if (subscriptionRef$.current) {
45
- subscriptionRef$.current.unsubscribe()
46
- }
47
- }
48
- }, [])
49
-
50
- if (shouldShow) {
51
- return (
52
- <SelectLanguage
53
- languages={config.supportedLanguages}
54
- defaultLanguages={config.defaultLanguages}
55
- documentTypes={config.documentTypes}
56
- currentDocumentType={currentDocumentType}
57
- selected={selected}
58
- onChange={setLangs}
59
- />
60
- )
61
- }
62
-
63
- if (FallbackImplementation) {
64
- return <FallbackImplementation schemaType={schemaType as any} />
65
- }
66
-
67
- return null
68
- }
69
-
70
- export default SelectLanguageProvider
package/src/datastore.ts DELETED
@@ -1,70 +0,0 @@
1
- // @todo: remove the following line when part imports has been removed from this file
2
- ///<reference types="@sanity/types/parts" />
3
-
4
- import {Observable, Subject} from 'rxjs'
5
- import {map, publishReplay, refCount, startWith, tap} from 'rxjs/operators'
6
- import config from 'part:@sanity/language-filter/config'
7
- import {intersection, union} from 'lodash'
8
- import {ObjectField, SchemaType} from '@sanity/types'
9
-
10
- export type SelectedLanguages = string[]
11
- interface SupportedLanguage {
12
- id: string
13
- title: string
14
- }
15
-
16
- const onSelect$ = new Subject<SelectedLanguages>()
17
-
18
- const id = (v: any) => v
19
-
20
- export const setLangs = (languages: SelectedLanguages) => onSelect$.next(languages)
21
-
22
- const persistOn = (key: string, defaultValue: string[]) => (input$: Observable<string[]>) => {
23
- let persisted
24
- try {
25
- const persistedValue = window.localStorage.getItem(key)
26
- if (persistedValue) {
27
- persisted = JSON.parse(persistedValue)
28
- }
29
- } catch (err) {} // eslint-disable-line no-empty
30
-
31
- return input$.pipe(
32
- startWith(persisted || defaultValue),
33
- tap((value) => {
34
- window.localStorage.setItem(key, JSON.stringify(value))
35
- })
36
- )
37
- }
38
-
39
- const SUPPORTED_LANG_IDS = config.supportedLanguages.map((lang: SupportedLanguage) => lang.id)
40
-
41
- export const selectedLanguages$ = onSelect$.pipe(
42
- persistOn(
43
- '@sanity/plugin/language-filter/selected-languages',
44
- config.defaultLanguages || SUPPORTED_LANG_IDS
45
- ),
46
- // constrain persisted/selected languages to the ones currently supported
47
- map((selectedLangs: SelectedLanguages) => intersection(selectedLangs, SUPPORTED_LANG_IDS)),
48
- // make sure default languages always gets selected
49
- Array.isArray(config.defaultLanguages)
50
- ? map((selectedLangs) => union(selectedLangs, config.defaultLanguages || []))
51
- : id,
52
- publishReplay(1),
53
- refCount()
54
- )
55
-
56
- const defaultFilterField = (
57
- enclosingType: SchemaType,
58
- field: ObjectField,
59
- selectedLanguages: string[]
60
- ) => !enclosingType.name.startsWith('locale') || selectedLanguages.includes(field.name)
61
-
62
- const filterField = config.filterField || defaultFilterField
63
-
64
- export const filterFn$ = selectedLanguages$.pipe(
65
- map((langs) => {
66
- return (enclosingType: SchemaType, field: ObjectField) => {
67
- return filterField(enclosingType, field, langs)
68
- }
69
- })
70
- )
@@ -1 +0,0 @@
1
- export {filterFn$ as default} from './datastore'
package/tsconfig.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig",
3
- "include": ["src"],
4
- "compilerOptions": {
5
- "composite": true,
6
- "rootDir": "./src",
7
- "outDir": "./dist/dts",
8
- "jsx": "react"
9
- },
10
- "references": [
11
- {"path": "../types"}
12
- ]
13
- }