@dxos/react-ui-form 0.7.4 → 0.7.5-main.937ce75

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 (47) hide show
  1. package/dist/lib/browser/index.mjs +246 -209
  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 +340 -302
  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 +246 -209
  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/FieldEditor/FieldEditor.d.ts +2 -2
  11. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/Form.d.ts +1 -1
  13. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.stories.d.ts +5 -0
  15. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Input.d.ts +3 -3
  17. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/{Custom.d.ts → custom/GeoPointInput.d.ts} +3 -3
  19. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -0
  20. package/dist/types/src/components/Form/custom/TupleInput.d.ts +7 -0
  21. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -0
  22. package/dist/types/src/components/Form/custom/index.d.ts +3 -0
  23. package/dist/types/src/components/Form/custom/index.d.ts.map +1 -0
  24. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  25. package/dist/types/src/components/Form/index.d.ts +2 -2
  26. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  27. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +4 -4
  28. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  29. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  30. package/dist/types/src/hooks/useForm.d.ts +9 -10
  31. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  32. package/dist/types/tsconfig.tsbuildinfo +1 -0
  33. package/package.json +24 -24
  34. package/src/components/FieldEditor/FieldEditor.stories.tsx +2 -2
  35. package/src/components/FieldEditor/FieldEditor.tsx +75 -50
  36. package/src/components/Form/Form.stories.tsx +33 -1
  37. package/src/components/Form/Form.tsx +3 -4
  38. package/src/components/Form/Input.tsx +3 -3
  39. package/src/components/Form/{Custom.tsx → custom/GeoPointInput.tsx} +4 -16
  40. package/src/components/Form/custom/TupleInput.tsx +53 -0
  41. package/src/components/Form/custom/index.ts +6 -0
  42. package/src/components/Form/factory.tsx +2 -2
  43. package/src/components/Form/index.ts +3 -2
  44. package/src/components/ViewEditor/ViewEditor.stories.tsx +6 -5
  45. package/src/components/ViewEditor/ViewEditor.tsx +4 -4
  46. package/src/hooks/useForm.ts +32 -52
  47. package/dist/types/src/components/Form/Custom.d.ts.map +0 -1
@@ -80,27 +80,16 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
80
80
  };
81
81
 
82
82
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
83
- import React6, { useCallback as useCallback2, useEffect as useEffect3, useState as useState2 } from "react";
83
+ import React7, { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo3, useState as useState2 } from "react";
84
84
  import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
85
85
  import { log as log3 } from "@dxos/log";
86
86
  import { useTranslation as useTranslation3 } from "@dxos/react-ui";
87
87
  import { getFormatSchema, getSchemaProperties as getSchemaProperties2, sortProperties } from "@dxos/schema";
88
88
 
89
- // packages/ui/react-ui-form/src/components/Form/Form.tsx
90
- import { pipe } from "effect";
91
- import { capitalize } from "effect/String";
92
- import React5, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
93
- import { AST, S } from "@dxos/echo-schema";
94
- import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
95
- import { log as log2 } from "@dxos/log";
96
- import { IconButton, useTranslation as useTranslation2 } from "@dxos/react-ui";
97
- import { mx } from "@dxos/react-ui-theme";
98
- import { getSchemaProperties } from "@dxos/schema";
99
- import { isNotFalsy } from "@dxos/util";
100
-
101
- // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
89
+ // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
102
90
  import React3 from "react";
103
- import { Input as Input2, Select } from "@dxos/react-ui";
91
+ import { Input as Input2, useTranslation } from "@dxos/react-ui";
92
+ import { safeParseFloat } from "@dxos/util";
104
93
 
105
94
  // packages/ui/react-ui-form/src/components/Form/Input.tsx
106
95
  import React2 from "react";
@@ -121,120 +110,156 @@ var InputHeader = ({ children, error }) => {
121
110
  }, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null), error)));
122
111
  };
123
112
 
124
- // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
125
- var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
113
+ // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
114
+ var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
115
+ const { t } = useTranslation(translationKey);
126
116
  const { status, error } = getStatus?.(property);
