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