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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/lib/browser/index.mjs +827 -537
  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 +675 -395
  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 +827 -537
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +1 -1
  11. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
  13. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.d.ts +6 -4
  15. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.stories.d.ts +37 -34
  17. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
  19. package/dist/types/src/components/Form/FormContent.d.ts +14 -11
  20. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
  21. package/dist/types/src/components/Form/FormContext.d.ts +2 -2
  22. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
  23. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  24. package/dist/types/src/components/Form/RefField.d.ts +12 -0
  25. package/dist/types/src/components/Form/RefField.d.ts.map +1 -0
  26. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  27. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  30. package/dist/types/src/components/Form/factory.d.ts +1 -1
  31. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  32. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  33. package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
  34. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +2 -2
  35. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  36. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/deprecated/Form.d.ts +2 -2
  38. package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
  39. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
  40. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
  41. package/dist/types/src/components/testing.d.ts.map +1 -1
  42. package/dist/types/src/hooks/index.d.ts +2 -0
  43. package/dist/types/src/hooks/index.d.ts.map +1 -1
  44. package/dist/types/src/hooks/useForm.d.ts +2 -2
  45. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  46. package/dist/types/src/hooks/useQueryRefOptions.d.ts +23 -0
  47. package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -0
  48. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +8 -0
  49. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -0
  50. package/dist/types/src/util/field.d.ts.map +1 -1
  51. package/dist/types/src/util/formatting.d.ts.map +1 -1
  52. package/dist/types/src/util/index.d.ts +2 -0
  53. package/dist/types/src/util/index.d.ts.map +1 -1
  54. package/dist/types/src/util/refs.d.ts +9 -0
  55. package/dist/types/src/util/refs.d.ts.map +1 -0
  56. package/dist/types/src/util/schema.d.ts +3 -0
  57. package/dist/types/src/util/schema.d.ts.map +1 -0
  58. package/dist/types/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +26 -25
  60. package/src/components/ControlSection/ControlSection.stories.tsx +1 -1
  61. package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
  62. package/src/components/Form/ArrayField.tsx +13 -17
  63. package/src/components/Form/Defaults.tsx +4 -1
  64. package/src/components/Form/Form.stories.tsx +92 -43
  65. package/src/components/Form/Form.tsx +7 -3
  66. package/src/components/Form/FormContent.tsx +90 -19
  67. package/src/components/Form/FormContext.tsx +13 -3
  68. package/src/components/Form/Input.tsx +3 -9
  69. package/src/components/Form/RefField.tsx +197 -0
  70. package/src/components/Form/custom/GeoPointInput.tsx +2 -2
  71. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +6 -5
  72. package/src/components/Form/custom/SelectOptionsInput.tsx +2 -2
  73. package/src/components/Form/factory.tsx +1 -1
  74. package/src/components/Form/index.ts +0 -1
  75. package/src/components/ViewEditor/ViewEditor.stories.tsx +5 -4
  76. package/src/components/ViewEditor/ViewEditor.tsx +23 -20
  77. package/src/components/deprecated/Form.tsx +6 -6
  78. package/src/hooks/index.ts +3 -1
  79. package/src/hooks/useForm.ts +4 -3
  80. package/src/hooks/useQueryRefOptions.ts +53 -0
  81. package/src/hooks/useRefQueryLookupHandler.ts +41 -0
  82. package/src/util/formatting.ts +15 -3
  83. package/src/util/index.ts +3 -1
  84. package/src/util/refs.ts +38 -0
  85. package/src/util/schema.ts +14 -0
@@ -181,9 +181,9 @@ var ControlFrameItem = ({ title, description, children }) => {
181
181
  };
182
182
 
183
183
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
184
- import React13, { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo7, useState as useState4 } from "react";
185
- import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
186
- import { log as log2 } from "@dxos/log";
184
+ import React14, { useCallback as useCallback8, useEffect as useEffect8, useMemo as useMemo7, useState as useState5 } from "react";
185
+ import { FormatEnum as FormatEnum5, FormatEnums, formatToType } from "@dxos/echo-schema";
186
+ import { log as log3 } from "@dxos/log";
187
187
  import { useTranslation as useTranslation6 } from "@dxos/react-ui";
188
188
  import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
189
189
 
@@ -201,15 +201,15 @@ var InputHeader = ({ children, error }) => {
201
201
  return /* @__PURE__ */ React3.createElement("div", {
202
202
  role: "none",
203
203
  className: "flex justify-between items-center mb-1"
204
- }, children, error && /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
205
- asChild: true
204
+ }, children, error && /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
205
+ asChild: true,
206
+ content: error,
207
+ side: "bottom"
206
208
  }, /* @__PURE__ */ React3.createElement(Icon, {
207
209
  icon: "ph--warning--regular",
208
210
  size: 4,
209
211
  classNames: errorText
210
- })), /* @__PURE__ */ React3.createElement(Tooltip.Content, {
211
- side: "bottom"
212
- }, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null), error)));
212
+ })));
213
213
  };
214
214
 
215
215
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
@@ -546,23 +546,28 @@ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, on
546
546
  };
547
547
  var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
548
548
  const { status, error } = getStatus();
549
+ const value = getValue3();
550
+ const handleValueChange = useCallback3((value2) => onValueChange(type, value2), [
551
+ type,
552
+ onValueChange
553
+ ]);
549
554
  return /* @__PURE__ */ React7.createElement(Input6.Root, {
550
555
  validationValence: status
551
556
  }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
552
557
  error
553
558
  }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Select.Root, {
554
- value: getValue3(),
555
- onValueChange: (value) => onValueChange(type, value)
559
+ value,
560
+ onValueChange: handleValueChange
556
561
  }, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
557
562
  classNames: "is-full",
558
563
  disabled,
559
564
  placeholder
560
- }), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
565
+ }), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value: value2, label: label2 }) => (
561
566
  // NOTE: Numeric values are converted to and from strings.
562
567
  /* @__PURE__ */ React7.createElement(Select.Option, {
563
- key: String(value),
564
- value: String(value)
565
- }, label2 ?? String(value))
568
+ key: String(value2),
569
+ value: String(value2)
570
+ }, label2 ?? String(value2))
566
571
  )))))), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
567
572
  };
568
573
  var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
@@ -606,7 +611,7 @@ var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus,
606
611
  };
607
612
 
608
613
  // packages/ui/react-ui-form/src/components/Form/Form.tsx
609
- import React12, { useEffect as useEffect6, useMemo as useMemo6, useRef as useRef3 } from "react";
614
+ import React13, { useEffect as useEffect7, useMemo as useMemo6, useRef as useRef3 } from "react";
610
615
  import { mx as mx8 } from "@dxos/react-ui-theme";
611
616
 
612
617
  // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
@@ -615,13 +620,13 @@ import { IconButton as IconButton2, useTranslation as useTranslation4 } from "@d
615
620
  import { mx as mx5 } from "@dxos/react-ui-theme";
616
621
 
617
622
  // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
618
- import React8, { createContext, useContext, useEffect as useEffect5, useMemo as useMemo3 } from "react";
623
+ import React8, { createContext, useContext, useEffect as useEffect6, useMemo as useMemo3 } from "react";
619
624
  import { raise } from "@dxos/debug";
620
625
  import { getValue as getValue2 } from "@dxos/echo-schema";
621
626
  import { createJsonPath as createJsonPath2 } from "@dxos/effect";
622
627
 
623
628
  // packages/ui/react-ui-form/src/hooks/useForm.ts
624
- import { SchemaAST as AST } from "effect";
629
+ import { SchemaAST } from "effect";
625
630
  import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useState as useState3 } from "react";
626
631
  import { getValue, setValue } from "@dxos/echo-schema";
627
632
  import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
@@ -630,12 +635,12 @@ import { log } from "@dxos/log";
630
635
  import { validateSchema } from "@dxos/schema";
631
636
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
632
637
  var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
