@dxos/react-ui-form 0.8.4-main.72ec0f3 → 0.8.4-main.7ace549

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 (58) hide show
  1. package/dist/lib/browser/index.mjs +82 -101
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +82 -101
  5. package/dist/lib/node-esm/index.mjs.map +3 -3
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +5 -4
  8. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +1 -1
  9. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +5 -4
  10. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/Form.d.ts +4 -4
  13. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.stories.d.ts +46 -31
  15. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
  17. package/dist/types/src/components/Form/FormContext.d.ts +3 -3
  18. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
  19. package/dist/types/src/components/Form/Input.d.ts +2 -2
  20. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  21. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +5 -4
  22. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Form/factory.d.ts +2 -2
  24. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  25. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +5 -4
  26. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -1
  27. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +2 -2
  28. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  29. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +6 -5
  30. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  31. package/dist/types/src/hooks/useForm.d.ts +4 -4
  32. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  33. package/dist/types/src/translations.d.ts +5 -4
  34. package/dist/types/src/translations.d.ts.map +1 -1
  35. package/dist/types/src/util/field.d.ts +3 -3
  36. package/dist/types/src/util/field.d.ts.map +1 -1
  37. package/dist/types/src/util/formatting.d.ts +2 -2
  38. package/dist/types/src/util/formatting.d.ts.map +1 -1
  39. package/dist/types/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +31 -31
  41. package/src/components/FieldEditor/FieldEditor.stories.tsx +2 -2
  42. package/src/components/FieldEditor/FieldEditor.tsx +3 -3
  43. package/src/components/Form/ArrayField.tsx +3 -1
  44. package/src/components/Form/Form.stories.tsx +21 -21
  45. package/src/components/Form/Form.tsx +4 -4
  46. package/src/components/Form/FormActions.tsx +7 -2
  47. package/src/components/Form/FormContent.tsx +1 -1
  48. package/src/components/Form/FormContext.tsx +4 -4
  49. package/src/components/Form/Input.tsx +2 -2
  50. package/src/components/Form/factory.tsx +7 -4
  51. package/src/components/ViewEditor/ViewEditor.stories.tsx +3 -6
  52. package/src/components/ViewEditor/ViewEditor.tsx +13 -24
  53. package/src/hooks/useForm.ts +5 -5
  54. package/src/hooks/useRefQueryLookupHandler.ts +3 -3
  55. package/src/translations.ts +5 -4
  56. package/src/util/field.ts +25 -25
  57. package/src/util/formatting.ts +22 -22
  58. package/src/util/refs.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-form",
3
- "version": "0.8.4-main.72ec0f3",
3
+ "version": "0.8.4-main.7ace549",
4
4
  "description": "Data components.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -32,28 +32,28 @@
32
32
  "@radix-ui/react-context": "1.1.1",
33
33
  "date-fns": "^3.3.1",
34
34
  "jsonpath": "^1.1.1",