117
+ const [lng = 0, lat = 0] = getValue2(property) ?? [];
127
118
  return /* @__PURE__ */ React3.createElement(Input2.Root, {
128
119
  validationValence: status
129
- }, !inputOnly && /* @__PURE__ */ React3.createElement(InputHeader, {
120
+ }, /* @__PURE__ */ React3.createElement(InputHeader, {
121
+ error
122
+ }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement("div", {
123
+ className: "grid grid-cols-2 gap-2"
124
+ }, /* @__PURE__ */ React3.createElement(Input2.TextInput, {
125
+ type: "number",
126
+ disabled,
127
+ placeholder: t("placeholder longitude"),
128
+ value: lng,
129
+ onChange: (event) => onValueChange(property, type, [
130
+ lat,
131
+ safeParseFloat(event.target.value, 0)
132
+ ]),
133
+ onBlur
134
+ }), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
135
+ type: "number",
136
+ disabled,
137
+ placeholder: t("placeholder latitude"),
138
+ value: lat,
139
+ onChange: (event) => onValueChange(property, type, [
140
+ safeParseFloat(event.target.value, 0),
141
+ lng
142
+ ]),
143
+ onBlur
144
+ })));
145
+ };
146
+
147
+ // packages/ui/react-ui-form/src/components/Form/custom/TupleInput.tsx
148
+ import React4 from "react";
149
+ import { Input as Input3 } from "@dxos/react-ui";
150
+ import { mx } from "@dxos/react-ui-theme";
151
+ import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
152
+ var gridCols = [
153
+ "grid-cols-1",
154
+ "grid-cols-2",
155
+ "grid-cols-3",
156
+ "grid-cols-4"
157
+ ];
158
+ var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
159
+ const { status, error } = getStatus?.(property);
160
+ const values = getValue2(property) ?? {};
161
+ return /* @__PURE__ */ React4.createElement(Input3.Root, {
162
+ validationValence: status
163
+ }, /* @__PURE__ */ React4.createElement(InputHeader, {
164
+ error
165
+ }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
166
+ className: mx("grid gap-2", gridCols[binding.length - 1])
167
+ }, binding.map((prop) => /* @__PURE__ */ React4.createElement(Input3.TextInput, {
168
+ key: prop,
169
+ type: "number",
170
+ disabled,
171
+ value: values[prop],
172
+ onChange: (event) => onValueChange(property, type, {
173
+ ...values,
174
+ [prop]: safeParseFloat2(event.target.value, 0)
175
+ }),
176
+ onBlur
177
+ }))));
178
+ };
179
+
180
+ // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
181
+ import React5 from "react";
182
+ import { Input as Input4, Select } from "@dxos/react-ui";
183
+ var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
184
+ const { status, error } = getStatus?.(property);
185
+ return /* @__PURE__ */ React5.createElement(Input4.Root, {
186
+ validationValence: status
187
+ }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
130
188
  error
131
- }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
189
+ }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.TextInput, {
132
190
  disabled,
133
191
  placeholder,
134
- value: getValue(property) ?? "",
192
+ value: getValue2(property) ?? "",
135
193
  onChange: (event) => onValueChange(property, type, event.target.value),
136
194
  onBlur
137
- }), inputOnly && /* @__PURE__ */ React3.createElement(Input2.Validation, null, error));
195
+ }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.Validation, null, error));
138
196
  };
139
- var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
197
+ var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
140
198
  const { status, error } = getStatus?.(property);
141
- return /* @__PURE__ */ React3.createElement(Input2.Root, {
199
+ return /* @__PURE__ */ React5.createElement(Input4.Root, {
142
200
  validationValence: status
143
- }, !inputOnly && /* @__PURE__ */ React3.createElement(InputHeader, {
201
+ }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
144
202
  error
145
- }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
203
+ }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.TextInput, {
146
204
  type: "number",
147
205
  disabled,
148
206
  placeholder,
149
- value: getValue(property) ?? 0,
207
+ value: getValue2(property) ?? 0,
150
208
  onChange: (event) => onValueChange(property, type, event.target.value),
151
209
  onBlur
152
- }), inputOnly && /* @__PURE__ */ React3.createElement(Input2.DescriptionAndValidation, null, error));
210
+ }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
153
211
  };
154
- var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue, onValueChange }) => {
212
+ var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue: getValue2, onValueChange }) => {
155
213
  const { status, error } = getStatus?.(property);
156
- return /* @__PURE__ */ React3.createElement(Input2.Root, {
214
+ return /* @__PURE__ */ React5.createElement(Input4.Root, {
157
215
  validationValence: status
158
- }, !inputOnly && /* @__PURE__ */ React3.createElement(InputHeader, {
216
+ }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
159
217
  error
160
- }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.Switch, {
161
- checked: getValue(property),
218
+ }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.Switch, {
219
+ checked: getValue2(property),
162
220
  onCheckedChange: (value) => onValueChange(property, type, value)
163
- }), inputOnly && /* @__PURE__ */ React3.createElement(Input2.DescriptionAndValidation, null, error));
221
+ }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
164
222
  };
165
- var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue, onValueChange }) => {
223
+ var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue2, onValueChange }) => {
166
224
  const { status, error } = getStatus?.(property);
167
- return /* @__PURE__ */ React3.createElement(Input2.Root, {
225
+ return /* @__PURE__ */ React5.createElement(Input4.Root, {
168
226
  validationValence: status
169
- }, !inputOnly && /* @__PURE__ */ React3.createElement(InputHeader, {
227
+ }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
170
228
  error
171
- }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Select.Root, {
172
- value: getValue(property),
229
+ }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Select.Root, {
230
+ value: getValue2(property),
173
231
  onValueChange: (value) => onValueChange(property, type, value)
174
- }, /* @__PURE__ */ React3.createElement(Select.TriggerButton, {
232
+ }, /* @__PURE__ */ React5.createElement(Select.TriggerButton, {
175
233
  classNames: "is-full",
176
234
  disabled,
177
235
  placeholder
178
- }), /* @__PURE__ */ React3.createElement(Select.Portal, null, /* @__PURE__ */ React3.createElement(Select.Content, null, /* @__PURE__ */ React3.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
236
+ }), /* @__PURE__ */ React5.createElement(Select.Portal, null, /* @__PURE__ */ React5.createElement(Select.Content, null, /* @__PURE__ */ React5.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
179
237
  // NOTE: Numeric values are converted to and from strings.
180
- /* @__PURE__ */ React3.createElement(Select.Option, {
238
+ /* @__PURE__ */ React5.createElement(Select.Option, {
181
239
  key: String(value),
182
240
  value: String(value)
183
241
  }, label2 ?? String(value))
184
- )))))), inputOnly && /* @__PURE__ */ React3.createElement(Input2.DescriptionAndValidation, null, error));
242
+ )))))), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
185
243
  };
