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