@sanity/code-input 6.0.3 → 7.0.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.
Files changed (51) hide show
  1. package/README.md +1 -16
  2. package/assets/all-options.png +0 -0
  3. package/assets/basic-input.png +0 -0
  4. package/dist/_chunks-es/CodeMirrorProxy.js +510 -0
  5. package/dist/_chunks-es/CodeMirrorProxy.js.map +1 -0
  6. package/dist/_chunks-es/index.js +427 -0
  7. package/dist/_chunks-es/index.js.map +1 -0
  8. package/dist/index.d.ts +95 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/package.json +31 -86
  11. package/lib/_chunks-cjs/CodeMirrorProxy.cjs +0 -407
  12. package/lib/_chunks-cjs/CodeMirrorProxy.cjs.map +0 -1
  13. package/lib/_chunks-cjs/index.cjs +0 -433
  14. package/lib/_chunks-cjs/index.cjs.map +0 -1
  15. package/lib/_chunks-es/CodeMirrorProxy.js +0 -395
  16. package/lib/_chunks-es/CodeMirrorProxy.js.map +0 -1
  17. package/lib/_chunks-es/index.js +0 -437
  18. package/lib/_chunks-es/index.js.map +0 -1
  19. package/lib/index.cjs +0 -8
  20. package/lib/index.cjs.map +0 -1
  21. package/lib/index.d.cts +0 -121
  22. package/lib/index.d.ts +0 -121
  23. package/sanity.json +0 -8
  24. package/src/CodeInput.tsx +0 -181
  25. package/src/LanguageField.tsx +0 -41
  26. package/src/LanguageInput.tsx +0 -35
  27. package/src/PreviewCode.tsx +0 -71
  28. package/src/codemirror/CodeMirrorProxy.tsx +0 -159
  29. package/src/codemirror/CodeModeContext.tsx +0 -5
  30. package/src/codemirror/defaultCodeModes.ts +0 -109
  31. package/src/codemirror/extensions/backwardsCompatibleTone.ts +0 -19
  32. package/src/codemirror/extensions/highlightLineExtension.ts +0 -175
  33. package/src/codemirror/extensions/theme.ts +0 -65
  34. package/src/codemirror/extensions/useCodeMirrorTheme.ts +0 -64
  35. package/src/codemirror/extensions/useFontSize.ts +0 -24
  36. package/src/codemirror/useCodeMirror-client.test.tsx +0 -51
  37. package/src/codemirror/useCodeMirror-server.test.tsx +0 -18
  38. package/src/codemirror/useCodeMirror.tsx +0 -11
  39. package/src/codemirror/useLanguageMode.tsx +0 -60
  40. package/src/config.ts +0 -35
  41. package/src/getMedia.tsx +0 -93
  42. package/src/index.ts +0 -8
  43. package/src/plugin.tsx +0 -40
  44. package/src/sanity-ui.d.ts +0 -5
  45. package/src/schema.tsx +0 -86
  46. package/src/types.ts +0 -35
  47. package/src/ui/focusRingStyle.ts +0 -27
  48. package/src/useFieldMember.ts +0 -16
  49. package/v2-incompatible.js +0 -11
  50. /package/{lib → dist}/index.js +0 -0
  51. /package/{lib → dist}/index.js.map +0 -0