186
244
 
187
- // packages/ui/react-ui-form/src/components/Form/factory.tsx
188
- import { FormatEnum } from "@dxos/echo-schema";
189
-
190
- // packages/ui/react-ui-form/src/components/Form/Custom.tsx
191
- import React4 from "react";
192
- import { Input as Input3, useTranslation } from "@dxos/react-ui";
193
- var GeiPointInput = ({ property, type, label, disabled, getStatus, getValue, onValueChange, onBlur }) => {
194
- const { t } = useTranslation(translationKey);
195
- const { status, error } = getStatus?.(property);
196
- const [lng = 0, lat = 0] = getValue(property) ?? [];
197
- return /* @__PURE__ */ React4.createElement(Input3.Root, {
198
- validationValence: status
199
- }, /* @__PURE__ */ React4.createElement(InputHeader, {
200
- error
201
- }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
202
- className: "grid grid-cols-2 gap-2"
203
- }, /* @__PURE__ */ React4.createElement(Input3.TextInput, {
204
- type: "number",
205
- disabled,
206
- placeholder: t("placeholder longitude"),
207
- value: lng,
208
- onChange: (event) => onValueChange(property, type, [
209
- lat,
210
- safeParseFloat(event.target.value, 0)
211
- ]),
212
- onBlur
213
- }), /* @__PURE__ */ React4.createElement(Input3.TextInput, {
214
- type: "number",
215
- disabled,
216
- placeholder: t("placeholder latitude"),
217
- value: lat,
218
- onChange: (event) => onValueChange(property, type, [
219
- safeParseFloat(event.target.value, 0),
220
- lng
221
- ]),
222
- onBlur
223
- })));
224
- };
225
- var safeParseFloat = (str, defaultValue) => {
226
- try {
227
- return parseFloat(str);
228
- } catch {
229
- return defaultValue ?? 0;
230
- }
231
- };
245
+ // packages/ui/react-ui-form/src/components/Form/Form.tsx
246
+ import { pipe } from "effect";
247
+ import { capitalize } from "effect/String";
248
+ import React6, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
249
+ import { AST, S } from "@dxos/echo-schema";
250
+ import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
251
+ import { log as log2 } from "@dxos/log";
252
+ import { IconButton, useTranslation as useTranslation2 } from "@dxos/react-ui";
253
+ import { mx as mx2 } from "@dxos/react-ui-theme";
254
+ import { getSchemaProperties } from "@dxos/schema";
255
+ import { isNotFalsy } from "@dxos/util";
232
256
 
233
257
  // packages/ui/react-ui-form/src/components/Form/factory.tsx
