@dxos/react-ui-form 0.7.5-feature-compute.4d9d99a → 0.7.5-labs.a279d8c

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 +416 -409
  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 +461 -469
  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 +416 -409
  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/Form/ArrayField.d.ts +16 -0
  11. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -0
  12. package/dist/types/src/components/Form/Defaults.d.ts +5 -6
  13. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.d.ts +10 -20
  15. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.stories.d.ts +2 -1
  17. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/FormActions.d.ts +7 -0
  19. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -0
  20. package/dist/types/src/components/Form/FormContent.d.ts +26 -0
  21. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -0
  22. package/dist/types/src/components/Form/FormContext.d.ts +20 -0
  23. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -0
  24. package/dist/types/src/components/Form/Input.d.ts +5 -6
  25. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  26. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +1 -2
  27. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/custom/TupleInput.d.ts +1 -2
  29. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  30. package/dist/types/src/components/Form/factory.d.ts +2 -2
  31. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  32. package/dist/types/src/hooks/useForm.d.ts +9 -10
  33. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  34. package/package.json +23 -23
  35. package/src/components/FieldEditor/FieldEditor.tsx +4 -4
  36. package/src/components/Form/ArrayField.tsx +111 -0
  37. package/src/components/Form/Defaults.tsx +18 -33
  38. package/src/components/Form/Form.stories.tsx +15 -5
  39. package/src/components/Form/Form.tsx +37 -359
  40. package/src/components/Form/FormActions.tsx +41 -0
  41. package/src/components/Form/FormContent.tsx +155 -0
  42. package/src/components/Form/FormContext.tsx +48 -0
  43. package/src/components/Form/Input.tsx +5 -6
  44. package/src/components/Form/custom/GeoPointInput.tsx +6 -15
  45. package/src/components/Form/custom/TupleInput.tsx +5 -9
  46. package/src/components/Form/factory.tsx +2 -5
  47. package/src/hooks/useForm.ts +54 -46
@@ -82,11 +82,11 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
82
82
  };
83
83
 
84
84
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
85
- import React7, { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo3, useState as useState2 } from "react";
85
+ import React11, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo5, useState as useState2 } from "react";
86
86
  import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
87
- import { log as log3 } from "@dxos/log";
88
- import { useTranslation as useTranslation3 } from "@dxos/react-ui";
89
- import { getFormatSchema, getSchemaProperties as getSchemaProperties2, sortProperties } from "@dxos/schema";
87
+ import { log as log2 } from "@dxos/log";
88
+ import { useTranslation as useTranslation4 } from "@dxos/react-ui";
89
+ import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
90
90
 
91
91
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
92
92
  import React3 from "react";
@@ -113,10 +113,10 @@ var InputHeader = ({ children, error }) => {
113
113
  };
114
114
 
115
115
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
116
- var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
116
+ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
117
117
  const { t } = useTranslation(translationKey);