35
- "@dxos/async": "0.8.4-main.72ec0f3",
36
- "@dxos/debug": "0.8.4-main.72ec0f3",
37
- "@dxos/echo": "0.8.4-main.72ec0f3",
38
- "@dxos/echo-query": "0.8.4-main.72ec0f3",
39
- "@dxos/effect": "0.8.4-main.72ec0f3",
40
- "@dxos/echo-db": "0.8.4-main.72ec0f3",
41
- "@dxos/keys": "0.8.4-main.72ec0f3",
42
- "@dxos/invariant": "0.8.4-main.72ec0f3",
43
- "@dxos/lit-ui": "0.8.4-main.72ec0f3",
44
- "@dxos/live-object": "0.8.4-main.72ec0f3",
45
- "@dxos/log": "0.8.4-main.72ec0f3",
46
- "@dxos/react-ui-components": "0.8.4-main.72ec0f3",
47
- "@dxos/react-ui-searchlist": "0.8.4-main.72ec0f3",
48
- "@dxos/react-client": "0.8.4-main.72ec0f3",
49
- "@dxos/react-ui-stack": "0.8.4-main.72ec0f3",
50
- "@dxos/react-ui-editor": "0.8.4-main.72ec0f3",
51
- "@dxos/react-ui-types": "0.8.4-main.72ec0f3",
52
- "@dxos/schema": "0.8.4-main.72ec0f3",
53
- "@dxos/types": "0.8.4-main.72ec0f3",
54
- "@dxos/util": "0.8.4-main.72ec0f3",
55
- "@dxos/react-ui-list": "0.8.4-main.72ec0f3",
56
- "@dxos/react-ui-pickers": "0.8.4-main.72ec0f3"
35
+ "@dxos/async": "0.8.4-main.7ace549",
36
+ "@dxos/debug": "0.8.4-main.7ace549",
37
+ "@dxos/effect": "0.8.4-main.7ace549",
38
+ "@dxos/echo": "0.8.4-main.7ace549",
39
+ "@dxos/invariant": "0.8.4-main.7ace549",
40
+ "@dxos/keys": "0.8.4-main.7ace549",
41
+ "@dxos/lit-ui": "0.8.4-main.7ace549",
42
+ "@dxos/echo-query": "0.8.4-main.7ace549",
43
+ "@dxos/live-object": "0.8.4-main.7ace549",
44
+ "@dxos/log": "0.8.4-main.7ace549",
45
+ "@dxos/react-ui-components": "0.8.4-main.7ace549",
46
+ "@dxos/react-ui-editor": "0.8.4-main.7ace549",
47
+ "@dxos/react-client": "0.8.4-main.7ace549",
48
+ "@dxos/react-ui-list": "0.8.4-main.7ace549",
49
+ "@dxos/react-ui-pickers": "0.8.4-main.7ace549",
50
+ "@dxos/react-ui-searchlist": "0.8.4-main.7ace549",
51
+ "@dxos/react-ui-stack": "0.8.4-main.7ace549",
52
+ "@dxos/schema": "0.8.4-main.7ace549",
53
+ "@dxos/types": "0.8.4-main.7ace549",
54
+ "@dxos/util": "0.8.4-main.7ace549",
55
+ "@dxos/react-ui-types": "0.8.4-main.7ace549",
56
+ "@dxos/echo-db": "0.8.4-main.7ace549"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@types/jsonpath": "^0.2.4",
@@ -64,19 +64,19 @@
64
64
  "react": "~19.2.0",
65
65
  "react-dom": "~19.2.0",
66
66
  "vite": "7.1.9",
67
- "@dxos/random": "0.8.4-main.72ec0f3",
68
- "@dxos/react-ui": "0.8.4-main.72ec0f3",
69
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.72ec0f3",
70
- "@dxos/react-ui-theme": "0.8.4-main.72ec0f3",
71
- "@dxos/storybook-utils": "0.8.4-main.72ec0f3",
72
- "@dxos/echo-signals": "0.8.4-main.72ec0f3"
67
+ "@dxos/echo-signals": "0.8.4-main.7ace549",
68
+ "@dxos/random": "0.8.4-main.7ace549",
69
+ "@dxos/react-ui": "0.8.4-main.7ace549",
70
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.7ace549",
71
+ "@dxos/react-ui-theme": "0.8.4-main.7ace549",
72
+ "@dxos/storybook-utils": "0.8.4-main.7ace549"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "effect": "^3.13.3",
76
76
  "react": "^19.0.0",
77
77
  "react-dom": "^19.0.0",
78
- "@dxos/react-ui": "0.8.4-main.72ec0f3",
79
- "@dxos/react-ui-theme": "0.8.4-main.72ec0f3"
78
+ "@dxos/react-ui": "0.8.4-main.7ace549",
79
+ "@dxos/react-ui-theme": "0.8.4-main.7ace549"
80
80
  },