258
+ import { FormatEnum } from "@dxos/echo-schema";
234
259
  var getInputComponent = (type, format) => {
235
260
  switch (format) {
236
261
  case FormatEnum.LatLng:
237
- return GeiPointInput;
262
+ return GeoPointInput;
238
263
  }
239
264
  switch (type) {
240
265
  case "string":
@@ -248,6 +273,7 @@ var getInputComponent = (type, format) => {
248
273
 
249
274
  // packages/ui/react-ui-form/src/hooks/useForm.ts
250
275
  import { useCallback, useEffect, useMemo, useState } from "react";
276
+ import { getValue, setValue } from "@dxos/echo-schema";
251
277
  import { invariant } from "@dxos/invariant";
252
278
  import { log } from "@dxos/log";
253
279
  import { validateSchema } from "@dxos/schema";
@@ -266,10 +292,12 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
266
292
  const validate = useCallback((values2) => {
267
293
  let errors2 = validateSchema(schema, values2) ?? [];
268
294
  if (errors2.length === 0 && onValidate) {
269
- errors2 = onValidate(values2) ?? [];
295
+ const validatedValues = values2;
296
+ errors2 = onValidate(validatedValues) ?? [];
270
297
  }
271
298
  setErrors(flatMap(errors2));
272
- return errors2.length === 0;
299
+ const valid = errors2.length === 0;
300
+ return valid;
273
301
  }, [
274
302
  schema,
275
303
  onValidate
@@ -307,7 +335,8 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
307
335
  }, [
308
336
  values,
309
337
  validate,
310
- onSave
338
+ onSave,
339
+ changed
311
340
  ]);
312
341
  const getStatus = useCallback((property) => ({
313
342
  status: errors[property] ? "error" : void 0,
@@ -316,8 +345,8 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
316
345
  touched,
317
346
  errors
318
347
  ]);
319
- const getValue = (property) => {
320
- return getByPath(values, property);
348
+ const getFormValue = (property) => {
349
+ return getValue(values, property);
321
350
  };
322
351
  const onValueChange = (property, type, value) => {
323
352
  let parsedValue = value;
@@ -328,13 +357,15 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
328
357
  } catch (err) {
329
358
  log.catch(err, void 0, {
330
359
  F: __dxlog_file,
331
- L: 183,
360
+ L: 178,
332
361
  S: void 0,
333
362
  C: (f, a) => f(...a)
334
363
  });
335
364
  parsedValue = void 0;
336
365
  }
337
- const newValues = setByPath(values, property, parsedValue);
366
+ const newValues = {
367
+ ...setValue(values, property, parsedValue)
368
+ };
338
369
  setValues(newValues);
339
370
  setChanged((prev) => ({
340
371
  ...prev,
@@ -372,7 +403,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
372
403
  handleSave,
373
404
  // Field utils.
374
405
  getStatus,
375
- getValue,
406
+ getValue: getFormValue,
376
407
  onValueChange,
377
408
  onBlur
378
409
  };
@@ -380,7 +411,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
380
411
  var createKeySet = (obj, value) => {
381
412
  invariant(obj, void 0, {
382
413
  F: __dxlog_file,
383
- L: 234,
414
+ L: 229,
384
415
  S: void 0,
385
416
  A: [
386
417
  "obj",
@@ -400,20 +431,6 @@ var flatMap = (errors) => {
400
431
  return result;
401
432
  }, {});
402
433
  };
403
- var getByPath = (obj, path) => {
404
- const [key, index] = path.split(".");
405
- return index === void 0 ? obj[key] : obj[key][parseInt(index)];
406
- };
407
- var setByPath = (obj, path, value) => {
408
- const [key, index] = path.split(".");
409
- const newValue = index === void 0 ? value : [
410
- ...obj[key]
411
- ].map((v, i) => i === parseInt(index) ? value : v);
412
- return {
413
- ...obj,
414
- [key]: newValue
415
- };
416
- };
417
434
 
418
435
  // packages/ui/react-ui-form/src/components/Form/Form.tsx
419
436
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
@@ -450,7 +467,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
450
467
  errors
451
468
  }, {
452
469
  F: __dxlog_file2,
453
- L: 100,
470
+ L: 99,
454
471
  S: void 0,
455
472
  C: (f, a) => f(...a)
456
473
  });
@@ -458,9 +475,9 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
458
475
  }, [
459
476
  errors
460
477
  ]);
461
- return /* @__PURE__ */ React5.createElement("div", {
478
+ return /* @__PURE__ */ React6.createElement("div", {
462
479
  role: "form",
463
- className: mx("flex flex-col w-full gap-2 py-2", classNames),
480
+ className: mx2("flex flex-col w-full gap-2 py-2", classNames),
464
481
  "data-testid": testId
465
482
  }, properties.map((property) => {
466
483
  const { ast, name, type, format, title, description, examples, options, array } = property;
@@ -473,11 +490,11 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
473
490
  let InputComponent = Custom?.[key.join(".")];
474
491
  if (!InputComponent) {
475
492
  if (options) {
476
- return /* @__PURE__ */ React5.createElement("div", {
493
+ return /* @__PURE__ */ React6.createElement("div", {
477
494
  key: name,
478
495
  role: "none",
479
496
  className: padding
480
- }, /* @__PURE__ */ React5.createElement(SelectInput, {
497
+ }, /* @__PURE__ */ React6.createElement(SelectInput, {
481
498
  type,
482
499
  format,
483
500
  property: name,
@@ -493,7 +510,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
493
510
  }
494
511
  InputComponent = getInputComponent(type, format);
495
512
  if (array) {
496
- return /* @__PURE__ */ React5.createElement(ArrayField, {
513
+ return /* @__PURE__ */ React6.createElement(ArrayField, {
497
514
  key: name,
498
515
  name,
499
516
  type,
@@ -515,12 +532,12 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
515
532
  const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(ast, AST.isTypeLiteral);
516
533
  if (typeLiteral) {
517
534
  const schema2 = S.make(typeLiteral);
518
- return /* @__PURE__ */ React5.createElement("div", {
535
+ return /* @__PURE__ */ React6.createElement("div", {
519
536
  key: name,
520
537
  role: "none"
521
- }, /* @__PURE__ */ React5.createElement("div", {
538
+ }, /* @__PURE__ */ React6.createElement("div", {
522
539
  className: padding
523
- }, label), /* @__PURE__ */ React5.createElement(Form, {
540
+ }, label), /* @__PURE__ */ React6.createElement(Form, {
524
541
  schema: schema2,
525
542
  path: key,
526
543
  values: values[name] ?? {},
@@ -536,17 +553,17 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
536
553
  type
537
554
  }, {
538
555
  F: __dxlog_file2,
539
- L: 185,
556
+ L: 184,
540
557
  S: void 0,
541
558
  C: (f, a) => f(...a)
542
559
  });
543
560
  return null;
544
561
  }
545
- return /* @__PURE__ */ React5.createElement("div", {
562
+ return /* @__PURE__ */ React6.createElement("div", {
546
563
  key: name,
547
564
  role: "none",
548
565
  className: padding
549
- }, /* @__PURE__ */ React5.createElement(InputComponent, {
566
+ }, /* @__PURE__ */ React6.createElement(InputComponent, {
550
567
  type,
551
568
  format,
552
569
  property: name,
@@ -555,7 +572,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
555
572
  placeholder,
556
573
  ...inputProps
557
574
  }));
558
- }).filter(isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React5.createElement(FormActions, {
575
+ }).filter(isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React6.createElement(FormActions, {
559
576
  onCancel,
560
577
  onSubmit: handleSave,
561
578
  canSubmit: canSave,
@@ -575,26 +592,26 @@ var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholde
575
592
  const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(elementType, AST.isTypeLiteral);
576
593
  if (typeLiteral) {
577
594
  const schema = S.make(typeLiteral);
578
- return /* @__PURE__ */ React5.createElement("div", {
595
+ return /* @__PURE__ */ React6.createElement("div", {
579
596
  key: name,
580
597
  role: "none",
581
- className: mx(padding)
582
- }, /* @__PURE__ */ React5.createElement(InputHeader, null, label), /* @__PURE__ */ React5.createElement("div", {
598
+ className: mx2(padding)
599
+ }, /* @__PURE__ */ React6.createElement(InputHeader, null, label), /* @__PURE__ */ React6.createElement("div", {
583
600
  role: "none",
584
601
  className: "flex flex-col gap-1"
585
602
  }, arrayValues.map((value, index) => {
586
- return /* @__PURE__ */ React5.createElement("div", {
603
+ return /* @__PURE__ */ React6.createElement("div", {
587
604
  key: index,
588
605
  role: "none",
589
606
  className: "flex items-center gap-1"
590
- }, /* @__PURE__ */ React5.createElement("div", {
607
+ }, /* @__PURE__ */ React6.createElement("div", {
591
608
  role: "none",
592
609
  className: "flex-1"
593
- }, /* @__PURE__ */ React5.createElement(Form, {
610
+ }, /* @__PURE__ */ React6.createElement(Form, {
594
611
  schema,
595
612
  path: [
596
613
  ...key,
597
- index.toString()
614
+ `[${index}]`
598
615
  ],
599
616
  values: value,
600
617
  onValuesChanged: (childValues) => {
@@ -605,7 +622,7 @@ var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholde
605
622
  inputProps.onValueChange(name, "object", newValues);
606
623
  },
607
624
  Custom
608
- })), /* @__PURE__ */ React5.createElement(IconButton, {
625
+ })), /* @__PURE__ */ React6.createElement(IconButton, {
609
626
  icon: "ph--trash--regular",
610
627
  iconOnly: true,
611
628
  label: t("button remove"),
@@ -614,10 +631,10 @@ var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholde
614
631
  inputProps.onValueChange(name, type, newValues);
615
632
  }
616
633
  }));
617
- })), /* @__PURE__ */ React5.createElement("div", {
634
+ })), /* @__PURE__ */ React6.createElement("div", {
618
635
  role: "none",
619
636
  className: "flex justify-between items-center plb-1"
620
- }, /* @__PURE__ */ React5.createElement(IconButton, {
637
+ }, /* @__PURE__ */ React6.createElement(IconButton, {
621
638
  icon: "ph--plus--regular",
622
639
  iconOnly: true,
623
640
  label: t("button add"),
@@ -630,7 +647,7 @@ var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholde
630
647
  }
631
648
  })));
632
649
  }
633
- return /* @__PURE__ */ React5.createElement("div", {
650
+ return /* @__PURE__ */ React6.createElement("div", {
634
651
  key: name,
635
652
  role: "none"
636
653
  }, "Nested form not supported in arrays, yet.");
@@ -639,30 +656,30 @@ var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholde
639
656
  if (!InputComponent) {
640
657
  return null;
641
658
  }
642
- return /* @__PURE__ */ React5.createElement("div", {
659
+ return /* @__PURE__ */ React6.createElement("div", {
643
660
  role: "none",
644
661
  key: "meta-input",
645
- className: mx(padding)
646
- }, /* @__PURE__ */ React5.createElement(InputHeader, null, label), /* @__PURE__ */ React5.createElement("div", {
662
+ className: mx2(padding)
663
+ }, /* @__PURE__ */ React6.createElement(InputHeader, null, label), /* @__PURE__ */ React6.createElement("div", {
647
664
  role: "none",
648
665
  className: "flex flex-col gap-1"
649
- }, arrayValues.map((_, index) => /* @__PURE__ */ React5.createElement("div", {
666
+ }, arrayValues.map((_, index) => /* @__PURE__ */ React6.createElement("div", {
650
667
  key: index,
651
668
  role: "none",
652
669
  className: "flex items-start gap-1"
653
- }, /* @__PURE__ */ React5.createElement("div", {
670
+ }, /* @__PURE__ */ React6.createElement("div", {
654
671
  role: "none",
655
672
  className: "flex-1"
656
- }, /* @__PURE__ */ React5.createElement(InputComponent, {
673
+ }, /* @__PURE__ */ React6.createElement(InputComponent, {
657
674
  type,
658
675
  format,
659
676
  label,
660
677
  inputOnly: true,
661
- property: `${name}.${index}`,
678
+ property: `${name}[${index}]`,
662
679
  disabled: readonly,
663
680
  placeholder,
664
681
  ...inputProps
665
- })), /* @__PURE__ */ React5.createElement(IconButton, {
682
+ })), /* @__PURE__ */ React6.createElement(IconButton, {
666
683
  icon: "ph--trash--regular",
667
684
  iconOnly: true,
668
685
  label: t("button remove"),
@@ -670,10 +687,10 @@ var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholde
670
687
  const newValues = arrayValues.filter((_2, i) => i !== index);
671
688
  inputProps.onValueChange(name, type, newValues);
672
689
  }
673
- })))), /* @__PURE__ */ React5.createElement("div", {
690
+ })))), /* @__PURE__ */ React6.createElement("div", {
674
691
  role: "none",
675
692
  className: "flex justify-between items-center plb-1"
676
- }, /* @__PURE__ */ React5.createElement(IconButton, {
693
+ }, /* @__PURE__ */ React6.createElement(IconButton, {
677
694
  icon: "ph--plus--regular",
678
695
  iconOnly: true,
679
696
  label: t("button add"),
@@ -688,18 +705,18 @@ var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholde
688
705
  };
689
706
  var FormActions = ({ onCancel, onSubmit, canSubmit, readonly }) => {
690
707
  const { t } = useTranslation2(translationKey);
691
- return /* @__PURE__ */ React5.createElement("div", {
708
+ return /* @__PURE__ */ React6.createElement("div", {
692
709
  role: "none",
693
710
  className: "flex justify-center"
694
- }, /* @__PURE__ */ React5.createElement("div", {
711
+ }, /* @__PURE__ */ React6.createElement("div", {
695
712
  role: "none",
696
- className: mx(onCancel && !readonly && "grid grid-cols-2 gap-2")
697
- }, onCancel && !readonly && /* @__PURE__ */ React5.createElement(IconButton, {
713
+ className: mx2(onCancel && !readonly && "grid grid-cols-2 gap-2")
714
+ }, onCancel && !readonly && /* @__PURE__ */ React6.createElement(IconButton, {
698
715
  "data-testid": "cancel-button",
699
716
  icon: "ph--x--regular",
700
717
  label: t("button cancel"),
701
718
  onClick: onCancel
702
- }), onSubmit && /* @__PURE__ */ React5.createElement(IconButton, {
719
+ }), onSubmit && /* @__PURE__ */ React6.createElement(IconButton, {
703
720
  type: "submit",
704
721
  "data-testid": "save-button",
705
722
  disabled: !canSubmit,
@@ -723,9 +740,11 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
723
740
  if (!registry) {
724
741
  return;
725
742
  }
726
- const subscription = registry.subscribe(setSchemas);
743
+ const subscription = registry.query().subscribe((query) => setSchemas(query.results), {
744
+ fire: true
745
+ });
727
746
  const t2 = setTimeout(async () => {
728
- const schemas2 = await registry.query();
747
+ const schemas2 = await registry.query().run();
729
748
  setSchemas(schemas2);
730
749
  });
731
750
  return () => {
@@ -735,9 +754,9 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
735
754
  }, [
736
755
  registry
737
756
  ]);
738
- const [schema, setSchema] = useState2();
757
+ const [referenceSchema, setReferenceSchema] = useState2();
739
758
  useEffect3(() => {
740
- setSchema(schemas.find((schema2) => schema2.typename === props?.referenceSchema));
759
+ setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
741
760
  }, [
742
761
  schemas,
743
762
  props?.referenceSchema
@@ -746,14 +765,24 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
746
765
  fieldSchema: getFormatSchema(props?.format)
747
766
  });
748
767
  const handleValuesChanged = useCallback2((_props) => {
749
- if (_props.format !== props.format) {
750
- setFieldSchema({
751
- fieldSchema: getFormatSchema(_props.format)
752
- });
753
- }
754
- if (_props.referenceSchema !== props.referenceSchema) {
755
- setSchema(schemas.find((schema2) => schema2.typename === _props.referenceSchema));
756
- }
768
+ setFieldSchema((prev) => {
769
+ const fieldSchema2 = getFormatSchema(_props.format);
770
+ if (prev.fieldSchema === fieldSchema2) {
771
+ return prev;
772
+ }
773
+ return {
774
+ fieldSchema: fieldSchema2
775
+ };
776
+ });
777
+ setReferenceSchema((prev) => {
778
+ if (_props.referenceSchema !== prev?.typename) {
779
+ const newSchema = schemas.find((schema) => schema.typename === _props.referenceSchema);
780
+ if (newSchema) {
781
+ return newSchema;
782
+ }
783
+ }
784
+ return prev;
785
+ });
757
786
  setProps((props2) => {
758
787
  const type = formatToType[_props.format];
759
788
  if (props2.type !== type) {
@@ -767,7 +796,8 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
767
796
  });
768
797
  }, [
769
798
  schemas,
770
- props
799
+ props.format,
800
+ props.referenceSchema
771
801
  ]);
772
802
  const handleValidate = useCallback2(({ property }) => {
773
803
  if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
@@ -799,23 +829,49 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
799
829
  }, [
800
830
  onSave
801
831
  ]);
832
+ const Custom = useMemo3(() => ({
833
+ ["format"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
834
+ ...props2,
835
+ options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
836
+ value,
837
+ label: t(`format ${value}`)
838
+ }))
839
+ }),
840
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
841
+ ...props2,
842
+ options: schemas.map((schema) => ({
843
+ value: schema.typename
844
+ }))
845
+ }),
846
+ ["referencePath"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
847
+ ...props2,
848
+ options: referenceSchema ? getSchemaProperties2(referenceSchema.ast).sort(sortProperties).map((p) => ({
849
+ value: p.name
850
+ })) : []
851
+ })
852
+ }), [
853
+ t,
854
+ schemas,
855
+ referenceSchema
856
+ ]);
857
+ const propIsNotType = useCallback2((props2) => props2.filter((p) => p.name !== "type"), []);
802
858
  if (!fieldSchema) {
803
859
  log3.warn("invalid format", {
804
860
  props
805
861
  }, {
806
862
  F: __dxlog_file3,
807
- L: 118,
863
+ L: 173,
808
864
  S: void 0,
809
865
  C: (f, a) => f(...a)
810
866
  });
811
867
  return null;
812
868
  }
813
- return /* @__PURE__ */ React6.createElement(Form, {
869
+ return /* @__PURE__ */ React7.createElement(Form, {
814
870
  key: field.id,
815
871
  autoFocus: true,
816
872
  values: props,
817
873
  schema: fieldSchema,
818
- filter: (props2) => props2.filter((p) => p.name !== "type"),
874
+ filter: propIsNotType,
819
875
  sort: [
820
876
  "property",
821
877
  "format"
@@ -824,36 +880,16 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
824
880
  onValidate: handleValidate,
825
881
  onSave: handleSave,
826
882
  onCancel: handleCancel,
827
- Custom: {
828
- ["format"]: (props2) => /* @__PURE__ */ React6.createElement(SelectInput, {
829
- ...props2,
830
- options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
831
- value,
832
- label: t(`format ${value}`)
833
- }))
834
- }),
835
- ["referenceSchema"]: (props2) => /* @__PURE__ */ React6.createElement(SelectInput, {
836
- ...props2,
837
- options: schemas.map((schema2) => ({
838
- value: schema2.typename
839
- }))
840
- }),
841
- ["referencePath"]: (props2) => /* @__PURE__ */ React6.createElement(SelectInput, {
842
- ...props2,
843
- options: schema ? getSchemaProperties2(schema.schema.ast).sort(sortProperties).map((p) => ({
844
- value: p.name
845
- })) : []
846
- })
847
- }
883
+ Custom
848
884
  });
849
885
  };
850
886
 
851
887
  // packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
852
- import React7, { useCallback as useCallback3, useMemo as useMemo3, useState as useState3 } from "react";
888
+ import React8, { useCallback as useCallback3, useMemo as useMemo4, useState as useState3 } from "react";
853
889
  import { AST as AST2, Format, S as S2 } from "@dxos/echo-schema";
854
890
  import { IconButton as IconButton2, useTranslation as useTranslation4 } from "@dxos/react-ui";
855
891
  import { List } from "@dxos/react-ui-list";
856
- import { ghostHover, inputTextLabel, mx as mx2 } from "@dxos/react-ui-theme";
892
+ import { ghostHover, inputTextLabel, mx as mx3 } from "@dxos/react-ui-theme";
857
893
  import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
858
894
  import { arrayMove } from "@dxos/util";
859
895
  var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
@@ -867,12 +903,12 @@ var ViewMetaSchema = S2.Struct({
867
903
  }).pipe(S2.mutable);
868
904
  var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onDelete }) => {
869
905
  const { t } = useTranslation4(translationKey);
870
- const projection = useMemo3(() => new ViewProjection(schema, view), [
906
+ const projection = useMemo4(() => new ViewProjection(schema, view), [
871
907
  schema,
872
908
  view
873
909
  ]);
874
910
  const [field, setField] = useState3();
875
- const viewValues = useMemo3(() => {
911
+ const viewValues = useMemo4(() => {
876
912
  return {
877
913
  name: view.name,
878
914
  // TODO(burdon): Need to warn user of possible consequences of editing.
@@ -907,52 +943,52 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
907
943
  view.fields
908
944
  ]);
909
945
  const handleClose = useCallback3(() => setField(void 0), []);
910
- return /* @__PURE__ */ React7.createElement("div", {
946
+ return /* @__PURE__ */ React8.createElement("div", {
911
947
  role: "none",
912
- className: mx2("flex flex-col w-full divide-y divide-separator", classNames)
913
- }, /* @__PURE__ */ React7.createElement(Form, {
948
+ className: mx3("flex flex-col w-full divide-y divide-separator", classNames)
949
+ }, /* @__PURE__ */ React8.createElement(Form, {
914
950
  autoFocus: true,
915
951
  autoSave: true,
916
952
  schema: ViewMetaSchema,
917
953
  values: viewValues,
918
954
  onSave: handleViewUpdate
919
- }), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement("div", {
955
+ }), /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("div", {
920
956
  role: "none",
921
957
  className: "p-2"
922
- }, /* @__PURE__ */ React7.createElement("label", {
923
- className: mx2(inputTextLabel)
924
- }, t("fields label"))), /* @__PURE__ */ React7.createElement(List.Root, {
958
+ }, /* @__PURE__ */ React8.createElement("label", {
959
+ className: mx3(inputTextLabel)
960
+ }, t("fields label"))), /* @__PURE__ */ React8.createElement(List.Root, {
925
961
  items: view.fields,
926
962
  isItem: S2.is(FieldSchema),
927
963
  getId: (field2) => field2.id,
928
964
  onMove: handleMove
929
- }, ({ items: fields }) => /* @__PURE__ */ React7.createElement(React7.Fragment, null, showHeading && /* @__PURE__ */ React7.createElement("div", {
965
+ }, ({ items: fields }) => /* @__PURE__ */ React8.createElement(React8.Fragment, null, showHeading && /* @__PURE__ */ React8.createElement("div", {
930
966
  role: "heading",
931
967
  className: grid
932
- }, /* @__PURE__ */ React7.createElement("div", null), /* @__PURE__ */ React7.createElement("div", {
968
+ }, /* @__PURE__ */ React8.createElement("div", null), /* @__PURE__ */ React8.createElement("div", {
933
969
  className: "flex items-center text-sm"
934
- }, t("field path label"))), /* @__PURE__ */ React7.createElement("div", {
970
+ }, t("field path label"))), /* @__PURE__ */ React8.createElement("div", {
935
971
  role: "list",
936
972
  className: "flex flex-col w-full"
937
- }, fields?.map((field2) => /* @__PURE__ */ React7.createElement(List.Item, {
973
+ }, fields?.map((field2) => /* @__PURE__ */ React8.createElement(List.Item, {
938
974
  key: field2.id,
939
975
  item: field2,
940
- classNames: mx2(grid, ghostHover, "cursor-pointer")
941
- }, /* @__PURE__ */ React7.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React7.createElement(List.ItemTitle, {
976
+ classNames: mx3(grid, ghostHover, "cursor-pointer")
977
+ }, /* @__PURE__ */ React8.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React8.createElement(List.ItemTitle, {
942
978
  onClick: () => handleSelect(field2)
943
- }, field2.path), /* @__PURE__ */ React7.createElement(List.ItemDeleteButton, {
979
+ }, field2.path), /* @__PURE__ */ React8.createElement(List.ItemDeleteButton, {
944
980
  disabled: view.fields.length <= 1,
945
981
  onClick: () => onDelete(field2.id)
946
- }))))))), field && /* @__PURE__ */ React7.createElement(FieldEditor, {
982
+ }))))))), field && /* @__PURE__ */ React8.createElement(FieldEditor, {
947
983
  key: field.id,
948
984
  view,
949
985
  projection,
950
986
  field,
951
987
  registry,
952
988
  onSave: handleClose
953
- }), !readonly && !field && /* @__PURE__ */ React7.createElement("div", {
989
+ }), !readonly && !field && /* @__PURE__ */ React8.createElement("div", {
954
990
  className: "flex p-2 justify-center"
955
- }, /* @__PURE__ */ React7.createElement(IconButton2, {
991
+ }, /* @__PURE__ */ React8.createElement(IconButton2, {
956
992
  icon: "ph--plus--regular",
957
993
  label: t("button add property"),
958
994
  onClick: handleAdd,
@@ -1186,11 +1222,12 @@ export {
1186
1222
  FieldEditor,
1187
1223
  Form,
1188
1224
  FormActions,
1189
- GeiPointInput,
1225
+ GeoPointInput,
1190
1226
  InputHeader,
1191
1227
  NumberInput,
1192
1228
  SelectInput,
1193
1229
  TextInput,
1230
+ TupleInput,
1194
1231
  ViewEditor,
1195
1232
  cellClassesForFieldType,
1196
1233
  cellClassesForRowSelection,