-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathjson.tsx
120 lines (109 loc) · 3.18 KB
/
json.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import React, { Suspense, useRef, useState } from 'react';
import { SchemaFieldJson, WidgetProps } from '@stac-manager/data-core';
import {
CircularProgress,
Flex,
FormControl,
FormLabel
} from '@chakra-ui/react';
import { FastField, FastFieldProps } from 'formik';
import {
CollecticonArrowSemiSpinCcw,
CollecticonArrowSemiSpinCw,
CollecticonWrench,
CollecticonTextBlock
} from '@devseed-ui/collecticons-chakra';
import type JSONEditor from 'jsoneditor';
import { FieldIconBtn, FieldLabel } from '../components/elements';
import { CollecticonIndent } from '../components/icons/indent';
const JsonEditor = React.lazy(() => import('../components/json-jsoneditor'));
// Extend to have access to internal methods provided by the textmode.
interface JSONEditorCodeMode extends JSONEditor {
compact: () => void;
format: () => void;
repair: () => void;
_onChange: () => void;
}
export function WidgetJSON(props: WidgetProps) {
const field = props.field as SchemaFieldJson;
const editorRef = useRef<JSONEditorCodeMode>(null);
const [isLoaded, setIsLoaded] = useState(false);
return (
<FormControl>
<Flex gap={4}>
{field.label && (
<FormLabel>
<FieldLabel size='xs'>{field.label}</FieldLabel>
</FormLabel>
)}
{isLoaded && <ControlBar editor={editorRef.current!} />}
</Flex>
<Suspense fallback={<Loading />}>
<FastField name={props.pointer}>
{({ field: { value }, form: { setFieldValue } }: FastFieldProps) => (
<JsonEditor
value={value}
onChange={(v) => setFieldValue(props.pointer, v)}
editorRef={editorRef}
onLoad={() => setIsLoaded(true)}
/>
)}
</FastField>
</Suspense>
</FormControl>
);
}
function Loading() {
return (
<Flex alignItems='center' gap={2} justifyContent='center'>
<CircularProgress isIndeterminate color='primary.500' size='1.5rem' />{' '}
Loading json editor...
</Flex>
);
}
function ControlBar(props: { editor: JSONEditorCodeMode }) {
const { editor } = props;
const undoManager = editor.aceEditor.getSession().getUndoManager();
return (
<Flex ml='auto' gap={2}>
<FieldIconBtn
aria-label='Fix'
onClick={() => {
editor.repair?.();
editor._onChange?.();
}}
icon={<CollecticonWrench size={3} />}
/>
<FieldIconBtn
aria-label='Compact'
onClick={() => {
editor.compact?.();
}}
icon={<CollecticonTextBlock size={3} />}
/>
<FieldIconBtn
aria-label='Format'
onClick={() => {
editor.format?.();
}}
icon={<CollecticonIndent size={3} />}
/>
<FieldIconBtn
aria-label='Undo'
isDisabled={!undoManager?.canUndo()}
onClick={() => {
undoManager?.undo();
}}
icon={<CollecticonArrowSemiSpinCcw size={3} />}
/>
<FieldIconBtn
aria-label='Redo'
isDisabled={!undoManager?.canRedo()}
onClick={() => {
undoManager?.redo();
}}
icon={<CollecticonArrowSemiSpinCw size={3} />}
/>
</Flex>
);
}