@dxos/react-ui-form 0.8.2-main.f11618f → 0.8.2-main.fbd8ed0

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 (81) hide show
  1. package/dist/lib/browser/index.mjs +731 -573
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +748 -598
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +731 -573
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +1 -1
  11. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
  13. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.d.ts +4 -4
  15. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.stories.d.ts +33 -32
  17. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
  19. package/dist/types/src/components/Form/FormContent.d.ts +3 -3
  20. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
  21. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
  22. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  23. package/dist/types/src/components/Form/RefField.d.ts +7 -18
  24. package/dist/types/src/components/Form/RefField.d.ts.map +1 -1
  25. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  26. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
  27. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  29. package/dist/types/src/components/Form/factory.d.ts +1 -1
  30. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  31. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  32. package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
  33. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +2 -2
  34. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  35. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/deprecated/Form.d.ts +2 -2
  37. package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
  38. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
  39. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
  40. package/dist/types/src/components/testing.d.ts.map +1 -1
  41. package/dist/types/src/hooks/index.d.ts +2 -0
  42. package/dist/types/src/hooks/index.d.ts.map +1 -1
  43. package/dist/types/src/hooks/useForm.d.ts +2 -2
  44. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  45. package/dist/types/src/hooks/useQueryRefOptions.d.ts +23 -0
  46. package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -0
  47. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +8 -0
  48. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -0
  49. package/dist/types/src/util/field.d.ts.map +1 -1
  50. package/dist/types/src/util/formatting.d.ts.map +1 -1
  51. package/dist/types/src/util/index.d.ts +2 -0
  52. package/dist/types/src/util/index.d.ts.map +1 -1
  53. package/dist/types/src/util/refs.d.ts +9 -0
  54. package/dist/types/src/util/refs.d.ts.map +1 -0
  55. package/dist/types/src/util/schema.d.ts +3 -0
  56. package/dist/types/src/util/schema.d.ts.map +1 -0
  57. package/dist/types/tsconfig.tsbuildinfo +1 -1
  58. package/package.json +26 -25
  59. package/src/components/ControlSection/ControlSection.stories.tsx +1 -1
  60. package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
  61. package/src/components/Form/ArrayField.tsx +10 -16
  62. package/src/components/Form/Defaults.tsx +4 -1
  63. package/src/components/Form/Form.stories.tsx +48 -42
  64. package/src/components/Form/Form.tsx +4 -4
  65. package/src/components/Form/FormContent.tsx +49 -22
  66. package/src/components/Form/FormContext.tsx +3 -1
  67. package/src/components/Form/Input.tsx +3 -9
  68. package/src/components/Form/RefField.tsx +147 -101
  69. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +6 -5
  70. package/src/components/Form/factory.tsx +1 -1
  71. package/src/components/Form/index.ts +0 -1
  72. package/src/components/ViewEditor/ViewEditor.stories.tsx +5 -4
  73. package/src/components/ViewEditor/ViewEditor.tsx +23 -20
  74. package/src/components/deprecated/Form.tsx +6 -6
  75. package/src/hooks/index.ts +3 -1
  76. package/src/hooks/useForm.ts +4 -3
  77. package/src/hooks/useQueryRefOptions.ts +53 -0
  78. package/src/hooks/useRefQueryLookupHandler.ts +41 -0
  79. package/src/util/index.ts +3 -1
  80. package/src/util/refs.ts +38 -0
  81. package/src/util/schema.ts +14 -0
@@ -2,11 +2,10 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { pipe } from 'effect';
5
+ import { Schema, SchemaAST, pipe } from 'effect';
6
6
  import { capitalize } from 'effect/String';
7
7
  import React, { useMemo } from 'react';
8
8
 
9
- import { AST, S } from '@dxos/echo-schema';
10
9
  import { createJsonPath, findNode, getDiscriminatedType, isDiscriminatedUnion } from '@dxos/effect';
11
10
  import { mx } from '@dxos/react-ui-theme';
12
11
  import { getSchemaProperties, type SchemaProperty } from '@dxos/schema';
@@ -17,8 +16,10 @@ import { SelectInput } from './Defaults';
17
16
  import { type ComponentLookup } from './Form';
18
17
  import { useInputProps, useFormValues } from './FormContext';