118
- const { status, error } = getStatus?.(property);
119
- const [lng = 0, lat = 0] = getValue2(property) ?? [];
118
+ const { status, error } = getStatus();
119
+ const [lng = 0, lat = 0] = getValue3() ?? [];
120
120
  return /* @__PURE__ */ React3.createElement(Input2.Root, {
121
121
  validationValence: status
122
122
  }, /* @__PURE__ */ React3.createElement(InputHeader, {
@@ -128,7 +128,7 @@ var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: get
128
128
  disabled,
129
129
  placeholder: t("placeholder longitude"),
130
130
  value: lng,
131
- onChange: (event) => onValueChange(property, type, [
131
+ onChange: (event) => onValueChange(type, [
132
132
  lat,
133
133
  safeParseFloat(event.target.value, 0)
134
134
  ]),
@@ -138,7 +138,7 @@ var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: get
138
138
  disabled,
139
139
  placeholder: t("placeholder latitude"),
140
140
  value: lat,
141
- onChange: (event) => onValueChange(property, type, [
141
+ onChange: (event) => onValueChange(type, [
142
142
  safeParseFloat(event.target.value, 0),
143
143
  lng
144
144
  ]),
@@ -157,9 +157,9 @@ var gridCols = [
157
157
  "grid-cols-3",
158
158
  "grid-cols-4"
159
159
  ];
160
- var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
161
- const { status, error } = getStatus?.(property);
162
- const values = getValue2(property) ?? {};
160
+ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
161
+ const { status, error } = getStatus();
162
+ const values = getValue3() ?? {};
163
163
  return /* @__PURE__ */ React4.createElement(Input3.Root, {
164
164
  validationValence: status
165
165
  }, /* @__PURE__ */ React4.createElement(InputHeader, {
@@ -171,7 +171,7 @@ var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValu
171
171
  type: "number",
172
172
  disabled,
173
173
  value: values[prop],
174
- onChange: (event) => onValueChange(property, type, {
174
+ onChange: (event) => onValueChange(type, {
175
175
  ...values,
176
176
  [prop]: safeParseFloat2(event.target.value, 0)
177
177
  }),
@@ -182,8 +182,8 @@ var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValu
182
182
  // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
183
183
  import React5 from "react";
184
184
  import { Input as Input4, Select } from "@dxos/react-ui";
185
- var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
186
- const { status, error } = getStatus?.(property);
185
+ var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
186
+ const { status, error } = getStatus();
187
187
  return /* @__PURE__ */ React5.createElement(Input4.Root, {
188
188
  validationValence: status
189
189
  }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
@@ -191,13 +191,13 @@ var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getS
191
191
  }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.TextInput, {
192
192
  disabled,
193
193
  placeholder,
194
- value: getValue2(property) ?? "",
195
- onChange: (event) => onValueChange(property, type, event.target.value),
194
+ value: getValue3() ?? "",
195
+ onChange: (event) => onValueChange(type, event.target.value),
196
196
  onBlur
197
197
  }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.Validation, null, error));
198
198
  };
199
- var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
200
- const { status, error } = getStatus?.(property);
199
+ var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
200
+ const { status, error } = getStatus();
201
201
  return /* @__PURE__ */ React5.createElement(Input4.Root, {
202
202
  validationValence: status
203
203
  }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
@@ -206,31 +206,31 @@ var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, ge
206
206
  type: "number",
207
207
  disabled,
208
208
  placeholder,
209
- value: getValue2(property) ?? 0,
210
- onChange: (event) => onValueChange(property, type, event.target.value),
209
+ value: getValue3() ?? 0,
210
+ onChange: (event) => onValueChange(type, event.target.value),
211
211
  onBlur
212
212
  }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
213
213
  };
214
- var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue: getValue2, onValueChange }) => {
215
- const { status, error } = getStatus?.(property);
214
+ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
215
+ const { status, error } = getStatus();
216
216
  return /* @__PURE__ */ React5.createElement(Input4.Root, {
217
217
  validationValence: status
218
218
  }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
219
219
  error
220
220
  }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.Switch, {
221
- checked: getValue2(property),
222
- onCheckedChange: (value) => onValueChange(property, type, value)
221
+ checked: getValue3(),
222
+ onCheckedChange: (value) => onValueChange(type, value)
223
223
  }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
224
224
  };
225
- var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue2, onValueChange }) => {
226
- const { status, error } = getStatus?.(property);
225
+ var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
226
+ const { status, error } = getStatus();
227
227
  return /* @__PURE__ */ React5.createElement(Input4.Root, {
228
228
  validationValence: status
229
229
  }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
230
230
  error
231
231
  }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Select.Root, {
232
- value: getValue2(property),
233
- onValueChange: (value) => onValueChange(property, type, value)
232
+ value: getValue3(),
233
+ onValueChange: (value) => onValueChange(type, value)
234
234
  }, /* @__PURE__ */ React5.createElement(Select.TriggerButton, {
235
235
  classNames: "is-full",
236
236
  disabled,
@@ -245,38 +245,24 @@ var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, op
245
245
  };
246
246
 
247
247
  // packages/ui/react-ui-form/src/components/Form/Form.tsx
248
- import { pipe } from "effect";
249
- import { capitalize } from "effect/String";
250
- import React6, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
251
- import { AST as AST2, S } from "@dxos/echo-schema";
252
- import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
253
- import { log as log2 } from "@dxos/log";
248
+ import React10, { useMemo as useMemo4 } from "react";
249
+ import { mx as mx5 } from "@dxos/react-ui-theme";
250
+
251
+ // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
252
+ import React7 from "react";
254
253
  import { IconButton, useTranslation as useTranslation2 } from "@dxos/react-ui";
255
254
  import { mx as mx2 } from "@dxos/react-ui-theme";
256
- import { getSchemaProperties } from "@dxos/schema";
257
- import { isNotFalsy } from "@dxos/util";
258
255
 
259
- // packages/ui/react-ui-form/src/components/Form/factory.tsx
260
- import { FormatEnum } from "@dxos/echo-schema";
261
- var getInputComponent = (type, format) => {
262
- switch (format) {
263
- case FormatEnum.LatLng:
264
- return GeoPointInput;
265
- }
266
- switch (type) {
267
- case "string":
268
- return TextInput;
269
- case "number":
270
- return NumberInput;
271
- case "boolean":
272
- return BooleanInput;
273
- }
274
- };
256
+ // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
257
+ import React6, { createContext, useContext } from "react";
258
+ import { raise } from "@dxos/debug";
259
+ import { getValue as getValue2 } from "@dxos/echo-schema";
260
+ import { createJsonPath as createJsonPath2 } from "@dxos/effect";
275
261
 
276
262
  // packages/ui/react-ui-form/src/hooks/useForm.ts
277
263
  import { useCallback, useEffect, useMemo, useState } from "react";
278
264
  import { getValue, setValue } from "@dxos/echo-schema";
279
- import { AST } from "@dxos/effect";
265
+ import { AST, createJsonPath, fromEffectValidationPath } from "@dxos/effect";
280
266
  import { invariant } from "@dxos/invariant";
281
267
  import { log } from "@dxos/log";
282
268
  import { validateSchema } from "@dxos/schema";
@@ -327,8 +313,8 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
327
313
  values,
328
314
  schemaDirty
329
315
  ]);
330
- const canSave = useMemo(() => !saving && Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
331
- values,
316
+ const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors
317
+ !Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
332
318
  touched,
333
319
  errors,
334
320
  saving
@@ -350,17 +336,21 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
350
336
  onSave,
351
337
  changed
352
338
  ]);
353
- const getStatus = useCallback((property) => ({
354
- status: errors[property] ? "error" : void 0,
355
- error: errors[property] ? errors[property] : void 0
356
- }), [
357
- touched,
339
+ const getStatus = useCallback((path) => {
340
+ const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
341
+ const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
342
+ return {
343
+ status: matchingError ? "error" : void 0,
344
+ error: matchingError ? matchingError[1] : void 0
345
+ };
346
+ }, [
358
347
  errors
359
348
  ]);
360
- const getFormValue = (property) => {
361
- return getValue(values, property);
349
+ const getFormValue = (path) => {
350
+ return getValue(values, createJsonPath(path));
362
351
  };
363
- const onValueChange = (property, type, value) => {
352
+ const onValueChange = (path, type, value) => {
353
+ const jsonPath = createJsonPath(path);
364
354
  let parsedValue = value;
365
355
  try {
366
356
  if (type === "number") {
@@ -369,19 +359,19 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
369
359
  } catch (err) {
370
360
  log.catch(err, void 0, {
371
361
  F: __dxlog_file,
372
- L: 179,
362
+ L: 194,
373
363
  S: void 0,
374
364
  C: (f, a) => f(...a)
375
365
  });
376
366
  parsedValue = void 0;
377
367
  }
378
368
  const newValues = {
379
- ...setValue(values, property, parsedValue)
369
+ ...setValue(values, jsonPath, parsedValue)
380
370
  };
381
371
  setValues(newValues);
382
372
  setChanged((prev) => ({
383
373
  ...prev,
384
- [property]: true
374
+ [jsonPath]: true
385
375
  }));
386
376
  onValuesChanged?.(newValues);
387
377
  const isValid = validate(newValues);
@@ -391,15 +381,12 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
391
381
  });
392
382
  }
393
383
  };
394
- const onBlur = useCallback((event) => {
395
- const { name } = event.target;
384
+ const onTouched = useCallback((path) => {
385
+ const jsonPath = createJsonPath(path);
396
386
  setTouched((touched2) => ({
397
387
  ...touched2,
398
- [name]: true
388
+ [jsonPath]: true
399
389
  }));
400
- if (event.relatedTarget?.getAttribute("type") === "submit") {
401
- setTouched(createKeySet(values, true));
402
- }
403
390
  validate(values);
404
391
  }, [
405
392
  validate,
@@ -417,13 +404,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
417
404
  getStatus,
418
405
  getValue: getFormValue,
419
406
  onValueChange,
420
- onBlur
407
+ onTouched
421
408
  };
422
409
  };
423
410
  var createKeySet = (obj, value) => {
424
411
  invariant(obj, void 0, {
425
412
  F: __dxlog_file,
426
- L: 230,
413
+ L: 236,
427
414
  S: void 0,
428
415
  A: [
429
416
  "obj",
@@ -437,338 +424,359 @@ var createKeySet = (obj, value) => {
437
424
  };
438
425
  var flatMap = (errors) => {
439
426
  return errors.reduce((result, { path, message }) => {
440
- if (!(path in result)) {
441
- result[path] = message;
427
+ const jsonPath = fromEffectValidationPath(path);
428
+ if (!(jsonPath in result)) {
429
+ result[jsonPath] = message;
442
430
  }
443
431
  return result;
444
432
  }, {});
445
433
  };
446
434
 
447
- // packages/ui/react-ui-form/src/components/Form/Form.tsx
448
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
435
+ // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
436
+ var FormContext = /* @__PURE__ */ createContext(void 0);
437
+ var useFormContext = () => {
438
+ return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
439
+ };
440
+ var useFormValues = (path = []) => {
441
+ const { values: formValues } = useFormContext();
442
+ const jsonPath = createJsonPath2(path);
443
+ return getValue2(formValues, jsonPath);
444
+ };
445
+ var useInputProps = (path = []) => {
446
+ const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
447
+ return {
448
+ getStatus: () => getStatus(path),
449
+ getValue: () => getFormValue(path),
450
+ onValueChange: (type, value) => onValueChange(path, type, value),
451
+ onBlur: () => onTouched(path)
452
+ };
453
+ };
454
+ var FormProvider = ({ children, ...formOptions }) => {
455
+ const formHandler = useForm(formOptions);
456
+ return /* @__PURE__ */ React6.createElement(FormContext.Provider, {
457
+ value: formHandler
458
+ }, children);
459
+ };
460
+
461
+ // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
462
+ var FormActions = ({ onCancel, readonly }) => {
463
+ const { t } = useTranslation2(translationKey);
464
+ const { canSave, handleSave } = useFormContext();
465
+ return /* @__PURE__ */ React7.createElement("div", {
466
+ role: "none",
467
+ className: "flex justify-center"
468
+ }, /* @__PURE__ */ React7.createElement("div", {
469
+ role: "none",
470
+ className: mx2(onCancel && !readonly && "grid grid-cols-2 gap-2")
471
+ }, onCancel && !readonly && /* @__PURE__ */ React7.createElement(IconButton, {
472
+ "data-testid": "cancel-button",
473
+ icon: "ph--x--regular",
474
+ label: t("button cancel"),
475
+ onClick: onCancel
476
+ }), handleSave && /* @__PURE__ */ React7.createElement(IconButton, {
477
+ type: "submit",
478
+ "data-testid": "save-button",
479
+ disabled: !canSave,
480
+ icon: "ph--check--regular",
481
+ label: t("button save"),
482
+ onClick: handleSave
483
+ })));
484
+ };
485
+
486
+ // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
487
+ import { pipe as pipe2 } from "effect";
488
+ import { capitalize as capitalize2 } from "effect/String";
489
+ import React9, { useMemo as useMemo3 } from "react";
490
+ import { AST as AST3, S } from "@dxos/echo-schema";
491
+ import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
492
+ import { mx as mx4 } from "@dxos/react-ui-theme";
493
+ import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
494
+ import { isNotFalsy } from "@dxos/util";
495
+
496
+ // packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
497
+ import { pipe } from "effect";
498
+ import { capitalize } from "effect/String";
499
+ import React8, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
500
+ import { AST as AST2 } from "@dxos/echo-schema";
501
+ import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
502
+ import { invariant as invariant2 } from "@dxos/invariant";
503
+ import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
504
+ import { mx as mx3 } from "@dxos/react-ui-theme";
505
+ import { getSchemaProperties } from "@dxos/schema";
506
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
449
507
  var padding = "px-2";
450
- var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
451
- const onValid = useMemo2(() => autoSave ? onSave : void 0, [
452
- autoSave,
453
- onSave
454
- ]);
455
- const { canSave, values, errors, handleSave, ...inputProps } = useForm({
456
- schema,
457
- initialValues,
458
- onValuesChanged,
459
- onValidate,
460
- onValid,
461
- onSave
508
+ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
509
+ const { t } = useTranslation3(translationKey);
510
+ const { ast, name, type, title } = property;
511
+ const values = useFormValues(path ?? []);
512
+ invariant2(Array.isArray(values), void 0, {
513
+ F: __dxlog_file2,
514
+ L: 37,
515
+ S: void 0,
516
+ A: [
517
+ "Array.isArray(values)",
518
+ ""
519
+ ]
462
520
  });
463
- const properties = useMemo2(() => {
464
- const props = getSchemaProperties(schema.ast, values);
465
- const filtered = filter ? filter(props) : props;
466
- const findIndex = (props2, prop) => {
467
- const idx = props2.findIndex((p) => p === prop);
468
- return idx === -1 ? Infinity : idx;
469
- };
470
- return sort ? filtered.sort(({ name: a }, { name: b }) => findIndex(sort, a) - findIndex(sort, b)) : filtered;
521
+ const label = title ?? pipe(name, capitalize);
522
+ const tupleType = findNode(ast, AST2.isTupleType);
523
+ const elementType = tupleType?.rest[0]?.type;
524
+ const getDefaultObjectValue = (typeNode) => {
525
+ const baseNode = findNode(typeNode, isDiscriminatedUnion);
526
+ const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode(typeNode, AST2.isTypeLiteral);
527
+ if (!typeLiteral) {
528
+ return {};
529
+ }
530
+ return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
531
+ prop.name,
532
+ prop.defaultValue
533
+ ]));
534
+ };
535
+ const newValue = useMemo2(() => {
536
+ if (type === "object" && elementType) {
537
+ return getDefaultObjectValue(elementType);
538
+ } else {
539
+ return SimpleType.getDefaultValue(type);
540
+ }
471
541
  }, [
472
- schema,
473
- filter,
542
+ type,
543
+ elementType
544
+ ]);
545
+ const handleAdd = useCallback2(() => {
546
+ inputProps.onValueChange(type, [
547
+ ...values,
548
+ newValue
549
+ ]);
550
+ }, [
551
+ type,
552
+ elementType,
553
+ inputProps,
554
+ newValue,
474
555
  values
475
556
  ]);
476
- useEffect2(() => {
477
- if (errors && Object.keys(errors).length) {
478
- log2.warn("validation", {
479
- errors
480
- }, {
481
- F: __dxlog_file2,
482
- L: 106,
483
- S: void 0,
484
- C: (f, a) => f(...a)
485
- });
486
- }
557
+ const handleRemove = useCallback2((index) => {
558
+ const newValues = values.filter((_, i) => i !== index);
559
+ inputProps.onValueChange(type, newValues);
487
560
  }, [
488
- errors
561
+ type,
562
+ inputProps,
563
+ values
489
564
  ]);
490
- return /* @__PURE__ */ React6.createElement("div", {
491
- role: "form",
492
- className: mx2("flex flex-col w-full gap-2 py-2", classNames),
493
- "data-testid": testId
494
- }, properties.map((property) => {
495
- const { ast, name, type, format, title, description, examples, options, array } = property;
496
- const key = [
497
- ...path,
498
- name
499
- ];
500
- const label = title ?? pipe(name, capitalize);
501
- const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
502
- const FoundComponent = lookupComponent?.({
503
- prop: name,
504
- schema: S.make(ast),
505
- inputProps: {
506
- property: name,
507
- type,
508
- format,
509
- label,
510
- disabled: readonly,
511
- placeholder,
512
- ...inputProps
513
- }
514
- });
515
- if (FoundComponent) {
516
- return /* @__PURE__ */ React6.createElement("div", {
517
- key: name,
518
- role: "none",
519
- className: padding
520
- }, FoundComponent);
521
- }
522
- let InputComponent = Custom?.[key.join(".")];
523
- if (!InputComponent) {
524
- if (options) {
525
- return /* @__PURE__ */ React6.createElement("div", {
526
- key: name,
527
- role: "none",
528
- className: padding
529
- }, /* @__PURE__ */ React6.createElement(SelectInput, {
530
- type,
531
- format,
532
- property: name,
533
- disabled: readonly,
534
- label,
535
- options: options.map((option) => ({
536
- value: option,
537
- label: String(option)
538
- })),
539
- placeholder,
540
- ...inputProps
541
- }));
542
- }
543
- InputComponent = getInputComponent(type, format);
544
- if (array) {
545
- return /* @__PURE__ */ React6.createElement(ArrayField, {
546
- key: name,
547
- name,
548
- type,
549
- array: true,
550
- label,
551
- ast,
552
- values,
553
- format,
554
- readonly,
555
- placeholder,
556
- inputProps,
557
- Custom
558
- });
559
- }
560
- }
561
- if (!InputComponent) {
562
- if (type === "object") {
563
- const baseNode = findNode(ast, isDiscriminatedUnion);
564
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(ast, AST2.isTypeLiteral);
565
- if (typeLiteral) {
566
- const schema2 = S.make(typeLiteral);
567
- return /* @__PURE__ */ React6.createElement("div", {
568
- key: name,
569
- role: "none"
570
- }, /* @__PURE__ */ React6.createElement("div", {
571
- className: padding
572
- }, label), /* @__PURE__ */ React6.createElement(Form, {
573
- schema: schema2,
574
- path: key,
575
- values: values[name] ?? {},
576
- onValuesChanged: (childValues) => {
577
- inputProps.onValueChange(name, "object", childValues);
578
- },
579
- Custom
580
- }));
581
- }
582
- }
583
- log2("no renderer for property", {
584
- name,
585
- type
586
- }, {
587
- F: __dxlog_file2,
588
- L: 213,
589
- S: void 0,
590
- C: (f, a) => f(...a)
591
- });
592
- return null;
593
- }
594
- return /* @__PURE__ */ React6.createElement("div", {
595
- key: name,
596
- role: "none",
597
- className: padding
598
- }, /* @__PURE__ */ React6.createElement(InputComponent, {
599
- type,
600
- format,
601
- property: name,
602
- disabled: readonly,
603
- label,
604
- placeholder,
605
- ...inputProps
606
- }));
607
- }).filter(isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React6.createElement(FormActions, {
608
- onCancel,
609
- onSubmit: handleSave,
610
- canSubmit: canSave,
611
- readonly
612
- }));
613
- };
614
- var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholder, inputProps, Custom }) => {
615
- const { t } = useTranslation2(translationKey);
616
- const arrayValues = values[name] ?? [];
617
- const key = [
618
- name
619
- ];
620
- const tupleType = findNode(ast, AST2.isTupleType);
621
- const elementType = tupleType?.rest[0]?.type;
622
- if (type === "object" && elementType) {
623
- const baseNode = findNode(elementType, isDiscriminatedUnion);
624
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(elementType, AST2.isTypeLiteral);
625
- if (typeLiteral) {
626
- const schema = S.make(typeLiteral);
627
- return /* @__PURE__ */ React6.createElement("div", {
628
- key: name,
629
- role: "none",
630
- className: mx2(padding)
631
- }, /* @__PURE__ */ React6.createElement(InputHeader, null, label), /* @__PURE__ */ React6.createElement("div", {
632
- role: "none",
633
- className: "flex flex-col gap-1"
634
- }, arrayValues.map((value, index) => {
635
- return /* @__PURE__ */ React6.createElement("div", {
636
- key: index,
637
- role: "none",
638
- className: "flex items-center gap-1"
639
- }, /* @__PURE__ */ React6.createElement("div", {
640
- role: "none",
641
- className: "flex-1"
642
- }, /* @__PURE__ */ React6.createElement(Form, {
643
- schema,
644
- path: [
645
- ...key,
646
- `[${index}]`
647
- ],
648
- values: value,
649
- onValuesChanged: (childValues) => {
650
- const newValues = [
651
- ...arrayValues
652
- ];
653
- newValues[index] = childValues;
654
- inputProps.onValueChange(name, "object", newValues);
655
- },
656
- Custom
657
- })), /* @__PURE__ */ React6.createElement(IconButton, {
658
- icon: "ph--trash--regular",
659
- iconOnly: true,
660
- label: t("button remove"),
661
- onClick: () => {
662
- const newValues = arrayValues.filter((_, i) => i !== index);
663
- inputProps.onValueChange(name, type, newValues);
664
- }
665
- }));
666
- })), /* @__PURE__ */ React6.createElement("div", {
667
- role: "none",
668
- className: "flex justify-between items-center plb-1"
669
- }, /* @__PURE__ */ React6.createElement(IconButton, {
670
- icon: "ph--plus--regular",
671
- iconOnly: true,
672
- label: t("button add"),
673
- onClick: () => {
674
- const newValues = [
675
- ...arrayValues,
676
- {}
677
- ];
678
- inputProps.onValueChange(name, type, newValues);
679
- }
680
- })));
681
- }
682
- return /* @__PURE__ */ React6.createElement("div", {
683
- key: name,
684
- role: "none"
685
- }, "Nested form not supported in arrays, yet.");
686
- }
687
- const InputComponent = getInputComponent(type, format);
688
- if (!InputComponent) {
565
+ if (!elementType) {
689
566
  return null;
690
567
  }
691
- return /* @__PURE__ */ React6.createElement("div", {
568
+ return /* @__PURE__ */ React8.createElement("div", {
692
569
  role: "none",
693
- key: "meta-input",
694
- className: mx2(padding)
695
- }, /* @__PURE__ */ React6.createElement(InputHeader, null, label), /* @__PURE__ */ React6.createElement("div", {
570
+ className: mx3(padding)
571
+ }, /* @__PURE__ */ React8.createElement(InputHeader, null, label), /* @__PURE__ */ React8.createElement("div", {
696
572
  role: "none",
697
573
  className: "flex flex-col gap-1"
698
- }, arrayValues.map((_, index) => /* @__PURE__ */ React6.createElement("div", {
574
+ }, values.map((_value, index) => /* @__PURE__ */ React8.createElement("div", {
699
575
  key: index,
700
576
  role: "none",
701
- className: "flex items-start gap-1"
702
- }, /* @__PURE__ */ React6.createElement("div", {
577
+ className: "flex items-center gap-1"
578
+ }, /* @__PURE__ */ React8.createElement("div", {
703
579
  role: "none",
704
580
  className: "flex-1"
705
- }, /* @__PURE__ */ React6.createElement(InputComponent, {
706
- type,
707
- format,
708
- label,
709
- inputOnly: true,
710
- property: `${name}[${index}]`,
711
- disabled: readonly,
712
- placeholder,
713
- ...inputProps
714
- })), /* @__PURE__ */ React6.createElement(IconButton, {
581
+ }, /* @__PURE__ */ React8.createElement(FormField, {
582
+ property: {
583
+ ...property,
584
+ array: false,
585
+ ast: elementType
586
+ },
587
+ path: [
588
+ ...path ?? [],
589
+ index
590
+ ],
591
+ readonly,
592
+ inline: true,
593
+ Custom,
594
+ lookupComponent
595
+ })), /* @__PURE__ */ React8.createElement(IconButton2, {
715
596
  icon: "ph--trash--regular",
716
597
  iconOnly: true,
717
598
  label: t("button remove"),
718
- onClick: () => {
719
- const newValues = arrayValues.filter((_2, i) => i !== index);
720
- inputProps.onValueChange(name, type, newValues);
721
- }
722
- })))), /* @__PURE__ */ React6.createElement("div", {
599
+ onClick: () => handleRemove(index)
600
+ })))), /* @__PURE__ */ React8.createElement("div", {
723
601
  role: "none",
724
602
  className: "flex justify-between items-center plb-1"
725
- }, /* @__PURE__ */ React6.createElement(IconButton, {
603
+ }, /* @__PURE__ */ React8.createElement(IconButton2, {
726
604
  icon: "ph--plus--regular",
727
605
  iconOnly: true,
728
606
  label: t("button add"),
729
- onClick: () => {
730
- const newValues = [
731
- ...arrayValues,
732
- SimpleType.getDefaultValue(type)
733
- ];
734
- inputProps.onValueChange(name, type, newValues);
735
- }
607
+ onClick: handleAdd
736
608
  })));
737
609
  };
738
- var FormActions = ({ onCancel, onSubmit, canSubmit, readonly }) => {
739
- const { t } = useTranslation2(translationKey);
740
- return /* @__PURE__ */ React6.createElement("div", {
741
- role: "none",
742
- className: "flex justify-center"
743
- }, /* @__PURE__ */ React6.createElement("div", {
610
+
611
+ // packages/ui/react-ui-form/src/components/Form/factory.tsx
612
+ import { FormatEnum } from "@dxos/echo-schema";
613
+ var getInputComponent = (type, format) => {
614
+ switch (format) {
615
+ case FormatEnum.LatLng:
616
+ return GeoPointInput;
617
+ }
618
+ switch (type) {
619
+ case "string":
620
+ return TextInput;
621
+ case "number":
622
+ return NumberInput;
623
+ case "boolean":
624
+ return BooleanInput;
625
+ }
626
+ };
627
+
628
+ // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
629
+ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom }) => {
630
+ const inputProps = useInputProps(path);
631
+ const { ast, name, type, format, title, description, options, examples, array } = property;
632
+ const label = useMemo3(() => title ?? pipe2(name, capitalize2), [
633
+ title,
634
+ name
635
+ ]);
636
+ const placeholder = useMemo3(() => examples?.length ? `Example: "${examples[0]}"` : description, [
637
+ examples,
638
+ description
639
+ ]);
640
+ if (array) {
641
+ return /* @__PURE__ */ React9.createElement(ArrayField, {
642
+ property,
643
+ path,
644
+ inputProps,
645
+ readonly,
646
+ Custom
647
+ });
648
+ }
649
+ const FoundComponent = lookupComponent?.({
650
+ prop: name,
651
+ schema: S.make(ast),
652
+ inputProps: {
653
+ type,
654
+ format,
655
+ label,
656
+ disabled: readonly,
657
+ placeholder,
658
+ ...inputProps
659
+ }
660
+ });
661
+ if (FoundComponent) {
662
+ return /* @__PURE__ */ React9.createElement("div", null, FoundComponent);
663
+ }
664
+ const jsonPath = createJsonPath3(path ?? []);
665
+ const InputComponent = Custom?.[jsonPath] || getInputComponent(type, format);
666
+ if (InputComponent) {
667
+ return /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement(InputComponent, {
668
+ type,
669
+ format,
670
+ label,
671
+ inputOnly: inline,
672
+ placeholder,
673
+ disabled: readonly,
674
+ ...inputProps
675
+ }));
676
+ }
677
+ if (options) {
678
+ return /* @__PURE__ */ React9.createElement("div", {
679
+ role: "none"
680
+ }, /* @__PURE__ */ React9.createElement(SelectInput, {
681
+ type,
682
+ format,
683
+ disabled: readonly,
684
+ inputOnly: inline,
685
+ label,
686
+ options: options.map((option) => ({
687
+ value: option,
688
+ label: String(option)
689
+ })),
690
+ placeholder,
691
+ ...inputProps
692
+ }));
693
+ }
694
+ if (type === "object") {
695
+ const baseNode = findNode2(ast, isDiscriminatedUnion2);
696
+ const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode2(ast, AST3.isTypeLiteral);
697
+ if (typeLiteral) {
698
+ return /* @__PURE__ */ React9.createElement("div", null, !inline && /* @__PURE__ */ React9.createElement("div", null, label), /* @__PURE__ */ React9.createElement(FormFields, {
699
+ schema: S.make(typeLiteral),
700
+ path,
701
+ readonly,
702
+ Custom
703
+ }));
704
+ }
705
+ }
706
+ return null;
707
+ };
708
+ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custom }) => {
709
+ const values = useFormValues(path);
710
+ const properties = useMemo3(() => {
711
+ const props = getSchemaProperties2(schema.ast, values);
712
+ const filtered = filter ? filter(props) : props;
713
+ return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
714
+ }, [
715
+ schema,
716
+ values,
717
+ filter,
718
+ sort
719
+ ]);
720
+ return /* @__PURE__ */ React9.createElement("div", {
721
+ role: "form",
722
+ className: mx4("flex flex-col w-full gap-2 py-2")
723
+ }, properties.map((property) => {
724
+ return /* @__PURE__ */ React9.createElement(FormField, {
725
+ key: property.name,
726
+ property,
727
+ path: [
728
+ ...path ?? [],
729
+ property.name
730
+ ],
731
+ readonly,
732
+ lookupComponent,
733
+ Custom
734
+ });
735
+ }).filter(isNotFalsy));
736
+ };
737
+
738
+ // packages/ui/react-ui-form/src/components/Form/Form.tsx
739
+ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
740
+ const onValid = useMemo4(() => autoSave ? onSave : void 0, [
741
+ autoSave,
742
+ onSave
743
+ ]);
744
+ return /* @__PURE__ */ React10.createElement(FormProvider, {
745
+ schema,
746
+ initialValues,
747
+ onValuesChanged,
748
+ onValidate,
749
+ onValid,
750
+ onSave
751
+ }, /* @__PURE__ */ React10.createElement("div", {
744
752
  role: "none",
745
- className: mx2(onCancel && !readonly && "grid grid-cols-2 gap-2")
746
- }, onCancel && !readonly && /* @__PURE__ */ React6.createElement(IconButton, {
747
- "data-testid": "cancel-button",
748
- icon: "ph--x--regular",
749
- label: t("button cancel"),
750
- onClick: onCancel
751
- }), onSubmit && /* @__PURE__ */ React6.createElement(IconButton, {
752
- type: "submit",
753
- "data-testid": "save-button",
754
- disabled: !canSubmit,
755
- icon: "ph--check--regular",
756
- label: t("button save"),
757
- onClick: onSubmit
753
+ className: mx5("p-2", classNames),
754
+ "data-testid": testId
755
+ }, /* @__PURE__ */ React10.createElement(FormFields, {
756
+ schema,
757
+ path,
758
+ readonly,
759
+ filter,
760
+ sort,
761
+ lookupComponent,
762
+ Custom
763
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React10.createElement(FormActions, {
764
+ onCancel,
765
+ readonly
758
766
  })));
759
767
  };
760
768
 
761
769
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
762
770
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
763
771
  var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
764
- const { t } = useTranslation3(translationKey);
772
+ const { t } = useTranslation4(translationKey);
765
773
  const [props, setProps] = useState2(projection.getFieldProjection(field.id).props);
766
- useEffect3(() => setProps(projection.getFieldProjection(field.id).props), [
774
+ useEffect2(() => setProps(projection.getFieldProjection(field.id).props), [
767
775
  field,
768
776
  projection
769
777
  ]);
770
778
  const [schemas, setSchemas] = useState2([]);
771
- useEffect3(() => {
779
+ useEffect2(() => {
772
780
  if (!registry) {
773
781
  return;
774
782
  }
@@ -787,7 +795,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
787
795
  registry
788
796
  ]);
789
797
  const [referenceSchema, setReferenceSchema] = useState2();
790
- useEffect3(() => {
798
+ useEffect2(() => {
791
799
  setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
792
800
  }, [
793
801
  schemas,
@@ -796,7 +804,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
796
804
  const [{ fieldSchema }, setFieldSchema] = useState2({
797
805
  fieldSchema: getFormatSchema(props?.format)
798
806
  });
799
- const handleValuesChanged = useCallback2((_props) => {
807
+ const handleValuesChanged = useCallback3((_props) => {
800
808
  setFieldSchema((prev) => {
801
809
  const fieldSchema2 = getFormatSchema(_props.format);
802
810
  if (prev.fieldSchema === fieldSchema2) {
@@ -831,7 +839,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
831
839
  props.format,
832
840
  props.referenceSchema
833
841
  ]);
834
- const handleValidate = useCallback2(({ property }) => {
842
+ const handleValidate = useCallback3(({ property }) => {
835
843
  if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
836
844
  return [
837
845
  {
@@ -844,7 +852,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
844
852
  view.fields,
845
853
  field
846
854
  ]);
847
- const handleSave = useCallback2((props2) => {
855
+ const handleSave = useCallback3((props2) => {
848
856
  projection.setFieldProjection({
849
857
  field,
850
858
  props: props2
@@ -855,29 +863,29 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
855
863
  field,
856
864
  onSave
857
865
  ]);
858
- const handleCancel = useCallback2(() => {
866
+ const handleCancel = useCallback3(() => {
859
867
  requestAnimationFrame(() => onCancel?.());
860
868
  onSave();
861
869
  }, [
862
870
  onSave
863
871
  ]);
864
- const Custom = useMemo3(() => ({
865
- ["format"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
872
+ const Custom = useMemo5(() => ({
873
+ ["format"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
866
874
  ...props2,
867
875
  options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
868
876
  value,
869
877
  label: t(`format ${value}`)
870
878
  }))
871
879
  }),
872
- ["referenceSchema"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
880
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
873
881
  ...props2,
874
882
  options: schemas.map((schema) => ({
875
883
  value: schema.typename
876
884
  }))
877
885
  }),
878
- ["referencePath"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
886
+ ["referencePath"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
879
887
  ...props2,
880
- options: referenceSchema ? getSchemaProperties2(referenceSchema.ast).sort(sortProperties).map((p) => ({
888
+ options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
881
889
  value: p.name
882
890
  })) : []
883
891
  })
@@ -886,9 +894,9 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
886
894
  schemas,
887
895
  referenceSchema
888
896
  ]);
889
- const propIsNotType = useCallback2((props2) => props2.filter((p) => p.name !== "type"), []);
897
+ const propIsNotType = useCallback3((props2) => props2.filter((p) => p.name !== "type"), []);
890
898
  if (!fieldSchema) {
891
- log3.warn("invalid format", {
899
+ log2.warn("invalid format", {
892
900
  props
893
901
  }, {
894
902
  F: __dxlog_file3,
@@ -898,7 +906,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
898
906
  });
899
907
  return null;
900
908
  }
901
- return /* @__PURE__ */ React7.createElement(Form, {
909
+ return /* @__PURE__ */ React11.createElement(Form, {
902
910
  key: field.id,
903
911
  autoFocus: true,
904
912
  values: props,
@@ -917,30 +925,30 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
917
925
  };
918
926
 
919
927
  // packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
920
- import React8, { useCallback as useCallback3, useMemo as useMemo4, useState as useState3 } from "react";
921
- import { AST as AST3, Format, S as S2 } from "@dxos/echo-schema";
922
- import { IconButton as IconButton2, useTranslation as useTranslation4 } from "@dxos/react-ui";
928
+ import React12, { useCallback as useCallback4, useMemo as useMemo6, useState as useState3 } from "react";
929
+ import { AST as AST4, Format, S as S2 } from "@dxos/echo-schema";
930
+ import { IconButton as IconButton3, useTranslation as useTranslation5 } from "@dxos/react-ui";
923
931
  import { List } from "@dxos/react-ui-list";
924
- import { ghostHover, inputTextLabel, mx as mx3 } from "@dxos/react-ui-theme";
932
+ import { ghostHover, inputTextLabel, mx as mx6 } from "@dxos/react-ui-theme";
925
933
  import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
926
934
  import { arrayMove } from "@dxos/util";
927
935
  var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
928
936
  var ViewMetaSchema = S2.Struct({
929
937
  name: S2.String.annotations({
930
- [AST3.TitleAnnotationId]: "View"
938
+ [AST4.TitleAnnotationId]: "View"
931
939
  }),
932
940
  typename: Format.DXN.annotations({
933
- [AST3.TitleAnnotationId]: "Typename"
941
+ [AST4.TitleAnnotationId]: "Typename"
934
942
  })
935
943
  }).pipe(S2.mutable);
936
944
  var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
937
- const { t } = useTranslation4(translationKey);
938
- const projection = useMemo4(() => new ViewProjection(schema, view), [
945
+ const { t } = useTranslation5(translationKey);
946
+ const projection = useMemo6(() => new ViewProjection(schema, view), [
939
947
  schema,
940
948
  view
941
949
  ]);
942
950
  const [field, setField] = useState3();
943
- const viewValues = useMemo4(() => {
951
+ const viewValues = useMemo6(() => {
944
952
  return {
945
953
  name: view.name,
946
954
  // TODO(burdon): Need to warn user of possible consequences of editing.
@@ -950,7 +958,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
950
958
  }, [
951
959
  view
952
960
  ]);
953
- const handleViewUpdate = useCallback3(({ name, typename }) => {
961
+ const handleViewUpdate = useCallback4(({ name, typename }) => {
954
962
  requestAnimationFrame(() => {
955
963
  if (view.name !== name) {
956
964
  view.name = name;
@@ -964,67 +972,67 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
964
972
  schema,
965
973
  onTypenameChanged
966
974
  ]);
967
- const handleSelect = useCallback3((field2) => {
975
+ const handleSelect = useCallback4((field2) => {
968
976
  setField((f) => f === field2 ? void 0 : field2);
969
977
  }, []);
970
- const handleAdd = useCallback3(() => {
978
+ const handleAdd = useCallback4(() => {
971
979
  const field2 = projection.createFieldProjection();
972
980
  setField(field2);
973
981
  }, [
974
982
  view
975
983
  ]);
976
- const handleMove = useCallback3((fromIndex, toIndex) => {
984
+ const handleMove = useCallback4((fromIndex, toIndex) => {
977
985
  arrayMove(view.fields, fromIndex, toIndex);
978
986
  }, [
979
987
  view.fields
980
988
  ]);
981
- const handleClose = useCallback3(() => setField(void 0), []);
982
- return /* @__PURE__ */ React8.createElement("div", {
989
+ const handleClose = useCallback4(() => setField(void 0), []);
990
+ return /* @__PURE__ */ React12.createElement("div", {
983
991
  role: "none",
984
- className: mx3("flex flex-col w-full divide-y divide-separator", classNames)
985
- }, /* @__PURE__ */ React8.createElement(Form, {
992
+ className: mx6("flex flex-col w-full divide-y divide-separator", classNames)
993
+ }, /* @__PURE__ */ React12.createElement(Form, {
986
994
  autoFocus: true,
987
995
  autoSave: true,
988
996
  schema: ViewMetaSchema,
989
997
  values: viewValues,
990
998
  onSave: handleViewUpdate
991
- }), /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("div", {
999
+ }), /* @__PURE__ */ React12.createElement("div", null, /* @__PURE__ */ React12.createElement("div", {
992
1000
  role: "none",
993
1001
  className: "p-2"
994
- }, /* @__PURE__ */ React8.createElement("label", {
995
- className: mx3(inputTextLabel)
996
- }, t("fields label"))), /* @__PURE__ */ React8.createElement(List.Root, {
1002
+ }, /* @__PURE__ */ React12.createElement("label", {
1003
+ className: mx6(inputTextLabel)
1004
+ }, t("fields label"))), /* @__PURE__ */ React12.createElement(List.Root, {
997
1005
  items: view.fields,
998
1006
  isItem: S2.is(FieldSchema),
999
1007
  getId: (field2) => field2.id,
1000
1008
  onMove: handleMove
1001
- }, ({ items: fields }) => /* @__PURE__ */ React8.createElement(React8.Fragment, null, showHeading && /* @__PURE__ */ React8.createElement("div", {
1009
+ }, ({ items: fields }) => /* @__PURE__ */ React12.createElement(React12.Fragment, null, showHeading && /* @__PURE__ */ React12.createElement("div", {
1002
1010
  role: "heading",
1003
1011
  className: grid
1004
- }, /* @__PURE__ */ React8.createElement("div", null), /* @__PURE__ */ React8.createElement("div", {
1012
+ }, /* @__PURE__ */ React12.createElement("div", null), /* @__PURE__ */ React12.createElement("div", {
1005
1013
  className: "flex items-center text-sm"
1006
- }, t("field path label"))), /* @__PURE__ */ React8.createElement("div", {
1014
+ }, t("field path label"))), /* @__PURE__ */ React12.createElement("div", {
1007
1015
  role: "list",
1008
1016
  className: "flex flex-col w-full"
1009
- }, fields?.map((field2) => /* @__PURE__ */ React8.createElement(List.Item, {
1017
+ }, fields?.map((field2) => /* @__PURE__ */ React12.createElement(List.Item, {
1010
1018
  key: field2.id,
1011
1019
  item: field2,
1012
- classNames: mx3(grid, ghostHover, "cursor-pointer")
1013
- }, /* @__PURE__ */ React8.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React8.createElement(List.ItemTitle, {
1020
+ classNames: mx6(grid, ghostHover, "cursor-pointer")
1021
+ }, /* @__PURE__ */ React12.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React12.createElement(List.ItemTitle, {
1014
1022
  onClick: () => handleSelect(field2)
1015
- }, field2.path), /* @__PURE__ */ React8.createElement(List.ItemDeleteButton, {
1023
+ }, field2.path), /* @__PURE__ */ React12.createElement(List.ItemDeleteButton, {
1016
1024
  disabled: view.fields.length <= 1,
1017
1025
  onClick: () => onDelete(field2.id)
1018
- }))))))), field && /* @__PURE__ */ React8.createElement(FieldEditor, {
1026
+ }))))))), field && /* @__PURE__ */ React12.createElement(FieldEditor, {
1019
1027
  key: field.id,
1020
1028
  view,
1021
1029
  projection,
1022
1030
  field,
1023
1031
  registry,
1024
1032
  onSave: handleClose
1025
- }), !readonly && !field && /* @__PURE__ */ React8.createElement("div", {
1033
+ }), !readonly && !field && /* @__PURE__ */ React12.createElement("div", {
1026
1034
  className: "flex p-2 justify-center"
1027
- }, /* @__PURE__ */ React8.createElement(IconButton2, {
1035
+ }, /* @__PURE__ */ React12.createElement(IconButton3, {
1028
1036
  icon: "ph--plus--regular",
1029
1037
  label: t("button add property"),
1030
1038
  onClick: handleAdd,
@@ -1257,7 +1265,6 @@ export {
1257
1265
  DeprecatedFormInput,
1258
1266
  FieldEditor,
1259
1267
  Form,
1260
- FormActions,
1261
1268
  GeoPointInput,
1262
1269
  InputHeader,
1263
1270
  NumberInput,