@dxos/react-ui-form 0.10.0 → 0.11.0
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/index.mjs +4064 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/translations.mjs +77 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +0 -0
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +1 -0
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Card.stories.d.ts +88 -0
- package/dist/types/src/components/Form/Card.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/Form.d.ts +7 -7
- package/dist/types/src/components/Form/Form.stories.d.ts +21 -0
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.theme.d.ts +6 -0
- package/dist/types/src/components/Form/Form.theme.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormControls.d.ts +7 -7
- package/dist/types/src/components/Form/FormControls.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/FormField.d.ts +1 -1
- package/dist/types/src/components/Form/FormField/FormField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/FormRow.d.ts +17 -3
- package/dist/types/src/components/Form/FormField/FormRow.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.d.ts +0 -6
- package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/ArrayField/default-value.d.ts +7 -0
- package/dist/types/src/components/Form/FormField/fields/ArrayField/default-value.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/ArrayField/index.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/ArrayField/index.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/BooleanField/BooleanField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/BooleanField/BooleanField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/DateField/DateField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/DateField/DateField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/DateField/DateField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/MarkdownField/MarkdownField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/MarkdownField/MarkdownField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/MarkdownField/MarkdownField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.d.ts +0 -11
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/NumberField/index.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/index.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/NumberField/numeric-constraints.d.ts +12 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/numeric-constraints.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.d.ts +1 -11
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/RefField/find-ref-option.d.ts +13 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/find-ref-option.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/index.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/index.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.d.ts +1 -13
- package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/SelectField/create-select-field.d.ts +15 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/create-select-field.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/index.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/index.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/TextField/TextField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/TextField/TextField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField/fields/TupleField/TupleField.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormField/fields/TupleField/TupleField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormFieldSet/FormFieldSetContainer.d.ts +1 -1
- package/dist/types/src/components/Form/FormFieldSet/FormFieldSetContainer.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormLayout/FormLayout.d.ts +0 -27
- package/dist/types/src/components/Form/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormLayout/FormLayout.stories.d.ts +1 -0
- package/dist/types/src/components/Form/FormLayout/FormLayout.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormLayout/index.d.ts +1 -0
- package/dist/types/src/components/Form/FormLayout/index.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormLayout/resolve-layout-field.d.ts +29 -0
- package/dist/types/src/components/Form/FormLayout/resolve-layout-field.d.ts.map +1 -0
- package/dist/types/src/components/ObjectForm/ObjectForm.d.ts +10 -1
- package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -1
- package/dist/types/src/components/ObjectForm/ObjectForm.stories.d.ts +2 -0
- package/dist/types/src/components/ObjectForm/ObjectForm.stories.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +8 -23
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +1 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -1
- package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +1 -1
- package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -1
- package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts +1 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts.map +1 -1
- package/dist/types/src/components/ObjectTree/ObjectTree.stories.d.ts +1 -0
- package/dist/types/src/components/ObjectTree/ObjectTree.stories.d.ts.map +1 -1
- package/dist/types/src/components/RefEditor/RefEditor.d.ts.map +1 -1
- package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts +2 -0
- package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/RefEditor/ref-editor-extension.d.ts +9 -8
- package/dist/types/src/components/RefEditor/ref-editor-extension.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +1 -0
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useFormHandler.d.ts +6 -2
- package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useFormHandler.test.d.ts +2 -0
- package/dist/types/src/hooks/useFormHandler.test.d.ts.map +1 -0
- package/dist/types/src/testing/TestLayout.d.ts +1 -1
- package/dist/types/src/testing/TestLayout.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +5 -0
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +0 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +39 -42
- package/src/components/Form/Card.stories.tsx +93 -0
- package/src/components/Form/Form.stories.tsx +95 -3
- package/src/components/Form/Form.theme.ts +14 -8
- package/src/components/Form/Form.tsx +2 -2
- package/src/components/Form/FormControls.tsx +32 -13
- package/src/components/Form/FormField/FormField.tsx +11 -3
- package/src/components/Form/FormField/FormRow.tsx +20 -1
- package/src/components/Form/FormField/fields/ArrayField/ArrayField.tsx +3 -46
- package/src/components/Form/FormField/fields/ArrayField/default-value.ts +49 -0
- package/src/components/Form/FormField/fields/ArrayField/index.ts +2 -0
- package/src/components/Form/FormField/fields/ComboboxField/ComboboxField.tsx +12 -2
- package/src/components/Form/FormField/fields/DateField/DateField.tsx +10 -3
- package/src/components/Form/FormField/fields/MarkdownField/MarkdownField.stories.tsx +1 -1
- package/src/components/Form/FormField/fields/MarkdownField/MarkdownField.tsx +2 -12
- package/src/components/Form/FormField/fields/NumberField/NumberField.test.ts +1 -1
- package/src/components/Form/FormField/fields/NumberField/NumberField.tsx +1 -36
- package/src/components/Form/FormField/fields/NumberField/index.ts +2 -0
- package/src/components/Form/FormField/fields/NumberField/numeric-constraints.ts +43 -0
- package/src/components/Form/FormField/fields/PasswordField/PasswordField.tsx +1 -0
- package/src/components/Form/FormField/fields/RefField/InlineRefField.tsx +2 -2
- package/src/components/Form/FormField/fields/RefField/RefField.test.ts +1 -1
- package/src/components/Form/FormField/fields/RefField/RefField.tsx +3 -45
- package/src/components/Form/FormField/fields/RefField/find-ref-option.ts +56 -0
- package/src/components/Form/FormField/fields/RefField/index.ts +2 -0
- package/src/components/Form/FormField/fields/SelectField/SelectField.tsx +2 -67
- package/src/components/Form/FormField/fields/SelectField/create-select-field.tsx +80 -0
- package/src/components/Form/FormField/fields/SelectField/index.ts +2 -0
- package/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.tsx +2 -1
- package/src/components/Form/FormFieldSet/FormFieldSetContainer.tsx +11 -9
- package/src/components/Form/FormLayout/FormLayout.test.ts +1 -1
- package/src/components/Form/FormLayout/FormLayout.tsx +1 -86
- package/src/components/Form/FormLayout/index.ts +2 -0
- package/src/components/Form/FormLayout/resolve-layout-field.ts +98 -0
- package/src/components/ObjectForm/ObjectForm.stories.tsx +93 -3
- package/src/components/ObjectForm/ObjectForm.tsx +22 -4
- package/src/components/ObjectPicker/ObjectPicker.stories.tsx +1 -1
- package/src/components/ObjectPicker/ObjectPicker.tsx +3 -3
- package/src/components/ObjectProperties/ObjectProperties.stories.tsx +1 -1
- package/src/components/ObjectProperties/ObjectProperties.tsx +7 -1
- package/src/components/ObjectTree/ObjectTree.stories.tsx +1 -1
- package/src/components/RefEditor/RefEditor.stories.tsx +9 -1
- package/src/components/RefEditor/RefEditor.tsx +42 -6
- package/src/components/RefEditor/ref-editor-extension.ts +168 -91
- package/src/components/ViewEditor/ViewEditor.stories.tsx +1 -1
- package/src/components/ViewEditor/ViewEditor.tsx +9 -9
- package/src/hooks/useFormHandler.test.ts +85 -0
- package/src/hooks/useFormHandler.ts +118 -31
- package/src/translations.ts +1 -0
- package/src/types.ts +5 -0
- package/src/util/index.ts +0 -1
- package/dist/lib/browser/index.mjs +0 -4675
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/translations.mjs +0 -87
- package/dist/lib/browser/translations.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -4677
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/translations.mjs +0 -89
- package/dist/lib/node-esm/translations.mjs.map +0 -7
- package/dist/types/src/util/formatting.d.ts +0 -15
- package/dist/types/src/util/formatting.d.ts.map +0 -1
- package/src/util/formatting.ts +0 -171
|
@@ -1,4675 +0,0 @@
|
|
|
1
|
-
// src/annotations.ts
|
|
2
|
-
import { createAnnotationHelper } from "@dxos/echo/internal";
|
|
3
|
-
var OptionsLookupAnnotationId = /* @__PURE__ */ Symbol.for("@dxos/schema/annotation/OptionsLookup");
|
|
4
|
-
var OptionsLookupAnnotation = createAnnotationHelper(OptionsLookupAnnotationId);
|
|
5
|
-
var optionsLookup = () => (deps, load, options) => ({
|
|
6
|
-
deps,
|
|
7
|
-
load,
|
|
8
|
-
combobox: options?.combobox
|
|
9
|
-
});
|
|
10
|
-
var AutofillAnnotationId = /* @__PURE__ */ Symbol.for("@dxos/schema/annotation/Autofill");
|
|
11
|
-
var AutofillAnnotation = createAnnotationHelper(AutofillAnnotationId);
|
|
12
|
-
var autofill = () => (deps, derive) => ({
|
|
13
|
-
deps,
|
|
14
|
-
derive
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
// src/components/FieldEditor/FieldEditor.tsx
|
|
18
|
-
import React26, { useCallback as useCallback18, useEffect as useEffect9, useMemo as useMemo13, useState as useState10 } from "react";
|
|
19
|
-
import { Filter as Filter2, Obj as Obj3, Type as Type4 } from "@dxos/echo";
|
|
20
|
-
import { Format as Format6, FormatEnums, formatToType } from "@dxos/echo/Format";
|
|
21
|
-
import { log as log3 } from "@dxos/log";
|
|
22
|
-
import { useAsyncEffect, useTranslation as useTranslation11 } from "@dxos/react-ui";
|
|
23
|
-
import { formatToAdditionalPropertyAttributes, getFormatSchema } from "@dxos/schema";
|
|
24
|
-
import { translationKey as translationKey11 } from "#translations";
|
|
25
|
-
|
|
26
|
-
// src/util/field.ts
|
|
27
|
-
import { Format, GeoLocation, TypeEnum } from "@dxos/echo/Format";
|
|
28
|
-
var parseValue = ({ type, format, value: value3 }) => {
|
|
29
|
-
if (value3 === void 0 || value3 === null || value3 === "") {
|
|
30
|
-
return void 0;
|
|
31
|
-
}
|
|
32
|
-
const parseScalar = (type2) => {
|
|
33
|
-
switch (type2) {
|
|
34
|
-
case TypeEnum.Boolean: {
|
|
35
|
-
if (typeof value3 === "string") {
|
|
36
|
-
const lowercaseValue = value3.toLowerCase();
|
|
37
|
-
if (lowercaseValue === "0" || lowercaseValue === "false") {
|
|
38
|
-
return false;
|
|
39
|
-
} else if (lowercaseValue === "1" || lowercaseValue === "true") {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return Boolean(value3);
|
|
44
|
-
}
|
|
45
|
-
case TypeEnum.Number: {
|
|
46
|
-
const cleaned = typeof value3 === "string" ? value3.replace(/[^0-9.-]+/g, "") : value3;
|
|
47
|
-
const num = Number(cleaned);
|
|
48
|
-
return Number.isNaN(num) ? null : num;
|
|
49
|
-
}
|
|
50
|
-
case TypeEnum.String:
|
|
51
|
-
case TypeEnum.Ref:
|
|
52
|
-
return String(value3);
|
|
53
|
-
default: {
|
|
54
|
-
return value3;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
if (!format) {
|
|
59
|
-
return parseScalar(type);
|
|
60
|
-
}
|
|
61
|
-
switch (format) {
|
|
62
|
-
case Format.TypeFormat.Boolean:
|
|
63
|
-
return parseScalar(TypeEnum.Boolean);
|
|
64
|
-
case Format.TypeFormat.Number:
|
|
65
|
-
case Format.TypeFormat.Percent:
|
|
66
|
-
case Format.TypeFormat.Currency:
|
|
67
|
-
return parseScalar(TypeEnum.Number);
|
|
68
|
-
case Format.TypeFormat.String:
|
|
69
|
-
case Format.TypeFormat.Markdown: {
|
|
70
|
-
return parseScalar(TypeEnum.String);
|
|
71
|
-
}
|
|
72
|
-
case Format.TypeFormat.Ref:
|
|
73
|
-
throw new Error(`unexpected format: ${Format.TypeFormat.Ref}`);
|
|
74
|
-
case Format.TypeFormat.DateTime:
|
|
75
|
-
case Format.TypeFormat.Date:
|
|
76
|
-
case Format.TypeFormat.Time:
|
|
77
|
-
case Format.TypeFormat.Timestamp: {
|
|
78
|
-
const date = new Date(value3);
|
|
79
|
-
return isNaN(date.getTime()) ? null : date;
|
|
80
|
-
}
|
|
81
|
-
case Format.TypeFormat.GeoPoint: {
|
|
82
|
-
if (typeof value3 === "string") {
|
|
83
|
-
const cleaned = value3.replace(/[^0-9.,-]+/g, "");
|
|
84
|
-
const parts = cleaned.split(",");
|
|
85
|
-
if (parts.length === 2) {
|
|
86
|
-
const lat = parseFloat(parts[0]);
|
|
87
|
-
const long = parseFloat(parts[1]);
|
|
88
|
-
if (!isNaN(lat) && !isNaN(long)) {
|
|
89
|
-
return GeoLocation.toGeoPoint({
|
|
90
|
-
latitude: lat,
|
|
91
|
-
longitude: long
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return [
|
|
97
|
-
0,
|
|
98
|
-
0
|
|
99
|
-
];
|
|
100
|
-
}
|
|
101
|
-
default: {
|
|
102
|
-
return value3;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
var cellClassesForFieldType = ({ type, format }) => {
|
|
107
|
-
switch (format || type) {
|
|
108
|
-
case Format.TypeFormat.Markdown:
|
|
109
|
-
return void 0;
|
|
110
|
-
case Format.TypeFormat.Time:
|
|
111
|
-
case Format.TypeFormat.Timestamp:
|
|
112
|
-
case Format.TypeFormat.DateTime:
|
|
113
|
-
case Format.TypeFormat.Date:
|
|
114
|
-
case Format.TypeFormat.Duration:
|
|
115
|
-
return [
|
|
116
|
-
"font-mono",
|
|
117
|
-
"text-right"
|
|
118
|
-
];
|
|
119
|
-
case Format.TypeFormat.Currency:
|
|
120
|
-
return [
|
|
121
|
-
"text-right"
|
|
122
|
-
];
|
|
123
|
-
case Format.TypeFormat.JSON:
|
|
124
|
-
case Format.TypeFormat.DID:
|
|
125
|
-
return [
|
|
126
|
-
"font-mono"
|
|
127
|
-
];
|
|
128
|
-
case TypeEnum.Number:
|
|
129
|
-
case TypeEnum.Boolean:
|
|
130
|
-
return [
|
|
131
|
-
"text-right",
|
|
132
|
-
"font-mono"
|
|
133
|
-
];
|
|
134
|
-
case TypeEnum.String:
|
|
135
|
-
return void 0;
|
|
136
|
-
case TypeEnum.Ref:
|
|
137
|
-
return void 0;
|
|
138
|
-
default:
|
|
139
|
-
return void 0;
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
var pathNotUniqueError = (path) => ({
|
|
143
|
-
path: "path",
|
|
144
|
-
message: `'${path}' is already present`
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// src/util/formatting.ts
|
|
148
|
-
import { format as formatDate } from "date-fns/format";
|
|
149
|
-
import { Format as Format2, GeoLocation as GeoLocation2, TypeEnum as TypeEnum2 } from "@dxos/echo/Format";
|
|
150
|
-
var formatForDisplay = ({ type, format, value: value3, locale = void 0 }) => {
|
|
151
|
-
const formatScalar = (type2) => {
|
|
152
|
-
switch (type2) {
|
|
153
|
-
case TypeEnum2.Boolean:
|
|
154
|
-
return value3.toLocaleString().toUpperCase();
|
|
155
|
-
case TypeEnum2.Number:
|
|
156
|
-
return value3.toLocaleString(locale);
|
|
157
|
-
case TypeEnum2.String:
|
|
158
|
-
case TypeEnum2.Ref:
|
|
159
|
-
return String(value3);
|
|
160
|
-
default: {
|
|
161
|
-
return String(value3);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
if (!format) {
|
|
166
|
-
return formatScalar(type);
|
|
167
|
-
}
|
|
168
|
-
switch (format) {
|
|
169
|
-
case Format2.TypeFormat.Boolean: {
|
|
170
|
-
return formatScalar(TypeEnum2.Boolean);
|
|
171
|
-
}
|
|
172
|
-
case Format2.TypeFormat.Number: {
|
|
173
|
-
return formatScalar(TypeEnum2.Number);
|
|
174
|
-
}
|
|
175
|
-
case Format2.TypeFormat.String:
|
|
176
|
-
case Format2.TypeFormat.Ref: {
|
|
177
|
-
return formatScalar(TypeEnum2.String);
|
|
178
|
-
}
|
|
179
|
-
case Format2.TypeFormat.Percent: {
|
|
180
|
-
return `${value3 * 100}%`;
|
|
181
|
-
}
|
|
182
|
-
case Format2.TypeFormat.Currency: {
|
|
183
|
-
return value3.toLocaleString(locale, {
|
|
184
|
-
style: "currency",
|
|
185
|
-
currency: "USD",
|
|
186
|
-
minimumFractionDigits: 2,
|
|
187
|
-
maximumFractionDigits: 2
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
case Format2.TypeFormat.Date: {
|
|
191
|
-
try {
|
|
192
|
-
return formatDate(new Date(value3), "yyyy-MM-dd");
|
|
193
|
-
} catch (error) {
|
|
194
|
-
return "Invalid Date";
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
case Format2.TypeFormat.Time: {
|
|
198
|
-
try {
|
|
199
|
-
return formatDate(new Date(value3), "HH:mm:ss");
|
|
200
|
-
} catch (error) {
|
|
201
|
-
return "Invalid Time";
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
case Format2.TypeFormat.DateTime: {
|
|
205
|
-
try {
|
|
206
|
-
return formatDate(new Date(value3), "yyyy-MM-dd HH:mm:ss");
|
|
207
|
-
} catch (error) {
|
|
208
|
-
return "Invalid DateTime";
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
case Format2.TypeFormat.GeoPoint: {
|
|
212
|
-
if (value3 === null || value3 === void 0) {
|
|
213
|
-
return "";
|
|
214
|
-
}
|
|
215
|
-
if (Array.isArray(value3) && value3.length >= 2 && value3.every(Number.isFinite)) {
|
|
216
|
-
const { latitude, longitude } = GeoLocation2.fromGeoPoint(value3);
|
|
217
|
-
return `${latitude},${longitude}`;
|
|
218
|
-
}
|
|
219
|
-
return String(value3);
|
|
220
|
-
}
|
|
221
|
-
default: {
|
|
222
|
-
if (value3 === null || value3 === "undefined") {
|
|
223
|
-
return "";
|
|
224
|
-
}
|
|
225
|
-
return String(value3);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
var formatForEditing = ({ type, format, value: value3, locale = void 0 }) => {
|
|
230
|
-
const formatScalar = (type2) => {
|
|
231
|
-
switch (type2) {
|
|
232
|
-
case TypeEnum2.Boolean:
|
|
233
|
-
case TypeEnum2.Number:
|
|
234
|
-
case TypeEnum2.String:
|
|
235
|
-
case TypeEnum2.Ref:
|
|
236
|
-
return String(value3);
|
|
237
|
-
default:
|
|
238
|
-
return String(value3);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
if (!format) {
|
|
242
|
-
return formatScalar(type);
|
|
243
|
-
}
|
|
244
|
-
switch (format) {
|
|
245
|
-
case Format2.TypeFormat.Boolean:
|
|
246
|
-
case Format2.TypeFormat.Number:
|
|
247
|
-
case Format2.TypeFormat.String:
|
|
248
|
-
case Format2.TypeFormat.Ref: {
|
|
249
|
-
return formatScalar(type);
|
|
250
|
-
}
|
|
251
|
-
case Format2.TypeFormat.Percent: {
|
|
252
|
-
return String(value3 * 100);
|
|
253
|
-
}
|
|
254
|
-
case Format2.TypeFormat.Currency: {
|
|
255
|
-
return String(value3);
|
|
256
|
-
}
|
|
257
|
-
case Format2.TypeFormat.DateTime: {
|
|
258
|
-
const date = new Date(value3);
|
|
259
|
-
return date.toISOString();
|
|
260
|
-
}
|
|
261
|
-
case Format2.TypeFormat.Date: {
|
|
262
|
-
const date = new Date(value3);
|
|
263
|
-
return date.toISOString().split("T")[0];
|
|
264
|
-
}
|
|
265
|
-
case Format2.TypeFormat.Time: {
|
|
266
|
-
const date = new Date(value3);
|
|
267
|
-
return date.toISOString().split("T")[1].split(".")[0];
|
|
268
|
-
}
|
|
269
|
-
case Format2.TypeFormat.GeoPoint: {
|
|
270
|
-
if (value3 === null || value3 === void 0) {
|
|
271
|
-
return "";
|
|
272
|
-
}
|
|
273
|
-
if (Array.isArray(value3) && value3.length >= 2 && value3.every(Number.isFinite)) {
|
|
274
|
-
const { latitude, longitude } = GeoLocation2.fromGeoPoint(value3);
|
|
275
|
-
return `${latitude},${longitude}`;
|
|
276
|
-
}
|
|
277
|
-
return String(value3);
|
|
278
|
-
}
|
|
279
|
-
default: {
|
|
280
|
-
return String(value3);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
// src/util/omit.ts
|
|
286
|
-
import * as Option from "effect/Option";
|
|
287
|
-
import * as Schema from "effect/Schema";
|
|
288
|
-
import * as SchemaAST from "effect/SchemaAST";
|
|
289
|
-
import { Annotation, Type } from "@dxos/echo";
|
|
290
|
-
var omitId = (schemaOrType) => {
|
|
291
|
-
const schema = Type.isType(schemaOrType) ? Type.getSchema(schemaOrType) : schemaOrType;
|
|
292
|
-
return omitIdFromSchema(schema);
|
|
293
|
-
};
|
|
294
|
-
var omitIdFromSchema = (schema) => {
|
|
295
|
-
const ast = schema.ast;
|
|
296
|
-
if (SchemaAST.isUnion(ast)) {
|
|
297
|
-
return Schema.Union(...ast.types.map((type) => omitIdFromSchema(Schema.make(type))));
|
|
298
|
-
}
|
|
299
|
-
const hasId = SchemaAST.getPropertySignatures(ast).some((prop) => prop.name === "id");
|
|
300
|
-
return hasId ? schema.pipe(Schema.omit("id")) : schema;
|
|
301
|
-
};
|
|
302
|
-
var omitHiddenFormFields = (schema) => {
|
|
303
|
-
const properties = SchemaAST.getPropertySignatures(schema.ast);
|
|
304
|
-
const hidden = properties.filter((prop) => Option.getOrElse(Annotation.FormInputAnnotation.getFromAst(prop.type), () => true) === false).map((prop) => prop.name);
|
|
305
|
-
return hidden.length === 0 ? schema : schema.pipe(Schema.omit(...hidden));
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
// src/util/properties.ts
|
|
309
|
-
import * as Option2 from "effect/Option";
|
|
310
|
-
import * as SchemaAST2 from "effect/SchemaAST";
|
|
311
|
-
import { Annotation as Annotation2 } from "@dxos/echo";
|
|
312
|
-
import { SchemaEx } from "@dxos/effect";
|
|
313
|
-
var unwrapOptional = (prop) => {
|
|
314
|
-
if (!prop.isOptional || !SchemaAST2.isUnion(prop.type)) {
|
|
315
|
-
return prop.type;
|
|
316
|
-
}
|
|
317
|
-
const defined = prop.type.types.filter((type) => type._tag !== "UndefinedKeyword");
|
|
318
|
-
if (defined.length === 0) {
|
|
319
|
-
return prop.type;
|
|
320
|
-
}
|
|
321
|
-
return defined.length === 1 ? defined[0] : SchemaAST2.Union.make(defined, prop.type.annotations);
|
|
322
|
-
};
|
|
323
|
-
var getRootFormProperties = (ast, values) => {
|
|
324
|
-
if (!SchemaEx.isDiscriminatedUnion(ast)) {
|
|
325
|
-
return getFormProperties(ast);
|
|
326
|
-
}
|
|
327
|
-
const activeType = SchemaEx.getDiscriminatedType(ast, values ?? {});
|
|
328
|
-
if (!activeType) {
|
|
329
|
-
return getFormProperties(ast);
|
|
330
|
-
}
|
|
331
|
-
const activeProps = getFormProperties(activeType);
|
|
332
|
-
const discriminators = new Set((SchemaEx.getDiscriminatingProps(ast) ?? []).map((name) => name.toString()));
|
|
333
|
-
if (discriminators.size === 0) {
|
|
334
|
-
return activeProps;
|
|
335
|
-
}
|
|
336
|
-
const fullType = SchemaEx.getDiscriminatedType(ast, {});
|
|
337
|
-
const fullDiscriminatorProps = fullType ? getFormProperties(fullType) : activeProps;
|
|
338
|
-
return activeProps.map((prop) => discriminators.has(prop.name.toString()) ? fullDiscriminatorProps.find((candidate) => candidate.name === prop.name) ?? prop : prop);
|
|
339
|
-
};
|
|
340
|
-
var getFormProperties = (ast) => {
|
|
341
|
-
const signatures = SchemaAST2.getPropertySignatures(ast);
|
|
342
|
-
const rawByName = new Map(signatures.map((prop) => [
|
|
343
|
-
prop.name,
|
|
344
|
-
unwrapOptional(prop)
|
|
345
|
-
]));
|
|
346
|
-
const hidden = new Set(signatures.filter((prop) => Annotation2.FormInputAnnotation.getFromAst(unwrapOptional(prop)).pipe(Option2.getOrElse(() => true)) === false).map((prop) => prop.name));
|
|
347
|
-
return SchemaEx.getProperties(ast).filter((prop) => !hidden.has(prop.name)).map((prop) => {
|
|
348
|
-
const raw = rawByName.get(prop.name);
|
|
349
|
-
return raw && (SchemaEx.isNestedType(raw) || SchemaEx.isArrayType(raw)) ? {
|
|
350
|
-
...prop,
|
|
351
|
-
type: raw
|
|
352
|
-
} : prop;
|
|
353
|
-
});
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
// src/util/refs.ts
|
|
357
|
-
import { Ref } from "@dxos/echo";
|
|
358
|
-
import { ReferenceAnnotationId } from "@dxos/echo/Annotation";
|
|
359
|
-
import { SchemaEx as SchemaEx2 } from "@dxos/effect";
|
|
360
|
-
var getRefProps = (ast) => {
|
|
361
|
-
if (SchemaEx2.isArrayType(ast)) {
|
|
362
|
-
const elementType = SchemaEx2.getArrayElementType(ast);
|
|
363
|
-
if (elementType) {
|
|
364
|
-
if (Ref.isRefType(elementType)) {
|
|
365
|
-
const typename = SchemaEx2.findAnnotation(elementType, ReferenceAnnotationId)?.typename;
|
|
366
|
-
return {
|
|
367
|
-
ast: elementType,
|
|
368
|
-
isArray: true,
|
|
369
|
-
typename
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
if (Ref.isRefType(ast)) {
|
|
375
|
-
const typename = SchemaEx2.findAnnotation(ast, ReferenceAnnotationId)?.typename;
|
|
376
|
-
return {
|
|
377
|
-
ast,
|
|
378
|
-
isArray: false,
|
|
379
|
-
typename
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
return void 0;
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
// src/components/Form/meta-tags.ts
|
|
386
|
-
import * as Schema2 from "effect/Schema";
|
|
387
|
-
import { Ref as Ref2, Tag } from "@dxos/echo";
|
|
388
|
-
var META_TAGS_KEY = "_tags";
|
|
389
|
-
var withMetaTags = (schema) => omitId(Schema2.Struct({
|
|
390
|
-
[META_TAGS_KEY]: Schema2.Array(Ref2.Ref(Tag.Tag)).pipe(Schema2.annotations({
|
|
391
|
-
title: "Tags"
|
|
392
|
-
}), Schema2.optional)
|
|
393
|
-
}).pipe(Schema2.extend(schema)));
|
|
394
|
-
|
|
395
|
-
// src/components/Form/FormControls.tsx
|
|
396
|
-
import React25, { useRef as useRef7 } from "react";
|
|
397
|
-
import { Column, IconButton as IconButton5, Input as Input14, ScrollArea, composable, composableProps, useMergeRefs, useTranslation as useTranslation10, withColumn } from "@dxos/react-ui";
|
|
398
|
-
import { MarkdownView } from "@dxos/react-ui-markdown";
|
|
399
|
-
import { mx as mx6 } from "@dxos/ui-theme";
|
|
400
|
-
import { translationKey as translationKey10 } from "#translations";
|
|
401
|
-
|
|
402
|
-
// src/hooks/useAsyncFieldEffect.ts
|
|
403
|
-
import * as Cause from "effect/Cause";
|
|
404
|
-
import * as Effect from "effect/Effect";
|
|
405
|
-
import * as Exit from "effect/Exit";
|
|
406
|
-
import { useEffect, useRef, useState } from "react";
|
|
407
|
-
var pickValues = (values, deps) => {
|
|
408
|
-
const subset = {};
|
|
409
|
-
for (const dep of deps) {
|
|
410
|
-
subset[dep] = values?.[dep];
|
|
411
|
-
}
|
|
412
|
-
return subset;
|
|
413
|
-
};
|
|
414
|
-
var useAsyncFieldEffect = (factory, key, { debounceMs = 400, enabled = true } = {}) => {
|
|
415
|
-
const factoryRef = useRef(factory);
|
|
416
|
-
factoryRef.current = factory;
|
|
417
|
-
const [state, setState] = useState({
|
|
418
|
-
loading: false,
|
|
419
|
-
error: void 0,
|
|
420
|
-
data: void 0
|
|
421
|
-
});
|
|
422
|
-
useEffect(() => {
|
|
423
|
-
if (!enabled) {
|
|
424
|
-
setState({
|
|
425
|
-
loading: false,
|
|
426
|
-
error: void 0,
|
|
427
|
-
data: void 0
|
|
428
|
-
});
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
let cancel;
|
|
432
|
-
const timer = setTimeout(() => {
|
|
433
|
-
setState((prev) => ({
|
|
434
|
-
...prev,
|
|
435
|
-
loading: true,
|
|
436
|
-
error: void 0
|
|
437
|
-
}));
|
|
438
|
-
cancel = Effect.runCallback(factoryRef.current(), {
|
|
439
|
-
onExit: (exit) => {
|
|
440
|
-
Exit.match(exit, {
|
|
441
|
-
onSuccess: (data) => setState({
|
|
442
|
-
loading: false,
|
|
443
|
-
error: void 0,
|
|
444
|
-
data
|
|
445
|
-
}),
|
|
446
|
-
onFailure: (cause) => {
|
|
447
|
-
if (!Cause.isInterruptedOnly(cause)) {
|
|
448
|
-
setState((prev) => ({
|
|
449
|
-
loading: false,
|
|
450
|
-
error: Cause.squash(cause),
|
|
451
|
-
data: prev.data
|
|
452
|
-
}));
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
});
|
|
458
|
-
}, debounceMs);
|
|
459
|
-
return () => {
|
|
460
|
-
clearTimeout(timer);
|
|
461
|
-
cancel?.();
|
|
462
|
-
};
|
|
463
|
-
}, [
|
|
464
|
-
key,
|
|
465
|
-
enabled,
|
|
466
|
-
debounceMs
|
|
467
|
-
]);
|
|
468
|
-
return state;
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
// src/hooks/useFormContext.ts
|
|
472
|
-
import { createContext } from "@radix-ui/react-context";
|
|
473
|
-
import * as SchemaAST3 from "effect/SchemaAST";
|
|
474
|
-
import { useEffect as useEffect2, useMemo, useRef as useRef2 } from "react";
|
|
475
|
-
import { SchemaEx as SchemaEx3 } from "@dxos/effect";
|
|
476
|
-
var [FormContextProvider, useFormContext] = createContext("Form");
|
|
477
|
-
var useFormValues = (componentName, path, defaultValue) => {
|
|
478
|
-
const stablePath = useMemo(() => path ?? [], [
|
|
479
|
-
path ? path.join(".") : void 0
|
|
480
|
-
]);
|
|
481
|
-
const jsonPath = SchemaEx3.createJsonPath(stablePath);
|
|
482
|
-
const { form: { values, onValueChange } } = useFormContext(componentName);
|
|
483
|
-
const value3 = SchemaEx3.getValue(values, jsonPath);
|
|
484
|
-
const lastAppliedPathRef = useRef2(null);
|
|
485
|
-
useEffect2(() => {
|
|
486
|
-
if (value3 == null && defaultValue && lastAppliedPathRef.current !== jsonPath) {
|
|
487
|
-
lastAppliedPathRef.current = jsonPath;
|
|
488
|
-
onValueChange(stablePath, SchemaAST3.stringKeyword, defaultValue());
|
|
489
|
-
}
|
|
490
|
-
}, [
|
|
491
|
-
value3,
|
|
492
|
-
defaultValue,
|
|
493
|
-
onValueChange,
|
|
494
|
-
stablePath,
|
|
495
|
-
jsonPath
|
|
496
|
-
]);
|
|
497
|
-
return value3;
|
|
498
|
-
};
|
|
499
|
-
var useFormFieldState = (componentName, path = []) => {
|
|
500
|
-
const stablePath = useMemo(() => path, [
|
|
501
|
-
Array.isArray(path) ? path.join(".") : path
|
|
502
|
-
]);
|
|
503
|
-
const { form: { getStatus, getValue, onBlur, onValueChange } } = useFormContext(componentName);
|
|
504
|
-
return useMemo(() => ({
|
|
505
|
-
getStatus: () => getStatus(stablePath),
|
|
506
|
-
getValue: () => getValue(stablePath),
|
|
507
|
-
onBlur: () => onBlur(stablePath),
|
|
508
|
-
onValueChange: (ast, value3) => onValueChange(stablePath, ast, value3)
|
|
509
|
-
}), [
|
|
510
|
-
getStatus,
|
|
511
|
-
getValue,
|
|
512
|
-
onBlur,
|
|
513
|
-
onValueChange,
|
|
514
|
-
stablePath
|
|
515
|
-
]);
|
|
516
|
-
};
|
|
517
|
-
|
|
518
|
-
// src/hooks/useFormHandler.ts
|
|
519
|
-
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
520
|
-
import { useCallback, useEffect as useEffect3, useMemo as useMemo2, useState as useState2 } from "react";
|
|
521
|
-
import { SchemaEx as SchemaEx4 } from "@dxos/effect";
|
|
522
|
-
import { log } from "@dxos/log";
|
|
523
|
-
import { useDefaultValue } from "@dxos/react-ui";
|
|
524
|
-
import { validateSchema } from "@dxos/schema";
|
|
525
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-form/src/hooks/useFormHandler.ts";
|
|
526
|
-
var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: defaultValuesProp, onValuesChanged, onValidate, onSave, onCancel, ...props }) => {
|
|
527
|
-
const [changed, setChanged] = useState2({});
|
|
528
|
-
const [touched, setTouched] = useState2({});
|
|
529
|
-
const [errors, setErrors] = useState2({});
|
|
530
|
-
const [saving, setSaving] = useState2(false);
|
|
531
|
-
const defaultValues = useDefaultValue(defaultValuesProp, () => ({}));
|
|
532
|
-
const [values$, setValues] = useControllableState({
|
|
533
|
-
prop: valuesProp,
|
|
534
|
-
defaultProp: defaultValues,
|
|
535
|
-
onChange: () => {
|
|
536
|
-
if (valuesProp !== void 0) {
|
|
537
|
-
setValues(valuesProp ?? defaultValues);
|
|
538
|
-
setChanged({});
|
|
539
|
-
setTouched({});
|
|
540
|
-
setErrors({});
|
|
541
|
-
setSaving(false);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
});
|
|
545
|
-
const values = values$;
|
|
546
|
-
const validate = useCallback((values2) => {
|
|
547
|
-
if (!schema) {
|
|
548
|
-
return false;
|
|
549
|
-
}
|
|
550
|
-
let errors2 = validateSchema(schema, values2) ?? [];
|
|
551
|
-
log("validate", {
|
|
552
|
-
values: values2,
|
|
553
|
-
errors: errors2
|
|
554
|
-
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 42, S: void 0 });
|
|
555
|
-
if (errors2.length === 0 && onValidate) {
|
|
556
|
-
const validatedValues = values2;
|
|
557
|
-
errors2 = onValidate(validatedValues) ?? [];
|
|
558
|
-
}
|
|
559
|
-
setErrors(flatMap(errors2));
|
|
560
|
-
const valid = errors2.length === 0;
|
|
561
|
-
return valid;
|
|
562
|
-
}, [
|
|
563
|
-
schema,
|
|
564
|
-
onValidate
|
|
565
|
-
]);
|
|
566
|
-
const [schemaChanged, setSchemaChanged] = useState2(false);
|
|
567
|
-
useEffect3(() => setSchemaChanged(true), [
|
|
568
|
-
schema
|
|
569
|
-
]);
|
|
570
|
-
useEffect3(() => {
|
|
571
|
-
if (schemaChanged) {
|
|
572
|
-
validate(values);
|
|
573
|
-
setSchemaChanged(false);
|
|
574
|
-
}
|
|
575
|
-
}, [
|
|
576
|
-
validate,
|
|
577
|
-
values,
|
|
578
|
-
schemaChanged
|
|
579
|
-
]);
|
|
580
|
-
const isValid = useMemo2(() => {
|
|
581
|
-
return Object.keys(errors).length === 0;
|
|
582
|
-
}, [
|
|
583
|
-
errors
|
|
584
|
-
]);
|
|
585
|
-
const canSave = useMemo2(() => !saving && // Check if any error paths that are touched have errors.
|
|
586
|
-
!Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
|
|
587
|
-
touched,
|
|
588
|
-
errors,
|
|
589
|
-
saving
|
|
590
|
-
]);
|
|
591
|
-
const handleSave = useCallback(async () => {
|
|
592
|
-
if (validate(values)) {
|
|
593
|
-
setSaving(true);
|
|
594
|
-
try {
|
|
595
|
-
await onSave?.(values, {
|
|
596
|
-
changed,
|
|
597
|
-
isValid
|
|
598
|
-
});
|
|
599
|
-
} finally {
|
|
600
|
-
setSaving(false);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
}, [
|
|
604
|
-
values,
|
|
605
|
-
validate,
|
|
606
|
-
onSave,
|
|
607
|
-
changed,
|
|
608
|
-
isValid
|
|
609
|
-
]);
|
|
610
|
-
const handleCancel = useCallback(() => {
|
|
611
|
-
onCancel?.();
|
|
612
|
-
}, [
|
|
613
|
-
onCancel
|
|
614
|
-
]);
|
|
615
|
-
const getStatus = useCallback((path) => {
|
|
616
|
-
const jsonPath = Array.isArray(path) ? SchemaEx4.createJsonPath(path) : path;
|
|
617
|
-
const [_, error] = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`)) ?? [];
|
|
618
|
-
const isTouched = touched[jsonPath];
|
|
619
|
-
if (!isTouched) {
|
|
620
|
-
return {
|
|
621
|
-
status: void 0,
|
|
622
|
-
error: void 0
|
|
623
|
-
};
|
|
624
|
-
}
|
|
625
|
-
return {
|
|
626
|
-
status: error ? "error" : void 0,
|
|
627
|
-
error: error ? error ?? void 0 : void 0
|
|
628
|
-
};
|
|
629
|
-
}, [
|
|
630
|
-
errors,
|
|
631
|
-
touched
|
|
632
|
-
]);
|
|
633
|
-
const getValue = useCallback((path) => {
|
|
634
|
-
return SchemaEx4.getValue(values, SchemaEx4.createJsonPath(path));
|
|
635
|
-
}, [
|
|
636
|
-
values
|
|
637
|
-
]);
|
|
638
|
-
const onValueChange = useCallback((path, type, value3) => {
|
|
639
|
-
log("onValueChange", {
|
|
640
|
-
path,
|
|
641
|
-
value: value3
|
|
642
|
-
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 138, S: void 0 });
|
|
643
|
-
const jsonPath = SchemaEx4.createJsonPath(path);
|
|
644
|
-
const pathArray = path;
|
|
645
|
-
let parsedValue = value3;
|
|
646
|
-
try {
|
|
647
|
-
if (type._tag === "NumberKeyword") {
|
|
648
|
-
parsedValue = parseFloat(value3) || 0;
|
|
649
|
-
}
|
|
650
|
-
} catch (err) {
|
|
651
|
-
log.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 150, S: void 0 });
|
|
652
|
-
parsedValue = void 0;
|
|
653
|
-
}
|
|
654
|
-
const newValues = mergeAtPath(values, pathArray, parsedValue);
|
|
655
|
-
const newChanged = {
|
|
656
|
-
[jsonPath]: true
|
|
657
|
-
};
|
|
658
|
-
setChanged((prev) => ({
|
|
659
|
-
...prev,
|
|
660
|
-
...newChanged
|
|
661
|
-
}));
|
|
662
|
-
const isValid2 = validate(newValues);
|
|
663
|
-
onValuesChanged?.(newValues, {
|
|
664
|
-
isValid: isValid2,
|
|
665
|
-
changed: newChanged
|
|
666
|
-
});
|
|
667
|
-
if (valuesProp === void 0) {
|
|
668
|
-
setValues(newValues);
|
|
669
|
-
}
|
|
670
|
-
}, [
|
|
671
|
-
values,
|
|
672
|
-
validate,
|
|
673
|
-
onValuesChanged,
|
|
674
|
-
valuesProp
|
|
675
|
-
]);
|
|
676
|
-
const onBlur = useCallback(async (path) => {
|
|
677
|
-
const jsonPath = SchemaEx4.createJsonPath(path);
|
|
678
|
-
setTouched((touched2) => ({
|
|
679
|
-
...touched2,
|
|
680
|
-
[jsonPath]: true
|
|
681
|
-
}));
|
|
682
|
-
const isValid2 = validate(values);
|
|
683
|
-
if (Object.keys(changed).length > 0 && isValid2 && autoSave) {
|
|
684
|
-
await onSave?.(values, {
|
|
685
|
-
changed,
|
|
686
|
-
isValid: isValid2
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
}, [
|
|
690
|
-
validate,
|
|
691
|
-
values,
|
|
692
|
-
changed,
|
|
693
|
-
autoSave,
|
|
694
|
-
onSave
|
|
695
|
-
]);
|
|
696
|
-
return useMemo2(() => ({
|
|
697
|
-
// State.
|
|
698
|
-
schema,
|
|
699
|
-
values,
|
|
700
|
-
errors,
|
|
701
|
-
touched,
|
|
702
|
-
changed,
|
|
703
|
-
isValid,
|
|
704
|
-
canSave,
|
|
705
|
-
autoSave,
|
|
706
|
-
// Actions.
|
|
707
|
-
onSave: handleSave,
|
|
708
|
-
onCancel: handleCancel,
|
|
709
|
-
// Field utils.
|
|
710
|
-
getStatus,
|
|
711
|
-
getValue,
|
|
712
|
-
onBlur,
|
|
713
|
-
onValueChange,
|
|
714
|
-
...props
|
|
715
|
-
}), [
|
|
716
|
-
schema,
|
|
717
|
-
autoSave,
|
|
718
|
-
values,
|
|
719
|
-
errors,
|
|
720
|
-
touched,
|
|
721
|
-
changed,
|
|
722
|
-
canSave,
|
|
723
|
-
isValid,
|
|
724
|
-
getStatus,
|
|
725
|
-
getValue,
|
|
726
|
-
onBlur,
|
|
727
|
-
onValueChange,
|
|
728
|
-
handleSave,
|
|
729
|
-
handleCancel
|
|
730
|
-
]);
|
|
731
|
-
};
|
|
732
|
-
var mergeAtPath = (obj, path, value3) => {
|
|
733
|
-
if (path.length === 0) {
|
|
734
|
-
return value3;
|
|
735
|
-
}
|
|
736
|
-
const [head, ...rest] = path;
|
|
737
|
-
const child = rest.length === 0 ? value3 : mergeAtPath(obj?.[head], rest, value3);
|
|
738
|
-
if (Array.isArray(obj)) {
|
|
739
|
-
const copy = [
|
|
740
|
-
...obj
|
|
741
|
-
];
|
|
742
|
-
copy[head] = child;
|
|
743
|
-
return copy;
|
|
744
|
-
}
|
|
745
|
-
return {
|
|
746
|
-
...obj,
|
|
747
|
-
[head]: child
|
|
748
|
-
};
|
|
749
|
-
};
|
|
750
|
-
var flatMap = (errors) => {
|
|
751
|
-
return errors.reduce((result, { path, message }) => {
|
|
752
|
-
const jsonPath = SchemaEx4.fromEffectValidationPath(path);
|
|
753
|
-
if (!(jsonPath in result)) {
|
|
754
|
-
result[jsonPath] = message;
|
|
755
|
-
}
|
|
756
|
-
return result;
|
|
757
|
-
}, {});
|
|
758
|
-
};
|
|
759
|
-
|
|
760
|
-
// src/hooks/useKeyHandler.tsx
|
|
761
|
-
import { useCallback as useCallback2, useLayoutEffect } from "react";
|
|
762
|
-
import { addEventListener } from "@dxos/async";
|
|
763
|
-
var useKeyHandler = (elRef, form) => {
|
|
764
|
-
const handleKeyDown = useCallback2((event) => {
|
|
765
|
-
switch (event.key) {
|
|
766
|
-
case "Enter": {
|
|
767
|
-
if (event.metaKey && form.canSave) {
|
|
768
|
-
form.onSave();
|
|
769
|
-
}
|
|
770
|
-
break;
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
}, [
|
|
774
|
-
form.isValid,
|
|
775
|
-
form.canSave,
|
|
776
|
-
form.onSave,
|
|
777
|
-
form.autoSave
|
|
778
|
-
]);
|
|
779
|
-
useLayoutEffect(() => {
|
|
780
|
-
const el = elRef.current;
|
|
781
|
-
if (!el) {
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
return addEventListener(el, "keydown", handleKeyDown);
|
|
785
|
-
}, [
|
|
786
|
-
elRef,
|
|
787
|
-
handleKeyDown
|
|
788
|
-
]);
|
|
789
|
-
};
|
|
790
|
-
|
|
791
|
-
// src/components/Form/Form.theme.ts
|
|
792
|
-
import { mx, tv } from "@dxos/ui-theme";
|
|
793
|
-
var formStyles = tv({
|
|
794
|
-
slots: {
|
|
795
|
-
viewport: "",
|
|
796
|
-
content: "",
|
|
797
|
-
section: "flex flex-col py-form-section-gap first:pt-0",
|
|
798
|
-
group: "flex flex-col gap-3 p-trim-md border border-separator rounded-sm",
|
|
799
|
-
sectionHeader: "",
|
|
800
|
-
sectionTitle: "text-lg",
|
|
801
|
-
sectionDescription: "text-description",
|
|
802
|
-
fieldSet: "",
|
|
803
|
-
field: "",
|
|
804
|
-
fieldLabel: "h-8 grid grid-cols-[1fr_auto_auto] items-center select-none",
|
|
805
|
-
fieldLabelText: "",
|
|
806
|
-
fieldDescription: "text-description",
|
|
807
|
-
fieldControl: "",
|
|
808
|
-
fieldValidation: "",
|
|
809
|
-
// Action bar (cancel/save), equal-width columns flowing horizontally.
|
|
810
|
-
actions: "grid grid-flow-col gap-form-gap auto-cols-fr py-form-padding",
|
|
811
|
-
// Standalone submit row (full-width primary button).
|
|
812
|
-
submit: "flex w-full pt-form-padding",
|
|
813
|
-
// Collapsible field-set body: indented column of sub-fields.
|
|
814
|
-
fieldSetBody: "flex flex-col gap-2 px-2 pb-2",
|
|
815
|
-
// Bordered container wrapping a collapsible nested group, plus its top spacing.
|
|
816
|
-
fieldSetBox: "border border-subdued-separator rounded-sm",
|
|
817
|
-
fieldSetBoxOuter: "pt-trim-md"
|
|
818
|
-
},
|
|
819
|
-
variants: {
|
|
820
|
-
variant: {
|
|
821
|
-
default: {},
|
|
822
|
-
settings: {
|
|
823
|
-
content: "dx-document",
|
|
824
|
-
// Gap on the section spaces its direct children — section title/description and, for action
|
|
825
|
-
// panels, the `Form.Row`s placed directly in the section (which have no `fieldSet` wrapper).
|
|
826
|
-
section: "py-form-section-gap! gap-trim-md",
|
|
827
|
-
sectionHeader: "pb-form-section-gap",
|
|
828
|
-
sectionTitle: "px-trim-md text-xl",
|
|
829
|
-
sectionDescription: "px-trim-md",
|
|
830
|
-
// No top padding: the section gap already separates the field set from the title above it.
|
|
831
|
-
fieldSet: "flex flex-col gap-trim-md",
|
|
832
|
-
field: mx("grid", 'grid-cols-1 [grid-template-areas:"header""description""control""validation"]', 'md:grid-cols-2 md:[grid-template-areas:"header_header""description_control""validation_validation"]', "gap-x-trim-lg gap-y-0 p-trim-md border border-input-separator rounded-md"),
|
|
833
|
-
fieldLabel: "[grid-area:header]",
|
|
834
|
-
fieldLabelText: "text-base-fg text-lg",
|
|
835
|
-
fieldDescription: "[grid-area:description] pt-1 text-description",
|
|
836
|
-
fieldControl: "[grid-area:control] flex justify-end items-start md:text-right pt-3 md:pt-0",
|
|
837
|
-
fieldValidation: "[grid-area:validation]"
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
},
|
|
841
|
-
defaultVariants: {
|
|
842
|
-
variant: "default"
|
|
843
|
-
}
|
|
844
|
-
});
|
|
845
|
-
var formTheme = {
|
|
846
|
-
styles: formStyles,
|
|
847
|
-
behavior: {
|
|
848
|
-
default: {
|
|
849
|
-
showDescription: false
|
|
850
|
-
},
|
|
851
|
-
settings: {
|
|
852
|
-
showDescription: true
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
};
|
|
856
|
-
var formSlots = Object.keys(formTheme.styles());
|
|
857
|
-
|
|
858
|
-
// src/components/Form/FormFieldSet/FormFieldSet.tsx
|
|
859
|
-
import * as Option7 from "effect/Option";
|
|
860
|
-
import React24, { useMemo as useMemo12 } from "react";
|
|
861
|
-
import { DEFAULT_LAYOUT_NAME, FormLayoutAnnotation } from "@dxos/echo/Annotation";
|
|
862
|
-
import { SchemaEx as SchemaEx10 } from "@dxos/effect";
|
|
863
|
-
|
|
864
|
-
// src/components/Form/FormField/fields/ArrayField/ArrayField.tsx
|
|
865
|
-
import * as Option4 from "effect/Option";
|
|
866
|
-
import * as SchemaAST5 from "effect/SchemaAST";
|
|
867
|
-
import React4, { useCallback as useCallback3, useRef as useRef3 } from "react";
|
|
868
|
-
import { Annotation as Annotation4, Ref as Ref3 } from "@dxos/echo";
|
|
869
|
-
import { useType as defaultUseType } from "@dxos/echo-react";
|
|
870
|
-
import { SchemaEx as SchemaEx6 } from "@dxos/effect";
|
|
871
|
-
import { DXN } from "@dxos/keys";
|
|
872
|
-
import { log as log2 } from "@dxos/log";
|
|
873
|
-
import { useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
874
|
-
import { OrderedList } from "@dxos/react-ui-list";
|
|
875
|
-
import { mx as mx3 } from "@dxos/ui-theme";
|
|
876
|
-
import { arrayMove } from "@dxos/util";
|
|
877
|
-
import { translationKey as translationKey2 } from "#translations";
|
|
878
|
-
|
|
879
|
-
// src/components/Form/FormField/FormField.tsx
|
|
880
|
-
import * as Match from "effect/Match";
|
|
881
|
-
import * as Option3 from "effect/Option";
|
|
882
|
-
import * as Schema3 from "effect/Schema";
|
|
883
|
-
import * as SchemaAST4 from "effect/SchemaAST";
|
|
884
|
-
import * as String2 from "effect/String";
|
|
885
|
-
import React, { useMemo as useMemo3 } from "react";
|
|
886
|
-
import { Annotation as Annotation3, Format as Format3 } from "@dxos/echo";
|
|
887
|
-
import { SchemaEx as SchemaEx5 } from "@dxos/effect";
|
|
888
|
-
import { IconButton, useTranslation } from "@dxos/react-ui";
|
|
889
|
-
import { translationKey } from "#translations";
|
|
890
|
-
var FormField = (props) => {
|
|
891
|
-
const {
|
|
892
|
-
type,
|
|
893
|
-
name,
|
|
894
|
-
label: labelProp,
|
|
895
|
-
path,
|
|
896
|
-
required,
|
|
897
|
-
projection,
|
|
898
|
-
fieldMap,
|
|
899
|
-
fieldProvider,
|
|
900
|
-
readonly,
|
|
901
|
-
layout,
|
|
902
|
-
// RefFieldProps
|
|
903
|
-
createTypename,
|
|
904
|
-
createOptionLabel,
|
|
905
|
-
createOptionIcon,
|
|
906
|
-
createInitialValuePath,
|
|
907
|
-
createFieldMap: createFieldMap3,
|
|
908
|
-
db,
|
|
909
|
-
useType: useType2,
|
|
910
|
-
getOptions,
|
|
911
|
-
onCreate,
|
|
912
|
-
resolveCreateEntry,
|
|
913
|
-
refInline
|
|
914
|
-
} = props;
|
|
915
|
-
const { t } = useTranslation(translationKey);
|
|
916
|
-
const title = SchemaEx5.getAnnotation(SchemaAST4.TitleAnnotationId)(type);
|
|
917
|
-
const description = SchemaEx5.getAnnotation(SchemaAST4.DescriptionAnnotationId)(type);
|
|
918
|
-
const examples = SchemaEx5.getAnnotation(SchemaAST4.ExamplesAnnotationId)(type);
|
|
919
|
-
const label = useMemo3(() => labelProp ?? title ?? (name == null ? "" : String2.capitalize(name)), [
|
|
920
|
-
labelProp,
|
|
921
|
-
title,
|
|
922
|
-
name
|
|
923
|
-
]);
|
|
924
|
-
const placeholder = useMemo3(() => examples?.length ? `${t("example.placeholder")}: ${examples[0]}` : description ?? label, [
|
|
925
|
-
examples,
|
|
926
|
-
description,
|
|
927
|
-
label,
|
|
928
|
-
t
|
|
929
|
-
]);
|
|
930
|
-
const providerSchema = useMemo3(() => fieldProvider ? Schema3.make(type) : void 0, [
|
|
931
|
-
fieldProvider,
|
|
932
|
-
type
|
|
933
|
-
]);
|
|
934
|
-
const fieldState = useFormFieldState(FormField.displayName, path);
|
|
935
|
-
const jsonPath = SchemaEx5.createJsonPath(path ?? []);
|
|
936
|
-
const fieldProps = {
|
|
937
|
-
type,
|
|
938
|
-
format: Format3.FormatAnnotation.getFromAst(type).pipe((annotation) => Option3.getOrUndefined(annotation)),
|
|
939
|
-
readonly,
|
|
940
|
-
label,
|
|
941
|
-
description,
|
|
942
|
-
jsonPath,
|
|
943
|
-
placeholder,
|
|
944
|
-
presentation: layout,
|
|
945
|
-
required,
|
|
946
|
-
db,
|
|
947
|
-
...fieldState
|
|
948
|
-
};
|
|
949
|
-
if (readonly && fieldState.getValue() == null) {
|
|
950
|
-
return null;
|
|
951
|
-
}
|
|
952
|
-
const CustomField = fieldMap?.[jsonPath];
|
|
953
|
-
if (CustomField) {
|
|
954
|
-
return /* @__PURE__ */ React.createElement(CustomField, fieldProps);
|
|
955
|
-
}
|
|
956
|
-
if (fieldProvider && providerSchema) {
|
|
957
|
-
const component = fieldProvider({
|
|
958
|
-
schema: providerSchema,
|
|
959
|
-
prop: name ?? "",
|
|
960
|
-
fieldProps
|
|
961
|
-
});
|
|
962
|
-
if (component) {
|
|
963
|
-
return component;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
const optionsLookup2 = Option3.getOrUndefined(OptionsLookupAnnotation.getFromAst(type));
|
|
967
|
-
if (optionsLookup2) {
|
|
968
|
-
return optionsLookup2.combobox ? /* @__PURE__ */ React.createElement(ComboboxField, {
|
|
969
|
-
...fieldProps,
|
|
970
|
-
lookup: optionsLookup2
|
|
971
|
-
}) : /* @__PURE__ */ React.createElement(AsyncSelectField, {
|
|
972
|
-
...fieldProps,
|
|
973
|
-
lookup: optionsLookup2
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
const autofill2 = Option3.getOrUndefined(AutofillAnnotation.getFromAst(type));
|
|
977
|
-
if (autofill2) {
|
|
978
|
-
return /* @__PURE__ */ React.createElement(AutofillField, {
|
|
979
|
-
...fieldProps,
|
|
980
|
-
autofill: autofill2
|
|
981
|
-
});
|
|
982
|
-
}
|
|
983
|
-
if (SchemaEx5.isArrayType(type)) {
|
|
984
|
-
return /* @__PURE__ */ React.createElement(ArrayField, {
|
|
985
|
-
fieldProps: fieldState,
|
|
986
|
-
label,
|
|
987
|
-
...props
|
|
988
|
-
});
|
|
989
|
-
}
|
|
990
|
-
const Field = getFormField(fieldProps);
|
|
991
|
-
if (Field) {
|
|
992
|
-
return /* @__PURE__ */ React.createElement(Field, fieldProps);
|
|
993
|
-
}
|
|
994
|
-
const options = getSelectOptions(type);
|
|
995
|
-
if (options) {
|
|
996
|
-
const fieldProjections = projection?.getFieldProjections();
|
|
997
|
-
const fieldProjection = fieldProjections?.find((fp) => fp.field.path === name);
|
|
998
|
-
const selectOptions = fieldProjection?.props.options;
|
|
999
|
-
return /* @__PURE__ */ React.createElement(SelectField, {
|
|
1000
|
-
...fieldProps,
|
|
1001
|
-
options: options.map((option) => {
|
|
1002
|
-
const selectOption = selectOptions?.find((so) => so.id === globalThis.String(option));
|
|
1003
|
-
return {
|
|
1004
|
-
value: option,
|
|
1005
|
-
label: selectOption?.title ?? option.toString()
|
|
1006
|
-
};
|
|
1007
|
-
})
|
|
1008
|
-
});
|
|
1009
|
-
}
|
|
1010
|
-
const refProps = getRefProps(type);
|
|
1011
|
-
if (refProps) {
|
|
1012
|
-
const inline = refInline || Annotation3.FormInlineAnnotation.getFromAst(refProps.ast).pipe(Option3.getOrElse(() => false));
|
|
1013
|
-
if (inline && !refProps.isArray) {
|
|
1014
|
-
return /* @__PURE__ */ React.createElement(InlineRefField, {
|
|
1015
|
-
...fieldProps,
|
|
1016
|
-
...refProps,
|
|
1017
|
-
db,
|
|
1018
|
-
useType: useType2,
|
|
1019
|
-
onCreate,
|
|
1020
|
-
resolveCreateEntry
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
const isCreateTarget = !createTypename || refProps.typename === createTypename;
|
|
1024
|
-
return /* @__PURE__ */ React.createElement(RefField, {
|
|
1025
|
-
...fieldProps,
|
|
1026
|
-
...refProps,
|
|
1027
|
-
createOptionLabel: isCreateTarget ? createOptionLabel : void 0,
|
|
1028
|
-
createOptionIcon: isCreateTarget ? createOptionIcon : void 0,
|
|
1029
|
-
createInitialValuePath: isCreateTarget ? createInitialValuePath : void 0,
|
|
1030
|
-
createFieldMap: isCreateTarget ? createFieldMap3 : void 0,
|
|
1031
|
-
db,
|
|
1032
|
-
useType: useType2,
|
|
1033
|
-
getOptions,
|
|
1034
|
-
onCreate,
|
|
1035
|
-
resolveCreateEntry
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
if (SchemaEx5.isNestedType(type)) {
|
|
1039
|
-
const baseNode = SchemaEx5.findNode(type, SchemaEx5.isDiscriminatedUnion);
|
|
1040
|
-
const typeLiteral = baseNode ? SchemaEx5.getDiscriminatedType(baseNode, fieldState.getValue()) : SchemaEx5.findNode(type, SchemaAST4.isTypeLiteral);
|
|
1041
|
-
if (typeLiteral) {
|
|
1042
|
-
const schema = Schema3.make(typeLiteral);
|
|
1043
|
-
return /* @__PURE__ */ React.createElement(FormFieldSet, {
|
|
1044
|
-
schema,
|
|
1045
|
-
path,
|
|
1046
|
-
readonly,
|
|
1047
|
-
layout,
|
|
1048
|
-
label,
|
|
1049
|
-
collapsible: true,
|
|
1050
|
-
projection,
|
|
1051
|
-
fieldMap,
|
|
1052
|
-
fieldProvider,
|
|
1053
|
-
createOptionLabel,
|
|
1054
|
-
createOptionIcon,
|
|
1055
|
-
createInitialValuePath,
|
|
1056
|
-
db,
|
|
1057
|
-
useType: useType2,
|
|
1058
|
-
getOptions,
|
|
1059
|
-
onCreate,
|
|
1060
|
-
resolveCreateEntry
|
|
1061
|
-
});
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
return null;
|
|
1065
|
-
};
|
|
1066
|
-
FormField.displayName = "Form.FormField";
|
|
1067
|
-
var CompactIconButton = (props) => {
|
|
1068
|
-
return /* @__PURE__ */ React.createElement(IconButton, {
|
|
1069
|
-
variant: "ghost",
|
|
1070
|
-
iconOnly: true,
|
|
1071
|
-
...props
|
|
1072
|
-
});
|
|
1073
|
-
};
|
|
1074
|
-
var getFormField = ({ type, format }) => {
|
|
1075
|
-
if (SchemaAST4.isRefinement(type)) {
|
|
1076
|
-
return getFormField({
|
|
1077
|
-
type: type.from,
|
|
1078
|
-
format
|
|
1079
|
-
});
|
|
1080
|
-
}
|
|
1081
|
-
const formatField = Match.value(format).pipe(Match.withReturnType(), Match.when(Format3.TypeFormat.Date, () => DateField), Match.when(Format3.TypeFormat.DateTime, () => DateField), Match.when(Format3.TypeFormat.GeoPoint, () => GeoPointField), Match.when(Format3.TypeFormat.Markdown, () => MarkdownField), Match.when(Format3.TypeFormat.Password, () => PasswordField), Match.when(Format3.TypeFormat.Text, () => TextAreaField), Match.when(Format3.TypeFormat.Time, () => DateField), Match.orElse(() => void 0));
|
|
1082
|
-
if (formatField) {
|
|
1083
|
-
return formatField;
|
|
1084
|
-
}
|
|
1085
|
-
switch (type._tag) {
|
|
1086
|
-
// TODO(wittjosiah): Schema.Any is currently used to represent template inputs.
|
|
1087
|
-
case "AnyKeyword":
|
|
1088
|
-
case "StringKeyword":
|
|
1089
|
-
return TextField;
|
|
1090
|
-
case "NumberKeyword":
|
|
1091
|
-
return NumberField;
|
|
1092
|
-
case "BooleanKeyword":
|
|
1093
|
-
return BooleanField;
|
|
1094
|
-
}
|
|
1095
|
-
return void 0;
|
|
1096
|
-
};
|
|
1097
|
-
var getSelectOptions = (ast) => {
|
|
1098
|
-
if (SchemaEx5.isLiteralUnion(ast)) {
|
|
1099
|
-
return ast.types.map((type) => type.literal).filter((v) => v !== null);
|
|
1100
|
-
}
|
|
1101
|
-
return Format3.OptionsAnnotation.getFromAst(ast).pipe((annotation) => Option3.getOrUndefined(annotation));
|
|
1102
|
-
};
|
|
1103
|
-
|
|
1104
|
-
// src/components/Form/FormField/FormFieldHeader.tsx
|
|
1105
|
-
import React3 from "react";
|
|
1106
|
-
|
|
1107
|
-
// src/components/Form/FormField/FormRow.tsx
|
|
1108
|
-
import { format as formatDate2 } from "date-fns";
|
|
1109
|
-
import React2, { Component } from "react";
|
|
1110
|
-
import { Format as Format4 } from "@dxos/echo";
|
|
1111
|
-
import { Icon, Input, Tooltip } from "@dxos/react-ui";
|
|
1112
|
-
import { mx as mx2 } from "@dxos/ui-theme";
|
|
1113
|
-
|
|
1114
|
-
// src/components/Form/FormField/presentation.tsx
|
|
1115
|
-
var presentationFor = (layout) => ({
|
|
1116
|
-
layout,
|
|
1117
|
-
isStatic: layout === "static",
|
|
1118
|
-
showLabel: layout !== "inline",
|
|
1119
|
-
showError: layout === "full"
|
|
1120
|
-
});
|
|
1121
|
-
|
|
1122
|
-
// src/components/Form/FormField/FormRow.tsx
|
|
1123
|
-
var FormFieldLabel = ({ classNames, labelClassName, variant = "default", label, error, readonly, required, standalone, button, onClick }) => {
|
|
1124
|
-
const styles3 = formTheme.styles({
|
|
1125
|
-
variant
|
|
1126
|
-
});
|
|
1127
|
-
const labelClassNames = mx2("text-sm text-description", required && "after:content-['*'] after:ms-0.5 after:text-warning-text", styles3.fieldLabelText({
|
|
1128
|
-
class: labelClassName
|
|
1129
|
-
}));
|
|
1130
|
-
const labelNode = readonly || standalone ? /* @__PURE__ */ React2.createElement("span", {
|
|
1131
|
-
className: labelClassNames
|
|
1132
|
-
}, label) : /* @__PURE__ */ React2.createElement(Input.Label, {
|
|
1133
|
-
classNames: labelClassNames
|
|
1134
|
-
}, label);
|
|
1135
|
-
return /* @__PURE__ */ React2.createElement("div", {
|
|
1136
|
-
className: styles3.fieldLabel({
|
|
1137
|
-
class: mx2(onClick && "cursor-pointer", classNames)
|
|
1138
|
-
}),
|
|
1139
|
-
onClick
|
|
1140
|
-
}, labelNode, error ? /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
1141
|
-
asChild: true,
|
|
1142
|
-
content: error,
|
|
1143
|
-
side: "bottom"
|
|
1144
|
-
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
1145
|
-
icon: "ph--warning--regular",
|
|
1146
|
-
size: 4,
|
|
1147
|
-
classNames: "text-error-text"
|
|
1148
|
-
})) : /* @__PURE__ */ React2.createElement("span", null), button);
|
|
1149
|
-
};
|
|
1150
|
-
FormFieldLabel.displayName = "Form.FieldLabel";
|
|
1151
|
-
var formatStaticValue = (value3, format) => {
|
|
1152
|
-
if (value3 == null) {
|
|
1153
|
-
return "";
|
|
1154
|
-
}
|
|
1155
|
-
switch (format) {
|
|
1156
|
-
case Format4.TypeFormat.DateTime:
|
|
1157
|
-
case Format4.TypeFormat.Date:
|
|
1158
|
-
case Format4.TypeFormat.Time: {
|
|
1159
|
-
const date = new Date(value3);
|
|
1160
|
-
if (Number.isNaN(date.getTime())) {
|
|
1161
|
-
return String(value3);
|
|
1162
|
-
}
|
|
1163
|
-
const pattern = format === Format4.TypeFormat.DateTime ? "PPp" : format === Format4.TypeFormat.Date ? "PP" : "p";
|
|
1164
|
-
return formatDate2(date, pattern);
|
|
1165
|
-
}
|
|
1166
|
-
default:
|
|
1167
|
-
return String(value3);
|
|
1168
|
-
}
|
|
1169
|
-
};
|
|
1170
|
-
var FORM_ROW_NAME = "Form.Row";
|
|
1171
|
-
var FormRow = ({ classNames, children, readonly, presentation, label, description, jsonPath, format, required, standalone, renderStatic, validation, getStatus, getValue, rootRef }) => {
|
|
1172
|
-
const { variant = "default" } = useFormContext(FORM_ROW_NAME);
|
|
1173
|
-
const styles3 = formTheme.styles({
|
|
1174
|
-
variant
|
|
1175
|
-
});
|
|
1176
|
-
const { showDescription } = formTheme.behavior[variant];
|
|
1177
|
-
const resolved = presentationFor(presentation);
|
|
1178
|
-
if (typeof children === "function" && getStatus && getValue) {
|
|
1179
|
-
const { status, error } = getStatus();
|
|
1180
|
-
const value3 = getValue();
|
|
1181
|
-
if (resolved.isStatic && value3 == null) {
|
|
1182
|
-
return null;
|
|
1183
|
-
}
|
|
1184
|
-
const control = resolved.isStatic ? renderStatic?.(value3) ?? /* @__PURE__ */ React2.createElement("p", {
|
|
1185
|
-
className: "truncate min-w-0"
|
|
1186
|
-
}, formatStaticValue(value3, format)) : children({
|
|
1187
|
-
value: value3,
|
|
1188
|
-
presentation: resolved
|
|
1189
|
-
});
|
|
1190
|
-
return /* @__PURE__ */ React2.createElement(Input.Root, {
|
|
1191
|
-
validationValence: status
|
|
1192
|
-
}, /* @__PURE__ */ React2.createElement("div", {
|
|
1193
|
-
className: styles3.field({
|
|
1194
|
-
class: classNames
|
|
1195
|
-
}),
|
|
1196
|
-
ref: rootRef
|
|
1197
|
-
}, resolved.showLabel && /* @__PURE__ */ React2.createElement(FormFieldLabel, {
|
|
1198
|
-
variant,
|
|
1199
|
-
error,
|
|
1200
|
-
readonly,
|
|
1201
|
-
required,
|
|
1202
|
-
standalone,
|
|
1203
|
-
label,
|
|
1204
|
-
path: jsonPath
|
|
1205
|
-
}), showDescription && description && /* @__PURE__ */ React2.createElement(Input.Description, {
|
|
1206
|
-
classNames: styles3.fieldDescription()
|
|
1207
|
-
}, description), /* @__PURE__ */ React2.createElement("div", {
|
|
1208
|
-
className: styles3.fieldControl()
|
|
1209
|
-
}, control), resolved.showError && error && /* @__PURE__ */ React2.createElement("div", {
|
|
1210
|
-
className: styles3.fieldValidation()
|
|
1211
|
-
}, /* @__PURE__ */ React2.createElement(Input.DescriptionAndValidation, null, /* @__PURE__ */ React2.createElement(Input.Validation, null, error)))));
|
|
1212
|
-
}
|
|
1213
|
-
return /* @__PURE__ */ React2.createElement("div", {
|
|
1214
|
-
ref: rootRef,
|
|
1215
|
-
className: styles3.field({
|
|
1216
|
-
class: classNames
|
|
1217
|
-
})
|
|
1218
|
-
}, resolved.showLabel && label && /* @__PURE__ */ React2.createElement(FormFieldLabel, {
|
|
1219
|
-
variant,
|
|
1220
|
-
readonly,
|
|
1221
|
-
required,
|
|
1222
|
-
standalone: true,
|
|
1223
|
-
label,
|
|
1224
|
-
path: jsonPath
|
|
1225
|
-
}), showDescription && description && /* @__PURE__ */ React2.createElement("p", {
|
|
1226
|
-
className: styles3.fieldDescription()
|
|
1227
|
-
}, description), /* @__PURE__ */ React2.createElement("div", {
|
|
1228
|
-
className: styles3.fieldControl()
|
|
1229
|
-
}, typeof children === "function" ? null : children), validation && /* @__PURE__ */ React2.createElement("div", {
|
|
1230
|
-
className: styles3.fieldValidation()
|
|
1231
|
-
}, validation));
|
|
1232
|
-
};
|
|
1233
|
-
FormRow.displayName = FORM_ROW_NAME;
|
|
1234
|
-
var FormFieldErrorBoundary = class extends Component {
|
|
1235
|
-
static getDerivedStateFromError(error) {
|
|
1236
|
-
return {
|
|
1237
|
-
error
|
|
1238
|
-
};
|
|
1239
|
-
}
|
|
1240
|
-
state = {
|
|
1241
|
-
error: void 0
|
|
1242
|
-
};
|
|
1243
|
-
componentDidUpdate(prevProps) {
|
|
1244
|
-
if (prevProps.path !== this.props.path) {
|
|
1245
|
-
this.resetError();
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
render() {
|
|
1249
|
-
if (this.state.error) {
|
|
1250
|
-
return /* @__PURE__ */ React2.createElement("div", {
|
|
1251
|
-
className: "flex gap-2 border border-error-border font-mono text-sm"
|
|
1252
|
-
}, /* @__PURE__ */ React2.createElement("span", {
|
|
1253
|
-
className: "bg-error-bg text-base-fg px-1 font-thin"
|
|
1254
|
-
}, "ERROR"), String(this.props.path?.join(".")));
|
|
1255
|
-
}
|
|
1256
|
-
return this.props.children;
|
|
1257
|
-
}
|
|
1258
|
-
resetError() {
|
|
1259
|
-
this.setState({
|
|
1260
|
-
error: void 0
|
|
1261
|
-
});
|
|
1262
|
-
}
|
|
1263
|
-
};
|
|
1264
|
-
|
|
1265
|
-
// src/components/Form/FormField/FormFieldHeader.tsx
|
|
1266
|
-
var FormFieldHeader = ({ label, path, required, readonly, classNames, add, actions, onClick }) => /* @__PURE__ */ React3.createElement(FormFieldLabel, {
|
|
1267
|
-
standalone: true,
|
|
1268
|
-
classNames,
|
|
1269
|
-
label,
|
|
1270
|
-
required,
|
|
1271
|
-
readonly,
|
|
1272
|
-
path,
|
|
1273
|
-
button: !readonly && add || actions ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, !readonly && add && /* @__PURE__ */ React3.createElement(CompactIconButton, {
|
|
1274
|
-
disabled: add.disabled,
|
|
1275
|
-
icon: add.icon ?? "ph--plus--regular",
|
|
1276
|
-
label: add.label,
|
|
1277
|
-
onClick: (event) => {
|
|
1278
|
-
event.stopPropagation();
|
|
1279
|
-
add.onClick();
|
|
1280
|
-
}
|
|
1281
|
-
}), actions) : void 0,
|
|
1282
|
-
onClick
|
|
1283
|
-
});
|
|
1284
|
-
|
|
1285
|
-
// src/components/Form/FormField/fields/ArrayField/ArrayField.tsx
|
|
1286
|
-
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/Form/FormField/fields/ArrayField/ArrayField.tsx";
|
|
1287
|
-
var DND_ID = "__dndId";
|
|
1288
|
-
var isOrderedItem = (item) => !!item && typeof item === "object" && typeof item[DND_ID] === "string";
|
|
1289
|
-
var getOrderedId = (item) => item[DND_ID];
|
|
1290
|
-
var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps, ...props }) => {
|
|
1291
|
-
const { t } = useTranslation2(translationKey2);
|
|
1292
|
-
const elementType = SchemaEx6.getArrayElementType(type);
|
|
1293
|
-
const { onValueChange } = inputProps;
|
|
1294
|
-
const values = useFormValues(ArrayField.displayName, path, () => []);
|
|
1295
|
-
const ordered = Annotation4.FormOrderedAnnotation.getFromAst(type).pipe(Option4.getOrElse(() => false));
|
|
1296
|
-
const { db, onCreate, getCreateDefaults, useType: useType2 = defaultUseType } = props;
|
|
1297
|
-
const createTypename = Annotation4.FormCreateAnnotation.getFromAst(type).pipe(Option4.getOrUndefined);
|
|
1298
|
-
const createSchema = useType2(db, createTypename ? DXN.make(createTypename) : void 0);
|
|
1299
|
-
const createInline = !!createTypename && !!elementType && Ref3.isRefType(elementType) && !readonly && layout !== "static";
|
|
1300
|
-
const idsRef = useRef3([]);
|
|
1301
|
-
const counterRef = useRef3(0);
|
|
1302
|
-
const nextId = useCallback3(() => `${DND_ID}-${counterRef.current++}`, []);
|
|
1303
|
-
const handleAddCreate = useCallback3(async () => {
|
|
1304
|
-
if (!createSchema || !onCreate) {
|
|
1305
|
-
return;
|
|
1306
|
-
}
|
|
1307
|
-
const defaults = getCreateDefaults?.({
|
|
1308
|
-
jsonPath: SchemaEx6.createJsonPath(path ?? []),
|
|
1309
|
-
schema: createSchema
|
|
1310
|
-
}) ?? {};
|
|
1311
|
-
const created = await onCreate(createSchema, defaults);
|
|
1312
|
-
if (!created) {
|
|
1313
|
-
return;
|
|
1314
|
-
}
|
|
1315
|
-
idsRef.current.push(nextId());
|
|
1316
|
-
onValueChange(type, [
|
|
1317
|
-
...values ?? [],
|
|
1318
|
-
Ref3.make(created)
|
|
1319
|
-
]);
|
|
1320
|
-
}, [
|
|
1321
|
-
createSchema,
|
|
1322
|
-
onCreate,
|
|
1323
|
-
getCreateDefaults,
|
|
1324
|
-
onValueChange,
|
|
1325
|
-
type,
|
|
1326
|
-
path,
|
|
1327
|
-
values,
|
|
1328
|
-
nextId
|
|
1329
|
-
]);
|
|
1330
|
-
const getDefaultObjectValue = (typeNode) => {
|
|
1331
|
-
const baseNode = SchemaEx6.findNode(typeNode, SchemaEx6.isDiscriminatedUnion);
|
|
1332
|
-
const typeLiteral = baseNode ? SchemaEx6.getDiscriminatedType(baseNode, {}) : SchemaEx6.findNode(typeNode, SchemaAST5.isTypeLiteral);
|
|
1333
|
-
if (!typeLiteral) {
|
|
1334
|
-
return {};
|
|
1335
|
-
}
|
|
1336
|
-
return Object.fromEntries(getFormProperties(typeLiteral).map((prop) => {
|
|
1337
|
-
const defaultValue = SchemaAST5.getDefaultAnnotation(prop.type).pipe((annotation) => Option4.getOrUndefined(annotation));
|
|
1338
|
-
return [
|
|
1339
|
-
prop.name,
|
|
1340
|
-
defaultValue
|
|
1341
|
-
];
|
|
1342
|
-
}));
|
|
1343
|
-
};
|
|
1344
|
-
const handleAdd = useCallback3(() => {
|
|
1345
|
-
let defaultValue;
|
|
1346
|
-
try {
|
|
1347
|
-
defaultValue = elementType && SchemaEx6.isNestedType(elementType) ? getDefaultObjectValue(elementType) : getDefaultValue(elementType);
|
|
1348
|
-
} catch (err) {
|
|
1349
|
-
log2.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 97, S: void 0 });
|
|
1350
|
-
return;
|
|
1351
|
-
}
|
|
1352
|
-
idsRef.current.push(nextId());
|
|
1353
|
-
onValueChange(type, [
|
|
1354
|
-
...values ?? [],
|
|
1355
|
-
defaultValue
|
|
1356
|
-
]);
|
|
1357
|
-
}, [
|
|
1358
|
-
onValueChange,
|
|
1359
|
-
type,
|
|
1360
|
-
elementType,
|
|
1361
|
-
values,
|
|
1362
|
-
nextId
|
|
1363
|
-
]);
|
|
1364
|
-
const handleDelete = useCallback3((idx) => {
|
|
1365
|
-
idsRef.current.splice(idx, 1);
|
|
1366
|
-
onValueChange(type, values?.filter((_, i) => i !== idx));
|
|
1367
|
-
}, [
|
|
1368
|
-
onValueChange,
|
|
1369
|
-
type,
|
|
1370
|
-
values
|
|
1371
|
-
]);
|
|
1372
|
-
const handleMove = useCallback3((fromIndex, toIndex) => {
|
|
1373
|
-
const next = [
|
|
1374
|
-
...values ?? []
|
|
1375
|
-
];
|
|
1376
|
-
arrayMove(next, fromIndex, toIndex);
|
|
1377
|
-
arrayMove(idsRef.current, fromIndex, toIndex);
|
|
1378
|
-
onValueChange(type, next);
|
|
1379
|
-
}, [
|
|
1380
|
-
onValueChange,
|
|
1381
|
-
type,
|
|
1382
|
-
values
|
|
1383
|
-
]);
|
|
1384
|
-
if (!elementType || (readonly || layout === "static") && values && values.length < 1) {
|
|
1385
|
-
return null;
|
|
1386
|
-
}
|
|
1387
|
-
const renderItemAsObject = elementType && SchemaEx6.isNestedType(elementType) && !Ref3.isRefType(elementType);
|
|
1388
|
-
const renderField = (index, isLast) => {
|
|
1389
|
-
const field = /* @__PURE__ */ React4.createElement(FormField, {
|
|
1390
|
-
...props,
|
|
1391
|
-
autoFocus: isLast,
|
|
1392
|
-
type: elementType,
|
|
1393
|
-
...renderItemAsObject || createInline ? {
|
|
1394
|
-
name: null
|
|
1395
|
-
} : {
|
|
1396
|
-
label
|
|
1397
|
-
},
|
|
1398
|
-
path: [
|
|
1399
|
-
...path ?? [],
|
|
1400
|
-
index
|
|
1401
|
-
],
|
|
1402
|
-
readonly: readonly || layout === "static",
|
|
1403
|
-
layout: renderItemAsObject ? layout === "static" ? "static" : void 0 : "inline",
|
|
1404
|
-
refInline: createInline || void 0
|
|
1405
|
-
});
|
|
1406
|
-
return createInline ? /* @__PURE__ */ React4.createElement("div", {
|
|
1407
|
-
role: "none",
|
|
1408
|
-
className: "w-full min-w-0 [--dx-col:auto]"
|
|
1409
|
-
}, field) : field;
|
|
1410
|
-
};
|
|
1411
|
-
const header = (layout !== "static" || values && values.length > 0) && /* @__PURE__ */ React4.createElement(FormFieldHeader, {
|
|
1412
|
-
label,
|
|
1413
|
-
path: SchemaEx6.createJsonPath(path ?? []),
|
|
1414
|
-
readonly,
|
|
1415
|
-
add: layout !== "static" ? {
|
|
1416
|
-
label: t("add-item.button"),
|
|
1417
|
-
onClick: createInline ? () => void handleAddCreate() : handleAdd
|
|
1418
|
-
} : void 0
|
|
1419
|
-
});
|
|
1420
|
-
if (ordered && !readonly && layout !== "static") {
|
|
1421
|
-
const ids = idsRef.current;
|
|
1422
|
-
const count = values?.length ?? 0;
|
|
1423
|
-
while (ids.length < count) {
|
|
1424
|
-
ids.push(nextId());
|
|
1425
|
-
}
|
|
1426
|
-
if (ids.length > count) {
|
|
1427
|
-
ids.length = count;
|
|
1428
|
-
}
|
|
1429
|
-
const items = (values ?? []).map((value3, index) => ({
|
|
1430
|
-
value: value3,
|
|
1431
|
-
index,
|
|
1432
|
-
[DND_ID]: ids[index]
|
|
1433
|
-
}));
|
|
1434
|
-
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, header, /* @__PURE__ */ React4.createElement(OrderedList.Root, {
|
|
1435
|
-
items,
|
|
1436
|
-
isItem: isOrderedItem,
|
|
1437
|
-
getId: getOrderedId,
|
|
1438
|
-
onMove: handleMove
|
|
1439
|
-
}, ({ items: items2 }) => /* @__PURE__ */ React4.createElement(OrderedList.Content, null, items2.map((item) => /* @__PURE__ */ React4.createElement(OrderedList.Item, {
|
|
1440
|
-
key: getOrderedId(item),
|
|
1441
|
-
id: getOrderedId(item),
|
|
1442
|
-
item,
|
|
1443
|
-
classNames: "grid grid-cols-[min-content_1fr_min-content] items-start gap-1 p-0 pb-1"
|
|
1444
|
-
}, /* @__PURE__ */ React4.createElement(OrderedList.DragHandle, null), renderField(item.index, item.index === items2.length - 1), /* @__PURE__ */ React4.createElement(CompactIconButton, {
|
|
1445
|
-
icon: "ph--x--regular",
|
|
1446
|
-
label: t("remove-item.button"),
|
|
1447
|
-
onClick: () => handleDelete(item.index)
|
|
1448
|
-
}))))));
|
|
1449
|
-
}
|
|
1450
|
-
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, header, /* @__PURE__ */ React4.createElement("div", {
|
|
1451
|
-
className: "flex flex-col gap-2"
|
|
1452
|
-
}, values?.map((_, index) => {
|
|
1453
|
-
const isLast = index === values.length - 1;
|
|
1454
|
-
return /* @__PURE__ */ React4.createElement("div", {
|
|
1455
|
-
key: index,
|
|
1456
|
-
className: mx3("grid grid-cols-[minmax(0,1fr)_min-content] gap-1", renderItemAsObject || createInline ? "items-start" : "items-center")
|
|
1457
|
-
}, renderField(index, isLast), !readonly && layout !== "static" && /* @__PURE__ */ React4.createElement(CompactIconButton, {
|
|
1458
|
-
icon: "ph--x--regular",
|
|
1459
|
-
label: t("remove-item.button"),
|
|
1460
|
-
onClick: () => handleDelete(index)
|
|
1461
|
-
}));
|
|
1462
|
-
})));
|
|
1463
|
-
};
|
|
1464
|
-
ArrayField.displayName = "Form.ArrayField";
|
|
1465
|
-
var getDefaultValue = (ast) => {
|
|
1466
|
-
switch (ast?._tag) {
|
|
1467
|
-
case "StringKeyword": {
|
|
1468
|
-
return "";
|
|
1469
|
-
}
|
|
1470
|
-
case "NumberKeyword": {
|
|
1471
|
-
return 0;
|
|
1472
|
-
}
|
|
1473
|
-
case "BooleanKeyword": {
|
|
1474
|
-
return false;
|
|
1475
|
-
}
|
|
1476
|
-
case "Suspend": {
|
|
1477
|
-
return getDefaultValue(ast.f());
|
|
1478
|
-
}
|
|
1479
|
-
case "Refinement": {
|
|
1480
|
-
const jsonSchema = Option4.getOrUndefined(SchemaAST5.getJSONSchemaAnnotation(ast));
|
|
1481
|
-
if (jsonSchema != null && "minimum" in jsonSchema && typeof jsonSchema.minimum === "number") {
|
|
1482
|
-
return jsonSchema.minimum;
|
|
1483
|
-
}
|
|
1484
|
-
return getDefaultValue(ast.from);
|
|
1485
|
-
}
|
|
1486
|
-
default: {
|
|
1487
|
-
if (ast && SchemaEx6.isNestedType(ast)) {
|
|
1488
|
-
return {};
|
|
1489
|
-
} else {
|
|
1490
|
-
throw new Error(`Unsupported type: ${ast?._tag}`);
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
}
|
|
1494
|
-
};
|
|
1495
|
-
|
|
1496
|
-
// src/components/Form/FormField/fields/AsyncSelectField/AsyncSelectField.tsx
|
|
1497
|
-
import React6, { useEffect as useEffect4, useMemo as useMemo4, useRef as useRef4 } from "react";
|
|
1498
|
-
|
|
1499
|
-
// src/components/Form/FormField/fields/SelectField/SelectField.tsx
|
|
1500
|
-
import React5, { useCallback as useCallback4 } from "react";
|
|
1501
|
-
import { invariant } from "@dxos/invariant";
|
|
1502
|
-
import { Icon as Icon2, Select } from "@dxos/react-ui";
|
|
1503
|
-
import { getStyles } from "@dxos/ui-theme";
|
|
1504
|
-
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/Form/FormField/fields/SelectField/SelectField.tsx";
|
|
1505
|
-
var SelectField = ({ type, readonly, placeholder, options, onValueChange, ...props }) => {
|
|
1506
|
-
const handleValueChange = useCallback4((value3) => onValueChange(type, value3), [
|
|
1507
|
-
type,
|
|
1508
|
-
onValueChange
|
|
1509
|
-
]);
|
|
1510
|
-
return /* @__PURE__ */ React5.createElement(FormRow, {
|
|
1511
|
-
readonly,
|
|
1512
|
-
renderStatic: (value3) => /* @__PURE__ */ React5.createElement("p", {
|
|
1513
|
-
className: "truncate min-w-0"
|
|
1514
|
-
}, options?.find(({ value: optionValue }) => optionValue === value3)?.label ?? String(value3)),
|
|
1515
|
-
...props
|
|
1516
|
-
}, ({ value: value3 }) => /* @__PURE__ */ React5.createElement(Select.Root, {
|
|
1517
|
-
value: value3,
|
|
1518
|
-
onValueChange: handleValueChange
|
|
1519
|
-
}, /* @__PURE__ */ React5.createElement(Select.TriggerButton, {
|
|
1520
|
-
classNames: "w-full",
|
|
1521
|
-
disabled: !!readonly,
|
|
1522
|
-
placeholder
|
|
1523
|
-
}), options?.length !== 0 && /* @__PURE__ */ React5.createElement(Select.Portal, null, /* @__PURE__ */ React5.createElement(Select.Content, null, /* @__PURE__ */ React5.createElement(Select.Viewport, null, options?.map(({ value: value4, label, secondaryLabel, icon, iconHue }) => (
|
|
1524
|
-
// NOTE: Numeric values are converted to and from strings.
|
|
1525
|
-
/* @__PURE__ */ React5.createElement(Select.Option, {
|
|
1526
|
-
key: String(value4),
|
|
1527
|
-
value: String(value4)
|
|
1528
|
-
}, /* @__PURE__ */ React5.createElement("span", {
|
|
1529
|
-
className: "flex items-center flex-row gap-2"
|
|
1530
|
-
}, icon && /* @__PURE__ */ React5.createElement(Icon2, {
|
|
1531
|
-
icon,
|
|
1532
|
-
classNames: getIconHueStyles(iconHue)
|
|
1533
|
-
}), label ?? String(value4), secondaryLabel && /* @__PURE__ */ React5.createElement("span", {
|
|
1534
|
-
className: "text-subdued text-xs"
|
|
1535
|
-
}, secondaryLabel)))
|
|
1536
|
-
))), /* @__PURE__ */ React5.createElement(Select.Arrow, null)))));
|
|
1537
|
-
};
|
|
1538
|
-
var getIconHueStyles = (iconHue) => {
|
|
1539
|
-
const styles3 = iconHue ? getStyles(iconHue) : void 0;
|
|
1540
|
-
return styles3?.fg;
|
|
1541
|
-
};
|
|
1542
|
-
var createSelectField = ({ options, defaultLabel = "Default" }) => {
|
|
1543
|
-
const normalized = options.map((option) => typeof option === "string" ? {
|
|
1544
|
-
value: option,
|
|
1545
|
-
label: option
|
|
1546
|
-
} : option);
|
|
1547
|
-
const hasDefault = defaultLabel !== null;
|
|
1548
|
-
const sentinel = "__default__";
|
|
1549
|
-
invariant(!normalized.some((option) => option.value === sentinel), `createSelectField: option value '${sentinel}' is reserved.`, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 57, S: void 0, A: ["!normalized.some((option)=>option.value === sentinel)", "`createSelectField: option value '${sentinel}' is reserved.`"] });
|
|
1550
|
-
return ({ type, readonly, onValueChange, ...props }) => /* @__PURE__ */ React5.createElement(FormRow, {
|
|
1551
|
-
readonly,
|
|
1552
|
-
renderStatic: (value3) => /* @__PURE__ */ React5.createElement("p", {
|
|
1553
|
-
className: "truncate min-w-0"
|
|
1554
|
-
}, normalized.find((option) => option.value === value3)?.label ?? String(value3 ?? "")),
|
|
1555
|
-
...props
|
|
1556
|
-
}, ({ value: value3 }) => /* @__PURE__ */ React5.createElement(Select.Root, {
|
|
1557
|
-
disabled: !!readonly,
|
|
1558
|
-
value: value3 ?? sentinel,
|
|
1559
|
-
onValueChange: (next) => onValueChange(type, hasDefault && next === sentinel ? void 0 : next)
|
|
1560
|
-
}, /* @__PURE__ */ React5.createElement(Select.TriggerButton, {
|
|
1561
|
-
classNames: "w-full",
|
|
1562
|
-
disabled: !!readonly
|
|
1563
|
-
}), normalized.length > 0 && /* @__PURE__ */ React5.createElement(Select.Portal, null, /* @__PURE__ */ React5.createElement(Select.Content, null, /* @__PURE__ */ React5.createElement(Select.Viewport, null, hasDefault && /* @__PURE__ */ React5.createElement(Select.Option, {
|
|
1564
|
-
value: sentinel
|
|
1565
|
-
}, defaultLabel), normalized.map((option) => /* @__PURE__ */ React5.createElement(Select.Option, {
|
|
1566
|
-
key: option.value,
|
|
1567
|
-
value: option.value
|
|
1568
|
-
}, option.label ?? option.value))), /* @__PURE__ */ React5.createElement(Select.Arrow, null)))));
|
|
1569
|
-
};
|
|
1570
|
-
|
|
1571
|
-
// src/components/Form/FormField/fields/AsyncSelectField/AsyncSelectField.tsx
|
|
1572
|
-
var AsyncSelectField = ({ lookup, ...fieldProps }) => {
|
|
1573
|
-
const values = useFormValues(AsyncSelectField.displayName);
|
|
1574
|
-
const subset = useMemo4(() => pickValues(values, lookup.deps), [
|
|
1575
|
-
values,
|
|
1576
|
-
lookup.deps
|
|
1577
|
-
]);
|
|
1578
|
-
const key = useMemo4(() => JSON.stringify(subset), [
|
|
1579
|
-
subset
|
|
1580
|
-
]);
|
|
1581
|
-
const { loading, data } = useAsyncFieldEffect(() => lookup.load(subset), key);
|
|
1582
|
-
const options = data ?? [];
|
|
1583
|
-
const { type, placeholder } = fieldProps;
|
|
1584
|
-
const current = fieldProps.getValue();
|
|
1585
|
-
const onValueChangeRef = useRef4(fieldProps.onValueChange);
|
|
1586
|
-
onValueChangeRef.current = fieldProps.onValueChange;
|
|
1587
|
-
const autoSelectedDataRef = useRef4(void 0);
|
|
1588
|
-
useEffect4(() => {
|
|
1589
|
-
if ((current == null || current === "") && data?.length === 1 && data !== autoSelectedDataRef.current) {
|
|
1590
|
-
autoSelectedDataRef.current = data;
|
|
1591
|
-
onValueChangeRef.current(type, data[0].value);
|
|
1592
|
-
}
|
|
1593
|
-
}, [
|
|
1594
|
-
current,
|
|
1595
|
-
data,
|
|
1596
|
-
type
|
|
1597
|
-
]);
|
|
1598
|
-
const resolvedPlaceholder = loading ? "Loading\u2026" : options.length === 0 ? "No options available" : placeholder;
|
|
1599
|
-
return /* @__PURE__ */ React6.createElement(SelectField, {
|
|
1600
|
-
...fieldProps,
|
|
1601
|
-
placeholder: resolvedPlaceholder,
|
|
1602
|
-
options: options.map(({ value: value3, label, secondaryLabel, icon }) => ({
|
|
1603
|
-
value: value3,
|
|
1604
|
-
label,
|
|
1605
|
-
secondaryLabel,
|
|
1606
|
-
icon
|
|
1607
|
-
}))
|
|
1608
|
-
});
|
|
1609
|
-
};
|
|
1610
|
-
AsyncSelectField.displayName = "Form.AsyncSelectField";
|
|
1611
|
-
|
|
1612
|
-
// src/components/Form/FormField/fields/AutofillField/AutofillField.tsx
|
|
1613
|
-
import React8, { useEffect as useEffect5, useMemo as useMemo5, useRef as useRef5 } from "react";
|
|
1614
|
-
|
|
1615
|
-
// src/components/Form/FormField/fields/TextField/TextField.tsx
|
|
1616
|
-
import React7, { useCallback as useCallback5 } from "react";
|
|
1617
|
-
import { Input as Input2 } from "@dxos/react-ui";
|
|
1618
|
-
var TextField = ({ type, readonly, placeholder, onBlur, onValueChange, ...props }) => {
|
|
1619
|
-
const handleChange = useCallback5((event) => onValueChange(type, event.target.value), [
|
|
1620
|
-
type,
|
|
1621
|
-
onValueChange
|
|
1622
|
-
]);
|
|
1623
|
-
return /* @__PURE__ */ React7.createElement(FormRow, {
|
|
1624
|
-
readonly,
|
|
1625
|
-
...props
|
|
1626
|
-
}, ({ value: value3 = "" }) => /* @__PURE__ */ React7.createElement(Input2.TextInput, {
|
|
1627
|
-
noAutoFill: true,
|
|
1628
|
-
disabled: !!readonly,
|
|
1629
|
-
placeholder,
|
|
1630
|
-
value: value3,
|
|
1631
|
-
onBlur,
|
|
1632
|
-
onChange: handleChange
|
|
1633
|
-
}));
|
|
1634
|
-
};
|
|
1635
|
-
|
|
1636
|
-
// src/components/Form/FormField/fields/AutofillField/AutofillField.tsx
|
|
1637
|
-
var AutofillField = ({ autofill: autofill2, ...fieldProps }) => {
|
|
1638
|
-
const values = useFormValues(AutofillField.displayName);
|
|
1639
|
-
const subset = useMemo5(() => pickValues(values, autofill2.deps), [
|
|
1640
|
-
values,
|
|
1641
|
-
autofill2.deps
|
|
1642
|
-
]);
|
|
1643
|
-
const key = useMemo5(() => JSON.stringify(subset), [
|
|
1644
|
-
subset
|
|
1645
|
-
]);
|
|
1646
|
-
const { data } = useAsyncFieldEffect(() => autofill2.derive(subset), key);
|
|
1647
|
-
const { type } = fieldProps;
|
|
1648
|
-
const getValueRef = useRef5(fieldProps.getValue);
|
|
1649
|
-
getValueRef.current = fieldProps.getValue;
|
|
1650
|
-
const onValueChangeRef = useRef5(fieldProps.onValueChange);
|
|
1651
|
-
onValueChangeRef.current = fieldProps.onValueChange;
|
|
1652
|
-
const lastFilledRef = useRef5(void 0);
|
|
1653
|
-
useEffect5(() => {
|
|
1654
|
-
const current = getValueRef.current();
|
|
1655
|
-
if (typeof data !== "string" || data.length === 0) {
|
|
1656
|
-
if (lastFilledRef.current != null && current === lastFilledRef.current) {
|
|
1657
|
-
lastFilledRef.current = void 0;
|
|
1658
|
-
onValueChangeRef.current(type, "");
|
|
1659
|
-
}
|
|
1660
|
-
return;
|
|
1661
|
-
}
|
|
1662
|
-
if (current === data) {
|
|
1663
|
-
lastFilledRef.current = data;
|
|
1664
|
-
return;
|
|
1665
|
-
}
|
|
1666
|
-
if (current == null || current === "" || current === lastFilledRef.current) {
|
|
1667
|
-
lastFilledRef.current = data;
|
|
1668
|
-
onValueChangeRef.current(type, data);
|
|
1669
|
-
}
|
|
1670
|
-
}, [
|
|
1671
|
-
data,
|
|
1672
|
-
type
|
|
1673
|
-
]);
|
|
1674
|
-
return /* @__PURE__ */ React8.createElement(TextField, fieldProps);
|
|
1675
|
-
};
|
|
1676
|
-
AutofillField.displayName = "Form.AutofillField";
|
|
1677
|
-
|
|
1678
|
-
// src/components/Form/FormField/fields/BooleanField/BooleanField.tsx
|
|
1679
|
-
import React9, { useCallback as useCallback6 } from "react";
|
|
1680
|
-
import { Input as Input3 } from "@dxos/react-ui";
|
|
1681
|
-
var BooleanField = ({ type, readonly, onValueChange, ...props }) => {
|
|
1682
|
-
const handleChange = useCallback6((value3) => onValueChange?.(type, value3), [
|
|
1683
|
-
type,
|
|
1684
|
-
onValueChange
|
|
1685
|
-
]);
|
|
1686
|
-
return /* @__PURE__ */ React9.createElement(FormRow, {
|
|
1687
|
-
readonly,
|
|
1688
|
-
...props
|
|
1689
|
-
}, ({ value: value3 }) => /* @__PURE__ */ React9.createElement(Input3.Block, null, /* @__PURE__ */ React9.createElement(Input3.Switch, {
|
|
1690
|
-
disabled: !!readonly,
|
|
1691
|
-
checked: value3,
|
|
1692
|
-
onCheckedChange: handleChange
|
|
1693
|
-
})));
|
|
1694
|
-
};
|
|
1695
|
-
|
|
1696
|
-
// src/components/Form/FormField/fields/ComboboxField/ComboboxField.tsx
|
|
1697
|
-
import React10, { useCallback as useCallback7, useMemo as useMemo6, useState as useState3 } from "react";
|
|
1698
|
-
import { Combobox } from "@dxos/react-ui-list";
|
|
1699
|
-
var ComboboxField = ({ lookup, type, readonly, placeholder, onValueChange, ...props }) => {
|
|
1700
|
-
const values = useFormValues(ComboboxField.displayName);
|
|
1701
|
-
const ownKey = props.jsonPath;
|
|
1702
|
-
const [query, setQuery] = useState3("");
|
|
1703
|
-
const lookupValues = useMemo6(() => {
|
|
1704
|
-
const subset = pickValues(values, lookup.deps);
|
|
1705
|
-
if (ownKey && lookup.deps.includes(ownKey)) {
|
|
1706
|
-
subset[ownKey] = query;
|
|
1707
|
-
}
|
|
1708
|
-
return subset;
|
|
1709
|
-
}, [
|
|
1710
|
-
values,
|
|
1711
|
-
lookup.deps,
|
|
1712
|
-
ownKey,
|
|
1713
|
-
query
|
|
1714
|
-
]);
|
|
1715
|
-
const key = useMemo6(() => JSON.stringify(lookupValues), [
|
|
1716
|
-
lookupValues
|
|
1717
|
-
]);
|
|
1718
|
-
const { data } = useAsyncFieldEffect(() => lookup.load(lookupValues), key);
|
|
1719
|
-
const trimmed = query.trim();
|
|
1720
|
-
const normalized = trimmed.toLowerCase();
|
|
1721
|
-
const results = useMemo6(() => normalized.length === 0 ? [] : (data ?? []).filter((option) => (option.label ?? option.value).toLowerCase().includes(normalized)), [
|
|
1722
|
-
data,
|
|
1723
|
-
normalized
|
|
1724
|
-
]);
|
|
1725
|
-
const hasExact = results.some((option) => option.value === trimmed);
|
|
1726
|
-
const handleValueChange = useCallback7((next) => onValueChange(type, next), [
|
|
1727
|
-
onValueChange,
|
|
1728
|
-
type
|
|
1729
|
-
]);
|
|
1730
|
-
const handleOpenChange = useCallback7((open) => {
|
|
1731
|
-
if (!open) {
|
|
1732
|
-
setQuery("");
|
|
1733
|
-
}
|
|
1734
|
-
}, []);
|
|
1735
|
-
return /* @__PURE__ */ React10.createElement(FormRow, {
|
|
1736
|
-
readonly,
|
|
1737
|
-
renderStatic: (value3) => /* @__PURE__ */ React10.createElement("p", {
|
|
1738
|
-
className: "truncate min-w-0"
|
|
1739
|
-
}, value3 ?? ""),
|
|
1740
|
-
...props
|
|
1741
|
-
}, ({ value: value3 = "" }) => /* @__PURE__ */ React10.createElement(Combobox.Root, {
|
|
1742
|
-
value: value3,
|
|
1743
|
-
onValueChange: handleValueChange,
|
|
1744
|
-
onOpenChange: handleOpenChange,
|
|
1745
|
-
placeholder
|
|
1746
|
-
}, /* @__PURE__ */ React10.createElement(Combobox.Trigger, {
|
|
1747
|
-
disabled: !!readonly,
|
|
1748
|
-
classNames: "w-full"
|
|
1749
|
-
}), /* @__PURE__ */ React10.createElement(Combobox.Portal, null, /* @__PURE__ */ React10.createElement(Combobox.Content, {
|
|
1750
|
-
resetSelectionOnChange: true
|
|
1751
|
-
}, /* @__PURE__ */ React10.createElement(Combobox.Input, {
|
|
1752
|
-
autoFocus: true,
|
|
1753
|
-
value: query,
|
|
1754
|
-
onValueChange: setQuery,
|
|
1755
|
-
placeholder
|
|
1756
|
-
}), /* @__PURE__ */ React10.createElement(Combobox.List, null, results.map((option) => /* @__PURE__ */ React10.createElement(Combobox.Item, {
|
|
1757
|
-
key: option.value,
|
|
1758
|
-
value: option.value,
|
|
1759
|
-
label: option.label ?? option.value,
|
|
1760
|
-
suffix: option.secondaryLabel
|
|
1761
|
-
})), normalized.length > 0 && !hasExact && /* @__PURE__ */ React10.createElement(Combobox.Item, {
|
|
1762
|
-
value: trimmed,
|
|
1763
|
-
label: trimmed
|
|
1764
|
-
})), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null)))));
|
|
1765
|
-
};
|
|
1766
|
-
ComboboxField.displayName = "Form.ComboboxField";
|
|
1767
|
-
|
|
1768
|
-
// src/components/Form/FormField/fields/DateField/DateField.tsx
|
|
1769
|
-
import { format as formatDate3 } from "date-fns";
|
|
1770
|
-
import React11, { useCallback as useCallback8 } from "react";
|
|
1771
|
-
import { Format as Format5 } from "@dxos/echo";
|
|
1772
|
-
import { Input as Input4 } from "@dxos/react-ui";
|
|
1773
|
-
var isoToLocalDateTime = (value3) => {
|
|
1774
|
-
if (!value3) {
|
|
1775
|
-
return "";
|
|
1776
|
-
}
|
|
1777
|
-
const date = new Date(value3);
|
|
1778
|
-
if (Number.isNaN(date.getTime())) {
|
|
1779
|
-
return "";
|
|
1780
|
-
}
|
|
1781
|
-
return formatDate3(date, "yyyy-MM-dd'T'HH:mm");
|
|
1782
|
-
};
|
|
1783
|
-
var localDateTimeToIso = (value3) => {
|
|
1784
|
-
if (!value3) {
|
|
1785
|
-
return void 0;
|
|
1786
|
-
}
|
|
1787
|
-
const date = new Date(value3);
|
|
1788
|
-
return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
|
|
1789
|
-
};
|
|
1790
|
-
var DateField = ({ type, format, readonly, placeholder: _placeholder, onValueChange, onBlur: _onBlur, ...props }) => {
|
|
1791
|
-
const handleSimpleChange = useCallback8((next) => onValueChange(type, next), [
|
|
1792
|
-
type,
|
|
1793
|
-
onValueChange
|
|
1794
|
-
]);
|
|
1795
|
-
const handleDateTimeChange = useCallback8((next) => {
|
|
1796
|
-
const iso = localDateTimeToIso(next);
|
|
1797
|
-
onValueChange(type, iso);
|
|
1798
|
-
}, [
|
|
1799
|
-
type,
|
|
1800
|
-
onValueChange
|
|
1801
|
-
]);
|
|
1802
|
-
return /* @__PURE__ */ React11.createElement(FormRow, {
|
|
1803
|
-
...props,
|
|
1804
|
-
readonly,
|
|
1805
|
-
format
|
|
1806
|
-
}, ({ value: value3 }) => {
|
|
1807
|
-
switch (format) {
|
|
1808
|
-
case Format5.TypeFormat.Date:
|
|
1809
|
-
return /* @__PURE__ */ React11.createElement("div", {
|
|
1810
|
-
className: "grid grid-cols-[minmax(0,1fr)_min-content] gap-1 items-stretch"
|
|
1811
|
-
}, /* @__PURE__ */ React11.createElement(Input4.Date, {
|
|
1812
|
-
classNames: "min-w-0 overflow-hidden",
|
|
1813
|
-
disabled: readonly,
|
|
1814
|
-
value: value3 ?? "",
|
|
1815
|
-
onValueChange: handleSimpleChange
|
|
1816
|
-
}), /* @__PURE__ */ React11.createElement(Input4.TriggerIcon, null));
|
|
1817
|
-
case Format5.TypeFormat.Time:
|
|
1818
|
-
return /* @__PURE__ */ React11.createElement(Input4.Time, {
|
|
1819
|
-
disabled: !!readonly,
|
|
1820
|
-
value: value3 ?? "",
|
|
1821
|
-
onValueChange: handleSimpleChange
|
|
1822
|
-
});
|
|
1823
|
-
case Format5.TypeFormat.DateTime:
|
|
1824
|
-
default:
|
|
1825
|
-
return /* @__PURE__ */ React11.createElement("div", {
|
|
1826
|
-
className: "grid grid-cols-[minmax(0,1fr)_min-content] gap-1 items-stretch"
|
|
1827
|
-
}, /* @__PURE__ */ React11.createElement(Input4.DateTime, {
|
|
1828
|
-
classNames: "min-w-0 overflow-hidden",
|
|
1829
|
-
disabled: readonly,
|
|
1830
|
-
value: isoToLocalDateTime(value3),
|
|
1831
|
-
onValueChange: handleDateTimeChange
|
|
1832
|
-
}), /* @__PURE__ */ React11.createElement(Input4.TriggerIcon, null));
|
|
1833
|
-
}
|
|
1834
|
-
});
|
|
1835
|
-
};
|
|
1836
|
-
|
|
1837
|
-
// src/components/Form/FormField/fields/GeoPointField/GeoPointField.tsx
|
|
1838
|
-
import React12, { useCallback as useCallback9, useEffect as useEffect6, useMemo as useMemo7, useState as useState4 } from "react";
|
|
1839
|
-
import { GeoLocation as GeoLocation3 } from "@dxos/echo/Format";
|
|
1840
|
-
import { Input as Input5, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
1841
|
-
import { safeParseFloat } from "@dxos/util";
|
|
1842
|
-
import { translationKey as translationKey3 } from "#translations";
|
|
1843
|
-
var GeoPointField = ({ type, readonly, getValue, onValueChange, onBlur, ...props }) => {
|
|
1844
|
-
const { t } = useTranslation3(translationKey3);
|
|
1845
|
-
const geoPoint = useMemo7(() => getValue() ?? [
|
|
1846
|
-
0,
|
|
1847
|
-
0
|
|
1848
|
-
], [
|
|
1849
|
-
getValue
|
|
1850
|
-
]);
|
|
1851
|
-
const value3 = useMemo7(() => GeoLocation3.fromGeoPoint(geoPoint), [
|
|
1852
|
-
geoPoint
|
|
1853
|
-
]);
|
|
1854
|
-
const [longitudeText, setLongitudeText] = useState4(value3.longitude?.toString());
|
|
1855
|
-
const [latitudeText, setLatitudeText] = useState4(value3.latitude?.toString());
|
|
1856
|
-
useEffect6(() => {
|
|
1857
|
-
const location = GeoLocation3.fromGeoPoint(geoPoint);
|
|
1858
|
-
setLongitudeText(location.longitude?.toString());
|
|
1859
|
-
setLatitudeText(location.latitude?.toString());
|
|
1860
|
-
}, [
|
|
1861
|
-
geoPoint
|
|
1862
|
-
]);
|
|
1863
|
-
const handleChange = useCallback9((coordinateType, setText) => (event) => {
|
|
1864
|
-
const inputText = event.target.value;
|
|
1865
|
-
setText(inputText);
|
|
1866
|
-
if (inputText !== "" && inputText !== "-") {
|
|
1867
|
-
const coord = safeParseFloat(inputText);
|
|
1868
|
-
if (coord !== void 0 && !isNaN(coord)) {
|
|
1869
|
-
const currentLocation = GeoLocation3.fromGeoPoint(getValue() ?? [
|
|
1870
|
-
0,
|
|
1871
|
-
0
|
|
1872
|
-
]);
|
|
1873
|
-
const newLocation = {
|
|
1874
|
-
...currentLocation,
|
|
1875
|
-
[coordinateType]: coord
|
|
1876
|
-
};
|
|
1877
|
-
const newValue = GeoLocation3.toGeoPoint(newLocation);
|
|
1878
|
-
onValueChange(type, newValue);
|
|
1879
|
-
}
|
|
1880
|
-
}
|
|
1881
|
-
}, [
|
|
1882
|
-
type,
|
|
1883
|
-
getValue,
|
|
1884
|
-
onValueChange
|
|
1885
|
-
]);
|
|
1886
|
-
return /* @__PURE__ */ React12.createElement(FormRow, {
|
|
1887
|
-
readonly,
|
|
1888
|
-
getValue,
|
|
1889
|
-
standalone: true,
|
|
1890
|
-
renderStatic: (point) => {
|
|
1891
|
-
const location = GeoLocation3.fromGeoPoint(point ?? [
|
|
1892
|
-
0,
|
|
1893
|
-
0
|
|
1894
|
-
]);
|
|
1895
|
-
return !location.latitude && !location.longitude ? null : /* @__PURE__ */ React12.createElement(LatLng, location);
|
|
1896
|
-
},
|
|
1897
|
-
...props
|
|
1898
|
-
}, ({ presentation }) => /* @__PURE__ */ React12.createElement("div", {
|
|
1899
|
-
className: "grid grid-cols-2 gap-form-gap"
|
|
1900
|
-
}, /* @__PURE__ */ React12.createElement("div", null, /* @__PURE__ */ React12.createElement(Input5.Root, null, presentation.showLabel && /* @__PURE__ */ React12.createElement(Input5.Label, null, t("latitude.label")), /* @__PURE__ */ React12.createElement(Input5.TextInput, {
|
|
1901
|
-
type: "number",
|
|
1902
|
-
step: "0.00001",
|
|
1903
|
-
min: "-90",
|
|
1904
|
-
max: "90",
|
|
1905
|
-
disabled: !!readonly,
|
|
1906
|
-
placeholder: t("latitude.placeholder"),
|
|
1907
|
-
value: latitudeText ?? "",
|
|
1908
|
-
onChange: handleChange("latitude", setLatitudeText),
|
|
1909
|
-
onBlur
|
|
1910
|
-
}))), /* @__PURE__ */ React12.createElement("div", null, /* @__PURE__ */ React12.createElement(Input5.Root, null, presentation.showLabel && /* @__PURE__ */ React12.createElement(Input5.Label, null, t("longitude.label")), /* @__PURE__ */ React12.createElement(Input5.TextInput, {
|
|
1911
|
-
type: "number",
|
|
1912
|
-
step: "0.00001",
|
|
1913
|
-
min: "-180",
|
|
1914
|
-
max: "180",
|
|
1915
|
-
disabled: !!readonly,
|
|
1916
|
-
placeholder: t("longitude.placeholder"),
|
|
1917
|
-
value: longitudeText ?? "",
|
|
1918
|
-
onChange: handleChange("longitude", setLongitudeText),
|
|
1919
|
-
onBlur
|
|
1920
|
-
})))));
|
|
1921
|
-
};
|
|
1922
|
-
var LatLng = ({ latitude = 0, longitude = 0 }) => {
|
|
1923
|
-
const latHem = latitude >= 0 ? "N" : "S";
|
|
1924
|
-
const lngHem = longitude >= 0 ? "E" : "W";
|
|
1925
|
-
return /* @__PURE__ */ React12.createElement("span", {
|
|
1926
|
-
className: "inline-flex items-center gap-form-gap"
|
|
1927
|
-
}, /* @__PURE__ */ React12.createElement("span", null, /* @__PURE__ */ React12.createElement("span", null, Math.abs(latitude).toFixed(5)), /* @__PURE__ */ React12.createElement("span", {
|
|
1928
|
-
className: "text-subdued"
|
|
1929
|
-
}, "\xB0", latHem)), /* @__PURE__ */ React12.createElement("span", null, /* @__PURE__ */ React12.createElement("span", null, Math.abs(longitude).toFixed(5)), /* @__PURE__ */ React12.createElement("span", {
|
|
1930
|
-
className: "text-subdued"
|
|
1931
|
-
}, "\xB0", lngHem)));
|
|
1932
|
-
};
|
|
1933
|
-
|
|
1934
|
-
// src/components/Form/FormField/fields/MarkdownField/MarkdownField.tsx
|
|
1935
|
-
import { useAtomValue } from "@effect-atom/atom-react";
|
|
1936
|
-
import React13, { useCallback as useCallback10, useMemo as useMemo8 } from "react";
|
|
1937
|
-
import { Ref as Ref4 } from "@dxos/echo";
|
|
1938
|
-
import { Doc } from "@dxos/echo-doc";
|
|
1939
|
-
import { IconButton as IconButton2, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
1940
|
-
import { Editor, useBasicMarkdownExtensions } from "@dxos/react-ui-editor";
|
|
1941
|
-
import { Text } from "@dxos/schema";
|
|
1942
|
-
import { createDataExtensions } from "@dxos/ui-editor";
|
|
1943
|
-
import { translationKey as translationKey4 } from "#translations";
|
|
1944
|
-
var editorClassNames = [
|
|
1945
|
-
"min-h-[6lh] transition-colors rounded-xs p-1 px-2 bg-input-surface border border-input-separator",
|
|
1946
|
-
"focus:border-separator focus-within:border-separator focus-within:bg-focus-surface",
|
|
1947
|
-
"focus-within:ring-2 focus-within:ring-offset-0 focus-within:ring-focus-ring-subtle focus-within:z-[1]"
|
|
1948
|
-
];
|
|
1949
|
-
var MarkdownField = ({ type, readonly, placeholder, db, getValue, onValueChange, ...props }) => {
|
|
1950
|
-
const isRef = Ref4.isRefType(type);
|
|
1951
|
-
const renderStatic = (value3) => {
|
|
1952
|
-
if (isRef) {
|
|
1953
|
-
const reference = value3;
|
|
1954
|
-
return reference ? /* @__PURE__ */ React13.createElement(RefStaticText, {
|
|
1955
|
-
reference
|
|
1956
|
-
}) : null;
|
|
1957
|
-
}
|
|
1958
|
-
return /* @__PURE__ */ React13.createElement("p", {
|
|
1959
|
-
className: "whitespace-pre-wrap"
|
|
1960
|
-
}, value3 ?? "");
|
|
1961
|
-
};
|
|
1962
|
-
const renderEditor = (value3) => {
|
|
1963
|
-
if (isRef) {
|
|
1964
|
-
const reference = value3;
|
|
1965
|
-
if (reference) {
|
|
1966
|
-
return /* @__PURE__ */ React13.createElement(RefMarkdownEditor, {
|
|
1967
|
-
reference,
|
|
1968
|
-
placeholder,
|
|
1969
|
-
readonly: !!readonly
|
|
1970
|
-
});
|
|
1971
|
-
}
|
|
1972
|
-
if (readonly) {
|
|
1973
|
-
return null;
|
|
1974
|
-
}
|
|
1975
|
-
return /* @__PURE__ */ React13.createElement(CreateTextButton, {
|
|
1976
|
-
db,
|
|
1977
|
-
disabled: !db,
|
|
1978
|
-
onCreate: (ref) => onValueChange(type, ref)
|
|
1979
|
-
});
|
|
1980
|
-
}
|
|
1981
|
-
return /* @__PURE__ */ React13.createElement(StringMarkdownEditor, {
|
|
1982
|
-
value: value3 ?? "",
|
|
1983
|
-
placeholder,
|
|
1984
|
-
readonly: !!readonly,
|
|
1985
|
-
onChange: (next) => onValueChange(type, next)
|
|
1986
|
-
});
|
|
1987
|
-
};
|
|
1988
|
-
return /* @__PURE__ */ React13.createElement(FormRow, {
|
|
1989
|
-
readonly,
|
|
1990
|
-
getValue,
|
|
1991
|
-
renderStatic,
|
|
1992
|
-
...props
|
|
1993
|
-
}, ({ value: value3 }) => renderEditor(value3));
|
|
1994
|
-
};
|
|
1995
|
-
var RefStaticText = ({ reference }) => {
|
|
1996
|
-
const text = useAtomValue(useMemo8(() => reference.atom, [
|
|
1997
|
-
reference
|
|
1998
|
-
]));
|
|
1999
|
-
if (!text?.content) {
|
|
2000
|
-
return null;
|
|
2001
|
-
}
|
|
2002
|
-
return /* @__PURE__ */ React13.createElement("p", {
|
|
2003
|
-
className: "whitespace-pre-wrap"
|
|
2004
|
-
}, text.content);
|
|
2005
|
-
};
|
|
2006
|
-
var RefMarkdownEditor = ({ reference, placeholder, readonly }) => {
|
|
2007
|
-
const text = useAtomValue(useMemo8(() => reference.atom, [
|
|
2008
|
-
reference
|
|
2009
|
-
]));
|
|
2010
|
-
const dataExtensions = useMemo8(() => text ? [
|
|
2011
|
-
createDataExtensions({
|
|
2012
|
-
id: reference.uri,
|
|
2013
|
-
text: Doc.createAccessor(text, [
|
|
2014
|
-
"content"
|
|
2015
|
-
])
|
|
2016
|
-
})
|
|
2017
|
-
] : [], [
|
|
2018
|
-
text,
|
|
2019
|
-
reference
|
|
2020
|
-
]);
|
|
2021
|
-
const extensions = useBasicMarkdownExtensions({
|
|
2022
|
-
placeholder,
|
|
2023
|
-
readonly,
|
|
2024
|
-
extensions: dataExtensions
|
|
2025
|
-
});
|
|
2026
|
-
if (!text) {
|
|
2027
|
-
return null;
|
|
2028
|
-
}
|
|
2029
|
-
return /* @__PURE__ */ React13.createElement(Editor.Root, null, /* @__PURE__ */ React13.createElement(Editor.View, {
|
|
2030
|
-
classNames: editorClassNames,
|
|
2031
|
-
extensions
|
|
2032
|
-
}));
|
|
2033
|
-
};
|
|
2034
|
-
var StringMarkdownEditor = ({ value: value3, placeholder, readonly, onChange }) => {
|
|
2035
|
-
const extensions = useBasicMarkdownExtensions({
|
|
2036
|
-
placeholder,
|
|
2037
|
-
readonly
|
|
2038
|
-
});
|
|
2039
|
-
const handleChange = useCallback10((next) => onChange(next), [
|
|
2040
|
-
onChange
|
|
2041
|
-
]);
|
|
2042
|
-
return /* @__PURE__ */ React13.createElement(Editor.Root, null, /* @__PURE__ */ React13.createElement(Editor.View, {
|
|
2043
|
-
classNames: editorClassNames,
|
|
2044
|
-
extensions,
|
|
2045
|
-
value: value3,
|
|
2046
|
-
onChange: readonly ? void 0 : handleChange
|
|
2047
|
-
}));
|
|
2048
|
-
};
|
|
2049
|
-
var CreateTextButton = ({ db, disabled, onCreate }) => {
|
|
2050
|
-
const { t } = useTranslation4(translationKey4);
|
|
2051
|
-
const handleClick = useCallback10(() => {
|
|
2052
|
-
if (!db) {
|
|
2053
|
-
return;
|
|
2054
|
-
}
|
|
2055
|
-
onCreate(Ref4.make(db.add(Text.make())));
|
|
2056
|
-
}, [
|
|
2057
|
-
db,
|
|
2058
|
-
onCreate
|
|
2059
|
-
]);
|
|
2060
|
-
return /* @__PURE__ */ React13.createElement(IconButton2, {
|
|
2061
|
-
icon: "ph--plus--regular",
|
|
2062
|
-
label: t("create-text.label"),
|
|
2063
|
-
onClick: handleClick,
|
|
2064
|
-
disabled
|
|
2065
|
-
});
|
|
2066
|
-
};
|
|
2067
|
-
|
|
2068
|
-
// src/components/Form/FormField/fields/NumberField/NumberField.tsx
|
|
2069
|
-
import * as Option5 from "effect/Option";
|
|
2070
|
-
import * as SchemaAST6 from "effect/SchemaAST";
|
|
2071
|
-
import React14, { useCallback as useCallback11, useEffect as useEffect7, useState as useState5 } from "react";
|
|
2072
|
-
import { Input as Input6 } from "@dxos/react-ui";
|
|
2073
|
-
import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
|
|
2074
|
-
var getNumericConstraints = (ast) => {
|
|
2075
|
-
let node = ast;
|
|
2076
|
-
let min;
|
|
2077
|
-
let max;
|
|
2078
|
-
let integer = false;
|
|
2079
|
-
while (node && SchemaAST6.isRefinement(node)) {
|
|
2080
|
-
const jsonSchema = Option5.getOrUndefined(SchemaAST6.getJSONSchemaAnnotation(node));
|
|
2081
|
-
if (jsonSchema != null) {
|
|
2082
|
-
if ("minimum" in jsonSchema && typeof jsonSchema.minimum === "number") {
|
|
2083
|
-
min = min === void 0 ? jsonSchema.minimum : Math.max(min, jsonSchema.minimum);
|
|
2084
|
-
}
|
|
2085
|
-
if ("maximum" in jsonSchema && typeof jsonSchema.maximum === "number") {
|
|
2086
|
-
max = max === void 0 ? jsonSchema.maximum : Math.min(max, jsonSchema.maximum);
|
|
2087
|
-
}
|
|
2088
|
-
if ("type" in jsonSchema && jsonSchema.type === "integer" || "multipleOf" in jsonSchema && jsonSchema.multipleOf === 1) {
|
|
2089
|
-
integer = true;
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
node = node.from;
|
|
2093
|
-
}
|
|
2094
|
-
return {
|
|
2095
|
-
min,
|
|
2096
|
-
max,
|
|
2097
|
-
integer
|
|
2098
|
-
};
|
|
2099
|
-
};
|
|
2100
|
-
var NumberField = ({ type, readonly, placeholder, getValue, onValueChange, onBlur, ...props }) => {
|
|
2101
|
-
const { min, max, integer } = getNumericConstraints(type);
|
|
2102
|
-
const clamp = useCallback11((n) => {
|
|
2103
|
-
let value3 = integer ? Math.round(n) : n;
|
|
2104
|
-
if (min !== void 0) {
|
|
2105
|
-
value3 = Math.max(min, value3);
|
|
2106
|
-
}
|
|
2107
|
-
if (max !== void 0) {
|
|
2108
|
-
value3 = Math.min(max, value3);
|
|
2109
|
-
}
|
|
2110
|
-
return value3;
|
|
2111
|
-
}, [
|
|
2112
|
-
min,
|
|
2113
|
-
max,
|
|
2114
|
-
integer
|
|
2115
|
-
]);
|
|
2116
|
-
const [raw, setRaw] = useState5(() => {
|
|
2117
|
-
const v = getValue();
|
|
2118
|
-
return v !== void 0 ? String(v) : "";
|
|
2119
|
-
});
|
|
2120
|
-
const externalValue = getValue();
|
|
2121
|
-
useEffect7(() => {
|
|
2122
|
-
if (externalValue !== safeParseFloat2(raw)) {
|
|
2123
|
-
setRaw(externalValue !== void 0 ? String(externalValue) : "");
|
|
2124
|
-
}
|
|
2125
|
-
}, [
|
|
2126
|
-
externalValue
|
|
2127
|
-
]);
|
|
2128
|
-
const handleChange = useCallback11((event) => {
|
|
2129
|
-
const value3 = event.target.value;
|
|
2130
|
-
setRaw(value3);
|
|
2131
|
-
const parsed = safeParseFloat2(value3);
|
|
2132
|
-
if (parsed !== void 0) {
|
|
2133
|
-
onValueChange(type, clamp(parsed));
|
|
2134
|
-
}
|
|
2135
|
-
}, [
|
|
2136
|
-
type,
|
|
2137
|
-
onValueChange,
|
|
2138
|
-
clamp
|
|
2139
|
-
]);
|
|
2140
|
-
const handleBlur = useCallback11((event) => {
|
|
2141
|
-
const parsed = safeParseFloat2(raw);
|
|
2142
|
-
if (parsed === void 0) {
|
|
2143
|
-
const committed = getValue();
|
|
2144
|
-
setRaw(committed !== void 0 ? String(committed) : "");
|
|
2145
|
-
} else {
|
|
2146
|
-
setRaw(String(clamp(parsed)));
|
|
2147
|
-
}
|
|
2148
|
-
onBlur(event);
|
|
2149
|
-
}, [
|
|
2150
|
-
raw,
|
|
2151
|
-
getValue,
|
|
2152
|
-
onBlur,
|
|
2153
|
-
clamp
|
|
2154
|
-
]);
|
|
2155
|
-
return /* @__PURE__ */ React14.createElement(FormRow, {
|
|
2156
|
-
readonly,
|
|
2157
|
-
getValue,
|
|
2158
|
-
...props
|
|
2159
|
-
}, () => /* @__PURE__ */ React14.createElement(Input6.TextInput, {
|
|
2160
|
-
type: "number",
|
|
2161
|
-
disabled: !!readonly,
|
|
2162
|
-
placeholder,
|
|
2163
|
-
value: raw,
|
|
2164
|
-
min,
|
|
2165
|
-
max,
|
|
2166
|
-
step: integer ? 1 : void 0,
|
|
2167
|
-
onChange: handleChange,
|
|
2168
|
-
onBlur: handleBlur
|
|
2169
|
-
}));
|
|
2170
|
-
};
|
|
2171
|
-
|
|
2172
|
-
// src/components/Form/FormField/fields/PasswordField/PasswordField.tsx
|
|
2173
|
-
import React15, { useCallback as useCallback12 } from "react";
|
|
2174
|
-
import { Input as Input7 } from "@dxos/react-ui";
|
|
2175
|
-
var PasswordField = ({ type, readonly, placeholder, onBlur, onValueChange, ...props }) => {
|
|
2176
|
-
const handleChange = useCallback12((event) => onValueChange(type, event.target.value), [
|
|
2177
|
-
type,
|
|
2178
|
-
onValueChange
|
|
2179
|
-
]);
|
|
2180
|
-
return /* @__PURE__ */ React15.createElement(FormRow, {
|
|
2181
|
-
readonly,
|
|
2182
|
-
...props
|
|
2183
|
-
}, ({ value: value3 = "" }) => /* @__PURE__ */ React15.createElement(Input7.TextInput, {
|
|
2184
|
-
type: "password",
|
|
2185
|
-
noAutoFill: true,
|
|
2186
|
-
disabled: !!readonly,
|
|
2187
|
-
placeholder,
|
|
2188
|
-
value: value3,
|
|
2189
|
-
onBlur,
|
|
2190
|
-
onChange: handleChange
|
|
2191
|
-
}));
|
|
2192
|
-
};
|
|
2193
|
-
|
|
2194
|
-
// src/components/Form/FormField/fields/RefField/RefField.tsx
|
|
2195
|
-
import React17, { useCallback as useCallback14, useMemo as useMemo9, useState as useState7 } from "react";
|
|
2196
|
-
import "@dxos/lit-ui/dx-tag-picker.pcss";
|
|
2197
|
-
import { Entity, Filter, Obj, Query, Ref as Ref5, Scope, Type as Type2 } from "@dxos/echo";
|
|
2198
|
-
import { useType as defaultUseType2, useQuery } from "@dxos/echo-react";
|
|
2199
|
-
import { ANY_OBJECT_TYPENAME, ReferenceAnnotationId as ReferenceAnnotationId2 } from "@dxos/echo/internal";
|
|
2200
|
-
import { SchemaEx as SchemaEx7 } from "@dxos/effect";
|
|
2201
|
-
import { DXN as DXN2, EID, URI } from "@dxos/keys";
|
|
2202
|
-
import { DxAnchor } from "@dxos/lit-ui/react";
|
|
2203
|
-
import { Button, Icon as Icon3, Input as Input8, useTranslation as useTranslation6 } from "@dxos/react-ui";
|
|
2204
|
-
import { ParentLabelAnnotationId } from "@dxos/schema";
|
|
2205
|
-
import { translationKey as translationKey6 } from "#translations";
|
|
2206
|
-
|
|
2207
|
-
// src/components/ObjectPicker/ObjectPicker.tsx
|
|
2208
|
-
import React16, { forwardRef, useCallback as useCallback13, useState as useState6 } from "react";
|
|
2209
|
-
import { Popover, useTranslation as useTranslation5 } from "@dxos/react-ui";
|
|
2210
|
-
import { Combobox as Combobox2 } from "@dxos/react-ui-list";
|
|
2211
|
-
import { useSearchListResults } from "@dxos/react-ui-search";
|
|
2212
|
-
import { translationKey as translationKey5 } from "#translations";
|
|
2213
|
-
var ObjectPickerContent = /* @__PURE__ */ forwardRef(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, createFieldMap: createFieldMap3, onSelect, onCreate, ...props }, forwardedRef) => {
|
|
2214
|
-
const { t } = useTranslation5(translationKey5);
|
|
2215
|
-
const [showForm, setShowForm] = useState6(false);
|
|
2216
|
-
const [formInitialValue, setFormInitialValue] = useState6("");
|
|
2217
|
-
const { results, query, handleSearch } = useSearchListResults({
|
|
2218
|
-
items: options
|
|
2219
|
-
});
|
|
2220
|
-
const handleFormSave = useCallback13(async (values) => {
|
|
2221
|
-
await onCreate?.(values);
|
|
2222
|
-
setShowForm(false);
|
|
2223
|
-
setFormInitialValue("");
|
|
2224
|
-
}, [
|
|
2225
|
-
onCreate
|
|
2226
|
-
]);
|
|
2227
|
-
const handleFormCancel = useCallback13(() => {
|
|
2228
|
-
setShowForm(false);
|
|
2229
|
-
setFormInitialValue("");
|
|
2230
|
-
}, []);
|
|
2231
|
-
const handleKeyDown = useCallback13((event) => {
|
|
2232
|
-
if (event.key === "Enter" && createSchema && event.currentTarget.querySelector('[role="option"][aria-selected="true"][data-value="__create__"]')) {
|
|
2233
|
-
event.stopPropagation();
|
|
2234
|
-
event.preventDefault();
|
|
2235
|
-
const input = event.currentTarget.querySelector('input[type="text"]');
|
|
2236
|
-
const currentQuery = input?.value || "";
|
|
2237
|
-
setFormInitialValue(currentQuery);
|
|
2238
|
-
setShowForm(true);
|
|
2239
|
-
}
|
|
2240
|
-
}, [
|
|
2241
|
-
createSchema
|
|
2242
|
-
]);
|
|
2243
|
-
if (showForm && createSchema) {
|
|
2244
|
-
return /* @__PURE__ */ React16.createElement(Combobox2.Content, {
|
|
2245
|
-
...props,
|
|
2246
|
-
onKeyDownCapture: handleKeyDown,
|
|
2247
|
-
ref: forwardedRef
|
|
2248
|
-
}, /* @__PURE__ */ React16.createElement(Popover.Viewport, null, /* @__PURE__ */ React16.createElement(Form.Root, {
|
|
2249
|
-
testId: "create-referenced-object-form",
|
|
2250
|
-
schema: createSchema,
|
|
2251
|
-
defaultValues: createInitialValuePath ? {
|
|
2252
|
-
[createInitialValuePath]: formInitialValue
|
|
2253
|
-
} : {},
|
|
2254
|
-
fieldMap: createFieldMap3,
|
|
2255
|
-
onSave: handleFormSave,
|
|
2256
|
-
onCancel: handleFormCancel
|
|
2257
|
-
}, /* @__PURE__ */ React16.createElement(Form.Viewport, null, /* @__PURE__ */ React16.createElement(Form.Content, null, /* @__PURE__ */ React16.createElement(Form.FieldSet, null), /* @__PURE__ */ React16.createElement(Form.Actions, null))))), /* @__PURE__ */ React16.createElement(Combobox2.Arrow, null));
|
|
2258
|
-
}
|
|
2259
|
-
return /* @__PURE__ */ React16.createElement(Combobox2.Content, {
|
|
2260
|
-
...props,
|
|
2261
|
-
onKeyDownCapture: handleKeyDown,
|
|
2262
|
-
ref: forwardedRef
|
|
2263
|
-
}, /* @__PURE__ */ React16.createElement(Combobox2.Input, {
|
|
2264
|
-
placeholder: t("ref-field-combobox-input.placeholder"),
|
|
2265
|
-
autoFocus: true,
|
|
2266
|
-
value: query,
|
|
2267
|
-
onValueChange: handleSearch
|
|
2268
|
-
}), /* @__PURE__ */ React16.createElement(Combobox2.List, null, results.map((option) => /* @__PURE__ */ React16.createElement(Combobox2.Item, {
|
|
2269
|
-
key: option.id,
|
|
2270
|
-
value: option.id,
|
|
2271
|
-
label: option.label,
|
|
2272
|
-
description: option.description,
|
|
2273
|
-
checked: selectedIds?.includes(option.id),
|
|
2274
|
-
onSelect: () => onSelect?.(option.id),
|
|
2275
|
-
classNames: "flex items-center gap-2"
|
|
2276
|
-
})), createSchema && onCreate && /* @__PURE__ */ React16.createElement(CreateItem, {
|
|
2277
|
-
query,
|
|
2278
|
-
createOptionLabel,
|
|
2279
|
-
createOptionIcon: createOptionIcon ?? "ph--plus--regular",
|
|
2280
|
-
onCreateItemSelect: (currentQuery) => {
|
|
2281
|
-
setFormInitialValue(currentQuery);
|
|
2282
|
-
setShowForm(true);
|
|
2283
|
-
}
|
|
2284
|
-
})), /* @__PURE__ */ React16.createElement(Combobox2.Arrow, null));
|
|
2285
|
-
});
|
|
2286
|
-
var CreateItem = ({ query, createOptionLabel, createOptionIcon, onCreateItemSelect }) => {
|
|
2287
|
-
const { t } = useTranslation5(translationKey5);
|
|
2288
|
-
const label = createOptionLabel ? t(createOptionLabel[0], {
|
|
2289
|
-
ns: createOptionLabel[1].ns,
|
|
2290
|
-
text: query
|
|
2291
|
-
}) : t("create-option.label");
|
|
2292
|
-
return /* @__PURE__ */ React16.createElement(Combobox2.Item, {
|
|
2293
|
-
value: "__create__",
|
|
2294
|
-
label,
|
|
2295
|
-
icon: createOptionIcon,
|
|
2296
|
-
classNames: "flex items-center gap-2",
|
|
2297
|
-
closeOnSelect: false,
|
|
2298
|
-
onSelect: () => {
|
|
2299
|
-
onCreateItemSelect(query);
|
|
2300
|
-
}
|
|
2301
|
-
});
|
|
2302
|
-
};
|
|
2303
|
-
ObjectPickerContent.displayName = "ObjectPicker.Content";
|
|
2304
|
-
var ObjectPicker = {
|
|
2305
|
-
Root: Combobox2.Root,
|
|
2306
|
-
Portal: Combobox2.Portal,
|
|
2307
|
-
Trigger: Combobox2.Trigger,
|
|
2308
|
-
VirtualTrigger: Combobox2.VirtualTrigger,
|
|
2309
|
-
Content: ObjectPickerContent
|
|
2310
|
-
};
|
|
2311
|
-
|
|
2312
|
-
// src/components/Form/FormField/fields/RefField/RefField.tsx
|
|
2313
|
-
var isRefSnapshot = (val) => {
|
|
2314
|
-
return typeof val === "object" && typeof val?.["/"] === "string";
|
|
2315
|
-
};
|
|
2316
|
-
var findRefOption = (value3, options) => {
|
|
2317
|
-
const isRef = Ref5.isRef(value3);
|
|
2318
|
-
if (!isRef && !isRefSnapshot(value3)) {
|
|
2319
|
-
return void 0;
|
|
2320
|
-
}
|
|
2321
|
-
const valueUri = isRef ? value3.uri : value3["/"];
|
|
2322
|
-
const directMatch = options.find((option) => option.id === valueUri);
|
|
2323
|
-
if (directMatch) {
|
|
2324
|
-
return directMatch;
|
|
2325
|
-
}
|
|
2326
|
-
const valueEid = EID.tryParse(valueUri);
|
|
2327
|
-
if (!valueEid) {
|
|
2328
|
-
return void 0;
|
|
2329
|
-
}
|
|
2330
|
-
const valueSpaceId = EID.getSpaceId(valueEid);
|
|
2331
|
-
const valueLocal = EID.toLocal(valueEid);
|
|
2332
|
-
return options.find((option) => {
|
|
2333
|
-
const optionEid = EID.tryParse(option.id);
|
|
2334
|
-
if (!optionEid) {
|
|
2335
|
-
return false;
|
|
2336
|
-
}
|
|
2337
|
-
const optionSpaceId = EID.getSpaceId(optionEid);
|
|
2338
|
-
if (valueSpaceId != null && optionSpaceId != null && valueSpaceId !== optionSpaceId) {
|
|
2339
|
-
return false;
|
|
2340
|
-
}
|
|
2341
|
-
return EID.equals(EID.toLocal(optionEid), valueLocal);
|
|
2342
|
-
});
|
|
2343
|
-
};
|
|
2344
|
-
var defaultGetOptions = (results, { parentLabel, getTypePlaceholder } = {}) => results.filter((result) => !parentLabel || Obj.getParent(result) != null).map((result) => {
|
|
2345
|
-
const id = Entity.getURI(result, {
|
|
2346
|
-
prefer: "named"
|
|
2347
|
-
});
|
|
2348
|
-
const parent = parentLabel ? Obj.getParent(result) : void 0;
|
|
2349
|
-
const labelEntity = parent ?? result;
|
|
2350
|
-
const typename = Entity.getTypename(labelEntity);
|
|
2351
|
-
const label = Entity.getLabel(labelEntity) ?? (typename ? getTypePlaceholder?.(typename) : void 0) ?? id;
|
|
2352
|
-
return {
|
|
2353
|
-
id,
|
|
2354
|
-
label
|
|
2355
|
-
};
|
|
2356
|
-
});
|
|
2357
|
-
var defaultUseResults = (db, typename) => useQuery(db, !typename ? Query.select(Filter.nothing()) : typename === ANY_OBJECT_TYPENAME ? Query.select(Filter.everything()) : Query.select(Filter.type(DXN2.make(typename))).from(Scope.space(), Scope.registry()));
|
|
2358
|
-
var RefField = (props) => {
|
|
2359
|
-
const { type, readonly, label, jsonPath, placeholder, presentation, required, getStatus, getValue, createOptionLabel, createOptionIcon, createInitialValuePath, createFieldMap: createFieldMap3, db, useType: useType2 = defaultUseType2, useResults = defaultUseResults, getOptions = defaultGetOptions, onCreate, resolveCreateEntry, onValueChange } = props;
|
|
2360
|
-
const { t } = useTranslation6(translationKey6);
|
|
2361
|
-
const { status, error } = getStatus();
|
|
2362
|
-
const resolved = presentationFor(presentation);
|
|
2363
|
-
const typename = useMemo9(() => type ? SchemaEx7.findAnnotation(type, ReferenceAnnotationId2)?.typename : void 0, [
|
|
2364
|
-
type
|
|
2365
|
-
]);
|
|
2366
|
-
const getTypePlaceholder = useCallback14((placeholderTypename) => {
|
|
2367
|
-
const segment = placeholderTypename.split(/[.:/]/).filter(Boolean).pop() ?? placeholderTypename;
|
|
2368
|
-
const humanized = segment.charAt(0).toUpperCase() + segment.slice(1);
|
|
2369
|
-
return t("object-name.placeholder", {
|
|
2370
|
-
ns: placeholderTypename,
|
|
2371
|
-
defaultValue: humanized
|
|
2372
|
-
});
|
|
2373
|
-
}, [
|
|
2374
|
-
t
|
|
2375
|
-
]);
|
|
2376
|
-
const results = useResults(db, typename);
|
|
2377
|
-
const options = useMemo9(() => {
|
|
2378
|
-
const parentLabel = type ? SchemaEx7.findAnnotation(type, ParentLabelAnnotationId) === true : false;
|
|
2379
|
-
return getOptions(results, {
|
|
2380
|
-
parentLabel,
|
|
2381
|
-
getTypePlaceholder
|
|
2382
|
-
});
|
|
2383
|
-
}, [
|
|
2384
|
-
results,
|
|
2385
|
-
getOptions,
|
|
2386
|
-
type,
|
|
2387
|
-
getTypePlaceholder
|
|
2388
|
-
]);
|
|
2389
|
-
const handleGetValue = useCallback14(() => findRefOption(getValue(), options), [
|
|
2390
|
-
options,
|
|
2391
|
-
getValue
|
|
2392
|
-
]);
|
|
2393
|
-
const item = handleGetValue();
|
|
2394
|
-
const selectedIds = useMemo9(() => item ? [
|
|
2395
|
-
item.id
|
|
2396
|
-
] : [], [
|
|
2397
|
-
item
|
|
2398
|
-
]);
|
|
2399
|
-
const createSchema = useType2(db, typename && typename !== ANY_OBJECT_TYPENAME ? DXN2.make(typename) : void 0);
|
|
2400
|
-
const createEntry = typename ? resolveCreateEntry?.(typename) : void 0;
|
|
2401
|
-
const [open, setOpen] = useState7(false);
|
|
2402
|
-
const handleCreate = useCallback14(async (values) => {
|
|
2403
|
-
if (createEntry?.createObject && db) {
|
|
2404
|
-
const newObject = await createEntry.createObject(values, db);
|
|
2405
|
-
if (newObject) {
|
|
2406
|
-
onValueChange(type, Ref5.make(newObject));
|
|
2407
|
-
}
|
|
2408
|
-
} else if (createSchema && onCreate) {
|
|
2409
|
-
const newObject = await onCreate(createSchema, values);
|
|
2410
|
-
if (newObject) {
|
|
2411
|
-
onValueChange(type, Ref5.make(newObject));
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
setOpen(false);
|
|
2415
|
-
}, [
|
|
2416
|
-
createEntry,
|
|
2417
|
-
db,
|
|
2418
|
-
createSchema,
|
|
2419
|
-
onCreate,
|
|
2420
|
-
type,
|
|
2421
|
-
onValueChange
|
|
2422
|
-
]);
|
|
2423
|
-
const handleUpdate = useCallback14((id) => {
|
|
2424
|
-
const item2 = options.find((option) => option.id === id);
|
|
2425
|
-
const ref = item2 ? Ref5.fromURI(URI.make(item2.id)) : void 0;
|
|
2426
|
-
onValueChange(type, ref);
|
|
2427
|
-
}, [
|
|
2428
|
-
options,
|
|
2429
|
-
type,
|
|
2430
|
-
onValueChange
|
|
2431
|
-
]);
|
|
2432
|
-
const handleSelect = useCallback14((id) => {
|
|
2433
|
-
if (item?.id === id) {
|
|
2434
|
-
handleUpdate(void 0);
|
|
2435
|
-
} else {
|
|
2436
|
-
handleUpdate(id);
|
|
2437
|
-
}
|
|
2438
|
-
}, [
|
|
2439
|
-
item,
|
|
2440
|
-
handleUpdate
|
|
2441
|
-
]);
|
|
2442
|
-
if (!typename || (readonly || resolved.isStatic) && !item) {
|
|
2443
|
-
return null;
|
|
2444
|
-
}
|
|
2445
|
-
return /* @__PURE__ */ React17.createElement(Input8.Root, {
|
|
2446
|
-
validationValence: status
|
|
2447
|
-
}, resolved.showLabel && /* @__PURE__ */ React17.createElement(FormFieldLabel, {
|
|
2448
|
-
error,
|
|
2449
|
-
readonly,
|
|
2450
|
-
required,
|
|
2451
|
-
label,
|
|
2452
|
-
path: jsonPath
|
|
2453
|
-
}), /* @__PURE__ */ React17.createElement("div", null, readonly ? !item ? /* @__PURE__ */ React17.createElement("p", {
|
|
2454
|
-
className: "text-description mb-2"
|
|
2455
|
-
}, t("empty-readonly-ref-field.label")) : /* @__PURE__ */ React17.createElement(DxAnchor, {
|
|
2456
|
-
key: item.id,
|
|
2457
|
-
dxn: item.id,
|
|
2458
|
-
rootclassname: "me-1"
|
|
2459
|
-
}, item.label) : /* @__PURE__ */ React17.createElement(ObjectPicker.Root, {
|
|
2460
|
-
open,
|
|
2461
|
-
onOpenChange: setOpen
|
|
2462
|
-
}, /* @__PURE__ */ React17.createElement(ObjectPicker.Trigger, {
|
|
2463
|
-
asChild: true,
|
|
2464
|
-
classNames: "p-0"
|
|
2465
|
-
}, item ? /* @__PURE__ */ React17.createElement("div", {
|
|
2466
|
-
className: "flex gap-form-gap w-full"
|
|
2467
|
-
}, /* @__PURE__ */ React17.createElement(Input8.Root, {
|
|
2468
|
-
key: item.id
|
|
2469
|
-
}, /* @__PURE__ */ React17.createElement(Input8.TextInput, {
|
|
2470
|
-
value: item.label,
|
|
2471
|
-
readOnly: true,
|
|
2472
|
-
classNames: "w-full"
|
|
2473
|
-
}))) : /* @__PURE__ */ React17.createElement(Button, {
|
|
2474
|
-
classNames: "w-full text-start gap-form-gap"
|
|
2475
|
-
}, /* @__PURE__ */ React17.createElement("div", {
|
|
2476
|
-
className: "grow overflow-hidden"
|
|
2477
|
-
}, /* @__PURE__ */ React17.createElement("span", {
|
|
2478
|
-
className: "truncate text-description"
|
|
2479
|
-
}, placeholder || label || t("ref-field.placeholder"))), /* @__PURE__ */ React17.createElement(Icon3, {
|
|
2480
|
-
size: 3,
|
|
2481
|
-
icon: "ph--caret-down--bold"
|
|
2482
|
-
}))), /* @__PURE__ */ React17.createElement(ObjectPicker.Portal, null, /* @__PURE__ */ React17.createElement(ObjectPicker.Content, {
|
|
2483
|
-
classNames: "dx-card-popover-width",
|
|
2484
|
-
options,
|
|
2485
|
-
selectedIds,
|
|
2486
|
-
// Prefer the plugin-registered inputSchema; fall back to stripping hidden fields
|
|
2487
|
-
// (`FormInputAnnotation.set(false)`) from the raw ECHO type schema so the form's
|
|
2488
|
-
// validator doesn't reject required-but-hidden fields such as backing-object refs
|
|
2489
|
-
// supplied by a `FactoryAnnotation`.
|
|
2490
|
-
createSchema: createEntry?.inputSchema ?? (createSchema && omitHiddenFormFields(omitId(Type2.getSchema(createSchema)))),
|
|
2491
|
-
createOptionLabel,
|
|
2492
|
-
createOptionIcon,
|
|
2493
|
-
createInitialValuePath,
|
|
2494
|
-
createFieldMap: createFieldMap3,
|
|
2495
|
-
// Offer inline create when the caller wired a handler OR a plugin-registered
|
|
2496
|
-
// createObject override is available. A resolvable `createSchema` alone is not
|
|
2497
|
-
// enough (e.g. operation refs, whose objects can't be created ad hoc).
|
|
2498
|
-
onCreate: onCreate || createEntry?.createObject ? handleCreate : void 0,
|
|
2499
|
-
onSelect: handleSelect
|
|
2500
|
-
})))), resolved.showError && /* @__PURE__ */ React17.createElement(Input8.DescriptionAndValidation, null, error));
|
|
2501
|
-
};
|
|
2502
|
-
|
|
2503
|
-
// src/components/Form/FormField/fields/RefField/InlineRefField.tsx
|
|
2504
|
-
import { useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
|
|
2505
|
-
import React18, { useCallback as useCallback15, useMemo as useMemo10 } from "react";
|
|
2506
|
-
import { Obj as Obj2, Ref as Ref6, Type as Type3 } from "@dxos/echo";
|
|
2507
|
-
import { useType as defaultUseType3 } from "@dxos/echo-react";
|
|
2508
|
-
import { ReferenceAnnotationId as ReferenceAnnotationId3 } from "@dxos/echo/Annotation";
|
|
2509
|
-
import { SchemaEx as SchemaEx8 } from "@dxos/effect";
|
|
2510
|
-
import { DXN as DXN3 } from "@dxos/keys";
|
|
2511
|
-
import { IconButton as IconButton3, Input as Input9, useTranslation as useTranslation7 } from "@dxos/react-ui";
|
|
2512
|
-
import { translationKey as translationKey7 } from "#translations";
|
|
2513
|
-
var InlineRefField = (props) => {
|
|
2514
|
-
const { type, readonly, label, jsonPath, presentation, required, db, getValue, onValueChange, onCreate, useType: useType2 = defaultUseType3 } = props;
|
|
2515
|
-
const { t } = useTranslation7(translationKey7);
|
|
2516
|
-
const resolved = presentationFor(presentation);
|
|
2517
|
-
const reference = getValue();
|
|
2518
|
-
const typename = useMemo10(() => type ? SchemaEx8.findAnnotation(type, ReferenceAnnotationId3)?.typename : void 0, [
|
|
2519
|
-
type
|
|
2520
|
-
]);
|
|
2521
|
-
const createType = useType2(db, typename ? DXN3.make(typename) : void 0);
|
|
2522
|
-
const handleCreate = useCallback15(async () => {
|
|
2523
|
-
if (!createType || !onCreate) {
|
|
2524
|
-
return;
|
|
2525
|
-
}
|
|
2526
|
-
const newObject = await onCreate(createType, {});
|
|
2527
|
-
if (newObject) {
|
|
2528
|
-
onValueChange(type, Ref6.make(newObject));
|
|
2529
|
-
}
|
|
2530
|
-
}, [
|
|
2531
|
-
createType,
|
|
2532
|
-
onCreate,
|
|
2533
|
-
type,
|
|
2534
|
-
onValueChange
|
|
2535
|
-
]);
|
|
2536
|
-
if (readonly && !reference) {
|
|
2537
|
-
return null;
|
|
2538
|
-
}
|
|
2539
|
-
return /* @__PURE__ */ React18.createElement(Input9.Root, null, resolved.showLabel && /* @__PURE__ */ React18.createElement(FormFieldLabel, {
|
|
2540
|
-
readonly,
|
|
2541
|
-
required,
|
|
2542
|
-
label,
|
|
2543
|
-
path: jsonPath
|
|
2544
|
-
}), reference ? /* @__PURE__ */ React18.createElement(InlineForm, {
|
|
2545
|
-
reference,
|
|
2546
|
-
db,
|
|
2547
|
-
readonly,
|
|
2548
|
-
useType: useType2
|
|
2549
|
-
}) : !readonly && onCreate && /* @__PURE__ */ React18.createElement(IconButton3, {
|
|
2550
|
-
classNames: "w-full gap-form-gap",
|
|
2551
|
-
disabled: !createType || !db,
|
|
2552
|
-
icon: "ph--plus--regular",
|
|
2553
|
-
label: label || t("ref-field.placeholder"),
|
|
2554
|
-
onClick: () => void handleCreate()
|
|
2555
|
-
}));
|
|
2556
|
-
};
|
|
2557
|
-
var InlineForm = ({ reference, db, readonly, useType: useType2 = defaultUseType3 }) => {
|
|
2558
|
-
const target = useAtomValue2(useMemo10(() => reference.atom, [
|
|
2559
|
-
reference
|
|
2560
|
-
]));
|
|
2561
|
-
const typeUri = target ? Obj2.getTypeURI(target) : void 0;
|
|
2562
|
-
const typeFromRegistry = useType2(db, typeUri);
|
|
2563
|
-
const targetType = target && Obj2.getType(target) || typeFromRegistry;
|
|
2564
|
-
const formSchema = useMemo10(() => targetType ? omitId(Type3.getSchema(targetType)) : void 0, [
|
|
2565
|
-
targetType
|
|
2566
|
-
]);
|
|
2567
|
-
const defaultValues = useMemo10(() => target ? {
|
|
2568
|
-
...target
|
|
2569
|
-
} : {}, [
|
|
2570
|
-
target
|
|
2571
|
-
]);
|
|
2572
|
-
const handleChange = useCallback15((values, { isValid, changed }) => {
|
|
2573
|
-
if (!isValid || !target) {
|
|
2574
|
-
return;
|
|
2575
|
-
}
|
|
2576
|
-
const changedPaths = Object.keys(changed).filter((path) => changed[path]);
|
|
2577
|
-
if (changedPaths.length === 0) {
|
|
2578
|
-
return;
|
|
2579
|
-
}
|
|
2580
|
-
Obj2.update(target, () => {
|
|
2581
|
-
for (const path of changedPaths) {
|
|
2582
|
-
const parts = SchemaEx8.splitJsonPath(path);
|
|
2583
|
-
Obj2.setValue(target, parts, Obj2.getValue(values, parts));
|
|
2584
|
-
}
|
|
2585
|
-
});
|
|
2586
|
-
}, [
|
|
2587
|
-
target
|
|
2588
|
-
]);
|
|
2589
|
-
if (!target || !formSchema) {
|
|
2590
|
-
return null;
|
|
2591
|
-
}
|
|
2592
|
-
return /* @__PURE__ */ React18.createElement(FormRoot, {
|
|
2593
|
-
db,
|
|
2594
|
-
schema: formSchema,
|
|
2595
|
-
defaultValues,
|
|
2596
|
-
onValuesChanged: handleChange
|
|
2597
|
-
}, /* @__PURE__ */ React18.createElement(FormContent, null, /* @__PURE__ */ React18.createElement(FormFieldSetController, {
|
|
2598
|
-
collapsible: true,
|
|
2599
|
-
readonly
|
|
2600
|
-
})));
|
|
2601
|
-
};
|
|
2602
|
-
|
|
2603
|
-
// src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.tsx
|
|
2604
|
-
import React19, { useCallback as useCallback16, useEffect as useEffect8, useRef as useRef6, useState as useState8 } from "react";
|
|
2605
|
-
import { PublicKey } from "@dxos/keys";
|
|
2606
|
-
import { IconButton as IconButton4, Input as Input10, Tag as Tag2, ToggleIconButton, useTranslation as useTranslation8 } from "@dxos/react-ui";
|
|
2607
|
-
import { OrderedList as OrderedList2 } from "@dxos/react-ui-list";
|
|
2608
|
-
import { HuePicker } from "@dxos/react-ui-pickers";
|
|
2609
|
-
import { hues, osTranslations } from "@dxos/ui-theme";
|
|
2610
|
-
import { translationKey as translationKey8 } from "#translations";
|
|
2611
|
-
var SelectOptionField = ({ type, readonly, label, jsonPath, getStatus, getValue, onValueChange }) => {
|
|
2612
|
-
const { t } = useTranslation8(translationKey8);
|
|
2613
|
-
const { status, error } = getStatus();
|
|
2614
|
-
const [selected, setSelectedId] = useState8(null);
|
|
2615
|
-
const [isNewOption, setIsNewOption] = useState8(false);
|
|
2616
|
-
const inputRef = useRef6(null);
|
|
2617
|
-
const options = getValue();
|
|
2618
|
-
useEffect8(() => {
|
|
2619
|
-
if (options === void 0) {
|
|
2620
|
-
onValueChange(type, []);
|
|
2621
|
-
}
|
|
2622
|
-
}, [
|
|
2623
|
-
options,
|
|
2624
|
-
type,
|
|
2625
|
-
onValueChange
|
|
2626
|
-
]);
|
|
2627
|
-
const randomHue = () => {
|
|
2628
|
-
const usedHues = new Set(options?.map((option) => option.color) ?? []);
|
|
2629
|
-
const unusedHues = hues.filter((hue) => !usedHues.has(hue));
|
|
2630
|
-
if (unusedHues.length > 0) {
|
|
2631
|
-
return unusedHues[Math.floor(Math.random() * unusedHues.length)];
|
|
2632
|
-
}
|
|
2633
|
-
const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
|
|
2634
|
-
const availableHues = hues.filter((hue) => !lastThree.has(hue));
|
|
2635
|
-
return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
|
|
2636
|
-
};
|
|
2637
|
-
const handleAdd = useCallback16(() => {
|
|
2638
|
-
const newId = PublicKey.random().truncate();
|
|
2639
|
-
const newOption = {
|
|
2640
|
-
id: newId,
|
|
2641
|
-
title: "",
|
|
2642
|
-
color: randomHue()
|
|
2643
|
-
};
|
|
2644
|
-
onValueChange(type, [
|
|
2645
|
-
...options ?? [],
|
|
2646
|
-
newOption
|
|
2647
|
-
]);
|
|
2648
|
-
setSelectedId(newId);
|
|
2649
|
-
setIsNewOption(true);
|
|
2650
|
-
}, [
|
|
2651
|
-
options,
|
|
2652
|
-
type,
|
|
2653
|
-
onValueChange
|
|
2654
|
-
]);
|
|
2655
|
-
const handleDelete = useCallback16((id) => {
|
|
2656
|
-
const newOptions = options?.filter((option) => option.id !== id) ?? [];
|
|
2657
|
-
onValueChange(type, newOptions);
|
|
2658
|
-
setSelectedId(null);
|
|
2659
|
-
}, [
|
|
2660
|
-
options,
|
|
2661
|
-
type,
|
|
2662
|
-
onValueChange
|
|
2663
|
-
]);
|
|
2664
|
-
const handleMove = useCallback16((from, to) => {
|
|
2665
|
-
if (!options) {
|
|
2666
|
-
return;
|
|
2667
|
-
}
|
|
2668
|
-
const newOptions = [
|
|
2669
|
-
...options
|
|
2670
|
-
];
|
|
2671
|
-
const [removed] = newOptions.splice(from, 1);
|
|
2672
|
-
newOptions.splice(to, 0, removed);
|
|
2673
|
-
onValueChange(type, newOptions);
|
|
2674
|
-
}, [
|
|
2675
|
-
options,
|
|
2676
|
-
type,
|
|
2677
|
-
onValueChange
|
|
2678
|
-
]);
|
|
2679
|
-
const handleClick = useCallback16((id) => {
|
|
2680
|
-
setSelectedId((current) => current === id ? null : id);
|
|
2681
|
-
}, []);
|
|
2682
|
-
const handleTitleChange = useCallback16((id) => (e) => {
|
|
2683
|
-
const newOptions = options?.map((o) => o.id === id ? {
|
|
2684
|
-
...o,
|
|
2685
|
-
title: e.target.value
|
|
2686
|
-
} : o);
|
|
2687
|
-
onValueChange(type, newOptions ?? []);
|
|
2688
|
-
}, [
|
|
2689
|
-
options,
|
|
2690
|
-
type,
|
|
2691
|
-
onValueChange
|
|
2692
|
-
]);
|
|
2693
|
-
const handleKeyDown = useCallback16((ev) => {
|
|
2694
|
-
if (ev.key === "Enter") {
|
|
2695
|
-
setSelectedId(null);
|
|
2696
|
-
}
|
|
2697
|
-
}, []);
|
|
2698
|
-
const handleColorChange = useCallback16((id) => (hue) => {
|
|
2699
|
-
const newOptions = options?.map((o) => o.id === id ? {
|
|
2700
|
-
...o,
|
|
2701
|
-
color: hue
|
|
2702
|
-
} : o);
|
|
2703
|
-
onValueChange(type, newOptions ?? []);
|
|
2704
|
-
}, [
|
|
2705
|
-
options,
|
|
2706
|
-
type,
|
|
2707
|
-
onValueChange
|
|
2708
|
-
]);
|
|
2709
|
-
useEffect8(() => {
|
|
2710
|
-
if (selected && isNewOption && inputRef.current) {
|
|
2711
|
-
inputRef.current.focus();
|
|
2712
|
-
setIsNewOption(false);
|
|
2713
|
-
}
|
|
2714
|
-
}, [
|
|
2715
|
-
selected,
|
|
2716
|
-
isNewOption
|
|
2717
|
-
]);
|
|
2718
|
-
return /* @__PURE__ */ React19.createElement(Input10.Root, {
|
|
2719
|
-
validationValence: status
|
|
2720
|
-
}, /* @__PURE__ */ React19.createElement(FormFieldLabel, {
|
|
2721
|
-
error,
|
|
2722
|
-
readonly,
|
|
2723
|
-
label,
|
|
2724
|
-
path: jsonPath
|
|
2725
|
-
}), /* @__PURE__ */ React19.createElement("div", null, options && /* @__PURE__ */ React19.createElement(OrderedList2.Root, {
|
|
2726
|
-
items: options,
|
|
2727
|
-
isItem: (_item) => true,
|
|
2728
|
-
getId: (option) => option.id,
|
|
2729
|
-
onMove: readonly ? void 0 : handleMove,
|
|
2730
|
-
readonly: !!readonly
|
|
2731
|
-
}, ({ items }) => /* @__PURE__ */ React19.createElement(OrderedList2.Content, {
|
|
2732
|
-
classNames: "w-full overflow-auto"
|
|
2733
|
-
}, items?.map((item) => /* @__PURE__ */ React19.createElement(OrderedList2.Item, {
|
|
2734
|
-
key: item.id,
|
|
2735
|
-
id: item.id,
|
|
2736
|
-
item,
|
|
2737
|
-
canDrag: !readonly,
|
|
2738
|
-
classNames: "flex flex-col cursor-pointer rounded-xs dx-hover"
|
|
2739
|
-
}, /* @__PURE__ */ React19.createElement("div", {
|
|
2740
|
-
className: "flex items-center"
|
|
2741
|
-
}, /* @__PURE__ */ React19.createElement(OrderedList2.DragHandle, null), /* @__PURE__ */ React19.createElement("div", {
|
|
2742
|
-
className: "flex grow items-center truncate px-2",
|
|
2743
|
-
onClick: () => handleClick(item.id)
|
|
2744
|
-
}, /* @__PURE__ */ React19.createElement(Tag2, {
|
|
2745
|
-
hue: item.color
|
|
2746
|
-
}, item.title || "\u200B")), /* @__PURE__ */ React19.createElement(ToggleIconButton, {
|
|
2747
|
-
iconOnly: true,
|
|
2748
|
-
variant: "ghost",
|
|
2749
|
-
active: selected === item.id,
|
|
2750
|
-
icon: "ph--caret-right--regular",
|
|
2751
|
-
label: t(selected === item.id ? "collapse.label" : "expand.label", {
|
|
2752
|
-
ns: osTranslations
|
|
2753
|
-
}),
|
|
2754
|
-
onClick: () => handleClick(item.id)
|
|
2755
|
-
})), selected === item.id && /* @__PURE__ */ React19.createElement("div", {
|
|
2756
|
-
className: "flex flex-col p-form-padding gap-form-gap dx-density-md"
|
|
2757
|
-
}, /* @__PURE__ */ React19.createElement(Input10.Label, {
|
|
2758
|
-
classNames: "text-sm"
|
|
2759
|
-
}, t("select-option.label")), /* @__PURE__ */ React19.createElement("div", {
|
|
2760
|
-
className: "grid grid-cols-[1fr_min-content_min-content] gap-form-gap"
|
|
2761
|
-
}, /* @__PURE__ */ React19.createElement(Input10.TextInput, {
|
|
2762
|
-
disabled: !!readonly,
|
|
2763
|
-
placeholder: t("select-option-label.placeholder"),
|
|
2764
|
-
ref: selected === item.id ? inputRef : void 0,
|
|
2765
|
-
value: item.title,
|
|
2766
|
-
onChange: handleTitleChange(item.id),
|
|
2767
|
-
onKeyDown: handleKeyDown,
|
|
2768
|
-
classNames: "flex-1"
|
|
2769
|
-
}), /* @__PURE__ */ React19.createElement(HuePicker, {
|
|
2770
|
-
disabled: !!readonly,
|
|
2771
|
-
value: item.color,
|
|
2772
|
-
onChange: handleColorChange(item.id)
|
|
2773
|
-
}), /* @__PURE__ */ React19.createElement(IconButton4, {
|
|
2774
|
-
disabled: !!readonly,
|
|
2775
|
-
icon: "ph--trash--fill",
|
|
2776
|
-
iconOnly: true,
|
|
2777
|
-
label: t("select-option-delete.button"),
|
|
2778
|
-
onClick: () => handleDelete(item.id)
|
|
2779
|
-
}))))), /* @__PURE__ */ React19.createElement(IconButton4, {
|
|
2780
|
-
classNames: "w-full",
|
|
2781
|
-
variant: "ghost",
|
|
2782
|
-
icon: "ph--plus--regular",
|
|
2783
|
-
label: t("select-option-add.button"),
|
|
2784
|
-
onClick: handleAdd,
|
|
2785
|
-
disabled: !!readonly
|
|
2786
|
-
})))));
|
|
2787
|
-
};
|
|
2788
|
-
|
|
2789
|
-
// src/components/Form/FormField/fields/TextAreaField/TextAreaField.tsx
|
|
2790
|
-
import React20, { useCallback as useCallback17 } from "react";
|
|
2791
|
-
import { Input as Input11 } from "@dxos/react-ui";
|
|
2792
|
-
var TextAreaField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props }) => {
|
|
2793
|
-
const handleChange = useCallback17((event) => onValueChange(type, event.target.value), [
|
|
2794
|
-
type,
|
|
2795
|
-
onValueChange
|
|
2796
|
-
]);
|
|
2797
|
-
return /* @__PURE__ */ React20.createElement(FormRow, {
|
|
2798
|
-
readonly,
|
|
2799
|
-
...props
|
|
2800
|
-
}, ({ value: value3 = "" }) => /* @__PURE__ */ React20.createElement(Input11.TextArea, {
|
|
2801
|
-
rows: 5,
|
|
2802
|
-
disabled: !!readonly,
|
|
2803
|
-
placeholder,
|
|
2804
|
-
value: value3,
|
|
2805
|
-
onChange: handleChange,
|
|
2806
|
-
onBlur
|
|
2807
|
-
}));
|
|
2808
|
-
};
|
|
2809
|
-
|
|
2810
|
-
// src/components/Form/FormField/fields/TupleField/TupleField.tsx
|
|
2811
|
-
import React21 from "react";
|
|
2812
|
-
import { Input as Input12 } from "@dxos/react-ui";
|
|
2813
|
-
import { mx as mx4 } from "@dxos/ui-theme";
|
|
2814
|
-
import { safeParseFloat as safeParseFloat3 } from "@dxos/util";
|
|
2815
|
-
var gridCols = [
|
|
2816
|
-
"grid-cols-1",
|
|
2817
|
-
"grid-cols-2",
|
|
2818
|
-
"grid-cols-3",
|
|
2819
|
-
"grid-cols-4"
|
|
2820
|
-
];
|
|
2821
|
-
var TupleField = ({ binding, type, readonly, label, jsonPath, getStatus, getValue, onValueChange, onBlur }) => {
|
|
2822
|
-
const { status, error } = getStatus();
|
|
2823
|
-
const values = getValue() ?? {};
|
|
2824
|
-
return /* @__PURE__ */ React21.createElement(Input12.Root, {
|
|
2825
|
-
validationValence: status
|
|
2826
|
-
}, /* @__PURE__ */ React21.createElement(FormFieldLabel, {
|
|
2827
|
-
error,
|
|
2828
|
-
readonly,
|
|
2829
|
-
label,
|
|
2830
|
-
path: jsonPath
|
|
2831
|
-
}), /* @__PURE__ */ React21.createElement("div", {
|
|
2832
|
-
className: mx4("grid gap-form-gap", gridCols[binding.length - 1])
|
|
2833
|
-
}, binding.map((prop) => /* @__PURE__ */ React21.createElement(Input12.TextInput, {
|
|
2834
|
-
key: prop,
|
|
2835
|
-
type: "number",
|
|
2836
|
-
disabled: !!readonly,
|
|
2837
|
-
value: values[prop],
|
|
2838
|
-
onChange: (event) => {
|
|
2839
|
-
onValueChange(type, {
|
|
2840
|
-
...values,
|
|
2841
|
-
[prop]: safeParseFloat3(event.target.value, 0)
|
|
2842
|
-
});
|
|
2843
|
-
},
|
|
2844
|
-
onBlur
|
|
2845
|
-
}))));
|
|
2846
|
-
};
|
|
2847
|
-
|
|
2848
|
-
// src/components/Form/FormLayout/FormLayout.tsx
|
|
2849
|
-
import * as Option6 from "effect/Option";
|
|
2850
|
-
import * as Schema4 from "effect/Schema";
|
|
2851
|
-
import * as SchemaAST7 from "effect/SchemaAST";
|
|
2852
|
-
import * as String3 from "effect/String";
|
|
2853
|
-
import React22, { Fragment, useMemo as useMemo11 } from "react";
|
|
2854
|
-
import { Annotation as Annotation5 } from "@dxos/echo";
|
|
2855
|
-
import { SchemaEx as SchemaEx9 } from "@dxos/effect";
|
|
2856
|
-
import { Input as Input13 } from "@dxos/react-ui";
|
|
2857
|
-
|
|
2858
|
-
// src/components/Form/FormLayout/parser.ts
|
|
2859
|
-
var LayoutParseError = class extends Error {
|
|
2860
|
-
position;
|
|
2861
|
-
_tag = "LayoutParseError";
|
|
2862
|
-
constructor(message, position) {
|
|
2863
|
-
super(position !== void 0 ? `${message} (at position ${position})` : message), this.position = position;
|
|
2864
|
-
}
|
|
2865
|
-
};
|
|
2866
|
-
var TAG_RE = /<\s*(\/?)\s*(\w+)([^>]*?)(\/?)\s*>/g;
|
|
2867
|
-
var ATTR_RE = /([\w-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\d+))/g;
|
|
2868
|
-
var parseAttrs = (raw) => {
|
|
2869
|
-
const attrs = {};
|
|
2870
|
-
ATTR_RE.lastIndex = 0;
|
|
2871
|
-
let match2;
|
|
2872
|
-
while ((match2 = ATTR_RE.exec(raw)) !== null) {
|
|
2873
|
-
const [, key, doubleQuoted, singleQuoted, bare] = match2;
|
|
2874
|
-
attrs[key] = doubleQuoted ?? singleQuoted ?? bare;
|
|
2875
|
-
}
|
|
2876
|
-
return attrs;
|
|
2877
|
-
};
|
|
2878
|
-
var tokenize = (input) => {
|
|
2879
|
-
const tokens = [];
|
|
2880
|
-
TAG_RE.lastIndex = 0;
|
|
2881
|
-
let match2;
|
|
2882
|
-
let cursor = 0;
|
|
2883
|
-
while ((match2 = TAG_RE.exec(input)) !== null) {
|
|
2884
|
-
const between = input.slice(cursor, match2.index);
|
|
2885
|
-
if (between.trim().length > 0) {
|
|
2886
|
-
throw new LayoutParseError(`unexpected text content: ${JSON.stringify(between.trim())}`, cursor);
|
|
2887
|
-
}
|
|
2888
|
-
const [, slash, name, attrsRaw, selfSlash] = match2;
|
|
2889
|
-
if (slash) {
|
|
2890
|
-
tokens.push({
|
|
2891
|
-
type: "close",
|
|
2892
|
-
name,
|
|
2893
|
-
position: match2.index
|
|
2894
|
-
});
|
|
2895
|
-
} else {
|
|
2896
|
-
tokens.push({
|
|
2897
|
-
type: "open",
|
|
2898
|
-
name,
|
|
2899
|
-
attrs: parseAttrs(attrsRaw),
|
|
2900
|
-
selfClosing: selfSlash === "/",
|
|
2901
|
-
position: match2.index
|
|
2902
|
-
});
|
|
2903
|
-
}
|
|
2904
|
-
cursor = match2.index + match2[0].length;
|
|
2905
|
-
}
|
|
2906
|
-
const trailing = input.slice(cursor);
|
|
2907
|
-
if (trailing.trim().length > 0) {
|
|
2908
|
-
throw new LayoutParseError(`unexpected text content: ${JSON.stringify(trailing.trim())}`, cursor);
|
|
2909
|
-
}
|
|
2910
|
-
return tokens;
|
|
2911
|
-
};
|
|
2912
|
-
var requireAttr = (attrs, key, tag, position) => {
|
|
2913
|
-
const value3 = attrs[key];
|
|
2914
|
-
if (value3 === void 0) {
|
|
2915
|
-
throw new LayoutParseError(`<${tag}> missing required attribute "${key}"`, position);
|
|
2916
|
-
}
|
|
2917
|
-
return value3;
|
|
2918
|
-
};
|
|
2919
|
-
var parseInteger = (value3, attr, tag, position) => {
|
|
2920
|
-
if (!/^\d+$/.test(value3)) {
|
|
2921
|
-
throw new LayoutParseError(`<${tag}> attribute "${attr}" expects an integer, got ${JSON.stringify(value3)}`, position);
|
|
2922
|
-
}
|
|
2923
|
-
return Number.parseInt(value3, 10);
|
|
2924
|
-
};
|
|
2925
|
-
var parseLayout = (template) => {
|
|
2926
|
-
const tokens = tokenize(template);
|
|
2927
|
-
if (tokens.length === 0) {
|
|
2928
|
-
throw new LayoutParseError("empty template");
|
|
2929
|
-
}
|
|
2930
|
-
let index = 0;
|
|
2931
|
-
const parseNode = () => {
|
|
2932
|
-
const token = tokens[index];
|
|
2933
|
-
if (!token || token.type !== "open") {
|
|
2934
|
-
throw new LayoutParseError(`expected an opening tag, got ${JSON.stringify(token)}`, token?.position);
|
|
2935
|
-
}
|
|
2936
|
-
if (token.name === "field") {
|
|
2937
|
-
if (!token.selfClosing) {
|
|
2938
|
-
throw new LayoutParseError('<field> must be self-closing (e.g. <field name="x"/>)', token.position);
|
|
2939
|
-
}
|
|
2940
|
-
const name = requireAttr(token.attrs, "name", "field", token.position);
|
|
2941
|
-
const spanRaw = token.attrs.span;
|
|
2942
|
-
const span = spanRaw !== void 0 ? parseInteger(spanRaw, "span", "field", token.position) : void 0;
|
|
2943
|
-
index += 1;
|
|
2944
|
-
return {
|
|
2945
|
-
kind: "field",
|
|
2946
|
-
name,
|
|
2947
|
-
span
|
|
2948
|
-
};
|
|
2949
|
-
}
|
|
2950
|
-
if (token.name === "grid") {
|
|
2951
|
-
if (token.selfClosing) {
|
|
2952
|
-
throw new LayoutParseError("<grid> must wrap children (cannot self-close)", token.position);
|
|
2953
|
-
}
|
|
2954
|
-
const cols = parseInteger(requireAttr(token.attrs, "cols", "grid", token.position), "cols", "grid", token.position);
|
|
2955
|
-
index += 1;
|
|
2956
|
-
const children = [];
|
|
2957
|
-
while (index < tokens.length && !(tokens[index].type === "close" && tokens[index].name === "grid")) {
|
|
2958
|
-
children.push(parseNode());
|
|
2959
|
-
}
|
|
2960
|
-
const closing = tokens[index];
|
|
2961
|
-
if (!closing || closing.type !== "close" || closing.name !== "grid") {
|
|
2962
|
-
throw new LayoutParseError("<grid> not closed", token.position);
|
|
2963
|
-
}
|
|
2964
|
-
index += 1;
|
|
2965
|
-
return {
|
|
2966
|
-
kind: "grid",
|
|
2967
|
-
cols,
|
|
2968
|
-
children
|
|
2969
|
-
};
|
|
2970
|
-
}
|
|
2971
|
-
throw new LayoutParseError(`unknown element <${token.name}>`, token.position);
|
|
2972
|
-
};
|
|
2973
|
-
const root = parseNode();
|
|
2974
|
-
if (index !== tokens.length) {
|
|
2975
|
-
const trailing = tokens[index];
|
|
2976
|
-
throw new LayoutParseError(`unexpected trailing tag <${trailing.type === "open" ? "" : "/"}${trailing.name}>`, trailing.position);
|
|
2977
|
-
}
|
|
2978
|
-
if (root.kind !== "grid") {
|
|
2979
|
-
throw new LayoutParseError("root element must be <grid>");
|
|
2980
|
-
}
|
|
2981
|
-
return root;
|
|
2982
|
-
};
|
|
2983
|
-
|
|
2984
|
-
// src/components/Form/FormLayout/FormLayout.tsx
|
|
2985
|
-
var FORM_LAYOUT_NAME = "Form.Layout";
|
|
2986
|
-
var FormLayout = ({ schema, template, name = Annotation5.DEFAULT_LAYOUT_NAME, path, readonly, layout, projection, ...props }) => {
|
|
2987
|
-
const annotated = Option6.getOrUndefined(Annotation5.FormLayoutAnnotation.get(schema));
|
|
2988
|
-
const source = template ?? annotated?.[name];
|
|
2989
|
-
if (source === void 0) {
|
|
2990
|
-
throw new LayoutParseError(annotated ? `no layout named "${name}" on schema (available: ${Object.keys(annotated).join(", ") || "\u2205"})` : `no template provided and schema has no FormLayoutAnnotation`);
|
|
2991
|
-
}
|
|
2992
|
-
const tree = useMemo11(() => parseLayout(source), [
|
|
2993
|
-
source
|
|
2994
|
-
]);
|
|
2995
|
-
return /* @__PURE__ */ React22.createElement(RenderNode, {
|
|
2996
|
-
node: tree,
|
|
2997
|
-
schema,
|
|
2998
|
-
basePath: path ?? [],
|
|
2999
|
-
readonly,
|
|
3000
|
-
layout,
|
|
3001
|
-
projection,
|
|
3002
|
-
...props
|
|
3003
|
-
});
|
|
3004
|
-
};
|
|
3005
|
-
FormLayout.displayName = FORM_LAYOUT_NAME;
|
|
3006
|
-
var RenderNode = ({ node, schema, basePath, ...props }) => {
|
|
3007
|
-
if (node.kind === "grid") {
|
|
3008
|
-
return /* @__PURE__ */ React22.createElement("div", {
|
|
3009
|
-
className: "grid gap-x-form-gap",
|
|
3010
|
-
style: {
|
|
3011
|
-
gridTemplateColumns: `repeat(${node.cols}, minmax(0, 1fr))`
|
|
3012
|
-
}
|
|
3013
|
-
}, node.children.map((child, index) => /* @__PURE__ */ React22.createElement(Fragment, {
|
|
3014
|
-
key: index
|
|
3015
|
-
}, /* @__PURE__ */ React22.createElement(RenderNode, {
|
|
3016
|
-
node: child,
|
|
3017
|
-
schema,
|
|
3018
|
-
basePath,
|
|
3019
|
-
...props
|
|
3020
|
-
}))));
|
|
3021
|
-
}
|
|
3022
|
-
const resolved = resolveLayoutField(schema, node.name);
|
|
3023
|
-
if (!resolved) {
|
|
3024
|
-
throw new LayoutParseError(`field "${node.name}" not found on schema`);
|
|
3025
|
-
}
|
|
3026
|
-
const { type, segments, leafName, title, labelType, required } = resolved;
|
|
3027
|
-
const path = [
|
|
3028
|
-
...basePath,
|
|
3029
|
-
...segments
|
|
3030
|
-
];
|
|
3031
|
-
const span = node.span ? {
|
|
3032
|
-
gridColumn: `span ${node.span} / span ${node.span}`
|
|
3033
|
-
} : void 0;
|
|
3034
|
-
return /* @__PURE__ */ React22.createElement("div", {
|
|
3035
|
-
className: "min-w-0",
|
|
3036
|
-
style: span
|
|
3037
|
-
}, /* @__PURE__ */ React22.createElement(FormFieldErrorBoundary, {
|
|
3038
|
-
path
|
|
3039
|
-
}, labelType ? /* @__PURE__ */ React22.createElement(LabelField, {
|
|
3040
|
-
schema: Schema4.make(labelType),
|
|
3041
|
-
label: title ?? String3.capitalize(leafName),
|
|
3042
|
-
path,
|
|
3043
|
-
layout: props.layout
|
|
3044
|
-
}) : /* @__PURE__ */ React22.createElement(FormField, {
|
|
3045
|
-
type,
|
|
3046
|
-
name: leafName,
|
|
3047
|
-
path,
|
|
3048
|
-
required,
|
|
3049
|
-
...props
|
|
3050
|
-
})));
|
|
3051
|
-
};
|
|
3052
|
-
var resolvePropertySignature = (ast, segments) => {
|
|
3053
|
-
let node = ast;
|
|
3054
|
-
for (let index = 0; index < segments.length; index++) {
|
|
3055
|
-
const typeLiteral = SchemaEx9.findNode(node, SchemaAST7.isTypeLiteral);
|
|
3056
|
-
if (!typeLiteral) {
|
|
3057
|
-
return void 0;
|
|
3058
|
-
}
|
|
3059
|
-
const prop = SchemaAST7.getPropertySignatures(typeLiteral).find((p) => globalThis.String(p.name) === segments[index]);
|
|
3060
|
-
if (!prop) {
|
|
3061
|
-
return void 0;
|
|
3062
|
-
}
|
|
3063
|
-
if (index === segments.length - 1) {
|
|
3064
|
-
return prop;
|
|
3065
|
-
}
|
|
3066
|
-
node = prop.type;
|
|
3067
|
-
}
|
|
3068
|
-
return void 0;
|
|
3069
|
-
};
|
|
3070
|
-
var resolveLayoutField = (schema, name) => {
|
|
3071
|
-
const segments = name.split(".");
|
|
3072
|
-
const prop = resolvePropertySignature(schema.ast, segments);
|
|
3073
|
-
if (!prop) {
|
|
3074
|
-
return void 0;
|
|
3075
|
-
}
|
|
3076
|
-
const { type: baseType } = SchemaEx9.getBaseType(prop);
|
|
3077
|
-
const type = prop.annotations && Reflect.ownKeys(prop.annotations).length > 0 ? {
|
|
3078
|
-
...baseType,
|
|
3079
|
-
annotations: {
|
|
3080
|
-
...baseType.annotations,
|
|
3081
|
-
...prop.annotations
|
|
3082
|
-
}
|
|
3083
|
-
} : baseType;
|
|
3084
|
-
const title = SchemaEx9.getAnnotation(SchemaAST7.TitleAnnotationId)(type);
|
|
3085
|
-
const labelType = SchemaEx9.findNode(prop.type, SchemaAST7.isTypeLiteral);
|
|
3086
|
-
const labelled = labelType != null && Option6.isSome(Annotation5.LabelAnnotation.getFromAst(labelType));
|
|
3087
|
-
return {
|
|
3088
|
-
type,
|
|
3089
|
-
segments,
|
|
3090
|
-
leafName: segments[segments.length - 1],
|
|
3091
|
-
title,
|
|
3092
|
-
labelType: labelled ? labelType : void 0,
|
|
3093
|
-
required: !prop.isOptional
|
|
3094
|
-
};
|
|
3095
|
-
};
|
|
3096
|
-
var LabelField = ({ schema, label, path, layout }) => {
|
|
3097
|
-
const { variant = "default" } = useFormContext(FORM_LAYOUT_NAME);
|
|
3098
|
-
const styles3 = formTheme.styles({
|
|
3099
|
-
variant
|
|
3100
|
-
});
|
|
3101
|
-
const { getValue } = useFormFieldState(FORM_LAYOUT_NAME, path);
|
|
3102
|
-
const value3 = getValue();
|
|
3103
|
-
const text = value3 == null ? void 0 : Annotation5.getLabelWithSchema(schema, value3);
|
|
3104
|
-
if (text == null || text.trim().length === 0) {
|
|
3105
|
-
return null;
|
|
3106
|
-
}
|
|
3107
|
-
const presentation = presentationFor(layout);
|
|
3108
|
-
return /* @__PURE__ */ React22.createElement(Input13.Root, null, /* @__PURE__ */ React22.createElement("div", {
|
|
3109
|
-
className: styles3.field()
|
|
3110
|
-
}, presentation.showLabel && /* @__PURE__ */ React22.createElement(FormFieldLabel, {
|
|
3111
|
-
variant,
|
|
3112
|
-
readonly: true,
|
|
3113
|
-
label,
|
|
3114
|
-
path: SchemaEx9.createJsonPath(path)
|
|
3115
|
-
}), /* @__PURE__ */ React22.createElement("div", {
|
|
3116
|
-
className: styles3.fieldControl()
|
|
3117
|
-
}, /* @__PURE__ */ React22.createElement("p", {
|
|
3118
|
-
className: "truncate min-w-0",
|
|
3119
|
-
title: text
|
|
3120
|
-
}, text))));
|
|
3121
|
-
};
|
|
3122
|
-
|
|
3123
|
-
// src/components/Form/FormFieldSet/FormFieldSetContainer.tsx
|
|
3124
|
-
import React23, { useState as useState9 } from "react";
|
|
3125
|
-
import { ToggleIconButton as ToggleIconButton2, useTranslation as useTranslation9 } from "@dxos/react-ui";
|
|
3126
|
-
import { mx as mx5 } from "@dxos/ui-theme";
|
|
3127
|
-
import { translationKey as translationKey9 } from "#translations";
|
|
3128
|
-
var styles = formTheme.styles();
|
|
3129
|
-
var FormFieldSetContainer = ({ classNames, label, path, readonly, presentation, collapsible, children }) => {
|
|
3130
|
-
const { t } = useTranslation9(translationKey9);
|
|
3131
|
-
const [collapsed, setCollapsed] = useState9(false);
|
|
3132
|
-
const showBody = !(collapsible && collapsed);
|
|
3133
|
-
const content = /* @__PURE__ */ React23.createElement(React23.Fragment, null, presentation.showLabel && label && /* @__PURE__ */ React23.createElement(FormFieldHeader, {
|
|
3134
|
-
label,
|
|
3135
|
-
path,
|
|
3136
|
-
readonly,
|
|
3137
|
-
classNames: "pl-2",
|
|
3138
|
-
actions: collapsible ? /* @__PURE__ */ React23.createElement(ToggleIconButton2, {
|
|
3139
|
-
active: !collapsed,
|
|
3140
|
-
classNames: "px-1 mr-0.5",
|
|
3141
|
-
variant: "ghost",
|
|
3142
|
-
density: "xs",
|
|
3143
|
-
iconOnly: true,
|
|
3144
|
-
icon: "ph--caret-right--regular",
|
|
3145
|
-
label: t(collapsed ? "expand-fields.label" : "collapse-fields.label")
|
|
3146
|
-
}) : void 0,
|
|
3147
|
-
onClick: collapsible ? () => setCollapsed((value3) => !value3) : void 0
|
|
3148
|
-
}), showBody && (collapsible ? /* @__PURE__ */ React23.createElement("div", {
|
|
3149
|
-
className: styles.fieldSetBody()
|
|
3150
|
-
}, children) : children));
|
|
3151
|
-
if (collapsible) {
|
|
3152
|
-
return /* @__PURE__ */ React23.createElement("div", {
|
|
3153
|
-
className: styles.fieldSetBoxOuter()
|
|
3154
|
-
}, /* @__PURE__ */ React23.createElement("div", {
|
|
3155
|
-
className: styles.fieldSetBox({
|
|
3156
|
-
class: mx5(classNames)
|
|
3157
|
-
})
|
|
3158
|
-
}, content));
|
|
3159
|
-
}
|
|
3160
|
-
return classNames ? /* @__PURE__ */ React23.createElement("div", {
|
|
3161
|
-
className: mx5(classNames)
|
|
3162
|
-
}, content) : /* @__PURE__ */ React23.createElement(React23.Fragment, null, content);
|
|
3163
|
-
};
|
|
3164
|
-
|
|
3165
|
-
// src/components/Form/FormFieldSet/FormFieldSet.tsx
|
|
3166
|
-
var FORM_FIELDSET_NAME = "Form.FieldSet";
|
|
3167
|
-
var FormFieldSet = ({ classNames, label, schema, readonly, path, sort, collapsible, filter, projection, layout, layoutName = DEFAULT_LAYOUT_NAME, ...props }) => {
|
|
3168
|
-
const values = useFormValues(FORM_FIELDSET_NAME, path);
|
|
3169
|
-
const properties = useFormFieldSetProperties({
|
|
3170
|
-
schema,
|
|
3171
|
-
values,
|
|
3172
|
-
filter,
|
|
3173
|
-
sort,
|
|
3174
|
-
projection
|
|
3175
|
-
});
|
|
3176
|
-
if ((readonly || layout === "static") && values == null) {
|
|
3177
|
-
return null;
|
|
3178
|
-
}
|
|
3179
|
-
const layouts = schema ? Option7.getOrUndefined(FormLayoutAnnotation.get(schema)) : void 0;
|
|
3180
|
-
const body = layouts?.[layoutName] !== void 0 && schema ? /* @__PURE__ */ React24.createElement(FormLayout, {
|
|
3181
|
-
schema,
|
|
3182
|
-
name: layoutName,
|
|
3183
|
-
path,
|
|
3184
|
-
readonly,
|
|
3185
|
-
layout,
|
|
3186
|
-
projection,
|
|
3187
|
-
...props
|
|
3188
|
-
}) : properties.map((property) => {
|
|
3189
|
-
const name = property.name.toString();
|
|
3190
|
-
return /* @__PURE__ */ React24.createElement(FormFieldErrorBoundary, {
|
|
3191
|
-
key: name,
|
|
3192
|
-
path: [
|
|
3193
|
-
...path ?? [],
|
|
3194
|
-
name
|
|
3195
|
-
]
|
|
3196
|
-
}, /* @__PURE__ */ React24.createElement(FormField, {
|
|
3197
|
-
type: property.type,
|
|
3198
|
-
name,
|
|
3199
|
-
path: [
|
|
3200
|
-
...path ?? [],
|
|
3201
|
-
name
|
|
3202
|
-
],
|
|
3203
|
-
required: !property.isOptional,
|
|
3204
|
-
readonly,
|
|
3205
|
-
layout,
|
|
3206
|
-
projection,
|
|
3207
|
-
...props
|
|
3208
|
-
}));
|
|
3209
|
-
});
|
|
3210
|
-
return /* @__PURE__ */ React24.createElement(FormFieldSetContainer, {
|
|
3211
|
-
classNames,
|
|
3212
|
-
label,
|
|
3213
|
-
path: SchemaEx10.createJsonPath(path ?? []),
|
|
3214
|
-
readonly,
|
|
3215
|
-
presentation: presentationFor(layout),
|
|
3216
|
-
collapsible
|
|
3217
|
-
}, body);
|
|
3218
|
-
};
|
|
3219
|
-
FormFieldSet.displayName = FORM_FIELDSET_NAME;
|
|
3220
|
-
var useFormFieldSetProperties = ({ schema, filter, projection, values, sort }) => {
|
|
3221
|
-
return useMemo12(() => {
|
|
3222
|
-
if (!schema) {
|
|
3223
|
-
return [];
|
|
3224
|
-
}
|
|
3225
|
-
const schemaProps = getRootFormProperties(schema.ast, values);
|
|
3226
|
-
const filteredProps = filter ? filter(schemaProps) : schemaProps;
|
|
3227
|
-
if (projection) {
|
|
3228
|
-
const fieldProjections = projection.getFieldProjections();
|
|
3229
|
-
const hiddenProperties = new Set(projection.getHiddenProperties());
|
|
3230
|
-
const visibleProps = filteredProps.filter((prop) => !hiddenProperties.has(prop.name.toString()));
|
|
3231
|
-
const orderedProps = [];
|
|
3232
|
-
for (const fieldProjection of fieldProjections) {
|
|
3233
|
-
const fieldPath = String(fieldProjection.field.path);
|
|
3234
|
-
const prop = visibleProps.find((prop2) => prop2.name === fieldPath);
|
|
3235
|
-
if (prop) {
|
|
3236
|
-
orderedProps.push(prop);
|
|
3237
|
-
}
|
|
3238
|
-
}
|
|
3239
|
-
const projectionPaths = new Set(fieldProjections.map((projection2) => String(projection2.field.path)));
|
|
3240
|
-
const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name.toString()));
|
|
3241
|
-
orderedProps.push(...remainingProps);
|
|
3242
|
-
return orderedProps;
|
|
3243
|
-
}
|
|
3244
|
-
return sort ? [
|
|
3245
|
-
...filteredProps
|
|
3246
|
-
].sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString())) : filteredProps;
|
|
3247
|
-
}, [
|
|
3248
|
-
schema,
|
|
3249
|
-
values,
|
|
3250
|
-
filter,
|
|
3251
|
-
sort,
|
|
3252
|
-
projection
|
|
3253
|
-
]);
|
|
3254
|
-
};
|
|
3255
|
-
|
|
3256
|
-
// src/components/Form/FormControls.tsx
|
|
3257
|
-
var FormRoot = ({ children, schema, values, onSave, onCancel, ...props }) => {
|
|
3258
|
-
const form = useFormHandler({
|
|
3259
|
-
schema,
|
|
3260
|
-
values,
|
|
3261
|
-
onSave,
|
|
3262
|
-
onCancel,
|
|
3263
|
-
...props
|
|
3264
|
-
});
|
|
3265
|
-
return /* @__PURE__ */ React25.createElement(FormContextProvider, {
|
|
3266
|
-
form,
|
|
3267
|
-
...props
|
|
3268
|
-
}, children);
|
|
3269
|
-
};
|
|
3270
|
-
FormRoot.displayName = "Form.Root";
|
|
3271
|
-
var FORM_VIEWPORT_NAME = "Form.Viewport";
|
|
3272
|
-
var FormViewport = composable(({ children, scroll, gutter = "sm", ...props }, forwardedRef) => {
|
|
3273
|
-
const { variant = "default" } = useFormContext(FORM_VIEWPORT_NAME);
|
|
3274
|
-
const styles3 = formTheme.styles({
|
|
3275
|
-
variant
|
|
3276
|
-
});
|
|
3277
|
-
const span = "[.dx-column-root_&]:col-span-full";
|
|
3278
|
-
if (scroll) {
|
|
3279
|
-
return /* @__PURE__ */ React25.createElement(Column.Root, {
|
|
3280
|
-
gutter,
|
|
3281
|
-
classNames: [
|
|
3282
|
-
"dx-expander",
|
|
3283
|
-
span
|
|
3284
|
-
]
|
|
3285
|
-
}, /* @__PURE__ */ React25.createElement(ScrollArea.Root, {
|
|
3286
|
-
...composableProps(props, {
|
|
3287
|
-
classNames: styles3.viewport()
|
|
3288
|
-
}),
|
|
3289
|
-
orientation: "vertical",
|
|
3290
|
-
centered: true,
|
|
3291
|
-
padding: true,
|
|
3292
|
-
thin: true,
|
|
3293
|
-
ref: forwardedRef
|
|
3294
|
-
}, /* @__PURE__ */ React25.createElement(ScrollArea.Viewport, null, children)));
|
|
3295
|
-
}
|
|
3296
|
-
return /* @__PURE__ */ React25.createElement(Column.Root, {
|
|
3297
|
-
...composableProps(props, {
|
|
3298
|
-
classNames: [
|
|
3299
|
-
"w-full min-w-0",
|
|
3300
|
-
span,
|
|
3301
|
-
styles3.viewport()
|
|
3302
|
-
]
|
|
3303
|
-
}),
|
|
3304
|
-
gutter,
|
|
3305
|
-
ref: forwardedRef
|
|
3306
|
-
}, children);
|
|
3307
|
-
});
|
|
3308
|
-
FormViewport.displayName = FORM_VIEWPORT_NAME;
|
|
3309
|
-
var FORM_CONTENT_NAME = "Form.Content";
|
|
3310
|
-
var FormContent = composable(({ children, ...props }, forwardedRef) => {
|
|
3311
|
-
const { form, testId, variant = "default" } = useFormContext(FORM_CONTENT_NAME);
|
|
3312
|
-
const styles3 = formTheme.styles({
|
|
3313
|
-
variant
|
|
3314
|
-
});
|
|
3315
|
-
const localRef = useRef7(null);
|
|
3316
|
-
const mergedRef = useMergeRefs([
|
|
3317
|
-
forwardedRef,
|
|
3318
|
-
localRef
|
|
3319
|
-
]);
|
|
3320
|
-
useKeyHandler(localRef, form);
|
|
3321
|
-
return /* @__PURE__ */ React25.createElement("div", {
|
|
3322
|
-
...composableProps(props, {
|
|
3323
|
-
role: "form",
|
|
3324
|
-
classNames: mx6(withColumn.center(), "flex flex-col w-full dx-document", styles3.content())
|
|
3325
|
-
}),
|
|
3326
|
-
"data-testid": testId,
|
|
3327
|
-
ref: mergedRef
|
|
3328
|
-
}, children);
|
|
3329
|
-
});
|
|
3330
|
-
FormContent.displayName = FORM_CONTENT_NAME;
|
|
3331
|
-
var FORM_FIELDSET_NAME2 = "Form.FieldSet";
|
|
3332
|
-
var FormFieldSetController = ({ classNames, ...props }) => {
|
|
3333
|
-
const { form, variant = "default", ...contextProps } = useFormContext(FORM_FIELDSET_NAME2);
|
|
3334
|
-
const styles3 = formTheme.styles({
|
|
3335
|
-
variant
|
|
3336
|
-
});
|
|
3337
|
-
return /* @__PURE__ */ React25.createElement(FormFieldSet, {
|
|
3338
|
-
schema: form.schema,
|
|
3339
|
-
classNames: styles3.fieldSet({
|
|
3340
|
-
class: classNames
|
|
3341
|
-
}),
|
|
3342
|
-
...contextProps,
|
|
3343
|
-
...props
|
|
3344
|
-
});
|
|
3345
|
-
};
|
|
3346
|
-
FormFieldSetController.displayName = FORM_FIELDSET_NAME2;
|
|
3347
|
-
var FORM_LAYOUT_NAME2 = "Form.Layout";
|
|
3348
|
-
var FormLayoutController = ({ schema, ...props }) => {
|
|
3349
|
-
const { form, ...contextProps } = useFormContext(FORM_LAYOUT_NAME2);
|
|
3350
|
-
const resolvedSchema = schema ?? form.schema;
|
|
3351
|
-
if (!resolvedSchema) {
|
|
3352
|
-
return null;
|
|
3353
|
-
}
|
|
3354
|
-
return /* @__PURE__ */ React25.createElement(FormLayout, {
|
|
3355
|
-
schema: resolvedSchema,
|
|
3356
|
-
...contextProps,
|
|
3357
|
-
...props
|
|
3358
|
-
});
|
|
3359
|
-
};
|
|
3360
|
-
FormLayoutController.displayName = FORM_LAYOUT_NAME2;
|
|
3361
|
-
var FORM_ACTIONS_NAME = "Form.Actions";
|
|
3362
|
-
var FormActions = ({ classNames }) => {
|
|
3363
|
-
const { t } = useTranslation10(translationKey10);
|
|
3364
|
-
const { form: { canSave, onSave, onCancel }, readonly, layout } = useFormContext(FORM_ACTIONS_NAME);
|
|
3365
|
-
if (readonly || layout === "static") {
|
|
3366
|
-
return null;
|
|
3367
|
-
}
|
|
3368
|
-
return /* @__PURE__ */ React25.createElement("div", {
|
|
3369
|
-
className: mx6(withColumn.center(), formTheme.styles().actions(), classNames)
|
|
3370
|
-
}, onCancel && /* @__PURE__ */ React25.createElement(IconButton5, {
|
|
3371
|
-
icon: "ph--x--regular",
|
|
3372
|
-
iconEnd: true,
|
|
3373
|
-
label: t("cancel-button.label"),
|
|
3374
|
-
onClick: onCancel,
|
|
3375
|
-
"data-testid": "cancel-button"
|
|
3376
|
-
}), onSave && /* @__PURE__ */ React25.createElement(IconButton5, {
|
|
3377
|
-
type: "submit",
|
|
3378
|
-
variant: "primary",
|
|
3379
|
-
disabled: !canSave,
|
|
3380
|
-
icon: "ph--check--regular",
|
|
3381
|
-
iconEnd: true,
|
|
3382
|
-
label: t("save-button.label"),
|
|
3383
|
-
onClick: onSave,
|
|
3384
|
-
"data-testid": "save-button"
|
|
3385
|
-
}));
|
|
3386
|
-
};
|
|
3387
|
-
FormActions.displayName = FORM_ACTIONS_NAME;
|
|
3388
|
-
var FORM_SECTION_NAME = "Form.Section";
|
|
3389
|
-
var FormSection = composable(({ children, title, description, ...props }, forwardedRef) => {
|
|
3390
|
-
const { variant = "default" } = useFormContext(FORM_SECTION_NAME);
|
|
3391
|
-
const styles3 = formTheme.styles({
|
|
3392
|
-
variant
|
|
3393
|
-
});
|
|
3394
|
-
return /* @__PURE__ */ React25.createElement("div", {
|
|
3395
|
-
...composableProps(props, {
|
|
3396
|
-
classNames: styles3.section()
|
|
3397
|
-
}),
|
|
3398
|
-
ref: forwardedRef
|
|
3399
|
-
}, (title || description) && /* @__PURE__ */ React25.createElement("div", {
|
|
3400
|
-
className: styles3.sectionHeader()
|
|
3401
|
-
}, title && /* @__PURE__ */ React25.createElement("h2", {
|
|
3402
|
-
className: styles3.sectionTitle()
|
|
3403
|
-
}, title), description && /* @__PURE__ */ React25.createElement(MarkdownView, {
|
|
3404
|
-
classNames: styles3.sectionDescription(),
|
|
3405
|
-
content: description
|
|
3406
|
-
})), children);
|
|
3407
|
-
});
|
|
3408
|
-
FormSection.displayName = FORM_SECTION_NAME;
|
|
3409
|
-
var FORM_GROUP_NAME = "Form.Group";
|
|
3410
|
-
var FormGroup = composable(({ children, ...props }, forwardedRef) => {
|
|
3411
|
-
const { variant = "default" } = useFormContext(FORM_SECTION_NAME);
|
|
3412
|
-
const styles3 = formTheme.styles({
|
|
3413
|
-
variant
|
|
3414
|
-
});
|
|
3415
|
-
return /* @__PURE__ */ React25.createElement("div", {
|
|
3416
|
-
...composableProps(props, {
|
|
3417
|
-
classNames: styles3.group()
|
|
3418
|
-
}),
|
|
3419
|
-
ref: forwardedRef
|
|
3420
|
-
}, children);
|
|
3421
|
-
});
|
|
3422
|
-
FormGroup.displayName = FORM_GROUP_NAME;
|
|
3423
|
-
var FORM_SUBMIT_NAME = "Form.Submit";
|
|
3424
|
-
var FormSubmit = ({ classNames, label, icon, disabled }) => {
|
|
3425
|
-
const { t } = useTranslation10(translationKey10);
|
|
3426
|
-
const { form: { canSave, onSave }, readonly, layout } = useFormContext(FORM_SUBMIT_NAME);
|
|
3427
|
-
if (readonly || layout === "static") {
|
|
3428
|
-
return null;
|
|
3429
|
-
}
|
|
3430
|
-
return /* @__PURE__ */ React25.createElement("div", {
|
|
3431
|
-
className: mx6(formTheme.styles().submit(), classNames)
|
|
3432
|
-
}, /* @__PURE__ */ React25.createElement(IconButton5, {
|
|
3433
|
-
classNames: "w-full",
|
|
3434
|
-
type: "submit",
|
|
3435
|
-
variant: "primary",
|
|
3436
|
-
disabled: disabled ?? !canSave,
|
|
3437
|
-
icon: icon ?? "ph--check--regular",
|
|
3438
|
-
label: label ?? t("save-button.label"),
|
|
3439
|
-
onClick: onSave,
|
|
3440
|
-
"data-testid": "save-button"
|
|
3441
|
-
}));
|
|
3442
|
-
};
|
|
3443
|
-
FormSubmit.displayName = FORM_SUBMIT_NAME;
|
|
3444
|
-
var FORM_ERROR_NAME = "Form.Error";
|
|
3445
|
-
var FormError = ({ children, classNames }) => {
|
|
3446
|
-
if (!children) {
|
|
3447
|
-
return null;
|
|
3448
|
-
}
|
|
3449
|
-
return /* @__PURE__ */ React25.createElement(Input14.Root, {
|
|
3450
|
-
validationValence: "error"
|
|
3451
|
-
}, /* @__PURE__ */ React25.createElement(Input14.Validation, {
|
|
3452
|
-
classNames
|
|
3453
|
-
}, children));
|
|
3454
|
-
};
|
|
3455
|
-
FormError.displayName = FORM_ERROR_NAME;
|
|
3456
|
-
|
|
3457
|
-
// src/components/Form/Form.tsx
|
|
3458
|
-
var Form = {
|
|
3459
|
-
Root: FormRoot,
|
|
3460
|
-
Viewport: FormViewport,
|
|
3461
|
-
Content: FormContent,
|
|
3462
|
-
Section: FormSection,
|
|
3463
|
-
Group: FormGroup,
|
|
3464
|
-
FieldSet: FormFieldSetController,
|
|
3465
|
-
Layout: FormLayoutController,
|
|
3466
|
-
Label: FormFieldLabel,
|
|
3467
|
-
Row: FormRow,
|
|
3468
|
-
Actions: FormActions,
|
|
3469
|
-
Submit: FormSubmit,
|
|
3470
|
-
Error: FormError
|
|
3471
|
-
};
|
|
3472
|
-
|
|
3473
|
-
// src/components/FieldEditor/FieldEditor.tsx
|
|
3474
|
-
var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
|
|
3475
|
-
var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCancel }) => {
|
|
3476
|
-
const { t } = useTranslation11(translationKey11);
|
|
3477
|
-
const [props, setProps] = useState10(projection.getFieldProjection(field.id).props);
|
|
3478
|
-
useEffect9(() => setProps(projection.getFieldProjection(field.id).props), [
|
|
3479
|
-
field,
|
|
3480
|
-
projection
|
|
3481
|
-
]);
|
|
3482
|
-
const [schemas, setSchemas] = useState10([]);
|
|
3483
|
-
useAsyncEffect(async () => {
|
|
3484
|
-
if (!registry) {
|
|
3485
|
-
return;
|
|
3486
|
-
}
|
|
3487
|
-
const subscription = registry.query(Filter2.type(Type4.Type)).subscribe((query) => setSchemas(query.results), {
|
|
3488
|
-
fire: true
|
|
3489
|
-
});
|
|
3490
|
-
const schemas2 = await registry.query(Filter2.type(Type4.Type)).run();
|
|
3491
|
-
setSchemas(schemas2);
|
|
3492
|
-
return () => subscription?.();
|
|
3493
|
-
}, [
|
|
3494
|
-
registry
|
|
3495
|
-
]);
|
|
3496
|
-
const [referenceSchema, setReferenceSchema] = useState10();
|
|
3497
|
-
useEffect9(() => {
|
|
3498
|
-
setReferenceSchema(() => schemas.find((schema) => Type4.getTypename(schema) === props?.referenceSchema));
|
|
3499
|
-
}, [
|
|
3500
|
-
schemas,
|
|
3501
|
-
props?.referenceSchema
|
|
3502
|
-
]);
|
|
3503
|
-
const [{ fieldSchema }, setFieldSchema] = useState10({
|
|
3504
|
-
fieldSchema: getFormatSchema(props?.format)
|
|
3505
|
-
});
|
|
3506
|
-
const fieldMap = useMemo13(() => ({
|
|
3507
|
-
["format"]: (props2) => /* @__PURE__ */ React26.createElement(SelectField, {
|
|
3508
|
-
...props2,
|
|
3509
|
-
options: FormatEnums.filter((value3) => value3 !== Format6.TypeFormat.None).map((value3) => ({
|
|
3510
|
-
value: value3,
|
|
3511
|
-
label: t(`format.${value3}.label`)
|
|
3512
|
-
}))
|
|
3513
|
-
}),
|
|
3514
|
-
["referenceSchema"]: (props2) => /* @__PURE__ */ React26.createElement(SelectField, {
|
|
3515
|
-
...props2,
|
|
3516
|
-
options: schemas.map((schema) => Type4.getTypename(schema)).filter((typename) => typename != null).map((typename) => ({
|
|
3517
|
-
value: typename
|
|
3518
|
-
}))
|
|
3519
|
-
}),
|
|
3520
|
-
["referencePath"]: (props2) => /* @__PURE__ */ React26.createElement(SelectField, {
|
|
3521
|
-
...props2,
|
|
3522
|
-
options: referenceSchema ? getFormProperties(Type4.getSchema(referenceSchema).ast).sort((a, b) => a.name.toString().localeCompare(b.name.toString())).map((p) => ({
|
|
3523
|
-
value: p.name.toString()
|
|
3524
|
-
})) : []
|
|
3525
|
-
}),
|
|
3526
|
-
["options"]: (props2) => /* @__PURE__ */ React26.createElement(SelectOptionField, props2)
|
|
3527
|
-
}), [
|
|
3528
|
-
t,
|
|
3529
|
-
schemas,
|
|
3530
|
-
referenceSchema
|
|
3531
|
-
]);
|
|
3532
|
-
const propIsNotType = useCallback18((props2) => props2.filter((prop) => prop.name !== "type"), []);
|
|
3533
|
-
const handleValuesChanged = useCallback18((_props) => {
|
|
3534
|
-
setFieldSchema((prev) => {
|
|
3535
|
-
const fieldSchema2 = getFormatSchema(_props.format);
|
|
3536
|
-
if (prev.fieldSchema === fieldSchema2) {
|
|
3537
|
-
return prev;
|
|
3538
|
-
}
|
|
3539
|
-
return {
|
|
3540
|
-
fieldSchema: fieldSchema2
|
|
3541
|
-
};
|
|
3542
|
-
});
|
|
3543
|
-
setReferenceSchema((prev) => {
|
|
3544
|
-
if (_props.referenceSchema !== (prev ? Type4.getTypename(prev) : void 0)) {
|
|
3545
|
-
const newSchema = schemas.find((schema) => Type4.getTypename(schema) === _props.referenceSchema);
|
|
3546
|
-
if (newSchema) {
|
|
3547
|
-
return newSchema;
|
|
3548
|
-
}
|
|
3549
|
-
}
|
|
3550
|
-
return prev;
|
|
3551
|
-
});
|
|
3552
|
-
setProps((props2) => {
|
|
3553
|
-
const type = formatToType[_props.format];
|
|
3554
|
-
const additionalProps = formatToAdditionalPropertyAttributes[_props.format];
|
|
3555
|
-
if (props2.type !== type) {
|
|
3556
|
-
return {
|
|
3557
|
-
...props2,
|
|
3558
|
-
..._props,
|
|
3559
|
-
...additionalProps,
|
|
3560
|
-
type
|
|
3561
|
-
};
|
|
3562
|
-
}
|
|
3563
|
-
return _props;
|
|
3564
|
-
});
|
|
3565
|
-
}, [
|
|
3566
|
-
schemas,
|
|
3567
|
-
props.format,
|
|
3568
|
-
props.referenceSchema
|
|
3569
|
-
]);
|
|
3570
|
-
const handleValidate = useCallback18(({ property }) => {
|
|
3571
|
-
if (property && projection.getFields().find((f) => f.path === property && f.path !== field.path)) {
|
|
3572
|
-
return [
|
|
3573
|
-
{
|
|
3574
|
-
path: "property",
|
|
3575
|
-
message: `property is not unique: '${property}'`
|
|
3576
|
-
}
|
|
3577
|
-
];
|
|
3578
|
-
}
|
|
3579
|
-
}, [
|
|
3580
|
-
projection.getFields(),
|
|
3581
|
-
field
|
|
3582
|
-
]);
|
|
3583
|
-
const handleSave = useCallback18((props2) => {
|
|
3584
|
-
if (view) {
|
|
3585
|
-
Obj3.update(view, () => {
|
|
3586
|
-
projection.setFieldProjection({
|
|
3587
|
-
field,
|
|
3588
|
-
props: props2
|
|
3589
|
-
});
|
|
3590
|
-
});
|
|
3591
|
-
} else {
|
|
3592
|
-
projection.setFieldProjection({
|
|
3593
|
-
field,
|
|
3594
|
-
props: props2
|
|
3595
|
-
});
|
|
3596
|
-
}
|
|
3597
|
-
onSave();
|
|
3598
|
-
}, [
|
|
3599
|
-
projection,
|
|
3600
|
-
field,
|
|
3601
|
-
view,
|
|
3602
|
-
onSave
|
|
3603
|
-
]);
|
|
3604
|
-
const handleCancel = useCallback18(() => {
|
|
3605
|
-
onSave();
|
|
3606
|
-
requestAnimationFrame(() => onCancel?.());
|
|
3607
|
-
}, [
|
|
3608
|
-
onSave
|
|
3609
|
-
]);
|
|
3610
|
-
if (!fieldSchema) {
|
|
3611
|
-
log3.warn("invalid format", {
|
|
3612
|
-
props
|
|
3613
|
-
}, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 159, S: void 0 });
|
|
3614
|
-
return null;
|
|
3615
|
-
}
|
|
3616
|
-
return /* @__PURE__ */ React26.createElement(Form.Root, {
|
|
3617
|
-
key: field.id,
|
|
3618
|
-
fieldMap,
|
|
3619
|
-
autoFocus: true,
|
|
3620
|
-
readonly,
|
|
3621
|
-
schema: fieldSchema,
|
|
3622
|
-
values: props,
|
|
3623
|
-
filter: propIsNotType,
|
|
3624
|
-
sort: [
|
|
3625
|
-
"property",
|
|
3626
|
-
"format"
|
|
3627
|
-
],
|
|
3628
|
-
onValuesChanged: handleValuesChanged,
|
|
3629
|
-
onValidate: handleValidate,
|
|
3630
|
-
onSave: handleSave,
|
|
3631
|
-
onCancel: handleCancel
|
|
3632
|
-
}, /* @__PURE__ */ React26.createElement(Form.Content, null, /* @__PURE__ */ React26.createElement(Form.FieldSet, null), /* @__PURE__ */ React26.createElement(Form.Actions, null)));
|
|
3633
|
-
};
|
|
3634
|
-
|
|
3635
|
-
// src/components/ObjectForm/ObjectForm.tsx
|
|
3636
|
-
import React27, { useCallback as useCallback19, useMemo as useMemo14 } from "react";
|
|
3637
|
-
import { Obj as Obj4, Ref as Ref7, Tag as Tag3, Type as Type5 } from "@dxos/echo";
|
|
3638
|
-
import { SchemaEx as SchemaEx11 } from "@dxos/effect";
|
|
3639
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
3640
|
-
import { HuePicker as HuePicker2 } from "@dxos/react-ui-pickers";
|
|
3641
|
-
import { translationKey as translationKey12 } from "#translations";
|
|
3642
|
-
var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ObjectForm/ObjectForm.tsx";
|
|
3643
|
-
var ObjectForm = ({ object, type }) => {
|
|
3644
|
-
const db = Obj4.getDatabase(object);
|
|
3645
|
-
const meta = Obj4.getMeta(object);
|
|
3646
|
-
const tags = [
|
|
3647
|
-
...meta.tags
|
|
3648
|
-
];
|
|
3649
|
-
const values = useMemo14(() => ({
|
|
3650
|
-
[META_TAGS_KEY]: tags,
|
|
3651
|
-
...object
|
|
3652
|
-
}), [
|
|
3653
|
-
object,
|
|
3654
|
-
tags
|
|
3655
|
-
]);
|
|
3656
|
-
const formSchema = useMemo14(() => withMetaTags(Type5.getSchema(type)), [
|
|
3657
|
-
type
|
|
3658
|
-
]);
|
|
3659
|
-
const handleCreate = useCallback19((type2, values2) => {
|
|
3660
|
-
invariant2(db, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 29, S: void 0, A: ["db", ""] });
|
|
3661
|
-
invariant2(Type5.isObject(type2), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 30, S: void 0, A: ["Type.isObject(type)", ""] });
|
|
3662
|
-
const newObject = db.add(Obj4.make(type2, values2));
|
|
3663
|
-
if (Obj4.instanceOf(Tag3.Tag, newObject)) {
|
|
3664
|
-
Obj4.update(object, (object2) => {
|
|
3665
|
-
Obj4.getMeta(object2).tags = [
|
|
3666
|
-
...Obj4.getMeta(object2).tags,
|
|
3667
|
-
Ref7.make(newObject)
|
|
3668
|
-
];
|
|
3669
|
-
});
|
|
3670
|
-
}
|
|
3671
|
-
}, []);
|
|
3672
|
-
const handleChange = useCallback19(({ [META_TAGS_KEY]: metaTags, ...values2 }, { isValid, changed }) => {
|
|
3673
|
-
if (!isValid) {
|
|
3674
|
-
return;
|
|
3675
|
-
}
|
|
3676
|
-
const changedPaths = Object.keys(changed).filter((path) => changed[path]);
|
|
3677
|
-
const hasTagsChange = changedPaths.some((path) => SchemaEx11.splitJsonPath(path)[0] === META_TAGS_KEY);
|
|
3678
|
-
if (hasTagsChange) {
|
|
3679
|
-
Obj4.update(object, (object2) => {
|
|
3680
|
-
Obj4.getMeta(object2).tags = Array.isArray(metaTags) ? [
|
|
3681
|
-
...metaTags
|
|
3682
|
-
] : [];
|
|
3683
|
-
});
|
|
3684
|
-
}
|
|
3685
|
-
const nonTagPaths = changedPaths.filter((path) => SchemaEx11.splitJsonPath(path)[0] !== META_TAGS_KEY);
|
|
3686
|
-
if (nonTagPaths.length > 0) {
|
|
3687
|
-
Obj4.update(object, () => {
|
|
3688
|
-
for (const path of nonTagPaths) {
|
|
3689
|
-
const parts = SchemaEx11.splitJsonPath(path);
|
|
3690
|
-
const value3 = Obj4.getValue(values2, parts);
|
|
3691
|
-
Obj4.setValue(object, parts, value3);
|
|
3692
|
-
}
|
|
3693
|
-
});
|
|
3694
|
-
}
|
|
3695
|
-
}, [
|
|
3696
|
-
object
|
|
3697
|
-
]);
|
|
3698
|
-
return /* @__PURE__ */ React27.createElement(Form.Root, {
|
|
3699
|
-
schema: formSchema,
|
|
3700
|
-
defaultValues: values,
|
|
3701
|
-
createTypename: Type5.getTypename(Tag3.Tag),
|
|
3702
|
-
createOptionIcon: "ph--plus--regular",
|
|
3703
|
-
createOptionLabel: [
|
|
3704
|
-
"add-tag.label",
|
|
3705
|
-
{
|
|
3706
|
-
ns: translationKey12
|
|
3707
|
-
}
|
|
3708
|
-
],
|
|
3709
|
-
createInitialValuePath: "label",
|
|
3710
|
-
createFieldMap,
|
|
3711
|
-
db,
|
|
3712
|
-
onValuesChanged: handleChange,
|
|
3713
|
-
onCreate: handleCreate
|
|
3714
|
-
}, /* @__PURE__ */ React27.createElement(Form.Viewport, null, /* @__PURE__ */ React27.createElement(Form.Content, null, /* @__PURE__ */ React27.createElement(Form.FieldSet, null))));
|
|
3715
|
-
};
|
|
3716
|
-
var createFieldMap = {
|
|
3717
|
-
hue: ({ type, label, presentation, getValue, onValueChange }) => {
|
|
3718
|
-
const handleChange = useCallback19((nextHue) => onValueChange(type, nextHue), [
|
|
3719
|
-
onValueChange,
|
|
3720
|
-
type
|
|
3721
|
-
]);
|
|
3722
|
-
const handleReset = useCallback19(() => onValueChange(type, void 0), [
|
|
3723
|
-
onValueChange,
|
|
3724
|
-
type
|
|
3725
|
-
]);
|
|
3726
|
-
return /* @__PURE__ */ React27.createElement(React27.Fragment, null, presentation !== "inline" && /* @__PURE__ */ React27.createElement(Form.Label, {
|
|
3727
|
-
label
|
|
3728
|
-
}), /* @__PURE__ */ React27.createElement(HuePicker2, {
|
|
3729
|
-
value: getValue(),
|
|
3730
|
-
onChange: handleChange,
|
|
3731
|
-
onReset: handleReset
|
|
3732
|
-
}));
|
|
3733
|
-
}
|
|
3734
|
-
};
|
|
3735
|
-
|
|
3736
|
-
// src/components/ObjectProperties/ObjectProperties.tsx
|
|
3737
|
-
import * as Function from "effect/Function";
|
|
3738
|
-
import * as Option8 from "effect/Option";
|
|
3739
|
-
import React28, { useCallback as useCallback20, useMemo as useMemo15 } from "react";
|
|
3740
|
-
import { Obj as Obj5, Tag as Tag4, Type as Type6 } from "@dxos/echo";
|
|
3741
|
-
import { useType } from "@dxos/echo-react";
|
|
3742
|
-
import { SchemaEx as SchemaEx12 } from "@dxos/effect";
|
|
3743
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
3744
|
-
import { composable as composable2, composableProps as composableProps2 } from "@dxos/react-ui";
|
|
3745
|
-
import { HuePicker as HuePicker3 } from "@dxos/react-ui-pickers";
|
|
3746
|
-
import { FactoryAnnotation } from "@dxos/schema";
|
|
3747
|
-
import { translationKey as translationKey13 } from "#translations";
|
|
3748
|
-
var __dxlog_file6 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ObjectProperties/ObjectProperties.tsx";
|
|
3749
|
-
var ObjectProperties = composable2(({ children, object, getCreateDefaults, resolveCreateEntry, ...props }, forwardedRef) => {
|
|
3750
|
-
const db = Obj5.getDatabase(object);
|
|
3751
|
-
const meta = Obj5.getMeta(object);
|
|
3752
|
-
const tags = [
|
|
3753
|
-
...meta.tags
|
|
3754
|
-
];
|
|
3755
|
-
const values = useMemo15(() => ({
|
|
3756
|
-
[META_TAGS_KEY]: tags,
|
|
3757
|
-
...object
|
|
3758
|
-
}), [
|
|
3759
|
-
object,
|
|
3760
|
-
tags
|
|
3761
|
-
]);
|
|
3762
|
-
const typeUri = Obj5.getTypeURI(object);
|
|
3763
|
-
const typeFromRegistry = useType(db, typeUri);
|
|
3764
|
-
const type = Obj5.getType(object) ?? typeFromRegistry;
|
|
3765
|
-
const formSchema = useMemo15(() => {
|
|
3766
|
-
return Function.pipe(type, Option8.fromNullable, Option8.map((type2) => Type6.getSchema(type2)), Option8.map((schema) => withMetaTags(schema)), Option8.getOrUndefined);
|
|
3767
|
-
}, [
|
|
3768
|
-
type
|
|
3769
|
-
]);
|
|
3770
|
-
const handleCreate = useCallback20((type2, values2) => {
|
|
3771
|
-
invariant3(db, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 52, S: void 0, A: ["db", ""] });
|
|
3772
|
-
invariant3(Type6.isObject(type2), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 53, S: void 0, A: ["Type.isObject(type)", ""] });
|
|
3773
|
-
const factory = Option8.getOrUndefined(FactoryAnnotation.get(Type6.getSchema(type2)));
|
|
3774
|
-
const newObject = factory ? factory(values2) : Obj5.make(type2, values2);
|
|
3775
|
-
return db.add(newObject);
|
|
3776
|
-
}, [
|
|
3777
|
-
db
|
|
3778
|
-
]);
|
|
3779
|
-
const handleChange = useCallback20(({ [META_TAGS_KEY]: metaTags, ...values2 }, { isValid, changed }) => {
|
|
3780
|
-
if (!isValid) {
|
|
3781
|
-
return;
|
|
3782
|
-
}
|
|
3783
|
-
const changedPaths = Object.keys(changed).filter((path) => changed[path]);
|
|
3784
|
-
const hasTagsChange = changedPaths.some((path) => SchemaEx12.splitJsonPath(path)[0] === META_TAGS_KEY);
|
|
3785
|
-
if (hasTagsChange) {
|
|
3786
|
-
Obj5.update(object, (object2) => {
|
|
3787
|
-
Obj5.getMeta(object2).tags = Array.isArray(metaTags) ? [
|
|
3788
|
-
...metaTags
|
|
3789
|
-
] : [];
|
|
3790
|
-
});
|
|
3791
|
-
}
|
|
3792
|
-
const nonTagPaths = changedPaths.filter((path) => SchemaEx12.splitJsonPath(path)[0] !== META_TAGS_KEY);
|
|
3793
|
-
if (nonTagPaths.length > 0) {
|
|
3794
|
-
Obj5.update(object, () => {
|
|
3795
|
-
for (const path of nonTagPaths) {
|
|
3796
|
-
const parts = SchemaEx12.splitJsonPath(path);
|
|
3797
|
-
const value3 = Obj5.getValue(values2, parts);
|
|
3798
|
-
Obj5.setValue(object, parts, value3);
|
|
3799
|
-
}
|
|
3800
|
-
});
|
|
3801
|
-
}
|
|
3802
|
-
}, [
|
|
3803
|
-
object
|
|
3804
|
-
]);
|
|
3805
|
-
if (!formSchema) {
|
|
3806
|
-
return null;
|
|
3807
|
-
}
|
|
3808
|
-
return /* @__PURE__ */ React28.createElement(Form.Root, {
|
|
3809
|
-
db,
|
|
3810
|
-
schema: formSchema,
|
|
3811
|
-
defaultValues: values,
|
|
3812
|
-
createTypename: Type6.getTypename(Tag4.Tag),
|
|
3813
|
-
createOptionIcon: "ph--plus--regular",
|
|
3814
|
-
createOptionLabel: [
|
|
3815
|
-
"add-tag.label",
|
|
3816
|
-
{
|
|
3817
|
-
ns: translationKey13
|
|
3818
|
-
}
|
|
3819
|
-
],
|
|
3820
|
-
createInitialValuePath: "label",
|
|
3821
|
-
createFieldMap: createFieldMap2,
|
|
3822
|
-
onValuesChanged: handleChange,
|
|
3823
|
-
onCreate: handleCreate,
|
|
3824
|
-
getCreateDefaults,
|
|
3825
|
-
resolveCreateEntry
|
|
3826
|
-
}, /* @__PURE__ */ React28.createElement(Form.Viewport, {
|
|
3827
|
-
...composableProps2(props),
|
|
3828
|
-
scroll: true,
|
|
3829
|
-
ref: forwardedRef
|
|
3830
|
-
}, /* @__PURE__ */ React28.createElement(Form.Content, null, /* @__PURE__ */ React28.createElement(Form.FieldSet, null), /* @__PURE__ */ React28.createElement(Form.Section, null, children))));
|
|
3831
|
-
});
|
|
3832
|
-
var createFieldMap2 = {
|
|
3833
|
-
hue: ({ type, label, presentation, getValue, onValueChange }) => {
|
|
3834
|
-
const handleChange = useCallback20((nextHue) => onValueChange(type, nextHue), [
|
|
3835
|
-
onValueChange,
|
|
3836
|
-
type
|
|
3837
|
-
]);
|
|
3838
|
-
const handleReset = useCallback20(() => onValueChange(type, void 0), [
|
|
3839
|
-
onValueChange,
|
|
3840
|
-
type
|
|
3841
|
-
]);
|
|
3842
|
-
return /* @__PURE__ */ React28.createElement(React28.Fragment, null, presentation !== "inline" && /* @__PURE__ */ React28.createElement(Form.Label, {
|
|
3843
|
-
label
|
|
3844
|
-
}), /* @__PURE__ */ React28.createElement(HuePicker3, {
|
|
3845
|
-
value: getValue(),
|
|
3846
|
-
onChange: handleChange,
|
|
3847
|
-
onReset: handleReset
|
|
3848
|
-
}));
|
|
3849
|
-
}
|
|
3850
|
-
};
|
|
3851
|
-
|
|
3852
|
-
// src/components/ObjectTree/ObjectTree.tsx
|
|
3853
|
-
import * as SchemaAST8 from "effect/SchemaAST";
|
|
3854
|
-
import React29 from "react";
|
|
3855
|
-
import { composable as composable3, composableProps as composableProps3 } from "@dxos/react-ui";
|
|
3856
|
-
import { mx as mx7 } from "@dxos/ui-theme";
|
|
3857
|
-
var ObjectTreeImpl = composable3(({ schema, value: value3, ...props }, forwardedRef) => /* @__PURE__ */ React29.createElement("div", {
|
|
3858
|
-
...composableProps3(props, {
|
|
3859
|
-
role: "table",
|
|
3860
|
-
classNames: "font-mono text-sm w-full"
|
|
3861
|
-
}),
|
|
3862
|
-
ref: forwardedRef
|
|
3863
|
-
}, /* @__PURE__ */ React29.createElement(Node, {
|
|
3864
|
-
ast: schema.ast,
|
|
3865
|
-
value: value3,
|
|
3866
|
-
label: null,
|
|
3867
|
-
depth: 0
|
|
3868
|
-
})));
|
|
3869
|
-
ObjectTreeImpl.displayName = "ObjectTree";
|
|
3870
|
-
var ObjectTree = ObjectTreeImpl;
|
|
3871
|
-
var unwrap = (ast) => {
|
|
3872
|
-
if (SchemaAST8.isRefinement(ast)) {
|
|
3873
|
-
return unwrap(ast.from);
|
|
3874
|
-
}
|
|
3875
|
-
if (SchemaAST8.isSuspend(ast)) {
|
|
3876
|
-
return unwrap(ast.f());
|
|
3877
|
-
}
|
|
3878
|
-
if (SchemaAST8.isTransformation(ast)) {
|
|
3879
|
-
return unwrap(ast.from);
|
|
3880
|
-
}
|
|
3881
|
-
return ast;
|
|
3882
|
-
};
|
|
3883
|
-
var stripOptional = (ast) => {
|
|
3884
|
-
if (!SchemaAST8.isUnion(ast)) {
|
|
3885
|
-
return ast;
|
|
3886
|
-
}
|
|
3887
|
-
const nonUndef = ast.types.filter((t) => !SchemaAST8.isUndefinedKeyword(t));
|
|
3888
|
-
return nonUndef.length === 1 ? nonUndef[0] : ast;
|
|
3889
|
-
};
|
|
3890
|
-
var Node = ({ ast, value: value3, label, depth }) => {
|
|
3891
|
-
const inner = unwrap(stripOptional(ast));
|
|
3892
|
-
if (SchemaAST8.isTypeLiteral(inner) && isPlainObject(value3)) {
|
|
3893
|
-
const childDepth = label === null ? depth : depth + 1;
|
|
3894
|
-
return /* @__PURE__ */ React29.createElement(React29.Fragment, null, label !== null && /* @__PURE__ */ React29.createElement(Row, {
|
|
3895
|
-
label,
|
|
3896
|
-
value: null,
|
|
3897
|
-
depth,
|
|
3898
|
-
kind: "group"
|
|
3899
|
-
}), inner.propertySignatures.map((prop) => /* @__PURE__ */ React29.createElement(Node, {
|
|
3900
|
-
key: String(prop.name),
|
|
3901
|
-
ast: prop.type,
|
|
3902
|
-
value: value3[String(prop.name)],
|
|
3903
|
-
label: String(prop.name),
|
|
3904
|
-
depth: childDepth
|
|
3905
|
-
})));
|
|
3906
|
-
}
|
|
3907
|
-
if (SchemaAST8.isTupleType(inner) && Array.isArray(value3)) {
|
|
3908
|
-
const elemType = inner.rest[0]?.type;
|
|
3909
|
-
return /* @__PURE__ */ React29.createElement(React29.Fragment, null, label !== null && /* @__PURE__ */ React29.createElement(Row, {
|
|
3910
|
-
label,
|
|
3911
|
-
value: `Array(${value3.length})`,
|
|
3912
|
-
depth,
|
|
3913
|
-
kind: "group"
|
|
3914
|
-
}), value3.map((item, index) => /* @__PURE__ */ React29.createElement(Node, {
|
|
3915
|
-
key: index,
|
|
3916
|
-
ast: elemType ?? SchemaAST8.unknownKeyword,
|
|
3917
|
-
value: item,
|
|
3918
|
-
label: `[${index}]`,
|
|
3919
|
-
depth: depth + 1
|
|
3920
|
-
})));
|
|
3921
|
-
}
|
|
3922
|
-
return /* @__PURE__ */ React29.createElement(Row, {
|
|
3923
|
-
label: label ?? "",
|
|
3924
|
-
value: formatLeaf(value3),
|
|
3925
|
-
depth,
|
|
3926
|
-
kind: "leaf"
|
|
3927
|
-
});
|
|
3928
|
-
};
|
|
3929
|
-
var Row = ({ label, value: value3, depth }) => /* @__PURE__ */ React29.createElement("div", {
|
|
3930
|
-
role: "row",
|
|
3931
|
-
className: mx7("flex items-baseline gap-3 py-1"),
|
|
3932
|
-
style: {
|
|
3933
|
-
paddingInlineStart: 8 + depth * 16
|
|
3934
|
-
}
|
|
3935
|
-
}, /* @__PURE__ */ React29.createElement("div", {
|
|
3936
|
-
role: "cell",
|
|
3937
|
-
className: "text-subdued"
|
|
3938
|
-
}, label), /* @__PURE__ */ React29.createElement("div", {
|
|
3939
|
-
role: "cell",
|
|
3940
|
-
className: mx7("break-all text-base-fg")
|
|
3941
|
-
}, value3));
|
|
3942
|
-
var isPlainObject = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
3943
|
-
var formatLeaf = (value3) => {
|
|
3944
|
-
if (value3 === void 0) {
|
|
3945
|
-
return null;
|
|
3946
|
-
}
|
|
3947
|
-
if (value3 === null) {
|
|
3948
|
-
return /* @__PURE__ */ React29.createElement("span", {
|
|
3949
|
-
className: "text-description"
|
|
3950
|
-
}, "null");
|
|
3951
|
-
}
|
|
3952
|
-
switch (typeof value3) {
|
|
3953
|
-
case "string":
|
|
3954
|
-
return /* @__PURE__ */ React29.createElement("span", {
|
|
3955
|
-
className: "text-blue-text"
|
|
3956
|
-
}, JSON.stringify(value3));
|
|
3957
|
-
case "number":
|
|
3958
|
-
case "bigint":
|
|
3959
|
-
return /* @__PURE__ */ React29.createElement("span", {
|
|
3960
|
-
className: "text-green-text"
|
|
3961
|
-
}, String(value3));
|
|
3962
|
-
case "boolean":
|
|
3963
|
-
return /* @__PURE__ */ React29.createElement("span", {
|
|
3964
|
-
className: "text-purple-text"
|
|
3965
|
-
}, String(value3));
|
|
3966
|
-
default:
|
|
3967
|
-
try {
|
|
3968
|
-
return JSON.stringify(value3);
|
|
3969
|
-
} catch {
|
|
3970
|
-
return String(value3);
|
|
3971
|
-
}
|
|
3972
|
-
}
|
|
3973
|
-
};
|
|
3974
|
-
|
|
3975
|
-
// src/components/RefEditor/RefEditor.tsx
|
|
3976
|
-
import { Prec } from "@codemirror/state";
|
|
3977
|
-
import React30, { forwardRef as forwardRef2, useCallback as useCallback21, useEffect as useEffect10, useMemo as useMemo16, useRef as useRef8 } from "react";
|
|
3978
|
-
import { Filter as Filter3, Obj as Obj6 } from "@dxos/echo";
|
|
3979
|
-
import { useQuery as useQuery2 } from "@dxos/react-client/echo";
|
|
3980
|
-
import { useThemeContext, useTranslation as useTranslation12 } from "@dxos/react-ui";
|
|
3981
|
-
import { Editor as Editor2 } from "@dxos/react-ui-editor";
|
|
3982
|
-
import { createBasicExtensions, createThemeExtensions, insertAtCursor, keymap } from "@dxos/ui-editor";
|
|
3983
|
-
import { getHashHue as getHashHue2 } from "@dxos/ui-theme";
|
|
3984
|
-
import { translationKey as translationKey14 } from "#translations";
|
|
3985
|
-
|
|
3986
|
-
// src/components/RefEditor/ref-editor-extension.ts
|
|
3987
|
-
import { RangeSetBuilder, StateEffect, StateField } from "@codemirror/state";
|
|
3988
|
-
import { Decoration, EditorView, WidgetType } from "@codemirror/view";
|
|
3989
|
-
import { Domino } from "@dxos/ui";
|
|
3990
|
-
import { getHashHue, getStyles as getStyles2, mx as mx8 } from "@dxos/ui-theme";
|
|
3991
|
-
var REF_REGEX = /^@([A-Za-z0-9]+)$/;
|
|
3992
|
-
var EMAIL_REGEX = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
|
|
3993
|
-
var NAME_ADDR_REGEX = /^(.*?)\s*<([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})>$/;
|
|
3994
|
-
var formatMailbox = (name, email) => name ? `${name} <${email}>` : email;
|
|
3995
|
-
var refEditorRedecorate = StateEffect.define();
|
|
3996
|
-
var refEditor = ({ mode = "ref", getRef, match: match2 } = {}) => {
|
|
3997
|
-
const buildRefDecorations = (state) => {
|
|
3998
|
-
const deco = new RangeSetBuilder();
|
|
3999
|
-
const text = state.doc.toString();
|
|
4000
|
-
const tokenRegex = /\S+/g;
|
|
4001
|
-
let tokenMatch;
|
|
4002
|
-
while (tokenMatch = tokenRegex.exec(text)) {
|
|
4003
|
-
const token = tokenMatch[0];
|
|
4004
|
-
const from = tokenMatch.index;
|
|
4005
|
-
const to = from + token.length;
|
|
4006
|
-
const refMatch = token.match(REF_REGEX);
|
|
4007
|
-
if (refMatch) {
|
|
4008
|
-
const ref = getRef?.(refMatch[1]);
|
|
4009
|
-
if (ref) {
|
|
4010
|
-
deco.add(from, to, Decoration.widget({
|
|
4011
|
-
widget: new RefWidget(ref.label, ref.hue ?? getHashHue(refMatch[1])),
|
|
4012
|
-
atomic: true
|
|
4013
|
-
}));
|
|
4014
|
-
}
|
|
4015
|
-
continue;
|
|
4016
|
-
}
|
|
4017
|
-
if (match2?.test(token)) {
|
|
4018
|
-
deco.add(from, to, Decoration.widget({
|
|
4019
|
-
widget: new TokenWidget(token),
|
|
4020
|
-
atomic: true
|
|
4021
|
-
}));
|
|
4022
|
-
}
|
|
4023
|
-
}
|
|
4024
|
-
return deco.finish();
|
|
4025
|
-
};
|
|
4026
|
-
const buildEmailDecorations = (state) => {
|
|
4027
|
-
const addrRegex = match2 ?? EMAIL_REGEX;
|
|
4028
|
-
const deco = new RangeSetBuilder();
|
|
4029
|
-
const text = state.doc.toString();
|
|
4030
|
-
const segmentRegex = /[^,]+(?:,\s*)?|,\s*/g;
|
|
4031
|
-
let segmentMatch;
|
|
4032
|
-
while (segmentMatch = segmentRegex.exec(text)) {
|
|
4033
|
-
const segment = segmentMatch[0];
|
|
4034
|
-
const commaIndex = segment.indexOf(",");
|
|
4035
|
-
const content = (commaIndex === -1 ? segment : segment.slice(0, commaIndex)).trim();
|
|
4036
|
-
if (!content) {
|
|
4037
|
-
continue;
|
|
4038
|
-
}
|
|
4039
|
-
const leading = segment.length - segment.trimStart().length;
|
|
4040
|
-
const from = segmentMatch.index + leading;
|
|
4041
|
-
const to = segmentMatch.index + segment.length;
|
|
4042
|
-
const nameAddr = content.match(NAME_ADDR_REGEX);
|
|
4043
|
-
if (nameAddr) {
|
|
4044
|
-
deco.add(from, to, Decoration.widget({
|
|
4045
|
-
widget: new RefWidget(nameAddr[1] || nameAddr[2], getHashHue(nameAddr[2])),
|
|
4046
|
-
atomic: true
|
|
4047
|
-
}));
|
|
4048
|
-
} else if (addrRegex.test(content)) {
|
|
4049
|
-
deco.add(from, to, Decoration.widget({
|
|
4050
|
-
widget: new TokenWidget(content),
|
|
4051
|
-
atomic: true
|
|
4052
|
-
}));
|
|
4053
|
-
}
|
|
4054
|
-
}
|
|
4055
|
-
return deco.finish();
|
|
4056
|
-
};
|
|
4057
|
-
const buildDecorations = mode === "email" ? buildEmailDecorations : buildRefDecorations;
|
|
4058
|
-
return [
|
|
4059
|
-
styles2,
|
|
4060
|
-
StateField.define({
|
|
4061
|
-
create: (state) => buildDecorations(state),
|
|
4062
|
-
update: (deco, tr) => {
|
|
4063
|
-
if (tr.docChanged || tr.effects.some((effect) => effect.is(refEditorRedecorate))) {
|
|
4064
|
-
return buildDecorations(tr.state);
|
|
4065
|
-
}
|
|
4066
|
-
return deco;
|
|
4067
|
-
},
|
|
4068
|
-
provide: (field) => [
|
|
4069
|
-
EditorView.decorations.from(field),
|
|
4070
|
-
EditorView.atomicRanges.of((view) => {
|
|
4071
|
-
const builder = new RangeSetBuilder();
|
|
4072
|
-
const cursor = view.state.field(field).iter();
|
|
4073
|
-
while (cursor.value) {
|
|
4074
|
-
if (cursor.value.spec.atomic) {
|
|
4075
|
-
builder.add(cursor.from, cursor.to, cursor.value);
|
|
4076
|
-
}
|
|
4077
|
-
cursor.next();
|
|
4078
|
-
}
|
|
4079
|
-
return builder.finish();
|
|
4080
|
-
})
|
|
4081
|
-
]
|
|
4082
|
-
})
|
|
4083
|
-
];
|
|
4084
|
-
};
|
|
4085
|
-
var lineHeight = "30px";
|
|
4086
|
-
var container = (classNames, ...children) => {
|
|
4087
|
-
const inner = Domino.of("span").classNames(mx8("inline-flex h-[26px] border rounded-xs", classNames)).append(...children);
|
|
4088
|
-
return Domino.of("span").classNames("inline-flex h-[28px] align-middle").append(inner).root;
|
|
4089
|
-
};
|
|
4090
|
-
var RefWidget = class extends WidgetType {
|
|
4091
|
-
_label;
|
|
4092
|
-
_hue;
|
|
4093
|
-
constructor(_label, _hue) {
|
|
4094
|
-
super(), this._label = _label, this._hue = _hue;
|
|
4095
|
-
}
|
|
4096
|
-
eq(other) {
|
|
4097
|
-
return this._label === other._label && this._hue === other._hue;
|
|
4098
|
-
}
|
|
4099
|
-
toDOM() {
|
|
4100
|
-
const { bg: fill, border, surface } = getStyles2(this._hue);
|
|
4101
|
-
return container(border, Domino.of("span").classNames(mx8("flex items-center px-1 text-black text-xs", fill)).text("@"), Domino.of("span").classNames(mx8("flex items-center px-1 text-subdued text-sm rounded-r-[3px]", surface)).text(this._label));
|
|
4102
|
-
}
|
|
4103
|
-
};
|
|
4104
|
-
var TokenWidget = class extends WidgetType {
|
|
4105
|
-
_token;
|
|
4106
|
-
constructor(_token) {
|
|
4107
|
-
super(), this._token = _token;
|
|
4108
|
-
}
|
|
4109
|
-
eq(other) {
|
|
4110
|
-
return this._token === other._token;
|
|
4111
|
-
}
|
|
4112
|
-
toDOM() {
|
|
4113
|
-
return container("border-separator", Domino.of("span").classNames("flex items-center px-1 text-subdued text-sm").text(this._token));
|
|
4114
|
-
}
|
|
4115
|
-
};
|
|
4116
|
-
var styles2 = EditorView.theme({
|
|
4117
|
-
".cm-line": {
|
|
4118
|
-
lineHeight
|
|
4119
|
-
},
|
|
4120
|
-
// Match the standard Input block size (md density): 2.5rem, 2rem on pointer-fine devices.
|
|
4121
|
-
".cm-scroller": {
|
|
4122
|
-
alignItems: "center",
|
|
4123
|
-
minHeight: "2.5rem"
|
|
4124
|
-
},
|
|
4125
|
-
"@media (pointer: fine)": {
|
|
4126
|
-
".cm-scroller": {
|
|
4127
|
-
minHeight: "2rem"
|
|
4128
|
-
}
|
|
4129
|
-
}
|
|
4130
|
-
});
|
|
4131
|
-
|
|
4132
|
-
// src/components/RefEditor/RefEditor.tsx
|
|
4133
|
-
var RefEditor = /* @__PURE__ */ forwardRef2(({ db, type, value: value3, readonly, mode = "ref", match: match2, getLabel, getValues, icon = "ph--link--regular", placeholder: placeholderProp, activateOnTyping, numItems = 8, ...props }, forwardedRef) => {
|
|
4134
|
-
const { t } = useTranslation12(translationKey14);
|
|
4135
|
-
const { themeMode } = useThemeContext();
|
|
4136
|
-
const getObjectLabel = useCallback21((object) => getLabel?.(object) ?? Obj6.getLabel(object) ?? object.id, [
|
|
4137
|
-
getLabel
|
|
4138
|
-
]);
|
|
4139
|
-
const filter = useMemo16(() => Filter3.type(type), [
|
|
4140
|
-
type
|
|
4141
|
-
]);
|
|
4142
|
-
const objects = useQuery2(db, filter);
|
|
4143
|
-
const refs = useMemo16(() => new Map(objects.map((object) => [
|
|
4144
|
-
object.id,
|
|
4145
|
-
{
|
|
4146
|
-
label: getObjectLabel(object),
|
|
4147
|
-
hue: getHashHue2(object.id)
|
|
4148
|
-
}
|
|
4149
|
-
])), [
|
|
4150
|
-
objects,
|
|
4151
|
-
getObjectLabel
|
|
4152
|
-
]);
|
|
4153
|
-
const refsRef = useRef8(refs);
|
|
4154
|
-
refsRef.current = refs;
|
|
4155
|
-
const controllerRef = useRef8(null);
|
|
4156
|
-
const composedRef = useCallback21((controller) => {
|
|
4157
|
-
controllerRef.current = controller;
|
|
4158
|
-
if (typeof forwardedRef === "function") {
|
|
4159
|
-
forwardedRef(controller);
|
|
4160
|
-
} else if (forwardedRef) {
|
|
4161
|
-
forwardedRef.current = controller;
|
|
4162
|
-
}
|
|
4163
|
-
}, [
|
|
4164
|
-
forwardedRef
|
|
4165
|
-
]);
|
|
4166
|
-
useEffect10(() => {
|
|
4167
|
-
controllerRef.current?.view?.dispatch({
|
|
4168
|
-
effects: refEditorRedecorate.of(null)
|
|
4169
|
-
});
|
|
4170
|
-
}, [
|
|
4171
|
-
refs
|
|
4172
|
-
]);
|
|
4173
|
-
const getMenu = useCallback21(async ({ text }) => {
|
|
4174
|
-
const query = (text ?? "").replace(/^@/, "").toLowerCase();
|
|
4175
|
-
const matchesQuery = (object) => !query || getObjectLabel(object).toLowerCase().includes(query) || (getValues?.(object) ?? []).some((entry) => entry.toLowerCase().includes(query));
|
|
4176
|
-
if (mode === "email") {
|
|
4177
|
-
const mailboxes = objects.flatMap((object) => (getValues?.(object) ?? []).map((entry) => ({
|
|
4178
|
-
object,
|
|
4179
|
-
entry
|
|
4180
|
-
}))).filter(({ object, entry }) => !query || getObjectLabel(object).toLowerCase().includes(query) || entry.toLowerCase().includes(query));
|
|
4181
|
-
return [
|
|
4182
|
-
{
|
|
4183
|
-
id: "mailboxes",
|
|
4184
|
-
items: mailboxes.slice(0, numItems * 2).map(({ object, entry }) => ({
|
|
4185
|
-
id: `${object.id}-${entry}`,
|
|
4186
|
-
label: `${getObjectLabel(object)} (${entry})`,
|
|
4187
|
-
icon,
|
|
4188
|
-
onSelect: ({ view, head }) => insertMailbox(view, head, formatMailbox(getObjectLabel(object), entry))
|
|
4189
|
-
}))
|
|
4190
|
-
}
|
|
4191
|
-
];
|
|
4192
|
-
}
|
|
4193
|
-
return [
|
|
4194
|
-
{
|
|
4195
|
-
id: "refs",
|
|
4196
|
-
items: objects.filter(matchesQuery).slice(0, numItems * 2).map((object) => {
|
|
4197
|
-
const label = getObjectLabel(object);
|
|
4198
|
-
const detail = getValues?.(object)?.[0];
|
|
4199
|
-
return {
|
|
4200
|
-
id: object.id,
|
|
4201
|
-
label: detail && detail !== label ? `${label} (${detail})` : label,
|
|
4202
|
-
icon,
|
|
4203
|
-
onSelect: ({ view, head }) => insertAtCursor(view, head, `@${object.id} `)
|
|
4204
|
-
};
|
|
4205
|
-
})
|
|
4206
|
-
}
|
|
4207
|
-
];
|
|
4208
|
-
}, [
|
|
4209
|
-
objects,
|
|
4210
|
-
numItems,
|
|
4211
|
-
mode,
|
|
4212
|
-
icon,
|
|
4213
|
-
getObjectLabel,
|
|
4214
|
-
getValues
|
|
4215
|
-
]);
|
|
4216
|
-
const placeholder = useMemo16(() => ({
|
|
4217
|
-
content: placeholderProp ?? t(activateOnTyping ? "ref-editor-auto.placeholder" : "ref-editor.placeholder"),
|
|
4218
|
-
focusOnly: false
|
|
4219
|
-
}), [
|
|
4220
|
-
t,
|
|
4221
|
-
placeholderProp,
|
|
4222
|
-
activateOnTyping
|
|
4223
|
-
]);
|
|
4224
|
-
const extensions = useMemo16(() => [
|
|
4225
|
-
createBasicExtensions({
|
|
4226
|
-
readOnly: readonly,
|
|
4227
|
-
lineWrapping: false
|
|
4228
|
-
}),
|
|
4229
|
-
createThemeExtensions({
|
|
4230
|
-
themeMode,
|
|
4231
|
-
slots: {
|
|
4232
|
-
scroller: {
|
|
4233
|
-
className: "scrollbar-none"
|
|
4234
|
-
}
|
|
4235
|
-
}
|
|
4236
|
-
}),
|
|
4237
|
-
refEditor({
|
|
4238
|
-
mode,
|
|
4239
|
-
match: match2,
|
|
4240
|
-
getRef: (id) => refsRef.current.get(id)
|
|
4241
|
-
}),
|
|
4242
|
-
Prec.highest(keymap.of([
|
|
4243
|
-
{
|
|
4244
|
-
key: "Enter",
|
|
4245
|
-
// Commit the in-progress token when it matches (insert the mode's separator, the
|
|
4246
|
-
// same gesture as typing it); always consume the key (single-line input).
|
|
4247
|
-
run: (view) => {
|
|
4248
|
-
const { head } = view.state.selection.main;
|
|
4249
|
-
const line = view.state.doc.lineAt(head);
|
|
4250
|
-
const before = line.text.slice(0, head - line.from);
|
|
4251
|
-
if (mode === "email") {
|
|
4252
|
-
const segment = before.slice(before.lastIndexOf(",") + 1).trim();
|
|
4253
|
-
if (NAME_ADDR_REGEX.test(segment) || (match2 ?? EMAIL_REGEX).test(segment)) {
|
|
4254
|
-
insertAtCursor(view, head, ", ");
|
|
4255
|
-
}
|
|
4256
|
-
} else {
|
|
4257
|
-
const token = before.slice(before.search(/\S+$/));
|
|
4258
|
-
if (token && match2?.test(token)) {
|
|
4259
|
-
insertAtCursor(view, head, " ");
|
|
4260
|
-
}
|
|
4261
|
-
}
|
|
4262
|
-
return true;
|
|
4263
|
-
}
|
|
4264
|
-
}
|
|
4265
|
-
]))
|
|
4266
|
-
], [
|
|
4267
|
-
readonly,
|
|
4268
|
-
themeMode,
|
|
4269
|
-
mode,
|
|
4270
|
-
match2
|
|
4271
|
-
]);
|
|
4272
|
-
return /* @__PURE__ */ React30.createElement(Editor2.Root, {
|
|
4273
|
-
extensions,
|
|
4274
|
-
numItems,
|
|
4275
|
-
trigger: "@",
|
|
4276
|
-
activateOnTyping,
|
|
4277
|
-
placeholder,
|
|
4278
|
-
// The menu owns its own matching (labels AND values); the built-in label filter would
|
|
4279
|
-
// drop value-matched objects whose label doesn't start with the query.
|
|
4280
|
-
filter: false,
|
|
4281
|
-
getMenu,
|
|
4282
|
-
ref: composedRef
|
|
4283
|
-
}, /* @__PURE__ */ React30.createElement(Editor2.View, {
|
|
4284
|
-
// TOOD(burdon): Use same style as react-ui Input.
|
|
4285
|
-
classNames: "border border-input-separator rounded-xs px-2",
|
|
4286
|
-
...props,
|
|
4287
|
-
initialValue: value3,
|
|
4288
|
-
selectionEnd: true
|
|
4289
|
-
}));
|
|
4290
|
-
});
|
|
4291
|
-
RefEditor.displayName = "RefEditor";
|
|
4292
|
-
var insertMailbox = (view, head, mailbox) => {
|
|
4293
|
-
const line = view.state.doc.lineAt(head);
|
|
4294
|
-
const before = line.text.slice(0, head - line.from);
|
|
4295
|
-
const lastComma = before.lastIndexOf(",");
|
|
4296
|
-
const from = line.from + (lastComma === -1 ? 0 : lastComma + 1);
|
|
4297
|
-
const insert = `${lastComma === -1 ? "" : " "}${mailbox}, `;
|
|
4298
|
-
view.dispatch({
|
|
4299
|
-
changes: {
|
|
4300
|
-
from,
|
|
4301
|
-
to: head,
|
|
4302
|
-
insert
|
|
4303
|
-
},
|
|
4304
|
-
selection: {
|
|
4305
|
-
anchor: from + insert.length,
|
|
4306
|
-
head: from + insert.length
|
|
4307
|
-
}
|
|
4308
|
-
});
|
|
4309
|
-
};
|
|
4310
|
-
|
|
4311
|
-
// src/components/ViewEditor/ViewEditor.tsx
|
|
4312
|
-
import { RegistryContext } from "@effect-atom/atom-react";
|
|
4313
|
-
import * as Match2 from "effect/Match";
|
|
4314
|
-
import * as Option9 from "effect/Option";
|
|
4315
|
-
import * as Schema5 from "effect/Schema";
|
|
4316
|
-
import React31, { forwardRef as forwardRef3, useCallback as useCallback22, useContext, useImperativeHandle, useMemo as useMemo17, useState as useState11 } from "react";
|
|
4317
|
-
import { DXN as DXN4, EID as EID2, Entity as Entity2, Feed, Filter as Filter4, Format as Format7, Obj as Obj7, Query as Query2, QueryAST, Ref as Ref8, Type as Type7, View } from "@dxos/echo";
|
|
4318
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4319
|
-
import { useObject, useQuery as useQuery3 } from "@dxos/react-client/echo";
|
|
4320
|
-
import { Input as Input15, Message, ToggleIconButton as ToggleIconButton3, useTranslation as useTranslation13 } from "@dxos/react-ui";
|
|
4321
|
-
import { QueryForm } from "@dxos/react-ui-components";
|
|
4322
|
-
import { OrderedList as OrderedList3 } from "@dxos/react-ui-list";
|
|
4323
|
-
import { ParentLabelAnnotation, ProjectionModel, VIEW_FIELD_LIMIT, createEchoChangeCallback, getTypeURIFromQuery } from "@dxos/schema";
|
|
4324
|
-
import { mx as mx9 } from "@dxos/ui-theme";
|
|
4325
|
-
import { translationKey as translationKey15 } from "#translations";
|
|
4326
|
-
var __dxlog_file7 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
|
|
4327
|
-
var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, type, view, mode = "schema", registry, db, readonly, showHeading = false, types, tags, onQueryChanged, onDelete }, forwardedRef) => {
|
|
4328
|
-
const atomRegistry = useContext(RegistryContext);
|
|
4329
|
-
const schemaReadonly = type == null || Type7.getDatabase(type) == null;
|
|
4330
|
-
const { t } = useTranslation13(translationKey15);
|
|
4331
|
-
const projectionModel = useMemo17(() => {
|
|
4332
|
-
if (!type) {
|
|
4333
|
-
return null;
|
|
4334
|
-
}
|
|
4335
|
-
const jsonSchema = type.jsonSchema;
|
|
4336
|
-
const change = createEchoChangeCallback(view, Type7.getDatabase(type) != null ? type : void 0);
|
|
4337
|
-
const model = new ProjectionModel({
|
|
4338
|
-
registry: atomRegistry,
|
|
4339
|
-
view,
|
|
4340
|
-
baseSchema: jsonSchema,
|
|
4341
|
-
change
|
|
4342
|
-
});
|
|
4343
|
-
return model;
|
|
4344
|
-
}, [
|
|
4345
|
-
atomRegistry,
|
|
4346
|
-
type,
|
|
4347
|
-
view
|
|
4348
|
-
]);
|
|
4349
|
-
useImperativeHandle(forwardedRef, () => projectionModel, [
|
|
4350
|
-
projectionModel
|
|
4351
|
-
]);
|
|
4352
|
-
const queueTarget = Match2.value(view.query.ast).pipe(Match2.when({
|
|
4353
|
-
type: "from"
|
|
4354
|
-
}, ({ from }) => {
|
|
4355
|
-
if (from._tag !== "scope") {
|
|
4356
|
-
return void 0;
|
|
4357
|
-
}
|
|
4358
|
-
const feedScope = from.scopes.find((s) => s._tag === "feed");
|
|
4359
|
-
return Option9.fromNullable(feedScope).pipe(Option9.map((s) => s.feedUri), Option9.getOrUndefined);
|
|
4360
|
-
}), Match2.orElse(() => void 0));
|
|
4361
|
-
const feeds = useQuery3(db, Filter4.type(Feed.Feed));
|
|
4362
|
-
const targetRef = useMemo17(() => {
|
|
4363
|
-
if (!queueTarget) {
|
|
4364
|
-
return void 0;
|
|
4365
|
-
}
|
|
4366
|
-
const targetEid = EID2.tryParse(queueTarget);
|
|
4367
|
-
const feed = feeds.find((feed2) => {
|
|
4368
|
-
const feedEid = Feed.getQueueUri(feed2);
|
|
4369
|
-
return feedEid != null && targetEid != null && EID2.equals(feedEid, targetEid);
|
|
4370
|
-
});
|
|
4371
|
-
return feed ? Ref8.fromURI(Entity2.getURI(feed)) : void 0;
|
|
4372
|
-
}, [
|
|
4373
|
-
queueTarget,
|
|
4374
|
-
feeds
|
|
4375
|
-
]);
|
|
4376
|
-
const viewSchema = useMemo17(() => {
|
|
4377
|
-
const base = Schema5.Struct({
|
|
4378
|
-
query: mode === "schema" ? Format7.URL.annotations({
|
|
4379
|
-
title: "Record type"
|
|
4380
|
-
}) : QueryAST.Query.annotations({
|
|
4381
|
-
title: "Query"
|
|
4382
|
-
})
|
|
4383
|
-
});
|
|
4384
|
-
if (mode === "tag") {
|
|
4385
|
-
return Schema5.Struct({
|
|
4386
|
-
...base.fields,
|
|
4387
|
-
// TODO(wittjosiah): Replace Type.Feed with Dataset.Dataset when Ref.Ref supports unions.
|
|
4388
|
-
target: Ref8.Ref(Feed.Feed).pipe(Schema5.annotations({
|
|
4389
|
-
title: "Target Feed"
|
|
4390
|
-
}), ParentLabelAnnotation.set(true), Schema5.optional)
|
|
4391
|
-
}).pipe(Schema5.mutable);
|
|
4392
|
-
}
|
|
4393
|
-
return base.pipe(Schema5.mutable);
|
|
4394
|
-
}, [
|
|
4395
|
-
mode
|
|
4396
|
-
]);
|
|
4397
|
-
const viewValues = useMemo17(() => {
|
|
4398
|
-
const typeUri = getTypeURIFromQuery(view.query.ast);
|
|
4399
|
-
const typeDxn = typeUri ? DXN4.tryMake(typeUri) : void 0;
|
|
4400
|
-
return {
|
|
4401
|
-
query: mode === "schema" ? typeDxn ? DXN4.getName(typeDxn) : typeUri ?? "" : view.query.ast,
|
|
4402
|
-
target: targetRef
|
|
4403
|
-
};
|
|
4404
|
-
}, [
|
|
4405
|
-
mode,
|
|
4406
|
-
view.query.ast,
|
|
4407
|
-
targetRef
|
|
4408
|
-
]);
|
|
4409
|
-
const fieldMap = useMemo17(() => mode === "tag" ? customFields({
|
|
4410
|
-
types,
|
|
4411
|
-
tags
|
|
4412
|
-
}) : void 0, [
|
|
4413
|
-
mode,
|
|
4414
|
-
types,
|
|
4415
|
-
tags
|
|
4416
|
-
]);
|
|
4417
|
-
const handleUpdate = useCallback22((values) => {
|
|
4418
|
-
const targetValue = values.target;
|
|
4419
|
-
let queueDxn;
|
|
4420
|
-
if (Ref8.isRef(targetValue)) {
|
|
4421
|
-
const feedUri = targetValue.uri;
|
|
4422
|
-
const feed = feeds.find((feed2) => Obj7.getURI(feed2) === feedUri);
|
|
4423
|
-
if (feed) {
|
|
4424
|
-
queueDxn = Feed.getQueueUri(feed);
|
|
4425
|
-
}
|
|
4426
|
-
}
|
|
4427
|
-
const query = mode === "schema" ? Query2.select(Filter4.type(EID2.isEID(values.query) ? values.query : DXN4.make(values.query))).ast : JSON.parse(JSON.stringify(values.query));
|
|
4428
|
-
onQueryChanged?.(query, queueDxn);
|
|
4429
|
-
}, [
|
|
4430
|
-
onQueryChanged,
|
|
4431
|
-
mode,
|
|
4432
|
-
feeds
|
|
4433
|
-
]);
|
|
4434
|
-
const handleDelete = useCallback22((fieldId) => {
|
|
4435
|
-
invariant4(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 138, S: void 0, A: ["!readonly", ""] });
|
|
4436
|
-
onDelete?.(fieldId);
|
|
4437
|
-
}, [
|
|
4438
|
-
onDelete,
|
|
4439
|
-
readonly
|
|
4440
|
-
]);
|
|
4441
|
-
return /* @__PURE__ */ React31.createElement("div", {
|
|
4442
|
-
className: mx9(classNames)
|
|
4443
|
-
}, /* @__PURE__ */ React31.createElement(Form.Root, {
|
|
4444
|
-
schema: viewSchema,
|
|
4445
|
-
values: viewValues,
|
|
4446
|
-
fieldMap,
|
|
4447
|
-
db,
|
|
4448
|
-
onValuesChanged: handleUpdate
|
|
4449
|
-
}, /* @__PURE__ */ React31.createElement(Form.Viewport, null, /* @__PURE__ */ React31.createElement(Form.Content, null, schemaReadonly && !readonly && /* @__PURE__ */ React31.createElement(Message.Root, {
|
|
4450
|
-
valence: "info",
|
|
4451
|
-
classNames: "my-form-padding"
|
|
4452
|
-
}, /* @__PURE__ */ React31.createElement(Message.Title, null, t("system-schema.description"))), /* @__PURE__ */ React31.createElement(Form.FieldSet, null), type && /* @__PURE__ */ React31.createElement(FieldList, {
|
|
4453
|
-
type,
|
|
4454
|
-
view,
|
|
4455
|
-
registry,
|
|
4456
|
-
readonly,
|
|
4457
|
-
showHeading,
|
|
4458
|
-
onDelete: handleDelete
|
|
4459
|
-
})))));
|
|
4460
|
-
});
|
|
4461
|
-
var customFields = ({ types, tags }) => ({
|
|
4462
|
-
query: ({ type, readonly, label, getValue, onValueChange }) => {
|
|
4463
|
-
const handleChange = useCallback22((query) => onValueChange(type, query.ast), [
|
|
4464
|
-
onValueChange
|
|
4465
|
-
]);
|
|
4466
|
-
return /* @__PURE__ */ React31.createElement(Input15.Root, null, /* @__PURE__ */ React31.createElement(FormFieldLabel, {
|
|
4467
|
-
readonly,
|
|
4468
|
-
label
|
|
4469
|
-
}), /* @__PURE__ */ React31.createElement(QueryForm, {
|
|
4470
|
-
initialQuery: getValue(),
|
|
4471
|
-
types,
|
|
4472
|
-
tags,
|
|
4473
|
-
onChange: handleChange
|
|
4474
|
-
}));
|
|
4475
|
-
}
|
|
4476
|
-
});
|
|
4477
|
-
var FieldList = ({ type, view, registry, readonly, showHeading = false, onDelete }) => {
|
|
4478
|
-
const atomRegistry = useContext(RegistryContext);
|
|
4479
|
-
const schemaReadonly = Type7.getDatabase(type) == null;
|
|
4480
|
-
const { t } = useTranslation13(translationKey15);
|
|
4481
|
-
const [viewSnapshot] = useObject(view);
|
|
4482
|
-
const projectionModel = useMemo17(() => {
|
|
4483
|
-
const jsonSchema = type.jsonSchema;
|
|
4484
|
-
const change = createEchoChangeCallback(view, Type7.getDatabase(type) != null ? type : void 0);
|
|
4485
|
-
return new ProjectionModel({
|
|
4486
|
-
registry: atomRegistry,
|
|
4487
|
-
view,
|
|
4488
|
-
baseSchema: jsonSchema,
|
|
4489
|
-
change
|
|
4490
|
-
});
|
|
4491
|
-
}, [
|
|
4492
|
-
atomRegistry,
|
|
4493
|
-
type,
|
|
4494
|
-
view
|
|
4495
|
-
]);
|
|
4496
|
-
const [expandedField, setExpandedField] = useState11();
|
|
4497
|
-
const handleAdd = useCallback22(() => {
|
|
4498
|
-
invariant4(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 204, S: void 0, A: ["!readonly", ""] });
|
|
4499
|
-
const field = projectionModel.createFieldProjection();
|
|
4500
|
-
setExpandedField(field.id);
|
|
4501
|
-
}, [
|
|
4502
|
-
projectionModel,
|
|
4503
|
-
readonly
|
|
4504
|
-
]);
|
|
4505
|
-
const handleDelete = useCallback22((fieldId) => {
|
|
4506
|
-
invariant4(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 212, S: void 0, A: ["!readonly", ""] });
|
|
4507
|
-
if (fieldId === expandedField) {
|
|
4508
|
-
setExpandedField(void 0);
|
|
4509
|
-
}
|
|
4510
|
-
onDelete?.(fieldId);
|
|
4511
|
-
}, [
|
|
4512
|
-
expandedField,
|
|
4513
|
-
onDelete,
|
|
4514
|
-
readonly
|
|
4515
|
-
]);
|
|
4516
|
-
const handleMove = useCallback22((fromIndex, toIndex) => {
|
|
4517
|
-
invariant4(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 223, S: void 0, A: ["!readonly", ""] });
|
|
4518
|
-
Obj7.update(view, (view2) => {
|
|
4519
|
-
const fields = [
|
|
4520
|
-
...view2.projection.fields
|
|
4521
|
-
];
|
|
4522
|
-
const [moved] = fields.splice(fromIndex, 1);
|
|
4523
|
-
fields.splice(toIndex, 0, moved);
|
|
4524
|
-
view2.projection.fields = fields;
|
|
4525
|
-
});
|
|
4526
|
-
}, [
|
|
4527
|
-
view,
|
|
4528
|
-
readonly
|
|
4529
|
-
]);
|
|
4530
|
-
const handleClose = useCallback22(() => setExpandedField(void 0), []);
|
|
4531
|
-
const handleHide = useCallback22((fieldId) => {
|
|
4532
|
-
setExpandedField(void 0);
|
|
4533
|
-
projectionModel.hideFieldProjection(fieldId);
|
|
4534
|
-
}, [
|
|
4535
|
-
projectionModel
|
|
4536
|
-
]);
|
|
4537
|
-
const handleShow = useCallback22((property) => {
|
|
4538
|
-
setExpandedField(void 0);
|
|
4539
|
-
projectionModel.showFieldProjection(property);
|
|
4540
|
-
}, [
|
|
4541
|
-
projectionModel
|
|
4542
|
-
]);
|
|
4543
|
-
if (!viewSnapshot) {
|
|
4544
|
-
return null;
|
|
4545
|
-
}
|
|
4546
|
-
return /* @__PURE__ */ React31.createElement(OrderedList3.Root, {
|
|
4547
|
-
items: viewSnapshot.projection.fields,
|
|
4548
|
-
isItem: Schema5.is(View.FieldSchema),
|
|
4549
|
-
getId: (field) => field.id,
|
|
4550
|
-
onMove: readonly ? void 0 : handleMove,
|
|
4551
|
-
readonly,
|
|
4552
|
-
expandedId: expandedField,
|
|
4553
|
-
onExpandedChange: setExpandedField
|
|
4554
|
-
}, ({ items: fields }) => /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement(FormFieldHeader, {
|
|
4555
|
-
label: t("fields.label"),
|
|
4556
|
-
readonly,
|
|
4557
|
-
add: {
|
|
4558
|
-
label: t("add-property-button.label"),
|
|
4559
|
-
disabled: viewSnapshot.projection.fields.length >= VIEW_FIELD_LIMIT,
|
|
4560
|
-
onClick: handleAdd
|
|
4561
|
-
}
|
|
4562
|
-
}), showHeading && /* @__PURE__ */ React31.createElement(FormFieldLabel, {
|
|
4563
|
-
standalone: true,
|
|
4564
|
-
classNames: "py-1",
|
|
4565
|
-
label: t("field-path.label")
|
|
4566
|
-
}), /* @__PURE__ */ React31.createElement(OrderedList3.Content, null, fields.map((field) => {
|
|
4567
|
-
const hidden = field.visible === false;
|
|
4568
|
-
return /* @__PURE__ */ React31.createElement(OrderedList3.DetailItem, {
|
|
4569
|
-
key: field.id,
|
|
4570
|
-
id: field.id,
|
|
4571
|
-
item: field,
|
|
4572
|
-
canDrag: !readonly && !schemaReadonly,
|
|
4573
|
-
expandable: !readonly,
|
|
4574
|
-
title: field.path,
|
|
4575
|
-
titleClassNames: hidden ? "text-subdued" : void 0,
|
|
4576
|
-
actions: /* @__PURE__ */ React31.createElement(ToggleIconButton3, {
|
|
4577
|
-
iconOnly: true,
|
|
4578
|
-
variant: "ghost",
|
|
4579
|
-
active: hidden,
|
|
4580
|
-
icon: "ph--eye--regular",
|
|
4581
|
-
activeIcon: "ph--eye-closed--regular",
|
|
4582
|
-
label: t(hidden ? "show-field.label" : "hide-field.label"),
|
|
4583
|
-
"data-testid": hidden ? "show-field-button" : "hide-field-button",
|
|
4584
|
-
disabled: readonly || !hidden && projectionModel.getFields().length <= 1,
|
|
4585
|
-
onClick: () => hidden ? handleShow(field.path) : handleHide(field.id)
|
|
4586
|
-
}),
|
|
4587
|
-
trailing: !readonly && /* @__PURE__ */ React31.createElement(CompactIconButton, {
|
|
4588
|
-
icon: "ph--x--regular",
|
|
4589
|
-
label: t("delete-field.label"),
|
|
4590
|
-
disabled: schemaReadonly || viewSnapshot.projection.fields.length <= 1,
|
|
4591
|
-
onClick: () => handleDelete(field.id),
|
|
4592
|
-
"data-testid": "field.delete"
|
|
4593
|
-
})
|
|
4594
|
-
}, /* @__PURE__ */ React31.createElement(FieldEditor, {
|
|
4595
|
-
readonly: readonly || schemaReadonly,
|
|
4596
|
-
registry,
|
|
4597
|
-
projection: projectionModel,
|
|
4598
|
-
field,
|
|
4599
|
-
onSave: handleClose
|
|
4600
|
-
}));
|
|
4601
|
-
}))));
|
|
4602
|
-
};
|
|
4603
|
-
export {
|
|
4604
|
-
ArrayField,
|
|
4605
|
-
AsyncSelectField,
|
|
4606
|
-
AutofillAnnotation,
|
|
4607
|
-
AutofillAnnotationId,
|
|
4608
|
-
AutofillField,
|
|
4609
|
-
BooleanField,
|
|
4610
|
-
ComboboxField,
|
|
4611
|
-
CompactIconButton,
|
|
4612
|
-
DateField,
|
|
4613
|
-
EMAIL_REGEX,
|
|
4614
|
-
FieldEditor,
|
|
4615
|
-
Form,
|
|
4616
|
-
FormContextProvider,
|
|
4617
|
-
FormField,
|
|
4618
|
-
FormFieldErrorBoundary,
|
|
4619
|
-
FormFieldHeader,
|
|
4620
|
-
FormFieldLabel,
|
|
4621
|
-
FormFieldSet,
|
|
4622
|
-
FormFieldSetContainer,
|
|
4623
|
-
FormRow,
|
|
4624
|
-
GeoPointField,
|
|
4625
|
-
InlineRefField,
|
|
4626
|
-
META_TAGS_KEY,
|
|
4627
|
-
MarkdownField,
|
|
4628
|
-
NAME_ADDR_REGEX,
|
|
4629
|
-
NumberField,
|
|
4630
|
-
ObjectForm,
|
|
4631
|
-
ObjectPicker,
|
|
4632
|
-
ObjectProperties,
|
|
4633
|
-
ObjectTree,
|
|
4634
|
-
OptionsLookupAnnotation,
|
|
4635
|
-
OptionsLookupAnnotationId,
|
|
4636
|
-
PasswordField,
|
|
4637
|
-
REF_REGEX,
|
|
4638
|
-
RefEditor,
|
|
4639
|
-
RefField,
|
|
4640
|
-
SelectField,
|
|
4641
|
-
SelectOptionField,
|
|
4642
|
-
TextAreaField,
|
|
4643
|
-
TextField,
|
|
4644
|
-
TupleField,
|
|
4645
|
-
ViewEditor,
|
|
4646
|
-
autofill,
|
|
4647
|
-
cellClassesForFieldType,
|
|
4648
|
-
createSelectField,
|
|
4649
|
-
findRefOption,
|
|
4650
|
-
formatForDisplay,
|
|
4651
|
-
formatForEditing,
|
|
4652
|
-
formatMailbox,
|
|
4653
|
-
getDefaultValue,
|
|
4654
|
-
getFormProperties,
|
|
4655
|
-
getNumericConstraints,
|
|
4656
|
-
getRefProps,
|
|
4657
|
-
getRootFormProperties,
|
|
4658
|
-
omitHiddenFormFields,
|
|
4659
|
-
omitId,
|
|
4660
|
-
optionsLookup,
|
|
4661
|
-
parseValue,
|
|
4662
|
-
pathNotUniqueError,
|
|
4663
|
-
pickValues,
|
|
4664
|
-
presentationFor,
|
|
4665
|
-
refEditor,
|
|
4666
|
-
refEditorRedecorate,
|
|
4667
|
-
useAsyncFieldEffect,
|
|
4668
|
-
useFormContext,
|
|
4669
|
-
useFormFieldState,
|
|
4670
|
-
useFormHandler,
|
|
4671
|
-
useFormValues,
|
|
4672
|
-
useKeyHandler,
|
|
4673
|
-
withMetaTags
|
|
4674
|
-
};
|
|
4675
|
-
//# sourceMappingURL=index.mjs.map
|