@dxos/react-ui-form 0.8.4-main.5ea62a8 → 0.8.4-main.66e292d

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 (91) hide show
  1. package/dist/lib/browser/index.mjs +534 -348
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +534 -348
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +8 -7
  8. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +1 -1
  9. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  10. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +8 -7
  11. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
  13. package/dist/types/src/components/Form/Form.d.ts +6 -5
  14. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  15. package/dist/types/src/components/Form/Form.stories.d.ts +52 -37
  16. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  17. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/FormContent.d.ts +5 -5
  19. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
  20. package/dist/types/src/components/Form/FormContext.d.ts +4 -4
  21. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
  22. package/dist/types/src/components/Form/Input.d.ts +2 -2
  23. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  24. package/dist/types/src/components/Form/RefField.d.ts +10 -6
  25. package/dist/types/src/components/Form/RefField.d.ts.map +1 -1
  26. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +8 -7
  27. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/factory.d.ts +2 -2
  29. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  30. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +41 -0
  31. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -0
  32. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +82 -0
  33. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -0
  34. package/dist/types/src/components/ObjectPicker/index.d.ts +2 -0
  35. package/dist/types/src/components/ObjectPicker/index.d.ts.map +1 -0
  36. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +20 -6
  37. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  38. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +13 -11
  39. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  40. package/dist/types/src/components/index.d.ts +1 -0
  41. package/dist/types/src/components/index.d.ts.map +1 -1
  42. package/dist/types/src/hooks/useForm.d.ts +5 -5
  43. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  44. package/dist/types/src/hooks/useQueryRefOptions.d.ts +9 -3
  45. package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -1
  46. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -1
  47. package/dist/types/src/translations.d.ts +7 -6
  48. package/dist/types/src/translations.d.ts.map +1 -1
  49. package/dist/types/src/util/field.d.ts +3 -3
  50. package/dist/types/src/util/field.d.ts.map +1 -1
  51. package/dist/types/src/util/formatting.d.ts +2 -2
  52. package/dist/types/src/util/formatting.d.ts.map +1 -1
  53. package/dist/types/src/util/refs.d.ts +1 -1
  54. package/dist/types/src/util/refs.d.ts.map +1 -1
  55. package/dist/types/src/util/schema.d.ts +1 -1
  56. package/dist/types/src/util/schema.d.ts.map +1 -1
  57. package/dist/types/tsconfig.tsbuildinfo +1 -1
  58. package/package.json +40 -37
  59. package/src/components/ControlSection/ControlSection.stories.tsx +4 -5
  60. package/src/components/ControlSection/ControlSection.tsx +1 -1
  61. package/src/components/FieldEditor/FieldEditor.stories.tsx +8 -7
  62. package/src/components/FieldEditor/FieldEditor.tsx +7 -4
  63. package/src/components/Form/ArrayField.tsx +7 -4
  64. package/src/components/Form/Defaults.tsx +1 -1
  65. package/src/components/Form/Form.stories.tsx +52 -52
  66. package/src/components/Form/Form.tsx +19 -9
  67. package/src/components/Form/FormActions.tsx +7 -2
  68. package/src/components/Form/FormContent.tsx +83 -23
  69. package/src/components/Form/FormContext.tsx +6 -6
  70. package/src/components/Form/Input.tsx +2 -2
  71. package/src/components/Form/RefField.tsx +50 -66
  72. package/src/components/Form/custom/GeoPointInput.tsx +1 -1
  73. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +5 -6
  74. package/src/components/Form/custom/SelectOptionsInput.tsx +2 -2
  75. package/src/components/Form/factory.tsx +7 -4
  76. package/src/components/ObjectPicker/ObjectPicker.stories.tsx +207 -0
  77. package/src/components/ObjectPicker/ObjectPicker.tsx +161 -0
  78. package/src/components/ObjectPicker/index.ts +5 -0
  79. package/src/components/ViewEditor/ViewEditor.stories.tsx +112 -49
  80. package/src/components/ViewEditor/ViewEditor.test.tsx +6 -5
  81. package/src/components/ViewEditor/ViewEditor.tsx +277 -208
  82. package/src/components/index.ts +1 -0
  83. package/src/components/testing.tsx +2 -2
  84. package/src/hooks/useForm.ts +11 -8
  85. package/src/hooks/useQueryRefOptions.ts +15 -6
  86. package/src/hooks/useRefQueryLookupHandler.ts +5 -5
  87. package/src/translations.ts +7 -6
  88. package/src/util/field.ts +25 -25
  89. package/src/util/formatting.ts +22 -22
  90. package/src/util/refs.ts +7 -7
  91. package/src/util/schema.ts +2 -4