633
- invariant(AST.isTypeLiteral(schema.ast), void 0, {
638
+ invariant(SchemaAST.isTypeLiteral(schema.ast), void 0, {
634
639
  F: __dxlog_file,
635
640
  L: 93,
636
641
  S: void 0,
637
642
  A: [
638
- "AST.isTypeLiteral(schema.ast)",
643
+ "SchemaAST.isTypeLiteral(schema.ast)",
639
644
  ""
640
645
  ]
641
646
  });
@@ -736,7 +741,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
736
741
  } catch (err) {
737
742
  log.catch(err, void 0, {
738
743
  F: __dxlog_file,
739
- L: 212,
744
+ L: 213,
740
745
  S: void 0,
741
746
  C: (f, a) => f(...a)
742
747
  });
@@ -807,7 +812,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
807
812
  var createKeySet = (obj, value) => {
808
813
  invariant(obj, void 0, {
809
814
  F: __dxlog_file,
810
- L: 274,
815
+ L: 275,
811
816
  S: void 0,
812
817
  A: [
813
818
  "obj",
@@ -829,6 +834,81 @@ var flatMap = (errors) => {
829
834
  }, {});
830
835
  };
831
836
 
837
+ // packages/ui/react-ui-form/src/hooks/useRefQueryLookupHandler.ts
838
+ import { useCallback as useCallback5 } from "react";
839
+ import { getDXN } from "@dxos/echo-schema";
840
+ import { Filter } from "@dxos/react-client/echo";
841
+ import { isNonNullable } from "@dxos/util";
842
+ var useRefQueryLookupHandler = ({ space }) => {
843
+ const handleRefQueryLookup = useCallback5(async (typeInfo) => {
844
+ if (!space) {
845
+ return [];
846
+ }
847
+ const query = space.db.query(Filter.typename(typeInfo.typename));
848
+ const { objects } = await query.run();
849
+ return objects.map((object) => {
850
+ const dxn = getDXN(object);
851
+ if (!dxn) {
852
+ return void 0;
853
+ }
854
+ const item = {
855
+ dxn,
856
+ label: object?.name ?? object?.id ?? ""
857
+ };
858
+ return item;
859
+ }).filter(isNonNullable);
860
+ }, [
861
+ space
862
+ ]);
863
+ return handleRefQueryLookup;
864
+ };
865
+
866
+ // packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts
867
+ import { useEffect as useEffect5, useState as useState4 } from "react";
868
+ import { log as log2 } from "@dxos/log";
869
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts";
870
+ var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
871
+ const [options, setOptions] = useState4([]);
872
+ const [loading, setLoading] = useState4(false);
873
+ useEffect5(() => {
874
+ if (!refTypeInfo || !onQueryRefOptions) {
875
+ return;
876
+ }
877
+ const fetchOptions = async () => {
878
+ setLoading(true);
879
+ try {
880
+ const fetchedOptions = await onQueryRefOptions(refTypeInfo);
881
+ setOptions(fetchedOptions.map((option) => {
882
+ const dxn = option.dxn.toString();
883
+ return {
884
+ id: dxn,
885
+ label: option.label ?? dxn,
886
+ hue: "neutral"
887
+ };
888
+ }));
889
+ } catch (error) {
890
+ log2.error("Failed to fetch ref options:", error, {
891
+ F: __dxlog_file2,
892
+ L: 42,
893
+ S: void 0,
894
+ C: (f, a) => f(...a)
895
+ });
896
+ setOptions([]);
897
+ } finally {
898
+ setLoading(false);
899
+ }
900
+ };
901
+ void fetchOptions();
902
+ }, [
903
+ refTypeInfo,
904
+ onQueryRefOptions
905
+ ]);
906
+ return {
907
+ options,
908
+ loading
909
+ };
910
+ };
911
+
832
912
  // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
833
913
  var FormContext = /* @__PURE__ */ createContext(void 0);
834
914
  var useFormContext = () => {
@@ -859,7 +939,7 @@ var useInputProps = (path = []) => {
859
939
  };
860
940
  var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
861
941
  const form = useForm(formOptions);
862
- useEffect5(() => {
942
+ useEffect6(() => {
863
943
  if (!formRef?.current) {
864
944
  return;
865
945
  }
@@ -867,7 +947,7 @@ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
867
947
  const keyIsEnter = event.key === "Enter";
868
948
  const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
869
949
  const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
870
- const inputOptOut = event.target.hasAttribute("data-no-submit");
950
+ const inputOptOut = event.target.hasAttribute("data-no-submit") || event.target.closest("[data-no-submit]") !== null;
871
951
  const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
872
952
  const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
873
953
  if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
@@ -920,182 +1000,619 @@ var FormActions = ({ onCancel, readonly }) => {
920
1000
  };
921
1001
 
922
1002
  // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
923
- import { pipe as pipe2 } from "effect";
1003
+ import { Schema, SchemaAST as SchemaAST4, pipe as pipe2 } from "effect";
924
1004
  import { capitalize as capitalize2 } from "effect/String";
925
- import React11, { useMemo as useMemo5 } from "react";
926
- import { AST as AST3, S } from "@dxos/echo-schema";
927
- import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
1005
+ import React12, { useMemo as useMemo5 } from "react";
1006
+ import { createJsonPath as createJsonPath3, findNode as findNode3, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
928
1007
  import { mx as mx7 } from "@dxos/react-ui-theme";
929
1008
  import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
930
1009
  import { isNotFalsy } from "@dxos/util";
931
1010
 
932
1011
  // packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
933
- import { pipe } from "effect";
1012
+ import { SchemaAST as SchemaAST3, pipe } from "effect";
934
1013
  import { capitalize } from "effect/String";
935
- import React10, { useCallback as useCallback5, useMemo as useMemo4 } from "react";
936
- import { AST as AST2 } from "@dxos/echo-schema";
937
- import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
1014
+ import React10, { useCallback as useCallback6 } from "react";
1015
+ import { findNode as findNode2, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
938
1016
  import { invariant as invariant2 } from "@dxos/invariant";
939
1017
  import { IconButton as IconButton3, useTranslation as useTranslation5 } from "@dxos/react-ui";
940
1018
  import { mx as mx6 } from "@dxos/react-ui-theme";
941
1019
  import { getSchemaProperties } from "@dxos/schema";
942
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
943
- var padding = "px-2";
944
- var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
945
- const { t } = useTranslation5(translationKey);
946
- const { ast, name, type, title } = property;
947
- const values = useFormValues(path ?? []);
948
- invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
949
- F: __dxlog_file2,
950
- L: 37,
951
- S: void 0,
952
- A: [
953
- "Array.isArray(values)",
954
- "`Values at path ${path?.join('.')} must be an array.`"
955
- ]
956
- });
957
- const label = title ?? pipe(name, capitalize);
958
- const tupleType = findNode(ast, AST2.isTupleType);
959
- const elementType = tupleType?.rest[0]?.type;
960
- const getDefaultObjectValue = (typeNode) => {
961
- const baseNode = findNode(typeNode, isDiscriminatedUnion);
962
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode(typeNode, AST2.isTypeLiteral);
963
- if (!typeLiteral) {
964
- return {};
1020
+
1021
+ // packages/ui/react-ui-form/src/util/field.ts
1022
+ import { FormatEnum, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
1023
+ var parseValue = ({ type, format, value }) => {
1024
+ if (value === void 0 || value === null || value === "") {
1025
+ return void 0;
1026
+ }
1027
+ const parseScalar = (type2) => {
1028
+ switch (type2) {
1029
+ case TypeEnum.Boolean: {
1030
+ if (typeof value === "string") {
1031
+ const lowercaseValue = value.toLowerCase();
1032
+ if (lowercaseValue === "0" || lowercaseValue === "false") {
1033
+ return false;
1034
+ } else if (lowercaseValue === "1" || lowercaseValue === "true") {
1035
+ return true;
1036
+ }
1037
+ }
1038
+ return Boolean(value);
1039
+ }
1040
+ case TypeEnum.Number: {
1041
+ const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1042
+ const num = Number(cleaned);
1043
+ return Number.isNaN(num) ? null : num;
1044
+ }
1045
+ case TypeEnum.String:
1046
+ case TypeEnum.Ref:
1047
+ return String(value);
1048
+ default: {
1049
+ return value;
1050
+ }
965
1051
  }
966
- return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
967
- prop.name,
968
- prop.defaultValue
969
- ]));
970
1052
  };
971
- const newValue = useMemo4(() => {
972
- if (type === "object" && elementType) {
973
- return getDefaultObjectValue(elementType);
974
- } else {
975
- return SimpleType.getDefaultValue(type);
1053
+ if (!format) {
1054
+ return parseScalar(type);
1055
+ }
1056
+ switch (format) {
1057
+ case FormatEnum.Boolean:
1058
+ return parseScalar(TypeEnum.Boolean);
1059
+ case FormatEnum.Number:
1060
+ case FormatEnum.Percent:
1061
+ case FormatEnum.Currency:
1062
+ return parseScalar(TypeEnum.Number);
1063
+ case FormatEnum.String:
1064
+ case FormatEnum.Markdown: {
1065
+ return parseScalar(TypeEnum.String);
1066
+ }
1067
+ case FormatEnum.Ref:
1068
+ throw new Error(`unexpected format: ${FormatEnum.Ref}`);
1069
+ case FormatEnum.DateTime:
1070
+ case FormatEnum.Date:
1071
+ case FormatEnum.Time:
1072
+ case FormatEnum.Timestamp: {
1073
+ const date = new Date(value);
1074
+ return isNaN(date.getTime()) ? null : date;
1075
+ }
1076
+ case FormatEnum.GeoPoint: {
1077
+ if (typeof value === "string") {
1078
+ const cleaned = value.replace(/[^0-9.,-]+/g, "");
1079
+ const parts = cleaned.split(",");
1080
+ if (parts.length === 2) {
1081
+ const lat = parseFloat(parts[0]);
1082
+ const long = parseFloat(parts[1]);
1083
+ if (!isNaN(lat) && !isNaN(long)) {
1084
+ return GeoLocation2.toGeoPoint({
1085
+ latitude: lat,
1086
+ longitude: long
1087
+ });
1088
+ }
1089
+ }
1090
+ }
1091
+ return [
1092
+ 0,
1093
+ 0
1094
+ ];
1095
+ }
1096
+ default: {
1097
+ return value;
976
1098
  }
977
- }, [
978
- type,
979
- elementType
980
- ]);
981
- const handleAdd = useCallback5(() => {
982
- inputProps.onValueChange(type, [
983
- ...values,
984
- newValue
985
- ]);
986
- }, [
987
- type,
988
- elementType,
989
- inputProps,
990
- newValue,
991
- values
992
- ]);
993
- const handleRemove = useCallback5((index) => {
994
- const newValues = values.filter((_, i) => i !== index);
995
- inputProps.onValueChange(type, newValues);
996
- }, [
997
- type,
998
- inputProps,
999
- values
1000
- ]);
1001
- if (!elementType) {
1002
- return null;
1003
1099
  }
1004
- return /* @__PURE__ */ React10.createElement("div", {
1005
- role: "none",
1006
- className: mx6(padding)
1007
- }, /* @__PURE__ */ React10.createElement(InputHeader, null, label), /* @__PURE__ */ React10.createElement("div", {
1008
- role: "none",
1009
- className: "flex flex-col gap-1"
1010
- }, values.map((_value, index) => /* @__PURE__ */ React10.createElement("div", {
1011
- key: index,
1012
- role: "none",
1013
- className: "flex items-center gap-1"
1014
- }, /* @__PURE__ */ React10.createElement("div", {
1015
- role: "none",
1016
- className: "flex-1"
1017
- }, /* @__PURE__ */ React10.createElement(FormField, {
1018
- property: {
1019
- ...property,
1020
- array: false,
1021
- ast: elementType
1022
- },
1023
- path: [
1024
- ...path ?? [],
1025
- index
1026
- ],
1027
- readonly,
1028
- inline: true,
1029
- Custom,
1030
- lookupComponent
1031
- })), /* @__PURE__ */ React10.createElement(IconButton3, {
1032
- icon: "ph--trash--regular",
1033
- iconOnly: true,
1034
- label: t("button remove"),
1035
- onClick: () => handleRemove(index)
1036
- })))), /* @__PURE__ */ React10.createElement("div", {
1037
- role: "none",
1038
- className: "flex justify-between items-center plb-1"
1039
- }, /* @__PURE__ */ React10.createElement(IconButton3, {
1040
- icon: "ph--plus--regular",
1041
- iconOnly: true,
1042
- label: t("button add"),
1043
- onClick: handleAdd
1044
- })));
1045
1100
  };
1046
-
1047
- // packages/ui/react-ui-form/src/components/Form/factory.tsx
1048
- import { FormatEnum } from "@dxos/echo-schema";
1049
- var getInputComponent = (type, format) => {
1101
+ var cellClassesForFieldType = ({ type, format }) => {
1102
+ if (!format) {
1103
+ switch (type) {
1104
+ case TypeEnum.Number:
1105
+ return [
1106
+ "text-right",
1107
+ "font-mono"
1108
+ ];
1109
+ case TypeEnum.Boolean:
1110
+ return [
1111
+ "text-right",
1112
+ "font-mono"
1113
+ ];
1114
+ case TypeEnum.String:
1115
+ return void 0;
1116
+ case TypeEnum.Ref:
1117
+ return void 0;
1118
+ default: {
1119
+ return void 0;
1120
+ }
1121
+ }
1122
+ }
1050
1123
  switch (format) {
1051
- case FormatEnum.GeoPoint:
1052
- return GeoPointInput;
1053
1124
  case FormatEnum.Markdown:
1054
- return MarkdownInput;
1055
- }
1056
- switch (type) {
1057
- case "string":
1058
- return TextInput;
1059
- case "number":
1060
- return NumberInput;
1061
- case "boolean":
1062
- return BooleanInput;
1125
+ return void 0;
1126
+ case FormatEnum.Time:
1127
+ case FormatEnum.Timestamp:
1128
+ case FormatEnum.DateTime:
1129
+ case FormatEnum.Date:
1130
+ case FormatEnum.Duration:
1131
+ return [
1132
+ "font-mono",
1133
+ "text-right"
1134
+ ];
1135
+ case FormatEnum.Currency:
1136
+ return [
1137
+ "text-right"
1138
+ ];
1139
+ case FormatEnum.JSON:
1140
+ case FormatEnum.DID:
1141
+ return [
1142
+ "font-mono"
1143
+ ];
1144
+ default:
1145
+ return void 0;
1063
1146
  }
1064
1147
  };
1148
+ var pathNotUniqueError = (path) => ({
1149
+ path: "path",
1150
+ message: `'${path}' is already present`
1151
+ });
1065
1152
 
1066
- // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
1067
- var FormField = ({ property, path, readonly, inline, lookupComponent, Custom }) => {
1068
- const inputProps = useInputProps(path);
1069
- const { ast, name, type, format, title, description, options, examples, array } = property;
1070
- const label = useMemo5(() => title ?? pipe2(name, capitalize2), [
1071
- title,
1072
- name
1073
- ]);
1074
- const placeholder = useMemo5(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1075
- examples,
1076
- description
1077
- ]);
1078
- const FoundComponent = lookupComponent?.({
1079
- prop: name,
1080
- schema: S.make(ast),
1081
- inputProps: {
1082
- type,
1083
- format,
1084
- label,
1085
- disabled: readonly,
1086
- placeholder,
1087
- ...inputProps
1088
- }
1089
- });
1090
- if (FoundComponent) {
1091
- return /* @__PURE__ */ React11.createElement("div", {
1092
- role: "none"
1093
- }, FoundComponent);
1094
- }
1095
- const jsonPath = createJsonPath3(path ?? []);
1153
+ // packages/ui/react-ui-form/src/util/formatting.ts
1154
+ import { format as formatDate } from "date-fns/format";
1155
+ import { FormatEnum as FormatEnum2, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1156
+ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1157
+ const formatScalar = (type2) => {
1158
+ switch (type2) {
1159
+ case TypeEnum2.Boolean:
1160
+ return value.toLocaleString().toUpperCase();
1161
+ case TypeEnum2.Number:
1162
+ return value.toLocaleString(locale);
1163
+ case TypeEnum2.String:
1164
+ case TypeEnum2.Ref:
1165
+ return String(value);
1166
+ default: {
1167
+ return String(value);
1168
+ }
1169
+ }
1170
+ };
1171
+ if (!format) {
1172
+ return formatScalar(type);
1173
+ }
1174
+ switch (format) {
1175
+ case FormatEnum2.Boolean: {
1176
+ return formatScalar(TypeEnum2.Boolean);
1177
+ }
1178
+ case FormatEnum2.Number: {
1179
+ return formatScalar(TypeEnum2.Number);
1180
+ }
1181
+ case FormatEnum2.String:
1182
+ case FormatEnum2.Ref: {
1183
+ return formatScalar(TypeEnum2.String);
1184
+ }
1185
+ case FormatEnum2.Percent: {
1186
+ return `${value * 100}%`;
1187
+ }
1188
+ case FormatEnum2.Currency: {
1189
+ return value.toLocaleString(locale, {
1190
+ style: "currency",
1191
+ currency: "USD",
1192
+ minimumFractionDigits: 2,
1193
+ maximumFractionDigits: 2
1194
+ });
1195
+ }
1196
+ case FormatEnum2.Date: {
1197
+ try {
1198
+ return formatDate(new Date(value), "yyyy-MM-dd");
1199
+ } catch (error) {
1200
+ return "Invalid Date";
1201
+ }
1202
+ }
1203
+ case FormatEnum2.Time: {
1204
+ try {
1205
+ return formatDate(new Date(value), "HH:mm:ss");
1206
+ } catch (error) {
1207
+ return "Invalid Time";
1208
+ }
1209
+ }
1210
+ case FormatEnum2.DateTime: {
1211
+ try {
1212
+ return formatDate(new Date(value), "yyyy-MM-dd HH:mm:ss");
1213
+ } catch (error) {
1214
+ return "Invalid DateTime";
1215
+ }
1216
+ }
1217
+ case FormatEnum2.GeoPoint: {
1218
+ if (value === null || value === void 0) {
1219
+ return "";
1220
+ }
1221
+ if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1222
+ const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1223
+ return `${latitude},${longitude}`;
1224
+ }
1225
+ return String(value);
1226
+ }
1227
+ default: {
1228
+ if (value === null || value === "undefined") {
1229
+ return "";
1230
+ }
1231
+ return String(value);
1232
+ }
1233
+ }
1234
+ };
1235
+ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1236
+ const formatScalar = (type2) => {
1237
+ switch (type2) {
1238
+ case TypeEnum2.Boolean:
1239
+ case TypeEnum2.Number:
1240
+ case TypeEnum2.String:
1241
+ case TypeEnum2.Ref:
1242
+ return String(value);
1243
+ default:
1244
+ return String(value);
1245
+ }
1246
+ };
1247
+ if (!format) {
1248
+ return formatScalar(type);
1249
+ }
1250
+ switch (format) {
1251
+ case FormatEnum2.Boolean:
1252
+ case FormatEnum2.Number:
1253
+ case FormatEnum2.String:
1254
+ case FormatEnum2.Ref: {
1255
+ return formatScalar(type);
1256
+ }
1257
+ case FormatEnum2.Percent: {
1258
+ return String(value * 100);
1259
+ }
1260
+ case FormatEnum2.Currency: {
1261
+ return String(value);
1262
+ }
1263
+ case FormatEnum2.DateTime: {
1264
+ const date = new Date(value);
1265
+ return date.toISOString();
1266
+ }
1267
+ case FormatEnum2.Date: {
1268
+ const date = new Date(value);
1269
+ return date.toISOString().split("T")[0];
1270
+ }
1271
+ case FormatEnum2.Time: {
1272
+ const date = new Date(value);
1273
+ return date.toISOString().split("T")[1].split(".")[0];
1274
+ }
1275
+ case FormatEnum2.GeoPoint: {
1276
+ if (value === null || value === void 0) {
1277
+ return "";
1278
+ }
1279
+ if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1280
+ const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1281
+ return `${latitude},${longitude}`;
1282
+ }
1283
+ return String(value);
1284
+ }
1285
+ default: {
1286
+ return String(value);
1287
+ }
1288
+ }
1289
+ };
1290
+
1291
+ // packages/ui/react-ui-form/src/util/refs.ts
1292
+ import { FormatEnum as FormatEnum3, ReferenceAnnotationId } from "@dxos/echo-schema";
1293
+ import { findAnnotation } from "@dxos/effect";
1294
+
1295
+ // packages/ui/react-ui-form/src/util/schema.ts
1296
+ import { SchemaAST as SchemaAST2 } from "effect";
1297
+ import { findNode } from "@dxos/effect";
1298
+ var findArrayElementType = (ast) => {
1299
+ const tupleType = findNode(ast, SchemaAST2.isTupleType);
1300
+ const elementType = tupleType?.rest[0]?.type;
1301
+ return elementType;
1302
+ };
1303
+
1304
+ // packages/ui/react-ui-form/src/util/refs.ts
1305
+ var getRefProps = (property) => {
1306
+ const { ast, format, array } = property;
1307
+ if (format === FormatEnum3.Ref) {
1308
+ return {
1309
+ ast,
1310
+ isArray: false
1311
+ };
1312
+ }
1313
+ if (array) {
1314
+ const elementType = findArrayElementType(ast);
1315
+ if (elementType) {
1316
+ const annotation = findAnnotation(elementType, ReferenceAnnotationId);
1317
+ if (annotation) {
1318
+ return {
1319
+ ast: elementType,
1320
+ isArray: true
1321
+ };
1322
+ }
1323
+ }
1324
+ }
1325
+ return void 0;
1326
+ };
1327
+
1328
+ // packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
1329
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
1330
+ var padding = "px-2";
1331
+ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
1332
+ const { t } = useTranslation5(translationKey);
1333
+ const { ast, name, type, title } = property;
1334
+ const values = useFormValues(path ?? []) ?? [];
1335
+ invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
1336
+ F: __dxlog_file3,
1337
+ L: 39,
1338
+ S: void 0,
1339
+ A: [
1340
+ "Array.isArray(values)",
1341
+ "`Values at path ${path?.join('.')} must be an array.`"
1342
+ ]
1343
+ });
1344
+ const label = title ?? pipe(name, capitalize);
1345
+ const elementType = findArrayElementType(ast);
1346
+ const getDefaultObjectValue = (typeNode) => {
1347
+ const baseNode = findNode2(typeNode, isDiscriminatedUnion);
1348
+ const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode2(typeNode, SchemaAST3.isTypeLiteral);
1349
+ if (!typeLiteral) {
1350
+ return {};
1351
+ }
1352
+ return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
1353
+ prop.name,
1354
+ prop.defaultValue
1355
+ ]));
1356
+ };
1357
+ const getDefaultValue = () => type === "object" && elementType ? getDefaultObjectValue(elementType) : SimpleType.getDefaultValue(type);
1358
+ const handleAdd = useCallback6(() => {
1359
+ inputProps.onValueChange(type, [
1360
+ ...values,
1361
+ getDefaultValue()
1362
+ ]);
1363
+ }, [
1364
+ type,
1365
+ elementType,
1366
+ inputProps,
1367
+ values
1368
+ ]);
1369
+ const handleRemove = useCallback6((index) => {
1370
+ const newValues = values.filter((_, i) => i !== index);
1371
+ inputProps.onValueChange(type, newValues);
1372
+ }, [
1373
+ type,
1374
+ inputProps,
1375
+ values
1376
+ ]);
1377
+ if (!elementType) {
1378
+ return null;
1379
+ }
1380
+ return /* @__PURE__ */ React10.createElement("div", {
1381
+ role: "none",
1382
+ className: mx6(padding)
1383
+ }, /* @__PURE__ */ React10.createElement(InputHeader, null, label), /* @__PURE__ */ React10.createElement("div", {
1384
+ role: "none",
1385
+ className: "flex flex-col gap-1"
1386
+ }, values.map((_value, index) => /* @__PURE__ */ React10.createElement("div", {
1387
+ key: index,
1388
+ role: "none",
1389
+ className: "flex items-center gap-1"
1390
+ }, /* @__PURE__ */ React10.createElement("div", {
1391
+ role: "none",
1392
+ className: "flex-1"
1393
+ }, /* @__PURE__ */ React10.createElement(FormField, {
1394
+ property: {
1395
+ ...property,
1396
+ array: false,
1397
+ ast: elementType
1398
+ },
1399
+ path: [
1400
+ ...path ?? [],
1401
+ index
1402
+ ],
1403
+ readonly,
1404
+ inline: true,
1405
+ Custom,
1406
+ lookupComponent
1407
+ })), /* @__PURE__ */ React10.createElement(IconButton3, {
1408
+ icon: "ph--trash--regular",
1409
+ iconOnly: true,
1410
+ label: t("button remove"),
1411
+ onClick: () => handleRemove(index)
1412
+ })))), /* @__PURE__ */ React10.createElement("div", {
1413
+ role: "none",
1414
+ className: "flex justify-between items-center plb-1"
1415
+ }, /* @__PURE__ */ React10.createElement(IconButton3, {
1416
+ icon: "ph--plus--regular",
1417
+ iconOnly: true,
1418
+ label: t("button add"),
1419
+ onClick: handleAdd
1420
+ })));
1421
+ };
1422
+
1423
+ // packages/ui/react-ui-form/src/components/Form/RefField.tsx
1424
+ import React11, { useCallback as useCallback7, useMemo as useMemo4 } from "react";
1425
+ import { Expando, getTypeAnnotation, Ref, ReferenceAnnotationId as ReferenceAnnotationId2 } from "@dxos/echo-schema";
1426
+ import { findAnnotation as findAnnotation2 } from "@dxos/effect";
1427
+ import { DXN } from "@dxos/keys";
1428
+ import { Input as Input7 } from "@dxos/react-ui";
1429
+ import { TagPicker } from "@dxos/react-ui-tag-picker";
1430
+ import { isNonNullable as isNonNullable2 } from "@dxos/util";
1431
+ var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, getValue: getValue3, onBlur, onQueryRefOptions, onValueChange, ...restInputProps }) => {
1432
+ const refTypeInfo = useMemo4(() => ast ? findAnnotation2(ast, ReferenceAnnotationId2) : void 0, [
1433
+ ast
1434
+ ]);
1435
+ const { options: availableOptions, loading: _loading } = useQueryRefOptions({
1436
+ refTypeInfo,
1437
+ onQueryRefOptions
1438
+ });
1439
+ if (refTypeInfo && refTypeInfo?.typename === getTypeAnnotation(Expando)?.typename || !onQueryRefOptions) {
1440
+ return /* @__PURE__ */ React11.createElement(RefFieldFallback, {
1441
+ type,
1442
+ label,
1443
+ placeholder,
1444
+ disabled,
1445
+ inputOnly,
1446
+ getValue: getValue3,
1447
+ onBlur,
1448
+ onValueChange,
1449
+ ...restInputProps
1450
+ });
1451
+ }
1452
+ const handleGetValue = useCallback7(() => {
1453
+ const formValue = getValue3();
1454
+ const unknownToRefOption = (val) => {
1455
+ if (Ref.isRef(val)) {
1456
+ const dxnString = val.dxn.toString();
1457
+ const matchingOption = availableOptions.find((option2) => option2.id === dxnString);
1458
+ if (matchingOption) {
1459
+ return matchingOption;
1460
+ }
1461
+ }
1462
+ return void 0;
1463
+ };
1464
+ if (array && Array.isArray(formValue)) {
1465
+ return formValue.map(unknownToRefOption).filter(isNonNullable2) ?? [];
1466
+ }
1467
+ const option = unknownToRefOption(formValue);
1468
+ if (option) {
1469
+ return [
1470
+ option
1471
+ ];
1472
+ }
1473
+ return [];
1474
+ }, [
1475
+ getValue3,
1476
+ availableOptions,
1477
+ array
1478
+ ]);
1479
+ const handleSearch = useCallback7((text, ids) => availableOptions.filter((option) => !ids.includes(option.id)).filter((option) => option.label.toLowerCase().includes(text.toLowerCase())).map((option) => ({
1480
+ id: option.id,
1481
+ label: option.label,
1482
+ hue: option.hue
1483
+ })), [
1484
+ availableOptions
1485
+ ]);
1486
+ const handleUpdate = useCallback7((ids) => {
1487
+ if (ids.length === 0) {
1488
+ onValueChange("object", void 0);
1489
+ return;
1490
+ }
1491
+ const refs = ids.map((id) => {
1492
+ const item = availableOptions.find((option) => option.id === id);
1493
+ if (item) {
1494
+ const dxn = DXN.parse(item.id);
1495
+ return Ref.fromDXN(dxn);
1496
+ }
1497
+ return null;
1498
+ }).filter(isNonNullable2);
1499
+ if (array) {
1500
+ onValueChange("object", refs);
1501
+ } else {
1502
+ onValueChange("object", refs[0]);
1503
+ }
1504
+ }, [
1505
+ availableOptions,
1506
+ array,
1507
+ onValueChange
1508
+ ]);
1509
+ const tagPickerMode = useMemo4(() => array ? "multi-select" : "single-select", [
1510
+ array
1511
+ ]);
1512
+ if (!refTypeInfo) {
1513
+ return null;
1514
+ }
1515
+ const { status, error } = restInputProps.getStatus();
1516
+ return /* @__PURE__ */ React11.createElement(Input7.Root, {
1517
+ validationValence: status
1518
+ }, !inputOnly && /* @__PURE__ */ React11.createElement(InputHeader, {
1519
+ error
1520
+ }, /* @__PURE__ */ React11.createElement(Input7.Label, null, label)), /* @__PURE__ */ React11.createElement("div", {
1521
+ "data-no-submit": true
1522
+ }, /* @__PURE__ */ React11.createElement(TagPicker, {
1523
+ items: handleGetValue(),
1524
+ mode: tagPickerMode,
1525
+ onBlur: (event) => onBlur(event),
1526
+ onUpdate: handleUpdate,
1527
+ onSearch: handleSearch,
1528
+ classNames: "rounded-sm bg-input p-1.5"
1529
+ })), inputOnly && /* @__PURE__ */ React11.createElement(Input7.DescriptionAndValidation, null, error));
1530
+ };
1531
+ var RefFieldFallback = ({ type, label, disabled, placeholder, inputOnly, getValue: getValue3, onValueChange, ...restInputProps }) => {
1532
+ const handleOnValueChange = (_type, dxnString) => {
1533
+ const dxn = DXN.tryParse(dxnString);
1534
+ if (dxn) {
1535
+ onValueChange?.("object", Ref.fromDXN(dxn));
1536
+ } else if (dxnString === "") {
1537
+ onValueChange?.("object", void 0);
1538
+ } else {
1539
+ onValueChange?.("string", dxnString);
1540
+ }
1541
+ };
1542
+ const handleGetValue = () => {
1543
+ const formValue = getValue3();
1544
+ if (typeof formValue === "string") {
1545
+ return formValue;
1546
+ }
1547
+ if (Ref.isRef(formValue)) {
1548
+ return formValue.dxn.toString();
1549
+ }
1550
+ return void 0;
1551
+ };
1552
+ return /* @__PURE__ */ React11.createElement(TextInput, {
1553
+ type,
1554
+ label,
1555
+ disabled,
1556
+ placeholder,
1557
+ inputOnly,
1558
+ getValue: handleGetValue,
1559
+ onValueChange: handleOnValueChange,
1560
+ ...restInputProps
1561
+ });
1562
+ };
1563
+
1564
+ // packages/ui/react-ui-form/src/components/Form/factory.tsx
1565
+ import { FormatEnum as FormatEnum4 } from "@dxos/echo-schema";
1566
+ var getInputComponent = (type, format) => {
1567
+ switch (format) {
1568
+ case FormatEnum4.GeoPoint:
1569
+ return GeoPointInput;
1570
+ case FormatEnum4.Markdown:
1571
+ return MarkdownInput;
1572
+ }
1573
+ switch (type) {
1574
+ case "string":
1575
+ return TextInput;
1576
+ case "number":
1577
+ return NumberInput;
1578
+ case "boolean":
1579
+ return BooleanInput;
1580
+ }
1581
+ };
1582
+
1583
+ // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
1584
+ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupComponent, Custom }) => {
1585
+ const inputProps = useInputProps(path);
1586
+ const { ast, name, type, format, title, description, options, examples, array } = property;
1587
+ const label = useMemo5(() => title ?? pipe2(name, capitalize2), [
1588
+ title,
1589
+ name
1590
+ ]);
1591
+ const placeholder = useMemo5(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1592
+ examples,
1593
+ description
1594
+ ]);
1595
+ const FoundComponent = lookupComponent?.({
1596
+ prop: name,
1597
+ schema: Schema.make(ast),
1598
+ inputProps: {
1599
+ type,
1600
+ format,
1601
+ label,
1602
+ disabled: readonly,
1603
+ placeholder,
1604
+ ...inputProps
1605
+ }
1606
+ });
1607
+ if (FoundComponent) {
1608
+ return /* @__PURE__ */ React12.createElement("div", {
1609
+ role: "none"
1610
+ }, FoundComponent);
1611
+ }
1612
+ const jsonPath = createJsonPath3(path ?? []);
1096
1613
  const CustomComponent = Custom?.[jsonPath];
