@dxos/react-ui-form 0.8.4-main.dedc0f3 → 0.8.4-main.dfabb4ec29
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/README.md +0 -1
- package/dist/lib/browser/index.mjs +2772 -2208
- 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 +2772 -2208
- 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 +8 -7
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +69 -60
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +109 -26
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +116 -138
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField.d.ts +43 -0
- package/dist/types/src/components/Form/FormField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldComponent.d.ts +79 -0
- package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts +9 -0
- package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldSet.d.ts +15 -0
- package/dist/types/src/components/Form/FormFieldSet.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/ArrayField.d.ts +18 -0
- package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/BooleanField.d.ts +4 -0
- package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/GeoPointField.d.ts +5 -0
- package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts +11 -0
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +1 -0
- 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 +4 -0
- package/dist/types/src/components/Form/fields/NumberField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/RefField.d.ts +22 -0
- package/dist/types/src/components/Form/fields/RefField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/SelectField.d.ts +10 -0
- package/dist/types/src/components/Form/fields/SelectField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/SelectOptionField.d.ts +5 -0
- package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts +84 -0
- package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/TextAreaField.d.ts +4 -0
- package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/TextField.d.ts +4 -0
- package/dist/types/src/components/Form/fields/TextField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/TupleField.d.ts +6 -0
- package/dist/types/src/components/Form/fields/TupleField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/index.d.ts +12 -0
- package/dist/types/src/components/Form/fields/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/index.d.ts +2 -4
- package/dist/types/src/components/Form/index.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 +68 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +87 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -0
- package/dist/types/src/components/ObjectPicker/index.d.ts +2 -0
- package/dist/types/src/components/ObjectPicker/index.d.ts.map +1 -0
- 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 +51 -0
- package/dist/types/src/components/Settings/Settings.d.ts.map +1 -0
- package/dist/types/src/components/Settings/Settings.stories.d.ts +84 -0
- package/dist/types/src/components/Settings/Settings.stories.d.ts.map +1 -0
- 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 +4 -0
- package/dist/types/src/components/Settings/index.d.ts.map +1 -0
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +22 -11
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +72 -65
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +4 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +4 -6
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -3
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useFormHandler.d.ts +82 -0
- package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -0
- package/dist/types/src/hooks/useKeyHandler.d.ts +7 -0
- package/dist/types/src/hooks/useKeyHandler.d.ts.map +1 -0
- 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 +65 -59
- 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 +3 -3
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts +2 -2
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/properties.d.ts +7 -0
- package/dist/types/src/util/properties.d.ts.map +1 -0
- package/dist/types/src/util/refs.d.ts +3 -3
- package/dist/types/src/util/refs.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +56 -50
- package/src/components/FieldEditor/FieldEditor.stories.tsx +46 -26
- package/src/components/FieldEditor/FieldEditor.test.tsx +0 -1
- package/src/components/FieldEditor/FieldEditor.tsx +80 -80
- package/src/components/Form/AUDIT.md +17 -0
- package/src/components/Form/Form.stories.tsx +142 -254
- package/src/components/Form/Form.tsx +375 -99
- package/src/components/Form/FormField.tsx +306 -0
- package/src/components/Form/FormFieldComponent.stories.tsx +65 -0
- package/src/components/Form/FormFieldComponent.tsx +174 -0
- package/src/components/Form/FormFieldSet.tsx +144 -0
- package/src/components/Form/README.md +3 -0
- package/src/components/Form/fields/ArrayField.tsx +155 -0
- package/src/components/Form/fields/BooleanField.tsx +22 -0
- package/src/components/Form/fields/GeoPointField.tsx +121 -0
- package/src/components/Form/fields/MarkdownField.stories.tsx +206 -0
- package/src/components/Form/fields/MarkdownField.tsx +168 -0
- package/src/components/Form/fields/NumberField.tsx +39 -0
- package/src/components/Form/fields/RefField.tsx +229 -0
- package/src/components/Form/fields/SelectField.tsx +65 -0
- package/src/components/Form/fields/SelectOptionField.stories.tsx +66 -0
- package/src/components/Form/{custom/SelectOptionsInput.tsx → fields/SelectOptionField.tsx} +31 -25
- package/src/components/Form/fields/TextAreaField.tsx +38 -0
- package/src/components/Form/fields/TextField.tsx +38 -0
- package/src/components/Form/{custom/TupleInput.tsx → fields/TupleField.tsx} +16 -9
- package/src/components/Form/fields/index.ts +15 -0
- package/src/components/Form/index.ts +3 -4
- package/src/components/ObjectForm/ObjectForm.tsx +114 -0
- package/src/components/{ControlSection → ObjectForm}/index.ts +1 -1
- package/src/components/ObjectPicker/ObjectPicker.stories.tsx +212 -0
- package/src/components/ObjectPicker/ObjectPicker.tsx +202 -0
- package/src/components/ObjectPicker/index.ts +5 -0
- 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 +104 -0
- package/src/components/Settings/Settings.tsx +80 -0
- 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 +7 -0
- package/src/components/ViewEditor/ViewEditor.stories.tsx +126 -75
- package/src/components/ViewEditor/ViewEditor.test.tsx +10 -9
- package/src/components/ViewEditor/ViewEditor.tsx +326 -195
- package/src/components/index.ts +4 -1
- package/src/components/testing.tsx +24 -11
- package/src/hooks/index.ts +2 -3
- package/src/hooks/useFormHandler.ts +380 -0
- package/src/hooks/useKeyHandler.tsx +37 -0
- package/src/index.ts +0 -4
- package/src/translations.ts +70 -64
- package/src/util/field-type.ts +60 -0
- package/src/util/field.ts +25 -25
- package/src/util/formatting.ts +22 -22
- package/src/util/index.ts +2 -1
- package/src/util/properties.ts +18 -0
- package/src/util/refs.ts +17 -19
- package/dist/types/src/components/ControlSection/ControlSection.d.ts +0 -23
- package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +0 -1
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +0 -83
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +0 -1
- package/dist/types/src/components/ControlSection/index.d.ts +0 -2
- package/dist/types/src/components/ControlSection/index.d.ts.map +0 -1
- package/dist/types/src/components/Form/ArrayField.d.ts +0 -16
- package/dist/types/src/components/Form/ArrayField.d.ts.map +0 -1
- package/dist/types/src/components/Form/Defaults.d.ts +0 -14
- package/dist/types/src/components/Form/Defaults.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormActions.d.ts +0 -9
- package/dist/types/src/components/Form/FormActions.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormContent.d.ts +0 -63
- package/dist/types/src/components/Form/FormContent.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormContext.d.ts +0 -23
- package/dist/types/src/components/Form/FormContext.d.ts.map +0 -1
- package/dist/types/src/components/Form/Input.d.ts +0 -29
- package/dist/types/src/components/Form/Input.d.ts.map +0 -1
- package/dist/types/src/components/Form/RefField.d.ts +0 -18
- package/dist/types/src/components/Form/RefField.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +0 -4
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +0 -4
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +0 -78
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts +0 -6
- package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/index.d.ts +0 -4
- package/dist/types/src/components/Form/custom/index.d.ts.map +0 -1
- package/dist/types/src/components/Form/factory.d.ts +0 -8
- package/dist/types/src/components/Form/factory.d.ts.map +0 -1
- package/dist/types/src/hooks/useForm.d.ts +0 -67
- package/dist/types/src/hooks/useForm.d.ts.map +0 -1
- package/dist/types/src/hooks/useQueryRefOptions.d.ts +0 -23
- package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +0 -1
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +0 -8
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +0 -1
- package/dist/types/src/util/schema.d.ts +0 -3
- package/dist/types/src/util/schema.d.ts.map +0 -1
- package/src/components/ControlSection/ControlSection.stories.tsx +0 -39
- package/src/components/ControlSection/ControlSection.tsx +0 -153
- package/src/components/Form/ArrayField.tsx +0 -124
- package/src/components/Form/Defaults.tsx +0 -205
- package/src/components/Form/FormActions.tsx +0 -54
- package/src/components/Form/FormContent.tsx +0 -302
- package/src/components/Form/FormContext.tsx +0 -110
- package/src/components/Form/Input.tsx +0 -54
- package/src/components/Form/RefField.tsx +0 -299
- package/src/components/Form/custom/GeoPointInput.tsx +0 -80
- package/src/components/Form/custom/SelectOptionsInput.stories.tsx +0 -62
- package/src/components/Form/custom/index.ts +0 -7
- package/src/components/Form/factory.tsx +0 -31
- package/src/hooks/useForm.ts +0 -293
- package/src/hooks/useQueryRefOptions.ts +0 -53
- package/src/hooks/useRefQueryLookupHandler.ts +0 -39
- package/src/util/schema.ts +0 -14
|
@@ -2,122 +2,262 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
5
|
+
import { RegistryContext } from '@effect-atom/atom-react';
|
|
6
|
+
import * as Array from 'effect/Array';
|
|
7
|
+
import * as Match from 'effect/Match';
|
|
8
|
+
import * as Option from 'effect/Option';
|
|
9
|
+
import * as Schema from 'effect/Schema';
|
|
10
|
+
import React, { forwardRef, useCallback, useContext, useImperativeHandle, useMemo, useState } from 'react';
|
|
7
11
|
|
|
8
|
-
import { type SchemaRegistry } from '@dxos/echo
|
|
9
|
-
import {
|
|
12
|
+
import { Entity, Feed, Filter, Format, Obj, Query, QueryAST, Ref, type SchemaRegistry } from '@dxos/echo';
|
|
13
|
+
import { View } from '@dxos/echo';
|
|
14
|
+
import { EchoSchema, type JsonProp, isMutable, toJsonSchema } from '@dxos/echo/internal';
|
|
10
15
|
import { invariant } from '@dxos/invariant';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
16
|
+
import { useObject, useQuery } from '@dxos/react-client/echo';
|
|
17
|
+
import { IconButton, Input, Message, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
18
|
+
import { QueryForm, type QueryFormProps } from '@dxos/react-ui-components';
|
|
14
19
|
import { List } from '@dxos/react-ui-list';
|
|
15
|
-
import { cardSpacing } from '@dxos/react-ui-stack';
|
|
16
|
-
import { inputTextLabel, mx, subtleHover } from '@dxos/react-ui-theme';
|
|
17
20
|
import {
|
|
18
|
-
|
|
19
|
-
FieldSchema,
|
|
20
|
-
type FieldType,
|
|
21
|
+
ParentLabelAnnotation,
|
|
21
22
|
ProjectionModel,
|
|
22
23
|
VIEW_FIELD_LIMIT,
|
|
23
|
-
|
|
24
|
+
createEchoChangeCallback,
|
|
25
|
+
getTypenameFromQuery,
|
|
24
26
|
} from '@dxos/schema';
|
|
27
|
+
import { mx, osTranslations, subtleHover } from '@dxos/ui-theme';
|
|
25
28
|
|
|
26
|
-
import { translationKey } from '
|
|
27
|
-
import { FieldEditor } from '../FieldEditor';
|
|
28
|
-
import { Form, type FormProps, type InputComponent, type InputProps } from '../Form';
|
|
29
|
+
import { translationKey } from '#translations';
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
import { FieldEditor } from '../FieldEditor';
|
|
32
|
+
import {
|
|
33
|
+
Form,
|
|
34
|
+
type FormFieldComponent,
|
|
35
|
+
type FormFieldComponentProps,
|
|
36
|
+
FormFieldLabel,
|
|
37
|
+
type FormFieldMap,
|
|
38
|
+
type FormRootProps,
|
|
39
|
+
} from '../Form';
|
|
32
40
|
|
|
33
41
|
export type ViewEditorProps = ThemedClassName<
|
|
34
42
|
{
|
|
35
43
|
schema: Schema.Schema.AnyNoContext;
|
|
36
|
-
view:
|
|
37
|
-
|
|
38
|
-
registry?: SchemaRegistry;
|
|
39
|
-
readonly?: boolean;
|
|
44
|
+
view: View.View;
|
|
45
|
+
mode?: 'schema' | 'tag';
|
|
46
|
+
registry?: SchemaRegistry.SchemaRegistry;
|
|
40
47
|
showHeading?: boolean;
|
|
41
|
-
onQueryChanged?: (query: string) => void;
|
|
48
|
+
onQueryChanged?: (query: QueryAST.Query, target?: string) => void;
|
|
42
49
|
onDelete?: (fieldId: string) => void;
|
|
43
|
-
} & Pick<
|
|
50
|
+
} & Pick<QueryFormProps, 'types' | 'tags'> &
|
|
51
|
+
Pick<FormRootProps<any>, 'readonly' | 'db'>
|
|
44
52
|
>;
|
|
45
53
|
|
|
46
54
|
/**
|
|
47
55
|
* Schema-based object form.
|
|
48
56
|
*/
|
|
49
|
-
export const ViewEditor = (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
|
|
58
|
+
(
|
|
59
|
+
{
|
|
60
|
+
classNames,
|
|
61
|
+
schema,
|
|
62
|
+
view,
|
|
63
|
+
mode = 'schema',
|
|
64
|
+
registry,
|
|
65
|
+
db,
|
|
66
|
+
readonly,
|
|
67
|
+
showHeading = false,
|
|
68
|
+
types,
|
|
69
|
+
tags,
|
|
70
|
+
onQueryChanged,
|
|
71
|
+
onDelete,
|
|
72
|
+
},
|
|
73
|
+
forwardedRef,
|
|
74
|
+
) => {
|
|
75
|
+
const atomRegistry = useContext(RegistryContext);
|
|
76
|
+
const schemaReadonly = !isMutable(schema);
|
|
77
|
+
const { t } = useTranslation(translationKey);
|
|
78
|
+
|
|
79
|
+
const projectionModel = useMemo(() => {
|
|
80
|
+
// Use reactive and mutable version of json schema when schema is mutable.
|
|
81
|
+
const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
|
|
82
|
+
|
|
83
|
+
// Always use createEchoChangeCallback since the view is ECHO-backed.
|
|
84
|
+
// Pass schema only when mutable to allow schema mutations.
|
|
85
|
+
const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : undefined);
|
|
86
|
+
|
|
87
|
+
const model = new ProjectionModel({
|
|
88
|
+
registry: atomRegistry,
|
|
89
|
+
view,
|
|
90
|
+
baseSchema: jsonSchema,
|
|
91
|
+
change,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return model;
|
|
95
|
+
}, [atomRegistry, schema, view]);
|
|
96
|
+
|
|
97
|
+
useImperativeHandle(forwardedRef, () => projectionModel, [projectionModel]);
|
|
98
|
+
|
|
99
|
+
const queueTarget = Match.value(view.query.ast).pipe(
|
|
100
|
+
Match.when({ type: 'from' }, ({ from }) => {
|
|
101
|
+
if (from._tag !== 'scope') {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
return Option.fromNullable(from.scope.queues).pipe(
|
|
105
|
+
Option.flatMap((queues) => Array.head(queues)),
|
|
106
|
+
Option.map(String),
|
|
107
|
+
Option.getOrUndefined,
|
|
108
|
+
);
|
|
109
|
+
}),
|
|
110
|
+
Match.orElse(() => undefined),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const feeds = useQuery(db, Filter.type(Feed.Feed));
|
|
114
|
+
|
|
115
|
+
const targetRef = useMemo(() => {
|
|
116
|
+
if (!queueTarget) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
const feed = feeds.find((feed) => Feed.getQueueDxn(feed)?.toString() === queueTarget);
|
|
120
|
+
return feed ? Ref.fromDXN(Entity.getDXN(feed)) : undefined;
|
|
121
|
+
}, [queueTarget, feeds]);
|
|
122
|
+
|
|
123
|
+
const viewSchema = useMemo(() => {
|
|
124
|
+
const base = Schema.Struct({
|
|
125
|
+
query:
|
|
126
|
+
mode === 'schema'
|
|
127
|
+
? Format.URL.annotations({ title: 'Record type' })
|
|
128
|
+
: QueryAST.Query.annotations({ title: 'Query' }),
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (mode === 'tag') {
|
|
132
|
+
return Schema.Struct({
|
|
133
|
+
...base.fields,
|
|
134
|
+
// TODO(wittjosiah): Replace Type.Feed with Dataset.Dataset when Ref.Ref supports unions.
|
|
135
|
+
target: Ref.Ref(Feed.Feed).pipe(
|
|
136
|
+
Schema.annotations({ title: 'Target Feed' }),
|
|
137
|
+
ParentLabelAnnotation.set(true),
|
|
138
|
+
Schema.optional,
|
|
139
|
+
),
|
|
140
|
+
}).pipe(Schema.mutable);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return base.pipe(Schema.mutable);
|
|
144
|
+
}, [mode]);
|
|
145
|
+
|
|
146
|
+
// TODO(burdon): Need to warn user of possible consequences of editing.
|
|
147
|
+
// TODO(burdon): Settings should have domain name owned by user.
|
|
148
|
+
const viewValues = useMemo(
|
|
149
|
+
() => ({
|
|
150
|
+
query: mode === 'schema' ? getTypenameFromQuery(view.query.ast) : view.query.ast,
|
|
151
|
+
target: targetRef,
|
|
152
|
+
}),
|
|
153
|
+
[mode, view.query.ast, targetRef],
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const fieldMap = useMemo<FormFieldMap | undefined>(
|
|
157
|
+
() => (mode === 'tag' ? customFields({ types, tags }) : undefined),
|
|
158
|
+
[mode, types, tags],
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const handleUpdate = useCallback(
|
|
162
|
+
(values: any) => {
|
|
163
|
+
const targetValue = values.target;
|
|
164
|
+
let queueDxn: string | undefined;
|
|
165
|
+
|
|
166
|
+
if (Ref.isRef(targetValue)) {
|
|
167
|
+
const feedDxn = targetValue.dxn.toString();
|
|
168
|
+
const feed = feeds.find((feed) => Obj.getDXN(feed).toString() === feedDxn);
|
|
169
|
+
if (feed) {
|
|
170
|
+
queueDxn = Feed.getQueueDxn(feed)?.toString();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// TODO(wittjosiah): Deep-clone the AST to plain JS or ECHO proxy arrays become objects with numeric keys.
|
|
175
|
+
const query =
|
|
176
|
+
mode === 'schema'
|
|
177
|
+
? Query.select(Filter.typename(values.query)).ast
|
|
178
|
+
: JSON.parse(JSON.stringify(values.query));
|
|
179
|
+
onQueryChanged?.(query, queueDxn);
|
|
180
|
+
},
|
|
181
|
+
[onQueryChanged, mode, feeds],
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const handleDelete = useCallback(
|
|
185
|
+
(fieldId: string) => {
|
|
186
|
+
invariant(!readonly);
|
|
187
|
+
onDelete?.(fieldId);
|
|
188
|
+
},
|
|
189
|
+
[onDelete, readonly],
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
<div className={mx(classNames)}>
|
|
194
|
+
{/* If readonly is set, then the callout is not needed. */}
|
|
195
|
+
{schemaReadonly && !readonly && (
|
|
196
|
+
<Message.Root valence='info' classNames='my-form-padding'>
|
|
197
|
+
<Message.Title>{t('system-schema.description')}</Message.Title>
|
|
198
|
+
</Message.Root>
|
|
199
|
+
)}
|
|
200
|
+
|
|
201
|
+
{/* TODO(burdon): Is the form read-only or just the schema? */}
|
|
202
|
+
<Form.Root schema={viewSchema} values={viewValues} fieldMap={fieldMap} db={db} onValuesChanged={handleUpdate}>
|
|
203
|
+
<Form.FieldSet />
|
|
204
|
+
|
|
205
|
+
<FormFieldLabel label={t('fields.label')} asChild />
|
|
206
|
+
<FieldList
|
|
207
|
+
schema={schema}
|
|
208
|
+
view={view}
|
|
209
|
+
registry={registry}
|
|
210
|
+
readonly={readonly}
|
|
211
|
+
showHeading={showHeading}
|
|
212
|
+
onDelete={handleDelete}
|
|
213
|
+
/>
|
|
214
|
+
</Form.Root>
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
},
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
type FieldListProps = Pick<ViewEditorProps, 'schema' | 'view' | 'registry' | 'readonly' | 'showHeading' | 'onDelete'>;
|
|
221
|
+
|
|
222
|
+
const FieldList = ({ schema, view, registry, readonly, showHeading = false, onDelete }: FieldListProps) => {
|
|
223
|
+
const atomRegistry = useContext(RegistryContext);
|
|
62
224
|
const schemaReadonly = !isMutable(schema);
|
|
63
225
|
const { t } = useTranslation(translationKey);
|
|
226
|
+
|
|
227
|
+
// Subscribe to view changes for reactivity.
|
|
228
|
+
const [viewSnapshot] = useObject(view);
|
|
229
|
+
|
|
64
230
|
const projectionModel = useMemo(() => {
|
|
65
231
|
// Use reactive and mutable version of json schema when schema is mutable.
|
|
66
232
|
const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
|
|
67
|
-
return new ProjectionModel(jsonSchema, view.projection);
|
|
68
|
-
}, [schema, view.projection]);
|
|
69
|
-
const [expandedField, setExpandedField] = useState<FieldType['id']>();
|
|
70
|
-
|
|
71
|
-
const serializedQuery = Match.value(kind).pipe(
|
|
72
|
-
Match.when('basic', () => typenameFromQuery(view.query)),
|
|
73
|
-
Match.when('advanced', () => {
|
|
74
|
-
if (view.query.type !== 'select') {
|
|
75
|
-
return '';
|
|
76
|
-
}
|
|
77
233
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
Match.exhaustive,
|
|
82
|
-
);
|
|
234
|
+
// Always use createEchoChangeCallback since the view is ECHO-backed.
|
|
235
|
+
// Pass schema only when mutable to allow schema mutations.
|
|
236
|
+
const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : undefined);
|
|
83
237
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}).pipe(Schema.mutable);
|
|
91
|
-
}, [kind]);
|
|
92
|
-
// TODO(burdon): Need to warn user of possible consequences of editing.
|
|
93
|
-
// TODO(burdon): Settings should have domain name owned by user.
|
|
94
|
-
const viewValues = useMemo(() => ({ query: serializedQuery }), [serializedQuery]);
|
|
238
|
+
const model = new ProjectionModel({
|
|
239
|
+
registry: atomRegistry,
|
|
240
|
+
view,
|
|
241
|
+
baseSchema: jsonSchema,
|
|
242
|
+
change,
|
|
243
|
+
});
|
|
95
244
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
setExpandedField((prevExpandedFieldId) => (prevExpandedFieldId === field.id ? undefined : field.id));
|
|
99
|
-
},
|
|
100
|
-
[readonly],
|
|
101
|
-
);
|
|
245
|
+
return model;
|
|
246
|
+
}, [atomRegistry, schema, view]);
|
|
102
247
|
|
|
103
|
-
|
|
248
|
+
const [expandedField, setExpandedField] = useState<View.FieldType['id']>();
|
|
104
249
|
|
|
105
250
|
const handleAdd = useCallback(() => {
|
|
106
251
|
invariant(!readonly);
|
|
107
252
|
const field = projectionModel.createFieldProjection();
|
|
108
253
|
setExpandedField(field.id);
|
|
109
|
-
}, [
|
|
254
|
+
}, [projectionModel, readonly]);
|
|
110
255
|
|
|
111
|
-
const
|
|
112
|
-
(
|
|
113
|
-
|
|
114
|
-
requestAnimationFrame(() => {
|
|
115
|
-
if (serializedQuery !== query && !readonly) {
|
|
116
|
-
onQueryChanged?.(query);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
256
|
+
const handleToggleField = useCallback(
|
|
257
|
+
(field: View.FieldType) => {
|
|
258
|
+
setExpandedField((prevExpandedFieldId) => (prevExpandedFieldId === field.id ? undefined : field.id));
|
|
119
259
|
},
|
|
120
|
-
[
|
|
260
|
+
[readonly],
|
|
121
261
|
);
|
|
122
262
|
|
|
123
263
|
const handleDelete = useCallback(
|
|
@@ -135,13 +275,15 @@ export const ViewEditor = ({
|
|
|
135
275
|
const handleMove = useCallback(
|
|
136
276
|
(fromIndex: number, toIndex: number) => {
|
|
137
277
|
invariant(!readonly);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
278
|
+
Obj.update(view, (view) => {
|
|
279
|
+
// NOTE(ZaymonFC): Using arrayMove here causes a race condition with the kanban model.
|
|
280
|
+
const fields = [...view.projection.fields];
|
|
281
|
+
const [moved] = fields.splice(fromIndex, 1);
|
|
282
|
+
fields.splice(toIndex, 0, moved);
|
|
283
|
+
view.projection.fields = fields;
|
|
284
|
+
});
|
|
143
285
|
},
|
|
144
|
-
[view
|
|
286
|
+
[view, readonly],
|
|
145
287
|
);
|
|
146
288
|
|
|
147
289
|
const handleClose = useCallback(() => setExpandedField(undefined), []);
|
|
@@ -162,128 +304,117 @@ export const ViewEditor = ({
|
|
|
162
304
|
[projectionModel],
|
|
163
305
|
);
|
|
164
306
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
? {
|
|
169
|
-
['query' satisfies keyof Schema.Schema.Type<typeof viewSchema>]: (props: InputProps) => {
|
|
170
|
-
const handleChange = useCallback(
|
|
171
|
-
(text: string) => props.onValueChange('string', text),
|
|
172
|
-
[props.onValueChange],
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
// TODO(wittjosiah): Add label & input styles.
|
|
176
|
-
return <QueryEditor space={space} initialValue={props.getValue()} onChange={handleChange} />;
|
|
177
|
-
},
|
|
178
|
-
}
|
|
179
|
-
: {},
|
|
180
|
-
[],
|
|
181
|
-
);
|
|
307
|
+
if (!viewSnapshot) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
182
310
|
|
|
183
311
|
return (
|
|
184
|
-
<
|
|
185
|
-
{
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
{
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
>
|
|
226
|
-
<div role='none' className={mx(subtleHover, listItemGrid, 'rounded-sm cursor-pointer min-bs-10')}>
|
|
227
|
-
<List.ItemDragHandle disabled={readonly} />
|
|
228
|
-
<List.ItemTitle classNames={hidden && 'text-subdued'} onClick={() => handleToggleField(field)}>
|
|
229
|
-
{field.path}
|
|
230
|
-
</List.ItemTitle>
|
|
231
|
-
<List.ItemButton
|
|
232
|
-
label={t(hidden ? 'show field label' : 'hide field label')}
|
|
233
|
-
data-testid={hidden ? 'show-field-button' : 'hide-field-button'}
|
|
234
|
-
icon={hidden ? 'ph--eye-closed--regular' : 'ph--eye--regular'}
|
|
235
|
-
autoHide={false}
|
|
236
|
-
disabled={readonly || (!hidden && projectionModel.fields.length <= 1)}
|
|
237
|
-
onClick={() => (hidden ? handleShow(field.path) : handleHide(field.id))}
|
|
238
|
-
/>
|
|
239
|
-
{/* TODO(burdon): Remove unless implement undo. */}
|
|
312
|
+
<List.Root<View.FieldType>
|
|
313
|
+
items={viewSnapshot.projection.fields as View.FieldType[]}
|
|
314
|
+
isItem={Schema.is(View.FieldSchema)}
|
|
315
|
+
getId={(field) => field.id}
|
|
316
|
+
onMove={readonly ? undefined : handleMove}
|
|
317
|
+
readonly={readonly}
|
|
318
|
+
>
|
|
319
|
+
{({ items: fields }) => (
|
|
320
|
+
<>
|
|
321
|
+
{showHeading && <h3 className='text-sm'>{t('field-path.label')}</h3>}
|
|
322
|
+
<div role='list' className='grid grid-cols-[min-content_1fr_min-content_min-content_min-content]'>
|
|
323
|
+
{fields?.map((field) => {
|
|
324
|
+
const hidden = field.visible === false;
|
|
325
|
+
return (
|
|
326
|
+
<List.Item<View.FieldType>
|
|
327
|
+
key={field.id}
|
|
328
|
+
item={field}
|
|
329
|
+
classNames={'grid grid-cols-subgrid col-span-5'}
|
|
330
|
+
aria-expanded={expandedField === field.id}
|
|
331
|
+
>
|
|
332
|
+
<div
|
|
333
|
+
className={mx(
|
|
334
|
+
subtleHover,
|
|
335
|
+
'grid grid-cols-subgrid col-span-5',
|
|
336
|
+
'rounded-xs cursor-pointer min-h-10',
|
|
337
|
+
)}
|
|
338
|
+
>
|
|
339
|
+
<List.ItemDragHandle disabled={readonly || schemaReadonly} />
|
|
340
|
+
<List.ItemTitle classNames={hidden && 'text-subdued'} onClick={() => handleToggleField(field)}>
|
|
341
|
+
{field.path}
|
|
342
|
+
</List.ItemTitle>
|
|
343
|
+
<List.ItemIconButton
|
|
344
|
+
label={t(hidden ? 'show-field.label' : 'hide-field.label')}
|
|
345
|
+
data-testid={hidden ? 'show-field-button' : 'hide-field-button'}
|
|
346
|
+
icon={hidden ? 'ph--eye-closed--regular' : 'ph--eye--regular'}
|
|
347
|
+
autoHide={false}
|
|
348
|
+
disabled={readonly || (!hidden && projectionModel.getFields().length <= 1)}
|
|
349
|
+
onClick={() => (hidden ? handleShow(field.path) : handleHide(field.id))}
|
|
350
|
+
/>
|
|
351
|
+
{!readonly && (
|
|
352
|
+
<>
|
|
240
353
|
<List.ItemDeleteButton
|
|
241
|
-
label={t('delete
|
|
354
|
+
label={t('delete-field.label')}
|
|
242
355
|
autoHide={false}
|
|
243
|
-
disabled={readonly || schemaReadonly ||
|
|
356
|
+
disabled={readonly || schemaReadonly || viewSnapshot.projection.fields.length <= 1}
|
|
244
357
|
onClick={() => handleDelete(field.id)}
|
|
245
358
|
data-testid='field.delete'
|
|
246
359
|
/>
|
|
247
|
-
<
|
|
360
|
+
<List.ItemIconButton
|
|
248
361
|
iconOnly
|
|
249
362
|
variant='ghost'
|
|
250
|
-
label={t('toggle
|
|
363
|
+
label={t('toggle-expand.label', { ns: osTranslations })}
|
|
251
364
|
icon={expandedField === field.id ? 'ph--caret-down--regular' : 'ph--caret-right--regular'}
|
|
252
365
|
onClick={() => handleToggleField(field)}
|
|
366
|
+
data-testid='field.toggle'
|
|
253
367
|
/>
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
</
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
368
|
+
</>
|
|
369
|
+
)}
|
|
370
|
+
</div>
|
|
371
|
+
{expandedField === field.id && !readonly && (
|
|
372
|
+
<div className='col-span-full mt-1 mb-1 border border-separator rounded-md'>
|
|
373
|
+
<FieldEditor
|
|
374
|
+
readonly={readonly || schemaReadonly}
|
|
375
|
+
registry={registry}
|
|
376
|
+
projection={projectionModel}
|
|
377
|
+
field={field}
|
|
378
|
+
onSave={handleClose}
|
|
379
|
+
/>
|
|
380
|
+
</div>
|
|
381
|
+
)}
|
|
382
|
+
</List.Item>
|
|
383
|
+
);
|
|
384
|
+
})}
|
|
385
|
+
</div>
|
|
386
|
+
{!readonly && !expandedField && (
|
|
387
|
+
<div className='my-form-padding'>
|
|
388
|
+
<IconButton
|
|
389
|
+
icon='ph--plus--regular'
|
|
390
|
+
label={t('add-property-button.label')}
|
|
391
|
+
onClick={handleAdd}
|
|
392
|
+
disabled={viewSnapshot.projection.fields.length >= VIEW_FIELD_LIMIT}
|
|
393
|
+
classNames='w-full'
|
|
394
|
+
/>
|
|
395
|
+
</div>
|
|
271
396
|
)}
|
|
272
|
-
|
|
273
|
-
</div>
|
|
274
|
-
|
|
275
|
-
{!readonly && !expandedField && (
|
|
276
|
-
<div role='none' className={outerSpacing ? cardSpacing : 'mlb-cardSpacingBlock'}>
|
|
277
|
-
<IconButton
|
|
278
|
-
icon='ph--plus--regular'
|
|
279
|
-
label={t('button add property')}
|
|
280
|
-
onClick={readonly ? undefined : handleAdd}
|
|
281
|
-
// TODO(burdon): Show field limit in ux (not tooltip).
|
|
282
|
-
disabled={view.projection.fields.length >= VIEW_FIELD_LIMIT}
|
|
283
|
-
classNames='is-full'
|
|
284
|
-
/>
|
|
285
|
-
</div>
|
|
397
|
+
</>
|
|
286
398
|
)}
|
|
287
|
-
</
|
|
399
|
+
</List.Root>
|
|
288
400
|
);
|
|
289
401
|
};
|
|
402
|
+
|
|
403
|
+
const customFields = ({
|
|
404
|
+
types,
|
|
405
|
+
tags,
|
|
406
|
+
}: Pick<ViewEditorProps, 'types' | 'tags'>): Record<string, FormFieldComponent> => ({
|
|
407
|
+
query: ({ type, readonly, label, getValue, onValueChange }: FormFieldComponentProps) => {
|
|
408
|
+
const handleChange = useCallback<NonNullable<QueryFormProps['onChange']>>(
|
|
409
|
+
(query) => onValueChange(type, query.ast),
|
|
410
|
+
[onValueChange],
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
return (
|
|
414
|
+
<Input.Root>
|
|
415
|
+
<FormFieldLabel readonly={readonly} label={label} />
|
|
416
|
+
<QueryForm initialQuery={getValue()} types={types} tags={tags} onChange={handleChange} />
|
|
417
|
+
</Input.Root>
|
|
418
|
+
);
|
|
419
|
+
},
|
|
420
|
+
});
|
package/src/components/index.ts
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
export * from './ControlSection';
|
|
6
5
|
export * from './FieldEditor';
|
|
7
6
|
export * from './Form';
|
|
7
|
+
export * from './ObjectForm';
|
|
8
|
+
export * from './ObjectPicker';
|
|
9
|
+
export * from './ObjectProperties';
|
|
10
|
+
export * from './Settings';
|
|
8
11
|
export * from './ViewEditor';
|
|
@@ -5,27 +5,40 @@
|
|
|
5
5
|
import React, { type PropsWithChildren } from 'react';
|
|
6
6
|
|
|
7
7
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { mx, textBlockWidth } from '@dxos/react-ui-theme';
|
|
8
|
+
import { Syntax } from '@dxos/react-ui-syntax-highlighter';
|
|
9
|
+
import { composableProps, slottable } from '@dxos/ui-theme';
|
|
11
10
|
|
|
12
|
-
type TestLayoutProps =
|
|
11
|
+
type TestLayoutProps = PropsWithChildren<{ json?: any }>;
|
|
13
12
|
|
|
14
|
-
export const TestLayout = ({
|
|
13
|
+
export const TestLayout = ({ children, json }: TestLayoutProps) => {
|
|
15
14
|
return (
|
|
16
|
-
<div className='
|
|
17
|
-
<
|
|
18
|
-
<
|
|
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>
|
|
26
|
+
</TestPanel>
|
|
19
27
|
</div>
|
|
20
28
|
);
|
|
21
29
|
};
|
|
22
30
|
|
|
23
31
|
type TestPanelProps = ThemedClassName<PropsWithChildren>;
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
return
|
|
27
|
-
}
|
|
33
|
+
const TestPanel = slottable<HTMLDivElement, TestPanelProps>(({ children }, forwardedRef) => {
|
|
34
|
+
return (
|
|
35
|
+
<div {...composableProps({ classNames: 'dx-container bg-modal-surface rounded-md' })} ref={forwardedRef}>
|
|
36
|
+
{children}
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
});
|
|
28
40
|
|
|
29
41
|
// Symbol for accessing debug objects in tests.
|
|
30
42
|
export const VIEW_EDITOR_DEBUG_SYMBOL = Symbol('viewEditorDebug');
|
|
31
43
|
export const FIELD_EDITOR_DEBUG_SYMBOL = Symbol('fieldEditorDebug');
|
|
44
|
+
export const OBJECT_PROPERTIES_DEBUG_SYMBOL = Symbol('objectPropertiesDebug');
|
package/src/hooks/index.ts
CHANGED