@@ -8,7 +8,7 @@ var translations = [
8
8
  "hidden fields label": "Hidden Fields",
9
9
  "empty readonly ref field label": "(none)",
10
10
  // TODO(burdon): Standardize field/property.
11
- "button add property": "Add property",
11
+ "add property button label": "Add property",
12
12
  "field property label": "Property",
13
13
  "field property placeholder": "Property name",
14
14
  "field format label": "Type",
@@ -21,11 +21,12 @@ var translations = [
21
21
  "show field label": "Show field",
22
22
  "hide field label": "Hide field",
23
23
  "delete field label": "Delete field",
24
+ "ref field combobox input placeholder": "Search\u2026",
24
25
  "ref field placeholder_one": "Select\u2026",
25
26
  "ref field placeholder_other": "Select items\u2026",
26
27
  // TODO(burdon): Factor out?
27
- "button cancel": "Cancel",
28
- "button save": "Save",
28
+ "cancel button label": "Cancel",
29
+ "save button label": "Save",
29
30
  // FormatEnum
30
31
  "format boolean": "Boolean",
31
32
  "format currency": "Currency",
@@ -39,7 +40,7 @@ var translations = [
39
40
  "format hostname": "Hostname",
40
41
  "format integer": "Integer",
41
42
  "format json": "JSON",
42
- "format latlng": "Geopoint",
43
+ "format lnglat": "Geopoint",
43
44
  "format markdown": "Markdown",
44
45
  "format percent": "Percent",
45
46
  "format ref": "Reference",
@@ -65,8 +66,8 @@ var translations = [
65
66
  "select option delete": "Delete",
66
67
  "select option add": "Add option",
67
68
  // System schema message.
68
- "system schema title": "System record type",
69
- "system schema description": "This is a system record type and cannot be modified, though the view can still be configured."
69
+ "system schema title": "System type",
70
+ "system schema description": "This is a system type and cannot be modified, though the view can still be configured."
70
71
  }
71
72
  }
72
73
  }
@@ -82,7 +83,8 @@ var ControlPage = ({ children, classNames, ...props }) => {
82
83
  var _effect = _useSignals();
83
84
  try {
84
85
  return /* @__PURE__ */ React.createElement(StackItem.Content, {
85
- classNames: "block overflow-y-auto [--control-spacing:var(--dx-trimMd)]"
86
+ scrollable: true,
87
+ classNames: "[--control-spacing:var(--dx-trimMd)]"
86
88
  }, /* @__PURE__ */ React.createElement("div", {
87
89
  role: "none",
88
90
  className: mx("pli-cardSpacingInline pbe-trimLg", classNames),
@@ -212,17 +214,17 @@ var ControlFrameItem = ({ title, description, children }) => {
212
214
  };
213
215
 
214
216
  // src/components/FieldEditor/FieldEditor.tsx
215
- import { useSignals as _useSignals13 } from "@preact-signals/safe-react/tracking";
216
- import React13, { useCallback as useCallback9, useEffect as useEffect8, useMemo as useMemo7, useState as useState6 } from "react";
217
- import { FormatEnum as FormatEnum5, FormatEnums, formatToType } from "@dxos/echo-schema";
217
+ import { useSignals as _useSignals14 } from "@preact-signals/safe-react/tracking";
218
+ import React14, { useCallback as useCallback12, useEffect as useEffect8, useMemo as useMemo7, useState as useState6 } from "react";
219
+ import { Format as Format5, FormatEnums, formatToType } from "@dxos/echo/internal";
218
220
  import { log as log3 } from "@dxos/log";
219
- import { useAsyncEffect, useTranslation as useTranslation8 } from "@dxos/react-ui";
220
- import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
221
+ import { useAsyncEffect, useTranslation as useTranslation9 } from "@dxos/react-ui";
222
+ import { formatToAdditionalPropertyAttributes, getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
221
223
 
222
224
  // src/components/Form/custom/GeoPointInput.tsx
223
225
  import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
224
226
  import React3, { useCallback, useEffect, useMemo, useState } from "react";
225
- import { GeoLocation } from "@dxos/echo-schema";
227
+ import { GeoLocation } from "@dxos/echo/internal";
226
228
  import { Input as Input3, useTranslation as useTranslation2 } from "@dxos/react-ui";
227
229
  import { safeParseFloat } from "@dxos/util";
228
230
 
@@ -470,7 +472,7 @@ var SelectOptionInput = ({ type, label, readonly, getStatus, getValue: getValue3
470
472
  readonly: !!readonly
471
473
  }, ({ items }) => /* @__PURE__ */ React4.createElement("div", {
472
474
  role: "list",
473
- className: "w-full overflow-auto"
475
+ className: "is-full overflow-auto"
474
476
  }, items?.map((item) => /* @__PURE__ */ React4.createElement("div", {
475
477
  key: item.id
476
478
  }, /* @__PURE__ */ React4.createElement(List.Item, {
@@ -635,7 +637,7 @@ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, on
635
637
  }), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, t(checked ? "boolean input true value" : "boolean input false value")) : /* @__PURE__ */ React6.createElement(Input6.Switch, {
636
638
  disabled: !!readonly,
637
639
  checked,
638
- onCheckedChange: (value) => onValueChange(type, value)
640
+ onCheckedChange: (value2) => onValueChange(type, value2)
639
641
  }), inputOnly && /* @__PURE__ */ React6.createElement(Input6.DescriptionAndValidation, null, error));
640
642
  } finally {
641
643
  _effect.f();
@@ -645,29 +647,29 @@ var SelectInput = ({ type, label, inputOnly, readonly, placeholder, options, get
645
647
  var _effect = _useSignals6();
646
648
  try {
647
649
  const { status, error } = getStatus();
648
- const value = getValue3();
649
- const handleValueChange = useCallback3((value2) => onValueChange(type, value2), [
650
+ const value2 = getValue3();
651
+ const handleValueChange = useCallback3((value3) => onValueChange(type, value3), [
650
652
  type,
651
653
  onValueChange
652
654
  ]);
653
- return readonly && !value ? null : /* @__PURE__ */ React6.createElement(Input6.Root, {
655
+ return readonly && !value2 ? null : /* @__PURE__ */ React6.createElement(Input6.Root, {
654
656
  validationValence: status
655
657
  }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
656
658
  error,
657
659
  label
658
- }), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value)?.label ?? String(value)) : /* @__PURE__ */ React6.createElement(Select.Root, {
659
- value,
660
+ }), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value2)?.label ?? String(value2)) : /* @__PURE__ */ React6.createElement(Select.Root, {
661
+ value: value2,
660
662
  onValueChange: handleValueChange
661
663
  }, /* @__PURE__ */ React6.createElement(Select.TriggerButton, {
662
664
  classNames: "is-full",
663
665
  disabled: !!readonly,
664
666
  placeholder
665
- }), /* @__PURE__ */ React6.createElement(Select.Portal, null, /* @__PURE__ */ React6.createElement(Select.Content, null, /* @__PURE__ */ React6.createElement(Select.Viewport, null, options?.map(({ value: value2, label: label2 }) => (
667
+ }), /* @__PURE__ */ React6.createElement(Select.Portal, null, /* @__PURE__ */ React6.createElement(Select.Content, null, /* @__PURE__ */ React6.createElement(Select.Viewport, null, options?.map(({ value: value3, label: label2 }) => (
666
668
  // NOTE: Numeric values are converted to and from strings.
667
669
  /* @__PURE__ */ React6.createElement(Select.Option, {
668
- key: String(value2),
669
- value: String(value2)
670
- }, label2 ?? String(value2))
670
+ key: String(value3),
671
+ value: String(value3)
672
+ }, label2 ?? String(value3))
671
673
  ))), /* @__PURE__ */ React6.createElement(Select.Arrow, null)))), inputOnly && /* @__PURE__ */ React6.createElement(Input6.DescriptionAndValidation, null, error));
672
674
  } finally {
673
675
  _effect.f();
@@ -706,7 +708,7 @@ var MarkdownInput = ({ type, label, inputOnly, readonly, placeholder, getStatus,
706
708
  disabled: !!readonly,
707
709
  placeholder,
708
710
  value: getValue3() ?? "",
709
- classNames: "min-bs-auto max-h-40 overflow-auto",
711
+ classNames: "min-bs-auto max-bs-40 overflow-auto",
710
712
  onChange: (event) => onValueChange(type, event.target.value),
711
713
  onBlur,
712
714
  style: {
@@ -720,9 +722,9 @@ var MarkdownInput = ({ type, label, inputOnly, readonly, placeholder, getStatus,
720
722
  };
721
723
 
722
724
  // src/components/Form/Form.tsx
723
- import { useSignals as _useSignals12 } from "@preact-signals/safe-react/tracking";
725
+ import { useSignals as _useSignals13 } from "@preact-signals/safe-react/tracking";
724
726
  import { useFocusFinders } from "@fluentui/react-tabster";
725
- import React12, { useEffect as useEffect7, useMemo as useMemo6, useRef as useRef3 } from "react";
727
+ import React13, { useCallback as useCallback11, useEffect as useEffect7, useRef as useRef3 } from "react";
726
728
  import { cardDialogOverflow, cardSpacing as cardSpacing2 } from "@dxos/react-ui-stack";
727
729
 
728
730
  // src/components/Form/FormActions.tsx
@@ -734,15 +736,15 @@ import { mx as mx4 } from "@dxos/react-ui-theme";
734
736
 
735
737
  // src/components/Form/FormContext.tsx
736
738
  import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
737
- import React7, { createContext, useCallback as useCallback6, useContext, useEffect as useEffect6, useMemo as useMemo3 } from "react";
739
+ import React7, { createContext, useCallback as useCallback7, useContext, useEffect as useEffect6, useMemo as useMemo3 } from "react";
738
740
  import { raise } from "@dxos/debug";
739
- import { getValue as getValue2 } from "@dxos/echo-schema";
741
+ import { getValue as getValue2 } from "@dxos/echo/internal";
740
742
  import { createJsonPath as createJsonPath2 } from "@dxos/effect";
741
743
 
742
744
  // src/hooks/useForm.ts
743
- import { SchemaAST } from "effect";
745
+ import * as SchemaAST from "effect/SchemaAST";
744
746
  import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useState as useState3 } from "react";
745
- import { getValue, setValue } from "@dxos/echo-schema";
747
+ import { getValue, setValue } from "@dxos/echo/internal";
746
748
  import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
747
749
  import { invariant } from "@dxos/invariant";
748
750
  import { log } from "@dxos/log";
@@ -751,7 +753,7 @@ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.t
751
753
  var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
752
754
  invariant(SchemaAST.isTypeLiteral(schema.ast), void 0, {
753
755
  F: __dxlog_file,
754
- L: 95,
756
+ L: 96,
755
757
  S: void 0,
756
758
  A: [
757
759
  "SchemaAST.isTypeLiteral(schema.ast)",
@@ -845,17 +847,17 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
845
847
  }, [
846
848
  values
847
849
  ]);
848
- const onValueChange = useCallback4((path, type, value) => {
850
+ const onValueChange = useCallback4((path, type, value2) => {
849
851
  const jsonPath = createJsonPath(path);
850
- let parsedValue = value;
852
+ let parsedValue = value2;
851
853
  try {
852
854
  if (type === "number") {
853
- parsedValue = parseFloat(value) || 0;
855
+ parsedValue = parseFloat(value2) || 0;
854
856
  }
855
857
  } catch (err) {
856
858
  log.catch(err, void 0, {
857
859
  F: __dxlog_file,
858
- L: 215,
860
+ L: 217,
859
861
  S: void 0,
860
862
  C: (f, a) => f(...a)
861
863
  });
@@ -865,15 +867,16 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
865
867
  ...setValue(values, jsonPath, parsedValue)
866
868
  };
867
869
  setValues(newValues);
868
- setChanged((prev) => ({
869
- ...prev,
870
+ const newChanged = {
871
+ ...changed,
870
872
  [jsonPath]: true
871
- }));
873
+ };
874
+ setChanged(newChanged);
872
875
  onValuesChanged?.(newValues);
873
876
  const isValid = validate(newValues);
874
877
  if (isValid && onValid) {
875
878
  onValid(newValues, {
876
- changed
879
+ changed: newChanged
877
880
  });
878
881
  }
879
882
  }, [
@@ -923,10 +926,10 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
923
926
  onTouched
924
927
  ]);
925
928
  };
926
- var createKeySet = (obj, value) => {
929
+ var createKeySet = (obj, value2) => {
927
930
  invariant(obj, void 0, {
928
931
  F: __dxlog_file,
929
- L: 277,
932
+ L: 280,
930
933
  S: void 0,
931
934
  A: [
932
935
  "obj",
@@ -935,7 +938,7 @@ var createKeySet = (obj, value) => {
935
938
  });
936
939
  return Object.keys(obj).reduce((acc, key) => ({
937
940
  ...acc,
938
- [key]: value
941
+ [key]: value2
939
942
  }), {});
940
943
  };
941
944
  var flatMap = (errors) => {
@@ -950,7 +953,7 @@ var flatMap = (errors) => {
950
953
 
951
954
  // src/hooks/useRefQueryLookupHandler.ts
952
955
  import { useCallback as useCallback5 } from "react";
953
- import { getObjectDXN } from "@dxos/echo-schema";
956
+ import { Obj } from "@dxos/echo";
954
957
  import { Filter } from "@dxos/react-client/echo";
955
958
  import { isNonNullable } from "@dxos/util";
956
959
  var useRefQueryLookupHandler = ({ space }) => {
@@ -961,13 +964,13 @@ var useRefQueryLookupHandler = ({ space }) => {
961
964
  const query = space.db.query(Filter.typename(typeInfo.typename));
962
965
  const { objects } = await query.run();
963
966
  return objects.map((object) => {
964
- const dxn = getObjectDXN(object);
967
+ const dxn = Obj.getDXN(object);
965
968
  if (!dxn) {
966
969
  return void 0;
967
970
  }
968
971
  const item = {
969
972
  dxn,
970
- label: object?.name ?? object?.id ?? ""
973
+ label: Obj.getLabel(object) ?? object?.id ?? ""
971
974
  };
972
975
  return item;
973
976
  }).filter(isNonNullable);
@@ -977,12 +980,14 @@ var useRefQueryLookupHandler = ({ space }) => {
977
980
  };
978
981
 
979
982
  // src/hooks/useQueryRefOptions.ts
980
- import { useEffect as useEffect5, useState as useState4 } from "react";
983
+ import { useCallback as useCallback6, useEffect as useEffect5, useState as useState4 } from "react";
981
984
  import { log as log2 } from "@dxos/log";
982
985
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts";
983
986
  var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
984
987
  const [options, setOptions] = useState4([]);
985
988
  const [loading, setLoading] = useState4(false);
989
+ const [state, setState] = useState4({});
990
+ const update = useCallback6(() => setState({}), []);
986
991
  useEffect5(() => {
987
992
  if (!refTypeInfo || !onQueryRefOptions) {
988
993
  return;
@@ -1002,7 +1007,7 @@ var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
1002
1007
  } catch (error) {
1003
1008
  log2.error("Failed to fetch ref options:", error, {
1004
1009
  F: __dxlog_file2,
1005
- L: 42,
1010
+ L: 51,
1006
1011
  S: void 0,
1007
1012
  C: (f, a) => f(...a)
1008
1013
  });
@@ -1014,10 +1019,12 @@ var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
1014
1019
  void fetchOptions();
1015
1020
  }, [
1016
1021
  refTypeInfo,
1017
- onQueryRefOptions
1022
+ onQueryRefOptions,
1023
+ state
1018
1024
  ]);
1019
1025
  return {
1020
1026
  options,
1027
+ update,
1021
1028
  loading
1022
1029
  };
1023
1030
  };
@@ -1040,7 +1047,7 @@ var useInputProps = (path = []) => {
1040
1047
  return useMemo3(() => ({
1041
1048
  getStatus: () => getStatus(stablePath),
1042
1049
  getValue: () => getFormValue(stablePath),
1043
- onValueChange: (type, value) => onValueChange(stablePath, type, value),
1050
+ onValueChange: (type, value2) => onValueChange(stablePath, type, value2),
1044
1051
  onBlur: () => onTouched(stablePath)
1045
1052
  }), [
1046
1053
  getStatus,
@@ -1054,7 +1061,7 @@ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
1054
1061
  var _effect = _useSignals7();
1055
1062
  try {
1056
1063
  const form = useForm(formOptions);
1057
- const handleKeyDown = useCallback6((event) => {
1064
+ const handleKeyDown = useCallback7((event) => {
1058
1065
  const keyIsEnter = event.key === "Enter";
1059
1066
  const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
1060
1067
  const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
@@ -1070,7 +1077,9 @@ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
1070
1077
  }
1071
1078
  }
1072
1079
  }, [
1073
- form,
1080
+ form.canSave,
1081
+ form.formIsValid,
1082
+ form.handleSave,
1074
1083
  autoSave
1075
1084
  ]);
1076
1085
  useEffect6(() => {
@@ -1107,14 +1116,14 @@ var FormActions = ({ readonly, onCancel, outerSpacing = true }) => {
1107
1116
  }, onCancel && !readonly && /* @__PURE__ */ React8.createElement(IconButton2, {
1108
1117
  "data-testid": "cancel-button",
1109
1118
  icon: "ph--x--regular",
1110
- label: t("button cancel"),
1119
+ label: t("cancel button label"),
1111
1120
  onClick: onCancel
1112
1121
  }), handleSave && /* @__PURE__ */ React8.createElement(IconButton2, {
1113
1122
  type: "submit",
1114
1123
  "data-testid": "save-button",
1115
1124
  disabled: !canSave,
1116
1125
  icon: "ph--check--regular",
1117
- label: t("button save"),
1126
+ label: t("save button label"),
1118
1127
  onClick: handleSave
1119
1128
  }));
1120
1129
  } finally {
@@ -1123,44 +1132,46 @@ var FormActions = ({ readonly, onCancel, outerSpacing = true }) => {
1123
1132
  };
1124
1133
 
1125
1134
  // src/components/Form/FormContent.tsx
1126
- import { useSignals as _useSignals11 } from "@preact-signals/safe-react/tracking";
1127
- import { Schema, SchemaAST as SchemaAST4, pipe as pipe2 } from "effect";
1128
- import { capitalize as capitalize2 } from "effect/String";
1129
- import React11, { forwardRef, useMemo as useMemo5 } from "react";
1135
+ import { useSignals as _useSignals12 } from "@preact-signals/safe-react/tracking";
1136
+ import * as Function2 from "effect/Function";
1137
+ import * as Schema from "effect/Schema";
1138
+ import * as SchemaAST4 from "effect/SchemaAST";
1139
+ import * as StringEffect from "effect/String";
1140
+ import React12, { Component, forwardRef as forwardRef2, useMemo as useMemo6 } from "react";
1130
1141
  import { createJsonPath as createJsonPath3, findNode as findNode3, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
1131
1142
  import { mx as mx6 } from "@dxos/react-ui-theme";
1132
1143
  import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
1133
- import { isNotFalsy } from "@dxos/util";
1144
+ import { isTruthy } from "@dxos/util";
1134
1145
 
1135
1146
  // src/util/field.ts
1136
- import { FormatEnum, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
1137
- var parseValue = ({ type, format, value }) => {
1138
- if (value === void 0 || value === null || value === "") {
1147
+ import { Format, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo/internal";
1148
+ var parseValue = ({ type, format, value: value2 }) => {
1149
+ if (value2 === void 0 || value2 === null || value2 === "") {
1139
1150
  return void 0;
1140
1151
  }
1141
1152
  const parseScalar = (type2) => {
1142
1153
  switch (type2) {
1143
1154
  case TypeEnum.Boolean: {
1144
- if (typeof value === "string") {
1145
- const lowercaseValue = value.toLowerCase();
1155
+ if (typeof value2 === "string") {
1156
+ const lowercaseValue = value2.toLowerCase();
1146
1157
  if (lowercaseValue === "0" || lowercaseValue === "false") {
1147
1158
  return false;
1148
1159
  } else if (lowercaseValue === "1" || lowercaseValue === "true") {
1149
1160
  return true;
1150
1161
  }
1151
1162
  }
1152
- return Boolean(value);
1163
+ return Boolean(value2);
1153
1164
  }
1154
1165
  case TypeEnum.Number: {
1155
- const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1166
+ const cleaned = typeof value2 === "string" ? value2.replace(/[^0-9.-]+/g, "") : value2;
1156
1167
  const num = Number(cleaned);
1157
1168
  return Number.isNaN(num) ? null : num;
1158
1169
  }
1159
1170
  case TypeEnum.String:
1160
1171
  case TypeEnum.Ref:
1161
- return String(value);
1172
+ return String(value2);
1162
1173
  default: {
1163
- return value;
1174
+ return value2;
1164
1175
  }
1165
1176
  }
1166
1177
  };
@@ -1168,28 +1179,28 @@ var parseValue = ({ type, format, value }) => {
1168
1179
  return parseScalar(type);
1169
1180
  }
1170
1181
  switch (format) {
1171
- case FormatEnum.Boolean:
1182
+ case Format.TypeFormat.Boolean:
1172
1183
  return parseScalar(TypeEnum.Boolean);
1173
- case FormatEnum.Number:
1174
- case FormatEnum.Percent:
1175
- case FormatEnum.Currency:
1184
+ case Format.TypeFormat.Number:
1185
+ case Format.TypeFormat.Percent:
1186
+ case Format.TypeFormat.Currency:
1176
1187
  return parseScalar(TypeEnum.Number);
1177
- case FormatEnum.String:
1178
- case FormatEnum.Markdown: {
1188
+ case Format.TypeFormat.String:
1189
+ case Format.TypeFormat.Markdown: {
1179
1190
  return parseScalar(TypeEnum.String);
1180
1191
  }
1181
- case FormatEnum.Ref:
1182
- throw new Error(`unexpected format: ${FormatEnum.Ref}`);
1183
- case FormatEnum.DateTime:
1184
- case FormatEnum.Date:
1185
- case FormatEnum.Time:
1186
- case FormatEnum.Timestamp: {
1187
- const date = new Date(value);
1192
+ case Format.TypeFormat.Ref:
1193
+ throw new Error(`unexpected format: ${Format.TypeFormat.Ref}`);
1194
+ case Format.TypeFormat.DateTime:
1195
+ case Format.TypeFormat.Date:
1196
+ case Format.TypeFormat.Time:
1197
+ case Format.TypeFormat.Timestamp: {
1198
+ const date = new Date(value2);
1188
1199
  return isNaN(date.getTime()) ? null : date;
1189
1200
  }
1190
- case FormatEnum.GeoPoint: {
1191
- if (typeof value === "string") {
1192
- const cleaned = value.replace(/[^0-9.,-]+/g, "");
1201
+ case Format.TypeFormat.GeoPoint: {
1202
+ if (typeof value2 === "string") {
1203
+ const cleaned = value2.replace(/[^0-9.,-]+/g, "");
1193
1204
  const parts = cleaned.split(",");
1194
1205
  if (parts.length === 2) {
1195
1206
  const lat = parseFloat(parts[0]);
@@ -1208,29 +1219,29 @@ var parseValue = ({ type, format, value }) => {
1208
1219
  ];
1209
1220
  }
1210
1221
  default: {
1211
- return value;
1222
+ return value2;
1212
1223
  }
1213
1224
  }
1214
1225
  };
1215
1226
  var cellClassesForFieldType = ({ type, format }) => {
1216
1227
  switch (format || type) {
1217
- case FormatEnum.Markdown:
1228
+ case Format.TypeFormat.Markdown:
1218
1229
  return void 0;
1219
- case FormatEnum.Time:
1220
- case FormatEnum.Timestamp:
1221
- case FormatEnum.DateTime:
1222
- case FormatEnum.Date:
1223
- case FormatEnum.Duration:
1230
+ case Format.TypeFormat.Time:
1231
+ case Format.TypeFormat.Timestamp:
1232
+ case Format.TypeFormat.DateTime:
1233
+ case Format.TypeFormat.Date:
1234
+ case Format.TypeFormat.Duration:
1224
1235
  return [
1225
1236
  "font-mono",
1226
1237
  "text-right"
1227
1238
  ];
1228
- case FormatEnum.Currency:
1239
+ case Format.TypeFormat.Currency:
1229
1240
  return [
1230
1241
  "text-right"
1231
1242
  ];
1232
- case FormatEnum.JSON:
1233
- case FormatEnum.DID:
1243
+ case Format.TypeFormat.JSON:
1244
+ case Format.TypeFormat.DID:
1234
1245
  return [
1235
1246
  "font-mono"
1236
1247
  ];
@@ -1255,19 +1266,19 @@ var pathNotUniqueError = (path) => ({
1255
1266
 
1256
1267
  // src/util/formatting.ts
1257
1268
  import { format as formatDate } from "date-fns/format";
1258
- import { FormatEnum as FormatEnum2, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1259
- var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1269
+ import { Format as Format2, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo/internal";
1270
+ var formatForDisplay = ({ type, format, value: value2, locale = void 0 }) => {
1260
1271
  const formatScalar = (type2) => {
1261
1272
  switch (type2) {
1262
1273
  case TypeEnum2.Boolean:
1263
- return value.toLocaleString().toUpperCase();
1274
+ return value2.toLocaleString().toUpperCase();
1264
1275
  case TypeEnum2.Number:
1265
- return value.toLocaleString(locale);
1276
+ return value2.toLocaleString(locale);
1266
1277
  case TypeEnum2.String:
1267
1278
  case TypeEnum2.Ref:
1268
- return String(value);
1279
+ return String(value2);
1269
1280
  default: {
1270
- return String(value);
1281
+ return String(value2);
1271
1282
  }
1272
1283
  }
1273
1284
  };
@@ -1275,144 +1286,137 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1275
1286
  return formatScalar(type);
1276
1287
  }
1277
1288
  switch (format) {
1278
- case FormatEnum2.Boolean: {
1289
+ case Format2.TypeFormat.Boolean: {
1279
1290
  return formatScalar(TypeEnum2.Boolean);
1280
1291
  }
1281
- case FormatEnum2.Number: {
1292
+ case Format2.TypeFormat.Number: {
1282
1293
  return formatScalar(TypeEnum2.Number);
1283
1294
  }
1284
- case FormatEnum2.String:
1285
- case FormatEnum2.Ref: {
1295
+ case Format2.TypeFormat.String:
1296
+ case Format2.TypeFormat.Ref: {
1286
1297
  return formatScalar(TypeEnum2.String);
1287
1298
  }
1288
- case FormatEnum2.Percent: {
1289
- return `${value * 100}%`;
1299
+ case Format2.TypeFormat.Percent: {
1300
+ return `${value2 * 100}%`;
1290
1301
  }
1291
- case FormatEnum2.Currency: {
1292
- return value.toLocaleString(locale, {
1302
+ case Format2.TypeFormat.Currency: {
1303
+ return value2.toLocaleString(locale, {
1293
1304
  style: "currency",
1294
1305
  currency: "USD",
1295
1306
  minimumFractionDigits: 2,
1296
1307
  maximumFractionDigits: 2
1297
1308
  });
1298
1309
  }
1299
- case FormatEnum2.Date: {
1310
+ case Format2.TypeFormat.Date: {
1300
1311
  try {
1301
- return formatDate(new Date(value), "yyyy-MM-dd");
1312
+ return formatDate(new Date(value2), "yyyy-MM-dd");
1302
1313
  } catch (error) {
1303
1314
  return "Invalid Date";
1304
1315
  }
1305
1316
  }
1306
- case FormatEnum2.Time: {
1317
+ case Format2.TypeFormat.Time: {
1307
1318
  try {
1308
- return formatDate(new Date(value), "HH:mm:ss");
1319
+ return formatDate(new Date(value2), "HH:mm:ss");
1309
1320
  } catch (error) {
1310
1321
  return "Invalid Time";
1311
1322
  }
1312
1323
  }
1313
- case FormatEnum2.DateTime: {
1324
+ case Format2.TypeFormat.DateTime: {
1314
1325
  try {
1315
- return formatDate(new Date(value), "yyyy-MM-dd HH:mm:ss");
1326
+ return formatDate(new Date(value2), "yyyy-MM-dd HH:mm:ss");
1316
1327
  } catch (error) {
1317
1328
  return "Invalid DateTime";
1318
1329
  }
1319
1330
  }
1320
- case FormatEnum2.GeoPoint: {
1321
- if (value === null || value === void 0) {
1331
+ case Format2.TypeFormat.GeoPoint: {
1332
+ if (value2 === null || value2 === void 0) {
1322
1333
  return "";
1323
1334
  }
1324
- if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1325
- const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1335
+ if (Array.isArray(value2) && value2.length >= 2 && value2.every(Number.isFinite)) {
1336
+ const { latitude, longitude } = GeoLocation3.fromGeoPoint(value2);
1326
1337
  return `${latitude},${longitude}`;
1327
1338
  }
1328
- return String(value);
1339
+ return String(value2);
1329
1340
  }
1330
1341
  default: {
1331
- if (value === null || value === "undefined") {
1342
+ if (value2 === null || value2 === "undefined") {
1332
1343
  return "";
1333
1344
  }
1334
- return String(value);
1345
+ return String(value2);
1335
1346
  }
1336
1347
  }
1337
1348
  };
1338
- var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1349
+ var formatForEditing = ({ type, format, value: value2, locale = void 0 }) => {
1339
1350
  const formatScalar = (type2) => {
1340
1351
  switch (type2) {
1341
1352
  case TypeEnum2.Boolean:
1342
1353
  case TypeEnum2.Number:
1343
1354
  case TypeEnum2.String:
1344
1355
  case TypeEnum2.Ref:
1345
- return String(value);
1356
+ return String(value2);
1346
1357
  default:
1347
- return String(value);
1358
+ return String(value2);
1348
1359
  }
1349
1360
  };
1350
1361
  if (!format) {
1351
1362
  return formatScalar(type);
1352
1363
  }
1353
1364
  switch (format) {
1354
- case FormatEnum2.Boolean:
1355
- case FormatEnum2.Number:
1356
- case FormatEnum2.String:
1357
- case FormatEnum2.Ref: {
1365
+ case Format2.TypeFormat.Boolean:
1366
+ case Format2.TypeFormat.Number:
1367
+ case Format2.TypeFormat.String:
1368
+ case Format2.TypeFormat.Ref: {
1358
1369
  return formatScalar(type);
1359
1370
  }
1360
- case FormatEnum2.Percent: {
1361
- return String(value * 100);
1371
+ case Format2.TypeFormat.Percent: {
1372
+ return String(value2 * 100);
1362
1373
  }
1363
- case FormatEnum2.Currency: {
1364
- return String(value);
1374
+ case Format2.TypeFormat.Currency: {
1375
+ return String(value2);
1365
1376
  }
1366
- case FormatEnum2.DateTime: {
1367
- const date = new Date(value);
1377
+ case Format2.TypeFormat.DateTime: {
1378
+ const date = new Date(value2);
1368
1379
  return date.toISOString();
1369
1380
  }
1370
- case FormatEnum2.Date: {
1371
- const date = new Date(value);
1381
+ case Format2.TypeFormat.Date: {
1382
+ const date = new Date(value2);
1372
1383
  return date.toISOString().split("T")[0];
1373
1384
  }
1374
- case FormatEnum2.Time: {
1375
- const date = new Date(value);
1385
+ case Format2.TypeFormat.Time: {
1386
+ const date = new Date(value2);
1376
1387
  return date.toISOString().split("T")[1].split(".")[0];
1377
1388
  }
1378
- case FormatEnum2.GeoPoint: {
1379
- if (value === null || value === void 0) {
1389
+ case Format2.TypeFormat.GeoPoint: {
1390
+ if (value2 === null || value2 === void 0) {
1380
1391
  return "";
1381
1392
  }
1382
- if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1383
- const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1393
+ if (Array.isArray(value2) && value2.length >= 2 && value2.every(Number.isFinite)) {
1394
+ const { latitude, longitude } = GeoLocation3.fromGeoPoint(value2);
1384
1395
  return `${latitude},${longitude}`;
1385
1396
  }
1386
- return String(value);
1397
+ return String(value2);
1387
1398
  }
1388
1399
  default: {
1389
- return String(value);
1400
+ return String(value2);
1390
1401
  }
1391
1402
  }
1392
1403
  };
1393
1404
 
1394
1405
  // src/util/refs.ts
1395
- import { FormatEnum as FormatEnum3, ReferenceAnnotationId } from "@dxos/echo-schema";
1406
+ import { Format as Format3, ReferenceAnnotationId } from "@dxos/echo/internal";
1396
1407
  import { findAnnotation } from "@dxos/effect";
1397
1408
 
1398
1409
  // src/util/schema.ts
1399
- import { SchemaAST as SchemaAST2 } from "effect";
1410
+ import * as SchemaAST2 from "effect/SchemaAST";
1400
1411
  import { findNode } from "@dxos/effect";
1401
1412
  var findArrayElementType = (ast) => {
1402
1413
  const tupleType = findNode(ast, SchemaAST2.isTupleType);
1403
- const elementType = tupleType?.rest[0]?.type;
1404
- return elementType;
1414
+ return tupleType?.rest[0]?.type;
1405
1415
  };
1406
1416
 
1407
1417
  // src/util/refs.ts
1408
1418
  var getRefProps = (property) => {
1409
1419
  const { ast, format, array } = property;
1410
- if (format === FormatEnum3.Ref) {
1411
- return {
1412
- ast,
1413
- isArray: false
1414
- };
1415
- }
1416
1420
  if (array) {
1417
1421
  const elementType = findArrayElementType(ast);
1418
1422
  if (elementType) {
@@ -1425,14 +1429,21 @@ var getRefProps = (property) => {
1425
1429
  }
1426
1430
  }
1427
1431
  }
1432
+ if (format === Format3.TypeFormat.Ref) {
1433
+ return {
1434
+ ast,
1435
+ isArray: false
1436
+ };
1437
+ }
1428
1438
  return void 0;
1429
1439
  };
1430
1440
 
1431
1441
  // src/components/Form/ArrayField.tsx
1432
1442
  import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
1433
- import { SchemaAST as SchemaAST3, pipe } from "effect";
1434
- import { capitalize } from "effect/String";
1435
- import React9, { Fragment, useCallback as useCallback7 } from "react";
1443
+ import * as Function from "effect/Function";
1444
+ import * as SchemaAST3 from "effect/SchemaAST";
1445
+ import * as String2 from "effect/String";
1446
+ import React9, { Fragment, useCallback as useCallback8 } from "react";
1436
1447
  import { SimpleType, findNode as findNode2, getDiscriminatedType, isDiscriminatedUnion } from "@dxos/effect";
1437
1448
  import { invariant as invariant2 } from "@dxos/invariant";
1438
1449
  import { IconButton as IconButton3, useTranslation as useTranslation6 } from "@dxos/react-ui";
@@ -1446,14 +1457,14 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1446
1457
  const values = useFormValues(path ?? []) ?? [];
1447
1458
  invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
1448
1459
  F: __dxlog_file3,
1449
- L: 36,
1460
+ L: 37,
1450
1461
  S: void 0,
1451
1462
  A: [
1452
1463
  "Array.isArray(values)",
1453
1464
  "`Values at path ${path?.join('.')} must be an array.`"
1454
1465
  ]
1455
1466
  });
1456
- const label = title ?? pipe(name, capitalize);
1467
+ const label = title ?? Function.pipe(name, String2.capitalize);
1457
1468
  const elementType = findArrayElementType(ast);
1458
1469
  const getDefaultObjectValue = (typeNode) => {
1459
1470
  const baseNode = findNode2(typeNode, isDiscriminatedUnion);
@@ -1461,13 +1472,15 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1461
1472
  if (!typeLiteral) {
1462
1473
  return {};
1463
1474
  }
1464
- return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
1475
+ return Object.fromEntries(getSchemaProperties(typeLiteral, {}, {
1476
+ form: true
1477
+ }).map((prop) => [
1465
1478
  prop.name,
1466
1479
  prop.defaultValue
1467
1480
  ]));
1468
1481
  };
1469
1482
  const getDefaultValue = () => type === "object" && elementType ? getDefaultObjectValue(elementType) : SimpleType.getDefaultValue(type);
1470
- const handleAdd = useCallback7(() => {
1483
+ const handleAdd = useCallback8(() => {
1471
1484
  inputProps.onValueChange(type, [
1472
1485
  ...values,
1473
1486
  getDefaultValue()
@@ -1478,7 +1491,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1478
1491
  inputProps,
1479
1492
  values
1480
1493
  ]);
1481
- const handleRemove = useCallback7((index) => {
1494
+ const handleRemove = useCallback8((index) => {
1482
1495
  const newValues = values.filter((_, i) => i !== index);
1483
1496
  inputProps.onValueChange(type, newValues);
1484
1497
  }, [
@@ -1534,12 +1547,12 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1534
1547
  };
1535
1548
 
1536
1549
  // src/components/Form/factory.tsx
1537
- import { FormatEnum as FormatEnum4 } from "@dxos/echo-schema";
1550
+ import { Format as Format4 } from "@dxos/echo/internal";
1538
1551
  var getInputComponent = (type, format) => {
1539
1552
  switch (format) {
1540
- case FormatEnum4.GeoPoint:
1553
+ case Format4.TypeFormat.GeoPoint:
1541
1554
  return GeoPointInput;
1542
- case FormatEnum4.Markdown:
1555
+ case Format4.TypeFormat.Markdown:
1543
1556
  return MarkdownInput;
1544
1557
  }
1545
1558
  switch (type) {
@@ -1553,33 +1566,129 @@ var getInputComponent = (type, format) => {
1553
1566
  };
1554
1567
 
1555
1568
  // src/components/Form/RefField.tsx
1556
- import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
1557
- import React10, { useCallback as useCallback8, useMemo as useMemo4, useState as useState5 } from "react";
1558
- import { Expando, Ref, ReferenceAnnotationId as ReferenceAnnotationId2, getTypeAnnotation } from "@dxos/echo-schema";
1569
+ import { useSignals as _useSignals11 } from "@preact-signals/safe-react/tracking";
1570
+ import "@dxos/lit-ui/dx-tag-picker.pcss";
1571
+ import React11, { useCallback as useCallback10, useMemo as useMemo5 } from "react";
1572
+ import { Expando, Ref, ReferenceAnnotationId as ReferenceAnnotationId2, getTypeAnnotation } from "@dxos/echo/internal";
1559
1573
  import { findAnnotation as findAnnotation2 } from "@dxos/effect";
1560
1574
  import { DXN } from "@dxos/keys";
1561
- import { DxRefTag } from "@dxos/lit-ui/react";
1562
- import { Button as Button2, Icon as Icon2, Input as Input7, useTranslation as useTranslation7 } from "@dxos/react-ui";
1563
- import { PopoverCombobox } from "@dxos/react-ui-searchlist";
1564
- import { TagPickerItem } from "@dxos/react-ui-tag-picker";
1575
+ import { DxAnchor, DxTagPickerItem } from "@dxos/lit-ui/react";
1576
+ import { Button as Button2, Icon as Icon3, Input as Input7, useTranslation as useTranslation8 } from "@dxos/react-ui";
1565
1577
  import { descriptionText, mx as mx5 } from "@dxos/react-ui-theme";
1566
1578
  import { isNonNullable as isNonNullable2 } from "@dxos/util";
1579
+
1580
+ // src/components/ObjectPicker/ObjectPicker.tsx
1581
+ import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
1582
+ import React10, { forwardRef, useCallback as useCallback9, useMemo as useMemo4, useState as useState5 } from "react";
1583
+ import { Icon as Icon2, Popover, useTranslation as useTranslation7 } from "@dxos/react-ui";
1584
+ import { Combobox } from "@dxos/react-ui-searchlist";
1585
+ var ObjectPickerContent = /* @__PURE__ */ forwardRef(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, onSelect, onCreate, ...props }, ref) => {
1586
+ var _effect = _useSignals10();
1587
+ try {
1588
+ const { t } = useTranslation7(translationKey);
1589
+ const [searchString, setSearchString] = useState5("");
1590
+ const [showForm, setShowForm] = useState5(false);
1591
+ const handleFormSave = useCallback9((values) => {
1592
+ onCreate?.(values);
1593
+ setShowForm(false);
1594
+ setSearchString("");
1595
+ }, [
1596
+ onCreate
1597
+ ]);
1598
+ const handleFormCancel = useCallback9(() => {
1599
+ setShowForm(false);
1600
+ setSearchString("");
1601
+ }, []);
1602
+ const handleClick = useCallback9((event) => {
1603
+ if (createSchema && event.target.closest('[data-value="__create__"]')) {
1604
+ event.stopPropagation();
1605
+ event.preventDefault();
1606
+ setShowForm(true);
1607
+ }
1608
+ }, [
1609
+ createSchema
1610
+ ]);
1611
+ const handleKeyDown = useCallback9((event) => {
1612
+ if (event.key === "Enter" && createSchema && event.currentTarget.querySelector('[role="option"][aria-selected="true"][data-value="__create__"]')) {
1613
+ event.stopPropagation();
1614
+ event.preventDefault();
1615
+ setShowForm(true);
1616
+ }
1617
+ }, [
1618
+ createSchema
1619
+ ]);
1620
+ const labelById = useMemo4(() => options.reduce((acc, option) => {
1621
+ acc[option.id.toLowerCase()] = option.label.toLowerCase();
1622
+ return acc;
1623
+ }, {}), [
1624
+ options
1625
+ ]);
1626
+ return /* @__PURE__ */ React10.createElement(Combobox.Content, {
1627
+ ...props,
1628
+ ref,
1629
+ filter: (value2, search) => value2 === "__create__" || labelById[value2]?.includes(search.toLowerCase()) ? 1 : 0,
1630
+ onClickCapture: handleClick,
1631
+ onKeyDownCapture: handleKeyDown
1632
+ }, showForm && createSchema ? /* @__PURE__ */ React10.createElement(Popover.Viewport, null, /* @__PURE__ */ React10.createElement(Form, {
1633
+ schema: createSchema,
1634
+ values: createInitialValuePath ? {
1635
+ [createInitialValuePath]: searchString
1636
+ } : {},
1637
+ onSave: handleFormSave,
1638
+ onCancel: handleFormCancel,
1639
+ testId: "create-referenced-object-form"
1640
+ })) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Combobox.Input, {
1641
+ placeholder: t("ref field combobox input placeholder"),
1642
+ value: searchString,
1643
+ onValueChange: setSearchString,
1644
+ autoFocus: true
1645
+ }), /* @__PURE__ */ React10.createElement(Combobox.List, null, options.map((option) => /* @__PURE__ */ React10.createElement(Combobox.Item, {
1646
+ key: option.id,
1647
+ value: option.id,
1648
+ onSelect: () => onSelect(option.id),
1649
+ classNames: "flex items-center gap-2"
1650
+ }, /* @__PURE__ */ React10.createElement("span", {
1651
+ className: "grow"
1652
+ }, option.label), selectedIds?.includes(option.id) && /* @__PURE__ */ React10.createElement(Icon2, {
1653
+ icon: "ph--check--regular"
1654
+ }))), searchString.length > 0 && createOptionLabel && createOptionIcon && createSchema && onCreate && /* @__PURE__ */ React10.createElement(Combobox.Item, {
1655
+ value: "__create__",
1656
+ classNames: "flex items-center gap-2"
1657
+ }, /* @__PURE__ */ React10.createElement(Icon2, {
1658
+ icon: createOptionIcon
1659
+ }), t(createOptionLabel[0], {
1660
+ ns: createOptionLabel[1].ns,
1661
+ text: searchString
1662
+ })))), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
1663
+ } finally {
1664
+ _effect.f();
1665
+ }
1666
+ });
1667
+ ObjectPickerContent.displayName = "ObjectPickerContent";
1668
+ var ObjectPicker = {
1669
+ Root: Combobox.Root,
1670
+ Trigger: Combobox.Trigger,
1671
+ VirtualTrigger: Combobox.VirtualTrigger,
1672
+ Content: ObjectPickerContent
1673
+ };
1674
+
1675
+ // src/components/Form/RefField.tsx
1567
1676
  var isRefSnapShot = (val) => {
1568
1677
  return typeof val === "object" && typeof val?.["/"] === "string";
1569
1678
  };
1570
- var RefField = ({ type, label, readonly, placeholder, inputOnly, array, ast, getValue: getValue3, onBlur, onQueryRefOptions, createOptionLabel, createOptionIcon, onCreateFromQuery, onValueChange, ...restInputProps }) => {
1571
- var _effect = _useSignals10();
1679
+ var RefField = ({ type, label, readonly, placeholder, inputOnly, array, ast, getValue: getValue3, createOptionLabel, createOptionIcon, onBlur, onCreate, createSchema, createInitialValuePath, onQueryRefOptions, onValueChange, ...restInputProps }) => {
1680
+ var _effect = _useSignals11();
1572
1681
  try {
1573
- const { t } = useTranslation7(translationKey);
1574
- const refTypeInfo = useMemo4(() => ast ? findAnnotation2(ast, ReferenceAnnotationId2) : void 0, [
1682
+ const { t } = useTranslation8(translationKey);
1683
+ const refTypeInfo = useMemo5(() => ast ? findAnnotation2(ast, ReferenceAnnotationId2) : void 0, [
1575
1684
  ast
1576
1685
  ]);
1577
- const { options: availableOptions, loading: _loading } = useQueryRefOptions({
1686
+ const { options: availableOptions, update: updateOptions, loading: _loading } = useQueryRefOptions({
1578
1687
  refTypeInfo,
1579
1688
  onQueryRefOptions
1580
1689
  });
1581
1690
  if (refTypeInfo && refTypeInfo?.typename === getTypeAnnotation(Expando)?.typename || !onQueryRefOptions) {
1582
- return /* @__PURE__ */ React10.createElement(RefFieldFallback, {
1691
+ return /* @__PURE__ */ React11.createElement(RefFieldFallback, {
1583
1692
  type,
1584
1693
  label,
1585
1694
  placeholder,
@@ -1591,7 +1700,7 @@ var RefField = ({ type, label, readonly, placeholder, inputOnly, array, ast, get
1591
1700
  ...restInputProps
1592
1701
  });
1593
1702
  }
1594
- const handleGetValue = useCallback8(() => {
1703
+ const handleGetValue = useCallback10(() => {
1595
1704
  const formValue = getValue3();
1596
1705
  const unknownToRefOption = (val) => {
1597
1706
  const isRef = Ref.isRef(val);
@@ -1619,7 +1728,7 @@ var RefField = ({ type, label, readonly, placeholder, inputOnly, array, ast, get
1619
1728
  availableOptions,
1620
1729
  array
1621
1730
  ]);
1622
- const handleUpdate = useCallback8((ids) => {
1731
+ const handleUpdate = useCallback10((ids) => {
1623
1732
  if (ids.length === 0) {
1624
1733
  onValueChange("object", void 0);
1625
1734
  return;
@@ -1642,22 +1751,22 @@ var RefField = ({ type, label, readonly, placeholder, inputOnly, array, ast, get
1642
1751
  array,
1643
1752
  onValueChange
1644
1753
  ]);
1754
+ const handleCreate = useCallback10((values) => {
1755
+ onCreate?.(values);
1756
+ updateOptions();
1757
+ }, [
1758
+ onCreate,
1759
+ updateOptions
1760
+ ]);
1645
1761
  if (!refTypeInfo) {
1646
1762
  return null;
1647
1763
  }
1648
1764
  const { status, error } = restInputProps.getStatus();
1649
1765
  const items = handleGetValue();
1650
- const selectedIds = useMemo4(() => items.map((i) => i.id), [
1766
+ const selectedIds = useMemo5(() => items.map((i) => i.id), [
1651
1767
  items
1652
1768
  ]);
1653
- const labelById = useMemo4(() => availableOptions.reduce((acc, option) => {
1654
- acc[option.id.toLowerCase()] = option.label.toLowerCase();
1655
- return acc;
1656
- }, {}), [
1657
- availableOptions
1658
- ]);
1659
- const [query, setQuery] = useState5("");
1660
- const toggleSelect = useCallback8((id) => {
1769
+ const toggleSelect = useCallback10((id) => {
1661
1770
  if (array) {
1662
1771
  const nextIds = selectedIds.includes(id) ? selectedIds.filter((x) => x !== id) : [
1663
1772
  ...selectedIds,
@@ -1678,28 +1787,28 @@ var RefField = ({ type, label, readonly, placeholder, inputOnly, array, ast, get
1678
1787
  selectedIds,
1679
1788
  handleUpdate
1680
1789
  ]);
1681
- return readonly && items.length < 1 ? null : /* @__PURE__ */ React10.createElement(Input7.Root, {
1790
+ return readonly && items.length < 1 ? null : /* @__PURE__ */ React11.createElement(Input7.Root, {
1682
1791
  validationValence: status
1683
- }, !inputOnly && /* @__PURE__ */ React10.createElement(InputHeader, {
1792
+ }, !inputOnly && /* @__PURE__ */ React11.createElement(InputHeader, {
1684
1793
  error,
1685
1794
  label
1686
- }), /* @__PURE__ */ React10.createElement("div", {
1795
+ }), /* @__PURE__ */ React11.createElement("div", {
1687
1796
  "data-no-submit": true
1688
- }, readonly ? items.length < 1 ? /* @__PURE__ */ React10.createElement("p", {
1797
+ }, readonly ? items.length < 1 ? /* @__PURE__ */ React11.createElement("p", {
1689
1798
  className: mx5(descriptionText, "mbe-2")
1690
- }, t("empty readonly ref field label")) : items.map((item) => /* @__PURE__ */ React10.createElement(DxRefTag, {
1799
+ }, t("empty readonly ref field label")) : items.map((item) => /* @__PURE__ */ React11.createElement(DxAnchor, {
1691
1800
  key: item.id,
1692
1801
  refid: item.id,
1693
1802
  rootclassname: "mie-1"
1694
- }, item.label)) : /* @__PURE__ */ React10.createElement(PopoverCombobox.Root, null, /* @__PURE__ */ React10.createElement(PopoverCombobox.Trigger, {
1803
+ }, item.label)) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Trigger, {
1695
1804
  asChild: true
1696
- }, /* @__PURE__ */ React10.createElement(Button2, {
1805
+ }, /* @__PURE__ */ React11.createElement(Button2, {
1697
1806
  variant: "ghost",
1698
1807
  classNames: "is-full text-start gap-2"
1699
- }, /* @__PURE__ */ React10.createElement("div", {
1808
+ }, /* @__PURE__ */ React11.createElement("div", {
1700
1809
  role: "none",
1701
1810
  className: "grow"
1702
- }, items?.length ? items?.map((item) => /* @__PURE__ */ React10.createElement(TagPickerItem, {
1811
+ }, items?.length ? items?.map((item) => /* @__PURE__ */ React11.createElement(DxTagPickerItem, {
1703
1812
  key: item.id,
1704
1813
  itemId: item.id,
1705
1814
  label: item.label,
@@ -1712,45 +1821,29 @@ var RefField = ({ type, label, readonly, placeholder, inputOnly, array, ast, get
1712
1821
  toggleSelect(item.id);
1713
1822
  }
1714
1823
  }
1715
- })) : /* @__PURE__ */ React10.createElement("span", {
1824
+ })) : /* @__PURE__ */ React11.createElement("span", {
1716
1825
  className: "text-description"
1717
1826
  }, placeholder ?? t("ref field placeholder", {
1718
1827
  count: array ? 99 : 1
1719
- }))), /* @__PURE__ */ React10.createElement(Icon2, {
1828
+ }))), /* @__PURE__ */ React11.createElement(Icon3, {
1720
1829
  size: 3,
1721
1830
  icon: "ph--caret-down--bold"
1722
- }))), /* @__PURE__ */ React10.createElement(PopoverCombobox.Content, {
1723
- filter: (value, search) => value === "__create__" || labelById[value]?.includes(search.toLowerCase()) ? 1 : 0
1724
- }, /* @__PURE__ */ React10.createElement(PopoverCombobox.Input, {
1725
- placeholder: "Search...",
1726
- value: query,
1727
- onValueChange: (v) => setQuery(v),
1728
- autoFocus: true
1729
- }), /* @__PURE__ */ React10.createElement(PopoverCombobox.List, null, availableOptions.map((option) => /* @__PURE__ */ React10.createElement(PopoverCombobox.Item, {
1730
- key: option.id,
1731
- value: option.id,
1732
- onSelect: () => toggleSelect(option.id),
1733
- classNames: "flex items-center gap-2"
1734
- }, /* @__PURE__ */ React10.createElement("span", {
1735
- className: "grow"
1736
- }, option.label), selectedIds.includes(option.id) && /* @__PURE__ */ React10.createElement(Icon2, {
1737
- icon: "ph--check--regular"
1738
- }))), query.length > 0 && createOptionLabel && createOptionIcon && onCreateFromQuery && /* @__PURE__ */ React10.createElement(PopoverCombobox.Item, {
1739
- value: "__create__",
1740
- onSelect: () => onCreateFromQuery?.(refTypeInfo, query),
1741
- classNames: "flex items-center gap-2"
1742
- }, /* @__PURE__ */ React10.createElement(Icon2, {
1743
- icon: createOptionIcon
1744
- }), t(createOptionLabel[0], {
1745
- ns: createOptionLabel[1].ns,
1746
- text: query
1747
- }))), /* @__PURE__ */ React10.createElement(PopoverCombobox.Arrow, null)))), inputOnly && /* @__PURE__ */ React10.createElement(Input7.DescriptionAndValidation, null, error));
1831
+ }))), /* @__PURE__ */ React11.createElement(ObjectPicker.Content, {
1832
+ options: availableOptions,
1833
+ selectedIds,
1834
+ onSelect: toggleSelect,
1835
+ createSchema,
1836
+ createOptionLabel,
1837
+ createOptionIcon,
1838
+ createInitialValuePath,
1839
+ onCreate: handleCreate
1840
+ }))), inputOnly && /* @__PURE__ */ React11.createElement(Input7.DescriptionAndValidation, null, error));
1748
1841
  } finally {
1749
1842
  _effect.f();
1750
1843
  }
1751
1844
  };
1752
1845
  var RefFieldFallback = ({ type, label, readonly, placeholder, inputOnly, getValue: getValue3, onValueChange, ...restInputProps }) => {
1753
- var _effect = _useSignals10();
1846
+ var _effect = _useSignals11();
1754
1847
  try {
1755
1848
  const handleOnValueChange = (_type, dxnString) => {
1756
1849
  const dxn = DXN.tryParse(dxnString);
@@ -1772,7 +1865,7 @@ var RefFieldFallback = ({ type, label, readonly, placeholder, inputOnly, getValu
1772
1865
  }
1773
1866
  return void 0;
1774
1867
  };
1775
- return /* @__PURE__ */ React10.createElement(TextInput, {
1868
+ return /* @__PURE__ */ React11.createElement(TextInput, {
1776
1869
  type,
1777
1870
  label,
1778
1871
  readonly,
@@ -1788,16 +1881,16 @@ var RefFieldFallback = ({ type, label, readonly, placeholder, inputOnly, getValu
1788
1881
  };
1789
1882
 
1790
1883
  // src/components/Form/FormContent.tsx
1791
- var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptions, createOptionLabel, createOptionIcon, onCreateFromQuery, lookupComponent, Custom }) => {
1792
- var _effect = _useSignals11();
1884
+ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptions, createOptionLabel, createOptionIcon, onCreate, createSchema, createInitialValuePath, lookupComponent, Custom }) => {
1885
+ var _effect = _useSignals12();
1793
1886
  try {
1794
1887
  const { ast, name, type, format, title, description, options, examples, array } = property;
1795
1888
  const inputProps = useInputProps(path);
1796
- const label = useMemo5(() => title ?? pipe2(name, capitalize2), [
1889
+ const label = useMemo6(() => title ?? Function2.pipe(name, StringEffect.capitalize), [
1797
1890
  title,
1798
1891
  name
1799
1892
  ]);
1800
- const placeholder = useMemo5(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1893
+ const placeholder = useMemo6(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1801
1894
  examples,
1802
1895
  description
1803
1896
  ]);
@@ -1819,7 +1912,7 @@ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptio
1819
1912
  const jsonPath = createJsonPath3(path ?? []);
1820
1913
  const CustomComponent = Custom?.[jsonPath];
1821
1914
  if (CustomComponent) {
1822
- return /* @__PURE__ */ React11.createElement(CustomComponent, {
1915
+ return /* @__PURE__ */ React12.createElement(CustomComponent, {
1823
1916
  type,
1824
1917
  format,
1825
1918
  label,
@@ -1831,7 +1924,7 @@ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptio
1831
1924
  }
1832
1925
  const refProps = getRefProps(property);
1833
1926
  if (refProps) {
1834
- return /* @__PURE__ */ React11.createElement(RefField, {
1927
+ return /* @__PURE__ */ React12.createElement(RefField, {
1835
1928
  ast: refProps.ast,
1836
1929
  array: refProps.isArray,
1837
1930
  type,
@@ -1843,12 +1936,14 @@ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptio
1843
1936
  onQueryRefOptions,
1844
1937
  createOptionLabel,
1845
1938
  createOptionIcon,
1846
- onCreateFromQuery,
1939
+ onCreate,
1940
+ createSchema,
1941
+ createInitialValuePath,
1847
1942
  ...inputProps
1848
1943
  });
1849
1944
  }
1850
1945
  if (array) {
1851
- return /* @__PURE__ */ React11.createElement(ArrayField, {
1946
+ return /* @__PURE__ */ React12.createElement(ArrayField, {
1852
1947
  property,
1853
1948
  path,
1854
1949
  inputProps,
@@ -1858,7 +1953,7 @@ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptio
1858
1953
  }
1859
1954
  const InputComponent = getInputComponent(type, format);
1860
1955
  if (InputComponent) {
1861
- return /* @__PURE__ */ React11.createElement(InputComponent, {
1956
+ return /* @__PURE__ */ React12.createElement(InputComponent, {
1862
1957
  type,
1863
1958
  format,
1864
1959
  label,
@@ -1869,7 +1964,7 @@ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptio
1869
1964
  });
1870
1965
  }
1871
1966
  if (options) {
1872
- return /* @__PURE__ */ React11.createElement(SelectInput, {
1967
+ return /* @__PURE__ */ React12.createElement(SelectInput, {
1873
1968
  type,
1874
1969
  format,
1875
1970
  readonly,
@@ -1887,9 +1982,9 @@ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptio
1887
1982
  const baseNode = findNode3(ast, isDiscriminatedUnion2);
1888
1983
  const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode3(ast, SchemaAST4.isTypeLiteral);
1889
1984
  if (typeLiteral) {
1890
- return /* @__PURE__ */ React11.createElement(React11.Fragment, null, !inline && /* @__PURE__ */ React11.createElement("h3", {
1985
+ return /* @__PURE__ */ React12.createElement(React12.Fragment, null, !inline && /* @__PURE__ */ React12.createElement("h3", {
1891
1986
  className: mx6("text-lg mlb-inputSpacingBlock first:mbs-0")
1892
- }, label), /* @__PURE__ */ React11.createElement(FormFields, {
1987
+ }, label), /* @__PURE__ */ React12.createElement(FormFields, {
1893
1988
  schema: Schema.make(typeLiteral),
1894
1989
  path,
1895
1990
  readonly,
@@ -1897,7 +1992,7 @@ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptio
1897
1992
  onQueryRefOptions,
1898
1993
  createOptionLabel,
1899
1994
  createOptionIcon,
1900
- onCreateFromQuery,
1995
+ onCreate,
1901
1996
  Custom,
1902
1997
  lookupComponent
1903
1998
  }));
@@ -1908,12 +2003,14 @@ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptio
1908
2003
  _effect.f();
1909
2004
  }
1910
2005
  };
1911
- var FormFields = /* @__PURE__ */ forwardRef(({ classNames, schema, path, filter, sort, projection, readonly, lookupComponent, Custom, onQueryRefOptions, ...props }, forwardRef2) => {
1912
- var _effect = _useSignals11();
2006
+ var FormFields = /* @__PURE__ */ forwardRef2(({ classNames, schema, path, filter, sort, projection, readonly, lookupComponent, Custom, onQueryRefOptions, ...props }, forwardRef4) => {
2007
+ var _effect = _useSignals12();
1913
2008
  try {
1914
2009
  const values = useFormValues(path);
1915
- const properties = useMemo5(() => {
1916
- const props2 = getSchemaProperties2(schema.ast, values);
2010
+ const properties = useMemo6(() => {
2011
+ const props2 = getSchemaProperties2(schema.ast, values, {
2012
+ form: true
2013
+ });
1917
2014
  if (projection) {
1918
2015
  const fieldProjections = projection.getFieldProjections();
1919
2016
  const hiddenProperties = new Set(projection.getHiddenProperties());
@@ -1940,13 +2037,18 @@ var FormFields = /* @__PURE__ */ forwardRef(({ classNames, schema, path, filter,
1940
2037
  sort,
1941
2038
  projection?.fields
1942
2039
  ]);
1943
- return /* @__PURE__ */ React11.createElement("div", {
2040
+ return /* @__PURE__ */ React12.createElement("div", {
1944
2041
  role: "form",
1945
2042
  className: mx6("is-full", classNames),
1946
- ref: forwardRef2
2043
+ ref: forwardRef4
1947
2044
  }, properties.map((property) => {
1948
- return /* @__PURE__ */ React11.createElement(FormField, {
2045
+ return /* @__PURE__ */ React12.createElement(ErrorBoundary, {
1949
2046
  key: property.name,
2047
+ path: [
2048
+ ...path ?? [],
2049
+ property.name
2050
+ ]
2051
+ }, /* @__PURE__ */ React12.createElement(FormField, {
1950
2052
  property,
1951
2053
  path: [
1952
2054
  ...path ?? [],
@@ -1958,16 +2060,46 @@ var FormFields = /* @__PURE__ */ forwardRef(({ classNames, schema, path, filter,
1958
2060
  lookupComponent,
1959
2061
  Custom,
1960
2062
  ...props
1961
- });
1962
- }).filter(isNotFalsy));
2063
+ }));
2064
+ }).filter(isTruthy));
1963
2065
  } finally {
1964
2066
  _effect.f();
1965
2067
  }
1966
2068
  });
2069
+ var ErrorBoundary = class extends Component {
2070
+ static getDerivedStateFromError(error) {
2071
+ return {
2072
+ error
2073
+ };
2074
+ }
2075
+ state = {
2076
+ error: void 0
2077
+ };
2078
+ componentDidUpdate(prevProps) {
2079
+ if (prevProps.path !== this.props.path) {
2080
+ this.resetError();
2081
+ }
2082
+ }
2083
+ render() {
2084
+ if (this.state.error) {
2085
+ return /* @__PURE__ */ React12.createElement("div", {
2086
+ className: "flex gap-2 border border-roseFill font-mono text-sm"
2087
+ }, /* @__PURE__ */ React12.createElement("span", {
2088
+ className: "bg-roseFill text-surfaceText pli-1 font-thin"
2089
+ }, "ERROR"), String(this.props.path?.join(".")));
2090
+ }
2091
+ return this.props.children;
2092
+ }
2093
+ resetError() {
2094
+ this.setState({
2095
+ error: void 0
2096
+ });
2097
+ }
2098
+ };
1967
2099
 
1968
2100
  // src/components/Form/Form.tsx
1969
- var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, autoSave, outerSpacing = true, schema, onCancel, onValuesChanged, onValidate, onSave, ...props }) => {
1970
- var _effect = _useSignals12();
2101
+ var Form = ({ classNames, id, testId, values: initialValues, autoFocus, readonly, autoSave, outerSpacing = true, schema, onCancel, onValuesChanged, onValidate, onSave, ...props }) => {
2102
+ var _effect = _useSignals13();
1971
2103
  try {
1972
2104
  const formRef = useRef3(null);
1973
2105
  const { findFirstFocusable } = useFocusFinders();
@@ -1981,11 +2113,15 @@ var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, au
1981
2113
  }, [
1982
2114
  autoFocus
1983
2115
  ]);
1984
- const handleValid = useMemo6(() => autoSave ? onSave : void 0, [
2116
+ const handleValid = useCallback11(async (values, meta) => {
2117
+ if (autoSave) {
2118
+ await onSave?.(values, meta);
2119
+ }
2120
+ }, [
1985
2121
  autoSave,
1986
2122
  onSave
1987
2123
  ]);
1988
- return /* @__PURE__ */ React12.createElement(FormProvider, {
2124
+ return /* @__PURE__ */ React13.createElement(FormProvider, {
1989
2125
  formRef,
1990
2126
  schema,
1991
2127
  autoSave,
@@ -1994,11 +2130,14 @@ var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, au
1994
2130
  onValidate,
1995
2131
  onValid: handleValid,
1996
2132
  onSave
1997
- }, /* @__PURE__ */ React12.createElement("div", {
2133
+ }, /* @__PURE__ */ React13.createElement("div", {
1998
2134
  role: "none",
1999
2135
  className: "contents",
2136
+ ...id && {
2137
+ "data-object-id": id
2138
+ },
2000
2139
  "data-testid": testId
2001
- }, /* @__PURE__ */ React12.createElement(FormFields, {
2140
+ }, /* @__PURE__ */ React13.createElement(FormFields, {
2002
2141
  ...props,
2003
2142
  ref: formRef,
2004
2143
  classNames: [
@@ -2008,7 +2147,7 @@ var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, au
2008
2147
  ],
2009
2148
  readonly,
2010
2149
  schema
2011
- }), (onCancel || onSave) && !autoSave && !readonly && /* @__PURE__ */ React12.createElement(FormActions, {
2150
+ }), (onCancel || onSave) && !autoSave && !readonly && /* @__PURE__ */ React13.createElement(FormActions, {
2012
2151
  readonly,
2013
2152
  onCancel,
2014
2153
  outerSpacing
@@ -2021,9 +2160,9 @@ var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, au
2021
2160
  // src/components/FieldEditor/FieldEditor.tsx
2022
2161
  var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
2023
2162
  var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel, outerSpacing }) => {
2024
- var _effect = _useSignals13();
2163
+ var _effect = _useSignals14();
2025
2164
  try {
2026
- const { t } = useTranslation8(translationKey);
2165
+ const { t } = useTranslation9(translationKey);
2027
2166
  const [props, setProps] = useState6(projection.getFieldProjection(field.id).props);
2028
2167
  useEffect8(() => setProps(projection.getFieldProjection(field.id).props), [
2029
2168
  field,
@@ -2053,7 +2192,7 @@ var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel, ou
2053
2192
  const [{ fieldSchema }, setFieldSchema] = useState6({
2054
2193
  fieldSchema: getFormatSchema(props?.format)
2055
2194
  });
2056
- const handleValuesChanged = useCallback9((_props) => {
2195
+ const handleValuesChanged = useCallback12((_props) => {
2057
2196
  setFieldSchema((prev) => {
2058
2197
  const fieldSchema2 = getFormatSchema(_props.format);
2059
2198
  if (prev.fieldSchema === fieldSchema2) {
@@ -2074,10 +2213,12 @@ var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel, ou
2074
2213
  });
2075
2214
  setProps((props2) => {
2076
2215
  const type = formatToType[_props.format];
2216
+ const additionalProps = formatToAdditionalPropertyAttributes[_props.format];
2077
2217
  if (props2.type !== type) {
2078
2218
  return {
2079
2219
  ...props2,
2080
2220
  ..._props,
2221
+ ...additionalProps,
2081
2222
  type
2082
2223
  };
2083
2224
  }
@@ -2088,7 +2229,7 @@ var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel, ou
2088
2229
  props.format,
2089
2230
  props.referenceSchema
2090
2231
  ]);
2091
- const handleValidate = useCallback9(({ property }) => {
2232
+ const handleValidate = useCallback12(({ property }) => {
2092
2233
  if (property && projection.fields.find((f) => f.path === property && f.path !== field.path)) {
2093
2234
  return [
2094
2235
  {
@@ -2101,7 +2242,7 @@ var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel, ou
2101
2242
  projection.fields,
2102
2243
  field
2103
2244
  ]);
2104
- const handleSave = useCallback9((props2) => {
2245
+ const handleSave = useCallback12((props2) => {
2105
2246
  projection.setFieldProjection({
2106
2247
  field,
2107
2248
  props: props2
@@ -2112,51 +2253,53 @@ var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel, ou
2112
2253
  field,
2113
2254
  onSave
2114
2255
  ]);
2115
- const handleCancel = useCallback9(() => {
2256
+ const handleCancel = useCallback12(() => {
2116
2257
  requestAnimationFrame(() => onCancel?.());
2117
2258
  onSave();
2118
2259
  }, [
2119
2260
  onSave
2120
2261
  ]);
2121
2262
  const custom = useMemo7(() => ({
2122
- ["format"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
2263
+ ["format"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
2123
2264
  ...props2,
2124
- options: FormatEnums.filter((value) => value !== FormatEnum5.None).map((value) => ({
2125
- value,
2126
- label: t(`format ${value}`)
2265
+ options: FormatEnums.filter((value2) => value2 !== Format5.TypeFormat.None).map((value2) => ({
2266
+ value: value2,
2267
+ label: t(`format ${value2}`)
2127
2268
  }))
2128
2269
  }),
2129
- ["referenceSchema"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
2270
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
2130
2271
  ...props2,
2131
2272
  options: schemas.map((schema) => ({
2132
2273
  value: schema.typename
2133
2274
  }))
2134
2275
  }),
2135
- ["referencePath"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
2276
+ ["referencePath"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
2136
2277
  ...props2,
2137
- options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
2278
+ options: referenceSchema ? getSchemaProperties3(referenceSchema.ast, {}, {
2279
+ form: true
2280
+ }).sort(sortProperties).map((p) => ({
2138
2281
  value: p.name
2139
2282
  })) : []
2140
2283
  }),
2141
- ["options"]: (props2) => /* @__PURE__ */ React13.createElement(SelectOptionInput, props2)
2284
+ ["options"]: (props2) => /* @__PURE__ */ React14.createElement(SelectOptionInput, props2)
2142
2285
  }), [
2143
2286
  t,
2144
2287
  schemas,
2145
2288
  referenceSchema
2146
2289
  ]);
2147
- const propIsNotType = useCallback9((props2) => props2.filter((p) => p.name !== "type"), []);
2290
+ const propIsNotType = useCallback12((props2) => props2.filter((p) => p.name !== "type"), []);
2148
2291
  if (!fieldSchema) {
2149
2292
  log3.warn("invalid format", {
2150
2293
  props
2151
2294
  }, {
2152
2295
  F: __dxlog_file4,
2153
- L: 177,
2296
+ L: 180,
2154
2297
  S: void 0,
2155
2298
  C: (f, a) => f(...a)
2156
2299
  });
2157
2300
  return null;
2158
2301
  }
2159
- return /* @__PURE__ */ React13.createElement(Form, {
2302
+ return /* @__PURE__ */ React14.createElement(Form, {
2160
2303
  key: field.id,
2161
2304
  autoFocus: true,
2162
2305
  readonly,
@@ -2180,55 +2323,83 @@ var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel, ou
2180
2323
  };
2181
2324
 
2182
2325
  // src/components/ViewEditor/ViewEditor.tsx
2183
- import { useSignals as _useSignals14 } from "@preact-signals/safe-react/tracking";
2184
- import { Schema as Schema2 } from "effect";
2185
- import React14, { useCallback as useCallback10, useMemo as useMemo8, useState as useState7 } from "react";
2186
- import { EchoSchema, Format, isMutable, toJsonSchema } from "@dxos/echo-schema";
2326
+ import { useSignals as _useSignals15 } from "@preact-signals/safe-react/tracking";
2327
+ import * as Array2 from "effect/Array";
2328
+ import * as Match from "effect/Match";
2329
+ import * as Option from "effect/Option";
2330
+ import * as Schema2 from "effect/Schema";
2331
+ import React15, { forwardRef as forwardRef3, useCallback as useCallback13, useImperativeHandle, useMemo as useMemo8, useState as useState7 } from "react";
2332
+ import { QueryAST } from "@dxos/echo";
2333
+ import { EchoSchema, Format as Format6, isMutable, toJsonSchema } from "@dxos/echo/internal";
2334
+ import { Filter as Filter2, Query } from "@dxos/echo-db";
2187
2335
  import { invariant as invariant3 } from "@dxos/invariant";
2188
- import { Callout, IconButton as IconButton4, useTranslation as useTranslation9 } from "@dxos/react-ui";
2336
+ import { Callout, IconButton as IconButton4, Input as Input8, useTranslation as useTranslation10 } from "@dxos/react-ui";
2337
+ import { QueryForm } from "@dxos/react-ui-components";
2189
2338
  import { List as List2 } from "@dxos/react-ui-list";
2190
2339
  import { cardSpacing as cardSpacing3 } from "@dxos/react-ui-stack";
2191
2340
  import { inputTextLabel, mx as mx7, subtleHover as subtleHover2 } from "@dxos/react-ui-theme";
2192
- import { FieldSchema, ProjectionModel, VIEW_FIELD_LIMIT } from "@dxos/schema";
2341
+ import { FieldSchema, ProjectionModel, VIEW_FIELD_LIMIT, getTypenameFromQuery } from "@dxos/schema";
2193
2342
  var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
2194
2343
  var listGrid = "grid grid-cols-[min-content_1fr_min-content_min-content_min-content]";
2195
2344
  var listItemGrid = "grid grid-cols-subgrid col-span-5";
2196
- var ViewMetaSchema = Schema2.Struct({
2197
- typename: Format.URL.annotations({
2198
- title: "Record type"
2199
- })
2200
- }).pipe(Schema2.mutable);
2201
- var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete, outerSpacing = true }) => {
2202
- var _effect = _useSignals14();
2345
+ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode = "schema", registry, readonly, showHeading = false, types, tags, onQueryChanged, onDelete, outerSpacing = true }, forwardedRef) => {
2346
+ var _effect = _useSignals15();
2203
2347
  try {
2204
2348
  const schemaReadonly = !isMutable(schema);
2205
- const { t } = useTranslation9(translationKey);
2349
+ const { t } = useTranslation10(translationKey);
2206
2350
  const projectionModel = useMemo8(() => {
2207
2351
  const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
2208
2352
  return new ProjectionModel(jsonSchema, view.projection);
2209
2353
  }, [
2210
2354
  schema,
2211
- view.projection
2355
+ JSON.stringify(view.projection)
2356
+ ]);
2357
+ useImperativeHandle(forwardedRef, () => projectionModel, [
2358
+ projectionModel
2212
2359
  ]);
2213
2360
  const [expandedField, setExpandedField] = useState7();
2214
- const viewValues = useMemo8(() => {
2215
- return {
2216
- // TODO(burdon): Need to warn user of possible consequences of editing.
2217
- // TODO(burdon): Settings should have domain name owned by user.
2218
- typename: view.query.typename
2219
- };
2361
+ const queueTarget = Match.value(view.query.ast).pipe(Match.when({
2362
+ type: "options"
2363
+ }, ({ options }) => {
2364
+ return Option.fromNullable(options.queues).pipe(Option.flatMap((queues) => Array2.head(queues)), Option.getOrUndefined);
2365
+ }), Match.orElse(() => void 0));
2366
+ const viewSchema = useMemo8(() => {
2367
+ const base = Schema2.Struct({
2368
+ query: mode === "schema" ? Format6.URL.annotations({
2369
+ title: "Record type"
2370
+ }) : QueryAST.Query.annotations({
2371
+ title: "Query"
2372
+ })
2373
+ });
2374
+ if (mode === "tag") {
2375
+ return Schema2.Struct({
2376
+ ...base.fields,
2377
+ target: Schema2.optional(Schema2.String.annotations({
2378
+ title: "Target Queue"
2379
+ }))
2380
+ }).pipe(Schema2.mutable);
2381
+ }
2382
+ return base.pipe(Schema2.mutable);
2220
2383
  }, [
2221
- view.query.typename
2384
+ mode
2385
+ ]);
2386
+ const viewValues = useMemo8(() => ({
2387
+ query: mode === "schema" ? getTypenameFromQuery(view.query.ast) : view.query.ast,
2388
+ target: queueTarget
2389
+ }), [
2390
+ mode,
2391
+ view.query.ast,
2392
+ queueTarget
2222
2393
  ]);
2223
- const handleToggleField = useCallback10((field) => {
2394
+ const handleToggleField = useCallback13((field) => {
2224
2395
  setExpandedField((prevExpandedFieldId) => prevExpandedFieldId === field.id ? void 0 : field.id);
2225
2396
  }, [
2226
2397
  readonly
2227
2398
  ]);
2228
- const handleAdd = useCallback10(() => {
2399
+ const handleAdd = useCallback13(() => {
2229
2400
  invariant3(!readonly, void 0, {
2230
2401
  F: __dxlog_file5,
2231
- L: 86,
2402
+ L: 129,
2232
2403
  S: void 0,
2233
2404
  A: [
2234
2405
  "!readonly",
@@ -2242,30 +2413,21 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
2242
2413
  projectionModel,
2243
2414
  readonly
2244
2415
  ]);
2245
- const handleUpdate = useCallback10(({ typename }) => {
2246
- invariant3(!readonly, void 0, {
2247
- F: __dxlog_file5,
2248
- L: 93,
2249
- S: void 0,
2250
- A: [
2251
- "!readonly",
2252
- ""
2253
- ]
2254
- });
2416
+ const handleUpdate = useCallback13((values) => {
2255
2417
  requestAnimationFrame(() => {
2256
- if (view.query.typename !== typename && !readonly) {
2257
- onTypenameChanged?.(typename);
2258
- }
2418
+ const query = mode === "schema" ? Query.select(Filter2.typename(values.query)).ast : values.query;
2419
+ onQueryChanged?.(query, values.target);
2259
2420
  });
2260
2421
  }, [
2261
- view.query.typename,
2262
- onTypenameChanged,
2263
- readonly
2422
+ onQueryChanged,
2423
+ view,
2424
+ queueTarget,
2425
+ mode
2264
2426
  ]);
2265
- const handleDelete = useCallback10((fieldId) => {
2427
+ const handleDelete = useCallback13((fieldId) => {
2266
2428
  invariant3(!readonly, void 0, {
2267
2429
  F: __dxlog_file5,
2268
- L: 105,
2430
+ L: 146,
2269
2431
  S: void 0,
2270
2432
  A: [
2271
2433
  "!readonly",
@@ -2281,10 +2443,10 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
2281
2443
  onDelete,
2282
2444
  readonly
2283
2445
  ]);
2284
- const handleMove = useCallback10((fromIndex, toIndex) => {
2446
+ const handleMove = useCallback13((fromIndex, toIndex) => {
2285
2447
  invariant3(!readonly, void 0, {
2286
2448
  F: __dxlog_file5,
2287
- L: 117,
2449
+ L: 158,
2288
2450
  S: void 0,
2289
2451
  A: [
2290
2452
  "!readonly",
@@ -2301,80 +2463,88 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
2301
2463
  view.projection.fields,
2302
2464
  readonly
2303
2465
  ]);
2304
- const handleClose = useCallback10(() => setExpandedField(void 0), []);
2305
- const handleHide = useCallback10((fieldId) => {
2466
+ const handleClose = useCallback13(() => setExpandedField(void 0), []);
2467
+ const handleHide = useCallback13((fieldId) => {
2306
2468
  setExpandedField(void 0);
2307
2469
  projectionModel.hideFieldProjection(fieldId);
2308
2470
  }, [
2309
2471
  projectionModel
2310
2472
  ]);
2311
- const handleShow = useCallback10((property) => {
2473
+ const handleShow = useCallback13((property) => {
2312
2474
  setExpandedField(void 0);
2313
2475
  projectionModel.showFieldProjection(property);
2314
2476
  }, [
2315
2477
  projectionModel
2316
2478
  ]);
2317
- return /* @__PURE__ */ React14.createElement("div", {
2479
+ const custom = useMemo8(() => mode === "tag" ? customFields({
2480
+ types,
2481
+ tags
2482
+ }) : void 0, [
2483
+ types,
2484
+ tags,
2485
+ mode
2486
+ ]);
2487
+ return /* @__PURE__ */ React15.createElement("div", {
2318
2488
  role: "none",
2319
2489
  className: mx7(classNames)
2320
- }, schemaReadonly && /* @__PURE__ */ React14.createElement(Callout.Root, {
2490
+ }, schemaReadonly && !readonly && /* @__PURE__ */ React15.createElement(Callout.Root, {
2321
2491
  valence: "info",
2322
2492
  classNames: [
2323
- "is-full mlb-cardSpacingBlock",
2493
+ "mlb-cardSpacingBlock",
2324
2494
  outerSpacing && "mli-cardSpacingInline"
2325
2495
  ]
2326
- }, /* @__PURE__ */ React14.createElement(Callout.Title, null, t("system schema description"))), /* @__PURE__ */ React14.createElement(Form, {
2496
+ }, /* @__PURE__ */ React15.createElement(Callout.Title, null, t("system schema description"))), /* @__PURE__ */ React15.createElement(Form, {
2327
2497
  autoSave: true,
2328
- schema: ViewMetaSchema,
2498
+ schema: viewSchema,
2329
2499
  values: viewValues,
2330
- readonly: readonly ? "disabled-input" : false,
2331
2500
  onSave: handleUpdate,
2332
- outerSpacing
2333
- }), /* @__PURE__ */ React14.createElement("div", {
2501
+ outerSpacing,
2502
+ Custom: custom
2503
+ }), /* @__PURE__ */ React15.createElement("div", {
2334
2504
  role: "none",
2335
2505
  className: outerSpacing ? cardSpacing3 : "mlb-cardSpacingBlock"
2336
- }, /* @__PURE__ */ React14.createElement("h2", {
2506
+ }, /* @__PURE__ */ React15.createElement("h2", {
2337
2507
  className: mx7(inputTextLabel)
2338
- }, t("fields label")), /* @__PURE__ */ React14.createElement(List2.Root, {
2508
+ }, t("fields label")), /* @__PURE__ */ React15.createElement(List2.Root, {
2339
2509
  items: view.projection.fields,
2340
2510
  isItem: Schema2.is(FieldSchema),
2341
2511
  getId: (field) => field.id,
2342
2512
  onMove: readonly ? void 0 : handleMove,
2343
2513
  readonly
2344
- }, ({ items: fields }) => /* @__PURE__ */ React14.createElement(React14.Fragment, null, showHeading && /* @__PURE__ */ React14.createElement("h3", {
2514
+ }, ({ items: fields }) => /* @__PURE__ */ React15.createElement(React15.Fragment, null, showHeading && /* @__PURE__ */ React15.createElement("h3", {
2345
2515
  className: "text-sm"
2346
- }, t("field path label")), /* @__PURE__ */ React14.createElement("div", {
2516
+ }, t("field path label")), /* @__PURE__ */ React15.createElement("div", {
2347
2517
  role: "list",
2348
2518
  className: listGrid
2349
2519
  }, fields?.map((field) => {
2350
2520
  const hidden = field.visible === false;
2351
- return /* @__PURE__ */ React14.createElement(List2.Item, {
2521
+ return /* @__PURE__ */ React15.createElement(List2.Item, {
2352
2522
  key: field.id,
2353
2523
  item: field,
2354
2524
  classNames: listItemGrid,
2355
2525
  "aria-expanded": expandedField === field.id
2356
- }, /* @__PURE__ */ React14.createElement("div", {
2526
+ }, /* @__PURE__ */ React15.createElement("div", {
2357
2527
  role: "none",
2358
2528
  className: mx7(subtleHover2, listItemGrid, "rounded-sm cursor-pointer min-bs-10")
2359
- }, /* @__PURE__ */ React14.createElement(List2.ItemDragHandle, {
2360
- disabled: readonly
2361
- }), /* @__PURE__ */ React14.createElement(List2.ItemTitle, {
2529
+ }, /* @__PURE__ */ React15.createElement(List2.ItemDragHandle, {
2530
+ disabled: readonly || schemaReadonly
2531
+ }), /* @__PURE__ */ React15.createElement(List2.ItemTitle, {
2362
2532
  classNames: hidden && "text-subdued",
2363
2533
  onClick: () => handleToggleField(field)
2364
- }, field.path), /* @__PURE__ */ React14.createElement(List2.ItemButton, {
2534
+ }, field.path), /* @__PURE__ */ React15.createElement(List2.ItemButton, {
2365
2535
  label: t(hidden ? "show field label" : "hide field label"),
2366
2536
  "data-testid": hidden ? "show-field-button" : "hide-field-button",
2367
2537
  icon: hidden ? "ph--eye-closed--regular" : "ph--eye--regular",
2368
2538
  autoHide: false,
2369
2539
  disabled: readonly || !hidden && projectionModel.fields.length <= 1,
2370
2540
  onClick: () => hidden ? handleShow(field.path) : handleHide(field.id)
2371
- }), /* @__PURE__ */ React14.createElement(List2.ItemDeleteButton, {
2541
+ }), !readonly && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(List2.ItemDeleteButton, {
2372
2542
  label: t("delete field label"),
2373
2543
  autoHide: false,
2374
2544
  disabled: readonly || schemaReadonly || view.projection.fields.length <= 1,
2375
2545
  onClick: () => handleDelete(field.id),
2376
2546
  "data-testid": "field.delete"
2377
- }), /* @__PURE__ */ React14.createElement(IconButton4, {
2547
+ }), /* @__PURE__ */ React15.createElement(IconButton4, {
2378
2548
  iconOnly: true,
2379
2549
  variant: "ghost",
2380
2550
  label: t("toggle expand label", {
@@ -2382,22 +2552,22 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
2382
2552
  }),
2383
2553
  icon: expandedField === field.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
2384
2554
  onClick: () => handleToggleField(field)
2385
- })), expandedField === field.id && /* @__PURE__ */ React14.createElement("div", {
2555
+ }))), expandedField === field.id && !readonly && /* @__PURE__ */ React15.createElement("div", {
2386
2556
  role: "none",
2387
2557
  className: "col-span-5 mbs-1 mbe-1 border border-separator rounded-md"
2388
- }, /* @__PURE__ */ React14.createElement(FieldEditor, {
2558
+ }, /* @__PURE__ */ React15.createElement(FieldEditor, {
2389
2559
  readonly: readonly || schemaReadonly ? "disabled-input" : false,
2390
2560
  projection: projectionModel,
2391
2561
  field,
2392
2562
  registry,
2393
2563
  onSave: handleClose
2394
2564
  })));
2395
- }))))), !readonly && !expandedField && /* @__PURE__ */ React14.createElement("div", {
2565
+ }))))), !readonly && !expandedField && /* @__PURE__ */ React15.createElement("div", {
2396
2566
  role: "none",
2397
2567
  className: outerSpacing ? cardSpacing3 : "mlb-cardSpacingBlock"
2398
- }, /* @__PURE__ */ React14.createElement(IconButton4, {
2568
+ }, /* @__PURE__ */ React15.createElement(IconButton4, {
2399
2569
  icon: "ph--plus--regular",
2400
- label: t("button add property"),
2570
+ label: t("add property button label"),
2401
2571
  onClick: readonly ? void 0 : handleAdd,
2402
2572
  // TODO(burdon): Show field limit in ux (not tooltip).
2403
2573
  disabled: view.projection.fields.length >= VIEW_FIELD_LIMIT,
@@ -2406,7 +2576,22 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
2406
2576
  } finally {
2407
2577
  _effect.f();
2408
2578
  }
2409
- };
2579
+ });
2580
+ var customFields = ({ types, tags }) => ({
2581
+ query: (props) => {
2582
+ const handleChange = useCallback13((query) => props.onValueChange("object", query.ast), [
2583
+ props.onValueChange
2584
+ ]);
2585
+ return /* @__PURE__ */ React15.createElement(Input8.Root, null, /* @__PURE__ */ React15.createElement(InputHeader, {
2586
+ label: props.label
2587
+ }), /* @__PURE__ */ React15.createElement(QueryForm, {
2588
+ initialQuery: props.getValue(),
2589
+ types,
2590
+ tags,
2591
+ onChange: handleChange
2592
+ }));
2593
+ }
2594
+ });
2410
2595
  export {
2411
2596
  BooleanInput,
2412
2597
  ControlFrame,
@@ -2425,6 +2610,7 @@ export {
2425
2610
  InputHeader,
2426
2611
  MarkdownInput,
2427
2612
  NumberInput,
2613
+ ObjectPicker,
2428
2614
  SelectInput,
2429
2615
  SelectOptionInput,
2430
2616
  TextInput,