81
81
  "publishConfig": {
82
82
  "access": "public"
@@ -9,7 +9,7 @@ import { createEchoSchema } from '@dxos/echo/testing';
9
9
  import { log } from '@dxos/log';
10
10
  import { withTheme } from '@dxos/react-ui/testing';
11
11
  import { ProjectionModel } from '@dxos/schema';
12
- import { TestSchema, testView } from '@dxos/schema/testing';
12
+ import { Example, testView } from '@dxos/schema/testing';
13
13
 
14
14
  import { translations } from '../../translations';
15
15
  import { FIELD_EDITOR_DEBUG_SYMBOL, TestLayout, TestPanel } from '../testing';
@@ -71,7 +71,7 @@ type Story = StoryObj<typeof meta>;
71
71
 
72
72
  export const Default: Story = {
73
73
  args: {
74
- projection: new ProjectionModel(createEchoSchema(TestSchema).jsonSchema, testView.projection),
74
+ projection: new ProjectionModel(createEchoSchema(Example).jsonSchema, testView.projection),
75
75
  field: testView.projection.fields[0],
76
76
  },
77
77
  parameters: { controls: { disabled: true } },
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
6
6
 
7
- import { type EchoSchema, FormatEnum, FormatEnums, formatToType } from '@dxos/echo/internal';
7
+ import { type EchoSchema, Format, FormatEnums, formatToType } from '@dxos/echo/internal';
8
8
  import { type SchemaRegistry } from '@dxos/echo-db';
9
9
  import { log } from '@dxos/log';
10
10
  import { useAsyncEffect, useTranslation } from '@dxos/react-ui';
@@ -140,7 +140,7 @@ export const FieldEditor = ({
140
140
  ['format' satisfies keyof PropertyType]: (props) => (
141
141
  <SelectInput
142
142
  {...props}
143
- options={FormatEnums.filter((value) => value !== FormatEnum.None).map((value) => ({
143
+ options={FormatEnums.filter((value) => value !== Format.TypeFormat.None).map((value) => ({
144
144
  value,
145
145
  label: t(`format ${value}`),
146
146
  }))}
@@ -159,7 +159,7 @@ export const FieldEditor = ({
159
159
  {...props}
160
160
  options={
161
161
  referenceSchema
162
- ? getSchemaProperties(referenceSchema.ast)
162
+ ? getSchemaProperties(referenceSchema.ast, {}, { form: true })
163
163
  .sort(sortProperties)
164
164
  .map((p) => ({ value: p.name }))
165
165
  : []
@@ -46,7 +46,9 @@ export const ArrayField = ({ property, readonly, path, inputProps, Custom, looku
46
46
  return {};
47
47
  }
48
48
 
49
- return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [prop.name, prop.defaultValue]));
49
+ return Object.fromEntries(
50
+ getSchemaProperties(typeLiteral, {}, { form: true }).map((prop) => [prop.name, prop.defaultValue]),
51
+ );
50
52
  };
51
53
 
52
54
  const getDefaultValue = () =>
@@ -6,13 +6,11 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import * as Schema from 'effect/Schema';
7
7
  import React, { useCallback, useState } from 'react';
8
8
 
9
- import { ContactType } from '@dxos/client/testing';
10
- import { type Type } from '@dxos/echo';
11
- import { type BaseObject, Expando, Format, Ref, type TypeAnnotation, getObjectDXN } from '@dxos/echo/internal';
12
- import { live } from '@dxos/echo/internal';
9
+ import { Format, Obj, Ref, Type } from '@dxos/echo';
10
+ import { type AnyProperties, type TypeAnnotation } from '@dxos/echo/internal';
13
11
  import { Tooltip } from '@dxos/react-ui';
14
12
  import { withLayoutVariants, withTheme } from '@dxos/react-ui/testing';
15
- import { Testing } from '@dxos/schema/testing';
13
+ import { TestSchema } from '@dxos/schema/testing';
16
14
 
17
15
  import { translations } from '../../translations';
18
16
  import { TestLayout, TestPanel } from '../testing';
@@ -20,12 +18,12 @@ import { TestLayout, TestPanel } from '../testing';
20
18
  import { SelectInput } from './Defaults';
21
19
  import { Form, type FormProps } from './Form';
22
20
 
23
- type StoryProps<T extends BaseObject> = {
21
+ type StoryProps<T extends AnyProperties> = {
24
22
  debug?: boolean;
25
- schema: Type.Obj.Any;
23
+ schema: Schema.Schema.AnyNoContext;
26
24
  } & FormProps<T>;
27
25
 
28
- const DefaultStory = <T extends BaseObject = any>({
26
+ const DefaultStory = <T extends AnyProperties = any>({
29
27
  debug,
30
28
  schema,
31
29
  values: initialValues,
@@ -51,13 +49,13 @@ const DefaultStory = <T extends BaseObject = any>({
51
49
  return <Form<T> schema={schema} values={values} onSave={handleSave} {...props} />;
52
50
  };
53
51
 
54
- const RefStory = <T extends BaseObject = any>(props: StoryProps<T>) => {
52
+ const RefStory = <T extends AnyProperties = any>(props: StoryProps<T>) => {
55
53
  const onQueryRefOptions = useCallback((typeInfo: TypeAnnotation) => {
56
54
  switch (typeInfo.typename) {
57
- case Testing.Person.typename:
55
+ case TestSchema.Person.typename:
58
56
  return [
59
- { dxn: getObjectDXN(contact1)!, label: 'John Coltraine' },
60
- { dxn: getObjectDXN(contact2)!, label: 'Erykah Badu' },
57
+ { dxn: Obj.getDXN(contact1), label: 'Alice' },
58
+ { dxn: Obj.getDXN(contact2), label: 'Bob' },
61
59
  ];
62
60
  default:
63
61
  return [];
@@ -122,7 +120,7 @@ export const Default: Story = {
122
120
  export const Organization: Story = {
123
121
  args: {
124
122
  debug: true,
125
- schema: Testing.OrganizationSchema,
123
+ schema: TestSchema.OrganizationSchema,
126
124
  values: {
127
125
  name: 'DXOS',
128
126
  website: 'https://dxos.org',
@@ -134,7 +132,7 @@ export const Organization: Story = {
134
132
  export const OrganizationAutoSave: Story = {
135
133
  args: {
136
134
  debug: true,
137
- schema: Testing.OrganizationSchema,
135
+ schema: TestSchema.OrganizationSchema,
138
136
  values: {
139
137
  name: 'DXOS',
140
138
  website: 'https://dxos.org',
@@ -150,7 +148,7 @@ export const OrganizationAutoSave: Story = {
150
148
  export const Person: Story = {
151
149
  args: {
152
150
  debug: true,
153
- schema: Testing.Person,
151
+ schema: TestSchema.Person,
154
152
  values: {
155
153
  name: 'Bot',
156
154
  },
@@ -278,16 +276,18 @@ export const Enum: StoryObj<StoryProps<ColorType>> = {
278
276
  //
279
277
 
280
278
  const RefSchema = Schema.Struct({
281
- contact: Ref(ContactType).annotations({ title: 'Contact Reference' }),
282
- optionalContact: Schema.optional(Ref(ContactType).annotations({ title: 'Optional Contact Reference' })),
283
- refArray: Schema.optional(Schema.Array(Ref(ContactType))),
284
- unknownExpando: Schema.optional(Ref(Expando).annotations({ title: 'Optional Ref to an Expando (DXN Input)' })),
279
+ contact: Type.Ref(TestSchema.Person).annotations({ title: 'Contact Reference' }),
280
+ optionalContact: Schema.optional(Type.Ref(TestSchema.Person).annotations({ title: 'Optional Contact Reference' })),
281
+ refArray: Schema.optional(Schema.Array(Type.Ref(TestSchema.Person))),
282
+ unknownExpando: Schema.optional(
283
+ Type.Ref(Type.Expando).annotations({ title: 'Optional Ref to an Expando (DXN Input)' }),
284
+ ),
285
285
  });
286
286
 
287
287
  type RefSchema = Schema.Schema.Type<typeof RefSchema>;
288
288
 
289
- const contact1 = live(ContactType, { identifiers: [] });
290
- const contact2 = live(ContactType, { identifiers: [] });
289
+ const contact1 = Obj.make(TestSchema.Person, { name: 'Alice' });
290
+ const contact2 = Obj.make(TestSchema.Person, { name: 'Bob' });
291
291
 
292
292
  export const Refs: StoryObj<StoryProps<RefSchema>> = {
293
293
  render: RefStory,
@@ -6,7 +6,7 @@ import { useFocusFinders } from '@fluentui/react-tabster';
6
6
  import type * as Schema from 'effect/Schema';
7
7
  import React, { type ReactElement, useCallback, useEffect, useRef } from 'react';
8
8
 
9
- import { type BaseObject, type PropertyKey } from '@dxos/echo/internal';
9
+ import { type AnyProperties, type PropertyKey } from '@dxos/echo/internal';
10
10
  import { type ThemedClassName } from '@dxos/react-ui';
11
11
  import { cardDialogOverflow, cardSpacing } from '@dxos/react-ui-stack';
12
12
  import { type ProjectionModel, type SchemaProperty } from '@dxos/schema';
@@ -18,7 +18,7 @@ import { FormFields, type FormFieldsProps } from './FormContent';
18
18
  import { FormProvider } from './FormContext';
19
19
  import { type InputComponent, type InputProps } from './Input';
20
20
 
21
- export type PropsFilter<T extends BaseObject> = (props: SchemaProperty<T>[]) => SchemaProperty<T>[];
21
+ export type PropsFilter<T extends AnyProperties> = (props: SchemaProperty<T>[]) => SchemaProperty<T>[];
22
22
 
23
23
  export type ComponentLookup = (args: {
24
24
  prop: string;
@@ -28,7 +28,7 @@ export type ComponentLookup = (args: {
28
28
 
29
29
  export type CustomInputMap = Partial<Record<string, InputComponent>>;
30
30
 
31
- export type FormProps<T extends BaseObject> = ThemedClassName<{
31
+ export type FormProps<T extends AnyProperties> = ThemedClassName<{
32
32
  id?: string;
33
33
  values: Partial<T>;
34
34
  // TODO(burdon): Autofocus first input.
@@ -45,7 +45,7 @@ export type FormProps<T extends BaseObject> = ThemedClassName<{
45
45
  // TODO(wittjosiah): This needs to support different ref field options per field.
46
46
  FormFieldsProps;
47
47
 
48
- export const Form = <T extends BaseObject>({
48
+ export const Form = <T extends AnyProperties>({
49
49
  classNames,
50
50
  id,
51
51
  testId,
@@ -37,7 +37,12 @@ export const FormActions = ({ readonly, onCancel, outerSpacing = true }: FormAct
37
37
  )}
38
38
  >
39
39
  {onCancel && !readonly && (
40
- <IconButton data-testid='cancel-button' icon='ph--x--regular' label={t('cancel button')} onClick={onCancel} />
40
+ <IconButton
41
+ data-testid='cancel-button'
42
+ icon='ph--x--regular'
43
+ label={t('cancel button label')}
44
+ onClick={onCancel}
45
+ />
41
46
  )}
42
47
  {handleSave && (
43
48
  <IconButton
@@ -45,7 +50,7 @@ export const FormActions = ({ readonly, onCancel, outerSpacing = true }: FormAct
45
50
  data-testid='save-button'
46
51
  disabled={!canSave}
47
52
  icon='ph--check--regular'
48
- label={t('save button')}
53
+ label={t('save button label')}
49
54
  onClick={handleSave}
50
55
  />
51
56
  )}
@@ -264,7 +264,7 @@ export const FormFields = forwardRef<HTMLDivElement, FormFieldsProps>(
264
264
  ) => {
265
265
  const values = useFormValues(path);
266
266
  const properties = useMemo(() => {
267
- const props = getSchemaProperties(schema.ast, values);
267
+ const props = getSchemaProperties(schema.ast, values, { form: true });
268
268
 
269
269
  // Use projection-based field management when view and projection are available
270
270
  if (projection) {
@@ -14,23 +14,23 @@ import React, {
14
14
  } from 'react';
15
15
 
16
16
  import { raise } from '@dxos/debug';
17
- import { type BaseObject, getValue } from '@dxos/echo/internal';
17
+ import { type AnyProperties, getValue } from '@dxos/echo/internal';
18
18
  import { type SimpleType, createJsonPath } from '@dxos/effect';
19
19
 
20
20
  import { type FormHandler, type FormOptions, useForm } from '../../hooks';
21
21
 
22
- type FormContextValue<T extends BaseObject> = FormHandler<T>;
22
+ type FormContextValue<T extends AnyProperties> = FormHandler<T>;
23
23
 
24
24
  const FormContext = createContext<FormContextValue<any> | undefined>(undefined);
25
25
 
26
- export const useFormContext = <T extends BaseObject>(): FormContextValue<T> => {
26
+ export const useFormContext = <T extends AnyProperties>(): FormContextValue<T> => {
27
27
  return useContext(FormContext) ?? raise(new Error('Missing FormContext'));
28
28
  };
29
29
 
30
30
  export const useFormValues = (path: (string | number)[] = []): any => {
31
31
  const { values: formValues } = useFormContext();
32
32
  const jsonPath = createJsonPath(path);
33
- return getValue(formValues, jsonPath) as BaseObject;
33
+ return getValue(formValues, jsonPath) as AnyProperties;
34
34
  };
35
35
 
36
36
  export type FormInputStateProps = {
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React, { type FC } from 'react';
6
6
 
7
- import { type FormatEnum } from '@dxos/echo/internal';
7
+ import { type Format } from '@dxos/echo/internal';
8
8
  import { type SimpleType } from '@dxos/effect';
9
9
  import { Icon, Input, Tooltip } from '@dxos/react-ui';
10
10
  import { labelSpacing } from '@dxos/react-ui-stack';
@@ -17,7 +17,7 @@ import { type FormInputStateProps } from './FormContext';
17
17
  */
18
18
  export type InputProps = {
19
19
  type: SimpleType;
20
- format?: FormatEnum;
20
+ format?: Format.TypeFormat;
21
21
  label: string;
22
22
  placeholder?: string;
23
23
  inputOnly?: boolean;
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { FormatEnum } from '@dxos/echo/internal';
5
+ import { Format } from '@dxos/echo/internal';
6
6
  import { type SimpleType } from '@dxos/effect';
7
7
 
8
8
  import { GeoPointInput } from './custom';
@@ -12,11 +12,14 @@ import { type InputComponent } from './Input';
12
12
  /**
13
13
  * Get property input component.
14
14
  */
15
- export const getInputComponent = (type: SimpleType, format?: FormatEnum | string): InputComponent | undefined => {
15
+ export const getInputComponent = (
16
+ type: SimpleType,
17
+ format?: Format.TypeFormat | string,
18
+ ): InputComponent | undefined => {
16
19
  switch (format) {
17
- case FormatEnum.GeoPoint:
20
+ case Format.TypeFormat.GeoPoint:
18
21
  return GeoPointInput;
19
- case FormatEnum.Markdown:
22
+ case Format.TypeFormat.Markdown:
20
23
  return MarkdownInput;
21
24
  }
22
25
 
@@ -74,7 +74,6 @@ const DefaultStory = (props: StoryProps) => {
74
74
  name: 'Test',
75
75
  query: Query.select(Filter.type(TestSchema)),
76
76
  jsonSchema: Type.toJsonSchema(TestSchema),
77
- presentation: Obj.make(Type.Expando, {}),
78
77
  });
79
78
 
80
79
  setSchema(testSchema);
@@ -88,7 +87,7 @@ const DefaultStory = (props: StoryProps) => {
88
87
  return;
89
88
  }
90
89
 
91
- if (props.mode === 'query') {
90
+ if (props.mode === 'tag') {
92
91
  const queue = target && DXN.tryParse(target) ? target : undefined;
93
92
  const query = queue ? Query.fromAst(newQuery).options({ queues: [queue] }) : Query.fromAst(newQuery);
94
93
  view.query.ast = query.ast;
@@ -102,12 +101,10 @@ const DefaultStory = (props: StoryProps) => {
102
101
  const newView = View.make({
103
102
  query,
104
103
  jsonSchema: newSchema.jsonSchema,
105
- presentation: Obj.make(Type.Expando, {}),
106
104
  });
107
105
  view.projection = Obj.getSnapshot(newView).projection;
108
106
  setSchema(() => newSchema);
109
107
  } else {
110
- console.log('updateViewQuery', { newQuery });
111
108
  view.query.ast = newQuery;
112
109
  schema.updateTypename(getTypenameFromQuery(newQuery));
113
110
  }
@@ -194,8 +191,8 @@ export const Readonly: Story = {
194
191
  },
195
192
  };
196
193
 
197
- export const QueryMode: Story = {
194
+ export const TagQueryMode: Story = {
198
195
  args: {
199
- mode: 'query',
196
+ mode: 'tag',
200
197
  },
201
198
  };
@@ -37,7 +37,7 @@ export type ViewEditorProps = ThemedClassName<
37
37
  {
38
38
  schema: Schema.Schema.AnyNoContext;
39
39
  view: View.View;
40
- mode?: 'schema' | 'query' | 'named-query';
40
+ mode?: 'schema' | 'tag';
41
41
  registry?: SchemaRegistry;
42
42
  readonly?: boolean;
43
43
  showHeading?: boolean;
@@ -96,13 +96,9 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
96
96
  : QueryAST.Query.annotations({ title: 'Query' }),
97
97
  });
98
98
 
99
- if (mode === 'query' || mode === 'named-query') {
100
- const name = Schema.Struct({
101
- name: Schema.optional(Schema.String.annotations({ title: 'Name' })),
102
- });
103
-
99
+ if (mode === 'tag') {
104
100
  return Schema.Struct({
105
- ...(mode === 'named-query' ? { ...name.fields, ...base.fields } : base.fields),
101
+ ...base.fields,
106
102
  target: Schema.optional(Schema.String.annotations({ title: 'Target Queue' })),
107
103
  }).pipe(Schema.mutable);
108
104
  }
@@ -114,11 +110,10 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
114
110
  // TODO(burdon): Settings should have domain name owned by user.
115
111
  const viewValues = useMemo(
116
112
  () => ({
117
- name: view.name,
118
113
  query: mode === 'schema' ? getTypenameFromQuery(view.query.ast) : view.query.ast,
119
114
  target: queueTarget,
120
115
  }),
121
- [view.name, mode, view.query.ast, queueTarget],
116
+ [mode, view.query.ast, queueTarget],
122
117
  );
123
118
 
124
119
  const handleToggleField = useCallback(
@@ -138,18 +133,12 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
138
133
 
139
134
  const handleUpdate = useCallback(
140
135
  (values: any) => {
141
- invariant(!readonly);
142
136
  requestAnimationFrame(() => {
143
- if ('name' in values && view.name !== values.name) {
144
- view.name = values.name;
145
- return;
146
- }
147
-
148
137
  const query = mode === 'schema' ? Query.select(Filter.typename(values.query)).ast : values.query;
149
138
  onQueryChanged?.(query, values.target);
150
139
  });
151
140
  },
152
- [onQueryChanged, readonly, view, queueTarget, mode],
141
+ [onQueryChanged, view, queueTarget, mode],
153
142
  );
154
143
 
155
144
  const handleDelete = useCallback(
@@ -194,11 +183,12 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
194
183
  [projectionModel],
195
184
  );
196
185
 
197
- const custom = useMemo(() => (mode === 'query' ? customFields({ types, tags }) : undefined), [types, tags, mode]);
186
+ const custom = useMemo(() => (mode === 'tag' ? customFields({ types, tags }) : undefined), [types, tags, mode]);
198
187
 
199
188
  return (
200
189
  <div role='none' className={mx(classNames)}>
201
- {schemaReadonly && mode === 'schema' && (
190
+ {/* If readonlyProp is set, then the callout is not needed. */}
191
+ {schemaReadonly && !readonly && (
202
192
  <Callout.Root valence='info' classNames={['mlb-cardSpacingBlock', outerSpacing && 'mli-cardSpacingInline']}>
203
193
  <Callout.Title>{t('system schema description')}</Callout.Title>
204
194
  </Callout.Root>
@@ -210,7 +200,6 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
210
200
  autoSave
211
201
  schema={viewSchema}
212
202
  values={viewValues}
213
- readonly={readonly ? 'disabled-input' : false}
214
203
  onSave={handleUpdate}
215
204
  outerSpacing={outerSpacing}
216
205
  Custom={custom}
@@ -243,7 +232,7 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
243
232
  role='none'
244
233
  className={mx(subtleHover, listItemGrid, 'rounded-sm cursor-pointer min-bs-10')}
245
234
  >
246
- <List.ItemDragHandle disabled={readonly} />
235
+ <List.ItemDragHandle disabled={readonly || schemaReadonly} />
247
236
  <List.ItemTitle
248
237
  classNames={hidden && 'text-subdued'}
249
238
  onClick={() => handleToggleField(field)}
@@ -258,7 +247,7 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
258
247
  disabled={readonly || (!hidden && projectionModel.fields.length <= 1)}
259
248
  onClick={() => (hidden ? handleShow(field.path) : handleHide(field.id))}
260
249
  />
261
- {mode === 'schema' && (
250
+ {!readonly && (
262
251
  <>
263
252
  <List.ItemDeleteButton
264
253
  label={t('delete field label')}
@@ -279,7 +268,7 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
279
268
  </>
280
269
  )}
281
270
  </div>
282
- {expandedField === field.id && mode === 'schema' && (
271
+ {expandedField === field.id && !readonly && (
283
272
  <div role='none' className='col-span-5 mbs-1 mbe-1 border border-separator rounded-md'>
284
273
  <FieldEditor
285
274
  readonly={readonly || schemaReadonly ? 'disabled-input' : false}
@@ -299,11 +288,11 @@ export const ViewEditor = forwardRef<ProjectionModel, ViewEditorProps>(
299
288
  </List.Root>
300
289
  </div>
301
290
 
302
- {!readonly && !expandedField && mode === 'schema' && (
291
+ {!readonly && !expandedField && (
303
292
  <div role='none' className={outerSpacing ? cardSpacing : 'mlb-cardSpacingBlock'}>
304
293
  <IconButton
305
294
  icon='ph--plus--regular'
306
- label={t('add property button')}
295
+ label={t('add property button label')}
307
296
  onClick={readonly ? undefined : handleAdd}
308
297
  // TODO(burdon): Show field limit in ux (not tooltip).
309
298
  disabled={view.projection.fields.length >= VIEW_FIELD_LIMIT}
@@ -6,7 +6,7 @@ import type * as Schema from 'effect/Schema';
6
6
  import * as SchemaAST from 'effect/SchemaAST';
7
7
  import { useCallback, useEffect, useMemo, useState } from 'react';
8
8
 
9
- import { type BaseObject, getValue, setValue } from '@dxos/echo/internal';
9
+ import { type AnyProperties, getValue, setValue } from '@dxos/echo/internal';
10
10
  import { type JsonPath, type SimpleType, createJsonPath, fromEffectValidationPath } from '@dxos/effect';
11
11
  import { invariant } from '@dxos/invariant';
12
12
  import { log } from '@dxos/log';
@@ -16,7 +16,7 @@ import { type MaybePromise } from '@dxos/util';
16
16
  /**
17
17
  * Return type from `useForm` hook.
18
18
  */
19
- export type FormHandler<T extends BaseObject> = {
19
+ export type FormHandler<T extends AnyProperties> = {
20
20
  //
21
21
  // Form state management.
22
22
  //
@@ -44,7 +44,7 @@ export type FormHandler<T extends BaseObject> = {
44
44
  /**
45
45
  * Hook options.
46
46
  */
47
- export interface FormOptions<T extends BaseObject> {
47
+ export interface FormOptions<T extends AnyProperties> {
48
48
  /**
49
49
  * Effect schema (Type literal).
50
50
  */
@@ -85,7 +85,7 @@ export interface FormOptions<T extends BaseObject> {
85
85
  * Creates a hook for managing form state, including values, validation, and submission.
86
86
  * Deeply integrated with `@dxos/schema` for schema-based validation.
87
87
  */
88
- export const useForm = <T extends BaseObject>({
88
+ export const useForm = <T extends AnyProperties>({
89
89
  schema,
90
90
  initialValues,
91
91
  onValuesChanged,
@@ -276,7 +276,7 @@ export const useForm = <T extends BaseObject>({
276
276
  );
277
277
  };
278
278
 
279
- const createKeySet = <T extends BaseObject, V>(obj: T, value: V): Record<JsonPath, V> => {
279
+ const createKeySet = <T extends AnyProperties, V>(obj: T, value: V): Record<JsonPath, V> => {
280
280
  invariant(obj);
281
281
  return Object.keys(obj).reduce((acc, key) => ({ ...acc, [key]: value }), {} as Record<JsonPath, V>);
282
282
  };
@@ -5,7 +5,7 @@
5
5
  import { useCallback } from 'react';
6
6
 
7
7
  import { Obj } from '@dxos/echo';
8
- import { type TypeAnnotation, getObjectDXN } from '@dxos/echo/internal';
8
+ import { type TypeAnnotation } from '@dxos/echo/internal';
9
9
  import { Filter, type Space } from '@dxos/react-client/echo';
10
10
  import { isNonNullable } from '@dxos/util';
11
11
 
@@ -19,12 +19,12 @@ export const useRefQueryLookupHandler = ({ space }: UseRefQueryLookupProps): Que
19
19
  if (!space) {
20
20
  return [];
21
21
  }
22
+
22
23
  const query = space.db.query(Filter.typename(typeInfo.typename));
23
24
  const { objects } = await query.run();
24
-
25
25
  return objects
26
26
  .map((object) => {
27
- const dxn = getObjectDXN(object);
27
+ const dxn = Obj.getDXN(object);
28
28
  if (!dxn) {
29
29
  return undefined;
30
30
  }
@@ -15,7 +15,7 @@ export const translations = [
15
15
  'empty readonly ref field label': '(none)',
16
16
 
17
17
  // TODO(burdon): Standardize field/property.
18
- 'add property button': 'Add property',
18
+ 'add property button label': 'Add property',
19
19
  'field property label': 'Property',
20
20
  'field property placeholder': 'Property name',
21
21
  'field format label': 'Type',
@@ -33,7 +33,8 @@ export const translations = [
33
33
  'ref field placeholder_other': 'Select items…',
34
34
 
35
35
  // TODO(burdon): Factor out?
36
- 'save button': 'Save',
36
+ 'cancel button label': 'Cancel',
37
+ 'save button label': 'Save',
37
38
 
38
39
  // FormatEnum
39
40
  'format boolean': 'Boolean',
@@ -77,9 +78,9 @@ export const translations = [
77
78
  'select option add': 'Add option',
78
79
 
79
80
  // System schema message.
80
- 'system schema title': 'System record type',
81
+ 'system schema title': 'System type',
81
82
  'system schema description':
82
- 'This is a system record type and cannot be modified, though the view can still be configured.',
83
+ 'This is a system type and cannot be modified, though the view can still be configured.',
83
84
  },
84
85
  },
85
86
  },