@jbrowse/plugin-config 1.7.11 → 2.1.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 (133) hide show
  1. package/dist/ConfigurationEditorWidget/components/CallbackEditor.d.ts +10 -7
  2. package/dist/ConfigurationEditorWidget/components/CallbackEditor.js +117 -115
  3. package/dist/ConfigurationEditorWidget/components/CallbackEditor.js.map +1 -0
  4. package/dist/ConfigurationEditorWidget/components/ColorEditor.d.ts +9 -33
  5. package/dist/ConfigurationEditorWidget/components/ColorEditor.js +68 -117
  6. package/dist/ConfigurationEditorWidget/components/ColorEditor.js.map +1 -0
  7. package/dist/ConfigurationEditorWidget/components/ConfigurationEditor.d.ts +7 -3
  8. package/dist/ConfigurationEditorWidget/components/ConfigurationEditor.js +117 -160
  9. package/dist/ConfigurationEditorWidget/components/ConfigurationEditor.js.map +1 -0
  10. package/dist/ConfigurationEditorWidget/components/JsonEditor.d.ts +9 -7
  11. package/dist/ConfigurationEditorWidget/components/JsonEditor.js +92 -77
  12. package/dist/ConfigurationEditorWidget/components/JsonEditor.js.map +1 -0
  13. package/dist/ConfigurationEditorWidget/components/SlotEditor.d.ts +17 -5
  14. package/dist/ConfigurationEditorWidget/components/SlotEditor.js +240 -374
  15. package/dist/ConfigurationEditorWidget/components/SlotEditor.js.map +1 -0
  16. package/dist/ConfigurationEditorWidget/components/StringArrayEditor.js +76 -105
  17. package/dist/ConfigurationEditorWidget/components/StringArrayEditor.js.map +1 -0
  18. package/dist/ConfigurationEditorWidget/components/TypeSelector.d.ts +8 -6
  19. package/dist/ConfigurationEditorWidget/components/TypeSelector.js +16 -46
  20. package/dist/ConfigurationEditorWidget/components/TypeSelector.js.map +1 -0
  21. package/dist/ConfigurationEditorWidget/index.d.ts +10 -3
  22. package/dist/ConfigurationEditorWidget/index.js +26 -42
  23. package/dist/ConfigurationEditorWidget/index.js.map +1 -0
  24. package/dist/ConfigurationEditorWidget/model.d.ts +3 -2
  25. package/dist/ConfigurationEditorWidget/model.js +19 -26
  26. package/dist/ConfigurationEditorWidget/model.js.map +1 -0
  27. package/dist/FromConfigAdapter/FromConfigAdapter.js +172 -204
  28. package/dist/FromConfigAdapter/FromConfigAdapter.js.map +1 -0
  29. package/dist/FromConfigAdapter/FromConfigRegionsAdapter.js +151 -142
  30. package/dist/FromConfigAdapter/FromConfigRegionsAdapter.js.map +1 -0
  31. package/dist/FromConfigAdapter/FromConfigSequenceAdapter.d.ts +2 -1
  32. package/dist/FromConfigAdapter/FromConfigSequenceAdapter.js +174 -181
  33. package/dist/FromConfigAdapter/FromConfigSequenceAdapter.js.map +1 -0
  34. package/dist/FromConfigAdapter/configSchema.js +33 -49
  35. package/dist/FromConfigAdapter/configSchema.js.map +1 -0
  36. package/dist/FromConfigAdapter/index.js +16 -50
  37. package/dist/FromConfigAdapter/index.js.map +1 -0
  38. package/dist/RefNameAliasAdapter/RefNameAliasAdapter.js +111 -125
  39. package/dist/RefNameAliasAdapter/RefNameAliasAdapter.js.map +1 -0
  40. package/dist/RefNameAliasAdapter/configSchema.js +16 -25
  41. package/dist/RefNameAliasAdapter/configSchema.js.map +1 -0
  42. package/dist/RefNameAliasAdapter/index.js +10 -22
  43. package/dist/RefNameAliasAdapter/index.js.map +1 -0
  44. package/dist/index.d.ts +9 -3
  45. package/dist/index.js +129 -144
  46. package/dist/index.js.map +1 -0
  47. package/esm/ConfigurationEditorWidget/components/CallbackEditor.d.ts +12 -0
  48. package/esm/ConfigurationEditorWidget/components/CallbackEditor.js +80 -0
  49. package/esm/ConfigurationEditorWidget/components/CallbackEditor.js.map +1 -0
  50. package/esm/ConfigurationEditorWidget/components/ColorEditor.d.ts +20 -0
  51. package/esm/ConfigurationEditorWidget/components/ColorEditor.js +22 -0
  52. package/esm/ConfigurationEditorWidget/components/ColorEditor.js.map +1 -0
  53. package/esm/ConfigurationEditorWidget/components/ConfigurationEditor.d.ts +8 -0
  54. package/esm/ConfigurationEditorWidget/components/ConfigurationEditor.js +87 -0
  55. package/esm/ConfigurationEditorWidget/components/ConfigurationEditor.js.map +1 -0
  56. package/esm/ConfigurationEditorWidget/components/JsonEditor.d.ts +11 -0
  57. package/esm/ConfigurationEditorWidget/components/JsonEditor.js +55 -0
  58. package/esm/ConfigurationEditorWidget/components/JsonEditor.js.map +1 -0
  59. package/esm/ConfigurationEditorWidget/components/SlotEditor.d.ts +18 -0
  60. package/esm/ConfigurationEditorWidget/components/SlotEditor.js +182 -0
  61. package/esm/ConfigurationEditorWidget/components/SlotEditor.js.map +1 -0
  62. package/esm/ConfigurationEditorWidget/components/StringArrayEditor.d.ts +12 -0
  63. package/esm/ConfigurationEditorWidget/components/StringArrayEditor.js +36 -0
  64. package/esm/ConfigurationEditorWidget/components/StringArrayEditor.js.map +1 -0
  65. package/esm/ConfigurationEditorWidget/components/TypeSelector.d.ts +9 -0
  66. package/esm/ConfigurationEditorWidget/components/TypeSelector.js +12 -0
  67. package/esm/ConfigurationEditorWidget/components/TypeSelector.js.map +1 -0
  68. package/esm/ConfigurationEditorWidget/index.d.ts +10 -0
  69. package/esm/ConfigurationEditorWidget/index.js +21 -0
  70. package/esm/ConfigurationEditorWidget/index.js.map +1 -0
  71. package/esm/ConfigurationEditorWidget/model.d.ts +9 -0
  72. package/esm/ConfigurationEditorWidget/model.js +17 -0
  73. package/esm/ConfigurationEditorWidget/model.js.map +1 -0
  74. package/esm/FromConfigAdapter/FromConfigAdapter.d.ts +24 -0
  75. package/esm/FromConfigAdapter/FromConfigAdapter.js +63 -0
  76. package/esm/FromConfigAdapter/FromConfigAdapter.js.map +1 -0
  77. package/esm/FromConfigAdapter/FromConfigRegionsAdapter.d.ts +23 -0
  78. package/esm/FromConfigAdapter/FromConfigRegionsAdapter.js +50 -0
  79. package/esm/FromConfigAdapter/FromConfigRegionsAdapter.js.map +1 -0
  80. package/esm/FromConfigAdapter/FromConfigSequenceAdapter.d.ts +26 -0
  81. package/esm/FromConfigAdapter/FromConfigSequenceAdapter.js +65 -0
  82. package/esm/FromConfigAdapter/FromConfigSequenceAdapter.js.map +1 -0
  83. package/esm/FromConfigAdapter/configSchema.d.ts +3 -0
  84. package/esm/FromConfigAdapter/configSchema.js +32 -0
  85. package/esm/FromConfigAdapter/configSchema.js.map +1 -0
  86. package/esm/FromConfigAdapter/index.d.ts +4 -0
  87. package/esm/FromConfigAdapter/index.js +5 -0
  88. package/esm/FromConfigAdapter/index.js.map +1 -0
  89. package/esm/RefNameAliasAdapter/RefNameAliasAdapter.d.ts +8 -0
  90. package/esm/RefNameAliasAdapter/RefNameAliasAdapter.js +24 -0
  91. package/esm/RefNameAliasAdapter/RefNameAliasAdapter.js.map +1 -0
  92. package/esm/RefNameAliasAdapter/configSchema.d.ts +2 -0
  93. package/esm/RefNameAliasAdapter/configSchema.js +15 -0
  94. package/esm/RefNameAliasAdapter/configSchema.js.map +1 -0
  95. package/esm/RefNameAliasAdapter/index.d.ts +2 -0
  96. package/esm/RefNameAliasAdapter/index.js +3 -0
  97. package/esm/RefNameAliasAdapter/index.js.map +1 -0
  98. package/esm/index.d.ts +18 -0
  99. package/esm/index.js +72 -0
  100. package/esm/index.js.map +1 -0
  101. package/package.json +21 -15
  102. package/src/ConfigurationEditorWidget/components/CallbackEditor.tsx +126 -0
  103. package/src/ConfigurationEditorWidget/components/ColorEditor.tsx +13 -60
  104. package/src/ConfigurationEditorWidget/components/{ConfigurationEditor.test.js → ConfigurationEditor.test.tsx} +0 -0
  105. package/src/ConfigurationEditorWidget/components/ConfigurationEditor.tsx +173 -0
  106. package/src/ConfigurationEditorWidget/components/JsonEditor.tsx +84 -0
  107. package/src/ConfigurationEditorWidget/components/SlotEditor.tsx +484 -0
  108. package/src/ConfigurationEditorWidget/components/StringArrayEditor.tsx +2 -2
  109. package/src/ConfigurationEditorWidget/components/{TypeSelector.js → TypeSelector.tsx} +15 -7
  110. package/src/ConfigurationEditorWidget/components/__snapshots__/ConfigurationEditor.test.tsx.snap +2024 -0
  111. package/src/ConfigurationEditorWidget/index.tsx +25 -0
  112. package/src/ConfigurationEditorWidget/{model.js → model.ts} +4 -2
  113. package/src/FromConfigAdapter/FromConfigSequenceAdapter.ts +6 -10
  114. package/src/index.ts +20 -14
  115. package/dist/ConfigurationEditorWidget/components/CodeEditor.d.ts +0 -4
  116. package/dist/ConfigurationEditorWidget/components/CodeEditor.js +0 -80
  117. package/dist/ConfigurationEditorWidget/components/ColorEditor.test.js +0 -31
  118. package/dist/ConfigurationEditorWidget/components/ColorPicker.d.ts +0 -14
  119. package/dist/ConfigurationEditorWidget/components/ColorPicker.js +0 -72
  120. package/dist/ConfigurationEditorWidget/components/ConfigurationEditor.test.js +0 -121
  121. package/dist/FromConfigAdapter/FromConfigAdapter.test.js +0 -100
  122. package/dist/FromConfigAdapter/FromConfigRegionsAdapter.test.js +0 -200
  123. package/dist/FromConfigAdapter/FromConfigSequenceAdapter.test.js +0 -110
  124. package/dist/RefNameAliasAdapter/RefNameAliasAdapter.test.js +0 -41
  125. package/dist/index.test.js +0 -41
  126. package/src/ConfigurationEditorWidget/components/CallbackEditor.js +0 -112
  127. package/src/ConfigurationEditorWidget/components/CodeEditor.js +0 -60
  128. package/src/ConfigurationEditorWidget/components/ColorPicker.tsx +0 -52
  129. package/src/ConfigurationEditorWidget/components/ConfigurationEditor.js +0 -154
  130. package/src/ConfigurationEditorWidget/components/JsonEditor.js +0 -56
  131. package/src/ConfigurationEditorWidget/components/SlotEditor.js +0 -377
  132. package/src/ConfigurationEditorWidget/components/__snapshots__/ConfigurationEditor.test.js.snap +0 -1753
  133. package/src/ConfigurationEditorWidget/index.js +0 -20