19
18
  import { type InputComponent } from './Input';
20
- import { RefField, type QueryRefOptions } from './RefField';
19
+ import { RefField } from './RefField';
21
20
  import { getInputComponent } from './factory';
21
+ import { type QueryRefOptions } from '../../hooks';
22
+ import { getRefProps } from '../../util';
22
23
 
23
24
  export type FormFieldProps = {
24
25
  property: SchemaProperty<any>;
@@ -49,9 +50,13 @@ export const FormField = ({
49
50
  [examples, description],
50
51
  );
51
52
 
53
+ //
54
+ // Registry and Custom.
55
+ //
56
+
52
57
  const FoundComponent = lookupComponent?.({
53
58
  prop: name,
54
- schema: S.make(ast),
59
+ schema: Schema.make(ast),
55
60
  inputProps: {
56
61
  type,
57
62
  format,
@@ -82,10 +87,40 @@ export const FormField = ({
82
87
  );
83
88
  }
84
89
 
90
+ //
91
+ // Refs.
92
+ //
93
+
94
+ const refProps = getRefProps(property);
95
+ if (refProps) {
96
+ return (
97
+ <RefField
98
+ ast={refProps.ast}
99
+ array={refProps.isArray}
100
+ type={type}
101
+ format={format}
102
+ label={label}
103
+ placeholder={placeholder}
104
+ disabled={readonly}
105
+ inputOnly={inline}
106
+ onQueryRefOptions={onQueryRefOptions}
107
+ {...inputProps}
108
+ />
109
+ );
110
+ }
111
+
112
+ //
113
+ // Arrays.
114
+ //
115
+
85
116
  if (array) {
86
117
  return <ArrayField property={property} path={path} inputProps={inputProps} readonly={readonly} Custom={Custom} />;
87
118
  }
88
119
 
120
+ //
121
+ // Standard Inputs.
122
+ //
123
+
89
124
  const InputComponent = getInputComponent(type, format);
90
125
  if (InputComponent) {
91
126
  return (
@@ -103,6 +138,10 @@ export const FormField = ({
103
138
  );
104
139
  }
105
140
 
141
+ //
142
+ // Select.
143
+ //
144
+
106
145
  if (options) {
107
146
  return (
108
147
  <div role='none'>
@@ -120,34 +159,22 @@ export const FormField = ({
120
159
  );
121
160
  }
122
161
 
123
- // TODO(ZaymonFC): Extract this to it's own component.
124
- if (format === 'ref') {
125
- return (
126
- <RefField
127
- ast={ast}
128
- type={type}
129
- label={label}
130
- readonly={readonly}
131
- placeholder={placeholder}
132
- inline={inline}
133
- onQueryRefOptions={onQueryRefOptions}
134
- inputProps={inputProps}
135
- />
136
- );
137
- }
162
+ //
163
+ // Nested Objects.
164
+ //
138
165
 
139
166
  if (type === 'object') {
140
167
  const baseNode = findNode(ast, isDiscriminatedUnion);
141
168
  const typeLiteral = baseNode
142
169
  ? getDiscriminatedType(baseNode, inputProps.getValue() as any)
143
- : findNode(ast, AST.isTypeLiteral);
170
+ : findNode(ast, SchemaAST.isTypeLiteral);
144
171
 
145
172
  if (typeLiteral) {
146
173
  return (
147
174
  <div role='none'>
148
175
  {!inline && <h3 className='text-lg mbs-2 mbe-1'>{label}</h3>}
149
176
  <FormFields
150
- schema={S.make(typeLiteral)}
177
+ schema={Schema.make(typeLiteral)}
151
178
  path={path}
152
179
  readonly={readonly}
153
180
  onQueryRefOptions={onQueryRefOptions}
@@ -163,7 +190,7 @@ export const FormField = ({
163
190
  };
164
191
 
165
192
  export type FormContentProps = {
166
- schema: S.Schema.All;
193
+ schema: Schema.Schema.All;
167
194
  path?: (string | number)[];
168
195
  filter?: (props: SchemaProperty<any>[]) => SchemaProperty<any>[];
169
196
  sort?: string[];
@@ -76,7 +76,9 @@ export const FormProvider = ({
76
76
  const keyIsEnter = event.key === 'Enter';
77
77
  const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
78
78
  const inputIsTextarea = (event.target as HTMLElement).tagName.toLowerCase() === 'textarea';
79
- const inputOptOut = (event.target as HTMLElement).hasAttribute('data-no-submit');
79
+ const inputOptOut =
80
+ (event.target as HTMLElement).hasAttribute('data-no-submit') ||
81
+ (event.target as HTMLElement).closest('[data-no-submit]') !== null;
80
82
 
81
83
  // Regular inputs: Submit on Enter (no modifiers).
82
84
  const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
@@ -37,15 +37,9 @@ export const InputHeader = ({ children, error }: InputHeaderProps) => {
37
37
  <div role='none' className='flex justify-between items-center mb-1'>
38
38
  {children}
39
39
  {error && (
40
- <Tooltip.Root>
41
- <Tooltip.Trigger asChild>
42
- <Icon icon='ph--warning--regular' size={4} classNames={errorText} />
43
- </Tooltip.Trigger>
44
- <Tooltip.Content side='bottom'>
45
- <Tooltip.Arrow />
46
- {error}
47
- </Tooltip.Content>
48
- </Tooltip.Root>
40
+ <Tooltip.Trigger asChild content={error} side='bottom'>
41
+ <Icon icon='ph--warning--regular' size={4} classNames={errorText} />
42
+ </Tooltip.Trigger>
49
43
  )}
50
44
  </div>
51
45
  );
@@ -2,149 +2,195 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React, { useEffect, useState } from 'react';
5
+ import { type SchemaAST } from 'effect';
6
+ import React, { useCallback, useMemo, type FocusEvent } from 'react';
6
7
 
7
8
  import {
8
- type AST,
9
9
  Expando,
10
10
  getTypeAnnotation,
11
+ Ref,
11
12
  ReferenceAnnotationId,
12
13
  type ReferenceAnnotationValue,
13
- type TypeAnnotation,
14
14
  } from '@dxos/echo-schema';
15
- import { findAnnotation, type SimpleType } from '@dxos/effect';
15
+ import { findAnnotation } from '@dxos/effect';
16
16
  import { DXN } from '@dxos/keys';
17
- import { refFromDXN, RefImpl } from '@dxos/live-object';
18
- import { log } from '@dxos/log';
19
- import { type MaybePromise } from '@dxos/util';
20
-
21
- import { SelectInput, TextInput } from './Defaults';
22
- import { type FormInputStateProps } from './FormContext';
23
-
24
- export type QueryRefOptions = (type: TypeAnnotation) => MaybePromise<{ dxn: DXN; label?: string }[]>;
25
-
26
- type RefFieldProps = {
27
- ast: AST.AST;
28
- type: SimpleType;
29
- label: string;
30
- readonly?: boolean;
31
- placeholder?: string;
32
- inline?: boolean;
17
+ import { Input } from '@dxos/react-ui';
18
+ import { TagPicker, type TagPickerMode, type TagPickerItemData } from '@dxos/react-ui-tag-picker';
19
+ import { isNonNullable } from '@dxos/util';
20
+
21
+ import { TextInput } from './Defaults';
22
+ import { InputHeader, type InputProps } from './Input';
23
+ import { type QueryRefOptions, useQueryRefOptions } from '../../hooks';
24
+
25
+ type RefFieldProps = InputProps & {
26
+ ast?: SchemaAST.AST;
27
+ array?: boolean;
33
28
  onQueryRefOptions?: QueryRefOptions;
34
- inputProps: FormInputStateProps;
35
29
  };
36
30
 
37
31
  export const RefField = ({
38
- ast,
39
32
  type,
40
33
  label,
41
- readonly,
34
+ disabled,
42
35
  placeholder,
43
- inline,
36
+ inputOnly,
37
+ array,
38
+ ast,
39
+ getValue,
40
+ onBlur,
44
41
  onQueryRefOptions,
45
- inputProps,
42
+ onValueChange,
43
+ ...restInputProps
46
44
  }: RefFieldProps) => {
47
- const { getValue, onValueChange, ...restInputProps } = inputProps;
48
- const refTypeInfo = findAnnotation<ReferenceAnnotationValue>(ast, ReferenceAnnotationId);
49
- const [refOptions, setRefOptions] = useState<Array<{ value: string; label?: string }>>([]);
50
- const [loading, setLoading] = useState(false);
51
-
52
- useEffect(() => {
53
- if (!refTypeInfo || !onQueryRefOptions) {
54
- return;
55
- }
45
+ const refTypeInfo = useMemo(
46
+ () => (ast ? findAnnotation<ReferenceAnnotationValue>(ast, ReferenceAnnotationId) : undefined),
47
+ [ast],
48
+ );
49
+ const { options: availableOptions, loading: _loading } = useQueryRefOptions({ refTypeInfo, onQueryRefOptions });
50
+
51
+ if ((refTypeInfo && refTypeInfo?.typename === getTypeAnnotation(Expando)?.typename) || !onQueryRefOptions) {
52
+ // If ref type is expando, fall back to taking a DXN in string format.
53
+ return (
54
+ <RefFieldFallback
55
+ {...{ type, label, placeholder, disabled, inputOnly, getValue, onBlur, onValueChange, ...restInputProps }}
56
+ />
57
+ );
58
+ }
59
+
60
+ const handleGetValue = useCallback((): TagPickerItemData[] => {
61
+ const formValue = getValue();
56
62
 
57
- const fetchOptions = async () => {
58
- setLoading(true);
59
- try {
60
- const options = await onQueryRefOptions(refTypeInfo);
61
- setRefOptions(
62
- options.map((option) => ({
63
- label: option.label,
64
- value: option.dxn.toString(),
65
- })),
66
- );
67
- } catch (error) {
68
- log.error('Failed to fetch ref options:', error);
69
- setRefOptions([]);
70
- } finally {
71
- setLoading(false);
63
+ const unknownToRefOption = (val: unknown) => {
64
+ if (Ref.isRef(val)) {
65
+ const dxnString = val.dxn.toString();
66
+ const matchingOption = availableOptions.find((option) => option.id === dxnString);
67
+ if (matchingOption) {
68
+ return matchingOption;
69
+ }
72
70
  }
71
+ return undefined;
73
72
  };
74
73
 
75
- void fetchOptions();
76
- }, [refTypeInfo, onQueryRefOptions]);
74
+ if (array && Array.isArray(formValue)) {
75
+ return formValue.map(unknownToRefOption).filter(isNonNullable) ?? [];
76
+ }
77
77
 
78
- if (!refTypeInfo) {
79
- return null;
80
- }
78
+ const option = unknownToRefOption(formValue);
79
+ if (option) {
80
+ return [option];
81
+ }
81
82
 
82
- // If ref type is expando, fall back to taking a DXN in string format.
83
- if (refTypeInfo.typename === getTypeAnnotation(Expando)?.typename || !onQueryRefOptions) {
84
- const handleOnValueChange = (_type: any, dxnString: string) => {
85
- const dxn = DXN.tryParse(dxnString);
86
- if (dxn) {
87
- onValueChange?.('object', refFromDXN(dxn));
88
- } else if (dxnString === '') {
89
- onValueChange?.('object', undefined);
90
- } else {
91
- onValueChange?.('string', dxnString);
92
- }
93
- };
83
+ return [];
84
+ }, [getValue, availableOptions, array]);
94
85
 
95
- const handleGetValue = () => {
96
- const formValue = getValue();
97
- if (typeof formValue === 'string') {
98
- return formValue;
86
+ const handleSearch = useCallback(
87
+ (text: string, ids: string[]): TagPickerItemData[] =>
88
+ availableOptions
89
+ .filter((option) => !ids.includes(option.id))
90
+ .filter((option) => option.label.toLowerCase().includes(text.toLowerCase()))
91
+ .map((option) => ({ id: option.id, label: option.label, hue: option.hue as any })),
92
+ [availableOptions],
93
+ );
94
+
95
+ const handleUpdate = useCallback(
96
+ (ids: string[]) => {
97
+ if (ids.length === 0) {
98
+ onValueChange('object', undefined);
99
+ return;
99
100
  }
100
- if (formValue instanceof RefImpl) {
101
- return formValue.dxn.toString();
101
+
102
+ const refs = ids
103
+ .map((id) => {
104
+ const item = availableOptions.find((option) => option.id === id);
105
+ if (item) {
106
+ const dxn = DXN.parse(item.id);
107
+ return Ref.fromDXN(dxn);
108
+ }
109
+ return null;
110
+ })
111
+ .filter(isNonNullable);
112
+
113
+ if (array) {
114
+ onValueChange('object', refs);
115
+ } else {
116
+ onValueChange('object', refs[0]);
102
117
  }
118
+ },
119
+ [availableOptions, array, onValueChange],
120
+ );
103
121
 
104
- return undefined;
105
- };
122
+ const tagPickerMode: TagPickerMode = useMemo(() => (array ? 'multi-select' : 'single-select'), [array]);
106
123
 
107
- return (
108
- <TextInput
109
- type={type}
110
- label={label}
111
- disabled={readonly}
112
- placeholder={placeholder}
113
- inputOnly={inline}
114
- getValue={handleGetValue as <V>() => V | undefined}
115
- onValueChange={handleOnValueChange}
116
- {...restInputProps}
117
- />
118
- );
124
+ if (!refTypeInfo) {
125
+ return null;
119
126
  }
120
127
 
128
+ const { status, error } = restInputProps.getStatus();
129
+
130
+ return (
131
+ <Input.Root validationValence={status}>
132
+ {!inputOnly && (
133
+ <InputHeader error={error}>
134
+ <Input.Label>{label}</Input.Label>
135
+ </InputHeader>
136
+ )}
137
+ <div data-no-submit>
138
+ <TagPicker
139
+ items={handleGetValue()}
140
+ mode={tagPickerMode}
141
+ onBlur={(event) => onBlur(event as unknown as FocusEvent<HTMLElement>)}
142
+ onUpdate={handleUpdate}
143
+ onSearch={handleSearch}
144
+ classNames='rounded-sm bg-input p-1.5'
145
+ />
146
+ </div>
147
+ {inputOnly && <Input.DescriptionAndValidation>{error}</Input.DescriptionAndValidation>}
148
+ </Input.Root>
149
+ );
150
+ };
151
+
152
+ const RefFieldFallback = ({
153
+ type,
154
+ label,
155
+ disabled,
156
+ placeholder,
157
+ inputOnly,
158
+ getValue,
159
+ onValueChange,
160
+ ...restInputProps
161
+ }: InputProps) => {
162
+ const handleOnValueChange = (_type: any, dxnString: string) => {
163
+ const dxn = DXN.tryParse(dxnString);
164
+ if (dxn) {
165
+ onValueChange?.('object', Ref.fromDXN(dxn));
166
+ } else if (dxnString === '') {
167
+ onValueChange?.('object', undefined);
168
+ } else {
169
+ onValueChange?.('string', dxnString);
170
+ }
171
+ };
172
+
121
173
  const handleGetValue = () => {
122
174
  const formValue = getValue();
123
-
124
- if (formValue instanceof RefImpl) {
175
+ if (typeof formValue === 'string') {
176
+ return formValue;
177
+ }
178
+ if (Ref.isRef(formValue)) {
125
179
  return formValue.dxn.toString();
126
180
  }
127
181
 
128
182
  return undefined;
129
183
  };
130
184
 
131
- const handleValueChanged = (_type: any, dxnString: string) => {
132
- const dxn = DXN.parse(dxnString);
133
- const ref = refFromDXN(dxn);
134
-
135
- onValueChange('object', ref);
136
- };
137
-
138
185
  return (
139
- <SelectInput
186
+ <TextInput
140
187
  type={type}
141
188
  label={label}
142
- disabled={readonly || loading}
143
- placeholder={loading ? 'Loading options...' : placeholder}
144
- inputOnly={inline}
189
+ disabled={disabled}
190
+ placeholder={placeholder}
191
+ inputOnly={inputOnly}
145
192
  getValue={handleGetValue as <V>() => V | undefined}
146
- onValueChange={handleValueChanged}
147
- options={refOptions}
193
+ onValueChange={handleOnValueChange}
148
194
  {...restInputProps}
149
195
  />
150
196
  );
@@ -5,9 +5,10 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { type Meta, type StoryObj } from '@storybook/react';
8
+ import { Schema } from 'effect';
8
9
  import React, { useState } from 'react';
9
10
 
10
- import { S, SelectOptionSchema, type SelectOption } from '@dxos/echo-schema';
11
+ import { SelectOptionSchema, type SelectOption } from '@dxos/echo-schema';
11
12
  import { withLayout, withTheme } from '@dxos/storybook-utils';
12
13
 
13
14
  import { SelectOptionInput } from './SelectOptionsInput';
@@ -15,9 +16,9 @@ import translations from '../../../translations';
15
16
  import { TestLayout, TestPanel } from '../../testing';
16
17
  import { Form } from '../Form';
17
18
 
18
- const schema = S.Struct({
19
- options: S.Array(SelectOptionSchema).pipe(S.mutable),
20
- }).pipe(S.mutable);
19
+ const schema = Schema.Struct({
20
+ options: Schema.Array(SelectOptionSchema).pipe(Schema.mutable),
21
+ }).pipe(Schema.mutable);
21
22
 
22
23
  const DefaultStory = () => {
23
24
  const [values, setValues] = useState<{ options: SelectOption[] }>({
@@ -46,7 +47,7 @@ const DefaultStory = () => {
46
47
  const meta: Meta = {
47
48
  title: 'ui/react-ui-form/SelectOptionsInput',
48
49
  component: SelectOptionInput,
49
- decorators: [withTheme, withLayout({ tooltips: true })],
50
+ decorators: [withTheme, withLayout()],
50
51
  parameters: { translations },
51
52
  };
52
53
 
@@ -12,7 +12,7 @@ import { GeoPointInput } from './custom';
12
12
  /**
13
13
  * Get property input component.
14
14
  */
15
- export const getInputComponent = (type: SimpleType, format?: FormatEnum): InputComponent | undefined => {
15
+ export const getInputComponent = (type: SimpleType, format?: FormatEnum | string): InputComponent | undefined => {
16
16
  switch (format) {
17
17
  case FormatEnum.GeoPoint:
18
18
  return GeoPointInput;
@@ -3,7 +3,6 @@
3
3
  //
4
4
 
5
5
  export * from './custom';
6
-
7
6
  export * from './Defaults';
8
7
  export * from './Form';
9
8
  export * from './FormContext';
@@ -5,9 +5,10 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { type Meta, type StoryObj } from '@storybook/react';
8
+ import { Schema } from 'effect';
8
9
  import React, { useCallback, useMemo, useState } from 'react';
9
10
 
10
- import { Format, type EchoSchema, S, toJsonSchema, TypedObject } from '@dxos/echo-schema';
11
+ import { Format, type EchoSchema, toJsonSchema, TypedObject } from '@dxos/echo-schema';
11
12
  import { Filter, useQuery, useSpace } from '@dxos/react-client/echo';
12
13
  import { withClientProvider } from '@dxos/react-client/testing';
13
14
  import { useAsyncEffect } from '@dxos/react-ui';
@@ -26,7 +27,7 @@ const DefaultStory = () => {
26
27
  useAsyncEffect(async () => {
27
28
  if (space) {
28
29
  class TestSchema extends TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
29
- name: S.String,
30
+ name: Schema.String,
30
31
  email: Format.Email,
31
32
  salary: Format.Currency(),
32
33
  }) {}
@@ -41,7 +42,7 @@ const DefaultStory = () => {
41
42
  }
42
43
  }, [space]);
43
44
 
44
- const views = useQuery(space, Filter.schema(ViewType));
45
+ const views = useQuery(space, Filter.type(ViewType));
45
46
  const currentTypename = useMemo(() => view?.query?.typename, [view]);
46
47
  const updateViewTypename = useCallback(
47
48
  (newTypename: string) => {
@@ -81,7 +82,7 @@ const meta: Meta<typeof ViewEditor> = {
81
82
  title: 'ui/react-ui-form/ViewEditor',
82
83
  component: ViewEditor,
83
84
  render: DefaultStory,
84
- decorators: [withClientProvider({ createSpace: true }), withLayout({ fullscreen: true, tooltips: true }), withTheme],
85
+ decorators: [withClientProvider({ createSpace: true }), withLayout({ fullscreen: true }), withTheme],
85
86
  parameters: {
86
87
  translations,
87
88
  },