@dxos/react-ui-form 0.8.2-main.5885341 → 0.8.2-main.600d381
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.
- package/dist/lib/browser/index.mjs +720 -557
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +734 -579
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +720 -557
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +4 -4
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +33 -32
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContent.d.ts +3 -3
- package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
- package/dist/types/src/components/Form/Input.d.ts.map +1 -1
- package/dist/types/src/components/Form/RefField.d.ts +7 -18
- package/dist/types/src/components/Form/RefField.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/factory.d.ts +1 -1
- package/dist/types/src/components/Form/factory.d.ts.map +1 -1
- package/dist/types/src/components/Form/index.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/Form.d.ts +2 -2
- package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +2 -2
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/dist/types/src/hooks/useQueryRefOptions.d.ts +23 -0
- package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -0
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +8 -0
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -0
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/refs.d.ts +9 -0
- package/dist/types/src/util/refs.d.ts.map +1 -0
- package/dist/types/src/util/schema.d.ts +3 -0
- package/dist/types/src/util/schema.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +25 -24
- package/src/components/ControlSection/ControlSection.stories.tsx +1 -1
- package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
- package/src/components/Form/ArrayField.tsx +5 -6
- package/src/components/Form/Defaults.tsx +4 -1
- package/src/components/Form/Form.stories.tsx +48 -42
- package/src/components/Form/Form.tsx +4 -4
- package/src/components/Form/FormContent.tsx +49 -22
- package/src/components/Form/FormContext.tsx +3 -1
- package/src/components/Form/Input.tsx +3 -9
- package/src/components/Form/RefField.tsx +145 -100
- package/src/components/Form/custom/SelectOptionsInput.stories.tsx +6 -5
- package/src/components/Form/factory.tsx +1 -1
- package/src/components/Form/index.ts +0 -1
- package/src/components/ViewEditor/ViewEditor.stories.tsx +4 -3
- package/src/components/ViewEditor/ViewEditor.tsx +9 -8
- package/src/components/deprecated/Form.tsx +6 -6
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useForm.ts +3 -3
- package/src/hooks/useQueryRefOptions.ts +53 -0
- package/src/hooks/useRefQueryLookupHandler.ts +41 -0
- package/src/util/index.ts +3 -1
- package/src/util/refs.ts +38 -0
- package/src/util/schema.ts +14 -0
|
@@ -183,8 +183,8 @@ var ControlFrameItem = ({ title, description, children }) => {
|
|
|
183
183
|
};
|
|
184
184
|
|
|
185
185
|
// packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
|
|
186
|
-
import React14, { useCallback as
|
|
187
|
-
import { FormatEnum as
|
|
186
|
+
import React14, { useCallback as useCallback8, useEffect as useEffect8, useMemo as useMemo8, useState as useState5 } from "react";
|
|
187
|
+
import { FormatEnum as FormatEnum5, FormatEnums, formatToType } from "@dxos/echo-schema";
|
|
188
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";
|
|
@@ -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.
|
|
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
|
-
}))
|
|
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
|
|
557
|
-
onValueChange:
|
|
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(
|
|
566
|
-
value: String(
|
|
567
|
-
}, label2 ?? String(
|
|
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 React13, { useEffect as useEffect7, useMemo as
|
|
616
|
+
import React13, { useEffect as useEffect7, useMemo as useMemo7, 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
|
|
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
|
|
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(
|
|
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
|
-
"
|
|
645
|
+
"SchemaAST.isTypeLiteral(schema.ast)",
|
|
641
646
|
""
|
|
642
647
|
]
|
|
643
648
|
});
|
|
@@ -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
|
-
|
|
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,243 +1002,588 @@ 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 React12, { useMemo as
|
|
928
|
-
import {
|
|
929
|
-
import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
|
|
1007
|
+
import React12, { useMemo as useMemo6 } 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
|
|
938
|
-
import {
|
|
939
|
-
import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
|
|
1016
|
+
import React10, { useCallback as useCallback6, useMemo as useMemo4 } 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: 39,
|
|
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 {};
|
|
967
|
-
}
|
|
968
|
-
return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
|
|
969
|
-
prop.name,
|
|
970
|
-
prop.defaultValue
|
|
971
|
-
]));
|
|
972
|
-
};
|
|
973
|
-
const newValue = useMemo4(() => {
|
|
974
|
-
if (type === "object" && elementType) {
|
|
975
|
-
return getDefaultObjectValue(elementType);
|
|
976
|
-
} else {
|
|
977
|
-
return SimpleType.getDefaultValue(type);
|
|
978
|
-
}
|
|
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
|
-
}
|
|
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
|
-
};
|
|
1048
1022
|
|
|
1049
|
-
// packages/ui/react-ui-form/src/
|
|
1050
|
-
import
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
import { refFromDXN } from "@dxos/live-object";
|
|
1055
|
-
import { log as log2 } from "@dxos/log";
|
|
1056
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/RefField.tsx";
|
|
1057
|
-
var RefField = ({ ast, type, label, readonly, placeholder, inline, onQueryRefOptions, inputProps }) => {
|
|
1058
|
-
const { getValue: getValue3, onValueChange, ...restInputProps } = inputProps;
|
|
1059
|
-
const refTypeInfo = findAnnotation(ast, ReferenceAnnotationId);
|
|
1060
|
-
const [refOptions, setRefOptions] = useState4([]);
|
|
1061
|
-
const [loading, setLoading] = useState4(false);
|
|
1062
|
-
useEffect6(() => {
|
|
1063
|
-
if (!refTypeInfo || !onQueryRefOptions) {
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
const fetchOptions = async () => {
|
|
1067
|
-
setLoading(true);
|
|
1068
|
-
try {
|
|
1069
|
-
const options = await onQueryRefOptions(refTypeInfo);
|
|
1070
|
-
setRefOptions(options.map((option) => ({
|
|
1071
|
-
label: option.label,
|
|
1072
|
-
value: option.dxn.toString()
|
|
1073
|
-
})));
|
|
1074
|
-
} catch (error) {
|
|
1075
|
-
log2.error("Failed to fetch ref options:", error, {
|
|
1076
|
-
F: __dxlog_file3,
|
|
1077
|
-
L: 69,
|
|
1078
|
-
S: void 0,
|
|
1079
|
-
C: (f, a) => f(...a)
|
|
1080
|
-
});
|
|
1081
|
-
setRefOptions([]);
|
|
1082
|
-
} finally {
|
|
1083
|
-
setLoading(false);
|
|
1084
|
-
}
|
|
1085
|
-
};
|
|
1086
|
-
void fetchOptions();
|
|
1087
|
-
}, [
|
|
1088
|
-
refTypeInfo,
|
|
1089
|
-
onQueryRefOptions
|
|
1090
|
-
]);
|
|
1091
|
-
if (!refTypeInfo) {
|
|
1092
|
-
return null;
|
|
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;
|
|
1093
1028
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
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);
|
|
1103
1041
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
return formValue;
|
|
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;
|
|
1109
1046
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1047
|
+
case TypeEnum.String:
|
|
1048
|
+
case TypeEnum.Ref:
|
|
1049
|
+
return String(value);
|
|
1050
|
+
default: {
|
|
1051
|
+
return value;
|
|
1112
1052
|
}
|
|
1113
|
-
return void 0;
|
|
1114
|
-
};
|
|
1115
|
-
return /* @__PURE__ */ React11.createElement(TextInput, {
|
|
1116
|
-
type,
|
|
1117
|
-
label,
|
|
1118
|
-
disabled: readonly,
|
|
1119
|
-
placeholder,
|
|
1120
|
-
inputOnly: inline,
|
|
1121
|
-
getValue: handleGetValue2,
|
|
1122
|
-
onValueChange: handleOnValueChange,
|
|
1123
|
-
...restInputProps
|
|
1124
|
-
});
|
|
1125
|
-
}
|
|
1126
|
-
const handleGetValue = () => {
|
|
1127
|
-
const formValue = getValue3();
|
|
1128
|
-
if (Ref.isRef(formValue)) {
|
|
1129
|
-
return formValue.dxn.toString();
|
|
1130
1053
|
}
|
|
1131
|
-
return void 0;
|
|
1132
|
-
};
|
|
1133
|
-
const handleValueChanged = (_type, dxnString) => {
|
|
1134
|
-
const dxn = DXN.parse(dxnString);
|
|
1135
|
-
const ref = refFromDXN(dxn);
|
|
1136
|
-
onValueChange("object", ref);
|
|
1137
1054
|
};
|
|
1138
|
-
|
|
1139
|
-
type
|
|
1140
|
-
|
|
1141
|
-
disabled: readonly || loading,
|
|
1142
|
-
placeholder: loading ? "Loading options..." : placeholder,
|
|
1143
|
-
inputOnly: inline,
|
|
1144
|
-
getValue: handleGetValue,
|
|
1145
|
-
onValueChange: handleValueChanged,
|
|
1146
|
-
options: refOptions,
|
|
1147
|
-
...restInputProps
|
|
1148
|
-
});
|
|
1149
|
-
};
|
|
1150
|
-
|
|
1151
|
-
// packages/ui/react-ui-form/src/components/Form/factory.tsx
|
|
1152
|
-
import { FormatEnum } from "@dxos/echo-schema";
|
|
1153
|
-
var getInputComponent = (type, format) => {
|
|
1055
|
+
if (!format) {
|
|
1056
|
+
return parseScalar(type);
|
|
1057
|
+
}
|
|
1154
1058
|
switch (format) {
|
|
1155
|
-
case FormatEnum.
|
|
1156
|
-
return
|
|
1157
|
-
case FormatEnum.
|
|
1158
|
-
|
|
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;
|
|
1100
|
+
}
|
|
1159
1101
|
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1102
|
+
};
|
|
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
|
+
}
|
|
1125
|
+
switch (format) {
|
|
1126
|
+
case FormatEnum.Markdown:
|
|
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;
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
var pathNotUniqueError = (path) => ({
|
|
1151
|
+
path: "path",
|
|
1152
|
+
message: `'${path}' is already present`
|
|
1153
|
+
});
|
|
1154
|
+
|
|
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 newValue = useMemo4(() => {
|
|
1360
|
+
if (type === "object" && elementType) {
|
|
1361
|
+
return getDefaultObjectValue(elementType);
|
|
1362
|
+
} else {
|
|
1363
|
+
return SimpleType.getDefaultValue(type);
|
|
1364
|
+
}
|
|
1365
|
+
}, [
|
|
1366
|
+
type,
|
|
1367
|
+
elementType
|
|
1368
|
+
]);
|
|
1369
|
+
const handleAdd = useCallback6(() => {
|
|
1370
|
+
inputProps.onValueChange(type, [
|
|
1371
|
+
...values,
|
|
1372
|
+
newValue
|
|
1373
|
+
]);
|
|
1374
|
+
}, [
|
|
1375
|
+
type,
|
|
1376
|
+
elementType,
|
|
1377
|
+
inputProps,
|
|
1378
|
+
newValue,
|
|
1379
|
+
values
|
|
1380
|
+
]);
|
|
1381
|
+
const handleRemove = useCallback6((index) => {
|
|
1382
|
+
const newValues = values.filter((_, i) => i !== index);
|
|
1383
|
+
inputProps.onValueChange(type, newValues);
|
|
1384
|
+
}, [
|
|
1385
|
+
type,
|
|
1386
|
+
inputProps,
|
|
1387
|
+
values
|
|
1388
|
+
]);
|
|
1389
|
+
if (!elementType) {
|
|
1390
|
+
return null;
|
|
1391
|
+
}
|
|
1392
|
+
return /* @__PURE__ */ React10.createElement("div", {
|
|
1393
|
+
role: "none",
|
|
1394
|
+
className: mx6(padding)
|
|
1395
|
+
}, /* @__PURE__ */ React10.createElement(InputHeader, null, label), /* @__PURE__ */ React10.createElement("div", {
|
|
1396
|
+
role: "none",
|
|
1397
|
+
className: "flex flex-col gap-1"
|
|
1398
|
+
}, values.map((_value, index) => /* @__PURE__ */ React10.createElement("div", {
|
|
1399
|
+
key: index,
|
|
1400
|
+
role: "none",
|
|
1401
|
+
className: "flex items-center gap-1"
|
|
1402
|
+
}, /* @__PURE__ */ React10.createElement("div", {
|
|
1403
|
+
role: "none",
|
|
1404
|
+
className: "flex-1"
|
|
1405
|
+
}, /* @__PURE__ */ React10.createElement(FormField, {
|
|
1406
|
+
property: {
|
|
1407
|
+
...property,
|
|
1408
|
+
array: false,
|
|
1409
|
+
ast: elementType
|
|
1410
|
+
},
|
|
1411
|
+
path: [
|
|
1412
|
+
...path ?? [],
|
|
1413
|
+
index
|
|
1414
|
+
],
|
|
1415
|
+
readonly,
|
|
1416
|
+
inline: true,
|
|
1417
|
+
Custom,
|
|
1418
|
+
lookupComponent
|
|
1419
|
+
})), /* @__PURE__ */ React10.createElement(IconButton3, {
|
|
1420
|
+
icon: "ph--trash--regular",
|
|
1421
|
+
iconOnly: true,
|
|
1422
|
+
label: t("button remove"),
|
|
1423
|
+
onClick: () => handleRemove(index)
|
|
1424
|
+
})))), /* @__PURE__ */ React10.createElement("div", {
|
|
1425
|
+
role: "none",
|
|
1426
|
+
className: "flex justify-between items-center plb-1"
|
|
1427
|
+
}, /* @__PURE__ */ React10.createElement(IconButton3, {
|
|
1428
|
+
icon: "ph--plus--regular",
|
|
1429
|
+
iconOnly: true,
|
|
1430
|
+
label: t("button add"),
|
|
1431
|
+
onClick: handleAdd
|
|
1432
|
+
})));
|
|
1433
|
+
};
|
|
1434
|
+
|
|
1435
|
+
// packages/ui/react-ui-form/src/components/Form/RefField.tsx
|
|
1436
|
+
import React11, { useCallback as useCallback7, useMemo as useMemo5 } from "react";
|
|
1437
|
+
import { Expando, getTypeAnnotation, Ref, ReferenceAnnotationId as ReferenceAnnotationId2 } from "@dxos/echo-schema";
|
|
1438
|
+
import { findAnnotation as findAnnotation2 } from "@dxos/effect";
|
|
1439
|
+
import { DXN } from "@dxos/keys";
|
|
1440
|
+
import { Input as Input7 } from "@dxos/react-ui";
|
|
1441
|
+
import { TagPicker } from "@dxos/react-ui-tag-picker";
|
|
1442
|
+
import { isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
1443
|
+
var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, getValue: getValue3, onBlur, onQueryRefOptions, onValueChange, ...restInputProps }) => {
|
|
1444
|
+
const refTypeInfo = useMemo5(() => ast ? findAnnotation2(ast, ReferenceAnnotationId2) : void 0, [
|
|
1445
|
+
ast
|
|
1446
|
+
]);
|
|
1447
|
+
const { options: availableOptions, loading: _loading } = useQueryRefOptions({
|
|
1448
|
+
refTypeInfo,
|
|
1449
|
+
onQueryRefOptions
|
|
1450
|
+
});
|
|
1451
|
+
if (refTypeInfo && refTypeInfo?.typename === getTypeAnnotation(Expando)?.typename || !onQueryRefOptions) {
|
|
1452
|
+
return /* @__PURE__ */ React11.createElement(RefFieldFallback, {
|
|
1453
|
+
type,
|
|
1454
|
+
label,
|
|
1455
|
+
placeholder,
|
|
1456
|
+
disabled,
|
|
1457
|
+
inputOnly,
|
|
1458
|
+
getValue: getValue3,
|
|
1459
|
+
onBlur,
|
|
1460
|
+
onValueChange,
|
|
1461
|
+
...restInputProps
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1464
|
+
const handleGetValue = useCallback7(() => {
|
|
1465
|
+
const formValue = getValue3();
|
|
1466
|
+
const unknownToRefOption = (val) => {
|
|
1467
|
+
if (Ref.isRef(val)) {
|
|
1468
|
+
const dxnString = val.dxn.toString();
|
|
1469
|
+
const matchingOption = availableOptions.find((option2) => option2.id === dxnString);
|
|
1470
|
+
if (matchingOption) {
|
|
1471
|
+
return matchingOption;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
return void 0;
|
|
1475
|
+
};
|
|
1476
|
+
if (array && Array.isArray(formValue)) {
|
|
1477
|
+
return formValue.map(unknownToRefOption).filter(isNonNullable2) ?? [];
|
|
1478
|
+
}
|
|
1479
|
+
const option = unknownToRefOption(formValue);
|
|
1480
|
+
if (option) {
|
|
1481
|
+
return [
|
|
1482
|
+
option
|
|
1483
|
+
];
|
|
1484
|
+
}
|
|
1485
|
+
return [];
|
|
1486
|
+
}, [
|
|
1487
|
+
getValue3,
|
|
1488
|
+
availableOptions,
|
|
1489
|
+
array
|
|
1490
|
+
]);
|
|
1491
|
+
const handleSearch = useCallback7((text, ids) => availableOptions.filter((option) => !ids.includes(option.id)).filter((option) => option.label.toLowerCase().includes(text.toLowerCase())).map((option) => ({
|
|
1492
|
+
id: option.id,
|
|
1493
|
+
label: option.label,
|
|
1494
|
+
hue: option.hue
|
|
1495
|
+
})), [
|
|
1496
|
+
availableOptions
|
|
1497
|
+
]);
|
|
1498
|
+
const handleUpdate = useCallback7((ids) => {
|
|
1499
|
+
if (ids.length === 0) {
|
|
1500
|
+
onValueChange("object", void 0);
|
|
1501
|
+
return;
|
|
1502
|
+
}
|
|
1503
|
+
const refs = ids.map((id) => {
|
|
1504
|
+
const item = availableOptions.find((option) => option.id === id);
|
|
1505
|
+
if (item) {
|
|
1506
|
+
const dxn = DXN.parse(item.id);
|
|
1507
|
+
return Ref.fromDXN(dxn);
|
|
1508
|
+
}
|
|
1509
|
+
return null;
|
|
1510
|
+
}).filter(isNonNullable2);
|
|
1511
|
+
if (array) {
|
|
1512
|
+
onValueChange("object", refs);
|
|
1513
|
+
} else {
|
|
1514
|
+
onValueChange("object", refs[0]);
|
|
1515
|
+
}
|
|
1516
|
+
}, [
|
|
1517
|
+
availableOptions,
|
|
1518
|
+
array,
|
|
1519
|
+
onValueChange
|
|
1520
|
+
]);
|
|
1521
|
+
const tagPickerMode = useMemo5(() => array ? "multi-select" : "single-select", [
|
|
1522
|
+
array
|
|
1523
|
+
]);
|
|
1524
|
+
if (!refTypeInfo) {
|
|
1525
|
+
return null;
|
|
1526
|
+
}
|
|
1527
|
+
const { status, error } = restInputProps.getStatus();
|
|
1528
|
+
return /* @__PURE__ */ React11.createElement(Input7.Root, {
|
|
1529
|
+
validationValence: status
|
|
1530
|
+
}, !inputOnly && /* @__PURE__ */ React11.createElement(InputHeader, {
|
|
1531
|
+
error
|
|
1532
|
+
}, /* @__PURE__ */ React11.createElement(Input7.Label, null, label)), /* @__PURE__ */ React11.createElement("div", {
|
|
1533
|
+
"data-no-submit": true
|
|
1534
|
+
}, /* @__PURE__ */ React11.createElement(TagPicker, {
|
|
1535
|
+
items: handleGetValue(),
|
|
1536
|
+
mode: tagPickerMode,
|
|
1537
|
+
onBlur: (event) => onBlur(event),
|
|
1538
|
+
onUpdate: handleUpdate,
|
|
1539
|
+
onSearch: handleSearch,
|
|
1540
|
+
classNames: "rounded-sm bg-input p-1.5"
|
|
1541
|
+
})), inputOnly && /* @__PURE__ */ React11.createElement(Input7.DescriptionAndValidation, null, error));
|
|
1542
|
+
};
|
|
1543
|
+
var RefFieldFallback = ({ type, label, disabled, placeholder, inputOnly, getValue: getValue3, onValueChange, ...restInputProps }) => {
|
|
1544
|
+
const handleOnValueChange = (_type, dxnString) => {
|
|
1545
|
+
const dxn = DXN.tryParse(dxnString);
|
|
1546
|
+
if (dxn) {
|
|
1547
|
+
onValueChange?.("object", Ref.fromDXN(dxn));
|
|
1548
|
+
} else if (dxnString === "") {
|
|
1549
|
+
onValueChange?.("object", void 0);
|
|
1550
|
+
} else {
|
|
1551
|
+
onValueChange?.("string", dxnString);
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
const handleGetValue = () => {
|
|
1555
|
+
const formValue = getValue3();
|
|
1556
|
+
if (typeof formValue === "string") {
|
|
1557
|
+
return formValue;
|
|
1558
|
+
}
|
|
1559
|
+
if (Ref.isRef(formValue)) {
|
|
1560
|
+
return formValue.dxn.toString();
|
|
1561
|
+
}
|
|
1562
|
+
return void 0;
|
|
1563
|
+
};
|
|
1564
|
+
return /* @__PURE__ */ React11.createElement(TextInput, {
|
|
1565
|
+
type,
|
|
1566
|
+
label,
|
|
1567
|
+
disabled,
|
|
1568
|
+
placeholder,
|
|
1569
|
+
inputOnly,
|
|
1570
|
+
getValue: handleGetValue,
|
|
1571
|
+
onValueChange: handleOnValueChange,
|
|
1572
|
+
...restInputProps
|
|
1573
|
+
});
|
|
1574
|
+
};
|
|
1575
|
+
|
|
1576
|
+
// packages/ui/react-ui-form/src/components/Form/factory.tsx
|
|
1577
|
+
import { FormatEnum as FormatEnum4 } from "@dxos/echo-schema";
|
|
1578
|
+
var getInputComponent = (type, format) => {
|
|
1579
|
+
switch (format) {
|
|
1580
|
+
case FormatEnum4.GeoPoint:
|
|
1581
|
+
return GeoPointInput;
|
|
1582
|
+
case FormatEnum4.Markdown:
|
|
1583
|
+
return MarkdownInput;
|
|
1584
|
+
}
|
|
1585
|
+
switch (type) {
|
|
1586
|
+
case "string":
|
|
1162
1587
|
return TextInput;
|
|
1163
1588
|
case "number":
|
|
1164
1589
|
return NumberInput;
|
|
@@ -1171,17 +1596,17 @@ var getInputComponent = (type, format) => {
|
|
|
1171
1596
|
var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupComponent, Custom }) => {
|
|
1172
1597
|
const inputProps = useInputProps(path);
|
|
1173
1598
|
const { ast, name, type, format, title, description, options, examples, array } = property;
|
|
1174
|
-
const label =
|
|
1599
|
+
const label = useMemo6(() => title ?? pipe2(name, capitalize2), [
|
|
1175
1600
|
title,
|
|
1176
1601
|
name
|
|
1177
1602
|
]);
|
|
1178
|
-
const placeholder =
|
|
1603
|
+
const placeholder = useMemo6(() => examples?.length ? `Example: "${examples[0]}"` : description, [
|
|
1179
1604
|
examples,
|
|
1180
1605
|
description
|
|
1181
1606
|
]);
|
|
1182
1607
|
const FoundComponent = lookupComponent?.({
|
|
1183
1608
|
prop: name,
|
|
1184
|
-
schema:
|
|
1609
|
+
schema: Schema.make(ast),
|
|
1185
1610
|
inputProps: {
|
|
1186
1611
|
type,
|
|
1187
1612
|
format,
|
|
@@ -1209,6 +1634,21 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
|
|
|
1209
1634
|
...inputProps
|
|
1210
1635
|
});
|
|
1211
1636
|
}
|
|
1637
|
+
const refProps = getRefProps(property);
|
|
1638
|
+
if (refProps) {
|
|
1639
|
+
return /* @__PURE__ */ React12.createElement(RefField, {
|
|
1640
|
+
ast: refProps.ast,
|
|
1641
|
+
array: refProps.isArray,
|
|
1642
|
+
type,
|
|
1643
|
+
format,
|
|
1644
|
+
label,
|
|
1645
|
+
placeholder,
|
|
1646
|
+
disabled: readonly,
|
|
1647
|
+
inputOnly: inline,
|
|
1648
|
+
onQueryRefOptions,
|
|
1649
|
+
...inputProps
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1212
1652
|
if (array) {
|
|
1213
1653
|
return /* @__PURE__ */ React12.createElement(ArrayField, {
|
|
1214
1654
|
property,
|
|
@@ -1249,28 +1689,16 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
|
|
|
1249
1689
|
...inputProps
|
|
1250
1690
|
}));
|
|
1251
1691
|
}
|
|
1252
|
-
if (format === "ref") {
|
|
1253
|
-
return /* @__PURE__ */ React12.createElement(RefField, {
|
|
1254
|
-
ast,
|
|
1255
|
-
type,
|
|
1256
|
-
label,
|
|
1257
|
-
readonly,
|
|
1258
|
-
placeholder,
|
|
1259
|
-
inline,
|
|
1260
|
-
onQueryRefOptions,
|
|
1261
|
-
inputProps
|
|
1262
|
-
});
|
|
1263
|
-
}
|
|
1264
1692
|
if (type === "object") {
|
|
1265
|
-
const baseNode =
|
|
1266
|
-
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) :
|
|
1693
|
+
const baseNode = findNode3(ast, isDiscriminatedUnion2);
|
|
1694
|
+
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode3(ast, SchemaAST4.isTypeLiteral);
|
|
1267
1695
|
if (typeLiteral) {
|
|
1268
1696
|
return /* @__PURE__ */ React12.createElement("div", {
|
|
1269
1697
|
role: "none"
|
|
1270
1698
|
}, !inline && /* @__PURE__ */ React12.createElement("h3", {
|
|
1271
1699
|
className: "text-lg mbs-2 mbe-1"
|
|
1272
1700
|
}, label), /* @__PURE__ */ React12.createElement(FormFields, {
|
|
1273
|
-
schema:
|
|
1701
|
+
schema: Schema.make(typeLiteral),
|
|
1274
1702
|
path,
|
|
1275
1703
|
readonly,
|
|
1276
1704
|
onQueryRefOptions,
|
|
@@ -1283,7 +1711,7 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
|
|
|
1283
1711
|
};
|
|
1284
1712
|
var FormFields = ({ schema, path, filter, sort, readonly, onQueryRefOptions, lookupComponent, Custom }) => {
|
|
1285
1713
|
const values = useFormValues(path);
|
|
1286
|
-
const properties =
|
|
1714
|
+
const properties = useMemo6(() => {
|
|
1287
1715
|
const props = getSchemaProperties2(schema.ast, values);
|
|
1288
1716
|
const filtered = filter ? filter(props) : props;
|
|
1289
1717
|
return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
|
|
@@ -1315,7 +1743,7 @@ var FormFields = ({ schema, path, filter, sort, readonly, onQueryRefOptions, loo
|
|
|
1315
1743
|
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
1316
1744
|
var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, onQueryRefOptions, lookupComponent, Custom }) => {
|
|
1317
1745
|
const formRef = useRef3(null);
|
|
1318
|
-
const onValid =
|
|
1746
|
+
const onValid = useMemo7(() => autoSave ? onSave : void 0, [
|
|
1319
1747
|
autoSave,
|
|
1320
1748
|
onSave
|
|
1321
1749
|
]);
|
|
@@ -1396,7 +1824,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1396
1824
|
const [{ fieldSchema }, setFieldSchema] = useState5({
|
|
1397
1825
|
fieldSchema: getFormatSchema(props?.format)
|
|
1398
1826
|
});
|
|
1399
|
-
const handleValuesChanged =
|
|
1827
|
+
const handleValuesChanged = useCallback8((_props) => {
|
|
1400
1828
|
setFieldSchema((prev) => {
|
|
1401
1829
|
const fieldSchema2 = getFormatSchema(_props.format);
|
|
1402
1830
|
if (prev.fieldSchema === fieldSchema2) {
|
|
@@ -1431,7 +1859,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1431
1859
|
props.format,
|
|
1432
1860
|
props.referenceSchema
|
|
1433
1861
|
]);
|
|
1434
|
-
const handleValidate =
|
|
1862
|
+
const handleValidate = useCallback8(({ property }) => {
|
|
1435
1863
|
if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
|
|
1436
1864
|
return [
|
|
1437
1865
|
{
|
|
@@ -1444,7 +1872,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1444
1872
|
view.fields,
|
|
1445
1873
|
field
|
|
1446
1874
|
]);
|
|
1447
|
-
const handleSave =
|
|
1875
|
+
const handleSave = useCallback8((props2) => {
|
|
1448
1876
|
projection.setFieldProjection({
|
|
1449
1877
|
field,
|
|
1450
1878
|
props: props2
|
|
@@ -1455,16 +1883,16 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1455
1883
|
field,
|
|
1456
1884
|
onSave
|
|
1457
1885
|
]);
|
|
1458
|
-
const handleCancel =
|
|
1886
|
+
const handleCancel = useCallback8(() => {
|
|
1459
1887
|
requestAnimationFrame(() => onCancel?.());
|
|
1460
1888
|
onSave();
|
|
1461
1889
|
}, [
|
|
1462
1890
|
onSave
|
|
1463
1891
|
]);
|
|
1464
|
-
const Custom =
|
|
1892
|
+
const Custom = useMemo8(() => ({
|
|
1465
1893
|
["format"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
|
|
1466
1894
|
...props2,
|
|
1467
|
-
options: FormatEnums.filter((value) => value !==
|
|
1895
|
+
options: FormatEnums.filter((value) => value !== FormatEnum5.None).map((value) => ({
|
|
1468
1896
|
value,
|
|
1469
1897
|
label: t(`format ${value}`)
|
|
1470
1898
|
}))
|
|
@@ -1487,7 +1915,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1487
1915
|
schemas,
|
|
1488
1916
|
referenceSchema
|
|
1489
1917
|
]);
|
|
1490
|
-
const propIsNotType =
|
|
1918
|
+
const propIsNotType = useCallback8((props2) => props2.filter((p) => p.name !== "type"), []);
|
|
1491
1919
|
if (!fieldSchema) {
|
|
1492
1920
|
log3.warn("invalid format", {
|
|
1493
1921
|
props
|
|
@@ -1518,8 +1946,9 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1518
1946
|
};
|
|
1519
1947
|
|
|
1520
1948
|
// packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
|
|
1521
|
-
import
|
|
1522
|
-
import {
|
|
1949
|
+
import { Schema as Schema2, SchemaAST as SchemaAST5 } from "effect";
|
|
1950
|
+
import React15, { useCallback as useCallback9, useMemo as useMemo9, useState as useState6 } from "react";
|
|
1951
|
+
import { Format } from "@dxos/echo-schema";
|
|
1523
1952
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1524
1953
|
import { IconButton as IconButton4, useTranslation as useTranslation7 } from "@dxos/react-ui";
|
|
1525
1954
|
import { List as List2 } from "@dxos/react-ui-list";
|
|
@@ -1527,22 +1956,22 @@ import { ghostHover, inputTextLabel, mx as mx9 } from "@dxos/react-ui-theme";
|
|
|
1527
1956
|
import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1528
1957
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
|
|
1529
1958
|
var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
|
|
1530
|
-
var ViewMetaSchema =
|
|
1531
|
-
name:
|
|
1532
|
-
[
|
|
1959
|
+
var ViewMetaSchema = Schema2.Struct({
|
|
1960
|
+
name: Schema2.String.annotations({
|
|
1961
|
+
[SchemaAST5.TitleAnnotationId]: "View"
|
|
1533
1962
|
}),
|
|
1534
1963
|
typename: Format.URL.annotations({
|
|
1535
|
-
[
|
|
1964
|
+
[SchemaAST5.TitleAnnotationId]: "Typename"
|
|
1536
1965
|
})
|
|
1537
|
-
}).pipe(
|
|
1966
|
+
}).pipe(Schema2.mutable);
|
|
1538
1967
|
var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
|
|
1539
1968
|
const { t } = useTranslation7(translationKey);
|
|
1540
|
-
const projection =
|
|
1969
|
+
const projection = useMemo9(() => new ViewProjection(schema.jsonSchema, view), [
|
|
1541
1970
|
schema,
|
|
1542
1971
|
view
|
|
1543
1972
|
]);
|
|
1544
1973
|
const [field, setField] = useState6();
|
|
1545
|
-
const viewValues =
|
|
1974
|
+
const viewValues = useMemo9(() => {
|
|
1546
1975
|
return {
|
|
1547
1976
|
name: view.name,
|
|
1548
1977
|
// TODO(burdon): Need to warn user of possible consequences of editing.
|
|
@@ -1552,13 +1981,13 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1552
1981
|
}, [
|
|
1553
1982
|
view
|
|
1554
1983
|
]);
|
|
1555
|
-
const handleSelect =
|
|
1984
|
+
const handleSelect = useCallback9((field2) => {
|
|
1556
1985
|
setField((f) => f === field2 ? void 0 : field2);
|
|
1557
1986
|
}, []);
|
|
1558
|
-
const handleAdd =
|
|
1987
|
+
const handleAdd = useCallback9(() => {
|
|
1559
1988
|
invariant3(!schema.readonly, void 0, {
|
|
1560
1989
|
F: __dxlog_file5,
|
|
1561
|
-
L:
|
|
1990
|
+
L: 77,
|
|
1562
1991
|
S: void 0,
|
|
1563
1992
|
A: [
|
|
1564
1993
|
"!schema.readonly",
|
|
@@ -1571,10 +2000,10 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1571
2000
|
schema,
|
|
1572
2001
|
view
|
|
1573
2002
|
]);
|
|
1574
|
-
const handleUpdate =
|
|
2003
|
+
const handleUpdate = useCallback9(({ name, typename }) => {
|
|
1575
2004
|
invariant3(!schema.readonly, void 0, {
|
|
1576
2005
|
F: __dxlog_file5,
|
|
1577
|
-
L:
|
|
2006
|
+
L: 84,
|
|
1578
2007
|
S: void 0,
|
|
1579
2008
|
A: [
|
|
1580
2009
|
"!schema.readonly",
|
|
@@ -1594,10 +2023,10 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1594
2023
|
view,
|
|
1595
2024
|
onTypenameChanged
|
|
1596
2025
|
]);
|
|
1597
|
-
const handleDelete =
|
|
2026
|
+
const handleDelete = useCallback9((fieldId) => {
|
|
1598
2027
|
invariant3(!schema.readonly, void 0, {
|
|
1599
2028
|
F: __dxlog_file5,
|
|
1600
|
-
L:
|
|
2029
|
+
L: 100,
|
|
1601
2030
|
S: void 0,
|
|
1602
2031
|
A: [
|
|
1603
2032
|
"!schema.readonly",
|
|
@@ -1613,10 +2042,10 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1613
2042
|
field,
|
|
1614
2043
|
onDelete
|
|
1615
2044
|
]);
|
|
1616
|
-
const handleMove =
|
|
2045
|
+
const handleMove = useCallback9((fromIndex, toIndex) => {
|
|
1617
2046
|
invariant3(!schema.readonly, void 0, {
|
|
1618
2047
|
F: __dxlog_file5,
|
|
1619
|
-
L:
|
|
2048
|
+
L: 112,
|
|
1620
2049
|
S: void 0,
|
|
1621
2050
|
A: [
|
|
1622
2051
|
"!schema.readonly",
|
|
@@ -1633,15 +2062,15 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1633
2062
|
schema,
|
|
1634
2063
|
view.fields
|
|
1635
2064
|
]);
|
|
1636
|
-
const handleClose =
|
|
2065
|
+
const handleClose = useCallback9(() => setField(void 0), []);
|
|
1637
2066
|
const hiddenProperties = projection.getHiddenProperties();
|
|
1638
|
-
const handleHide =
|
|
2067
|
+
const handleHide = useCallback9((fieldId) => {
|
|
1639
2068
|
setField(void 0);
|
|
1640
2069
|
projection.hideFieldProjection(fieldId);
|
|
1641
2070
|
}, [
|
|
1642
2071
|
projection
|
|
1643
2072
|
]);
|
|
1644
|
-
const handleShow =
|
|
2073
|
+
const handleShow = useCallback9((property) => {
|
|
1645
2074
|
setField(void 0);
|
|
1646
2075
|
projection.showFieldProjection(property);
|
|
1647
2076
|
}, [
|
|
@@ -1666,7 +2095,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1666
2095
|
className: mx9(inputTextLabel)
|
|
1667
2096
|
}, t("fields label"))), /* @__PURE__ */ React15.createElement(List2.Root, {
|
|
1668
2097
|
items: view.fields,
|
|
1669
|
-
isItem:
|
|
2098
|
+
isItem: Schema2.is(FieldSchema),
|
|
1670
2099
|
getId: (field2) => field2.id,
|
|
1671
2100
|
onMove: schema.readonly ? void 0 : handleMove
|
|
1672
2101
|
}, ({ items: fields }) => /* @__PURE__ */ React15.createElement(React15.Fragment, null, showHeading && /* @__PURE__ */ React15.createElement("div", {
|
|
@@ -1729,276 +2158,6 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1729
2158
|
disabled: view.fields.length >= VIEW_FIELD_LIMIT
|
|
1730
2159
|
})));
|
|
1731
2160
|
};
|
|
1732
|
-
|
|
1733
|
-
// packages/ui/react-ui-form/src/util/field.ts
|
|
1734
|
-
import { FormatEnum as FormatEnum3, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
|
|
1735
|
-
var parseValue = ({ type, format, value }) => {
|
|
1736
|
-
if (value === void 0 || value === null || value === "") {
|
|
1737
|
-
return void 0;
|
|
1738
|
-
}
|
|
1739
|
-
const parseScalar = (type2) => {
|
|
1740
|
-
switch (type2) {
|
|
1741
|
-
case TypeEnum.Boolean: {
|
|
1742
|
-
if (typeof value === "string") {
|
|
1743
|
-
const lowercaseValue = value.toLowerCase();
|
|
1744
|
-
if (lowercaseValue === "0" || lowercaseValue === "false") {
|
|
1745
|
-
return false;
|
|
1746
|
-
} else if (lowercaseValue === "1" || lowercaseValue === "true") {
|
|
1747
|
-
return true;
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
return Boolean(value);
|
|
1751
|
-
}
|
|
1752
|
-
case TypeEnum.Number: {
|
|
1753
|
-
const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
|
|
1754
|
-
const num = Number(cleaned);
|
|
1755
|
-
return Number.isNaN(num) ? null : num;
|
|
1756
|
-
}
|
|
1757
|
-
case TypeEnum.String:
|
|
1758
|
-
case TypeEnum.Ref:
|
|
1759
|
-
return String(value);
|
|
1760
|
-
default: {
|
|
1761
|
-
return value;
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
};
|
|
1765
|
-
if (!format) {
|
|
1766
|
-
return parseScalar(type);
|
|
1767
|
-
}
|
|
1768
|
-
switch (format) {
|
|
1769
|
-
case FormatEnum3.Boolean:
|
|
1770
|
-
return parseScalar(TypeEnum.Boolean);
|
|
1771
|
-
case FormatEnum3.Number:
|
|
1772
|
-
case FormatEnum3.Percent:
|
|
1773
|
-
case FormatEnum3.Currency:
|
|
1774
|
-
return parseScalar(TypeEnum.Number);
|
|
1775
|
-
case FormatEnum3.String:
|
|
1776
|
-
case FormatEnum3.Markdown: {
|
|
1777
|
-
return parseScalar(TypeEnum.String);
|
|
1778
|
-
}
|
|
1779
|
-
case FormatEnum3.Ref:
|
|
1780
|
-
throw new Error(`unexpected format: ${FormatEnum3.Ref}`);
|
|
1781
|
-
case FormatEnum3.DateTime:
|
|
1782
|
-
case FormatEnum3.Date:
|
|
1783
|
-
case FormatEnum3.Time:
|
|
1784
|
-
case FormatEnum3.Timestamp: {
|
|
1785
|
-
const date = new Date(value);
|
|
1786
|
-
return isNaN(date.getTime()) ? null : date;
|
|
1787
|
-
}
|
|
1788
|
-
case FormatEnum3.GeoPoint: {
|
|
1789
|
-
if (typeof value === "string") {
|
|
1790
|
-
const cleaned = value.replace(/[^0-9.,-]+/g, "");
|
|
1791
|
-
const parts = cleaned.split(",");
|
|
1792
|
-
if (parts.length === 2) {
|
|
1793
|
-
const lat = parseFloat(parts[0]);
|
|
1794
|
-
const long = parseFloat(parts[1]);
|
|
1795
|
-
if (!isNaN(lat) && !isNaN(long)) {
|
|
1796
|
-
return GeoLocation2.toGeoPoint({
|
|
1797
|
-
latitude: lat,
|
|
1798
|
-
longitude: long
|
|
1799
|
-
});
|
|
1800
|
-
}
|
|
1801
|
-
}
|
|
1802
|
-
}
|
|
1803
|
-
return [
|
|
1804
|
-
0,
|
|
1805
|
-
0
|
|
1806
|
-
];
|
|
1807
|
-
}
|
|
1808
|
-
default: {
|
|
1809
|
-
return value;
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
};
|
|
1813
|
-
var cellClassesForFieldType = ({ type, format }) => {
|
|
1814
|
-
if (!format) {
|
|
1815
|
-
switch (type) {
|
|
1816
|
-
case TypeEnum.Number:
|
|
1817
|
-
return [
|
|
1818
|
-
"text-right",
|
|
1819
|
-
"font-mono"
|
|
1820
|
-
];
|
|
1821
|
-
case TypeEnum.Boolean:
|
|
1822
|
-
return [
|
|
1823
|
-
"text-right",
|
|
1824
|
-
"font-mono"
|
|
1825
|
-
];
|
|
1826
|
-
case TypeEnum.String:
|
|
1827
|
-
return void 0;
|
|
1828
|
-
case TypeEnum.Ref:
|
|
1829
|
-
return void 0;
|
|
1830
|
-
default: {
|
|
1831
|
-
return void 0;
|
|
1832
|
-
}
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1835
|
-
switch (format) {
|
|
1836
|
-
case FormatEnum3.Markdown:
|
|
1837
|
-
return void 0;
|
|
1838
|
-
case FormatEnum3.Time:
|
|
1839
|
-
case FormatEnum3.Timestamp:
|
|
1840
|
-
case FormatEnum3.DateTime:
|
|
1841
|
-
case FormatEnum3.Date:
|
|
1842
|
-
case FormatEnum3.Duration:
|
|
1843
|
-
return [
|
|
1844
|
-
"font-mono",
|
|
1845
|
-
"text-right"
|
|
1846
|
-
];
|
|
1847
|
-
case FormatEnum3.Currency:
|
|
1848
|
-
return [
|
|
1849
|
-
"text-right"
|
|
1850
|
-
];
|
|
1851
|
-
case FormatEnum3.JSON:
|
|
1852
|
-
case FormatEnum3.DID:
|
|
1853
|
-
return [
|
|
1854
|
-
"font-mono"
|
|
1855
|
-
];
|
|
1856
|
-
default:
|
|
1857
|
-
return void 0;
|
|
1858
|
-
}
|
|
1859
|
-
};
|
|
1860
|
-
var pathNotUniqueError = (path) => ({
|
|
1861
|
-
path: "path",
|
|
1862
|
-
message: `'${path}' is already present`
|
|
1863
|
-
});
|
|
1864
|
-
|
|
1865
|
-
// packages/ui/react-ui-form/src/util/formatting.ts
|
|
1866
|
-
import { format as formatDate } from "date-fns/format";
|
|
1867
|
-
import { FormatEnum as FormatEnum4, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
|
|
1868
|
-
var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
|
|
1869
|
-
const formatScalar = (type2) => {
|
|
1870
|
-
switch (type2) {
|
|
1871
|
-
case TypeEnum2.Boolean:
|
|
1872
|
-
return value.toLocaleString().toUpperCase();
|
|
1873
|
-
case TypeEnum2.Number:
|
|
1874
|
-
return value.toLocaleString(locale);
|
|
1875
|
-
case TypeEnum2.String:
|
|
1876
|
-
case TypeEnum2.Ref:
|
|
1877
|
-
return String(value);
|
|
1878
|
-
default: {
|
|
1879
|
-
return String(value);
|
|
1880
|
-
}
|
|
1881
|
-
}
|
|
1882
|
-
};
|
|
1883
|
-
if (!format) {
|
|
1884
|
-
return formatScalar(type);
|
|
1885
|
-
}
|
|
1886
|
-
switch (format) {
|
|
1887
|
-
case FormatEnum4.Boolean: {
|
|
1888
|
-
return formatScalar(TypeEnum2.Boolean);
|
|
1889
|
-
}
|
|
1890
|
-
case FormatEnum4.Number: {
|
|
1891
|
-
return formatScalar(TypeEnum2.Number);
|
|
1892
|
-
}
|
|
1893
|
-
case FormatEnum4.String:
|
|
1894
|
-
case FormatEnum4.Ref: {
|
|
1895
|
-
return formatScalar(TypeEnum2.String);
|
|
1896
|
-
}
|
|
1897
|
-
case FormatEnum4.Percent: {
|
|
1898
|
-
return `${value * 100}%`;
|
|
1899
|
-
}
|
|
1900
|
-
case FormatEnum4.Currency: {
|
|
1901
|
-
return value.toLocaleString(locale, {
|
|
1902
|
-
style: "currency",
|
|
1903
|
-
currency: "USD",
|
|
1904
|
-
minimumFractionDigits: 2,
|
|
1905
|
-
maximumFractionDigits: 2
|
|
1906
|
-
});
|
|
1907
|
-
}
|
|
1908
|
-
case FormatEnum4.Date: {
|
|
1909
|
-
try {
|
|
1910
|
-
return formatDate(new Date(value), "yyyy-MM-dd");
|
|
1911
|
-
} catch (error) {
|
|
1912
|
-
return "Invalid Date";
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
1915
|
-
case FormatEnum4.Time: {
|
|
1916
|
-
try {
|
|
1917
|
-
return formatDate(new Date(value), "HH:mm:ss");
|
|
1918
|
-
} catch (error) {
|
|
1919
|
-
return "Invalid Time";
|
|
1920
|
-
}
|
|
1921
|
-
}
|
|
1922
|
-
case FormatEnum4.DateTime: {
|
|
1923
|
-
try {
|
|
1924
|
-
return formatDate(new Date(value), "yyyy-MM-dd HH:mm:ss");
|
|
1925
|
-
} catch (error) {
|
|
1926
|
-
return "Invalid DateTime";
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
case FormatEnum4.GeoPoint: {
|
|
1930
|
-
if (value === null || value === void 0) {
|
|
1931
|
-
return "";
|
|
1932
|
-
}
|
|
1933
|
-
if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
|
|
1934
|
-
const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
|
|
1935
|
-
return `${latitude},${longitude}`;
|
|
1936
|
-
}
|
|
1937
|
-
return String(value);
|
|
1938
|
-
}
|
|
1939
|
-
default: {
|
|
1940
|
-
if (value === null || value === "undefined") {
|
|
1941
|
-
return "";
|
|
1942
|
-
}
|
|
1943
|
-
return String(value);
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
};
|
|
1947
|
-
var formatForEditing = ({ type, format, value, locale = void 0 }) => {
|
|
1948
|
-
const formatScalar = (type2) => {
|
|
1949
|
-
switch (type2) {
|
|
1950
|
-
case TypeEnum2.Boolean:
|
|
1951
|
-
case TypeEnum2.Number:
|
|
1952
|
-
case TypeEnum2.String:
|
|
1953
|
-
case TypeEnum2.Ref:
|
|
1954
|
-
return String(value);
|
|
1955
|
-
default:
|
|
1956
|
-
return String(value);
|
|
1957
|
-
}
|
|
1958
|
-
};
|
|
1959
|
-
if (!format) {
|
|
1960
|
-
return formatScalar(type);
|
|
1961
|
-
}
|
|
1962
|
-
switch (format) {
|
|
1963
|
-
case FormatEnum4.Boolean:
|
|
1964
|
-
case FormatEnum4.Number:
|
|
1965
|
-
case FormatEnum4.String:
|
|
1966
|
-
case FormatEnum4.Ref: {
|
|
1967
|
-
return formatScalar(type);
|
|
1968
|
-
}
|
|
1969
|
-
case FormatEnum4.Percent: {
|
|
1970
|
-
return String(value * 100);
|
|
1971
|
-
}
|
|
1972
|
-
case FormatEnum4.Currency: {
|
|
1973
|
-
return String(value);
|
|
1974
|
-
}
|
|
1975
|
-
case FormatEnum4.DateTime: {
|
|
1976
|
-
const date = new Date(value);
|
|
1977
|
-
return date.toISOString();
|
|
1978
|
-
}
|
|
1979
|
-
case FormatEnum4.Date: {
|
|
1980
|
-
const date = new Date(value);
|
|
1981
|
-
return date.toISOString().split("T")[0];
|
|
1982
|
-
}
|
|
1983
|
-
case FormatEnum4.Time: {
|
|
1984
|
-
const date = new Date(value);
|
|
1985
|
-
return date.toISOString().split("T")[1].split(".")[0];
|
|
1986
|
-
}
|
|
1987
|
-
case FormatEnum4.GeoPoint: {
|
|
1988
|
-
if (value === null || value === void 0) {
|
|
1989
|
-
return "";
|
|
1990
|
-
}
|
|
1991
|
-
if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
|
|
1992
|
-
const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
|
|
1993
|
-
return `${latitude},${longitude}`;
|
|
1994
|
-
}
|
|
1995
|
-
return String(value);
|
|
1996
|
-
}
|
|
1997
|
-
default: {
|
|
1998
|
-
return String(value);
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
};
|
|
2002
2161
|
export {
|
|
2003
2162
|
BooleanInput,
|
|
2004
2163
|
ControlFrame,
|
|
@@ -2026,14 +2185,18 @@ export {
|
|
|
2026
2185
|
ViewEditor,
|
|
2027
2186
|
cellClassesForFieldType,
|
|
2028
2187
|
controlItemClasses,
|
|
2188
|
+
findArrayElementType,
|
|
2029
2189
|
formatForDisplay,
|
|
2030
2190
|
formatForEditing,
|
|
2191
|
+
getRefProps,
|
|
2031
2192
|
parseValue,
|
|
2032
2193
|
pathNotUniqueError,
|
|
2033
2194
|
translations_default as translations,
|
|
2034
2195
|
useForm,
|
|
2035
2196
|
useFormContext,
|
|
2036
2197
|
useFormValues,
|
|
2037
|
-
useInputProps
|
|
2198
|
+
useInputProps,
|
|
2199
|
+
useQueryRefOptions,
|
|
2200
|
+
useRefQueryLookupHandler
|
|
2038
2201
|
};
|
|
2039
2202
|
//# sourceMappingURL=index.mjs.map
|