@dxos/react-ui-form 0.8.2-main.f11618f → 0.8.2-main.fbd8ed0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +731 -573
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +748 -598
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +731 -573
- 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 +2 -2
- 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 +26 -25
- package/src/components/ControlSection/ControlSection.stories.tsx +1 -1
- package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
- package/src/components/Form/ArrayField.tsx +10 -16
- 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 +147 -101
- 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 +5 -4
- package/src/components/ViewEditor/ViewEditor.tsx +23 -20
- package/src/components/deprecated/Form.tsx +6 -6
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useForm.ts +4 -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 useMemo7, 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 }) => {
|
|
@@ -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
|
});
|
|
@@ -736,7 +741,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
736
741
|
} catch (err) {
|
|
737
742
|
log.catch(err, void 0, {
|
|
738
743
|
F: __dxlog_file,
|
|
739
|
-
L:
|
|
744
|
+
L: 213,
|
|
740
745
|
S: void 0,
|
|
741
746
|
C: (f, a) => f(...a)
|
|
742
747
|
});
|
|
@@ -807,7 +812,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
807
812
|
var createKeySet = (obj, value) => {
|
|
808
813
|
invariant(obj, void 0, {
|
|
809
814
|
F: __dxlog_file,
|
|
810
|
-
L:
|
|
815
|
+
L: 275,
|
|
811
816
|
S: void 0,
|
|
812
817
|
A: [
|
|
813
818
|
"obj",
|
|
@@ -829,6 +834,81 @@ var flatMap = (errors) => {
|
|
|
829
834
|
}, {});
|
|
830
835
|
};
|
|
831
836
|
|
|
837
|
+
// packages/ui/react-ui-form/src/hooks/useRefQueryLookupHandler.ts
|
|
838
|
+
import { useCallback as useCallback5 } from "react";
|
|
839
|
+
import { getDXN } from "@dxos/echo-schema";
|
|
840
|
+
import { Filter } from "@dxos/react-client/echo";
|
|
841
|
+
import { isNonNullable } from "@dxos/util";
|
|
842
|
+
var useRefQueryLookupHandler = ({ space }) => {
|
|
843
|
+
const handleRefQueryLookup = useCallback5(async (typeInfo) => {
|
|
844
|
+
if (!space) {
|
|
845
|
+
return [];
|
|
846
|
+
}
|
|
847
|
+
const query = space.db.query(Filter.typename(typeInfo.typename));
|
|
848
|
+
const { objects } = await query.run();
|
|
849
|
+
return objects.map((object) => {
|
|
850
|
+
const dxn = getDXN(object);
|
|
851
|
+
if (!dxn) {
|
|
852
|
+
return void 0;
|
|
853
|
+
}
|
|
854
|
+
const item = {
|
|
855
|
+
dxn,
|
|
856
|
+
label: object?.name ?? object?.id ?? ""
|
|
857
|
+
};
|
|
858
|
+
return item;
|
|
859
|
+
}).filter(isNonNullable);
|
|
860
|
+
}, [
|
|
861
|
+
space
|
|
862
|
+
]);
|
|
863
|
+
return handleRefQueryLookup;
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
// packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts
|
|
867
|
+
import { useEffect as useEffect5, useState as useState4 } from "react";
|
|
868
|
+
import { log as log2 } from "@dxos/log";
|
|
869
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts";
|
|
870
|
+
var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
|
|
871
|
+
const [options, setOptions] = useState4([]);
|
|
872
|
+
const [loading, setLoading] = useState4(false);
|
|
873
|
+
useEffect5(() => {
|
|
874
|
+
if (!refTypeInfo || !onQueryRefOptions) {
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
const fetchOptions = async () => {
|
|
878
|
+
setLoading(true);
|
|
879
|
+
try {
|
|
880
|
+
const fetchedOptions = await onQueryRefOptions(refTypeInfo);
|
|
881
|
+
setOptions(fetchedOptions.map((option) => {
|
|
882
|
+
const dxn = option.dxn.toString();
|
|
883
|
+
return {
|
|
884
|
+
id: dxn,
|
|
885
|
+
label: option.label ?? dxn,
|
|
886
|
+
hue: "neutral"
|
|
887
|
+
};
|
|
888
|
+
}));
|
|
889
|
+
} catch (error) {
|
|
890
|
+
log2.error("Failed to fetch ref options:", error, {
|
|
891
|
+
F: __dxlog_file2,
|
|
892
|
+
L: 42,
|
|
893
|
+
S: void 0,
|
|
894
|
+
C: (f, a) => f(...a)
|
|
895
|
+
});
|
|
896
|
+
setOptions([]);
|
|
897
|
+
} finally {
|
|
898
|
+
setLoading(false);
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
void fetchOptions();
|
|
902
|
+
}, [
|
|
903
|
+
refTypeInfo,
|
|
904
|
+
onQueryRefOptions
|
|
905
|
+
]);
|
|
906
|
+
return {
|
|
907
|
+
options,
|
|
908
|
+
loading
|
|
909
|
+
};
|
|
910
|
+
};
|
|
911
|
+
|
|
832
912
|
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
833
913
|
var FormContext = /* @__PURE__ */ createContext(void 0);
|
|
834
914
|
var useFormContext = () => {
|
|
@@ -859,7 +939,7 @@ var useInputProps = (path = []) => {
|
|
|
859
939
|
};
|
|
860
940
|
var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
|
|
861
941
|
const form = useForm(formOptions);
|
|
862
|
-
|
|
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,252 +1000,587 @@ 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
1005
|
import React12, { useMemo as useMemo5 } from "react";
|
|
926
|
-
import {
|
|
927
|
-
import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
|
|
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 } 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, RefImpl } 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: 68,
|
|
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 (formValue instanceof RefImpl) {
|
|
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
|
-
label,
|
|
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) => {
|
|
1152
|
-
switch (format) {
|
|
1153
|
-
case FormatEnum.GeoPoint:
|
|
1154
|
-
return GeoPointInput;
|
|
1155
|
-
case FormatEnum.Markdown:
|
|
1156
|
-
return MarkdownInput;
|
|
1053
|
+
if (!format) {
|
|
1054
|
+
return parseScalar(type);
|
|
1157
1055
|
}
|
|
1158
|
-
switch (
|
|
1159
|
-
case
|
|
1160
|
-
return
|
|
1161
|
-
case
|
|
1162
|
-
|
|
1163
|
-
case
|
|
1164
|
-
return
|
|
1056
|
+
switch (format) {
|
|
1057
|
+
case FormatEnum.Boolean:
|
|
1058
|
+
return parseScalar(TypeEnum.Boolean);
|
|
1059
|
+
case FormatEnum.Number:
|
|
1060
|
+
case FormatEnum.Percent:
|
|
1061
|
+
case FormatEnum.Currency:
|
|
1062
|
+
return parseScalar(TypeEnum.Number);
|
|
1063
|
+
case FormatEnum.String:
|
|
1064
|
+
case FormatEnum.Markdown: {
|
|
1065
|
+
return parseScalar(TypeEnum.String);
|
|
1066
|
+
}
|
|
1067
|
+
case FormatEnum.Ref:
|
|
1068
|
+
throw new Error(`unexpected format: ${FormatEnum.Ref}`);
|
|
1069
|
+
case FormatEnum.DateTime:
|
|
1070
|
+
case FormatEnum.Date:
|
|
1071
|
+
case FormatEnum.Time:
|
|
1072
|
+
case FormatEnum.Timestamp: {
|
|
1073
|
+
const date = new Date(value);
|
|
1074
|
+
return isNaN(date.getTime()) ? null : date;
|
|
1075
|
+
}
|
|
1076
|
+
case FormatEnum.GeoPoint: {
|
|
1077
|
+
if (typeof value === "string") {
|
|
1078
|
+
const cleaned = value.replace(/[^0-9.,-]+/g, "");
|
|
1079
|
+
const parts = cleaned.split(",");
|
|
1080
|
+
if (parts.length === 2) {
|
|
1081
|
+
const lat = parseFloat(parts[0]);
|
|
1082
|
+
const long = parseFloat(parts[1]);
|
|
1083
|
+
if (!isNaN(lat) && !isNaN(long)) {
|
|
1084
|
+
return GeoLocation2.toGeoPoint({
|
|
1085
|
+
latitude: lat,
|
|
1086
|
+
longitude: long
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
return [
|
|
1092
|
+
0,
|
|
1093
|
+
0
|
|
1094
|
+
];
|
|
1095
|
+
}
|
|
1096
|
+
default: {
|
|
1097
|
+
return value;
|
|
1098
|
+
}
|
|
1165
1099
|
}
|
|
1166
1100
|
};
|
|
1167
|
-
|
|
1168
|
-
|
|
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 getDefaultValue = () => type === "object" && elementType ? getDefaultObjectValue(elementType) : SimpleType.getDefaultValue(type);
|
|
1358
|
+
const handleAdd = useCallback6(() => {
|
|
1359
|
+
inputProps.onValueChange(type, [
|
|
1360
|
+
...values,
|
|
1361
|
+
getDefaultValue()
|
|
1362
|
+
]);
|
|
1363
|
+
}, [
|
|
1364
|
+
type,
|
|
1365
|
+
elementType,
|
|
1366
|
+
inputProps,
|
|
1367
|
+
values
|
|
1368
|
+
]);
|
|
1369
|
+
const handleRemove = useCallback6((index) => {
|
|
1370
|
+
const newValues = values.filter((_, i) => i !== index);
|
|
1371
|
+
inputProps.onValueChange(type, newValues);
|
|
1372
|
+
}, [
|
|
1373
|
+
type,
|
|
1374
|
+
inputProps,
|
|
1375
|
+
values
|
|
1376
|
+
]);
|
|
1377
|
+
if (!elementType) {
|
|
1378
|
+
return null;
|
|
1379
|
+
}
|
|
1380
|
+
return /* @__PURE__ */ React10.createElement("div", {
|
|
1381
|
+
role: "none",
|
|
1382
|
+
className: mx6(padding)
|
|
1383
|
+
}, /* @__PURE__ */ React10.createElement(InputHeader, null, label), /* @__PURE__ */ React10.createElement("div", {
|
|
1384
|
+
role: "none",
|
|
1385
|
+
className: "flex flex-col gap-1"
|
|
1386
|
+
}, values.map((_value, index) => /* @__PURE__ */ React10.createElement("div", {
|
|
1387
|
+
key: index,
|
|
1388
|
+
role: "none",
|
|
1389
|
+
className: "flex items-center gap-1"
|
|
1390
|
+
}, /* @__PURE__ */ React10.createElement("div", {
|
|
1391
|
+
role: "none",
|
|
1392
|
+
className: "flex-1"
|
|
1393
|
+
}, /* @__PURE__ */ React10.createElement(FormField, {
|
|
1394
|
+
property: {
|
|
1395
|
+
...property,
|
|
1396
|
+
array: false,
|
|
1397
|
+
ast: elementType
|
|
1398
|
+
},
|
|
1399
|
+
path: [
|
|
1400
|
+
...path ?? [],
|
|
1401
|
+
index
|
|
1402
|
+
],
|
|
1403
|
+
readonly,
|
|
1404
|
+
inline: true,
|
|
1405
|
+
Custom,
|
|
1406
|
+
lookupComponent
|
|
1407
|
+
})), /* @__PURE__ */ React10.createElement(IconButton3, {
|
|
1408
|
+
icon: "ph--trash--regular",
|
|
1409
|
+
iconOnly: true,
|
|
1410
|
+
label: t("button remove"),
|
|
1411
|
+
onClick: () => handleRemove(index)
|
|
1412
|
+
})))), /* @__PURE__ */ React10.createElement("div", {
|
|
1413
|
+
role: "none",
|
|
1414
|
+
className: "flex justify-between items-center plb-1"
|
|
1415
|
+
}, /* @__PURE__ */ React10.createElement(IconButton3, {
|
|
1416
|
+
icon: "ph--plus--regular",
|
|
1417
|
+
iconOnly: true,
|
|
1418
|
+
label: t("button add"),
|
|
1419
|
+
onClick: handleAdd
|
|
1420
|
+
})));
|
|
1421
|
+
};
|
|
1422
|
+
|
|
1423
|
+
// packages/ui/react-ui-form/src/components/Form/RefField.tsx
|
|
1424
|
+
import React11, { useCallback as useCallback7, useMemo as useMemo4 } from "react";
|
|
1425
|
+
import { Expando, getTypeAnnotation, Ref, ReferenceAnnotationId as ReferenceAnnotationId2 } from "@dxos/echo-schema";
|
|
1426
|
+
import { findAnnotation as findAnnotation2 } from "@dxos/effect";
|
|
1427
|
+
import { DXN } from "@dxos/keys";
|
|
1428
|
+
import { Input as Input7 } from "@dxos/react-ui";
|
|
1429
|
+
import { TagPicker } from "@dxos/react-ui-tag-picker";
|
|
1430
|
+
import { isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
1431
|
+
var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, getValue: getValue3, onBlur, onQueryRefOptions, onValueChange, ...restInputProps }) => {
|
|
1432
|
+
const refTypeInfo = useMemo4(() => ast ? findAnnotation2(ast, ReferenceAnnotationId2) : void 0, [
|
|
1433
|
+
ast
|
|
1434
|
+
]);
|
|
1435
|
+
const { options: availableOptions, loading: _loading } = useQueryRefOptions({
|
|
1436
|
+
refTypeInfo,
|
|
1437
|
+
onQueryRefOptions
|
|
1438
|
+
});
|
|
1439
|
+
if (refTypeInfo && refTypeInfo?.typename === getTypeAnnotation(Expando)?.typename || !onQueryRefOptions) {
|
|
1440
|
+
return /* @__PURE__ */ React11.createElement(RefFieldFallback, {
|
|
1441
|
+
type,
|
|
1442
|
+
label,
|
|
1443
|
+
placeholder,
|
|
1444
|
+
disabled,
|
|
1445
|
+
inputOnly,
|
|
1446
|
+
getValue: getValue3,
|
|
1447
|
+
onBlur,
|
|
1448
|
+
onValueChange,
|
|
1449
|
+
...restInputProps
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
const handleGetValue = useCallback7(() => {
|
|
1453
|
+
const formValue = getValue3();
|
|
1454
|
+
const unknownToRefOption = (val) => {
|
|
1455
|
+
if (Ref.isRef(val)) {
|
|
1456
|
+
const dxnString = val.dxn.toString();
|
|
1457
|
+
const matchingOption = availableOptions.find((option2) => option2.id === dxnString);
|
|
1458
|
+
if (matchingOption) {
|
|
1459
|
+
return matchingOption;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
return void 0;
|
|
1463
|
+
};
|
|
1464
|
+
if (array && Array.isArray(formValue)) {
|
|
1465
|
+
return formValue.map(unknownToRefOption).filter(isNonNullable2) ?? [];
|
|
1466
|
+
}
|
|
1467
|
+
const option = unknownToRefOption(formValue);
|
|
1468
|
+
if (option) {
|
|
1469
|
+
return [
|
|
1470
|
+
option
|
|
1471
|
+
];
|
|
1472
|
+
}
|
|
1473
|
+
return [];
|
|
1474
|
+
}, [
|
|
1475
|
+
getValue3,
|
|
1476
|
+
availableOptions,
|
|
1477
|
+
array
|
|
1478
|
+
]);
|
|
1479
|
+
const handleSearch = useCallback7((text, ids) => availableOptions.filter((option) => !ids.includes(option.id)).filter((option) => option.label.toLowerCase().includes(text.toLowerCase())).map((option) => ({
|
|
1480
|
+
id: option.id,
|
|
1481
|
+
label: option.label,
|
|
1482
|
+
hue: option.hue
|
|
1483
|
+
})), [
|
|
1484
|
+
availableOptions
|
|
1485
|
+
]);
|
|
1486
|
+
const handleUpdate = useCallback7((ids) => {
|
|
1487
|
+
if (ids.length === 0) {
|
|
1488
|
+
onValueChange("object", void 0);
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
const refs = ids.map((id) => {
|
|
1492
|
+
const item = availableOptions.find((option) => option.id === id);
|
|
1493
|
+
if (item) {
|
|
1494
|
+
const dxn = DXN.parse(item.id);
|
|
1495
|
+
return Ref.fromDXN(dxn);
|
|
1496
|
+
}
|
|
1497
|
+
return null;
|
|
1498
|
+
}).filter(isNonNullable2);
|
|
1499
|
+
if (array) {
|
|
1500
|
+
onValueChange("object", refs);
|
|
1501
|
+
} else {
|
|
1502
|
+
onValueChange("object", refs[0]);
|
|
1503
|
+
}
|
|
1504
|
+
}, [
|
|
1505
|
+
availableOptions,
|
|
1506
|
+
array,
|
|
1507
|
+
onValueChange
|
|
1508
|
+
]);
|
|
1509
|
+
const tagPickerMode = useMemo4(() => array ? "multi-select" : "single-select", [
|
|
1510
|
+
array
|
|
1511
|
+
]);
|
|
1512
|
+
if (!refTypeInfo) {
|
|
1513
|
+
return null;
|
|
1514
|
+
}
|
|
1515
|
+
const { status, error } = restInputProps.getStatus();
|
|
1516
|
+
return /* @__PURE__ */ React11.createElement(Input7.Root, {
|
|
1517
|
+
validationValence: status
|
|
1518
|
+
}, !inputOnly && /* @__PURE__ */ React11.createElement(InputHeader, {
|
|
1519
|
+
error
|
|
1520
|
+
}, /* @__PURE__ */ React11.createElement(Input7.Label, null, label)), /* @__PURE__ */ React11.createElement("div", {
|
|
1521
|
+
"data-no-submit": true
|
|
1522
|
+
}, /* @__PURE__ */ React11.createElement(TagPicker, {
|
|
1523
|
+
items: handleGetValue(),
|
|
1524
|
+
mode: tagPickerMode,
|
|
1525
|
+
onBlur: (event) => onBlur(event),
|
|
1526
|
+
onUpdate: handleUpdate,
|
|
1527
|
+
onSearch: handleSearch,
|
|
1528
|
+
classNames: "rounded-sm bg-input p-1.5"
|
|
1529
|
+
})), inputOnly && /* @__PURE__ */ React11.createElement(Input7.DescriptionAndValidation, null, error));
|
|
1530
|
+
};
|
|
1531
|
+
var RefFieldFallback = ({ type, label, disabled, placeholder, inputOnly, getValue: getValue3, onValueChange, ...restInputProps }) => {
|
|
1532
|
+
const handleOnValueChange = (_type, dxnString) => {
|
|
1533
|
+
const dxn = DXN.tryParse(dxnString);
|
|
1534
|
+
if (dxn) {
|
|
1535
|
+
onValueChange?.("object", Ref.fromDXN(dxn));
|
|
1536
|
+
} else if (dxnString === "") {
|
|
1537
|
+
onValueChange?.("object", void 0);
|
|
1538
|
+
} else {
|
|
1539
|
+
onValueChange?.("string", dxnString);
|
|
1540
|
+
}
|
|
1541
|
+
};
|
|
1542
|
+
const handleGetValue = () => {
|
|
1543
|
+
const formValue = getValue3();
|
|
1544
|
+
if (typeof formValue === "string") {
|
|
1545
|
+
return formValue;
|
|
1546
|
+
}
|
|
1547
|
+
if (Ref.isRef(formValue)) {
|
|
1548
|
+
return formValue.dxn.toString();
|
|
1549
|
+
}
|
|
1550
|
+
return void 0;
|
|
1551
|
+
};
|
|
1552
|
+
return /* @__PURE__ */ React11.createElement(TextInput, {
|
|
1553
|
+
type,
|
|
1554
|
+
label,
|
|
1555
|
+
disabled,
|
|
1556
|
+
placeholder,
|
|
1557
|
+
inputOnly,
|
|
1558
|
+
getValue: handleGetValue,
|
|
1559
|
+
onValueChange: handleOnValueChange,
|
|
1560
|
+
...restInputProps
|
|
1561
|
+
});
|
|
1562
|
+
};
|
|
1563
|
+
|
|
1564
|
+
// packages/ui/react-ui-form/src/components/Form/factory.tsx
|
|
1565
|
+
import { FormatEnum as FormatEnum4 } from "@dxos/echo-schema";
|
|
1566
|
+
var getInputComponent = (type, format) => {
|
|
1567
|
+
switch (format) {
|
|
1568
|
+
case FormatEnum4.GeoPoint:
|
|
1569
|
+
return GeoPointInput;
|
|
1570
|
+
case FormatEnum4.Markdown:
|
|
1571
|
+
return MarkdownInput;
|
|
1572
|
+
}
|
|
1573
|
+
switch (type) {
|
|
1574
|
+
case "string":
|
|
1575
|
+
return TextInput;
|
|
1576
|
+
case "number":
|
|
1577
|
+
return NumberInput;
|
|
1578
|
+
case "boolean":
|
|
1579
|
+
return BooleanInput;
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
|
|
1583
|
+
// packages/ui/react-ui-form/src/components/Form/FormContent.tsx
|
|
1169
1584
|
var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupComponent, Custom }) => {
|
|
1170
1585
|
const inputProps = useInputProps(path);
|
|
1171
1586
|
const { ast, name, type, format, title, description, options, examples, array } = property;
|
|
@@ -1179,7 +1594,7 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
|
|
|
1179
1594
|
]);
|
|
1180
1595
|
const FoundComponent = lookupComponent?.({
|
|
1181
1596
|
prop: name,
|
|
1182
|
-
schema:
|
|
1597
|
+
schema: Schema.make(ast),
|
|
1183
1598
|
inputProps: {
|
|
1184
1599
|
type,
|
|
1185
1600
|
format,
|
|
@@ -1207,6 +1622,21 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
|
|
|
1207
1622
|
...inputProps
|
|
1208
1623
|
});
|
|
1209
1624
|
}
|
|
1625
|
+
const refProps = getRefProps(property);
|
|
1626
|
+
if (refProps) {
|
|
1627
|
+
return /* @__PURE__ */ React12.createElement(RefField, {
|
|
1628
|
+
ast: refProps.ast,
|
|
1629
|
+
array: refProps.isArray,
|
|
1630
|
+
type,
|
|
1631
|
+
format,
|
|
1632
|
+
label,
|
|
1633
|
+
placeholder,
|
|
1634
|
+
disabled: readonly,
|
|
1635
|
+
inputOnly: inline,
|
|
1636
|
+
onQueryRefOptions,
|
|
1637
|
+
...inputProps
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1210
1640
|
if (array) {
|
|
1211
1641
|
return /* @__PURE__ */ React12.createElement(ArrayField, {
|
|
1212
1642
|
property,
|
|
@@ -1247,28 +1677,16 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
|
|
|
1247
1677
|
...inputProps
|
|
1248
1678
|
}));
|
|
1249
1679
|
}
|
|
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
1680
|
if (type === "object") {
|
|
1263
|
-
const baseNode =
|
|
1264
|
-
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) :
|
|
1681
|
+
const baseNode = findNode3(ast, isDiscriminatedUnion2);
|
|
1682
|
+
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode3(ast, SchemaAST4.isTypeLiteral);
|
|
1265
1683
|
if (typeLiteral) {
|
|
1266
1684
|
return /* @__PURE__ */ React12.createElement("div", {
|
|
1267
1685
|
role: "none"
|
|
1268
1686
|
}, !inline && /* @__PURE__ */ React12.createElement("h3", {
|
|
1269
1687
|
className: "text-lg mbs-2 mbe-1"
|
|
1270
1688
|
}, label), /* @__PURE__ */ React12.createElement(FormFields, {
|
|
1271
|
-
schema:
|
|
1689
|
+
schema: Schema.make(typeLiteral),
|
|
1272
1690
|
path,
|
|
1273
1691
|
readonly,
|
|
1274
1692
|
onQueryRefOptions,
|
|
@@ -1394,7 +1812,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1394
1812
|
const [{ fieldSchema }, setFieldSchema] = useState5({
|
|
1395
1813
|
fieldSchema: getFormatSchema(props?.format)
|
|
1396
1814
|
});
|
|
1397
|
-
const handleValuesChanged =
|
|
1815
|
+
const handleValuesChanged = useCallback8((_props) => {
|
|
1398
1816
|
setFieldSchema((prev) => {
|
|
1399
1817
|
const fieldSchema2 = getFormatSchema(_props.format);
|
|
1400
1818
|
if (prev.fieldSchema === fieldSchema2) {
|
|
@@ -1429,7 +1847,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1429
1847
|
props.format,
|
|
1430
1848
|
props.referenceSchema
|
|
1431
1849
|
]);
|
|
1432
|
-
const handleValidate =
|
|
1850
|
+
const handleValidate = useCallback8(({ property }) => {
|
|
1433
1851
|
if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
|
|
1434
1852
|
return [
|
|
1435
1853
|
{
|
|
@@ -1442,7 +1860,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1442
1860
|
view.fields,
|
|
1443
1861
|
field
|
|
1444
1862
|
]);
|
|
1445
|
-
const handleSave =
|
|
1863
|
+
const handleSave = useCallback8((props2) => {
|
|
1446
1864
|
projection.setFieldProjection({
|
|
1447
1865
|
field,
|
|
1448
1866
|
props: props2
|
|
@@ -1453,7 +1871,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1453
1871
|
field,
|
|
1454
1872
|
onSave
|
|
1455
1873
|
]);
|
|
1456
|
-
const handleCancel =
|
|
1874
|
+
const handleCancel = useCallback8(() => {
|
|
1457
1875
|
requestAnimationFrame(() => onCancel?.());
|
|
1458
1876
|
onSave();
|
|
1459
1877
|
}, [
|
|
@@ -1462,7 +1880,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1462
1880
|
const Custom = useMemo7(() => ({
|
|
1463
1881
|
["format"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
|
|
1464
1882
|
...props2,
|
|
1465
|
-
options: FormatEnums.filter((value) => value !==
|
|
1883
|
+
options: FormatEnums.filter((value) => value !== FormatEnum5.None).map((value) => ({
|
|
1466
1884
|
value,
|
|
1467
1885
|
label: t(`format ${value}`)
|
|
1468
1886
|
}))
|
|
@@ -1485,7 +1903,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1485
1903
|
schemas,
|
|
1486
1904
|
referenceSchema
|
|
1487
1905
|
]);
|
|
1488
|
-
const propIsNotType =
|
|
1906
|
+
const propIsNotType = useCallback8((props2) => props2.filter((p) => p.name !== "type"), []);
|
|
1489
1907
|
if (!fieldSchema) {
|
|
1490
1908
|
log3.warn("invalid format", {
|
|
1491
1909
|
props
|
|
@@ -1516,8 +1934,9 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1516
1934
|
};
|
|
1517
1935
|
|
|
1518
1936
|
// packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
|
|
1519
|
-
import
|
|
1520
|
-
import {
|
|
1937
|
+
import { Schema as Schema2, SchemaAST as SchemaAST5 } from "effect";
|
|
1938
|
+
import React15, { useCallback as useCallback9, useMemo as useMemo8, useState as useState6 } from "react";
|
|
1939
|
+
import { Format, isMutable, toJsonSchema } from "@dxos/echo-schema";
|
|
1521
1940
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1522
1941
|
import { IconButton as IconButton4, useTranslation as useTranslation7 } from "@dxos/react-ui";
|
|
1523
1942
|
import { List as List2 } from "@dxos/react-ui-list";
|
|
@@ -1525,21 +1944,22 @@ import { ghostHover, inputTextLabel, mx as mx9 } from "@dxos/react-ui-theme";
|
|
|
1525
1944
|
import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1526
1945
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
|
|
1527
1946
|
var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
|
|
1528
|
-
var ViewMetaSchema =
|
|
1529
|
-
name:
|
|
1530
|
-
[
|
|
1947
|
+
var ViewMetaSchema = Schema2.Struct({
|
|
1948
|
+
name: Schema2.String.annotations({
|
|
1949
|
+
[SchemaAST5.TitleAnnotationId]: "View"
|
|
1531
1950
|
}),
|
|
1532
1951
|
typename: Format.URL.annotations({
|
|
1533
|
-
[
|
|
1952
|
+
[SchemaAST5.TitleAnnotationId]: "Typename"
|
|
1534
1953
|
})
|
|
1535
|
-
}).pipe(
|
|
1954
|
+
}).pipe(Schema2.mutable);
|
|
1536
1955
|
var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
|
|
1537
1956
|
const { t } = useTranslation7(translationKey);
|
|
1538
|
-
const projection = useMemo8(() => new ViewProjection(schema
|
|
1957
|
+
const projection = useMemo8(() => new ViewProjection(toJsonSchema(schema), view), [
|
|
1539
1958
|
schema,
|
|
1540
1959
|
view
|
|
1541
1960
|
]);
|
|
1542
1961
|
const [field, setField] = useState6();
|
|
1962
|
+
const immutable = readonly || !isMutable(schema);
|
|
1543
1963
|
const viewValues = useMemo8(() => {
|
|
1544
1964
|
return {
|
|
1545
1965
|
name: view.name,
|
|
@@ -1550,16 +1970,16 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1550
1970
|
}, [
|
|
1551
1971
|
view
|
|
1552
1972
|
]);
|
|
1553
|
-
const handleSelect =
|
|
1973
|
+
const handleSelect = useCallback9((field2) => {
|
|
1554
1974
|
setField((f) => f === field2 ? void 0 : field2);
|
|
1555
1975
|
}, []);
|
|
1556
|
-
const handleAdd =
|
|
1557
|
-
invariant3(!
|
|
1976
|
+
const handleAdd = useCallback9(() => {
|
|
1977
|
+
invariant3(!immutable, void 0, {
|
|
1558
1978
|
F: __dxlog_file5,
|
|
1559
|
-
L:
|
|
1979
|
+
L: 78,
|
|
1560
1980
|
S: void 0,
|
|
1561
1981
|
A: [
|
|
1562
|
-
"!
|
|
1982
|
+
"!immutable",
|
|
1563
1983
|
""
|
|
1564
1984
|
]
|
|
1565
1985
|
});
|
|
@@ -1569,13 +1989,13 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1569
1989
|
schema,
|
|
1570
1990
|
view
|
|
1571
1991
|
]);
|
|
1572
|
-
const handleUpdate =
|
|
1573
|
-
invariant3(!
|
|
1992
|
+
const handleUpdate = useCallback9(({ name, typename }) => {
|
|
1993
|
+
invariant3(!immutable, void 0, {
|
|
1574
1994
|
F: __dxlog_file5,
|
|
1575
|
-
L:
|
|
1995
|
+
L: 85,
|
|
1576
1996
|
S: void 0,
|
|
1577
1997
|
A: [
|
|
1578
|
-
"!
|
|
1998
|
+
"!immutable",
|
|
1579
1999
|
""
|
|
1580
2000
|
]
|
|
1581
2001
|
});
|
|
@@ -1592,13 +2012,13 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1592
2012
|
view,
|
|
1593
2013
|
onTypenameChanged
|
|
1594
2014
|
]);
|
|
1595
|
-
const handleDelete =
|
|
1596
|
-
invariant3(!
|
|
2015
|
+
const handleDelete = useCallback9((fieldId) => {
|
|
2016
|
+
invariant3(!immutable, void 0, {
|
|
1597
2017
|
F: __dxlog_file5,
|
|
1598
|
-
L:
|
|
2018
|
+
L: 101,
|
|
1599
2019
|
S: void 0,
|
|
1600
2020
|
A: [
|
|
1601
|
-
"!
|
|
2021
|
+
"!immutable",
|
|
1602
2022
|
""
|
|
1603
2023
|
]
|
|
1604
2024
|
});
|
|
@@ -1611,13 +2031,13 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1611
2031
|
field,
|
|
1612
2032
|
onDelete
|
|
1613
2033
|
]);
|
|
1614
|
-
const handleMove =
|
|
1615
|
-
invariant3(!
|
|
2034
|
+
const handleMove = useCallback9((fromIndex, toIndex) => {
|
|
2035
|
+
invariant3(!immutable, void 0, {
|
|
1616
2036
|
F: __dxlog_file5,
|
|
1617
|
-
L:
|
|
2037
|
+
L: 113,
|
|
1618
2038
|
S: void 0,
|
|
1619
2039
|
A: [
|
|
1620
|
-
"!
|
|
2040
|
+
"!immutable",
|
|
1621
2041
|
""
|
|
1622
2042
|
]
|
|
1623
2043
|
});
|
|
@@ -1631,15 +2051,15 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1631
2051
|
schema,
|
|
1632
2052
|
view.fields
|
|
1633
2053
|
]);
|
|
1634
|
-
const handleClose =
|
|
2054
|
+
const handleClose = useCallback9(() => setField(void 0), []);
|
|
1635
2055
|
const hiddenProperties = projection.getHiddenProperties();
|
|
1636
|
-
const handleHide =
|
|
2056
|
+
const handleHide = useCallback9((fieldId) => {
|
|
1637
2057
|
setField(void 0);
|
|
1638
2058
|
projection.hideFieldProjection(fieldId);
|
|
1639
2059
|
}, [
|
|
1640
2060
|
projection
|
|
1641
2061
|
]);
|
|
1642
|
-
const handleShow =
|
|
2062
|
+
const handleShow = useCallback9((property) => {
|
|
1643
2063
|
setField(void 0);
|
|
1644
2064
|
projection.showFieldProjection(property);
|
|
1645
2065
|
}, [
|
|
@@ -1647,22 +2067,26 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1647
2067
|
]);
|
|
1648
2068
|
return /* @__PURE__ */ React15.createElement("div", {
|
|
1649
2069
|
role: "none",
|
|
1650
|
-
className: mx9("
|
|
2070
|
+
className: mx9("grid grid-rows-[1fr_1fr] min-bs-0", classNames)
|
|
1651
2071
|
}, /* @__PURE__ */ React15.createElement(Form, {
|
|
1652
2072
|
autoSave: true,
|
|
1653
2073
|
schema: ViewMetaSchema,
|
|
1654
2074
|
values: viewValues,
|
|
1655
|
-
onSave:
|
|
1656
|
-
|
|
2075
|
+
onSave: immutable ? void 0 : handleUpdate,
|
|
2076
|
+
classNames: "min-bs-0 overflow-y-auto"
|
|
2077
|
+
}), /* @__PURE__ */ React15.createElement("div", {
|
|
2078
|
+
role: "none",
|
|
2079
|
+
className: "border-bs border-separator min-bs-0 overflow-y-auto"
|
|
2080
|
+
}, /* @__PURE__ */ React15.createElement("div", {
|
|
1657
2081
|
role: "none",
|
|
1658
2082
|
className: "p-2"
|
|
1659
2083
|
}, /* @__PURE__ */ React15.createElement("label", {
|
|
1660
2084
|
className: mx9(inputTextLabel)
|
|
1661
2085
|
}, t("fields label"))), /* @__PURE__ */ React15.createElement(List2.Root, {
|
|
1662
2086
|
items: view.fields,
|
|
1663
|
-
isItem:
|
|
2087
|
+
isItem: Schema2.is(FieldSchema),
|
|
1664
2088
|
getId: (field2) => field2.id,
|
|
1665
|
-
onMove:
|
|
2089
|
+
onMove: immutable ? void 0 : handleMove
|
|
1666
2090
|
}, ({ items: fields }) => /* @__PURE__ */ React15.createElement(React15.Fragment, null, showHeading && /* @__PURE__ */ React15.createElement("div", {
|
|
1667
2091
|
role: "heading",
|
|
1668
2092
|
className: grid
|
|
@@ -1683,7 +2107,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1683
2107
|
icon: "ph--eye-slash--regular",
|
|
1684
2108
|
disabled: view.fields.length <= 1,
|
|
1685
2109
|
onClick: () => handleHide(field2.id)
|
|
1686
|
-
}), !
|
|
2110
|
+
}), !immutable && /* @__PURE__ */ React15.createElement(List2.ItemDeleteButton, {
|
|
1687
2111
|
icon: "ph--trash--regular",
|
|
1688
2112
|
disabled: view.fields.length <= 1,
|
|
1689
2113
|
onClick: () => handleDelete(field2.id)
|
|
@@ -1718,281 +2142,11 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1718
2142
|
}, /* @__PURE__ */ React15.createElement(IconButton4, {
|
|
1719
2143
|
icon: "ph--plus--regular",
|
|
1720
2144
|
label: t("button add property"),
|
|
1721
|
-
onClick:
|
|
2145
|
+
onClick: immutable ? void 0 : handleAdd,
|
|
1722
2146
|
// TODO(burdon): Show field limit in ux (not tooltip).
|
|
1723
2147
|
disabled: view.fields.length >= VIEW_FIELD_LIMIT
|
|
1724
2148
|
})));
|
|
1725
2149
|
};
|
|
1726
|
-
|
|
1727
|
-
// packages/ui/react-ui-form/src/util/field.ts
|
|
1728
|
-
import { FormatEnum as FormatEnum3, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
|
|
1729
|
-
var parseValue = ({ type, format, value }) => {
|
|
1730
|
-
if (value === void 0 || value === null || value === "") {
|
|
1731
|
-
return void 0;
|
|
1732
|
-
}
|
|
1733
|
-
const parseScalar = (type2) => {
|
|
1734
|
-
switch (type2) {
|
|
1735
|
-
case TypeEnum.Boolean: {
|
|
1736
|
-
if (typeof value === "string") {
|
|
1737
|
-
const lowercaseValue = value.toLowerCase();
|
|
1738
|
-
if (lowercaseValue === "0" || lowercaseValue === "false") {
|
|
1739
|
-
return false;
|
|
1740
|
-
} else if (lowercaseValue === "1" || lowercaseValue === "true") {
|
|
1741
|
-
return true;
|
|
1742
|
-
}
|
|
1743
|
-
}
|
|
1744
|
-
return Boolean(value);
|
|
1745
|
-
}
|
|
1746
|
-
case TypeEnum.Number: {
|
|
1747
|
-
const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
|
|
1748
|
-
const num = Number(cleaned);
|
|
1749
|
-
return Number.isNaN(num) ? null : num;
|
|
1750
|
-
}
|
|
1751
|
-
case TypeEnum.String:
|
|
1752
|
-
case TypeEnum.Ref:
|
|
1753
|
-
return String(value);
|
|
1754
|
-
default: {
|
|
1755
|
-
return value;
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
};
|
|
1759
|
-
if (!format) {
|
|
1760
|
-
return parseScalar(type);
|
|
1761
|
-
}
|
|
1762
|
-
switch (format) {
|
|
1763
|
-
case FormatEnum3.Boolean:
|
|
1764
|
-
return parseScalar(TypeEnum.Boolean);
|
|
1765
|
-
case FormatEnum3.Number:
|
|
1766
|
-
case FormatEnum3.Percent:
|
|
1767
|
-
case FormatEnum3.Currency:
|
|
1768
|
-
return parseScalar(TypeEnum.Number);
|
|
1769
|
-
case FormatEnum3.String:
|
|
1770
|
-
case FormatEnum3.Markdown: {
|
|
1771
|
-
return parseScalar(TypeEnum.String);
|
|
1772
|
-
}
|
|
1773
|
-
case FormatEnum3.Ref:
|
|
1774
|
-
throw new Error(`unexpected format: ${FormatEnum3.Ref}`);
|
|
1775
|
-
case FormatEnum3.DateTime:
|
|
1776
|
-
case FormatEnum3.Date:
|
|
1777
|
-
case FormatEnum3.Time:
|
|
1778
|
-
case FormatEnum3.Timestamp: {
|
|
1779
|
-
const date = new Date(value);
|
|
1780
|
-
return isNaN(date.getTime()) ? null : date;
|
|
1781
|
-
}
|
|
1782
|
-
case FormatEnum3.GeoPoint: {
|
|
1783
|
-
if (typeof value === "string") {
|
|
1784
|
-
const cleaned = value.replace(/[^0-9.,-]+/g, "");
|
|
1785
|
-
const parts = cleaned.split(",");
|
|
1786
|
-
if (parts.length === 2) {
|
|
1787
|
-
const lat = parseFloat(parts[0]);
|
|
1788
|
-
const long = parseFloat(parts[1]);
|
|
1789
|
-
if (!isNaN(lat) && !isNaN(long)) {
|
|
1790
|
-
return GeoLocation2.toGeoPoint({
|
|
1791
|
-
latitude: lat,
|
|
1792
|
-
longitude: long
|
|
1793
|
-
});
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
return [
|
|
1798
|
-
0,
|
|
1799
|
-
0
|
|
1800
|
-
];
|
|
1801
|
-
}
|
|
1802
|
-
default: {
|
|
1803
|
-
return value;
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
};
|
|
1807
|
-
var cellClassesForFieldType = ({ type, format }) => {
|
|
1808
|
-
if (!format) {
|
|
1809
|
-
switch (type) {
|
|
1810
|
-
case TypeEnum.Number:
|
|
1811
|
-
return [
|
|
1812
|
-
"text-right",
|
|
1813
|
-
"font-mono"
|
|
1814
|
-
];
|
|
1815
|
-
case TypeEnum.Boolean:
|
|
1816
|
-
return [
|
|
1817
|
-
"text-right",
|
|
1818
|
-
"font-mono"
|
|
1819
|
-
];
|
|
1820
|
-
case TypeEnum.String:
|
|
1821
|
-
return void 0;
|
|
1822
|
-
case TypeEnum.Ref:
|
|
1823
|
-
return void 0;
|
|
1824
|
-
default: {
|
|
1825
|
-
return void 0;
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
}
|
|
1829
|
-
switch (format) {
|
|
1830
|
-
case FormatEnum3.Markdown:
|
|
1831
|
-
return void 0;
|
|
1832
|
-
case FormatEnum3.Time:
|
|
1833
|
-
case FormatEnum3.Timestamp:
|
|
1834
|
-
case FormatEnum3.DateTime:
|
|
1835
|
-
case FormatEnum3.Date:
|
|
1836
|
-
case FormatEnum3.Duration:
|
|
1837
|
-
return [
|
|
1838
|
-
"font-mono",
|
|
1839
|
-
"text-right"
|
|
1840
|
-
];
|
|
1841
|
-
case FormatEnum3.Currency:
|
|
1842
|
-
return [
|
|
1843
|
-
"text-right"
|
|
1844
|
-
];
|
|
1845
|
-
case FormatEnum3.JSON:
|
|
1846
|
-
case FormatEnum3.DID:
|
|
1847
|
-
return [
|
|
1848
|
-
"font-mono"
|
|
1849
|
-
];
|
|
1850
|
-
default:
|
|
1851
|
-
return void 0;
|
|
1852
|
-
}
|
|
1853
|
-
};
|
|
1854
|
-
var pathNotUniqueError = (path) => ({
|
|
1855
|
-
path: "path",
|
|
1856
|
-
message: `'${path}' is already present`
|
|
1857
|
-
});
|
|
1858
|
-
|
|
1859
|
-
// packages/ui/react-ui-form/src/util/formatting.ts
|
|
1860
|
-
import { format as formatDate } from "date-fns/format";
|
|
1861
|
-
import { FormatEnum as FormatEnum4, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
|
|
1862
|
-
var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
|
|
1863
|
-
const formatScalar = (type2) => {
|
|
1864
|
-
switch (type2) {
|
|
1865
|
-
case TypeEnum2.Boolean:
|
|
1866
|
-
return value.toLocaleString().toUpperCase();
|
|
1867
|
-
case TypeEnum2.Number:
|
|
1868
|
-
return value.toLocaleString(locale);
|
|
1869
|
-
case TypeEnum2.String:
|
|
1870
|
-
case TypeEnum2.Ref:
|
|
1871
|
-
return String(value);
|
|
1872
|
-
default: {
|
|
1873
|
-
return String(value);
|
|
1874
|
-
}
|
|
1875
|
-
}
|
|
1876
|
-
};
|
|
1877
|
-
if (!format) {
|
|
1878
|
-
return formatScalar(type);
|
|
1879
|
-
}
|
|
1880
|
-
switch (format) {
|
|
1881
|
-
case FormatEnum4.Boolean: {
|
|
1882
|
-
return formatScalar(TypeEnum2.Boolean);
|
|
1883
|
-
}
|
|
1884
|
-
case FormatEnum4.Number: {
|
|
1885
|
-
return formatScalar(TypeEnum2.Number);
|
|
1886
|
-
}
|
|
1887
|
-
case FormatEnum4.String:
|
|
1888
|
-
case FormatEnum4.Ref: {
|
|
1889
|
-
return formatScalar(TypeEnum2.String);
|
|
1890
|
-
}
|
|
1891
|
-
case FormatEnum4.Percent: {
|
|
1892
|
-
return `${value * 100}%`;
|
|
1893
|
-
}
|
|
1894
|
-
case FormatEnum4.Currency: {
|
|
1895
|
-
return value.toLocaleString(locale, {
|
|
1896
|
-
style: "currency",
|
|
1897
|
-
currency: "USD",
|
|
1898
|
-
minimumFractionDigits: 2,
|
|
1899
|
-
maximumFractionDigits: 2
|
|
1900
|
-
});
|
|
1901
|
-
}
|
|
1902
|
-
case FormatEnum4.Date: {
|
|
1903
|
-
try {
|
|
1904
|
-
return formatDate(new Date(value), "yyyy-MM-dd");
|
|
1905
|
-
} catch (error) {
|
|
1906
|
-
return "Invalid Date";
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
case FormatEnum4.Time: {
|
|
1910
|
-
try {
|
|
1911
|
-
return formatDate(new Date(value), "HH:mm:ss");
|
|
1912
|
-
} catch (error) {
|
|
1913
|
-
return "Invalid Time";
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
case FormatEnum4.DateTime: {
|
|
1917
|
-
try {
|
|
1918
|
-
return formatDate(new Date(value), "yyyy-MM-dd HH:mm:ss");
|
|
1919
|
-
} catch (error) {
|
|
1920
|
-
return "Invalid DateTime";
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
1923
|
-
case FormatEnum4.GeoPoint: {
|
|
1924
|
-
if (value === null || value === void 0) {
|
|
1925
|
-
return "";
|
|
1926
|
-
}
|
|
1927
|
-
if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
|
|
1928
|
-
const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
|
|
1929
|
-
return `${latitude},${longitude}`;
|
|
1930
|
-
}
|
|
1931
|
-
return String(value);
|
|
1932
|
-
}
|
|
1933
|
-
default: {
|
|
1934
|
-
if (value === null || value === "undefined") {
|
|
1935
|
-
return "";
|
|
1936
|
-
}
|
|
1937
|
-
return String(value);
|
|
1938
|
-
}
|
|
1939
|
-
}
|
|
1940
|
-
};
|
|
1941
|
-
var formatForEditing = ({ type, format, value, locale = void 0 }) => {
|
|
1942
|
-
const formatScalar = (type2) => {
|
|
1943
|
-
switch (type2) {
|
|
1944
|
-
case TypeEnum2.Boolean:
|
|
1945
|
-
case TypeEnum2.Number:
|
|
1946
|
-
case TypeEnum2.String:
|
|
1947
|
-
case TypeEnum2.Ref:
|
|
1948
|
-
return String(value);
|
|
1949
|
-
default:
|
|
1950
|
-
return String(value);
|
|
1951
|
-
}
|
|
1952
|
-
};
|
|
1953
|
-
if (!format) {
|
|
1954
|
-
return formatScalar(type);
|
|
1955
|
-
}
|
|
1956
|
-
switch (format) {
|
|
1957
|
-
case FormatEnum4.Boolean:
|
|
1958
|
-
case FormatEnum4.Number:
|
|
1959
|
-
case FormatEnum4.String:
|
|
1960
|
-
case FormatEnum4.Ref: {
|
|
1961
|
-
return formatScalar(type);
|
|
1962
|
-
}
|
|
1963
|
-
case FormatEnum4.Percent: {
|
|
1964
|
-
return String(value * 100);
|
|
1965
|
-
}
|
|
1966
|
-
case FormatEnum4.Currency: {
|
|
1967
|
-
return String(value);
|
|
1968
|
-
}
|
|
1969
|
-
case FormatEnum4.DateTime: {
|
|
1970
|
-
const date = new Date(value);
|
|
1971
|
-
return date.toISOString();
|
|
1972
|
-
}
|
|
1973
|
-
case FormatEnum4.Date: {
|
|
1974
|
-
const date = new Date(value);
|
|
1975
|
-
return date.toISOString().split("T")[0];
|
|
1976
|
-
}
|
|
1977
|
-
case FormatEnum4.Time: {
|
|
1978
|
-
const date = new Date(value);
|
|
1979
|
-
return date.toISOString().split("T")[1].split(".")[0];
|
|
1980
|
-
}
|
|
1981
|
-
case FormatEnum4.GeoPoint: {
|
|
1982
|
-
if (value === null || value === void 0) {
|
|
1983
|
-
return "";
|
|
1984
|
-
}
|
|
1985
|
-
if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
|
|
1986
|
-
const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
|
|
1987
|
-
return `${latitude},${longitude}`;
|
|
1988
|
-
}
|
|
1989
|
-
return String(value);
|
|
1990
|
-
}
|
|
1991
|
-
default: {
|
|
1992
|
-
return String(value);
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
};
|
|
1996
2150
|
export {
|
|
1997
2151
|
BooleanInput,
|
|
1998
2152
|
ControlFrame,
|
|
@@ -2020,14 +2174,18 @@ export {
|
|
|
2020
2174
|
ViewEditor,
|
|
2021
2175
|
cellClassesForFieldType,
|
|
2022
2176
|
controlItemClasses,
|
|
2177
|
+
findArrayElementType,
|
|
2023
2178
|
formatForDisplay,
|
|
2024
2179
|
formatForEditing,
|
|
2180
|
+
getRefProps,
|
|
2025
2181
|
parseValue,
|
|
2026
2182
|
pathNotUniqueError,
|
|
2027
2183
|
translations_default as translations,
|
|
2028
2184
|
useForm,
|
|
2029
2185
|
useFormContext,
|
|
2030
2186
|
useFormValues,
|
|
2031
|
-
useInputProps
|
|
2187
|
+
useInputProps,
|
|
2188
|
+
useQueryRefOptions,
|
|
2189
|
+
useRefQueryLookupHandler
|
|
2032
2190
|
};
|
|
2033
2191
|
//# sourceMappingURL=index.mjs.map
|