1097
1614
  if (CustomComponent) {
1098
- return /* @__PURE__ */ React11.createElement(CustomComponent, {
1615
+ return /* @__PURE__ */ React12.createElement(CustomComponent, {
1099
1616
  type,
1100
1617
  format,
1101
1618
  label,
@@ -1105,8 +1622,23 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
1105
1622
  ...inputProps
1106
1623
  });
1107
1624
  }
1625
+ const refProps = getRefProps(property);
1626
+ if (refProps) {
1627
+ return /* @__PURE__ */ React12.createElement(RefField, {
1628
+ ast: refProps.ast,
1629
+ array: refProps.isArray,
1630
+ type,
1631
+ format,
1632
+ label,
1633
+ placeholder,
1634
+ disabled: readonly,
1635
+ inputOnly: inline,
1636
+ onQueryRefOptions,
1637
+ ...inputProps
1638
+ });
1639
+ }
1108
1640
  if (array) {
1109
- return /* @__PURE__ */ React11.createElement(ArrayField, {
1641
+ return /* @__PURE__ */ React12.createElement(ArrayField, {
1110
1642
  property,
1111
1643
  path,
1112
1644
  inputProps,
@@ -1116,9 +1648,9 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
1116
1648
  }
1117
1649
  const InputComponent = getInputComponent(type, format);
1118
1650
  if (InputComponent) {
1119
- return /* @__PURE__ */ React11.createElement("div", {
1651
+ return /* @__PURE__ */ React12.createElement("div", {
1120
1652
  role: "none"
1121
- }, /* @__PURE__ */ React11.createElement(InputComponent, {
1653
+ }, /* @__PURE__ */ React12.createElement(InputComponent, {
1122
1654
  type,
1123
1655
  format,
1124
1656
  label,
@@ -1129,9 +1661,9 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
1129
1661
  }));
1130
1662
  }
1131
1663
  if (options) {
1132
- return /* @__PURE__ */ React11.createElement("div", {
1664
+ return /* @__PURE__ */ React12.createElement("div", {
1133
1665
  role: "none"
1134
- }, /* @__PURE__ */ React11.createElement(SelectInput, {
1666
+ }, /* @__PURE__ */ React12.createElement(SelectInput, {
1135
1667
  type,
1136
1668
  format,
1137
1669
  disabled: readonly,
@@ -1146,22 +1678,26 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
1146
1678
  }));
1147
1679
  }
1148
1680
  if (type === "object") {
1149
- const baseNode = findNode2(ast, isDiscriminatedUnion2);
1150
- const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode2(ast, AST3.isTypeLiteral);
1681
+ const baseNode = findNode3(ast, isDiscriminatedUnion2);
1682
+ const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode3(ast, SchemaAST4.isTypeLiteral);
1151
1683
  if (typeLiteral) {
1152
- return /* @__PURE__ */ React11.createElement("div", {
1684
+ return /* @__PURE__ */ React12.createElement("div", {
1153
1685
  role: "none"
1154
- }, !inline && /* @__PURE__ */ React11.createElement("div", null, label), /* @__PURE__ */ React11.createElement(FormFields, {
1155
- schema: S.make(typeLiteral),
1686
+ }, !inline && /* @__PURE__ */ React12.createElement("h3", {
1687
+ className: "text-lg mbs-2 mbe-1"
1688
+ }, label), /* @__PURE__ */ React12.createElement(FormFields, {
1689
+ schema: Schema.make(typeLiteral),
1156
1690
  path,
1157
1691
  readonly,
1158
- Custom
1692
+ onQueryRefOptions,
1693
+ Custom,
1694
+ lookupComponent
1159
1695
  }));
1160
1696
  }
1161
1697
  }
1162
1698
  return null;
1163
1699
  };
1164
- var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custom }) => {
1700
+ var FormFields = ({ schema, path, filter, sort, readonly, onQueryRefOptions, lookupComponent, Custom }) => {
1165
1701
  const values = useFormValues(path);
1166
1702
  const properties = useMemo5(() => {
1167
1703
  const props = getSchemaProperties2(schema.ast, values);
@@ -1173,11 +1709,11 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
1173
1709
  filter,
1174
1710
  sort
1175
1711
  ]);
1176
- return /* @__PURE__ */ React11.createElement("div", {
1712
+ return /* @__PURE__ */ React12.createElement("div", {
1177
1713
  role: "form",
1178
1714
  className: mx7("flex flex-col w-full gap-2")
1179
1715
  }, properties.map((property) => {
1180
- return /* @__PURE__ */ React11.createElement(FormField, {
1716
+ return /* @__PURE__ */ React12.createElement(FormField, {
1181
1717
  key: property.name,
1182
1718
  property,
1183
1719
  path: [
@@ -1185,6 +1721,7 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
1185
1721
  property.name
1186
1722
  ],
1187
1723
  readonly,
1724
+ onQueryRefOptions,
1188
1725
  lookupComponent,
1189
1726
  Custom
1190
1727
  });
@@ -1192,13 +1729,13 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
1192
1729
  };
1193
1730
 
1194
1731
  // packages/ui/react-ui-form/src/components/Form/Form.tsx
1195
- var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
1732
+ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, onQueryRefOptions, lookupComponent, Custom }) => {
1196
1733
  const formRef = useRef3(null);
1197
1734
  const onValid = useMemo6(() => autoSave ? onSave : void 0, [
1198
1735
  autoSave,
1199
1736
  onSave
1200
1737
  ]);
1201
- useEffect6(() => {
1738
+ useEffect7(() => {
1202
1739
  if (autoFocus && formRef.current) {
1203
1740
  const input = formRef.current.querySelector("input");
1204
1741
  if (input) {
@@ -1208,7 +1745,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
1208
1745
  }, [
1209
1746
  autoFocus
1210
1747
  ]);
1211
- return /* @__PURE__ */ React12.createElement(FormProvider, {
1748
+ return /* @__PURE__ */ React13.createElement(FormProvider, {
1212
1749
  formRef,
1213
1750
  schema,
1214
1751
  autoSave,
@@ -1217,36 +1754,37 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
1217
1754
  onValidate,
1218
1755
  onValid,
1219
1756
  onSave
1220
- }, /* @__PURE__ */ React12.createElement("div", {
1757
+ }, /* @__PURE__ */ React13.createElement("div", {
1221
1758
  ref: formRef,
1222
1759
  role: "none",
1223
1760
  className: mx8("p-2", classNames),
1224
1761
  "data-testid": testId
1225
- }, /* @__PURE__ */ React12.createElement(FormFields, {
1762
+ }, /* @__PURE__ */ React13.createElement(FormFields, {
1226
1763
  schema,
1227
1764
  path,
1228
1765
  readonly,
1229
1766
  filter,
1230
1767
  sort,
1768
+ onQueryRefOptions,
1231
1769
  lookupComponent,
1232
1770
  Custom
1233
- }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React12.createElement(FormActions, {
1771
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React13.createElement(FormActions, {
1234
1772
  onCancel,
1235
1773
  readonly
1236
1774
  })));
1237
1775
  };
1238
1776
 
1239
1777
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
1240
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
1778
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
1241
1779
  var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1242
1780
  const { t } = useTranslation6(translationKey);
1243
- const [props, setProps] = useState4(projection.getFieldProjection(field.id).props);
1244
- useEffect7(() => setProps(projection.getFieldProjection(field.id).props), [
1781
+ const [props, setProps] = useState5(projection.getFieldProjection(field.id).props);
1782
+ useEffect8(() => setProps(projection.getFieldProjection(field.id).props), [
1245
1783
  field,
1246
1784
  projection
1247
1785
  ]);
1248
- const [schemas, setSchemas] = useState4([]);
1249
- useEffect7(() => {
1786
+ const [schemas, setSchemas] = useState5([]);
1787
+ useEffect8(() => {
1250
1788
  if (!registry) {
1251
1789
  return;
1252
1790
  }
@@ -1264,17 +1802,17 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1264
1802
  }, [
1265
1803
  registry
1266
1804
  ]);
1267
- const [referenceSchema, setReferenceSchema] = useState4();
1268
- useEffect7(() => {
1805
+ const [referenceSchema, setReferenceSchema] = useState5();
1806
+ useEffect8(() => {
1269
1807
  setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
1270
1808
  }, [
1271
1809
  schemas,
1272
1810
  props?.referenceSchema
1273
1811
  ]);
1274
- const [{ fieldSchema }, setFieldSchema] = useState4({
1812
+ const [{ fieldSchema }, setFieldSchema] = useState5({
1275
1813
  fieldSchema: getFormatSchema(props?.format)
1276
1814
  });
1277
- const handleValuesChanged = useCallback6((_props) => {
1815
+ const handleValuesChanged = useCallback8((_props) => {
1278
1816
  setFieldSchema((prev) => {
1279
1817
  const fieldSchema2 = getFormatSchema(_props.format);
1280
1818
  if (prev.fieldSchema === fieldSchema2) {
@@ -1309,7 +1847,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1309
1847
  props.format,
1310
1848
  props.referenceSchema
1311
1849
  ]);
1312
- const handleValidate = useCallback6(({ property }) => {
1850
+ const handleValidate = useCallback8(({ property }) => {
1313
1851
  if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
1314
1852
  return [
1315
1853
  {
@@ -1322,7 +1860,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1322
1860
  view.fields,
1323
1861
  field
1324
1862
  ]);
1325
- const handleSave = useCallback6((props2) => {
1863
+ const handleSave = useCallback8((props2) => {
1326
1864
  projection.setFieldProjection({
1327
1865
  field,
1328
1866
  props: props2
@@ -1333,51 +1871,51 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1333
1871
  field,
1334
1872
  onSave
1335
1873
  ]);
1336
- const handleCancel = useCallback6(() => {
1874
+ const handleCancel = useCallback8(() => {
1337
1875
  requestAnimationFrame(() => onCancel?.());
1338
1876
  onSave();
1339
1877
  }, [
1340
1878
  onSave
1341
1879
  ]);
1342
1880
  const Custom = useMemo7(() => ({
1343
- ["format"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
1881
+ ["format"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
1344
1882
  ...props2,
1345
- options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
1883
+ options: FormatEnums.filter((value) => value !== FormatEnum5.None).map((value) => ({
1346
1884
  value,
1347
1885
  label: t(`format ${value}`)
1348
1886
  }))
1349
1887
  }),
1350
- ["referenceSchema"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
1888
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
1351
1889
  ...props2,
1352
1890
  options: schemas.map((schema) => ({
1353
1891
  value: schema.typename
1354
1892
  }))
1355
1893
  }),
1356
- ["referencePath"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
1894
+ ["referencePath"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
1357
1895
  ...props2,
1358
1896
  options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
1359
1897
  value: p.name
1360
1898
  })) : []
1361
1899
  }),
1362
- ["options"]: (props2) => /* @__PURE__ */ React13.createElement(SelectOptionInput, props2)
1900
+ ["options"]: (props2) => /* @__PURE__ */ React14.createElement(SelectOptionInput, props2)
1363
1901
  }), [
1364
1902
  t,
1365
1903
  schemas,
1366
1904
  referenceSchema
1367
1905
  ]);
1368
- const propIsNotType = useCallback6((props2) => props2.filter((p) => p.name !== "type"), []);
1906
+ const propIsNotType = useCallback8((props2) => props2.filter((p) => p.name !== "type"), []);
1369
1907
  if (!fieldSchema) {
1370
- log2.warn("invalid format", {
1908
+ log3.warn("invalid format", {
1371
1909
  props
1372
1910
  }, {
1373
- F: __dxlog_file3,
1911
+ F: __dxlog_file4,
1374
1912
  L: 174,
1375
1913
  S: void 0,
1376
1914
  C: (f, a) => f(...a)
1377
1915
  });
1378
1916
  return null;
1379
1917
  }
1380
- return /* @__PURE__ */ React13.createElement(Form, {
1918
+ return /* @__PURE__ */ React14.createElement(Form, {
1381
1919
  key: field.id,
1382
1920
  autoFocus: true,
1383
1921
  values: props,
@@ -1396,30 +1934,32 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1396
1934
  };
1397
1935
 
1398
1936
  // packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
1399
- import React14, { useCallback as useCallback7, useMemo as useMemo8, useState as useState5 } from "react";
1400
- import { AST as AST4, Format, S as S2 } from "@dxos/echo-schema";
1937
+ import { Schema as Schema2, SchemaAST as SchemaAST5 } from "effect";
1938
+ import React15, { useCallback as useCallback9, useMemo as useMemo8, useState as useState6 } from "react";
1939
+ import { Format, isMutable, toJsonSchema } from "@dxos/echo-schema";
1401
1940
  import { invariant as invariant3 } from "@dxos/invariant";
1402
1941
  import { IconButton as IconButton4, useTranslation as useTranslation7 } from "@dxos/react-ui";
1403
1942
  import { List as List2 } from "@dxos/react-ui-list";
1404
1943
  import { ghostHover, inputTextLabel, mx as mx9 } from "@dxos/react-ui-theme";
1405
1944
  import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
1406
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
1945
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
1407
1946
  var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
1408
- var ViewMetaSchema = S2.Struct({
1409
- name: S2.String.annotations({
1410
- [AST4.TitleAnnotationId]: "View"
1947
+ var ViewMetaSchema = Schema2.Struct({
1948
+ name: Schema2.String.annotations({
1949
+ [SchemaAST5.TitleAnnotationId]: "View"
1411
1950
  }),
1412
1951
  typename: Format.URL.annotations({
1413
- [AST4.TitleAnnotationId]: "Typename"
1952
+ [SchemaAST5.TitleAnnotationId]: "Typename"
1414
1953
  })
1415
- }).pipe(S2.mutable);
1954
+ }).pipe(Schema2.mutable);
1416
1955
  var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
1417
1956
  const { t } = useTranslation7(translationKey);
1418
- const projection = useMemo8(() => new ViewProjection(schema.jsonSchema, view), [
1957
+ const projection = useMemo8(() => new ViewProjection(toJsonSchema(schema), view), [
1419
1958
  schema,
1420
1959
  view
1421
1960
  ]);
1422
- const [field, setField] = useState5();
1961
+ const [field, setField] = useState6();
1962
+ const immutable = readonly || !isMutable(schema);
1423
1963
  const viewValues = useMemo8(() => {
1424
1964
  return {
1425
1965
  name: view.name,
@@ -1430,16 +1970,16 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1430
1970
  }, [
1431
1971
  view
1432
1972
  ]);
1433
- const handleSelect = useCallback7((field2) => {
1973
+ const handleSelect = useCallback9((field2) => {
1434
1974
  setField((f) => f === field2 ? void 0 : field2);
1435
1975
  }, []);
1436
- const handleAdd = useCallback7(() => {
1437
- invariant3(!schema.readonly, void 0, {
1438
- F: __dxlog_file4,
1439
- L: 76,
1976
+ const handleAdd = useCallback9(() => {
1977
+ invariant3(!immutable, void 0, {
1978
+ F: __dxlog_file5,
1979
+ L: 78,
1440
1980
  S: void 0,
1441
1981
  A: [
1442
- "!schema.readonly",
1982
+ "!immutable",
1443
1983
  ""
1444
1984
  ]
1445
1985
  });
@@ -1449,13 +1989,13 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1449
1989
  schema,
1450
1990
  view
1451
1991
  ]);
1452
- const handleUpdate = useCallback7(({ name, typename }) => {
1453
- invariant3(!schema.readonly, void 0, {
1454
- F: __dxlog_file4,
1455
- L: 83,
1992
+ const handleUpdate = useCallback9(({ name, typename }) => {
1993
+ invariant3(!immutable, void 0, {
1994
+ F: __dxlog_file5,
1995
+ L: 85,
1456
1996
  S: void 0,
1457
1997
  A: [
1458
- "!schema.readonly",
1998
+ "!immutable",
1459
1999
  ""
1460
2000
  ]
1461
2001
  });
@@ -1472,13 +2012,13 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1472
2012
  view,
1473
2013
  onTypenameChanged
1474
2014
  ]);
1475
- const handleDelete = useCallback7((fieldId) => {
1476
- invariant3(!schema.readonly, void 0, {
1477
- F: __dxlog_file4,
1478
- L: 99,
2015
+ const handleDelete = useCallback9((fieldId) => {
2016
+ invariant3(!immutable, void 0, {
2017
+ F: __dxlog_file5,
2018
+ L: 101,
1479
2019
  S: void 0,
1480
2020
  A: [
1481
- "!schema.readonly",
2021
+ "!immutable",
1482
2022
  ""
1483
2023
  ]
1484
2024
  });
@@ -1491,13 +2031,13 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1491
2031
  field,
1492
2032
  onDelete
1493
2033
  ]);
1494
- const handleMove = useCallback7((fromIndex, toIndex) => {
1495
- invariant3(!schema.readonly, void 0, {
1496
- F: __dxlog_file4,
1497
- L: 111,
2034
+ const handleMove = useCallback9((fromIndex, toIndex) => {
2035
+ invariant3(!immutable, void 0, {
2036
+ F: __dxlog_file5,
2037
+ L: 113,
1498
2038
  S: void 0,
1499
2039
  A: [
1500
- "!schema.readonly",
2040
+ "!immutable",
1501
2041
  ""
1502
2042
  ]
1503
2043
  });
@@ -1511,356 +2051,102 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1511
2051
  schema,
1512
2052
  view.fields
1513
2053
  ]);
1514
- const handleClose = useCallback7(() => setField(void 0), []);
2054
+ const handleClose = useCallback9(() => setField(void 0), []);
1515
2055
  const hiddenProperties = projection.getHiddenProperties();
1516
- const handleHide = useCallback7((fieldId) => {
2056
+ const handleHide = useCallback9((fieldId) => {
1517
2057
  setField(void 0);
1518
2058
  projection.hideFieldProjection(fieldId);
1519
2059
  }, [
1520
2060
  projection
1521
2061
  ]);
1522
- const handleShow = useCallback7((property) => {
2062
+ const handleShow = useCallback9((property) => {
1523
2063
  setField(void 0);
1524
2064
  projection.showFieldProjection(property);
1525
2065
  }, [
1526
2066
  projection
1527
2067
  ]);
1528
- return /* @__PURE__ */ React14.createElement("div", {
2068
+ return /* @__PURE__ */ React15.createElement("div", {
1529
2069
  role: "none",
1530
- className: mx9("flex flex-col w-full divide-y divide-separator", classNames)
1531
- }, /* @__PURE__ */ React14.createElement(Form, {
2070
+ className: mx9("grid grid-rows-[1fr_1fr] min-bs-0", classNames)
2071
+ }, /* @__PURE__ */ React15.createElement(Form, {
1532
2072
  autoSave: true,
1533
2073
  schema: ViewMetaSchema,
1534
2074
  values: viewValues,
1535
- onSave: schema.readonly ? void 0 : handleUpdate
1536
- }), /* @__PURE__ */ React14.createElement("div", null, /* @__PURE__ */ React14.createElement("div", {
2075
+ onSave: immutable ? void 0 : handleUpdate,
2076
+ classNames: "min-bs-0 overflow-y-auto"
2077
+ }), /* @__PURE__ */ React15.createElement("div", {
2078
+ role: "none",
2079
+ className: "border-bs border-separator min-bs-0 overflow-y-auto"
2080
+ }, /* @__PURE__ */ React15.createElement("div", {
1537
2081
  role: "none",
1538
2082
  className: "p-2"
1539
- }, /* @__PURE__ */ React14.createElement("label", {
2083
+ }, /* @__PURE__ */ React15.createElement("label", {
1540
2084
  className: mx9(inputTextLabel)
1541
- }, t("fields label"))), /* @__PURE__ */ React14.createElement(List2.Root, {
2085
+ }, t("fields label"))), /* @__PURE__ */ React15.createElement(List2.Root, {
1542
2086
  items: view.fields,
1543
- isItem: S2.is(FieldSchema),
2087
+ isItem: Schema2.is(FieldSchema),
1544
2088
  getId: (field2) => field2.id,
1545
- onMove: schema.readonly ? void 0 : handleMove
1546
- }, ({ items: fields }) => /* @__PURE__ */ React14.createElement(React14.Fragment, null, showHeading && /* @__PURE__ */ React14.createElement("div", {
2089
+ onMove: immutable ? void 0 : handleMove
2090
+ }, ({ items: fields }) => /* @__PURE__ */ React15.createElement(React15.Fragment, null, showHeading && /* @__PURE__ */ React15.createElement("div", {
1547
2091
  role: "heading",
1548
2092
  className: grid
1549
- }, /* @__PURE__ */ React14.createElement("div", null), /* @__PURE__ */ React14.createElement("div", {
2093
+ }, /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement("div", {
1550
2094
  className: "flex items-center text-sm"
1551
- }, t("field path label"))), /* @__PURE__ */ React14.createElement("div", {
2095
+ }, t("field path label"))), /* @__PURE__ */ React15.createElement("div", {
1552
2096
  role: "list",
1553
2097
  className: "flex flex-col w-full"
1554
- }, fields?.map((field2) => /* @__PURE__ */ React14.createElement(List2.Item, {
2098
+ }, fields?.map((field2) => /* @__PURE__ */ React15.createElement(List2.Item, {
1555
2099
  key: field2.id,
1556
2100
  item: field2,
1557
2101
  classNames: mx9(grid, ghostHover, "cursor-pointer")
1558
- }, /* @__PURE__ */ React14.createElement(List2.ItemDragHandle, null), /* @__PURE__ */ React14.createElement(List2.ItemTitle, {
2102
+ }, /* @__PURE__ */ React15.createElement(List2.ItemDragHandle, null), /* @__PURE__ */ React15.createElement(List2.ItemTitle, {
1559
2103
  onClick: () => handleSelect(field2)
1560
- }, field2.path), /* @__PURE__ */ React14.createElement("div", {
2104
+ }, field2.path), /* @__PURE__ */ React15.createElement("div", {
1561
2105
  className: "flex items-center gap-2 -ml-4"
1562
- }, /* @__PURE__ */ React14.createElement(List2.ItemButton, {
2106
+ }, /* @__PURE__ */ React15.createElement(List2.ItemButton, {
1563
2107
  icon: "ph--eye-slash--regular",
1564
2108
  disabled: view.fields.length <= 1,
1565
2109
  onClick: () => handleHide(field2.id)
1566
- }), !schema.readonly && /* @__PURE__ */ React14.createElement(List2.ItemDeleteButton, {
2110
+ }), !immutable && /* @__PURE__ */ React15.createElement(List2.ItemDeleteButton, {
1567
2111
  icon: "ph--trash--regular",
1568
2112
  disabled: view.fields.length <= 1,
1569
2113
  onClick: () => handleDelete(field2.id)
1570
- }))))))), hiddenProperties.length > 0 && /* @__PURE__ */ React14.createElement("div", null, /* @__PURE__ */ React14.createElement("div", {
2114
+ }))))))), hiddenProperties.length > 0 && /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", {
1571
2115
  role: "none",
1572
2116
  className: "p-2"
1573
- }, /* @__PURE__ */ React14.createElement("label", {
2117
+ }, /* @__PURE__ */ React15.createElement("label", {
1574
2118
  className: mx9(inputTextLabel)
1575
- }, t("hidden fields label"))), /* @__PURE__ */ React14.createElement(List2.Root, {
2119
+ }, t("hidden fields label"))), /* @__PURE__ */ React15.createElement(List2.Root, {
1576
2120
  items: hiddenProperties,
1577
2121
  isItem: (item) => typeof item === "string",
1578
2122
  getId: (property) => property
1579
- }, ({ items: properties }) => /* @__PURE__ */ React14.createElement("div", {
2123
+ }, ({ items: properties }) => /* @__PURE__ */ React15.createElement("div", {
1580
2124
  role: "list",
1581
2125
  className: "flex flex-col w-full"
1582
- }, properties?.map((property) => /* @__PURE__ */ React14.createElement(List2.Item, {
2126
+ }, properties?.map((property) => /* @__PURE__ */ React15.createElement(List2.Item, {
1583
2127
  key: property,
1584
2128
  item: property,
1585
2129
  classNames: mx9(grid, ghostHover, "cursor-pointer")
1586
- }, /* @__PURE__ */ React14.createElement("div", null), /* @__PURE__ */ React14.createElement(List2.ItemTitle, null, property), /* @__PURE__ */ React14.createElement(List2.ItemButton, {
2130
+ }, /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement(List2.ItemTitle, null, property), /* @__PURE__ */ React15.createElement(List2.ItemButton, {
1587
2131
  icon: "ph--eye--regular",
1588
2132
  onClick: () => handleShow(property)
1589
- }))))))), field && /* @__PURE__ */ React14.createElement(FieldEditor, {
2133
+ }))))))), field && /* @__PURE__ */ React15.createElement(FieldEditor, {
1590
2134
  key: field.id,
1591
2135
  view,
1592
2136
  projection,
1593
2137
  field,
1594
2138
  registry,
1595
2139
  onSave: handleClose
1596
- }), !readonly && !field && /* @__PURE__ */ React14.createElement("div", {
2140
+ }), !readonly && !field && /* @__PURE__ */ React15.createElement("div", {
1597
2141
  className: "flex p-2 justify-center"
1598
- }, /* @__PURE__ */ React14.createElement(IconButton4, {
2142
+ }, /* @__PURE__ */ React15.createElement(IconButton4, {
1599
2143
  icon: "ph--plus--regular",
1600
2144
  label: t("button add property"),
1601
- onClick: schema.readonly ? void 0 : handleAdd,
2145
+ onClick: immutable ? void 0 : handleAdd,
1602
2146
  // TODO(burdon): Show field limit in ux (not tooltip).
1603
2147
  disabled: view.fields.length >= VIEW_FIELD_LIMIT
1604
2148
  })));
1605
2149
  };
1606
-
1607
- // packages/ui/react-ui-form/src/util/field.ts
1608
- import { FormatEnum as FormatEnum3, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
1609
- var parseValue = ({ type, format, value }) => {
1610
- if (value === void 0 || value === null || value === "") {
1611
- return void 0;
1612
- }
1613
- const parseScalar = (type2) => {
1614
- switch (type2) {
1615
- case TypeEnum.Boolean: {
1616
- if (typeof value === "string") {
1617
- const lowercaseValue = value.toLowerCase();
1618
- if (lowercaseValue === "0" || lowercaseValue === "false") {
1619
- return false;
1620
- } else if (lowercaseValue === "1" || lowercaseValue === "true") {
1621
- return true;
1622
- }
1623
- }
1624
- return Boolean(value);
1625
- }
1626
- case TypeEnum.Number: {
1627
- const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1628
- const num = Number(cleaned);
1629
- return Number.isNaN(num) ? null : num;
1630
- }
1631
- case TypeEnum.String:
1632
- case TypeEnum.Ref:
1633
- return String(value);
1634
- default: {
1635
- return value;
1636
- }
1637
- }
1638
- };
1639
- if (!format) {
1640
- return parseScalar(type);
1641
- }
1642
- switch (format) {
1643
- case FormatEnum3.Boolean:
1644
- return parseScalar(TypeEnum.Boolean);
1645
- case FormatEnum3.Number:
1646
- case FormatEnum3.Percent:
1647
- case FormatEnum3.Currency:
1648
- return parseScalar(TypeEnum.Number);
1649
- case FormatEnum3.String:
1650
- case FormatEnum3.Markdown: {
1651
- return parseScalar(TypeEnum.String);
1652
- }
1653
- case FormatEnum3.Ref:
1654
- throw new Error(`unexpected format: ${FormatEnum3.Ref}`);
1655
- case FormatEnum3.DateTime:
1656
- case FormatEnum3.Date:
1657
- case FormatEnum3.Time:
1658
- case FormatEnum3.Timestamp: {
1659
- const date = new Date(value);
1660
- return isNaN(date.getTime()) ? null : date;
1661
- }
1662
- case FormatEnum3.GeoPoint: {
1663
- if (typeof value === "string") {
1664
- const cleaned = value.replace(/[^0-9.,-]+/g, "");
1665
- const parts = cleaned.split(",");
1666
- if (parts.length === 2) {
1667
- const lat = parseFloat(parts[0]);
1668
- const long = parseFloat(parts[1]);
1669
- if (!isNaN(lat) && !isNaN(long)) {
1670
- return GeoLocation2.toGeoPoint({
1671
- latitude: lat,
1672
- longitude: long
1673
- });
1674
- }
1675
- }
1676
- }
1677
- return [
1678
- 0,
1679
- 0
1680
- ];
1681
- }
1682
- default: {
1683
- return value;
1684
- }
1685
- }
1686
- };
1687
- var cellClassesForFieldType = ({ type, format }) => {
1688
- if (!format) {
1689
- switch (type) {
1690
- case TypeEnum.Number:
1691
- return [
1692
- "text-right",
1693
- "font-mono"
1694
- ];
1695
- case TypeEnum.Boolean:
1696
- return [
1697
- "text-right",
1698
- "font-mono"
1699
- ];
1700
- case TypeEnum.String:
1701
- return void 0;
1702
- case TypeEnum.Ref:
1703
- return void 0;
1704
- default: {
1705
- return void 0;
1706
- }
1707
- }
1708
- }
1709
- switch (format) {
1710
- case FormatEnum3.Markdown:
1711
- return void 0;
1712
- case FormatEnum3.Time:
1713
- case FormatEnum3.Timestamp:
1714
- case FormatEnum3.DateTime:
1715
- case FormatEnum3.Date:
1716
- case FormatEnum3.Duration:
1717
- return [
1718
- "font-mono",
1719
- "text-right"
1720
- ];
1721
- case FormatEnum3.Currency:
1722
- return [
1723
- "text-right"
1724
- ];
1725
- case FormatEnum3.JSON:
1726
- case FormatEnum3.DID:
1727
- return [
1728
- "font-mono"
1729
- ];
1730
- default:
1731
- return void 0;
1732
- }
1733
- };
1734
- var pathNotUniqueError = (path) => ({
1735
- path: "path",
1736
- message: `'${path}' is already present`
1737
- });
1738
-
1739
- // packages/ui/react-ui-form/src/util/formatting.ts
1740
- import { format as formatDate } from "date-fns/format";
1741
- import { FormatEnum as FormatEnum4, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1742
- var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1743
- const formatScalar = (type2) => {
1744
- switch (type2) {
1745
- case TypeEnum2.Boolean:
1746
- return value.toLocaleString().toUpperCase();
1747
- case TypeEnum2.Number:
1748
- return value.toLocaleString(locale);
1749
- case TypeEnum2.String:
1750
- case TypeEnum2.Ref:
1751
- return String(value);
1752
- default: {
1753
- return String(value);
1754
- }
1755
- }
1756
- };
1757
- if (!format) {
1758
- return formatScalar(type);
1759
- }
1760
- switch (format) {
1761
- case FormatEnum4.Boolean: {
1762
- return formatScalar(TypeEnum2.Boolean);
1763
- }
1764
- case FormatEnum4.Number: {
1765
- return formatScalar(TypeEnum2.Number);
1766
- }
1767
- case FormatEnum4.String:
1768
- case FormatEnum4.Ref: {
1769
- return formatScalar(TypeEnum2.String);
1770
- }
1771
- case FormatEnum4.Percent: {
1772
- return `${value * 100}%`;
1773
- }
1774
- case FormatEnum4.Currency: {
1775
- return value.toLocaleString(locale, {
1776
- style: "currency",
1777
- currency: "USD",
1778
- minimumFractionDigits: 2,
1779
- maximumFractionDigits: 2
1780
- });
1781
- }
1782
- case FormatEnum4.Date: {
1783
- return formatDate(new Date(value), "yyyy-MM-dd");
1784
- }
1785
- case FormatEnum4.Time: {
1786
- return formatDate(new Date(value), "HH:mm:ss");
1787
- }
1788
- case FormatEnum4.DateTime: {
1789
- return formatDate(new Date(value), "yyyy-MM-dd HH:mm:ss");
1790
- }
1791
- case FormatEnum4.GeoPoint: {
1792
- if (value === null || value === void 0) {
1793
- return "";
1794
- }
1795
- if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1796
- const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1797
- return `${latitude},${longitude}`;
1798
- }
1799
- return String(value);
1800
- }
1801
- default: {
1802
- if (value === null || value === "undefined") {
1803
- return "";
1804
- }
1805
- return String(value);
1806
- }
1807
- }
1808
- };
1809
- var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1810
- const formatScalar = (type2) => {
1811
- switch (type2) {
1812
- case TypeEnum2.Boolean:
1813
- case TypeEnum2.Number:
1814
- case TypeEnum2.String:
1815
- case TypeEnum2.Ref:
1816
- return String(value);
1817
- default:
1818
- return String(value);
1819
- }
1820
- };
1821
- if (!format) {
1822
- return formatScalar(type);
1823
- }
1824
- switch (format) {
1825
- case FormatEnum4.Boolean:
1826
- case FormatEnum4.Number:
1827
- case FormatEnum4.String:
1828
- case FormatEnum4.Ref: {
1829
- return formatScalar(type);
1830
- }
1831
- case FormatEnum4.Percent: {
1832
- return String(value * 100);
1833
- }
1834
- case FormatEnum4.Currency: {
1835
- return String(value);
1836
- }
1837
- case FormatEnum4.DateTime: {
1838
- const date = new Date(value);
1839
- return date.toISOString();
1840
- }
1841
- case FormatEnum4.Date: {
1842
- const date = new Date(value);
1843
- return date.toISOString().split("T")[0];
1844
- }
1845
- case FormatEnum4.Time: {
1846
- const date = new Date(value);
1847
- return date.toISOString().split("T")[1].split(".")[0];
1848
- }
1849
- case FormatEnum4.GeoPoint: {
1850
- if (value === null || value === void 0) {
1851
- return "";
1852
- }
1853
- if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1854
- const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1855
- return `${latitude},${longitude}`;
1856
- }
1857
- return String(value);
1858
- }
1859
- default: {
1860
- return String(value);
1861
- }
1862
- }
1863
- };
1864
2150
  export {
1865
2151
  BooleanInput,
1866
2152
  ControlFrame,
@@ -1888,14 +2174,18 @@ export {
1888
2174
  ViewEditor,
1889
2175
  cellClassesForFieldType,
1890
2176
  controlItemClasses,
2177
+ findArrayElementType,
1891
2178
  formatForDisplay,
1892
2179
  formatForEditing,
2180
+ getRefProps,
1893
2181
  parseValue,
1894
2182
  pathNotUniqueError,
1895
2183
  translations_default as translations,
1896
2184
  useForm,
1897
2185
  useFormContext,
1898
2186
  useFormValues,
1899
- useInputProps
2187
+ useInputProps,
2188
+ useQueryRefOptions,
2189
+ useRefQueryLookupHandler
1900
2190
  };
1901
2191
  //# sourceMappingURL=index.mjs.map