@dxos/react-ui-form 0.8.4-main.74a063c4e0 → 0.8.4-main.765dc60934
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/LICENSE +102 -5
- package/dist/lib/browser/index.mjs +873 -446
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/translations.mjs +82 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +873 -446
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/translations.mjs +84 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +63 -61
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +34 -12
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +73 -71
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField.d.ts +5 -5
- package/dist/types/src/components/Form/FormField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormFieldComponent.d.ts +8 -6
- package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormFieldSet.d.ts +5 -8
- package/dist/types/src/components/Form/FormFieldSet.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/ArrayField.d.ts +4 -4
- package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts +8 -1
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts +84 -0
- package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/NumberField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/RefField.d.ts +10 -4
- package/dist/types/src/components/Form/fields/RefField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/SelectField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts +63 -61
- package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/TextField.d.ts +1 -1
- package/dist/types/src/components/Form/fields/TextField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/TupleField.d.ts.map +1 -1
- package/dist/types/src/components/ObjectForm/ObjectForm.d.ts +9 -0
- package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -0
- package/dist/types/src/components/ObjectForm/index.d.ts +2 -0
- package/dist/types/src/components/ObjectForm/index.d.ts.map +1 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +17 -3
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +63 -61
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -1
- package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +9 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts +127 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts.map +1 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts +2 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts.map +1 -0
- package/dist/types/src/components/ObjectProperties/index.d.ts +2 -0
- package/dist/types/src/components/ObjectProperties/index.d.ts.map +1 -0
- package/dist/types/src/components/Settings/Settings.d.ts +24 -12
- package/dist/types/src/components/Settings/Settings.d.ts.map +1 -1
- package/dist/types/src/components/Settings/Settings.stories.d.ts +64 -61
- package/dist/types/src/components/Settings/Settings.stories.d.ts.map +1 -1
- package/dist/types/src/components/Settings/SettingsFieldSet.d.ts +43 -0
- package/dist/types/src/components/Settings/SettingsFieldSet.d.ts.map +1 -0
- package/dist/types/src/components/Settings/SettingsItem.d.ts +16 -0
- package/dist/types/src/components/Settings/SettingsItem.d.ts.map +1 -0
- package/dist/types/src/components/Settings/SettingsSelectField.d.ts +18 -0
- package/dist/types/src/components/Settings/SettingsSelectField.d.ts.map +1 -0
- package/dist/types/src/components/Settings/index.d.ts +2 -0
- package/dist/types/src/components/Settings/index.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +3 -4
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +63 -61
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +4 -4
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useKeyHandler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +63 -61
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/field-type.d.ts +19 -0
- package/dist/types/src/util/field-type.d.ts.map +1 -0
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/properties.d.ts.map +1 -1
- package/dist/types/src/util/refs.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +40 -38
- package/src/components/FieldEditor/FieldEditor.stories.tsx +2 -1
- package/src/components/FieldEditor/FieldEditor.tsx +3 -2
- package/src/components/Form/Form.stories.tsx +9 -19
- package/src/components/Form/Form.tsx +59 -7
- package/src/components/Form/FormField.tsx +12 -10
- package/src/components/Form/FormFieldComponent.tsx +6 -3
- package/src/components/Form/FormFieldSet.tsx +47 -31
- package/src/components/Form/fields/ArrayField.tsx +7 -6
- package/src/components/Form/fields/GeoPointField.tsx +3 -2
- package/src/components/Form/fields/MarkdownField.stories.tsx +206 -0
- package/src/components/Form/fields/MarkdownField.tsx +135 -45
- package/src/components/Form/fields/RefField.tsx +61 -30
- package/src/components/Form/fields/SelectOptionField.stories.tsx +8 -5
- package/src/components/Form/fields/SelectOptionField.tsx +6 -5
- package/src/components/Form/fields/TextField.tsx +2 -2
- package/src/components/ObjectForm/ObjectForm.tsx +114 -0
- package/src/components/ObjectForm/index.ts +5 -0
- package/src/components/ObjectPicker/ObjectPicker.stories.tsx +9 -6
- package/src/components/ObjectPicker/ObjectPicker.tsx +28 -12
- package/src/components/ObjectProperties/ObjectProperties.stories.tsx +362 -0
- package/src/components/ObjectProperties/ObjectProperties.test.tsx +101 -0
- package/src/components/ObjectProperties/ObjectProperties.tsx +141 -0
- package/src/components/ObjectProperties/index.ts +5 -0
- package/src/components/Settings/AUDIT.md +52 -0
- package/src/components/Settings/Settings.stories.tsx +50 -1
- package/src/components/Settings/Settings.tsx +7 -56
- package/src/components/Settings/SettingsFieldSet.tsx +257 -0
- package/src/components/Settings/SettingsItem.tsx +58 -0
- package/src/components/Settings/SettingsSelectField.tsx +59 -0
- package/src/components/Settings/index.ts +2 -0
- package/src/components/ViewEditor/ViewEditor.stories.tsx +10 -10
- package/src/components/ViewEditor/ViewEditor.tsx +19 -26
- package/src/components/index.ts +2 -0
- package/src/components/testing.tsx +20 -21
- package/src/index.ts +0 -4
- package/src/translations.ts +7 -3
- package/src/util/field-type.ts +60 -0
- package/src/util/index.ts +1 -0
|
@@ -9,8 +9,7 @@ import * as Option from 'effect/Option';
|
|
|
9
9
|
import * as Schema from 'effect/Schema';
|
|
10
10
|
import React, { forwardRef, useCallback, useContext, useImperativeHandle, useMemo, useState } from 'react';
|
|
11
11
|
|
|
12
|
-
import { Entity, Feed, Filter, Format, Obj, Query, QueryAST, Ref, type SchemaRegistry } from '@dxos/echo';
|
|
13
|
-
import { View } from '@dxos/echo';
|
|
12
|
+
import { Entity, Feed, Filter, Format, Obj, Query, QueryAST, Ref, type SchemaRegistry, View } from '@dxos/echo';
|
|
14
13
|
import { EchoSchema, type JsonProp, isMutable, toJsonSchema } from '@dxos/echo/internal';
|
|
15
14
|
import { invariant } from '@dxos/invariant';
|
|
16
15
|
import { useObject, useQuery } from '@dxos/react-client/echo';
|
|
@@ -24,9 +23,10 @@ import {
|
|
|
24
23
|
createEchoChangeCallback,
|
|
25
24
|
getTypenameFromQuery,
|
|
26
25
|
} from '@dxos/schema';
|
|
27
|
-
import { mx, osTranslations
|
|
26
|
+
import { mx, osTranslations } from '@dxos/ui-theme';
|
|
27
|
+
|
|
28
|
+
import { translationKey } from '#translations';
|
|
28
29
|
|
|
29
|
-
import { translationKey } from '../../translations';
|
|
30
30
|
import { FieldEditor } from '../FieldEditor';
|
|
31
31
|
import {
|
|
32
32
|
Form,
|
|
@@ -100,8 +100,8 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
|
|
|
100
100
|
if (from._tag !== 'scope') {
|
|
101
101
|
return undefined;
|
|
102
102
|
}
|
|
103
|
-
return Option.fromNullable(from.scope.
|
|
104
|
-
Option.flatMap((
|
|
103
|
+
return Option.fromNullable(from.scope.feeds).pipe(
|
|
104
|
+
Option.flatMap((feeds) => Array.head(feeds)),
|
|
105
105
|
Option.map(String),
|
|
106
106
|
Option.getOrUndefined,
|
|
107
107
|
);
|
|
@@ -160,13 +160,13 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
|
|
|
160
160
|
const handleUpdate = useCallback(
|
|
161
161
|
(values: any) => {
|
|
162
162
|
const targetValue = values.target;
|
|
163
|
-
let
|
|
163
|
+
let feedDXN: string | undefined;
|
|
164
164
|
|
|
165
165
|
if (Ref.isRef(targetValue)) {
|
|
166
|
-
const
|
|
167
|
-
const feed = feeds.find((feed) => Obj.getDXN(feed).toString() ===
|
|
166
|
+
const targetDXN = targetValue.dxn.toString();
|
|
167
|
+
const feed = feeds.find((feed) => Obj.getDXN(feed).toString() === targetDXN);
|
|
168
168
|
if (feed) {
|
|
169
|
-
|
|
169
|
+
feedDXN = Feed.getQueueDxn(feed)?.toString();
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -175,7 +175,7 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
|
|
|
175
175
|
mode === 'schema'
|
|
176
176
|
? Query.select(Filter.typename(values.query)).ast
|
|
177
177
|
: JSON.parse(JSON.stringify(values.query));
|
|
178
|
-
onQueryChanged?.(query,
|
|
178
|
+
onQueryChanged?.(query, feedDXN);
|
|
179
179
|
},
|
|
180
180
|
[onQueryChanged, mode, feeds],
|
|
181
181
|
);
|
|
@@ -189,7 +189,7 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
|
|
|
189
189
|
);
|
|
190
190
|
|
|
191
191
|
return (
|
|
192
|
-
<div
|
|
192
|
+
<div className={mx(classNames)}>
|
|
193
193
|
{/* If readonly is set, then the callout is not needed. */}
|
|
194
194
|
{schemaReadonly && !readonly && (
|
|
195
195
|
<Message.Root valence='info' classNames='my-form-padding'>
|
|
@@ -274,12 +274,12 @@ const FieldList = ({ schema, view, registry, readonly, showHeading = false, onDe
|
|
|
274
274
|
const handleMove = useCallback(
|
|
275
275
|
(fromIndex: number, toIndex: number) => {
|
|
276
276
|
invariant(!readonly);
|
|
277
|
-
Obj.
|
|
277
|
+
Obj.update(view, (view) => {
|
|
278
278
|
// NOTE(ZaymonFC): Using arrayMove here causes a race condition with the kanban model.
|
|
279
|
-
const fields = [...
|
|
279
|
+
const fields = [...view.projection.fields];
|
|
280
280
|
const [moved] = fields.splice(fromIndex, 1);
|
|
281
281
|
fields.splice(toIndex, 0, moved);
|
|
282
|
-
|
|
282
|
+
view.projection.fields = fields;
|
|
283
283
|
});
|
|
284
284
|
},
|
|
285
285
|
[view, readonly],
|
|
@@ -328,20 +328,13 @@ const FieldList = ({ schema, view, registry, readonly, showHeading = false, onDe
|
|
|
328
328
|
classNames={'grid grid-cols-subgrid col-span-5'}
|
|
329
329
|
aria-expanded={expandedField === field.id}
|
|
330
330
|
>
|
|
331
|
-
<div
|
|
332
|
-
role='none'
|
|
333
|
-
className={mx(
|
|
334
|
-
subtleHover,
|
|
335
|
-
'grid grid-cols-subgrid col-span-5',
|
|
336
|
-
'rounded-xs cursor-pointer min-h-10',
|
|
337
|
-
)}
|
|
338
|
-
>
|
|
331
|
+
<div className='grid grid-cols-subgrid col-span-5 rounded-xs cursor-pointer min-h-10 dx-hover'>
|
|
339
332
|
<List.ItemDragHandle disabled={readonly || schemaReadonly} />
|
|
340
333
|
<List.ItemTitle classNames={hidden && 'text-subdued'} onClick={() => handleToggleField(field)}>
|
|
341
334
|
{field.path}
|
|
342
335
|
</List.ItemTitle>
|
|
343
336
|
<List.ItemIconButton
|
|
344
|
-
label={t(hidden ? 'show
|
|
337
|
+
label={t(hidden ? 'show-field.label' : 'hide-field.label')}
|
|
345
338
|
data-testid={hidden ? 'show-field-button' : 'hide-field-button'}
|
|
346
339
|
icon={hidden ? 'ph--eye-closed--regular' : 'ph--eye--regular'}
|
|
347
340
|
autoHide={false}
|
|
@@ -369,7 +362,7 @@ const FieldList = ({ schema, view, registry, readonly, showHeading = false, onDe
|
|
|
369
362
|
)}
|
|
370
363
|
</div>
|
|
371
364
|
{expandedField === field.id && !readonly && (
|
|
372
|
-
<div
|
|
365
|
+
<div className='col-span-full mt-1 mb-1 border border-separator rounded-md'>
|
|
373
366
|
<FieldEditor
|
|
374
367
|
readonly={readonly || schemaReadonly}
|
|
375
368
|
registry={registry}
|
|
@@ -384,7 +377,7 @@ const FieldList = ({ schema, view, registry, readonly, showHeading = false, onDe
|
|
|
384
377
|
})}
|
|
385
378
|
</div>
|
|
386
379
|
{!readonly && !expandedField && (
|
|
387
|
-
<div
|
|
380
|
+
<div className='my-form-padding'>
|
|
388
381
|
<IconButton
|
|
389
382
|
icon='ph--plus--regular'
|
|
390
383
|
label={t('add-property-button.label')}
|
package/src/components/index.ts
CHANGED
|
@@ -4,27 +4,25 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { type PropsWithChildren } from 'react';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { type ThemedClassName } from '@dxos/react-ui';
|
|
8
|
+
import { Syntax } from '@dxos/react-ui-syntax-highlighter';
|
|
9
|
+
import { composableProps, slottable } from '@dxos/ui-theme';
|
|
10
10
|
|
|
11
|
-
type TestLayoutProps =
|
|
11
|
+
type TestLayoutProps = PropsWithChildren<{ json?: any }>;
|
|
12
12
|
|
|
13
|
-
export const TestLayout = ({
|
|
13
|
+
export const TestLayout = ({ children, json }: TestLayoutProps) => {
|
|
14
14
|
return (
|
|
15
|
-
<div className='
|
|
16
|
-
<TestPanel
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</Json.Content>
|
|
27
|
-
</Json.Root>
|
|
15
|
+
<div className='dx-container grid grid-cols-[1fr_1fr] p-4 gap-4'>
|
|
16
|
+
<TestPanel>{children}</TestPanel>
|
|
17
|
+
<TestPanel>
|
|
18
|
+
<Syntax.Root data={json}>
|
|
19
|
+
<Syntax.Content>
|
|
20
|
+
<Syntax.Filter />
|
|
21
|
+
<Syntax.Viewport>
|
|
22
|
+
<Syntax.Code testId='debug' classNames='text-xs' />
|
|
23
|
+
</Syntax.Viewport>
|
|
24
|
+
</Syntax.Content>
|
|
25
|
+
</Syntax.Root>
|
|
28
26
|
</TestPanel>
|
|
29
27
|
</div>
|
|
30
28
|
);
|
|
@@ -32,14 +30,15 @@ export const TestLayout = ({ classNames, children, json }: TestLayoutProps) => {
|
|
|
32
30
|
|
|
33
31
|
type TestPanelProps = ThemedClassName<PropsWithChildren>;
|
|
34
32
|
|
|
35
|
-
const TestPanel = ({
|
|
33
|
+
const TestPanel = slottable<HTMLDivElement, TestPanelProps>(({ children }, forwardedRef) => {
|
|
36
34
|
return (
|
|
37
|
-
<div
|
|
35
|
+
<div {...composableProps({ classNames: 'dx-container bg-modal-surface rounded-md' })} ref={forwardedRef}>
|
|
38
36
|
{children}
|
|
39
37
|
</div>
|
|
40
38
|
);
|
|
41
|
-
};
|
|
39
|
+
});
|
|
42
40
|
|
|
43
41
|
// Symbol for accessing debug objects in tests.
|
|
44
42
|
export const VIEW_EDITOR_DEBUG_SYMBOL = Symbol('viewEditorDebug');
|
|
45
43
|
export const FIELD_EDITOR_DEBUG_SYMBOL = Symbol('fieldEditorDebug');
|
|
44
|
+
export const OBJECT_PROPERTIES_DEBUG_SYMBOL = Symbol('objectPropertiesDebug');
|
package/src/index.ts
CHANGED
package/src/translations.ts
CHANGED
|
@@ -14,22 +14,25 @@ export const translations = [
|
|
|
14
14
|
'hidden-fields.label': 'Hidden Fields',
|
|
15
15
|
'empty-readonly-ref-field.label': '(none)',
|
|
16
16
|
|
|
17
|
-
'add-property-button.label': 'Add property',
|
|
18
17
|
'field-property.label': 'Property',
|
|
19
18
|
'field-property.placeholder': 'Property name',
|
|
20
19
|
'field-format.label': 'Type',
|
|
21
20
|
'field-path.label': 'Field path',
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
'add-item.button': 'Add item',
|
|
23
|
+
'add-property-button.label': 'Add property',
|
|
23
24
|
'boolean-input-true.value': 'Yes',
|
|
24
25
|
'boolean-input-false.value': 'No',
|
|
25
26
|
'show-field.label': 'Show field',
|
|
26
27
|
'hide-field.label': 'Hide field',
|
|
27
28
|
'delete-field.label': 'Delete field',
|
|
29
|
+
'create-option.label': 'Create',
|
|
30
|
+
'add-tag.label': 'Add tag',
|
|
31
|
+
|
|
28
32
|
'ref-field-combobox-input.placeholder': 'Search…',
|
|
29
33
|
'ref-field.placeholder': 'Select…',
|
|
30
34
|
'ref-field.placeholder_one': 'Select…',
|
|
31
35
|
'ref-field.placeholder_other': 'Select items…',
|
|
32
|
-
'create-option.label': 'Create',
|
|
33
36
|
|
|
34
37
|
'example.placeholder': 'Example',
|
|
35
38
|
'latitude.placeholder': 'Latitude (e.g., 40.7128)',
|
|
@@ -37,6 +40,7 @@ export const translations = [
|
|
|
37
40
|
|
|
38
41
|
'cancel-button.label': 'Cancel',
|
|
39
42
|
'save-button.label': 'Save',
|
|
43
|
+
'create-text.label': 'Create text',
|
|
40
44
|
|
|
41
45
|
// TypeFormat
|
|
42
46
|
'format.boolean.label': 'Boolean',
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as SchemaAST from 'effect/SchemaAST';
|
|
6
|
+
|
|
7
|
+
import { getAnnotation, isLiteralUnion } from '@dxos/effect';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Detected field type for a schema property.
|
|
11
|
+
*/
|
|
12
|
+
export type SettingsFieldType = 'boolean' | 'string' | 'number' | 'select' | 'struct';
|
|
13
|
+
|
|
14
|
+
export type SelectOption = {
|
|
15
|
+
value: string | number;
|
|
16
|
+
label?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Detect the field type from an Effect Schema AST node.
|
|
21
|
+
*/
|
|
22
|
+
export const detectFieldType = (ast: SchemaAST.AST): SettingsFieldType | undefined => {
|
|
23
|
+
if (isLiteralUnion(ast)) {
|
|
24
|
+
return 'select';
|
|
25
|
+
}
|
|
26
|
+
if (SchemaAST.isTypeLiteral(ast)) {
|
|
27
|
+
return 'struct';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
switch (ast._tag) {
|
|
31
|
+
case 'BooleanKeyword':
|
|
32
|
+
return 'boolean';
|
|
33
|
+
case 'StringKeyword':
|
|
34
|
+
return 'string';
|
|
35
|
+
case 'NumberKeyword':
|
|
36
|
+
return 'number';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return undefined;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Extract select options from a literal union AST node.
|
|
44
|
+
* Reads title annotations from individual literals for labels.
|
|
45
|
+
*/
|
|
46
|
+
export const getSelectOptionsFromAst = (ast: SchemaAST.AST): SelectOption[] | undefined => {
|
|
47
|
+
if (!isLiteralUnion(ast)) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (ast as SchemaAST.Union<SchemaAST.Literal>).types.flatMap((literalNode) => {
|
|
52
|
+
const value = literalNode.literal;
|
|
53
|
+
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
const title = getAnnotation<string>(SchemaAST.TitleAnnotationId, false)(literalNode);
|
|
57
|
+
const label = title ?? (typeof value === 'string' ? value.charAt(0).toUpperCase() + value.slice(1) : String(value));
|
|
58
|
+
return [{ value, label }];
|
|
59
|
+
});
|
|
60
|
+
};
|