@@ -1,154 +0,0 @@
1
- import React from 'react'
2
- import {
3
- readConfObject,
4
- getTypeNamesFromExplicitlyTypedUnion,
5
- isConfigurationSchemaType,
6
- isConfigurationSlotType,
7
- } from '@jbrowse/core/configuration'
8
- import {
9
- FormGroup,
10
- Accordion,
11
- AccordionDetails,
12
- AccordionSummary,
13
- Typography,
14
- makeStyles,
15
- } from '@material-ui/core'
16
- import { observer } from 'mobx-react'
17
- import { getMembers } from 'mobx-state-tree'
18
- import { singular } from 'pluralize'
19
-
20
- // icons
21
- import ExpandMoreIcon from '@material-ui/icons/ExpandMore'
22
-
23
- // locals
24
- import SlotEditor from './SlotEditor'
25
- import TypeSelector from './TypeSelector'
26
-
27
- const useStyles = makeStyles(theme => ({
28
- expandIcon: {
29
- color: '#fff',
30
- },
31
- root: {
32
- padding: theme.spacing(1, 3, 1, 1),
33
- },
34
- expansionPanelDetails: {
35
- display: 'block',
36
- padding: theme.spacing(1),
37
- },
38
-
39
- accordion: {
40
- border: `1px solid ${theme.palette.text.primary}`,
41
- },
42
- }))
43
-
44
- const Member = observer(props => {
45
- const classes = useStyles()
46
- const {
47
- slotName,
48
- slotSchema,
49
- schema,
50
- slot = schema[slotName],
51
- path = [],
52
- } = props
53
- let typeSelector
54
- if (isConfigurationSchemaType(slotSchema)) {
55
- if (slot.length) {
56
- return slot.map((subslot, slotIndex) => {
57
- const key = `${singular(slotName)} ${slotIndex + 1}`
58
- return <Member {...props} key={key} slot={subslot} slotName={key} />
59
- })
60
- }
61
- // if this is an explicitly typed schema, make a type-selecting dropdown
62
- // that can be used to change its type
63
- const typeNameChoices = getTypeNamesFromExplicitlyTypedUnion(slotSchema)
64
- if (typeNameChoices.length) {
65
- typeSelector = (
66
- <TypeSelector
67
- typeNameChoices={typeNameChoices}
68
- slotName={slotName}
69
- slot={slot}
70
- onChange={evt => {
71
- if (evt.target.value !== slot.type) {
72
- schema.setSubschema(slotName, { type: evt.target.value })
73
- }
74
- }}
75
- />
76
- )
77
- }
78
- return (
79
- <Accordion
80
- defaultExpanded
81
- className={classes.accordion}
82
- TransitionProps={{ unmountOnExit: true, timeout: 150 }}
83
- >
84
- <AccordionSummary
85
- expandIcon={<ExpandMoreIcon className={classes.expandIcon} />}
86
- >
87
- <Typography>{[...path, slotName].join('🡒')}</Typography>
88
- </AccordionSummary>
89
- <AccordionDetails className={classes.expansionPanelDetails}>
90
- {typeSelector}
91
- <FormGroup>
92
- <Schema schema={slot} path={[...path, slotName]} />
93
- </FormGroup>
94
- </AccordionDetails>
95
- </Accordion>
96
- )
97
- }
98
-
99
- if (isConfigurationSlotType(slotSchema)) {
100
- // this is a regular config slot
101
- return <SlotEditor key={slotName} slot={slot} slotSchema={slotSchema} />
102
- }
103
-
104
- return null
105
- })
106
-
107
- const Schema = observer(({ schema, path = [] }) => {
108
- const properties = getMembers(schema).properties
109
- return Object.entries(properties).map(([slotName, slotSchema]) => (
110
- <Member
111
- key={slotName}
112
- slotName={slotName}
113
- slotSchema={slotSchema}
114
- path={path}
115
- schema={schema}
116
- />
117
- ))
118
- })
119
-
120
- const ConfigurationEditor = observer(({ model }) => {
121
- const classes = useStyles()
122
- // key forces a re-render, otherwise the same field can end up being used
123
- // for different tracks since only the backing model changes for example
124
- // see pr #804
125
- const key = model.target && readConfObject(model.target, 'trackId')
126
- const name = model.target && readConfObject(model.target, 'name')
127
- return (
128
- <>
129
- <Accordion
130
- key={key}
131
- defaultExpanded
132
- className={classes.accordion}
133
- TransitionProps={{ unmountOnExit: true, timeout: 150 }}
134
- >
135
- <AccordionSummary
136
- expandIcon={<ExpandMoreIcon className={classes.expandIcon} />}
137
- >
138
- <Typography>{name ? name : 'Configuration'}</Typography>
139
- </AccordionSummary>
140
- <AccordionDetails
141
- className={classes.expansionPanelDetails}
142
- data-testid="configEditor"
143
- >
144
- {!model.target ? 'no target set' : <Schema schema={model.target} />}
145
- </AccordionDetails>
146
- </Accordion>
147
-
148
- {/* blank space at the bottom of screen allows scroll */}
149
- <div style={{ height: 300 }} />
150
- </>
151
- )
152
- })
153
-
154
- export default ConfigurationEditor
@@ -1,56 +0,0 @@
1
- import React, { lazy, useEffect, useState } from 'react'
2
- import { useDebounce } from '@jbrowse/core/util'
3
- import {
4
- FormControl,
5
- FormHelperText,
6
- InputLabel,
7
- makeStyles,
8
- } from '@material-ui/core'
9
- import { observer, PropTypes } from 'mobx-react'
10
- const useStyles = makeStyles({
11
- error: {
12
- color: 'red',
13
- fontSize: '0.8em',
14
- },
15
- })
16
-
17
- const CodeEditor = lazy(() => import('./CodeEditor'))
18
-
19
- function JsonEditor({ slot }) {
20
- const classes = useStyles()
21
- const [contents, setContents] = useState(
22
- JSON.stringify(slot.value, null, ' '),
23
- )
24
- const [error, setError] = useState()
25
- const debouncedJson = useDebounce(contents, 400)
26
-
27
- useEffect(() => {
28
- try {
29
- slot.set(JSON.parse(debouncedJson))
30
- setError(undefined)
31
- } catch (e) {
32
- setError(e.message)
33
- }
34
- }, [debouncedJson, slot])
35
-
36
- return (
37
- <>
38
- {error ? <p className={classes.error}>{error}</p> : null}
39
- <FormControl error={error}>
40
- <InputLabel shrink htmlFor="callback-editor">
41
- {slot.name}
42
- </InputLabel>
43
- <React.Suspense fallback={<div />}>
44
- <CodeEditor contents={contents} setContents={setContents} />
45
- </React.Suspense>
46
- <FormHelperText>{slot.description}</FormHelperText>
47
- </FormControl>
48
- </>
49
- )
50
- }
51
-
52
- JsonEditor.propTypes = {
53
- slot: PropTypes.objectOrObservableObject.isRequired,
54
- }
55
-
56
- export default observer(JsonEditor)
@@ -1,377 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { observer } from 'mobx-react'
3
- import { getPropertyMembers, getEnv } from 'mobx-state-tree'
4
- import { FileSelector, SanitizedHTML } from '@jbrowse/core/ui'
5
- import {
6
- getPropertyType,
7
- getSubType,
8
- getUnionSubTypes,
9
- } from '@jbrowse/core/util/mst-reflection'
10
- import {
11
- Card,
12
- CardContent,
13
- CardHeader,
14
- Checkbox,
15
- FormControl,
16
- FormControlLabel,
17
- FormHelperText,
18
- IconButton,
19
- InputAdornment,
20
- InputLabel,
21
- MenuItem,
22
- Paper,
23
- SvgIcon,
24
- TextField,
25
- makeStyles,
26
- } from '@material-ui/core'
27
-
28
- // icons
29
- import DeleteIcon from '@material-ui/icons/Delete'
30
- import AddIcon from '@material-ui/icons/Add'
31
- import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked'
32
-
33
- // locals
34
- import StringArrayEditor from './StringArrayEditor'
35
- import CallbackEditor from './CallbackEditor'
36
- import ColorEditor from './ColorEditor'
37
- import JsonEditor from './JsonEditor'
38
-
39
- // adds ability to have html in helperText. note that FormHelperTextProps is
40
- // div because the default is p which does not like div children
41
- const MyTextField = props => {
42
- // eslint-disable-next-line react/prop-types
43
- const { helperText } = props
44
- return (
45
- <TextField
46
- {...props}
47
- helperText={<SanitizedHTML html={helperText} />}
48
- FormHelperTextProps={{
49
- component: 'div',
50
- }}
51
- fullWidth
52
- />
53
- )
54
- }
55
-
56
- const StringEditor = observer(({ slot }) => (
57
- <MyTextField
58
- label={slot.name}
59
- helperText={slot.description}
60
- value={slot.value}
61
- onChange={evt => slot.set(evt.target.value)}
62
- />
63
- ))
64
-
65
- const TextEditor = observer(({ slot }) => (
66
- <TextField
67
- label={slot.name}
68
- helperText={slot.description}
69
- multiline
70
- value={slot.value}
71
- onChange={evt => slot.set(evt.target.value)}
72
- />
73
- ))
74
-
75
- // checked checkbox, looks like a styled (x)
76
- const SvgCheckbox = () => (
77
- <SvgIcon>
78
- <path d="M20.41,3C21.8,5.71 22.35,8.84 22,12C21.8,15.16 20.7,18.29 18.83,21L17.3,20C18.91,17.57 19.85,14.8 20,12C20.34,9.2 19.89,6.43 18.7,4L20.41,3M5.17,3L6.7,4C5.09,6.43 4.15,9.2 4,12C3.66,14.8 4.12,17.57 5.3,20L3.61,21C2.21,18.29 1.65,15.17 2,12C2.2,8.84 3.3,5.71 5.17,3M12.08,10.68L14.4,7.45H16.93L13.15,12.45L15.35,17.37H13.09L11.71,14L9.28,17.33H6.76L10.66,12.21L8.53,7.45H10.8L12.08,10.68Z" />
79
- </SvgIcon>
80
- )
81
-
82
- const useMapEditorStyles = makeStyles(theme => ({
83
- card: {
84
- marginTop: theme.spacing(1),
85
- },
86
- }))
87
-
88
- const StringArrayMapEditor = observer(({ slot }) => {
89
- const classes = useMapEditorStyles()
90
- const [value, setValue] = useState('')
91
- return (
92
- <>
93
- <InputLabel>{slot.name}</InputLabel>
94
- {Array.from(slot.value, ([key, val]) => (
95
- <Card raised key={key} className={classes.card}>
96
- <CardHeader
97
- title={key}
98
- action={
99
- <IconButton color="secondary" onClick={() => slot.remove(key)}>
100
- <DeleteIcon />
101
- </IconButton>
102
- }
103
- />
104
- <CardContent>
105
- <StringArrayEditor
106
- slot={{
107
- value: val,
108
- description: `Values associated with entry ${key}`,
109
- setAtIndex: (idx, strValue) => {
110
- slot.setAtKeyIndex(key, idx, strValue)
111
- },
112
- removeAtIndex: idx => {
113
- slot.removeAtKeyIndex(key, idx)
114
- },
115
- add: strValue => {
116
- slot.addToKey(key, strValue)
117
- },
118
- }}
119
- />
120
- </CardContent>
121
- </Card>
122
- ))}
123
- <Card raised className={classes.card}>
124
- <CardHeader
125
- disableTypography
126
- title={
127
- <TextField
128
- fullWidth
129
- value={value}
130
- placeholder="add new"
131
- onChange={event => setValue(event.target.value)}
132
- InputProps={{
133
- endAdornment: (
134
- <InputAdornment position="end">
135
- <IconButton
136
- disabled={value === ''}
137
- onClick={() => {
138
- slot.add(value, [])
139
- setValue('')
140
- }}
141
- color="secondary"
142
- >
143
- <AddIcon />
144
- </IconButton>
145
- </InputAdornment>
146
- ),
147
- }}
148
- />
149
- }
150
- />
151
- </Card>
152
- <FormHelperText>{slot.description}</FormHelperText>
153
- </>
154
- )
155
- })
156
-
157
- const NumberMapEditor = observer(({ slot }) => {
158
- const classes = useMapEditorStyles()
159
- const [value, setValue] = useState('')
160
- return (
161
- <>
162
- <InputLabel>{slot.name}</InputLabel>
163
- {Array.from(slot.value, ([key, val]) => (
164
- <Card raised key={key} className={classes.card}>
165
- <CardHeader
166
- title={key}
167
- action={
168
- <IconButton color="secondary" onClick={() => slot.remove(key)}>
169
- <DeleteIcon />
170
- </IconButton>
171
- }
172
- />
173
- <CardContent>
174
- <NumberEditor
175
- slot={{
176
- value: val,
177
- set: numValue => slot.add(key, numValue),
178
- }}
179
- />
180
- </CardContent>
181
- </Card>
182
- ))}
183
- <Card raised className={classes.card}>
184
- <CardHeader
185
- disableTypography
186
- title={
187
- <TextField
188
- fullWidth
189
- value={value}
190
- placeholder="add new"
191
- onChange={event => setValue(event.target.value)}
192
- InputProps={{
193
- endAdornment: (
194
- <InputAdornment position="end">
195
- <IconButton
196
- disabled={value === ''}
197
- onClick={() => {
198
- slot.add(value, 0)
199
- setValue('')
200
- }}
201
- color="secondary"
202
- >
203
- <AddIcon />
204
- </IconButton>
205
- </InputAdornment>
206
- ),
207
- }}
208
- />
209
- }
210
- />
211
- </Card>
212
- <FormHelperText>{slot.description}</FormHelperText>
213
- </>
214
- )
215
- })
216
-
217
- const NumberEditor = observer(({ slot }) => {
218
- const [val, setVal] = useState(slot.value)
219
- useEffect(() => {
220
- const num = parseFloat(val, 10)
221
- if (!Number.isNaN(num)) {
222
- slot.set(num)
223
- } else {
224
- slot.reset()
225
- }
226
- }, [slot, val])
227
- return (
228
- <MyTextField
229
- label={slot.name}
230
- helperText={slot.description}
231
- value={val}
232
- type="number"
233
- onChange={evt => setVal(evt.target.value)}
234
- />
235
- )
236
- })
237
-
238
- const IntegerEditor = observer(({ slot }) => {
239
- const [val, setVal] = useState(slot.value)
240
- useEffect(() => {
241
- const num = parseInt(val, 10)
242
- if (!Number.isNaN(num)) {
243
- slot.set(num)
244
- }
245
- }, [slot, val])
246
- return (
247
- <MyTextField
248
- label={slot.name}
249
- helperText={slot.description}
250
- value={val}
251
- type="number"
252
- onChange={evt => setVal(evt.target.value)}
253
- />
254
- )
255
- })
256
-
257
- const BooleanEditor = observer(({ slot }) => (
258
- <FormControl>
259
- <FormControlLabel
260
- label={slot.name}
261
- control={
262
- <Checkbox
263
- checked={slot.value}
264
- onChange={evt => slot.set(evt.target.checked)}
265
- />
266
- }
267
- />
268
- <FormHelperText>{slot.description}</FormHelperText>
269
- </FormControl>
270
- ))
271
-
272
- const StringEnumEditor = observer(({ slot, slotSchema }) => {
273
- const p = getPropertyMembers(getSubType(slotSchema))
274
- const choices = getUnionSubTypes(
275
- getUnionSubTypes(getSubType(getPropertyType(p, 'value')))[1],
276
- ).map(t => t.value)
277
-
278
- return (
279
- <MyTextField
280
- value={slot.value}
281
- label={slot.name}
282
- select
283
- helperText={slot.description}
284
- onChange={evt => slot.set(evt.target.value)}
285
- >
286
- {choices.map(str => (
287
- <MenuItem key={str} value={str}>
288
- {str}
289
- </MenuItem>
290
- ))}
291
- </MyTextField>
292
- )
293
- })
294
-
295
- const FileSelectorWrapper = observer(({ slot }) => {
296
- return (
297
- <FileSelector
298
- location={slot.value}
299
- setLocation={location => slot.set(location)}
300
- name={slot.name}
301
- description={slot.description}
302
- rootModel={getEnv(slot).pluginManager?.rootModel}
303
- />
304
- )
305
- })
306
-
307
- const valueComponents = {
308
- string: StringEditor,
309
- text: TextEditor,
310
- fileLocation: FileSelectorWrapper,
311
- stringArray: StringArrayEditor,
312
- stringArrayMap: StringArrayMapEditor,
313
- numberMap: NumberMapEditor,
314
- number: NumberEditor,
315
- integer: IntegerEditor,
316
- color: ColorEditor,
317
- stringEnum: StringEnumEditor,
318
- boolean: BooleanEditor,
319
- frozen: JsonEditor,
320
- configRelationships: JsonEditor,
321
- }
322
-
323
- export const useSlotEditorStyles = makeStyles(theme => ({
324
- paper: {
325
- display: 'flex',
326
- marginBottom: theme.spacing(2),
327
- position: 'relative',
328
- },
329
- paperContent: {
330
- width: '100%',
331
- },
332
- slotModeSwitch: {
333
- width: 24,
334
- background: theme.palette.secondary.light,
335
- display: 'flex',
336
- justifyContent: 'center',
337
- alignItems: 'center',
338
- },
339
- }))
340
-
341
- const SlotEditor = observer(({ slot, slotSchema }) => {
342
- const classes = useSlotEditorStyles()
343
- const { type } = slot
344
- let ValueComponent = slot.isCallback ? CallbackEditor : valueComponents[type]
345
- if (!ValueComponent) {
346
- console.warn(`no slot editor defined for ${type}, editing as string`)
347
- ValueComponent = StringEditor
348
- }
349
- if (!(type in valueComponents)) {
350
- console.warn(`SlotEditor needs to implement ${type}`)
351
- }
352
- return (
353
- <Paper className={classes.paper}>
354
- <div className={classes.paperContent}>
355
- <ValueComponent slot={slot} slotSchema={slotSchema} />
356
- </div>
357
- <div className={classes.slotModeSwitch}>
358
- {slot.contextVariable.length ? (
359
- <IconButton
360
- className={classes.slotModeIcon}
361
- onClick={() =>
362
- slot.isCallback ? slot.convertToValue() : slot.convertToCallback()
363
- }
364
- title={`convert to ${
365
- slot.isCallback ? 'regular value' : 'callback'
366
- }`}
367
- color="secondary"
368
- >
369
- {!slot.isCallback ? <RadioButtonUncheckedIcon /> : <SvgCheckbox />}
370
- </IconButton>
371
- ) : null}
372
- </div>
373
- </Paper>
374
- )
375
- })
376
-
377
- export default SlotEditor