package/lib/index.d.ts DELETED
@@ -1,121 +0,0 @@
1
- import type {Extension} from '@codemirror/state'
2
- import {JSX} from 'react'
3
- import {ObjectDefinition} from 'sanity'
4
- import {ObjectInputProps} from 'sanity'
5
- import type {ObjectSchemaType} from 'sanity'
6
- import {Plugin as Plugin_2} from 'sanity'
7
- import {PreviewConfig} from 'sanity'
8
- import type {PreviewProps} from 'sanity'
9
-
10
- /**
11
- * @public
12
- */
13
- export declare interface CodeDefinition
14
- extends Omit<ObjectDefinition, 'type' | 'fields' | 'options'> {
15
- type: typeof codeTypeName
16
- options?: CodeOptions
17
- }
18
-
19
- /** @public */
20
- export declare function CodeInput(props: CodeInputProps): React.JSX.Element
21
-
22
- /**
23
- * @public
24
- */
25
- export declare const codeInput: Plugin_2<void | CodeInputConfig>
26
-
27
- declare interface CodeInputConfig {
28
- codeModes?: CodeMode[]
29
- }
30
-
31
- export declare interface CodeInputLanguage {
32
- title: string
33
- value: string
34
- mode?: string
35
- }
36
-
37
- /**
38
- * @public
39
- */
40
- export declare interface CodeInputProps extends ObjectInputProps<CodeInputValue, CodeSchemaType> {}
41
-
42
- /**
43
- * @public
44
- */
45
- export declare interface CodeInputValue {
46
- _type?: 'code'
47
- code?: string
48
- filename?: string
49
- language?: string
50
- highlightedLines?: number[]
51
- }
52
-
53
- declare interface CodeMode {
54
- name: string
55
- loader: ModeLoader
56
- }
57
-
58
- /**
59
- * @public
60
- */
61
- export declare interface CodeOptions {
62
- theme?: string
63
- darkTheme?: string
64
- languageAlternatives?: CodeInputLanguage[]
65
- language?: string
66
- withFilename?: boolean
67
- }
68
-
69
- /**
70
- * @public
71
- */
72
- export declare const codeSchema: {
73
- type: 'object'
74
- name: 'code'
75
- } & Omit<ObjectDefinition, 'preview'> & {
76
- preview?:
77
- | PreviewConfig<
78
- {
79
- language: string
80
- code: string
81
- filename: string
82
- highlightedLines: string
83
- },
84
- Record<'language' | 'code' | 'filename' | 'highlightedLines', any>
85
- >
86
- | undefined
87
- }
88
-
89
- /**
90
- * @public
91
- */
92
- export declare interface CodeSchemaType extends Omit<ObjectSchemaType, 'options'> {
93
- options?: CodeOptions
94
- }
95
-
96
- /**
97
- * @public
98
- */
99
- export declare const codeTypeName: 'code'
100
-
101
- declare type ModeLoader = () => Promise<Extension | undefined> | Extension | undefined
102
-
103
- /**
104
- * @public
105
- */
106
- export declare function PreviewCode(props: PreviewCodeProps): JSX.Element
107
-
108
- /**
109
- * @public
110
- */
111
- export declare interface PreviewCodeProps extends PreviewProps {
112
- selection?: CodeInputValue
113
- }
114
-
115
- export {}
116
-
117
- declare module 'sanity' {
118
- interface IntrinsicDefinitions {
119
- code: CodeDefinition
120
- }
121
- }
package/sanity.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "parts": [
3
- {
4
- "implements": "part:@sanity/base/sanity-root",
5
- "path": "./v2-incompatible.js"
6
- }
7
- ]
8
- }
package/src/CodeInput.tsx DELETED
@@ -1,181 +0,0 @@
1
- import {Box, Card, Stack, Text} from '@sanity/ui'
2
- import {Suspense, useCallback} from 'react'
3
- import {
4
- MemberField,
5
- type ObjectInputProps,
6
- type RenderInputCallback,
7
- set,
8
- setIfMissing,
9
- unset,
10
- } from 'sanity'
11
- import {css, styled} from 'styled-components'
12
-
13
- import {CodeMirrorProxy, useMounted} from './codemirror/useCodeMirror'
14
- import {useLanguageMode} from './codemirror/useLanguageMode'
15
- import {PATH_CODE} from './config'
16
- import {LanguageField} from './LanguageField'
17
- import type {CodeInputValue, CodeSchemaType} from './types'
18
- import {focusRingBorderStyle, focusRingStyle} from './ui/focusRingStyle'
19
- import {useFieldMember} from './useFieldMember'
20
-
21
- export type {CodeInputLanguage, CodeInputValue} from './types'
22
-
23
- /**
24
- * @public
25
- */
26
- export interface CodeInputProps extends ObjectInputProps<CodeInputValue, CodeSchemaType> {}
27
-
28
- const EditorContainer = styled(Card)(({theme}) => {
29
- const {focusRing, input} = theme.sanity
30
- const base = theme.sanity.color.base
31
- const color = theme.sanity.color.input
32
- const border = {
33
- color: color.default.enabled.border,
34
- width: input.border.width,
35
- }
36
-
37
- return css`
38
- --input-box-shadow: ${focusRingBorderStyle(border)};
39
-
40
- box-shadow: var(--input-box-shadow);
41
- height: 250px;
42
- min-height: 80px;
43
- overflow-y: auto;
44
- position: relative;
45
- resize: vertical;
46
- z-index: 0;
47
-
48
- & > .cm-theme {
49
- height: 100%;
50
- }
51
-
52
- &:focus-within {
53
- --input-box-shadow: ${focusRingStyle({
54
- base,
55
- border,
56
- focusRing,
57
- })};
58
- }
59
- `
60
- })
61
-
62
- /** @public */
63
- export function CodeInput(props: CodeInputProps): React.JSX.Element {
64
- const {
65
- members,
66
- elementProps,
67
- onChange,
68
- readOnly,
69
- renderField,
70
- renderInput,
71
- renderItem,
72
- renderPreview,
73
- schemaType: type,
74
- value,
75
- onPathFocus,
76
- } = props
77
-
78
- const languageFieldMember = useFieldMember(members, 'language')
79
- const filenameMember = useFieldMember(members, 'filename')
80
- const codeFieldMember = useFieldMember(members, 'code')
81
-
82
- const handleCodeFocus = useCallback(() => {
83
- onPathFocus(PATH_CODE)
84
- }, [onPathFocus])
85
-
86
- const onHighlightChange = useCallback(
87
- (lines: number[]) => onChange(set(lines, ['highlightedLines'])),
88
- [onChange],
89
- )
90
-
91
- const handleCodeChange = useCallback(
92
- (code: string) => {
93
- const path = PATH_CODE
94
- const fixedLanguage = type.options?.language
95
-
96
- onChange([
97
- setIfMissing({_type: type.name, language: fixedLanguage}),
98
- code ? set(code, path) : unset(path),
99
- ])
100
- },
101
- [onChange, type],
102
- )
103
- const {languages, language, languageMode} = useLanguageMode(props.schemaType, props.value)
104
-
105
- const mounted = useMounted()
106
-
107
- const renderCodeInput: RenderInputCallback = useCallback(
108
- (inputProps) => {
109
- return (
110
- <EditorContainer border overflow="hidden" radius={1} sizing="border" readOnly={readOnly}>
111
- {mounted && (
112
- <Suspense
113
- fallback={
114
- <Box padding={3}>
115
- <Text>Loading code editor...</Text>
116
- </Box>
117
- }
118
- >
119
- <CodeMirrorProxy
120
- languageMode={languageMode}
121
- onChange={handleCodeChange}
122
- value={inputProps.value as string}
123
- highlightLines={value?.highlightedLines}
124
- onHighlightChange={onHighlightChange}
125
- readOnly={readOnly}
126
- onFocus={handleCodeFocus}
127
- onBlur={elementProps.onBlur}
128
- />
129
- </Suspense>
130
- )}
131
- </EditorContainer>
132
- )
133
- },
134
- [
135
- readOnly,
136
- mounted,
137
- languageMode,
138
- handleCodeChange,
139
- value?.highlightedLines,
140
- onHighlightChange,
141
- handleCodeFocus,
142
- elementProps.onBlur,
143
- ],
144
- )
145
-
146
- return (
147
- <Stack space={4}>
148
- {languageFieldMember && (
149
- <LanguageField
150
- member={languageFieldMember}
151
- language={language}
152
- languages={languages}
153
- renderField={renderField}
154
- renderItem={renderItem}
155
- renderInput={renderInput}
156
- renderPreview={renderPreview}
157
- />
158
- )}
159
-
160
- {type.options?.withFilename && filenameMember && (
161
- <MemberField
162
- member={filenameMember}
163
- renderItem={renderItem}
164
- renderField={renderField}
165
- renderInput={renderInput}
166
- renderPreview={renderPreview}
167
- />
168
- )}
169
-
170
- {codeFieldMember && (
171
- <MemberField
172
- member={codeFieldMember}
173
- renderInput={renderCodeInput}
174
- renderItem={renderItem}
175
- renderField={renderField}
176
- renderPreview={renderPreview}
177
- />
178
- )}
179
- </Stack>
180
- )
181
- }
@@ -1,41 +0,0 @@
1
- import {useCallback} from 'react'
2
- import {
3
- type FieldMember,
4
- type InputProps,
5
- MemberField,
6
- type MemberFieldProps,
7
- type PrimitiveInputElementProps,
8
- } from 'sanity'
9
-
10
- import {LanguageInput} from './LanguageInput'
11
- import type {CodeInputLanguage} from './types'
12
-
13
- export function LanguageField(
14
- props: MemberFieldProps & {member: FieldMember; language: string; languages: CodeInputLanguage[]},
15
- ) {
16
- const {member, languages, language, renderItem, renderField, renderPreview} = props
17
-
18
- const renderInput = useCallback(
19
- ({elementProps, onChange}: Omit<InputProps, 'renderDefault'>) => {
20
- return (
21
- <LanguageInput
22
- onChange={onChange}
23
- elementProps={elementProps as PrimitiveInputElementProps}
24
- language={language}
25
- languages={languages}
26
- />
27
- )
28
- },
29
- [languages, language],
30
- )
31
-
32
- return (
33
- <MemberField
34
- member={member}
35
- renderItem={renderItem}
36
- renderField={renderField}
37
- renderInput={renderInput}
38
- renderPreview={renderPreview}
39
- />
40
- )
41
- }
@@ -1,35 +0,0 @@
1
- import {Select} from '@sanity/ui'
2
- import {type ChangeEvent, useCallback} from 'react'
3
- import {set, type StringInputProps, unset} from 'sanity'
4
-
5
- import type {CodeInputLanguage} from './types'
6
-
7
- export interface LanguageInputProps {
8
- language: string
9
- languages: CodeInputLanguage[]
10
- onChange: StringInputProps['onChange']
11
- elementProps: StringInputProps['elementProps']
12
- }
13
-
14
- /** @internal */
15
- export function LanguageInput(props: LanguageInputProps) {
16
- const {language, languages, onChange, elementProps} = props
17
-
18
- const handleChange = useCallback(
19
- (e: ChangeEvent<HTMLSelectElement>) => {
20
- const newValue = e.currentTarget.value
21
- onChange(newValue ? set(newValue) : unset())
22
- },
23
- [onChange],
24
- )
25
-
26
- return (
27
- <Select {...elementProps} value={language} onChange={handleChange}>
28
- {languages.map((lang: {title: string; value: string}) => (
29
- <option key={lang.value} value={lang.value}>
30
- {lang.title}
31
- </option>
32
- ))}
33
- </Select>
34
- )
35
- }
@@ -1,71 +0,0 @@
1
- import {Box, Card, Flex, Label, Text} from '@sanity/ui'
2
- import {Suspense} from 'react'
3
- import type {PreviewProps} from 'sanity'
4
- import {styled} from 'styled-components'
5
-
6
- import {CodeMirrorProxy, useMounted} from './codemirror/useCodeMirror'
7
- import {useLanguageMode} from './codemirror/useLanguageMode'
8
- import type {CodeInputValue, CodeSchemaType} from './types'
9
-
10
- const PreviewContainer = styled(Box)`
11
- position: relative;
12
- `
13
-
14
- /**
15
- * @public
16
- */
17
- export interface PreviewCodeProps extends PreviewProps {
18
- selection?: CodeInputValue
19
- }
20
-
21
- /**
22
- * @public
23
- */
24
- export function PreviewCode(props: PreviewCodeProps) {
25
- const {selection, schemaType: type} = props
26
- const {languageMode} = useLanguageMode(type as CodeSchemaType, props.selection)
27
-
28
- const mounted = useMounted()
29
- return (
30
- <PreviewContainer>
31
- <Card padding={4}>
32
- {selection?.filename || selection?.language ? (
33
- <Card
34
- paddingBottom={4}
35
- marginBottom={selection.code ? 4 : 0}
36
- borderBottom={!!selection.code}
37
- >
38
- <Flex align="center" justify="flex-end">
39
- {selection?.filename ? (
40
- <Box flex={1}>
41
- <Text>
42
- <code>{selection.filename}</code>
43
- </Text>
44
- </Box>
45
- ) : null}
46
- {selection?.language ? <Label muted>{selection.language}</Label> : null}
47
- </Flex>
48
- </Card>
49
- ) : null}
50
- {mounted && (
51
- <Suspense fallback={<Card padding={2}>Loading code preview...</Card>}>
52
- <CodeMirrorProxy
53
- readOnly
54
- editable={false}
55
- value={selection?.code || ''}
56
- highlightLines={selection?.highlightedLines || []}
57
- basicSetup={{
58
- lineNumbers: false,
59
- foldGutter: false,
60
- highlightSelectionMatches: false,
61
- highlightActiveLineGutter: false,
62
- highlightActiveLine: false,
63
- }}
64
- languageMode={languageMode}
65
- />
66
- </Suspense>
67
- )}
68
- </Card>
69
- </PreviewContainer>
70
- )
71
- }
@@ -1,159 +0,0 @@
1
- import type {Extension} from '@codemirror/state'
2
- import {EditorView} from '@codemirror/view'
3
- import {useRootTheme} from '@sanity/ui'
4
- import CodeMirror, {type ReactCodeMirrorProps, type ReactCodeMirrorRef} from '@uiw/react-codemirror'
5
- import {forwardRef, useCallback, useContext, useEffect, useMemo, useState} from 'react'
6
-
7
- import {CodeInputConfigContext} from './CodeModeContext'
8
- import {defaultCodeModes} from './defaultCodeModes'
9
- import {
10
- highlightLine,
11
- highlightState,
12
- setHighlightedLines,
13
- } from './extensions/highlightLineExtension'
14
- import {useThemeExtension} from './extensions/theme'
15
- import {useCodeMirrorTheme} from './extensions/useCodeMirrorTheme'
16
- import {useFontSizeExtension} from './extensions/useFontSize'
17
-
18
- export interface CodeMirrorProps extends ReactCodeMirrorProps {
19
- highlightLines?: number[]
20
- languageMode?: string
21
- onHighlightChange?: (lines: number[]) => void
22
- }
23
-
24
- /**
25
- * CodeMirrorProxy is a wrapper component around CodeMirror that we lazy load to reduce initial bundle size.
26
- *
27
- * It is also responsible for integrating any CodeMirror extensions.
28
- */
29
- const CodeMirrorProxy = forwardRef<ReactCodeMirrorRef, CodeMirrorProps>(
30
- function CodeMirrorProxy(props, ref) {
31
- const {
32
- basicSetup: basicSetupProp,
33
- highlightLines,
34
- languageMode,
35
- onHighlightChange,
36
- readOnly,
37
- value,
38
- ...codeMirrorProps
39
- } = props
40
-
41
- const themeCtx = useRootTheme()
42
- const codeMirrorTheme = useCodeMirrorTheme()
43
- const [editorView, setEditorView] = useState<EditorView | undefined>(undefined)
44
-
45
- // Resolve extensions
46
- const themeExtension = useThemeExtension()
47
- const fontSizeExtension = useFontSizeExtension({fontSize: 1})
48
- const languageExtension = useLanguageExtension(languageMode)
49
- const highlightLineExtension = useMemo(
50
- () =>
51
- highlightLine({
52
- onHighlightChange,
53
- readOnly,
54
- theme: themeCtx,
55
- }),
56
- [onHighlightChange, readOnly, themeCtx],
57
- )
58
-
59
- const extensions = useMemo(() => {
60
- const baseExtensions = [
61
- themeExtension,
62
- fontSizeExtension,
63
- highlightLineExtension,
64
- EditorView.lineWrapping,
65
- ]
66
- if (languageExtension) {
67
- return [...baseExtensions, languageExtension]
68
- }
69
- return baseExtensions
70
- }, [fontSizeExtension, highlightLineExtension, languageExtension, themeExtension])
71
-
72
- useEffect(() => {
73
- if (editorView) {
74
- setHighlightedLines(editorView, highlightLines ?? [])
75
- }
76
- }, [editorView, highlightLines, value])
77
-
78
- const initialState = useMemo(() => {
79
- return {
80
- json: {
81
- doc: value ?? '',
82
- selection: {
83
- main: 0,
84
- ranges: [{anchor: 0, head: 0}],
85
- },
86
- highlight: highlightLines ?? [],
87
- },
88
- fields: highlightState,
89
- }
90
- // only need to calculate this on initial render
91
- // eslint-disable-next-line react-hooks/exhaustive-deps
92
- }, [])
93
-
94
- const handleCreateEditor = useCallback((view: EditorView) => {
95
- setEditorView(view)
96
- }, [])
97
-
98
- const basicSetup = useMemo(
99
- () =>
100
- basicSetupProp ?? {
101
- highlightActiveLine: false,
102
- },
103
- [basicSetupProp],
104
- )
105
-
106
- return (
107
- <CodeMirror
108
- {...codeMirrorProps}
109
- value={value}
110
- ref={ref}
111
- extensions={extensions}
112
- theme={codeMirrorTheme}
113
- onCreateEditor={handleCreateEditor}
114
- initialState={initialState}
115
- basicSetup={basicSetup}
116
- />
117
- )
118
- },
119
- )
120
-
121
- function useLanguageExtension(mode?: string) {
122
- const codeConfig = useContext(CodeInputConfigContext)
123
-
124
- const [languageExtension, setLanguageExtension] = useState<Extension | undefined>()
125
-
126
- useEffect(() => {
127
- const customModes = codeConfig?.codeModes ?? []
128
- const modes = [...customModes, ...defaultCodeModes]
129
-
130
- const codeMode = modes.find((m) => m.name === mode)
131
- if (!codeMode?.loader) {
132
- // eslint-disable-next-line no-console
133
- console.warn(
134
- `Found no codeMode for language mode ${mode}, syntax highlighting will be disabled.`,
135
- )
136
- }
137
- let active = true
138
- Promise.resolve(codeMode?.loader())
139
- .then((extension) => {
140
- if (active) {
141
- setLanguageExtension(extension)
142
- }
143
- })
144
- .catch((e) => {
145
- // eslint-disable-next-line no-console
146
- console.error(`Failed to load language mode ${mode}`, e)
147
- if (active) {
148
- setLanguageExtension(undefined)
149
- }
150
- })
151
- return () => {
152
- active = false
153
- }
154
- }, [mode, codeConfig])
155
-
156
- return languageExtension
157
- }
158
-
159
- export default CodeMirrorProxy
@@ -1,5 +0,0 @@
1
- import {createContext} from 'react'
2
-
3
- import type {CodeInputConfig} from '../plugin'
4
-
5
- export const CodeInputConfigContext = createContext<CodeInputConfig | undefined>(undefined)