@dxos/react-ui-form 0.8.4-main.406dc2a → 0.8.4-main.52d7546f51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +2228 -2254
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +2228 -2254
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +6 -5
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +13 -7
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form-old.stories.d.ts +131 -0
- package/dist/types/src/components/Form/Form-old.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/Form.d.ts +81 -26
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +59 -84
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField.d.ts +37 -0
- package/dist/types/src/components/Form/FormField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldComponent.d.ts +78 -0
- package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts +9 -0
- package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldSet.d.ts +19 -0
- package/dist/types/src/components/Form/FormFieldSet.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/ArrayField.d.ts +18 -0
- package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/BooleanField.d.ts +4 -0
- package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/GeoPointField.d.ts +5 -0
- package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts +4 -0
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/NumberField.d.ts +4 -0
- package/dist/types/src/components/Form/fields/NumberField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/RefField.d.ts +14 -0
- package/dist/types/src/components/Form/fields/RefField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/SelectField.d.ts +10 -0
- package/dist/types/src/components/Form/fields/SelectField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/SelectOptionField.d.ts +5 -0
- package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +1 -0
- package/dist/types/src/components/{ControlSection/ControlSection.stories.d.ts → Form/fields/SelectOptionField.stories.d.ts} +12 -14
- package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/TextAreaField.d.ts +4 -0
- package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/TextField.d.ts +4 -0
- package/dist/types/src/components/Form/fields/TextField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/TupleField.d.ts +6 -0
- package/dist/types/src/components/Form/fields/TupleField.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/index.d.ts +12 -0
- package/dist/types/src/components/Form/fields/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/index.d.ts +2 -4
- package/dist/types/src/components/Form/index.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +14 -9
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +9 -6
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -1
- package/dist/types/src/components/Settings/Settings.d.ts +56 -0
- package/dist/types/src/components/Settings/Settings.d.ts.map +1 -0
- package/dist/types/src/components/{Form/custom/SelectOptionsInput.stories.d.ts → Settings/Settings.stories.d.ts} +10 -8
- package/dist/types/src/components/Settings/Settings.stories.d.ts.map +1 -0
- package/dist/types/src/components/Settings/index.d.ts +2 -0
- package/dist/types/src/components/Settings/index.d.ts.map +1 -0
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +11 -13
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +12 -9
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +0 -2
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -3
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useFormHandler.d.ts +82 -0
- package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -0
- package/dist/types/src/hooks/useKeyHandler.d.ts +6 -0
- package/dist/types/src/hooks/useKeyHandler.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +10 -7
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/echo.d.ts +6 -0
- package/dist/types/src/util/echo.d.ts.map +1 -0
- package/dist/types/src/util/field.d.ts +3 -3
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts +2 -2
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/properties.d.ts +7 -0
- package/dist/types/src/util/properties.d.ts.map +1 -0
- package/dist/types/src/util/refs.d.ts +1 -2
- package/dist/types/src/util/refs.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +49 -43
- package/src/components/FieldEditor/FieldEditor.stories.tsx +43 -22
- package/src/components/FieldEditor/FieldEditor.tsx +73 -76
- package/src/components/Form/Form-old.stories.tsx +314 -0
- package/src/components/Form/Form.stories.tsx +151 -248
- package/src/components/Form/Form.tsx +329 -108
- package/src/components/Form/FormField.tsx +286 -0
- package/src/components/Form/FormFieldComponent.stories.tsx +65 -0
- package/src/components/Form/FormFieldComponent.tsx +174 -0
- package/src/components/Form/FormFieldSet.tsx +127 -0
- package/src/components/Form/README.md +3 -0
- package/src/components/Form/fields/ArrayField.tsx +154 -0
- package/src/components/Form/fields/BooleanField.tsx +22 -0
- package/src/components/Form/fields/GeoPointField.tsx +120 -0
- package/src/components/Form/fields/MarkdownField.tsx +78 -0
- package/src/components/Form/fields/NumberField.tsx +39 -0
- package/src/components/Form/fields/RefField.tsx +189 -0
- package/src/components/Form/fields/SelectField.tsx +65 -0
- package/src/components/Form/{custom/SelectOptionsInput.stories.tsx → fields/SelectOptionField.stories.tsx} +18 -15
- package/src/components/Form/{custom/SelectOptionsInput.tsx → fields/SelectOptionField.tsx} +21 -15
- package/src/components/Form/fields/TextAreaField.tsx +38 -0
- package/src/components/Form/fields/TextField.tsx +38 -0
- package/src/components/Form/{custom/TupleInput.tsx → fields/TupleField.tsx} +15 -8
- package/src/components/Form/fields/index.ts +15 -0
- package/src/components/Form/index.ts +3 -4
- package/src/components/ObjectPicker/ObjectPicker.stories.tsx +21 -14
- package/src/components/ObjectPicker/ObjectPicker.tsx +76 -62
- package/src/components/Settings/Settings.stories.tsx +56 -0
- package/src/components/Settings/Settings.tsx +234 -0
- package/src/components/{ControlSection → Settings}/index.ts +1 -1
- package/src/components/ViewEditor/ViewEditor.stories.tsx +43 -41
- package/src/components/ViewEditor/ViewEditor.test.tsx +5 -5
- package/src/components/ViewEditor/ViewEditor.tsx +245 -192
- package/src/components/index.ts +1 -1
- package/src/components/testing.tsx +9 -7
- package/src/hooks/index.ts +2 -3
- package/src/hooks/useFormHandler.ts +362 -0
- package/src/hooks/useKeyHandler.tsx +37 -0
- package/src/translations.ts +12 -10
- package/src/util/echo.ts +25 -0
- package/src/util/field.ts +25 -25
- package/src/util/formatting.ts +22 -22
- package/src/util/index.ts +2 -1
- package/src/util/properties.ts +18 -0
- package/src/util/refs.ts +11 -17
- package/dist/types/src/components/ControlSection/ControlSection.d.ts +0 -23
- package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +0 -1
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +0 -1
- package/dist/types/src/components/ControlSection/index.d.ts +0 -2
- package/dist/types/src/components/ControlSection/index.d.ts.map +0 -1
- package/dist/types/src/components/Form/ArrayField.d.ts +0 -16
- package/dist/types/src/components/Form/ArrayField.d.ts.map +0 -1
- package/dist/types/src/components/Form/Defaults.d.ts +0 -14
- package/dist/types/src/components/Form/Defaults.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormActions.d.ts +0 -9
- package/dist/types/src/components/Form/FormActions.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormContent.d.ts +0 -63
- package/dist/types/src/components/Form/FormContent.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormContext.d.ts +0 -23
- package/dist/types/src/components/Form/FormContext.d.ts.map +0 -1
- package/dist/types/src/components/Form/Input.d.ts +0 -29
- package/dist/types/src/components/Form/Input.d.ts.map +0 -1
- package/dist/types/src/components/Form/RefField.d.ts +0 -22
- package/dist/types/src/components/Form/RefField.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +0 -4
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +0 -4
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts +0 -6
- package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/index.d.ts +0 -4
- package/dist/types/src/components/Form/custom/index.d.ts.map +0 -1
- package/dist/types/src/components/Form/factory.d.ts +0 -8
- package/dist/types/src/components/Form/factory.d.ts.map +0 -1
- package/dist/types/src/hooks/useForm.d.ts +0 -67
- package/dist/types/src/hooks/useForm.d.ts.map +0 -1
- package/dist/types/src/hooks/useQueryRefOptions.d.ts +0 -29
- package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +0 -1
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +0 -8
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +0 -1
- package/dist/types/src/util/schema.d.ts +0 -3
- package/dist/types/src/util/schema.d.ts.map +0 -1
- package/src/components/ControlSection/ControlSection.stories.tsx +0 -38
- package/src/components/ControlSection/ControlSection.tsx +0 -153
- package/src/components/Form/ArrayField.tsx +0 -125
- package/src/components/Form/Defaults.tsx +0 -205
- package/src/components/Form/FormActions.tsx +0 -54
- package/src/components/Form/FormContent.tsx +0 -322
- package/src/components/Form/FormContext.tsx +0 -110
- package/src/components/Form/Input.tsx +0 -54
- package/src/components/Form/RefField.tsx +0 -283
- package/src/components/Form/custom/GeoPointInput.tsx +0 -80
- package/src/components/Form/custom/index.ts +0 -7
- package/src/components/Form/factory.tsx +0 -31
- package/src/hooks/useForm.ts +0 -296
- package/src/hooks/useQueryRefOptions.ts +0 -62
- package/src/hooks/useRefQueryLookupHandler.ts +0 -39
- package/src/util/schema.ts +0 -12
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
|
|
3
3
|
// src/translations.ts
|
|
4
|
-
var translationKey = "react-ui-form";
|
|
4
|
+
var translationKey = "@dxos/react-ui-form";
|
|
5
5
|
var translations = [
|
|
6
6
|
{
|
|
7
7
|
"en-US": {
|
|
@@ -10,7 +10,7 @@ var translations = [
|
|
|
10
10
|
"hidden fields label": "Hidden Fields",
|
|
11
11
|
"empty readonly ref field label": "(none)",
|
|
12
12
|
// TODO(burdon): Standardize field/property.
|
|
13
|
-
"
|
|
13
|
+
"add property button label": "Add property",
|
|
14
14
|
"field property label": "Property",
|
|
15
15
|
"field property placeholder": "Property name",
|
|
16
16
|
"field format label": "Type",
|
|
@@ -26,9 +26,11 @@ var translations = [
|
|
|
26
26
|
"ref field combobox input placeholder": "Search\u2026",
|
|
27
27
|
"ref field placeholder_one": "Select\u2026",
|
|
28
28
|
"ref field placeholder_other": "Select items\u2026",
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
29
|
+
"example placeholder": "Example",
|
|
30
|
+
"latitude placeholder": "Latitude (e.g., 40.7128)",
|
|
31
|
+
"longitude placeholder": "Longitude (e.g., -74.0060)",
|
|
32
|
+
"cancel button label": "Cancel",
|
|
33
|
+
"save button label": "Save",
|
|
32
34
|
// FormatEnum
|
|
33
35
|
"format boolean": "Boolean",
|
|
34
36
|
"format currency": "Currency",
|
|
@@ -58,722 +60,391 @@ var translations = [
|
|
|
58
60
|
"format uri": "URI",
|
|
59
61
|
"format url": "URL",
|
|
60
62
|
"format uuid": "UUID",
|
|
61
|
-
//
|
|
63
|
+
// GeoPointField.
|
|
62
64
|
"latitude label": "Latitude",
|
|
63
65
|
"longitude label": "Longitude",
|
|
64
|
-
//
|
|
66
|
+
// SelectOptionsField.
|
|
65
67
|
"select option label": "Label",
|
|
66
68
|
"select option label placeholder": "Option label",
|
|
67
69
|
"select option color": "Color",
|
|
68
70
|
"select option delete": "Delete",
|
|
69
71
|
"select option add": "Add option",
|
|
70
72
|
// System schema message.
|
|
71
|
-
"system schema title": "System
|
|
72
|
-
"system schema description": "
|
|
73
|
+
"system schema title": "System type",
|
|
74
|
+
"system schema description": "System type: cannot add or remove fields."
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
];
|
|
77
79
|
|
|
78
|
-
// src/components/
|
|
79
|
-
import {
|
|
80
|
-
import
|
|
81
|
-
import {
|
|
82
|
-
import {
|
|
83
|
-
import {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
...props
|
|
94
|
-
}, children));
|
|
95
|
-
} finally {
|
|
96
|
-
_effect.f();
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
var ControlSection = ({ title, description, children }) => {
|
|
100
|
-
var _effect = _useSignals();
|
|
101
|
-
try {
|
|
102
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ControlSectionHeading, {
|
|
103
|
-
title,
|
|
104
|
-
description
|
|
105
|
-
}), children);
|
|
106
|
-
} finally {
|
|
107
|
-
_effect.f();
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
var ControlSectionHeading = ({ title, description }) => {
|
|
111
|
-
var _effect = _useSignals();
|
|
112
|
-
try {
|
|
113
|
-
const { t } = useTranslation(translationKey);
|
|
114
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("h2", {
|
|
115
|
-
className: "pli-trimMd container-max-width text-xl mbs-trimLg mbe-trimMd"
|
|
116
|
-
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React.createElement("p", {
|
|
117
|
-
className: "pli-trimMd mlb-trimMd container-max-width text-description"
|
|
118
|
-
}, toLocalizedString(description, t)));
|
|
119
|
-
} finally {
|
|
120
|
-
_effect.f();
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
var ControlGroupButton = ({ classNames, ...props }) => {
|
|
124
|
-
var _effect = _useSignals();
|
|
125
|
-
try {
|
|
126
|
-
return /* @__PURE__ */ React.createElement(Button, {
|
|
127
|
-
...props,
|
|
128
|
-
classNames: [
|
|
129
|
-
"md:col-span-2",
|
|
130
|
-
classNames
|
|
131
|
-
]
|
|
80
|
+
// src/components/FieldEditor/FieldEditor.tsx
|
|
81
|
+
import React17, { useCallback as useCallback14, useEffect as useEffect7, useMemo as useMemo7, useState as useState5 } from "react";
|
|
82
|
+
import { Obj as Obj3 } from "@dxos/echo";
|
|
83
|
+
import { Format as Format4, FormatEnums, formatToType } from "@dxos/echo/internal";
|
|
84
|
+
import { log as log2 } from "@dxos/log";
|
|
85
|
+
import { useAsyncEffect, useTranslation as useTranslation8 } from "@dxos/react-ui";
|
|
86
|
+
import { formatToAdditionalPropertyAttributes, getFormatSchema } from "@dxos/schema";
|
|
87
|
+
|
|
88
|
+
// src/util/echo.ts
|
|
89
|
+
import { Obj } from "@dxos/echo";
|
|
90
|
+
import { setValue as setValuePlain, splitJsonPath } from "@dxos/effect";
|
|
91
|
+
var setValueEchoAware = (obj, path, value3) => {
|
|
92
|
+
if (Obj.isObject(obj)) {
|
|
93
|
+
Obj.change(obj, (mutableObj) => {
|
|
94
|
+
Obj.setValue(mutableObj, splitJsonPath(path), value3);
|
|
132
95
|
});
|
|
133
|
-
|
|
134
|
-
_effect.f();
|
|
96
|
+
return obj;
|
|
135
97
|
}
|
|
98
|
+
return setValuePlain(obj, path, value3);
|
|
136
99
|
};
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}, children);
|
|
144
|
-
} finally {
|
|
145
|
-
_effect.f();
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
var ControlFrame = ({ children }) => {
|
|
149
|
-
var _effect = _useSignals();
|
|
150
|
-
try {
|
|
151
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
152
|
-
role: "none",
|
|
153
|
-
className: mx("container-max-width grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-trimSm md:gap-trimMd p-trimMd", "border border-separator rounded-md")
|
|
154
|
-
}, children);
|
|
155
|
-
} finally {
|
|
156
|
-
_effect.f();
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
var controlItemClasses = mx([
|
|
160
|
-
"container-max-width grid md:col-span-2 grid-cols-subgrid gap-trimSm items-center",
|
|
161
|
-
// TODO(burdon): Use grid gap consistently or apply margins consistently?
|
|
162
|
-
"mlb-[--control-spacing] *:first:!mbs-0 *:last:!mbe-0 pli-trimMd plb-trimMd",
|
|
163
|
-
"border border-separator rounded-md"
|
|
164
|
-
]);
|
|
165
|
-
var controlItemTitleClasses = "mbe-0 text-lg text-baseText font-normal";
|
|
166
|
-
var controlItemDescriptionClasses = "mlb-trimSm md:mbe-0 text-base text-description";
|
|
167
|
-
var ControlItem = ({ title, description, children }) => {
|
|
168
|
-
var _effect = _useSignals();
|
|
169
|
-
try {
|
|
170
|
-
const { t } = useTranslation(translationKey);
|
|
171
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
172
|
-
className: controlItemClasses
|
|
173
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
174
|
-
role: "none"
|
|
175
|
-
}, /* @__PURE__ */ React.createElement("h3", {
|
|
176
|
-
className: controlItemTitleClasses
|
|
177
|
-
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React.createElement("p", {
|
|
178
|
-
className: controlItemDescriptionClasses
|
|
179
|
-
}, toLocalizedString(description, t))), children);
|
|
180
|
-
} finally {
|
|
181
|
-
_effect.f();
|
|
100
|
+
|
|
101
|
+
// src/util/field.ts
|
|
102
|
+
import { Format, GeoLocation, TypeEnum } from "@dxos/echo/internal";
|
|
103
|
+
var parseValue = ({ type, format, value: value3 }) => {
|
|
104
|
+
if (value3 === void 0 || value3 === null || value3 === "") {
|
|
105
|
+
return void 0;
|
|
182
106
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
107
|
+
const parseScalar = (type2) => {
|
|
108
|
+
switch (type2) {
|
|
109
|
+
case TypeEnum.Boolean: {
|
|
110
|
+
if (typeof value3 === "string") {
|
|
111
|
+
const lowercaseValue = value3.toLowerCase();
|
|
112
|
+
if (lowercaseValue === "0" || lowercaseValue === "false") {
|
|
113
|
+
return false;
|
|
114
|
+
} else if (lowercaseValue === "1" || lowercaseValue === "true") {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return Boolean(value3);
|
|
119
|
+
}
|
|
120
|
+
case TypeEnum.Number: {
|
|
121
|
+
const cleaned = typeof value3 === "string" ? value3.replace(/[^0-9.-]+/g, "") : value3;
|
|
122
|
+
const num = Number(cleaned);
|
|
123
|
+
return Number.isNaN(num) ? null : num;
|
|
124
|
+
}
|
|
125
|
+
case TypeEnum.String:
|
|
126
|
+
case TypeEnum.Ref:
|
|
127
|
+
return String(value3);
|
|
128
|
+
default: {
|
|
129
|
+
return value3;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
if (!format) {
|
|
134
|
+
return parseScalar(type);
|
|
199
135
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
136
|
+
switch (format) {
|
|
137
|
+
case Format.TypeFormat.Boolean:
|
|
138
|
+
return parseScalar(TypeEnum.Boolean);
|
|
139
|
+
case Format.TypeFormat.Number:
|
|
140
|
+
case Format.TypeFormat.Percent:
|
|
141
|
+
case Format.TypeFormat.Currency:
|
|
142
|
+
return parseScalar(TypeEnum.Number);
|
|
143
|
+
case Format.TypeFormat.String:
|
|
144
|
+
case Format.TypeFormat.Markdown: {
|
|
145
|
+
return parseScalar(TypeEnum.String);
|
|
146
|
+
}
|
|
147
|
+
case Format.TypeFormat.Ref:
|
|
148
|
+
throw new Error(`unexpected format: ${Format.TypeFormat.Ref}`);
|
|
149
|
+
case Format.TypeFormat.DateTime:
|
|
150
|
+
case Format.TypeFormat.Date:
|
|
151
|
+
case Format.TypeFormat.Time:
|
|
152
|
+
case Format.TypeFormat.Timestamp: {
|
|
153
|
+
const date = new Date(value3);
|
|
154
|
+
return isNaN(date.getTime()) ? null : date;
|
|
155
|
+
}
|
|
156
|
+
case Format.TypeFormat.GeoPoint: {
|
|
157
|
+
if (typeof value3 === "string") {
|
|
158
|
+
const cleaned = value3.replace(/[^0-9.,-]+/g, "");
|
|
159
|
+
const parts = cleaned.split(",");
|
|
160
|
+
if (parts.length === 2) {
|
|
161
|
+
const lat = parseFloat(parts[0]);
|
|
162
|
+
const long = parseFloat(parts[1]);
|
|
163
|
+
if (!isNaN(lat) && !isNaN(long)) {
|
|
164
|
+
return GeoLocation.toGeoPoint({
|
|
165
|
+
latitude: lat,
|
|
166
|
+
longitude: long
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return [
|
|
172
|
+
0,
|
|
173
|
+
0
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
default: {
|
|
177
|
+
return value3;
|
|
178
|
+
}
|
|
215
179
|
}
|
|
216
180
|
};
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
content: error,
|
|
252
|
-
side: "bottom"
|
|
253
|
-
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
254
|
-
icon: "ph--warning--regular",
|
|
255
|
-
size: 4,
|
|
256
|
-
classNames: errorText
|
|
257
|
-
})));
|
|
258
|
-
} finally {
|
|
259
|
-
_effect.f();
|
|
181
|
+
var cellClassesForFieldType = ({ type, format }) => {
|
|
182
|
+
switch (format || type) {
|
|
183
|
+
case Format.TypeFormat.Markdown:
|
|
184
|
+
return void 0;
|
|
185
|
+
case Format.TypeFormat.Time:
|
|
186
|
+
case Format.TypeFormat.Timestamp:
|
|
187
|
+
case Format.TypeFormat.DateTime:
|
|
188
|
+
case Format.TypeFormat.Date:
|
|
189
|
+
case Format.TypeFormat.Duration:
|
|
190
|
+
return [
|
|
191
|
+
"font-mono",
|
|
192
|
+
"text-right"
|
|
193
|
+
];
|
|
194
|
+
case Format.TypeFormat.Currency:
|
|
195
|
+
return [
|
|
196
|
+
"text-right"
|
|
197
|
+
];
|
|
198
|
+
case Format.TypeFormat.JSON:
|
|
199
|
+
case Format.TypeFormat.DID:
|
|
200
|
+
return [
|
|
201
|
+
"font-mono"
|
|
202
|
+
];
|
|
203
|
+
case TypeEnum.Number:
|
|
204
|
+
case TypeEnum.Boolean:
|
|
205
|
+
return [
|
|
206
|
+
"text-right",
|
|
207
|
+
"font-mono"
|
|
208
|
+
];
|
|
209
|
+
case TypeEnum.String:
|
|
210
|
+
return void 0;
|
|
211
|
+
case TypeEnum.Ref:
|
|
212
|
+
return void 0;
|
|
213
|
+
default:
|
|
214
|
+
return void 0;
|
|
260
215
|
}
|
|
261
216
|
};
|
|
217
|
+
var pathNotUniqueError = (path) => ({
|
|
218
|
+
path: "path",
|
|
219
|
+
message: `'${path}' is already present`
|
|
220
|
+
});
|
|
262
221
|
|
|
263
|
-
// src/
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
const [longitudeText, setLongitudeText] = useState(geoLocation.longitude?.toString());
|
|
279
|
-
const [latitudeText, setLatitudeText] = useState(geoLocation.latitude?.toString());
|
|
280
|
-
useEffect(() => {
|
|
281
|
-
const location = GeoLocation.fromGeoPoint(geoPoint);
|
|
282
|
-
setLongitudeText(location.longitude.toString());
|
|
283
|
-
setLatitudeText(location.latitude.toString());
|
|
284
|
-
}, [
|
|
285
|
-
geoPoint
|
|
286
|
-
]);
|
|
287
|
-
const handleCoordinateChange = useCallback((coordinateType, setText) => (event) => {
|
|
288
|
-
const inputText = event.target.value;
|
|
289
|
-
setText(inputText);
|
|
290
|
-
if (inputText !== "" && inputText !== "-") {
|
|
291
|
-
const coord = safeParseFloat(inputText);
|
|
292
|
-
if (coord !== void 0 && !isNaN(coord)) {
|
|
293
|
-
const currentLocation = GeoLocation.fromGeoPoint(getValue3() ?? [
|
|
294
|
-
0,
|
|
295
|
-
0
|
|
296
|
-
]);
|
|
297
|
-
const newLocation = {
|
|
298
|
-
...currentLocation,
|
|
299
|
-
[coordinateType]: coord
|
|
300
|
-
};
|
|
301
|
-
const newValue = GeoLocation.toGeoPoint(newLocation);
|
|
302
|
-
onValueChange(type, newValue);
|
|
303
|
-
}
|
|
222
|
+
// src/util/formatting.ts
|
|
223
|
+
import { format as formatDate } from "date-fns/format";
|
|
224
|
+
import { Format as Format2, GeoLocation as GeoLocation2, TypeEnum as TypeEnum2 } from "@dxos/echo/internal";
|
|
225
|
+
var formatForDisplay = ({ type, format, value: value3, locale = void 0 }) => {
|
|
226
|
+
const formatScalar = (type2) => {
|
|
227
|
+
switch (type2) {
|
|
228
|
+
case TypeEnum2.Boolean:
|
|
229
|
+
return value3.toLocaleString().toUpperCase();
|
|
230
|
+
case TypeEnum2.Number:
|
|
231
|
+
return value3.toLocaleString(locale);
|
|
232
|
+
case TypeEnum2.String:
|
|
233
|
+
case TypeEnum2.Ref:
|
|
234
|
+
return String(value3);
|
|
235
|
+
default: {
|
|
236
|
+
return String(value3);
|
|
304
237
|
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
]);
|
|
310
|
-
return /* @__PURE__ */ React3.createElement(Input3.Root, {
|
|
311
|
-
validationValence: status
|
|
312
|
-
}, /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
313
|
-
error,
|
|
314
|
-
label
|
|
315
|
-
}), /* @__PURE__ */ React3.createElement("div", {
|
|
316
|
-
role: "none",
|
|
317
|
-
className: "grid grid-cols-2 gap-2"
|
|
318
|
-
}, /* @__PURE__ */ React3.createElement("div", {
|
|
319
|
-
role: "none"
|
|
320
|
-
}, /* @__PURE__ */ React3.createElement(Input3.Label, null, t("latitude label")), /* @__PURE__ */ React3.createElement(Input3.TextInput, {
|
|
321
|
-
type: "number",
|
|
322
|
-
step: "0.00001",
|
|
323
|
-
min: "-90",
|
|
324
|
-
max: "90",
|
|
325
|
-
disabled: !!readonly,
|
|
326
|
-
value: latitudeText,
|
|
327
|
-
onChange: handleCoordinateChange("latitude", setLatitudeText),
|
|
328
|
-
onBlur
|
|
329
|
-
})), /* @__PURE__ */ React3.createElement("div", {
|
|
330
|
-
role: "none"
|
|
331
|
-
}, /* @__PURE__ */ React3.createElement(Input3.Label, null, t("longitude label")), /* @__PURE__ */ React3.createElement(Input3.TextInput, {
|
|
332
|
-
type: "number",
|
|
333
|
-
step: "0.00001",
|
|
334
|
-
min: "-180",
|
|
335
|
-
max: "180",
|
|
336
|
-
disabled: !!readonly,
|
|
337
|
-
value: longitudeText,
|
|
338
|
-
onChange: handleCoordinateChange("longitude", setLongitudeText),
|
|
339
|
-
onBlur
|
|
340
|
-
}))));
|
|
341
|
-
} finally {
|
|
342
|
-
_effect.f();
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
if (!format) {
|
|
241
|
+
return formatScalar(type);
|
|
343
242
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
243
|
+
switch (format) {
|
|
244
|
+
case Format2.TypeFormat.Boolean: {
|
|
245
|
+
return formatScalar(TypeEnum2.Boolean);
|
|
246
|
+
}
|
|
247
|
+
case Format2.TypeFormat.Number: {
|
|
248
|
+
return formatScalar(TypeEnum2.Number);
|
|
249
|
+
}
|
|
250
|
+
case Format2.TypeFormat.String:
|
|
251
|
+
case Format2.TypeFormat.Ref: {
|
|
252
|
+
return formatScalar(TypeEnum2.String);
|
|
253
|
+
}
|
|
254
|
+
case Format2.TypeFormat.Percent: {
|
|
255
|
+
return `${value3 * 100}%`;
|
|
256
|
+
}
|
|
257
|
+
case Format2.TypeFormat.Currency: {
|
|
258
|
+
return value3.toLocaleString(locale, {
|
|
259
|
+
style: "currency",
|
|
260
|
+
currency: "USD",
|
|
261
|
+
minimumFractionDigits: 2,
|
|
262
|
+
maximumFractionDigits: 2
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
case Format2.TypeFormat.Date: {
|
|
266
|
+
try {
|
|
267
|
+
return formatDate(new Date(value3), "yyyy-MM-dd");
|
|
268
|
+
} catch (error) {
|
|
269
|
+
return "Invalid Date";
|
|
366
270
|
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
const usedHues = new Set(options?.map((option) => option.color) ?? []);
|
|
374
|
-
const unusedHues = hues.filter((hue) => !usedHues.has(hue));
|
|
375
|
-
if (unusedHues.length > 0) {
|
|
376
|
-
return unusedHues[Math.floor(Math.random() * unusedHues.length)];
|
|
271
|
+
}
|
|
272
|
+
case Format2.TypeFormat.Time: {
|
|
273
|
+
try {
|
|
274
|
+
return formatDate(new Date(value3), "HH:mm:ss");
|
|
275
|
+
} catch (error) {
|
|
276
|
+
return "Invalid Time";
|
|
377
277
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
const newOption = {
|
|
385
|
-
id: newId,
|
|
386
|
-
title: "",
|
|
387
|
-
color: randomHue()
|
|
388
|
-
};
|
|
389
|
-
onValueChange(type, [
|
|
390
|
-
...options ?? [],
|
|
391
|
-
newOption
|
|
392
|
-
]);
|
|
393
|
-
setSelectedId(newId);
|
|
394
|
-
setIsNewOption(true);
|
|
395
|
-
}, [
|
|
396
|
-
options,
|
|
397
|
-
type,
|
|
398
|
-
onValueChange
|
|
399
|
-
]);
|
|
400
|
-
const handleDelete = useCallback2((id) => {
|
|
401
|
-
const newOptions = options?.filter((option) => option.id !== id) ?? [];
|
|
402
|
-
onValueChange(type, newOptions);
|
|
403
|
-
setSelectedId(null);
|
|
404
|
-
}, [
|
|
405
|
-
options,
|
|
406
|
-
type,
|
|
407
|
-
onValueChange
|
|
408
|
-
]);
|
|
409
|
-
const handleMove = useCallback2((from, to) => {
|
|
410
|
-
if (!options) {
|
|
411
|
-
return;
|
|
278
|
+
}
|
|
279
|
+
case Format2.TypeFormat.DateTime: {
|
|
280
|
+
try {
|
|
281
|
+
return formatDate(new Date(value3), "yyyy-MM-dd HH:mm:ss");
|
|
282
|
+
} catch (error) {
|
|
283
|
+
return "Invalid DateTime";
|
|
412
284
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
newOptions.splice(to, 0, removed);
|
|
418
|
-
onValueChange(type, newOptions);
|
|
419
|
-
}, [
|
|
420
|
-
options,
|
|
421
|
-
type,
|
|
422
|
-
onValueChange
|
|
423
|
-
]);
|
|
424
|
-
const handleClick = useCallback2((id) => {
|
|
425
|
-
setSelectedId((current) => current === id ? null : id);
|
|
426
|
-
}, []);
|
|
427
|
-
const handleTitleChange = useCallback2((id) => (e) => {
|
|
428
|
-
const newOptions = options?.map((o) => o.id === id ? {
|
|
429
|
-
...o,
|
|
430
|
-
title: e.target.value
|
|
431
|
-
} : o);
|
|
432
|
-
onValueChange(type, newOptions ?? []);
|
|
433
|
-
}, [
|
|
434
|
-
options,
|
|
435
|
-
type,
|
|
436
|
-
onValueChange
|
|
437
|
-
]);
|
|
438
|
-
const handleKeyDown = useCallback2((e) => {
|
|
439
|
-
if (e.key === "Enter") {
|
|
440
|
-
setSelectedId(null);
|
|
285
|
+
}
|
|
286
|
+
case Format2.TypeFormat.GeoPoint: {
|
|
287
|
+
if (value3 === null || value3 === void 0) {
|
|
288
|
+
return "";
|
|
441
289
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
...o,
|
|
446
|
-
color: hue
|
|
447
|
-
} : o);
|
|
448
|
-
onValueChange(type, newOptions ?? []);
|
|
449
|
-
}, [
|
|
450
|
-
options,
|
|
451
|
-
type,
|
|
452
|
-
onValueChange
|
|
453
|
-
]);
|
|
454
|
-
useEffect2(() => {
|
|
455
|
-
if (selected && isNewOption && inputRef.current) {
|
|
456
|
-
inputRef.current.focus();
|
|
457
|
-
setIsNewOption(false);
|
|
290
|
+
if (Array.isArray(value3) && value3.length >= 2 && value3.every(Number.isFinite)) {
|
|
291
|
+
const { latitude, longitude } = GeoLocation2.fromGeoPoint(value3);
|
|
292
|
+
return `${latitude},${longitude}`;
|
|
458
293
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
label
|
|
468
|
-
}), /* @__PURE__ */ React4.createElement("div", {
|
|
469
|
-
role: "none"
|
|
470
|
-
}, options && /* @__PURE__ */ React4.createElement(List.Root, {
|
|
471
|
-
items: options,
|
|
472
|
-
isItem: (item) => true,
|
|
473
|
-
onMove: readonly ? void 0 : handleMove,
|
|
474
|
-
readonly: !!readonly
|
|
475
|
-
}, ({ items }) => /* @__PURE__ */ React4.createElement("div", {
|
|
476
|
-
role: "list",
|
|
477
|
-
className: "w-full overflow-auto"
|
|
478
|
-
}, items?.map((item) => /* @__PURE__ */ React4.createElement("div", {
|
|
479
|
-
key: item.id
|
|
480
|
-
}, /* @__PURE__ */ React4.createElement(List.Item, {
|
|
481
|
-
role: "button",
|
|
482
|
-
item,
|
|
483
|
-
classNames: [
|
|
484
|
-
subtleHover,
|
|
485
|
-
"flex flex-col cursor-pointer rounded-sm"
|
|
486
|
-
],
|
|
487
|
-
"aria-expanded": selected === item.id
|
|
488
|
-
}, /* @__PURE__ */ React4.createElement("div", {
|
|
489
|
-
className: "flex items-center"
|
|
490
|
-
}, /* @__PURE__ */ React4.createElement(List.ItemDragHandle, {
|
|
491
|
-
disabled: !!readonly
|
|
492
|
-
}), /* @__PURE__ */ React4.createElement(List.ItemTitle, {
|
|
493
|
-
onClick: () => handleClick(item.id),
|
|
494
|
-
classNames: "flex-1"
|
|
495
|
-
}, /* @__PURE__ */ React4.createElement(Tag, {
|
|
496
|
-
palette: item.color
|
|
497
|
-
}, item.title || "\u200B")), /* @__PURE__ */ React4.createElement(IconButton, {
|
|
498
|
-
iconOnly: true,
|
|
499
|
-
variant: "ghost",
|
|
500
|
-
label: t(selected === item.id ? "collapse label" : "expand label", {
|
|
501
|
-
ns: "os"
|
|
502
|
-
}),
|
|
503
|
-
icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
504
|
-
onClick: () => handleClick(item.id)
|
|
505
|
-
})), selected === item.id && /* @__PURE__ */ React4.createElement("div", {
|
|
506
|
-
className: "pli-cardSpacingInline plb-cardSpacingBlock flex flex-col gap-1 density-fine"
|
|
507
|
-
}, /* @__PURE__ */ React4.createElement(Input4.Label, {
|
|
508
|
-
classNames: "text-xs"
|
|
509
|
-
}, t("select option label")), /* @__PURE__ */ React4.createElement("div", {
|
|
510
|
-
className: "grid grid-cols-[1fr_min-content_min-content] gap-1"
|
|
511
|
-
}, /* @__PURE__ */ React4.createElement(Input4.TextInput, {
|
|
512
|
-
disabled: !!readonly,
|
|
513
|
-
placeholder: t("select option label placeholder"),
|
|
514
|
-
ref: selected === item.id ? inputRef : void 0,
|
|
515
|
-
value: item.title,
|
|
516
|
-
onChange: handleTitleChange(item.id),
|
|
517
|
-
onKeyDown: handleKeyDown,
|
|
518
|
-
classNames: "flex-1",
|
|
519
|
-
"data-no-submit": true
|
|
520
|
-
}), /* @__PURE__ */ React4.createElement(HuePicker, {
|
|
521
|
-
disabled: !!readonly,
|
|
522
|
-
value: item.color,
|
|
523
|
-
onChange: handleColorChange(item.id)
|
|
524
|
-
}), /* @__PURE__ */ React4.createElement(IconButton, {
|
|
525
|
-
disabled: !!readonly,
|
|
526
|
-
icon: "ph--trash--fill",
|
|
527
|
-
iconOnly: true,
|
|
528
|
-
label: t("select option delete"),
|
|
529
|
-
onClick: () => handleDelete(item.id)
|
|
530
|
-
})))))), /* @__PURE__ */ React4.createElement(IconButton, {
|
|
531
|
-
variant: "ghost",
|
|
532
|
-
icon: "ph--plus--regular",
|
|
533
|
-
label: t("select option add"),
|
|
534
|
-
onClick: handleAdd,
|
|
535
|
-
disabled: !!readonly,
|
|
536
|
-
classNames: "is-full"
|
|
537
|
-
})))));
|
|
538
|
-
} finally {
|
|
539
|
-
_effect.f();
|
|
540
|
-
}
|
|
541
|
-
};
|
|
542
|
-
|
|
543
|
-
// src/components/Form/custom/TupleInput.tsx
|
|
544
|
-
import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
|
|
545
|
-
import React5 from "react";
|
|
546
|
-
import { Input as Input5 } from "@dxos/react-ui";
|
|
547
|
-
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
548
|
-
import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
|
|
549
|
-
var gridCols = [
|
|
550
|
-
"grid-cols-1",
|
|
551
|
-
"grid-cols-2",
|
|
552
|
-
"grid-cols-3",
|
|
553
|
-
"grid-cols-4"
|
|
554
|
-
];
|
|
555
|
-
var TupleInput = ({ binding, type, label, readonly, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
556
|
-
var _effect = _useSignals5();
|
|
557
|
-
try {
|
|
558
|
-
const { status, error } = getStatus();
|
|
559
|
-
const values = getValue3() ?? {};
|
|
560
|
-
return /* @__PURE__ */ React5.createElement(Input5.Root, {
|
|
561
|
-
validationValence: status
|
|
562
|
-
}, /* @__PURE__ */ React5.createElement(InputHeader, {
|
|
563
|
-
error,
|
|
564
|
-
label
|
|
565
|
-
}), /* @__PURE__ */ React5.createElement("div", {
|
|
566
|
-
className: mx3("grid gap-2", gridCols[binding.length - 1])
|
|
567
|
-
}, binding.map((prop) => /* @__PURE__ */ React5.createElement(Input5.TextInput, {
|
|
568
|
-
key: prop,
|
|
569
|
-
type: "number",
|
|
570
|
-
disabled: !!readonly,
|
|
571
|
-
value: values[prop],
|
|
572
|
-
onChange: (event) => onValueChange(type, {
|
|
573
|
-
...values,
|
|
574
|
-
[prop]: safeParseFloat2(event.target.value, 0)
|
|
575
|
-
}),
|
|
576
|
-
onBlur
|
|
577
|
-
}))));
|
|
578
|
-
} finally {
|
|
579
|
-
_effect.f();
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
// src/components/Form/Defaults.tsx
|
|
584
|
-
import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
|
|
585
|
-
import React6, { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
586
|
-
import { Input as Input6, Select, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
587
|
-
var TextInput = ({ type, label, inputOnly, readonly, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
588
|
-
var _effect = _useSignals6();
|
|
589
|
-
try {
|
|
590
|
-
const { status, error } = getStatus();
|
|
591
|
-
return readonly && !getValue3() ? null : readonly === "static" && inputOnly ? /* @__PURE__ */ React6.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React6.createElement(Input6.Root, {
|
|
592
|
-
validationValence: status
|
|
593
|
-
}, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
594
|
-
error,
|
|
595
|
-
label
|
|
596
|
-
}), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React6.createElement(Input6.TextInput, {
|
|
597
|
-
disabled: !!readonly,
|
|
598
|
-
placeholder,
|
|
599
|
-
value: getValue3() ?? "",
|
|
600
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
601
|
-
onBlur
|
|
602
|
-
}), inputOnly && /* @__PURE__ */ React6.createElement(Input6.Validation, null, error));
|
|
603
|
-
} finally {
|
|
604
|
-
_effect.f();
|
|
294
|
+
return String(value3);
|
|
295
|
+
}
|
|
296
|
+
default: {
|
|
297
|
+
if (value3 === null || value3 === "undefined") {
|
|
298
|
+
return "";
|
|
299
|
+
}
|
|
300
|
+
return String(value3);
|
|
301
|
+
}
|
|
605
302
|
}
|
|
606
303
|
};
|
|
607
|
-
var
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
622
|
-
onBlur
|
|
623
|
-
}), inputOnly && /* @__PURE__ */ React6.createElement(Input6.DescriptionAndValidation, null, error));
|
|
624
|
-
} finally {
|
|
625
|
-
_effect.f();
|
|
304
|
+
var formatForEditing = ({ type, format, value: value3, locale = void 0 }) => {
|
|
305
|
+
const formatScalar = (type2) => {
|
|
306
|
+
switch (type2) {
|
|
307
|
+
case TypeEnum2.Boolean:
|
|
308
|
+
case TypeEnum2.Number:
|
|
309
|
+
case TypeEnum2.String:
|
|
310
|
+
case TypeEnum2.Ref:
|
|
311
|
+
return String(value3);
|
|
312
|
+
default:
|
|
313
|
+
return String(value3);
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
if (!format) {
|
|
317
|
+
return formatScalar(type);
|
|
626
318
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
|
|
319
|
+
switch (format) {
|
|
320
|
+
case Format2.TypeFormat.Boolean:
|
|
321
|
+
case Format2.TypeFormat.Number:
|
|
322
|
+
case Format2.TypeFormat.String:
|
|
323
|
+
case Format2.TypeFormat.Ref: {
|
|
324
|
+
return formatScalar(type);
|
|
325
|
+
}
|
|
326
|
+
case Format2.TypeFormat.Percent: {
|
|
327
|
+
return String(value3 * 100);
|
|
328
|
+
}
|
|
329
|
+
case Format2.TypeFormat.Currency: {
|
|
330
|
+
return String(value3);
|
|
331
|
+
}
|
|
332
|
+
case Format2.TypeFormat.DateTime: {
|
|
333
|
+
const date = new Date(value3);
|
|
334
|
+
return date.toISOString();
|
|
335
|
+
}
|
|
336
|
+
case Format2.TypeFormat.Date: {
|
|
337
|
+
const date = new Date(value3);
|
|
338
|
+
return date.toISOString().split("T")[0];
|
|
339
|
+
}
|
|
340
|
+
case Format2.TypeFormat.Time: {
|
|
341
|
+
const date = new Date(value3);
|
|
342
|
+
return date.toISOString().split("T")[1].split(".")[0];
|
|
343
|
+
}
|
|
344
|
+
case Format2.TypeFormat.GeoPoint: {
|
|
345
|
+
if (value3 === null || value3 === void 0) {
|
|
346
|
+
return "";
|
|
347
|
+
}
|
|
348
|
+
if (Array.isArray(value3) && value3.length >= 2 && value3.every(Number.isFinite)) {
|
|
349
|
+
const { latitude, longitude } = GeoLocation2.fromGeoPoint(value3);
|
|
350
|
+
return `${latitude},${longitude}`;
|
|
351
|
+
}
|
|
352
|
+
return String(value3);
|
|
353
|
+
}
|
|
354
|
+
default: {
|
|
355
|
+
return String(value3);
|
|
356
|
+
}
|
|
646
357
|
}
|
|
647
358
|
};
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
onValueChange
|
|
656
|
-
]);
|
|
657
|
-
return readonly && !value2 ? null : /* @__PURE__ */ React6.createElement(Input6.Root, {
|
|
658
|
-
validationValence: status
|
|
659
|
-
}, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
660
|
-
error,
|
|
661
|
-
label
|
|
662
|
-
}), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value2)?.label ?? String(value2)) : /* @__PURE__ */ React6.createElement(Select.Root, {
|
|
663
|
-
value: value2,
|
|
664
|
-
onValueChange: handleValueChange
|
|
665
|
-
}, /* @__PURE__ */ React6.createElement(Select.TriggerButton, {
|
|
666
|
-
classNames: "is-full",
|
|
667
|
-
disabled: !!readonly,
|
|
668
|
-
placeholder
|
|
669
|
-
}), /* @__PURE__ */ React6.createElement(Select.Portal, null, /* @__PURE__ */ React6.createElement(Select.Content, null, /* @__PURE__ */ React6.createElement(Select.Viewport, null, options?.map(({ value: value3, label: label2 }) => (
|
|
670
|
-
// NOTE: Numeric values are converted to and from strings.
|
|
671
|
-
/* @__PURE__ */ React6.createElement(Select.Option, {
|
|
672
|
-
key: String(value3),
|
|
673
|
-
value: String(value3)
|
|
674
|
-
}, label2 ?? String(value3))
|
|
675
|
-
))), /* @__PURE__ */ React6.createElement(Select.Arrow, null)))), inputOnly && /* @__PURE__ */ React6.createElement(Input6.DescriptionAndValidation, null, error));
|
|
676
|
-
} finally {
|
|
677
|
-
_effect.f();
|
|
678
|
-
}
|
|
359
|
+
|
|
360
|
+
// src/util/properties.ts
|
|
361
|
+
import * as Option from "effect/Option";
|
|
362
|
+
import { Annotation } from "@dxos/echo";
|
|
363
|
+
import { getProperties } from "@dxos/effect";
|
|
364
|
+
var getFormProperties = (ast) => {
|
|
365
|
+
return getProperties(ast).filter((prop) => Annotation.FormInputAnnotation.getFromAst(prop.type).pipe(Option.getOrElse(() => true)));
|
|
679
366
|
};
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
367
|
+
|
|
368
|
+
// src/util/refs.ts
|
|
369
|
+
import { Ref } from "@dxos/echo";
|
|
370
|
+
import { getArrayElementType, isArrayType } from "@dxos/effect";
|
|
371
|
+
var getRefProps = (ast) => {
|
|
372
|
+
if (isArrayType(ast)) {
|
|
373
|
+
const elementType = getArrayElementType(ast);
|
|
374
|
+
if (elementType) {
|
|
375
|
+
if (Ref.isRefType(elementType)) {
|
|
376
|
+
return {
|
|
377
|
+
ast: elementType,
|
|
378
|
+
isArray: true
|
|
379
|
+
};
|
|
690
380
|
}
|
|
691
|
-
}
|
|
692
|
-
useEffect3(() => {
|
|
693
|
-
adjustHeight();
|
|
694
|
-
}, [
|
|
695
|
-
adjustHeight
|
|
696
|
-
]);
|
|
697
|
-
useEffect3(() => {
|
|
698
|
-
adjustHeight();
|
|
699
|
-
}, [
|
|
700
|
-
getValue3(),
|
|
701
|
-
adjustHeight
|
|
702
|
-
]);
|
|
703
|
-
return /* @__PURE__ */ React6.createElement(Input6.Root, {
|
|
704
|
-
validationValence: status
|
|
705
|
-
}, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
706
|
-
error,
|
|
707
|
-
label
|
|
708
|
-
}), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React6.createElement(Input6.TextArea, {
|
|
709
|
-
ref: textareaRef,
|
|
710
|
-
disabled: !!readonly,
|
|
711
|
-
placeholder,
|
|
712
|
-
value: getValue3() ?? "",
|
|
713
|
-
classNames: "min-bs-auto max-h-40 overflow-auto",
|
|
714
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
715
|
-
onBlur,
|
|
716
|
-
style: {
|
|
717
|
-
resize: "none"
|
|
718
|
-
},
|
|
719
|
-
spellCheck: false
|
|
720
|
-
}), inputOnly && /* @__PURE__ */ React6.createElement(Input6.Validation, null, error));
|
|
721
|
-
} finally {
|
|
722
|
-
_effect.f();
|
|
381
|
+
}
|
|
723
382
|
}
|
|
383
|
+
if (Ref.isRefType(ast)) {
|
|
384
|
+
return {
|
|
385
|
+
ast,
|
|
386
|
+
isArray: false
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
return void 0;
|
|
724
390
|
};
|
|
725
391
|
|
|
726
|
-
// src/components/Form/
|
|
727
|
-
import
|
|
728
|
-
import
|
|
729
|
-
import
|
|
730
|
-
import {
|
|
731
|
-
|
|
732
|
-
// src/components/Form/FormActions.tsx
|
|
733
|
-
import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
|
|
734
|
-
import React8 from "react";
|
|
735
|
-
import { IconButton as IconButton2, useTranslation as useTranslation5 } from "@dxos/react-ui";
|
|
736
|
-
import { cardSpacing } from "@dxos/react-ui-stack";
|
|
737
|
-
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
392
|
+
// src/components/Form/fields/ArrayField.tsx
|
|
393
|
+
import * as Option3 from "effect/Option";
|
|
394
|
+
import * as SchemaAST2 from "effect/SchemaAST";
|
|
395
|
+
import React5, { useCallback as useCallback3 } from "react";
|
|
396
|
+
import { findNode as findNode2, getArrayElementType as getArrayElementType2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2, isNestedType as isNestedType2 } from "@dxos/effect";
|
|
397
|
+
import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
738
398
|
|
|
739
|
-
// src/components/Form/
|
|
740
|
-
import {
|
|
741
|
-
import
|
|
742
|
-
import {
|
|
743
|
-
import { getValue as
|
|
744
|
-
import {
|
|
399
|
+
// src/components/Form/Form.tsx
|
|
400
|
+
import { createContext } from "@radix-ui/react-context";
|
|
401
|
+
import * as Schema2 from "effect/Schema";
|
|
402
|
+
import React4, { useEffect as useEffect3, useMemo as useMemo4, useRef } from "react";
|
|
403
|
+
import { createJsonPath as createJsonPath3, getValue as getValue$2 } from "@dxos/effect";
|
|
404
|
+
import { IconButton, ScrollArea, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
405
|
+
import { mx as mx2 } from "@dxos/ui-theme";
|
|
745
406
|
|
|
746
|
-
// src/hooks/
|
|
747
|
-
import
|
|
748
|
-
import { useCallback
|
|
749
|
-
import {
|
|
750
|
-
import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
|
|
751
|
-
import { invariant } from "@dxos/invariant";
|
|
407
|
+
// src/hooks/useFormHandler.ts
|
|
408
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
409
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
410
|
+
import { Obj as Obj2 } from "@dxos/echo";
|
|
411
|
+
import { createJsonPath, fromEffectValidationPath, getValue as getValue$, setValue as setValue$ } from "@dxos/effect";
|
|
752
412
|
import { log } from "@dxos/log";
|
|
413
|
+
import { useDefaultValue } from "@dxos/react-ui";
|
|
753
414
|
import { validateSchema } from "@dxos/schema";
|
|
754
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-form/src/hooks/
|
|
755
|
-
var
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
415
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-form/src/hooks/useFormHandler.ts";
|
|
416
|
+
var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: defaultValuesProp, onValuesChanged, onValidate, onSave, onCancel, ...props }) => {
|
|
417
|
+
const [changed, setChanged] = useState({});
|
|
418
|
+
const [touched, setTouched] = useState({});
|
|
419
|
+
const [errors, setErrors] = useState({});
|
|
420
|
+
const [saving, setSaving] = useState(false);
|
|
421
|
+
const defaultValues = useDefaultValue(defaultValuesProp, () => ({}));
|
|
422
|
+
const [values$, setValues] = useControllableState({
|
|
423
|
+
prop: valuesProp,
|
|
424
|
+
defaultProp: defaultValues,
|
|
425
|
+
onChange: () => {
|
|
426
|
+
setValues(valuesProp ?? defaultValues);
|
|
427
|
+
setChanged({});
|
|
428
|
+
setTouched({});
|
|
429
|
+
setErrors({});
|
|
430
|
+
setSaving(false);
|
|
431
|
+
}
|
|
764
432
|
});
|
|
765
|
-
const
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
]);
|
|
771
|
-
const [touched, setTouched] = useState3(createKeySet(initialValues, false));
|
|
772
|
-
const [changed, setChanged] = useState3(createKeySet(initialValues, false));
|
|
773
|
-
const [errors, setErrors] = useState3({});
|
|
774
|
-
const [saving, setSaving] = useState3(false);
|
|
775
|
-
const validate = useCallback4((values2) => {
|
|
433
|
+
const values = values$;
|
|
434
|
+
const validate = useCallback((values2) => {
|
|
435
|
+
if (!schema) {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
776
438
|
let errors2 = validateSchema(schema, values2) ?? [];
|
|
439
|
+
log("validate", {
|
|
440
|
+
values: values2,
|
|
441
|
+
errors: errors2
|
|
442
|
+
}, {
|
|
443
|
+
F: __dxlog_file,
|
|
444
|
+
L: 160,
|
|
445
|
+
S: void 0,
|
|
446
|
+
C: (f, a) => f(...a)
|
|
447
|
+
});
|
|
777
448
|
if (errors2.length === 0 && onValidate) {
|
|
778
449
|
const validatedValues = values2;
|
|
779
450
|
errors2 = onValidate(validatedValues) ?? [];
|
|
@@ -785,36 +456,38 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
785
456
|
schema,
|
|
786
457
|
onValidate
|
|
787
458
|
]);
|
|
788
|
-
const [
|
|
789
|
-
|
|
459
|
+
const [schemaChanged, setSchemaChanged] = useState(false);
|
|
460
|
+
useEffect(() => setSchemaChanged(true), [
|
|
790
461
|
schema
|
|
791
462
|
]);
|
|
792
|
-
|
|
793
|
-
if (
|
|
463
|
+
useEffect(() => {
|
|
464
|
+
if (schemaChanged) {
|
|
794
465
|
validate(values);
|
|
795
|
-
|
|
466
|
+
setSchemaChanged(false);
|
|
796
467
|
}
|
|
797
468
|
}, [
|
|
469
|
+
validate,
|
|
798
470
|
values,
|
|
799
|
-
|
|
471
|
+
schemaChanged
|
|
800
472
|
]);
|
|
801
|
-
const
|
|
473
|
+
const isValid = useMemo(() => {
|
|
802
474
|
return Object.keys(errors).length === 0;
|
|
803
475
|
}, [
|
|
804
476
|
errors
|
|
805
477
|
]);
|
|
806
|
-
const canSave =
|
|
478
|
+
const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors.
|
|
807
479
|
!Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
|
|
808
480
|
touched,
|
|
809
481
|
errors,
|
|
810
482
|
saving
|
|
811
483
|
]);
|
|
812
|
-
const handleSave =
|
|
484
|
+
const handleSave = useCallback(async () => {
|
|
813
485
|
if (validate(values)) {
|
|
814
486
|
setSaving(true);
|
|
815
487
|
try {
|
|
816
488
|
await onSave?.(values, {
|
|
817
|
-
changed
|
|
489
|
+
changed,
|
|
490
|
+
isValid
|
|
818
491
|
});
|
|
819
492
|
} finally {
|
|
820
493
|
setSaving(false);
|
|
@@ -824,11 +497,17 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
824
497
|
values,
|
|
825
498
|
validate,
|
|
826
499
|
onSave,
|
|
827
|
-
changed
|
|
500
|
+
changed,
|
|
501
|
+
isValid
|
|
828
502
|
]);
|
|
829
|
-
const
|
|
503
|
+
const handleCancel = useCallback(() => {
|
|
504
|
+
onCancel?.();
|
|
505
|
+
}, [
|
|
506
|
+
onCancel
|
|
507
|
+
]);
|
|
508
|
+
const getStatus = useCallback((path) => {
|
|
830
509
|
const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
|
|
831
|
-
const
|
|
510
|
+
const [_, error] = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`)) ?? [];
|
|
832
511
|
const isTouched = touched[jsonPath];
|
|
833
512
|
if (!isTouched) {
|
|
834
513
|
return {
|
|
@@ -837,112 +516,120 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
837
516
|
};
|
|
838
517
|
}
|
|
839
518
|
return {
|
|
840
|
-
status:
|
|
841
|
-
error:
|
|
519
|
+
status: error ? "error" : void 0,
|
|
520
|
+
error: error ? error ?? void 0 : void 0
|
|
842
521
|
};
|
|
843
522
|
}, [
|
|
844
523
|
errors,
|
|
845
524
|
touched
|
|
846
525
|
]);
|
|
847
|
-
const
|
|
848
|
-
return getValue(values, createJsonPath(path));
|
|
526
|
+
const getValue = useCallback((path) => {
|
|
527
|
+
return getValue$(values, createJsonPath(path));
|
|
849
528
|
}, [
|
|
850
529
|
values
|
|
851
530
|
]);
|
|
852
|
-
const onValueChange =
|
|
531
|
+
const onValueChange = useCallback((path, type, value3) => {
|
|
532
|
+
log("onValueChange", {
|
|
533
|
+
path,
|
|
534
|
+
value: value3
|
|
535
|
+
}, {
|
|
536
|
+
F: __dxlog_file,
|
|
537
|
+
L: 259,
|
|
538
|
+
S: void 0,
|
|
539
|
+
C: (f, a) => f(...a)
|
|
540
|
+
});
|
|
853
541
|
const jsonPath = createJsonPath(path);
|
|
854
|
-
let parsedValue =
|
|
542
|
+
let parsedValue = value3;
|
|
855
543
|
try {
|
|
856
|
-
if (type === "
|
|
857
|
-
parsedValue = parseFloat(
|
|
544
|
+
if (type._tag === "NumberKeyword") {
|
|
545
|
+
parsedValue = parseFloat(value3) || 0;
|
|
858
546
|
}
|
|
859
547
|
} catch (err) {
|
|
860
548
|
log.catch(err, void 0, {
|
|
861
549
|
F: __dxlog_file,
|
|
862
|
-
L:
|
|
550
|
+
L: 268,
|
|
863
551
|
S: void 0,
|
|
864
552
|
C: (f, a) => f(...a)
|
|
865
553
|
});
|
|
866
554
|
parsedValue = void 0;
|
|
867
555
|
}
|
|
868
|
-
const newValues = {
|
|
869
|
-
...setValue(values, jsonPath, parsedValue)
|
|
556
|
+
const newValues = Obj2.isObject(values) ? (setValueEchoAware(values, jsonPath, parsedValue), values) : {
|
|
557
|
+
...setValue$(values, jsonPath, parsedValue)
|
|
870
558
|
};
|
|
871
559
|
setValues(newValues);
|
|
872
560
|
const newChanged = {
|
|
873
|
-
...changed,
|
|
874
561
|
[jsonPath]: true
|
|
875
562
|
};
|
|
876
|
-
setChanged(
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
563
|
+
setChanged({
|
|
564
|
+
...changed,
|
|
565
|
+
...newChanged
|
|
566
|
+
});
|
|
567
|
+
const isValid2 = validate(newValues);
|
|
568
|
+
onValuesChanged?.(newValues, {
|
|
569
|
+
isValid: isValid2,
|
|
570
|
+
changed: newChanged
|
|
571
|
+
});
|
|
884
572
|
}, [
|
|
885
573
|
values,
|
|
886
|
-
|
|
574
|
+
changed,
|
|
887
575
|
validate,
|
|
888
|
-
|
|
889
|
-
changed
|
|
576
|
+
onValuesChanged
|
|
890
577
|
]);
|
|
891
|
-
const
|
|
578
|
+
const onBlur = useCallback(async (path) => {
|
|
892
579
|
const jsonPath = createJsonPath(path);
|
|
893
580
|
setTouched((touched2) => ({
|
|
894
581
|
...touched2,
|
|
895
582
|
[jsonPath]: true
|
|
896
583
|
}));
|
|
897
|
-
validate(values);
|
|
584
|
+
const isValid2 = validate(values);
|
|
585
|
+
if (Object.keys(changed).length > 0 && isValid2 && autoSave) {
|
|
586
|
+
await onSave?.(values, {
|
|
587
|
+
changed,
|
|
588
|
+
isValid: isValid2
|
|
589
|
+
});
|
|
590
|
+
}
|
|
898
591
|
}, [
|
|
899
592
|
validate,
|
|
900
|
-
values
|
|
593
|
+
values,
|
|
594
|
+
changed,
|
|
595
|
+
autoSave,
|
|
596
|
+
onSave
|
|
901
597
|
]);
|
|
902
|
-
return
|
|
598
|
+
return useMemo(() => ({
|
|
903
599
|
// State.
|
|
600
|
+
schema,
|
|
904
601
|
values,
|
|
905
602
|
errors,
|
|
906
603
|
touched,
|
|
907
604
|
changed,
|
|
605
|
+
isValid,
|
|
908
606
|
canSave,
|
|
909
|
-
|
|
607
|
+
autoSave,
|
|
910
608
|
// Actions.
|
|
911
|
-
handleSave,
|
|
609
|
+
onSave: handleSave,
|
|
610
|
+
onCancel: handleCancel,
|
|
912
611
|
// Field utils.
|
|
913
612
|
getStatus,
|
|
914
|
-
getValue
|
|
613
|
+
getValue,
|
|
614
|
+
onBlur,
|
|
915
615
|
onValueChange,
|
|
916
|
-
|
|
616
|
+
...props
|
|
917
617
|
}), [
|
|
618
|
+
schema,
|
|
918
619
|
values,
|
|
919
620
|
errors,
|
|
920
621
|
touched,
|
|
921
622
|
changed,
|
|
922
623
|
canSave,
|
|
923
|
-
|
|
924
|
-
handleSave,
|
|
624
|
+
isValid,
|
|
925
625
|
getStatus,
|
|
926
|
-
|
|
626
|
+
getValue,
|
|
627
|
+
onBlur,
|
|
927
628
|
onValueChange,
|
|
928
|
-
|
|
629
|
+
onSave,
|
|
630
|
+
onCancel
|
|
929
631
|
]);
|
|
930
632
|
};
|
|
931
|
-
var createKeySet = (obj, value2) => {
|
|
932
|
-
invariant(obj, void 0, {
|
|
933
|
-
F: __dxlog_file,
|
|
934
|
-
L: 280,
|
|
935
|
-
S: void 0,
|
|
936
|
-
A: [
|
|
937
|
-
"obj",
|
|
938
|
-
""
|
|
939
|
-
]
|
|
940
|
-
});
|
|
941
|
-
return Object.keys(obj).reduce((acc, key) => ({
|
|
942
|
-
...acc,
|
|
943
|
-
[key]: value2
|
|
944
|
-
}), {});
|
|
945
|
-
};
|
|
946
633
|
var flatMap = (errors) => {
|
|
947
634
|
return errors.reduce((result, { path, message }) => {
|
|
948
635
|
const jsonPath = fromEffectValidationPath(path);
|
|
@@ -953,1618 +640,1908 @@ var flatMap = (errors) => {
|
|
|
953
640
|
}, {});
|
|
954
641
|
};
|
|
955
642
|
|
|
956
|
-
// src/hooks/
|
|
957
|
-
import { useCallback as
|
|
958
|
-
import {
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
const query = space.db.query(Filter.typename(typeInfo.typename));
|
|
968
|
-
const { objects } = await query.run();
|
|
969
|
-
return objects.map((object) => {
|
|
970
|
-
const dxn = getObjectDXN(object);
|
|
971
|
-
if (!dxn) {
|
|
972
|
-
return void 0;
|
|
643
|
+
// src/hooks/useKeyHandler.tsx
|
|
644
|
+
import { useCallback as useCallback2, useEffect as useEffect2 } from "react";
|
|
645
|
+
import { addEventListener } from "@dxos/async";
|
|
646
|
+
var useKeyHandler = (formElement, form) => {
|
|
647
|
+
const handleKeyDown = useCallback2((event) => {
|
|
648
|
+
switch (event.key) {
|
|
649
|
+
case "Enter": {
|
|
650
|
+
if (event.metaKey && form.canSave) {
|
|
651
|
+
form.onSave();
|
|
652
|
+
}
|
|
653
|
+
break;
|
|
973
654
|
}
|
|
974
|
-
|
|
975
|
-
dxn,
|
|
976
|
-
label: Obj.getLabel(object) ?? object?.id ?? ""
|
|
977
|
-
};
|
|
978
|
-
return item;
|
|
979
|
-
}).filter(isNonNullable);
|
|
655
|
+
}
|
|
980
656
|
}, [
|
|
981
|
-
|
|
657
|
+
form.isValid,
|
|
658
|
+
form.canSave,
|
|
659
|
+
form.onSave,
|
|
660
|
+
form.autoSave
|
|
982
661
|
]);
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
// src/hooks/useQueryRefOptions.ts
|
|
986
|
-
import { useCallback as useCallback6, useEffect as useEffect5, useState as useState4 } from "react";
|
|
987
|
-
import { log as log2 } from "@dxos/log";
|
|
988
|
-
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts";
|
|
989
|
-
var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
|
|
990
|
-
const [options, setOptions] = useState4([]);
|
|
991
|
-
const [loading, setLoading] = useState4(false);
|
|
992
|
-
const [state, setState] = useState4({});
|
|
993
|
-
const update = useCallback6(() => setState({}), []);
|
|
994
|
-
useEffect5(() => {
|
|
995
|
-
if (!refTypeInfo || !onQueryRefOptions) {
|
|
662
|
+
useEffect2(() => {
|
|
663
|
+
if (!formElement) {
|
|
996
664
|
return;
|
|
997
665
|
}
|
|
998
|
-
|
|
999
|
-
setLoading(true);
|
|
1000
|
-
try {
|
|
1001
|
-
const fetchedOptions = await onQueryRefOptions(refTypeInfo);
|
|
1002
|
-
setOptions(fetchedOptions.map((option) => {
|
|
1003
|
-
const dxn = option.dxn.toString();
|
|
1004
|
-
return {
|
|
1005
|
-
id: dxn,
|
|
1006
|
-
label: option.label ?? dxn,
|
|
1007
|
-
hue: "neutral"
|
|
1008
|
-
};
|
|
1009
|
-
}));
|
|
1010
|
-
} catch (error) {
|
|
1011
|
-
log2.error("Failed to fetch ref options:", error, {
|
|
1012
|
-
F: __dxlog_file2,
|
|
1013
|
-
L: 51,
|
|
1014
|
-
S: void 0,
|
|
1015
|
-
C: (f, a) => f(...a)
|
|
1016
|
-
});
|
|
1017
|
-
setOptions([]);
|
|
1018
|
-
} finally {
|
|
1019
|
-
setLoading(false);
|
|
1020
|
-
}
|
|
1021
|
-
};
|
|
1022
|
-
void fetchOptions();
|
|
666
|
+
return addEventListener(formElement, "keydown", handleKeyDown);
|
|
1023
667
|
}, [
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
state
|
|
668
|
+
formElement,
|
|
669
|
+
handleKeyDown
|
|
1027
670
|
]);
|
|
1028
|
-
return {
|
|
1029
|
-
options,
|
|
1030
|
-
update,
|
|
1031
|
-
loading
|
|
1032
|
-
};
|
|
1033
671
|
};
|
|
1034
672
|
|
|
1035
|
-
// src/components/Form/
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
return useMemo3(() => ({
|
|
1051
|
-
getStatus: () => getStatus(stablePath),
|
|
1052
|
-
getValue: () => getFormValue(stablePath),
|
|
1053
|
-
onValueChange: (type, value2) => onValueChange(stablePath, type, value2),
|
|
1054
|
-
onBlur: () => onTouched(stablePath)
|
|
1055
|
-
}), [
|
|
1056
|
-
getStatus,
|
|
1057
|
-
getFormValue,
|
|
1058
|
-
onValueChange,
|
|
1059
|
-
onTouched,
|
|
1060
|
-
stablePath
|
|
1061
|
-
]);
|
|
673
|
+
// src/components/Form/FormFieldComponent.tsx
|
|
674
|
+
import React, { Component } from "react";
|
|
675
|
+
import { Icon, Input, Tooltip } from "@dxos/react-ui";
|
|
676
|
+
import { errorText } from "@dxos/ui-theme";
|
|
677
|
+
var FormFieldLabel = ({ label, error, readonly, asChild }) => {
|
|
678
|
+
const Label = readonly || asChild ? "span" : Input.Label;
|
|
679
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Label, null, label), error && /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
|
|
680
|
+
asChild: true,
|
|
681
|
+
content: error,
|
|
682
|
+
side: "bottom"
|
|
683
|
+
}, /* @__PURE__ */ React.createElement(Icon, {
|
|
684
|
+
icon: "ph--warning--regular",
|
|
685
|
+
size: 4,
|
|
686
|
+
classNames: errorText
|
|
687
|
+
})));
|
|
1062
688
|
};
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
|
|
1071
|
-
const inputOptOut = event.target.hasAttribute("data-no-submit") || event.target.closest("[data-no-submit]") !== null;
|
|
1072
|
-
const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
|
|
1073
|
-
const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
|
|
1074
|
-
if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
|
|
1075
|
-
if (!autoSave && form.canSave) {
|
|
1076
|
-
form.handleSave();
|
|
1077
|
-
}
|
|
1078
|
-
if (autoSave && form.formIsValid) {
|
|
1079
|
-
event.target.blur();
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
}, [
|
|
1083
|
-
form.canSave,
|
|
1084
|
-
form.formIsValid,
|
|
1085
|
-
form.handleSave,
|
|
1086
|
-
autoSave
|
|
1087
|
-
]);
|
|
1088
|
-
useEffect6(() => {
|
|
1089
|
-
if (!formRef?.current) {
|
|
1090
|
-
return;
|
|
1091
|
-
}
|
|
1092
|
-
const formElement = formRef.current;
|
|
1093
|
-
formElement.addEventListener("keydown", handleKeyDown);
|
|
1094
|
-
return () => formElement.removeEventListener("keydown", handleKeyDown);
|
|
1095
|
-
}, [
|
|
1096
|
-
formRef,
|
|
1097
|
-
form.canSave,
|
|
1098
|
-
form.formIsValid,
|
|
1099
|
-
form.handleSave,
|
|
1100
|
-
autoSave
|
|
1101
|
-
]);
|
|
1102
|
-
return /* @__PURE__ */ React7.createElement(FormContext.Provider, {
|
|
1103
|
-
value: form
|
|
1104
|
-
}, children);
|
|
1105
|
-
} finally {
|
|
1106
|
-
_effect.f();
|
|
689
|
+
FormFieldLabel.displayName = "Form.FieldLabel";
|
|
690
|
+
var FormFieldWrapper = (props) => {
|
|
691
|
+
const { children, readonly, layout, label, getStatus, getValue } = props;
|
|
692
|
+
const { status, error } = getStatus();
|
|
693
|
+
const value3 = getValue();
|
|
694
|
+
if (layout === "static" && value3 == null) {
|
|
695
|
+
return null;
|
|
1107
696
|
}
|
|
697
|
+
const str = String(value3 ?? "");
|
|
698
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
699
|
+
role: "none",
|
|
700
|
+
className: "contents"
|
|
701
|
+
}, /* @__PURE__ */ React.createElement(Input.Root, {
|
|
702
|
+
validationValence: status
|
|
703
|
+
}, layout !== "inline" && /* @__PURE__ */ React.createElement(FormFieldLabel, {
|
|
704
|
+
error,
|
|
705
|
+
readonly,
|
|
706
|
+
label
|
|
707
|
+
}), layout === "static" ? /* @__PURE__ */ React.createElement("p", null, str) : children ? children({
|
|
708
|
+
value: value3
|
|
709
|
+
}) : null, layout === "full" && /* @__PURE__ */ React.createElement(Input.DescriptionAndValidation, null, /* @__PURE__ */ React.createElement(Input.Validation, null, error))));
|
|
1108
710
|
};
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
}
|
|
1133
|
-
|
|
711
|
+
var FormFieldErrorBoundary = class extends Component {
|
|
712
|
+
static getDerivedStateFromError(error) {
|
|
713
|
+
return {
|
|
714
|
+
error
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
state = {
|
|
718
|
+
error: void 0
|
|
719
|
+
};
|
|
720
|
+
componentDidUpdate(prevProps) {
|
|
721
|
+
if (prevProps.path !== this.props.path) {
|
|
722
|
+
this.resetError();
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
render() {
|
|
726
|
+
if (this.state.error) {
|
|
727
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
728
|
+
className: "flex gap-2 border border-roseFill font-mono text-sm"
|
|
729
|
+
}, /* @__PURE__ */ React.createElement("span", {
|
|
730
|
+
className: "bg-roseFill text-surfaceText pli-1 font-thin"
|
|
731
|
+
}, "ERROR"), String(this.props.path?.join(".")));
|
|
732
|
+
}
|
|
733
|
+
return this.props.children;
|
|
734
|
+
}
|
|
735
|
+
resetError() {
|
|
736
|
+
this.setState({
|
|
737
|
+
error: void 0
|
|
738
|
+
});
|
|
1134
739
|
}
|
|
1135
740
|
};
|
|
1136
741
|
|
|
1137
|
-
// src/components/Form/
|
|
1138
|
-
import {
|
|
1139
|
-
import
|
|
1140
|
-
import * as Schema from "effect/Schema";
|
|
1141
|
-
import * as SchemaAST4 from "effect/SchemaAST";
|
|
1142
|
-
import * as StringEffect from "effect/String";
|
|
1143
|
-
import React12, { forwardRef as forwardRef2, useMemo as useMemo6 } from "react";
|
|
1144
|
-
import { createJsonPath as createJsonPath3, findNode as findNode3, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
|
|
1145
|
-
import { mx as mx6 } from "@dxos/react-ui-theme";
|
|
1146
|
-
import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
|
|
742
|
+
// src/components/Form/FormFieldSet.tsx
|
|
743
|
+
import React3, { forwardRef, useMemo as useMemo3 } from "react";
|
|
744
|
+
import { mx } from "@dxos/ui-theme";
|
|
1147
745
|
import { isTruthy } from "@dxos/util";
|
|
1148
746
|
|
|
1149
|
-
// src/
|
|
1150
|
-
import
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
747
|
+
// src/components/Form/FormField.tsx
|
|
748
|
+
import * as Match from "effect/Match";
|
|
749
|
+
import * as Option2 from "effect/Option";
|
|
750
|
+
import * as Schema from "effect/Schema";
|
|
751
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
752
|
+
import * as String2 from "effect/String";
|
|
753
|
+
import React2, { useMemo as useMemo2 } from "react";
|
|
754
|
+
import { Format as Format3 } from "@dxos/echo";
|
|
755
|
+
import { createJsonPath as createJsonPath2, findNode, getAnnotation, getDiscriminatedType, isArrayType as isArrayType2, isDiscriminatedUnion, isLiteralUnion, isNestedType } from "@dxos/effect";
|
|
756
|
+
import { useTranslation } from "@dxos/react-ui";
|
|
757
|
+
var FormField = (props) => {
|
|
758
|
+
const {
|
|
759
|
+
type,
|
|
760
|
+
name,
|
|
761
|
+
path,
|
|
762
|
+
projection,
|
|
763
|
+
fieldMap,
|
|
764
|
+
fieldProvider,
|
|
765
|
+
readonly,
|
|
766
|
+
layout,
|
|
767
|
+
// RefFieldProps
|
|
768
|
+
createOptionLabel,
|
|
769
|
+
createOptionIcon,
|
|
770
|
+
createInitialValuePath,
|
|
771
|
+
db,
|
|
772
|
+
schemaHook,
|
|
773
|
+
getOptions: getRefOptions,
|
|
774
|
+
onCreate
|
|
775
|
+
} = props;
|
|
776
|
+
const { t } = useTranslation(translationKey);
|
|
777
|
+
const title = getAnnotation(SchemaAST.TitleAnnotationId)(type);
|
|
778
|
+
const description = getAnnotation(SchemaAST.DescriptionAnnotationId)(type);
|
|
779
|
+
const examples = getAnnotation(SchemaAST.ExamplesAnnotationId)(type);
|
|
780
|
+
const label = useMemo2(() => title ?? String2.capitalize(name), [
|
|
781
|
+
title,
|
|
782
|
+
name
|
|
783
|
+
]);
|
|
784
|
+
const placeholder = useMemo2(() => examples?.length ? `${t("example placeholder")}: ${examples[0]}` : description ?? label, [
|
|
785
|
+
examples,
|
|
786
|
+
description,
|
|
787
|
+
label
|
|
788
|
+
]);
|
|
789
|
+
const fieldState = useFormFieldState(FormField.displayName, path);
|
|
790
|
+
const fieldProps = {
|
|
791
|
+
type,
|
|
792
|
+
format: Format3.FormatAnnotation.getFromAst(type).pipe((annotation) => Option2.getOrUndefined(annotation)),
|
|
793
|
+
readonly,
|
|
794
|
+
label,
|
|
795
|
+
placeholder,
|
|
796
|
+
layout,
|
|
797
|
+
...fieldState
|
|
1180
798
|
};
|
|
1181
|
-
|
|
1182
|
-
|
|
799
|
+
const jsonPath = createJsonPath2(path ?? []);
|
|
800
|
+
const CustomField = fieldMap?.[jsonPath];
|
|
801
|
+
if (CustomField) {
|
|
802
|
+
return /* @__PURE__ */ React2.createElement(CustomField, fieldProps);
|
|
1183
803
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
804
|
+
const component = fieldProvider?.({
|
|
805
|
+
schema: Schema.make(type),
|
|
806
|
+
prop: name,
|
|
807
|
+
fieldProps
|
|
808
|
+
});
|
|
809
|
+
if (component) {
|
|
810
|
+
return component;
|
|
811
|
+
}
|
|
812
|
+
if (isArrayType2(type)) {
|
|
813
|
+
return /* @__PURE__ */ React2.createElement(ArrayField, {
|
|
814
|
+
fieldProps: fieldState,
|
|
815
|
+
label,
|
|
816
|
+
...props
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
const Field = getFormField(fieldProps);
|
|
820
|
+
if (Field) {
|
|
821
|
+
return /* @__PURE__ */ React2.createElement(Field, fieldProps);
|
|
822
|
+
}
|
|
823
|
+
const options = getOptions(type);
|
|
824
|
+
if (options) {
|
|
825
|
+
return /* @__PURE__ */ React2.createElement(SelectField, {
|
|
826
|
+
...fieldProps,
|
|
827
|
+
options: options.map((option) => ({
|
|
828
|
+
value: option,
|
|
829
|
+
label: option.toString()
|
|
830
|
+
}))
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
const refProps = getRefProps(type);
|
|
834
|
+
if (refProps) {
|
|
835
|
+
return /* @__PURE__ */ React2.createElement(RefField, {
|
|
836
|
+
...fieldProps,
|
|
837
|
+
...refProps,
|
|
838
|
+
createOptionLabel,
|
|
839
|
+
createOptionIcon,
|
|
840
|
+
createInitialValuePath,
|
|
841
|
+
db,
|
|
842
|
+
schemaHook,
|
|
843
|
+
getOptions: getRefOptions,
|
|
844
|
+
onCreate
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
if (isNestedType(type)) {
|
|
848
|
+
const baseNode = findNode(type, isDiscriminatedUnion);
|
|
849
|
+
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, fieldState.getValue()) : findNode(type, SchemaAST.isTypeLiteral);
|
|
850
|
+
if (typeLiteral) {
|
|
851
|
+
const schema = Schema.make(typeLiteral);
|
|
852
|
+
return /* @__PURE__ */ React2.createElement(FormFieldSet, {
|
|
853
|
+
schema,
|
|
854
|
+
path,
|
|
855
|
+
readonly,
|
|
856
|
+
layout,
|
|
857
|
+
label,
|
|
858
|
+
projection,
|
|
859
|
+
fieldMap,
|
|
860
|
+
fieldProvider,
|
|
861
|
+
createOptionLabel,
|
|
862
|
+
createOptionIcon,
|
|
863
|
+
createInitialValuePath,
|
|
864
|
+
db,
|
|
865
|
+
schemaHook,
|
|
866
|
+
getOptions: getRefOptions,
|
|
867
|
+
onCreate
|
|
868
|
+
});
|
|
1226
869
|
}
|
|
1227
870
|
}
|
|
871
|
+
return null;
|
|
1228
872
|
};
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
case
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
case
|
|
1243
|
-
return
|
|
1244
|
-
"text-right"
|
|
1245
|
-
];
|
|
1246
|
-
case FormatEnum.JSON:
|
|
1247
|
-
case FormatEnum.DID:
|
|
1248
|
-
return [
|
|
1249
|
-
"font-mono"
|
|
1250
|
-
];
|
|
1251
|
-
case TypeEnum.Number:
|
|
1252
|
-
case TypeEnum.Boolean:
|
|
1253
|
-
return [
|
|
1254
|
-
"text-right",
|
|
1255
|
-
"font-mono"
|
|
1256
|
-
];
|
|
1257
|
-
case TypeEnum.String:
|
|
1258
|
-
return void 0;
|
|
1259
|
-
case TypeEnum.Ref:
|
|
1260
|
-
return void 0;
|
|
1261
|
-
default:
|
|
1262
|
-
return void 0;
|
|
873
|
+
FormField.displayName = "Form.FormField";
|
|
874
|
+
var getFormField = ({ type, format }) => {
|
|
875
|
+
const formatField = Match.value(format).pipe(Match.withReturnType(), Match.when(Format3.TypeFormat.GeoPoint, () => GeoPointField), Match.when(Format3.TypeFormat.Markdown, () => MarkdownField), Match.when(Format3.TypeFormat.Text, () => TextAreaField), Match.orElse(() => void 0));
|
|
876
|
+
if (formatField) {
|
|
877
|
+
return formatField;
|
|
878
|
+
}
|
|
879
|
+
switch (type._tag) {
|
|
880
|
+
// TODO(wittjosiah): Schema.Any is currently used to represent template inputs.
|
|
881
|
+
case "AnyKeyword":
|
|
882
|
+
case "StringKeyword":
|
|
883
|
+
return TextField;
|
|
884
|
+
case "NumberKeyword":
|
|
885
|
+
return NumberField;
|
|
886
|
+
case "BooleanKeyword":
|
|
887
|
+
return BooleanField;
|
|
1263
888
|
}
|
|
1264
889
|
};
|
|
1265
|
-
var
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
});
|
|
1269
|
-
|
|
1270
|
-
// src/util/formatting.ts
|
|
1271
|
-
import { format as formatDate } from "date-fns/format";
|
|
1272
|
-
import { FormatEnum as FormatEnum2, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo/internal";
|
|
1273
|
-
var formatForDisplay = ({ type, format, value: value2, locale = void 0 }) => {
|
|
1274
|
-
const formatScalar = (type2) => {
|
|
1275
|
-
switch (type2) {
|
|
1276
|
-
case TypeEnum2.Boolean:
|
|
1277
|
-
return value2.toLocaleString().toUpperCase();
|
|
1278
|
-
case TypeEnum2.Number:
|
|
1279
|
-
return value2.toLocaleString(locale);
|
|
1280
|
-
case TypeEnum2.String:
|
|
1281
|
-
case TypeEnum2.Ref:
|
|
1282
|
-
return String(value2);
|
|
1283
|
-
default: {
|
|
1284
|
-
return String(value2);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
};
|
|
1288
|
-
if (!format) {
|
|
1289
|
-
return formatScalar(type);
|
|
890
|
+
var getOptions = (ast) => {
|
|
891
|
+
if (isLiteralUnion(ast)) {
|
|
892
|
+
return ast.types.map((type) => type.literal).filter((v) => v !== null);
|
|
1290
893
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
return
|
|
1301
|
-
}
|
|
1302
|
-
case FormatEnum2.Percent: {
|
|
1303
|
-
return `${value2 * 100}%`;
|
|
1304
|
-
}
|
|
1305
|
-
case FormatEnum2.Currency: {
|
|
1306
|
-
return value2.toLocaleString(locale, {
|
|
1307
|
-
style: "currency",
|
|
1308
|
-
currency: "USD",
|
|
1309
|
-
minimumFractionDigits: 2,
|
|
1310
|
-
maximumFractionDigits: 2
|
|
1311
|
-
});
|
|
1312
|
-
}
|
|
1313
|
-
case FormatEnum2.Date: {
|
|
1314
|
-
try {
|
|
1315
|
-
return formatDate(new Date(value2), "yyyy-MM-dd");
|
|
1316
|
-
} catch (error) {
|
|
1317
|
-
return "Invalid Date";
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
case FormatEnum2.Time: {
|
|
1321
|
-
try {
|
|
1322
|
-
return formatDate(new Date(value2), "HH:mm:ss");
|
|
1323
|
-
} catch (error) {
|
|
1324
|
-
return "Invalid Time";
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
case FormatEnum2.DateTime: {
|
|
1328
|
-
try {
|
|
1329
|
-
return formatDate(new Date(value2), "yyyy-MM-dd HH:mm:ss");
|
|
1330
|
-
} catch (error) {
|
|
1331
|
-
return "Invalid DateTime";
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
case FormatEnum2.GeoPoint: {
|
|
1335
|
-
if (value2 === null || value2 === void 0) {
|
|
1336
|
-
return "";
|
|
1337
|
-
}
|
|
1338
|
-
if (Array.isArray(value2) && value2.length >= 2 && value2.every(Number.isFinite)) {
|
|
1339
|
-
const { latitude, longitude } = GeoLocation3.fromGeoPoint(value2);
|
|
1340
|
-
return `${latitude},${longitude}`;
|
|
1341
|
-
}
|
|
1342
|
-
return String(value2);
|
|
894
|
+
return Format3.OptionsAnnotation.getFromAst(ast).pipe((annotation) => Option2.getOrUndefined(annotation));
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
// src/components/Form/FormFieldSet.tsx
|
|
898
|
+
var FORM_FIELDSET_NAME = "Form.FieldSet";
|
|
899
|
+
var FormFieldSet = /* @__PURE__ */ forwardRef(({ classNames, label, schema, readonly, path, exclude, sort, projection, layout, ...props }, forwardRef4) => {
|
|
900
|
+
const values = useFormValues(FORM_FIELDSET_NAME, path);
|
|
901
|
+
const properties = useMemo3(() => {
|
|
902
|
+
if (!schema) {
|
|
903
|
+
return [];
|
|
1343
904
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
905
|
+
const props2 = getFormProperties(schema.ast);
|
|
906
|
+
if (projection) {
|
|
907
|
+
const fieldProjections = projection.getFieldProjections();
|
|
908
|
+
const hiddenProperties = new Set(projection.getHiddenProperties());
|
|
909
|
+
const visibleProps = props2.filter((prop) => !hiddenProperties.has(prop.name.toString()));
|
|
910
|
+
const orderedProps = [];
|
|
911
|
+
for (const fieldProjection of fieldProjections) {
|
|
912
|
+
const fieldPath = String(fieldProjection.field.path);
|
|
913
|
+
const prop = visibleProps.find((p) => p.name === fieldPath);
|
|
914
|
+
if (prop) {
|
|
915
|
+
orderedProps.push(prop);
|
|
916
|
+
}
|
|
1347
917
|
}
|
|
1348
|
-
|
|
918
|
+
const projectionPaths = new Set(fieldProjections.map((projection2) => String(projection2.field.path)));
|
|
919
|
+
const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name.toString()));
|
|
920
|
+
orderedProps.push(...remainingProps);
|
|
921
|
+
return orderedProps;
|
|
1349
922
|
}
|
|
923
|
+
const filtered = exclude ? exclude(props2) : props2;
|
|
924
|
+
return sort ? filtered.sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString())) : filtered;
|
|
925
|
+
}, [
|
|
926
|
+
schema,
|
|
927
|
+
values,
|
|
928
|
+
exclude,
|
|
929
|
+
sort,
|
|
930
|
+
projection?.fields
|
|
931
|
+
]);
|
|
932
|
+
if ((readonly || layout === "static") && values == null) {
|
|
933
|
+
return null;
|
|
1350
934
|
}
|
|
935
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
936
|
+
role: "form",
|
|
937
|
+
className: mx("is-full", layout === "inline" && "flex flex-col gap-2", classNames),
|
|
938
|
+
ref: forwardRef4
|
|
939
|
+
}, layout !== "inline" && label && /* @__PURE__ */ React3.createElement(FormFieldLabel, {
|
|
940
|
+
label,
|
|
941
|
+
asChild: true
|
|
942
|
+
}), properties.map((property) => {
|
|
943
|
+
const name = property.name.toString();
|
|
944
|
+
return /* @__PURE__ */ React3.createElement(FormFieldErrorBoundary, {
|
|
945
|
+
key: name,
|
|
946
|
+
path: [
|
|
947
|
+
...path ?? [],
|
|
948
|
+
name
|
|
949
|
+
]
|
|
950
|
+
}, /* @__PURE__ */ React3.createElement(FormField, {
|
|
951
|
+
type: property.type,
|
|
952
|
+
name,
|
|
953
|
+
path: [
|
|
954
|
+
...path ?? [],
|
|
955
|
+
name
|
|
956
|
+
],
|
|
957
|
+
readonly,
|
|
958
|
+
layout,
|
|
959
|
+
projection,
|
|
960
|
+
...props
|
|
961
|
+
}));
|
|
962
|
+
}).filter(isTruthy));
|
|
963
|
+
});
|
|
964
|
+
FormFieldSet.displayName = FORM_FIELDSET_NAME;
|
|
965
|
+
|
|
966
|
+
// src/components/Form/Form.tsx
|
|
967
|
+
var omitId = (schema) => schema.pipe(Schema2.omit("id"));
|
|
968
|
+
var [FormContextProvider, useFormContext] = createContext("Form");
|
|
969
|
+
var useFormValues = (componentName, path = [], defaultValue) => {
|
|
970
|
+
const jsonPath = createJsonPath3(path);
|
|
971
|
+
const { form: { values } } = useFormContext(componentName);
|
|
972
|
+
const value3 = getValue$2(values, jsonPath);
|
|
973
|
+
useEffect3(() => {
|
|
974
|
+
if (!value3 && defaultValue) {
|
|
975
|
+
setValueEchoAware(values, jsonPath, defaultValue());
|
|
976
|
+
}
|
|
977
|
+
}, [
|
|
978
|
+
value3,
|
|
979
|
+
defaultValue
|
|
980
|
+
]);
|
|
981
|
+
return value3;
|
|
1351
982
|
};
|
|
1352
|
-
var
|
|
1353
|
-
const
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
983
|
+
var useFormFieldState = (componentName, path = []) => {
|
|
984
|
+
const stablePath = useMemo4(() => path, [
|
|
985
|
+
Array.isArray(path) ? path.join(".") : path
|
|
986
|
+
]);
|
|
987
|
+
const { form: { getStatus, getValue, onBlur, onValueChange } } = useFormContext(componentName);
|
|
988
|
+
return useMemo4(() => ({
|
|
989
|
+
getStatus: () => getStatus(stablePath),
|
|
990
|
+
getValue: () => getValue(stablePath),
|
|
991
|
+
onBlur: () => onBlur(stablePath),
|
|
992
|
+
onValueChange: (ast, value3) => onValueChange(stablePath, ast, value3)
|
|
993
|
+
}), [
|
|
994
|
+
getStatus,
|
|
995
|
+
getValue,
|
|
996
|
+
onBlur,
|
|
997
|
+
onValueChange,
|
|
998
|
+
stablePath
|
|
999
|
+
]);
|
|
1000
|
+
};
|
|
1001
|
+
var FormRoot = ({ children, schema, values, onSave, onCancel, ...props }) => {
|
|
1002
|
+
const form = useFormHandler({
|
|
1003
|
+
schema,
|
|
1004
|
+
values,
|
|
1005
|
+
onSave,
|
|
1006
|
+
onCancel,
|
|
1007
|
+
...props
|
|
1008
|
+
});
|
|
1009
|
+
return /* @__PURE__ */ React4.createElement(FormContextProvider, {
|
|
1010
|
+
form,
|
|
1011
|
+
...props
|
|
1012
|
+
}, children);
|
|
1013
|
+
};
|
|
1014
|
+
FormRoot.displayName = "Form.Root";
|
|
1015
|
+
var FORM_VIEWPORT_NAME = "Form.Viewport";
|
|
1016
|
+
var FormViewport = ({ children }) => {
|
|
1017
|
+
return /* @__PURE__ */ React4.createElement(ScrollArea.Root, {
|
|
1018
|
+
orientation: "vertical"
|
|
1019
|
+
}, /* @__PURE__ */ React4.createElement(ScrollArea.Viewport, null, children));
|
|
1020
|
+
};
|
|
1021
|
+
FormViewport.displayName = FORM_VIEWPORT_NAME;
|
|
1022
|
+
var FORM_CONTENT_NAME = "Form.Content";
|
|
1023
|
+
var FormContent = ({ classNames, children }) => {
|
|
1024
|
+
const { form, testId } = useFormContext(FORM_CONTENT_NAME);
|
|
1025
|
+
const ref = useRef(null);
|
|
1026
|
+
useKeyHandler(ref.current, form);
|
|
1027
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
1028
|
+
ref,
|
|
1029
|
+
role: "form",
|
|
1030
|
+
className: mx2("flex flex-col is-full pli-cardSpacingInline density-fine", classNames),
|
|
1031
|
+
"data-testid": testId
|
|
1032
|
+
}, children);
|
|
1033
|
+
};
|
|
1034
|
+
FormContent.displayName = FORM_CONTENT_NAME;
|
|
1035
|
+
var FORM_FIELDSET_NAME2 = "Form.FieldSet";
|
|
1036
|
+
var FormFieldSet2 = ({ classNames }) => {
|
|
1037
|
+
const { form, ...props } = useFormContext(FORM_FIELDSET_NAME2);
|
|
1038
|
+
return /* @__PURE__ */ React4.createElement(FormFieldSet, {
|
|
1039
|
+
classNames,
|
|
1040
|
+
schema: form.schema,
|
|
1041
|
+
...props
|
|
1042
|
+
});
|
|
1043
|
+
};
|
|
1044
|
+
FormFieldSet2.displayName = FORM_FIELDSET_NAME2;
|
|
1045
|
+
var FORM_ACTIONS_NAME = "Form.Actions";
|
|
1046
|
+
var FormActions = ({ classNames }) => {
|
|
1047
|
+
const { t } = useTranslation2(translationKey);
|
|
1048
|
+
const { form: { canSave, onSave, onCancel }, readonly, layout } = useFormContext(FORM_ACTIONS_NAME);
|
|
1049
|
+
if (readonly || layout === "static") {
|
|
1050
|
+
return null;
|
|
1051
|
+
}
|
|
1052
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
1053
|
+
role: "none",
|
|
1054
|
+
className: mx2("grid grid-flow-col auto-cols-fr gap-2 pbs-cardSpacingBlock", classNames)
|
|
1055
|
+
}, onCancel && /* @__PURE__ */ React4.createElement(IconButton, {
|
|
1056
|
+
icon: "ph--x--regular",
|
|
1057
|
+
iconEnd: true,
|
|
1058
|
+
label: t("cancel button label"),
|
|
1059
|
+
onClick: onCancel,
|
|
1060
|
+
"data-testid": "cancel-button"
|
|
1061
|
+
}), onSave && /* @__PURE__ */ React4.createElement(IconButton, {
|
|
1062
|
+
type: "submit",
|
|
1063
|
+
variant: "primary",
|
|
1064
|
+
disabled: !canSave,
|
|
1065
|
+
icon: "ph--check--regular",
|
|
1066
|
+
iconEnd: true,
|
|
1067
|
+
label: t("save button label"),
|
|
1068
|
+
onClick: onSave,
|
|
1069
|
+
"data-testid": "save-button"
|
|
1070
|
+
}));
|
|
1071
|
+
};
|
|
1072
|
+
FormActions.displayName = FORM_ACTIONS_NAME;
|
|
1073
|
+
var FORM_SUBMIT_NAME = "Form.Submit";
|
|
1074
|
+
var FormSubmit = ({ classNames, label, icon, disabled }) => {
|
|
1075
|
+
const { t } = useTranslation2(translationKey);
|
|
1076
|
+
const { form: { canSave, onSave }, readonly, layout } = useFormContext(FORM_SUBMIT_NAME);
|
|
1077
|
+
if (readonly || layout === "static") {
|
|
1078
|
+
return null;
|
|
1079
|
+
}
|
|
1080
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
1081
|
+
role: "none",
|
|
1082
|
+
className: mx2("flex is-full pbs-cardSpacingBlock", classNames)
|
|
1083
|
+
}, /* @__PURE__ */ React4.createElement(IconButton, {
|
|
1084
|
+
classNames: "is-full",
|
|
1085
|
+
type: "submit",
|
|
1086
|
+
variant: "primary",
|
|
1087
|
+
disabled: disabled ?? !canSave,
|
|
1088
|
+
icon: icon ?? "ph--check--regular",
|
|
1089
|
+
label: label ?? t("save button label"),
|
|
1090
|
+
onClick: onSave,
|
|
1091
|
+
"data-testid": "save-button"
|
|
1092
|
+
}));
|
|
1093
|
+
};
|
|
1094
|
+
FormSubmit.displayName = FORM_SUBMIT_NAME;
|
|
1095
|
+
var Form = {
|
|
1096
|
+
Root: FormRoot,
|
|
1097
|
+
Viewport: FormViewport,
|
|
1098
|
+
Content: FormContent,
|
|
1099
|
+
FieldSet: FormFieldSet2,
|
|
1100
|
+
Actions: FormActions,
|
|
1101
|
+
Submit: FormSubmit,
|
|
1102
|
+
Label: FormFieldLabel
|
|
1103
|
+
};
|
|
1104
|
+
|
|
1105
|
+
// src/components/Form/fields/ArrayField.tsx
|
|
1106
|
+
var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps, ...props }) => {
|
|
1107
|
+
const { t } = useTranslation3(translationKey);
|
|
1108
|
+
const elementType = getArrayElementType2(type);
|
|
1109
|
+
const { onValueChange } = inputProps;
|
|
1110
|
+
const values = useFormValues(ArrayField.displayName, path, () => []);
|
|
1111
|
+
const getDefaultObjectValue = (typeNode) => {
|
|
1112
|
+
const baseNode = findNode2(typeNode, isDiscriminatedUnion2);
|
|
1113
|
+
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, {}) : findNode2(typeNode, SchemaAST2.isTypeLiteral);
|
|
1114
|
+
if (!typeLiteral) {
|
|
1115
|
+
return {};
|
|
1362
1116
|
}
|
|
1117
|
+
return Object.fromEntries(getFormProperties(typeLiteral).map((prop) => {
|
|
1118
|
+
const defaultValue = SchemaAST2.getDefaultAnnotation(prop.type).pipe((annotation) => Option3.getOrUndefined(annotation));
|
|
1119
|
+
return [
|
|
1120
|
+
prop.name,
|
|
1121
|
+
defaultValue
|
|
1122
|
+
];
|
|
1123
|
+
}));
|
|
1363
1124
|
};
|
|
1364
|
-
|
|
1365
|
-
|
|
1125
|
+
const handleAdd = useCallback3(() => {
|
|
1126
|
+
const defaultValue = isNestedType2(type) && elementType ? getDefaultObjectValue(elementType) : getDefaultValue(elementType);
|
|
1127
|
+
values && onValueChange(type, [
|
|
1128
|
+
...values,
|
|
1129
|
+
defaultValue
|
|
1130
|
+
]);
|
|
1131
|
+
}, [
|
|
1132
|
+
onValueChange,
|
|
1133
|
+
type,
|
|
1134
|
+
elementType,
|
|
1135
|
+
values
|
|
1136
|
+
]);
|
|
1137
|
+
const handleDelete = useCallback3((idx) => {
|
|
1138
|
+
onValueChange(type, values?.filter((_, i) => i !== idx));
|
|
1139
|
+
}, [
|
|
1140
|
+
onValueChange,
|
|
1141
|
+
type,
|
|
1142
|
+
values
|
|
1143
|
+
]);
|
|
1144
|
+
if (!elementType || (readonly || layout === "static") && values && values.length < 1) {
|
|
1145
|
+
return null;
|
|
1366
1146
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1147
|
+
return /* @__PURE__ */ React5.createElement(React5.Fragment, null, (layout !== "static" || values && values.length > 0) && /* @__PURE__ */ React5.createElement(FormFieldLabel, {
|
|
1148
|
+
readonly,
|
|
1149
|
+
label,
|
|
1150
|
+
asChild: true
|
|
1151
|
+
}), /* @__PURE__ */ React5.createElement("div", {
|
|
1152
|
+
role: "none",
|
|
1153
|
+
className: "flex flex-col gap-2"
|
|
1154
|
+
}, values?.map((_, index) => {
|
|
1155
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
1156
|
+
role: "none",
|
|
1157
|
+
key: index,
|
|
1158
|
+
className: "grid grid-cols-[1fr_min-content] gap-2 last:mb-3"
|
|
1159
|
+
}, /* @__PURE__ */ React5.createElement(FormField, {
|
|
1160
|
+
autoFocus: index === values.length - 1,
|
|
1161
|
+
type: elementType,
|
|
1162
|
+
path: [
|
|
1163
|
+
...path ?? [],
|
|
1164
|
+
index
|
|
1165
|
+
],
|
|
1166
|
+
readonly: readonly || layout === "static",
|
|
1167
|
+
layout: "inline",
|
|
1168
|
+
...props
|
|
1169
|
+
}), !readonly && layout !== "static" && /* @__PURE__ */ React5.createElement("div", {
|
|
1170
|
+
role: "none",
|
|
1171
|
+
className: "flex flex-col bs-full justify-end"
|
|
1172
|
+
}, /* @__PURE__ */ React5.createElement("div", {
|
|
1173
|
+
role: "none",
|
|
1174
|
+
className: "flex items-center bs-[var(--line-height)]"
|
|
1175
|
+
}, /* @__PURE__ */ React5.createElement(IconButton2, {
|
|
1176
|
+
icon: "ph--x--regular",
|
|
1177
|
+
iconOnly: true,
|
|
1178
|
+
label: t("button remove"),
|
|
1179
|
+
onClick: () => handleDelete(index),
|
|
1180
|
+
classNames: "self-center"
|
|
1181
|
+
}))));
|
|
1182
|
+
})), !readonly && layout !== "static" && /* @__PURE__ */ React5.createElement(IconButton2, {
|
|
1183
|
+
classNames: "flex is-full _mlb-cardSpacingBlock",
|
|
1184
|
+
icon: "ph--plus--regular",
|
|
1185
|
+
label: t("add field"),
|
|
1186
|
+
onClick: handleAdd
|
|
1187
|
+
}));
|
|
1188
|
+
};
|
|
1189
|
+
ArrayField.displayName = "Form.ArrayField";
|
|
1190
|
+
var getDefaultValue = (ast) => {
|
|
1191
|
+
switch (ast?._tag) {
|
|
1192
|
+
case "StringKeyword": {
|
|
1193
|
+
return "";
|
|
1383
1194
|
}
|
|
1384
|
-
case
|
|
1385
|
-
|
|
1386
|
-
return date.toISOString().split("T")[0];
|
|
1195
|
+
case "NumberKeyword": {
|
|
1196
|
+
return 0;
|
|
1387
1197
|
}
|
|
1388
|
-
case
|
|
1389
|
-
|
|
1390
|
-
return date.toISOString().split("T")[1].split(".")[0];
|
|
1198
|
+
case "BooleanKeyword": {
|
|
1199
|
+
return false;
|
|
1391
1200
|
}
|
|
1392
|
-
case
|
|
1393
|
-
|
|
1394
|
-
return "";
|
|
1395
|
-
}
|
|
1396
|
-
if (Array.isArray(value2) && value2.length >= 2 && value2.every(Number.isFinite)) {
|
|
1397
|
-
const { latitude, longitude } = GeoLocation3.fromGeoPoint(value2);
|
|
1398
|
-
return `${latitude},${longitude}`;
|
|
1399
|
-
}
|
|
1400
|
-
return String(value2);
|
|
1201
|
+
case "Suspend": {
|
|
1202
|
+
return getDefaultValue(ast.f());
|
|
1401
1203
|
}
|
|
1402
1204
|
default: {
|
|
1403
|
-
|
|
1205
|
+
if (ast && isNestedType2(ast)) {
|
|
1206
|
+
return {};
|
|
1207
|
+
} else {
|
|
1208
|
+
throw new Error(`Unsupported type: ${ast?._tag}`);
|
|
1209
|
+
}
|
|
1404
1210
|
}
|
|
1405
1211
|
}
|
|
1406
1212
|
};
|
|
1407
1213
|
|
|
1408
|
-
// src/
|
|
1409
|
-
import {
|
|
1410
|
-
import {
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1214
|
+
// src/components/Form/fields/BooleanField.tsx
|
|
1215
|
+
import React6, { useCallback as useCallback4 } from "react";
|
|
1216
|
+
import { Input as Input2 } from "@dxos/react-ui";
|
|
1217
|
+
var BooleanField = ({ type, readonly, onValueChange, ...props }) => {
|
|
1218
|
+
const handleChange = useCallback4((value3) => onValueChange?.(type, value3), [
|
|
1219
|
+
type,
|
|
1220
|
+
onValueChange
|
|
1221
|
+
]);
|
|
1222
|
+
return /* @__PURE__ */ React6.createElement(FormFieldWrapper, {
|
|
1223
|
+
readonly,
|
|
1224
|
+
...props
|
|
1225
|
+
}, ({ value: value3 }) => /* @__PURE__ */ React6.createElement(Input2.Switch, {
|
|
1226
|
+
disabled: !!readonly,
|
|
1227
|
+
checked: value3,
|
|
1228
|
+
onCheckedChange: handleChange
|
|
1229
|
+
}));
|
|
1418
1230
|
};
|
|
1419
1231
|
|
|
1420
|
-
// src/
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1232
|
+
// src/components/Form/fields/GeoPointField.tsx
|
|
1233
|
+
import React7, { useCallback as useCallback5, useEffect as useEffect4, useMemo as useMemo5, useState as useState2 } from "react";
|
|
1234
|
+
import { GeoLocation as GeoLocation3 } from "@dxos/echo/internal";
|
|
1235
|
+
import { Input as Input3, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
1236
|
+
import { safeParseFloat } from "@dxos/util";
|
|
1237
|
+
var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onValueChange, onBlur }) => {
|
|
1238
|
+
const { t } = useTranslation4(translationKey);
|
|
1239
|
+
const { status, error } = getStatus();
|
|
1240
|
+
const geoPoint = useMemo5(() => getValue() ?? [
|
|
1241
|
+
0,
|
|
1242
|
+
0
|
|
1243
|
+
], [
|
|
1244
|
+
getValue
|
|
1245
|
+
]);
|
|
1246
|
+
const value3 = useMemo5(() => GeoLocation3.fromGeoPoint(geoPoint), [
|
|
1247
|
+
geoPoint
|
|
1248
|
+
]);
|
|
1249
|
+
const [longitudeText, setLongitudeText] = useState2(value3.longitude?.toString());
|
|
1250
|
+
const [latitudeText, setLatitudeText] = useState2(value3.latitude?.toString());
|
|
1251
|
+
useEffect4(() => {
|
|
1252
|
+
const location = GeoLocation3.fromGeoPoint(geoPoint);
|
|
1253
|
+
setLongitudeText(location.longitude?.toString());
|
|
1254
|
+
setLatitudeText(location.latitude?.toString());
|
|
1255
|
+
}, [
|
|
1256
|
+
geoPoint
|
|
1257
|
+
]);
|
|
1258
|
+
const handleChange = useCallback5((coordinateType, setText) => (event) => {
|
|
1259
|
+
const inputText = event.target.value;
|
|
1260
|
+
setText(inputText);
|
|
1261
|
+
if (inputText !== "" && inputText !== "-") {
|
|
1262
|
+
const coord = safeParseFloat(inputText);
|
|
1263
|
+
if (coord !== void 0 && !isNaN(coord)) {
|
|
1264
|
+
const currentLocation = GeoLocation3.fromGeoPoint(getValue() ?? [
|
|
1265
|
+
0,
|
|
1266
|
+
0
|
|
1267
|
+
]);
|
|
1268
|
+
const newLocation = {
|
|
1269
|
+
...currentLocation,
|
|
1270
|
+
[coordinateType]: coord
|
|
1437
1271
|
};
|
|
1272
|
+
const newValue = GeoLocation3.toGeoPoint(newLocation);
|
|
1273
|
+
onValueChange(type, newValue);
|
|
1438
1274
|
}
|
|
1439
1275
|
}
|
|
1276
|
+
}, [
|
|
1277
|
+
type,
|
|
1278
|
+
getValue,
|
|
1279
|
+
onValueChange
|
|
1280
|
+
]);
|
|
1281
|
+
if ((readonly || layout === "static") && !value3?.latitude && !value3?.longitude) {
|
|
1282
|
+
return null;
|
|
1440
1283
|
}
|
|
1441
|
-
return
|
|
1284
|
+
return /* @__PURE__ */ React7.createElement(Input3.Root, {
|
|
1285
|
+
validationValence: status
|
|
1286
|
+
}, layout !== "inline" && /* @__PURE__ */ React7.createElement(FormFieldLabel, {
|
|
1287
|
+
error,
|
|
1288
|
+
readonly,
|
|
1289
|
+
label,
|
|
1290
|
+
asChild: true
|
|
1291
|
+
}), layout === "static" ? /* @__PURE__ */ React7.createElement(LatLng, value3) : /* @__PURE__ */ React7.createElement("div", {
|
|
1292
|
+
role: "none",
|
|
1293
|
+
className: "grid grid-cols-2 gap-2"
|
|
1294
|
+
}, /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("latitude label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
|
|
1295
|
+
type: "number",
|
|
1296
|
+
step: "0.00001",
|
|
1297
|
+
min: "-90",
|
|
1298
|
+
max: "90",
|
|
1299
|
+
disabled: !!readonly,
|
|
1300
|
+
placeholder: t("latitude placeholder"),
|
|
1301
|
+
value: latitudeText ?? "",
|
|
1302
|
+
onChange: handleChange("latitude", setLatitudeText),
|
|
1303
|
+
onBlur
|
|
1304
|
+
}))), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("longitude label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
|
|
1305
|
+
type: "number",
|
|
1306
|
+
step: "0.00001",
|
|
1307
|
+
min: "-180",
|
|
1308
|
+
max: "180",
|
|
1309
|
+
disabled: !!readonly,
|
|
1310
|
+
placeholder: t("longitude placeholder"),
|
|
1311
|
+
value: longitudeText ?? "",
|
|
1312
|
+
onChange: handleChange("longitude", setLongitudeText),
|
|
1313
|
+
onBlur
|
|
1314
|
+
})))));
|
|
1315
|
+
};
|
|
1316
|
+
var LatLng = ({ latitude = 0, longitude = 0 }) => {
|
|
1317
|
+
const latHem = latitude >= 0 ? "N" : "S";
|
|
1318
|
+
const lngHem = longitude >= 0 ? "E" : "W";
|
|
1319
|
+
return /* @__PURE__ */ React7.createElement("span", {
|
|
1320
|
+
className: "inline-flex items-center gap-1"
|
|
1321
|
+
}, /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement("span", null, Math.abs(latitude).toFixed(5)), /* @__PURE__ */ React7.createElement("span", {
|
|
1322
|
+
className: "text-subdued"
|
|
1323
|
+
}, "\xB0", latHem)), /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement("span", null, Math.abs(longitude).toFixed(5)), /* @__PURE__ */ React7.createElement("span", {
|
|
1324
|
+
className: "text-subdued"
|
|
1325
|
+
}, "\xB0", lngHem)));
|
|
1442
1326
|
};
|
|
1443
1327
|
|
|
1444
|
-
// src/components/Form/
|
|
1445
|
-
import {
|
|
1446
|
-
import
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
|
|
1456
|
-
var _effect = _useSignals9();
|
|
1457
|
-
try {
|
|
1458
|
-
const { t } = useTranslation6(translationKey);
|
|
1459
|
-
const { ast, name, type, title } = property;
|
|
1460
|
-
const values = useFormValues(path ?? []) ?? [];
|
|
1461
|
-
invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
|
|
1462
|
-
F: __dxlog_file3,
|
|
1463
|
-
L: 37,
|
|
1464
|
-
S: void 0,
|
|
1465
|
-
A: [
|
|
1466
|
-
"Array.isArray(values)",
|
|
1467
|
-
"`Values at path ${path?.join('.')} must be an array.`"
|
|
1468
|
-
]
|
|
1469
|
-
});
|
|
1470
|
-
const label = title ?? Function.pipe(name, String2.capitalize);
|
|
1471
|
-
const elementType = findArrayElementType(ast);
|
|
1472
|
-
const getDefaultObjectValue = (typeNode) => {
|
|
1473
|
-
const baseNode = findNode2(typeNode, isDiscriminatedUnion);
|
|
1474
|
-
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode2(typeNode, SchemaAST3.isTypeLiteral);
|
|
1475
|
-
if (!typeLiteral) {
|
|
1476
|
-
return {};
|
|
1477
|
-
}
|
|
1478
|
-
return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
|
|
1479
|
-
prop.name,
|
|
1480
|
-
prop.defaultValue
|
|
1481
|
-
]));
|
|
1482
|
-
};
|
|
1483
|
-
const getDefaultValue = () => type === "object" && elementType ? getDefaultObjectValue(elementType) : SimpleType.getDefaultValue(type);
|
|
1484
|
-
const handleAdd = useCallback8(() => {
|
|
1485
|
-
inputProps.onValueChange(type, [
|
|
1486
|
-
...values,
|
|
1487
|
-
getDefaultValue()
|
|
1488
|
-
]);
|
|
1489
|
-
}, [
|
|
1490
|
-
type,
|
|
1491
|
-
elementType,
|
|
1492
|
-
inputProps,
|
|
1493
|
-
values
|
|
1494
|
-
]);
|
|
1495
|
-
const handleRemove = useCallback8((index) => {
|
|
1496
|
-
const newValues = values.filter((_, i) => i !== index);
|
|
1497
|
-
inputProps.onValueChange(type, newValues);
|
|
1498
|
-
}, [
|
|
1499
|
-
type,
|
|
1500
|
-
inputProps,
|
|
1501
|
-
values
|
|
1502
|
-
]);
|
|
1503
|
-
if (!elementType) {
|
|
1504
|
-
return null;
|
|
1328
|
+
// src/components/Form/fields/MarkdownField.tsx
|
|
1329
|
+
import React8, { useCallback as useCallback6, useEffect as useEffect5, useRef as useRef2 } from "react";
|
|
1330
|
+
import { Input as Input4 } from "@dxos/react-ui";
|
|
1331
|
+
var MarkdownField = ({ type, readonly, label, placeholder, layout, getStatus, getValue, onValueChange, onBlur }) => {
|
|
1332
|
+
const { status, error } = getStatus();
|
|
1333
|
+
const textareaRef = useRef2(null);
|
|
1334
|
+
const adjustHeight = useCallback6(() => {
|
|
1335
|
+
const textarea = textareaRef.current;
|
|
1336
|
+
if (textarea) {
|
|
1337
|
+
textarea.style.blockSize = "auto";
|
|
1338
|
+
textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
|
|
1505
1339
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
Custom,
|
|
1526
|
-
lookupComponent
|
|
1527
|
-
});
|
|
1528
|
-
return readonly ? field : /* @__PURE__ */ React9.createElement(Fragment, {
|
|
1529
|
-
key: index
|
|
1530
|
-
}, /* @__PURE__ */ React9.createElement("div", {
|
|
1531
|
-
role: "none"
|
|
1532
|
-
}, field), /* @__PURE__ */ React9.createElement(IconButton3, {
|
|
1533
|
-
icon: "ph--trash--regular",
|
|
1534
|
-
iconOnly: true,
|
|
1535
|
-
label: t("button remove"),
|
|
1536
|
-
onClick: () => handleRemove(index),
|
|
1537
|
-
classNames: "self-center"
|
|
1538
|
-
}));
|
|
1539
|
-
})), !readonly && /* @__PURE__ */ React9.createElement(IconButton3, {
|
|
1540
|
-
classNames: "is-full mlb-cardSpacingBlock flex",
|
|
1541
|
-
icon: "ph--plus--regular",
|
|
1542
|
-
label: t("add field"),
|
|
1543
|
-
onClick: handleAdd
|
|
1544
|
-
}));
|
|
1545
|
-
} finally {
|
|
1546
|
-
_effect.f();
|
|
1340
|
+
}, []);
|
|
1341
|
+
useEffect5(() => {
|
|
1342
|
+
adjustHeight();
|
|
1343
|
+
}, [
|
|
1344
|
+
adjustHeight
|
|
1345
|
+
]);
|
|
1346
|
+
useEffect5(() => {
|
|
1347
|
+
adjustHeight();
|
|
1348
|
+
}, [
|
|
1349
|
+
getValue(),
|
|
1350
|
+
adjustHeight
|
|
1351
|
+
]);
|
|
1352
|
+
const handleChange = useCallback6((event) => onValueChange(type, event.target.value), [
|
|
1353
|
+
type,
|
|
1354
|
+
onValueChange
|
|
1355
|
+
]);
|
|
1356
|
+
const value3 = getValue();
|
|
1357
|
+
if ((readonly || layout === "static") && !value3) {
|
|
1358
|
+
return null;
|
|
1547
1359
|
}
|
|
1360
|
+
return /* @__PURE__ */ React8.createElement(Input4.Root, {
|
|
1361
|
+
validationValence: status
|
|
1362
|
+
}, layout !== "inline" && /* @__PURE__ */ React8.createElement(FormFieldLabel, {
|
|
1363
|
+
error,
|
|
1364
|
+
readonly,
|
|
1365
|
+
label
|
|
1366
|
+
}), layout === "static" ? /* @__PURE__ */ React8.createElement("p", null, value3) : /* @__PURE__ */ React8.createElement(Input4.TextArea, {
|
|
1367
|
+
ref: textareaRef,
|
|
1368
|
+
disabled: !!readonly,
|
|
1369
|
+
placeholder,
|
|
1370
|
+
value: value3 ?? "",
|
|
1371
|
+
classNames: "min-bs-auto max-bs-40 overflow-auto",
|
|
1372
|
+
onChange: handleChange,
|
|
1373
|
+
onBlur,
|
|
1374
|
+
style: {
|
|
1375
|
+
resize: "none"
|
|
1376
|
+
},
|
|
1377
|
+
spellCheck: false
|
|
1378
|
+
}), layout === "full" && /* @__PURE__ */ React8.createElement(Input4.Validation, null, error));
|
|
1548
1379
|
};
|
|
1549
1380
|
|
|
1550
|
-
// src/components/Form/
|
|
1551
|
-
import {
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1381
|
+
// src/components/Form/fields/NumberField.tsx
|
|
1382
|
+
import React9, { useCallback as useCallback7 } from "react";
|
|
1383
|
+
import { Input as Input5 } from "@dxos/react-ui";
|
|
1384
|
+
import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
|
|
1385
|
+
var NumberField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props }) => {
|
|
1386
|
+
const handleChange = useCallback7((event) => onValueChange(type, safeParseFloat2(event.target.value) || 0), [
|
|
1387
|
+
type,
|
|
1388
|
+
onValueChange
|
|
1389
|
+
]);
|
|
1390
|
+
return /* @__PURE__ */ React9.createElement(FormFieldWrapper, {
|
|
1391
|
+
readonly,
|
|
1392
|
+
...props
|
|
1393
|
+
}, ({ value: value3 = "" }) => /* @__PURE__ */ React9.createElement(Input5.TextInput, {
|
|
1394
|
+
type: "number",
|
|
1395
|
+
disabled: !!readonly,
|
|
1396
|
+
placeholder,
|
|
1397
|
+
value: value3,
|
|
1398
|
+
onChange: handleChange,
|
|
1399
|
+
onBlur
|
|
1400
|
+
}));
|
|
1567
1401
|
};
|
|
1568
1402
|
|
|
1569
|
-
// src/components/Form/RefField.tsx
|
|
1570
|
-
import { useSignals as _useSignals11 } from "@preact-signals/safe-react/tracking";
|
|
1403
|
+
// src/components/Form/fields/RefField.tsx
|
|
1571
1404
|
import "@dxos/lit-ui/dx-tag-picker.pcss";
|
|
1572
|
-
import React11, { useCallback as
|
|
1573
|
-
import {
|
|
1574
|
-
import {
|
|
1405
|
+
import React11, { useCallback as useCallback9, useMemo as useMemo6 } from "react";
|
|
1406
|
+
import { Entity, Filter, Ref as Ref2, Type } from "@dxos/echo";
|
|
1407
|
+
import { ReferenceAnnotationId } from "@dxos/echo/internal";
|
|
1408
|
+
import { useQuery, useSchema as useSchema$ } from "@dxos/echo-react";
|
|
1409
|
+
import { findAnnotation } from "@dxos/effect";
|
|
1575
1410
|
import { DXN } from "@dxos/keys";
|
|
1576
|
-
import { DxAnchor
|
|
1577
|
-
import { Button
|
|
1578
|
-
import { descriptionText, mx as
|
|
1579
|
-
import { isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
1411
|
+
import { DxAnchor } from "@dxos/lit-ui/react";
|
|
1412
|
+
import { Button, Icon as Icon2, Input as Input6, useTranslation as useTranslation6 } from "@dxos/react-ui";
|
|
1413
|
+
import { descriptionText, mx as mx3 } from "@dxos/ui-theme";
|
|
1580
1414
|
|
|
1581
1415
|
// src/components/ObjectPicker/ObjectPicker.tsx
|
|
1582
|
-
import {
|
|
1583
|
-
import
|
|
1584
|
-
import {
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
const [showForm, setShowForm] = useState5(false);
|
|
1592
|
-
const handleFormSave = useCallback9((values) => {
|
|
1593
|
-
onCreate?.(values);
|
|
1594
|
-
setShowForm(false);
|
|
1595
|
-
setSearchString("");
|
|
1596
|
-
}, [
|
|
1597
|
-
onCreate
|
|
1598
|
-
]);
|
|
1599
|
-
const handleFormCancel = useCallback9(() => {
|
|
1600
|
-
setShowForm(false);
|
|
1601
|
-
setSearchString("");
|
|
1602
|
-
}, []);
|
|
1603
|
-
const handleClick = useCallback9((event) => {
|
|
1604
|
-
if (createSchema && event.target.closest('[data-value="__create__"]')) {
|
|
1605
|
-
event.stopPropagation();
|
|
1606
|
-
event.preventDefault();
|
|
1607
|
-
setShowForm(true);
|
|
1608
|
-
}
|
|
1609
|
-
}, [
|
|
1610
|
-
createSchema
|
|
1611
|
-
]);
|
|
1612
|
-
const handleKeyDown = useCallback9((event) => {
|
|
1613
|
-
if (event.key === "Enter" && createSchema && event.currentTarget.querySelector('[role="option"][aria-selected="true"][data-value="__create__"]')) {
|
|
1614
|
-
event.stopPropagation();
|
|
1615
|
-
event.preventDefault();
|
|
1616
|
-
setShowForm(true);
|
|
1617
|
-
}
|
|
1618
|
-
}, [
|
|
1619
|
-
createSchema
|
|
1620
|
-
]);
|
|
1621
|
-
const labelById = useMemo4(() => options.reduce((acc, option) => {
|
|
1622
|
-
acc[option.id.toLowerCase()] = option.label.toLowerCase();
|
|
1623
|
-
return acc;
|
|
1624
|
-
}, {}), [
|
|
1625
|
-
options
|
|
1626
|
-
]);
|
|
1627
|
-
return /* @__PURE__ */ React10.createElement(Combobox.Content, {
|
|
1628
|
-
...props,
|
|
1629
|
-
ref,
|
|
1630
|
-
filter: (value2, search) => value2 === "__create__" || labelById[value2]?.includes(search.toLowerCase()) ? 1 : 0,
|
|
1631
|
-
onClickCapture: handleClick,
|
|
1632
|
-
onKeyDownCapture: handleKeyDown
|
|
1633
|
-
}, showForm && createSchema ? /* @__PURE__ */ React10.createElement(Popover.Viewport, null, /* @__PURE__ */ React10.createElement(Form, {
|
|
1634
|
-
schema: createSchema,
|
|
1635
|
-
values: createInitialValuePath ? {
|
|
1636
|
-
[createInitialValuePath]: searchString
|
|
1637
|
-
} : {},
|
|
1638
|
-
onSave: handleFormSave,
|
|
1639
|
-
onCancel: handleFormCancel,
|
|
1640
|
-
testId: "create-referenced-object-form"
|
|
1641
|
-
})) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Combobox.Input, {
|
|
1642
|
-
placeholder: t("ref field combobox input placeholder"),
|
|
1643
|
-
value: searchString,
|
|
1644
|
-
onValueChange: setSearchString,
|
|
1645
|
-
autoFocus: true
|
|
1646
|
-
}), /* @__PURE__ */ React10.createElement(Combobox.List, null, options.map((option) => /* @__PURE__ */ React10.createElement(Combobox.Item, {
|
|
1647
|
-
key: option.id,
|
|
1648
|
-
value: option.id,
|
|
1649
|
-
onSelect: () => onSelect(option.id),
|
|
1650
|
-
classNames: "flex items-center gap-2"
|
|
1651
|
-
}, /* @__PURE__ */ React10.createElement("span", {
|
|
1652
|
-
className: "grow"
|
|
1653
|
-
}, option.label), selectedIds?.includes(option.id) && /* @__PURE__ */ React10.createElement(Icon2, {
|
|
1654
|
-
icon: "ph--check--regular"
|
|
1655
|
-
}))), searchString.length > 0 && createOptionLabel && createOptionIcon && createSchema && onCreate && /* @__PURE__ */ React10.createElement(Combobox.Item, {
|
|
1656
|
-
value: "__create__",
|
|
1657
|
-
classNames: "flex items-center gap-2"
|
|
1658
|
-
}, /* @__PURE__ */ React10.createElement(Icon2, {
|
|
1659
|
-
icon: createOptionIcon
|
|
1660
|
-
}), t(createOptionLabel[0], {
|
|
1416
|
+
import React10, { forwardRef as forwardRef2, useCallback as useCallback8, useState as useState3 } from "react";
|
|
1417
|
+
import { Popover, useTranslation as useTranslation5 } from "@dxos/react-ui";
|
|
1418
|
+
import { Combobox, useSearchListInput, useSearchListResults } from "@dxos/react-ui-searchlist";
|
|
1419
|
+
var CreateItem = ({ createOptionLabel, createOptionIcon, onCreateItemSelect }) => {
|
|
1420
|
+
const { t } = useTranslation5(translationKey);
|
|
1421
|
+
const { query } = useSearchListInput();
|
|
1422
|
+
return /* @__PURE__ */ React10.createElement(Combobox.Item, {
|
|
1423
|
+
value: "__create__",
|
|
1424
|
+
label: t(createOptionLabel[0], {
|
|
1661
1425
|
ns: createOptionLabel[1].ns,
|
|
1662
|
-
text:
|
|
1663
|
-
})
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1426
|
+
text: query
|
|
1427
|
+
}),
|
|
1428
|
+
icon: createOptionIcon,
|
|
1429
|
+
classNames: "flex items-center gap-2",
|
|
1430
|
+
closeOnSelect: false,
|
|
1431
|
+
onSelect: () => {
|
|
1432
|
+
onCreateItemSelect(query);
|
|
1433
|
+
}
|
|
1434
|
+
});
|
|
1435
|
+
};
|
|
1436
|
+
var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, onSelect, onCreate, ...props }, ref) => {
|
|
1437
|
+
const { t } = useTranslation5(translationKey);
|
|
1438
|
+
const [showForm, setShowForm] = useState3(false);
|
|
1439
|
+
const [formInitialValue, setFormInitialValue] = useState3("");
|
|
1440
|
+
const { results, handleSearch } = useSearchListResults({
|
|
1441
|
+
items: options
|
|
1442
|
+
});
|
|
1443
|
+
const handleFormSave = useCallback8((values) => {
|
|
1444
|
+
onCreate?.(values);
|
|
1445
|
+
setShowForm(false);
|
|
1446
|
+
setFormInitialValue("");
|
|
1447
|
+
}, [
|
|
1448
|
+
onCreate
|
|
1449
|
+
]);
|
|
1450
|
+
const handleFormCancel = useCallback8(() => {
|
|
1451
|
+
setShowForm(false);
|
|
1452
|
+
setFormInitialValue("");
|
|
1453
|
+
}, []);
|
|
1454
|
+
const handleKeyDown = useCallback8((event) => {
|
|
1455
|
+
if (event.key === "Enter" && createSchema && event.currentTarget.querySelector('[role="option"][aria-selected="true"][data-value="__create__"]')) {
|
|
1456
|
+
event.stopPropagation();
|
|
1457
|
+
event.preventDefault();
|
|
1458
|
+
const input = event.currentTarget.querySelector('input[type="text"]');
|
|
1459
|
+
const currentQuery = input?.value || "";
|
|
1460
|
+
setFormInitialValue(currentQuery);
|
|
1461
|
+
setShowForm(true);
|
|
1462
|
+
}
|
|
1463
|
+
}, [
|
|
1464
|
+
createSchema
|
|
1465
|
+
]);
|
|
1466
|
+
return /* @__PURE__ */ React10.createElement(Combobox.Content, {
|
|
1467
|
+
...props,
|
|
1468
|
+
ref,
|
|
1469
|
+
onSearch: handleSearch,
|
|
1470
|
+
onKeyDownCapture: handleKeyDown
|
|
1471
|
+
}, showForm && createSchema ? /* @__PURE__ */ React10.createElement(Popover.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Root, {
|
|
1472
|
+
testId: "create-referenced-object-form",
|
|
1473
|
+
schema: createSchema,
|
|
1474
|
+
values: createInitialValuePath ? {
|
|
1475
|
+
[createInitialValuePath]: formInitialValue
|
|
1476
|
+
} : {},
|
|
1477
|
+
onSave: handleFormSave,
|
|
1478
|
+
onCancel: handleFormCancel
|
|
1479
|
+
}, /* @__PURE__ */ React10.createElement(Form.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Content, null, /* @__PURE__ */ React10.createElement(Form.FieldSet, null), /* @__PURE__ */ React10.createElement(Form.Actions, null))))) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Combobox.Input, {
|
|
1480
|
+
placeholder: t("ref field combobox input placeholder"),
|
|
1481
|
+
autoFocus: true
|
|
1482
|
+
}), /* @__PURE__ */ React10.createElement(Combobox.List, null, results.map((option) => /* @__PURE__ */ React10.createElement(Combobox.Item, {
|
|
1483
|
+
key: option.id,
|
|
1484
|
+
value: option.id,
|
|
1485
|
+
label: option.label,
|
|
1486
|
+
checked: selectedIds?.includes(option.id),
|
|
1487
|
+
onSelect: () => onSelect(option.id),
|
|
1488
|
+
classNames: "flex items-center gap-2"
|
|
1489
|
+
})), createOptionLabel && createOptionIcon && createSchema && onCreate && /* @__PURE__ */ React10.createElement(CreateItem, {
|
|
1490
|
+
createOptionLabel,
|
|
1491
|
+
createOptionIcon,
|
|
1492
|
+
onCreateItemSelect: (query) => {
|
|
1493
|
+
setFormInitialValue(query);
|
|
1494
|
+
setShowForm(true);
|
|
1495
|
+
}
|
|
1496
|
+
}))), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
|
|
1667
1497
|
});
|
|
1668
1498
|
ObjectPickerContent.displayName = "ObjectPickerContent";
|
|
1669
1499
|
var ObjectPicker = {
|
|
1670
1500
|
Root: Combobox.Root,
|
|
1501
|
+
Portal: Combobox.Portal,
|
|
1671
1502
|
Trigger: Combobox.Trigger,
|
|
1672
1503
|
VirtualTrigger: Combobox.VirtualTrigger,
|
|
1673
1504
|
Content: ObjectPickerContent
|
|
1674
1505
|
};
|
|
1675
1506
|
|
|
1676
|
-
// src/components/Form/RefField.tsx
|
|
1677
|
-
var
|
|
1507
|
+
// src/components/Form/fields/RefField.tsx
|
|
1508
|
+
var isRefSnapshot = (val) => {
|
|
1678
1509
|
return typeof val === "object" && typeof val?.["/"] === "string";
|
|
1679
1510
|
};
|
|
1680
|
-
var
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
const
|
|
1708
|
-
if (
|
|
1709
|
-
|
|
1710
|
-
const matchingOption = availableOptions.find((option2) => option2.id === dxnString);
|
|
1711
|
-
if (matchingOption) {
|
|
1712
|
-
return matchingOption;
|
|
1713
|
-
}
|
|
1714
|
-
}
|
|
1715
|
-
return void 0;
|
|
1716
|
-
};
|
|
1717
|
-
if (array && Array.isArray(formValue)) {
|
|
1718
|
-
return formValue.map(unknownToRefOption).filter(isNonNullable2) ?? [];
|
|
1719
|
-
}
|
|
1720
|
-
const option = unknownToRefOption(formValue);
|
|
1721
|
-
if (option) {
|
|
1722
|
-
return [
|
|
1723
|
-
option
|
|
1724
|
-
];
|
|
1725
|
-
}
|
|
1726
|
-
return [];
|
|
1727
|
-
}, [
|
|
1728
|
-
getValue3,
|
|
1729
|
-
availableOptions,
|
|
1730
|
-
array
|
|
1731
|
-
]);
|
|
1732
|
-
const handleUpdate = useCallback10((ids) => {
|
|
1733
|
-
if (ids.length === 0) {
|
|
1734
|
-
onValueChange("object", void 0);
|
|
1735
|
-
return;
|
|
1736
|
-
}
|
|
1737
|
-
const refs = ids.map((id) => {
|
|
1738
|
-
const item = availableOptions.find((option) => option.id === id);
|
|
1739
|
-
if (item) {
|
|
1740
|
-
const dxn = DXN.parse(item.id);
|
|
1741
|
-
return Ref.fromDXN(dxn);
|
|
1511
|
+
var defaultGetOptions = (results) => results.map((result) => {
|
|
1512
|
+
const id = Entity.getDXN(result).toString();
|
|
1513
|
+
const label = Entity.getLabel(result);
|
|
1514
|
+
return {
|
|
1515
|
+
id,
|
|
1516
|
+
label: label ?? id
|
|
1517
|
+
};
|
|
1518
|
+
});
|
|
1519
|
+
var defaultResultsHook = (db, typename) => useQuery(db, typename ? typename === Type.getTypename(Type.Obj) ? Filter.everything() : Filter.typename(typename) : Filter.nothing());
|
|
1520
|
+
var RefField = (props) => {
|
|
1521
|
+
const { type, readonly, label, placeholder, layout, getStatus, getValue, createOptionLabel, createOptionIcon, createInitialValuePath, db, resultsHook: useResults = defaultResultsHook, schemaHook: useSchema = useSchema$, getOptions: getOptions2 = defaultGetOptions, onCreate, onValueChange } = props;
|
|
1522
|
+
const { t } = useTranslation6(translationKey);
|
|
1523
|
+
const { status, error } = getStatus();
|
|
1524
|
+
const typename = useMemo6(() => type ? findAnnotation(type, ReferenceAnnotationId)?.typename : void 0, [
|
|
1525
|
+
type
|
|
1526
|
+
]);
|
|
1527
|
+
const results = useResults(db, typename);
|
|
1528
|
+
const options = useMemo6(() => getOptions2(results), [
|
|
1529
|
+
results,
|
|
1530
|
+
getOptions2
|
|
1531
|
+
]);
|
|
1532
|
+
const handleGetValue = useCallback9(() => {
|
|
1533
|
+
const formValue = getValue();
|
|
1534
|
+
const unknownToRefOption = (value3) => {
|
|
1535
|
+
const isRef = Ref2.isRef(value3);
|
|
1536
|
+
if (isRef || isRefSnapshot(value3)) {
|
|
1537
|
+
const dxnString = isRef ? value3.dxn.toString() : value3["/"];
|
|
1538
|
+
const matchingOption = options.find((option) => option.id === dxnString);
|
|
1539
|
+
if (matchingOption) {
|
|
1540
|
+
return matchingOption;
|
|
1742
1541
|
}
|
|
1743
|
-
return null;
|
|
1744
|
-
}).filter(isNonNullable2);
|
|
1745
|
-
if (array) {
|
|
1746
|
-
onValueChange("object", refs);
|
|
1747
|
-
} else {
|
|
1748
|
-
onValueChange("object", refs[0]);
|
|
1749
1542
|
}
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1543
|
+
return void 0;
|
|
1544
|
+
};
|
|
1545
|
+
return unknownToRefOption(formValue);
|
|
1546
|
+
}, [
|
|
1547
|
+
options,
|
|
1548
|
+
getValue
|
|
1549
|
+
]);
|
|
1550
|
+
const handleUpdate = useCallback9((id) => {
|
|
1551
|
+
const item2 = options.find((option) => option.id === id);
|
|
1552
|
+
const ref = item2 ? Ref2.fromDXN(DXN.parse(item2.id)) : void 0;
|
|
1553
|
+
onValueChange(type, ref);
|
|
1554
|
+
}, [
|
|
1555
|
+
options,
|
|
1556
|
+
type,
|
|
1557
|
+
onValueChange
|
|
1558
|
+
]);
|
|
1559
|
+
const item = handleGetValue();
|
|
1560
|
+
const selectedIds = useMemo6(() => item ? [
|
|
1561
|
+
item.id
|
|
1562
|
+
] : [], [
|
|
1563
|
+
item
|
|
1564
|
+
]);
|
|
1565
|
+
const createSchema = useSchema(db, typename);
|
|
1566
|
+
const handleCreate = useCallback9((values) => {
|
|
1567
|
+
if (createSchema && onCreate) {
|
|
1568
|
+
onCreate(createSchema, values);
|
|
1764
1569
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
handleUpdate([
|
|
1782
|
-
id
|
|
1783
|
-
]);
|
|
1784
|
-
}
|
|
1785
|
-
}
|
|
1786
|
-
}, [
|
|
1787
|
-
array,
|
|
1788
|
-
selectedIds,
|
|
1789
|
-
handleUpdate
|
|
1790
|
-
]);
|
|
1791
|
-
return readonly && items.length < 1 ? null : /* @__PURE__ */ React11.createElement(Input7.Root, {
|
|
1792
|
-
validationValence: status
|
|
1793
|
-
}, !inputOnly && /* @__PURE__ */ React11.createElement(InputHeader, {
|
|
1794
|
-
error,
|
|
1795
|
-
label
|
|
1796
|
-
}), /* @__PURE__ */ React11.createElement("div", {
|
|
1797
|
-
"data-no-submit": true
|
|
1798
|
-
}, readonly ? items.length < 1 ? /* @__PURE__ */ React11.createElement("p", {
|
|
1799
|
-
className: mx5(descriptionText, "mbe-2")
|
|
1800
|
-
}, t("empty readonly ref field label")) : items.map((item) => /* @__PURE__ */ React11.createElement(DxAnchor, {
|
|
1801
|
-
key: item.id,
|
|
1802
|
-
refid: item.id,
|
|
1803
|
-
rootclassname: "mie-1"
|
|
1804
|
-
}, item.label)) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Trigger, {
|
|
1805
|
-
asChild: true
|
|
1806
|
-
}, /* @__PURE__ */ React11.createElement(Button2, {
|
|
1807
|
-
variant: "ghost",
|
|
1808
|
-
classNames: "is-full text-start gap-2"
|
|
1809
|
-
}, /* @__PURE__ */ React11.createElement("div", {
|
|
1810
|
-
role: "none",
|
|
1811
|
-
className: "grow"
|
|
1812
|
-
}, items?.length ? items?.map((item) => /* @__PURE__ */ React11.createElement(DxTagPickerItem, {
|
|
1813
|
-
key: item.id,
|
|
1814
|
-
itemId: item.id,
|
|
1815
|
-
label: item.label,
|
|
1816
|
-
...item.hue ? {
|
|
1817
|
-
hue: item.hue
|
|
1818
|
-
} : {},
|
|
1819
|
-
removeLabel: t("remove item label"),
|
|
1820
|
-
onItemClick: (event) => {
|
|
1821
|
-
if (event.action === "remove") {
|
|
1822
|
-
toggleSelect(item.id);
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
})) : /* @__PURE__ */ React11.createElement("span", {
|
|
1826
|
-
className: "text-description"
|
|
1827
|
-
}, placeholder ?? t("ref field placeholder", {
|
|
1828
|
-
count: array ? 99 : 1
|
|
1829
|
-
}))), /* @__PURE__ */ React11.createElement(Icon3, {
|
|
1830
|
-
size: 3,
|
|
1831
|
-
icon: "ph--caret-down--bold"
|
|
1832
|
-
}))), /* @__PURE__ */ React11.createElement(ObjectPicker.Content, {
|
|
1833
|
-
options: availableOptions,
|
|
1834
|
-
selectedIds,
|
|
1835
|
-
onSelect: toggleSelect,
|
|
1836
|
-
createSchema,
|
|
1837
|
-
createOptionLabel,
|
|
1838
|
-
createOptionIcon,
|
|
1839
|
-
createInitialValuePath,
|
|
1840
|
-
onCreate: handleCreate
|
|
1841
|
-
}))), inputOnly && /* @__PURE__ */ React11.createElement(Input7.DescriptionAndValidation, null, error));
|
|
1842
|
-
} finally {
|
|
1843
|
-
_effect.f();
|
|
1570
|
+
}, [
|
|
1571
|
+
createSchema,
|
|
1572
|
+
onCreate
|
|
1573
|
+
]);
|
|
1574
|
+
const handleSelect = useCallback9((id) => {
|
|
1575
|
+
if (item?.id === id) {
|
|
1576
|
+
handleUpdate(void 0);
|
|
1577
|
+
} else {
|
|
1578
|
+
handleUpdate(id);
|
|
1579
|
+
}
|
|
1580
|
+
}, [
|
|
1581
|
+
item,
|
|
1582
|
+
handleUpdate
|
|
1583
|
+
]);
|
|
1584
|
+
if (!typename || (readonly || layout === "static") && !item) {
|
|
1585
|
+
return null;
|
|
1844
1586
|
}
|
|
1587
|
+
return /* @__PURE__ */ React11.createElement(Input6.Root, {
|
|
1588
|
+
validationValence: status
|
|
1589
|
+
}, layout !== "inline" && /* @__PURE__ */ React11.createElement(FormFieldLabel, {
|
|
1590
|
+
error,
|
|
1591
|
+
readonly,
|
|
1592
|
+
label
|
|
1593
|
+
}), /* @__PURE__ */ React11.createElement("div", null, readonly ? !item ? /* @__PURE__ */ React11.createElement("p", {
|
|
1594
|
+
className: mx3(descriptionText, "mbe-2")
|
|
1595
|
+
}, t("empty readonly ref field label")) : /* @__PURE__ */ React11.createElement(DxAnchor, {
|
|
1596
|
+
key: item.id,
|
|
1597
|
+
dxn: item.id,
|
|
1598
|
+
rootclassname: "mie-1"
|
|
1599
|
+
}, item.label) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Trigger, {
|
|
1600
|
+
asChild: true,
|
|
1601
|
+
classNames: "p-0"
|
|
1602
|
+
}, item ? /* @__PURE__ */ React11.createElement("div", {
|
|
1603
|
+
className: "flex gap-2 is-full"
|
|
1604
|
+
}, /* @__PURE__ */ React11.createElement(Input6.Root, {
|
|
1605
|
+
key: item.id
|
|
1606
|
+
}, /* @__PURE__ */ React11.createElement(Input6.TextInput, {
|
|
1607
|
+
value: item.label,
|
|
1608
|
+
readOnly: true,
|
|
1609
|
+
classNames: "is-full"
|
|
1610
|
+
}))) : /* @__PURE__ */ React11.createElement(Button, {
|
|
1611
|
+
classNames: "is-full text-start gap-2"
|
|
1612
|
+
}, /* @__PURE__ */ React11.createElement("div", {
|
|
1613
|
+
role: "none",
|
|
1614
|
+
className: "grow overflow-hidden"
|
|
1615
|
+
}, /* @__PURE__ */ React11.createElement("span", {
|
|
1616
|
+
className: "flex truncate text-description"
|
|
1617
|
+
}, placeholder ?? t("ref field placeholder"))), /* @__PURE__ */ React11.createElement(Icon2, {
|
|
1618
|
+
size: 3,
|
|
1619
|
+
icon: "ph--caret-down--bold"
|
|
1620
|
+
}))), /* @__PURE__ */ React11.createElement(ObjectPicker.Portal, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Content, {
|
|
1621
|
+
classNames: "popover-card-width",
|
|
1622
|
+
options,
|
|
1623
|
+
selectedIds,
|
|
1624
|
+
createSchema: createSchema && omitId(createSchema),
|
|
1625
|
+
createOptionLabel,
|
|
1626
|
+
createOptionIcon,
|
|
1627
|
+
createInitialValuePath,
|
|
1628
|
+
onCreate: handleCreate,
|
|
1629
|
+
onSelect: handleSelect
|
|
1630
|
+
})))), layout === "full" && /* @__PURE__ */ React11.createElement(Input6.DescriptionAndValidation, null, error));
|
|
1845
1631
|
};
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
const handleGetValue = () => {
|
|
1860
|
-
const formValue = getValue3();
|
|
1861
|
-
if (typeof formValue === "string") {
|
|
1862
|
-
return formValue;
|
|
1863
|
-
}
|
|
1864
|
-
if (Ref.isRef(formValue)) {
|
|
1865
|
-
return formValue.dxn.toString();
|
|
1866
|
-
}
|
|
1867
|
-
return void 0;
|
|
1868
|
-
};
|
|
1869
|
-
return /* @__PURE__ */ React11.createElement(TextInput, {
|
|
1870
|
-
type,
|
|
1871
|
-
label,
|
|
1872
|
-
readonly,
|
|
1873
|
-
placeholder,
|
|
1874
|
-
inputOnly,
|
|
1875
|
-
getValue: handleGetValue,
|
|
1876
|
-
onValueChange: handleOnValueChange,
|
|
1877
|
-
...restInputProps
|
|
1878
|
-
});
|
|
1879
|
-
} finally {
|
|
1880
|
-
_effect.f();
|
|
1632
|
+
|
|
1633
|
+
// src/components/Form/fields/SelectField.tsx
|
|
1634
|
+
import React12, { useCallback as useCallback10 } from "react";
|
|
1635
|
+
import { Input as Input7, Select } from "@dxos/react-ui";
|
|
1636
|
+
var SelectField = ({ type, readonly, label, layout, placeholder, options, getStatus, getValue, onValueChange }) => {
|
|
1637
|
+
const { status, error } = getStatus();
|
|
1638
|
+
const value3 = getValue();
|
|
1639
|
+
const handleValueChange = useCallback10((value4) => onValueChange(type, value4), [
|
|
1640
|
+
type,
|
|
1641
|
+
onValueChange
|
|
1642
|
+
]);
|
|
1643
|
+
if ((readonly || layout === "static") && value3 == null) {
|
|
1644
|
+
return null;
|
|
1881
1645
|
}
|
|
1646
|
+
return /* @__PURE__ */ React12.createElement(Input7.Root, {
|
|
1647
|
+
validationValence: status
|
|
1648
|
+
}, layout !== "inline" && /* @__PURE__ */ React12.createElement(FormFieldLabel, {
|
|
1649
|
+
error,
|
|
1650
|
+
readonly,
|
|
1651
|
+
label
|
|
1652
|
+
}), layout === "static" ? /* @__PURE__ */ React12.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value3)?.label ?? String(value3)) : /* @__PURE__ */ React12.createElement(Select.Root, {
|
|
1653
|
+
value: value3,
|
|
1654
|
+
onValueChange: handleValueChange
|
|
1655
|
+
}, /* @__PURE__ */ React12.createElement(Select.TriggerButton, {
|
|
1656
|
+
classNames: "is-full",
|
|
1657
|
+
disabled: !!readonly,
|
|
1658
|
+
placeholder
|
|
1659
|
+
}), /* @__PURE__ */ React12.createElement(Select.Portal, null, /* @__PURE__ */ React12.createElement(Select.Content, null, /* @__PURE__ */ React12.createElement(Select.Viewport, null, options?.map(({ value: value4, label: label2 }) => (
|
|
1660
|
+
// NOTE: Numeric values are converted to and from strings.
|
|
1661
|
+
/* @__PURE__ */ React12.createElement(Select.Option, {
|
|
1662
|
+
key: String(value4),
|
|
1663
|
+
value: String(value4)
|
|
1664
|
+
}, label2 ?? String(value4))
|
|
1665
|
+
))), /* @__PURE__ */ React12.createElement(Select.Arrow, null)))), layout === "full" && /* @__PURE__ */ React12.createElement(Input7.DescriptionAndValidation, null, error));
|
|
1882
1666
|
};
|
|
1883
1667
|
|
|
1884
|
-
// src/components/Form/
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
inputProps: {
|
|
1902
|
-
type,
|
|
1903
|
-
format,
|
|
1904
|
-
label,
|
|
1905
|
-
readonly,
|
|
1906
|
-
placeholder,
|
|
1907
|
-
...inputProps
|
|
1908
|
-
}
|
|
1909
|
-
});
|
|
1910
|
-
if (FoundComponent) {
|
|
1911
|
-
return FoundComponent;
|
|
1912
|
-
}
|
|
1913
|
-
const jsonPath = createJsonPath3(path ?? []);
|
|
1914
|
-
const CustomComponent = Custom?.[jsonPath];
|
|
1915
|
-
if (CustomComponent) {
|
|
1916
|
-
return /* @__PURE__ */ React12.createElement(CustomComponent, {
|
|
1917
|
-
type,
|
|
1918
|
-
format,
|
|
1919
|
-
label,
|
|
1920
|
-
inputOnly: inline,
|
|
1921
|
-
placeholder,
|
|
1922
|
-
readonly,
|
|
1923
|
-
...inputProps
|
|
1924
|
-
});
|
|
1925
|
-
}
|
|
1926
|
-
const refProps = getRefProps(property);
|
|
1927
|
-
if (refProps) {
|
|
1928
|
-
return /* @__PURE__ */ React12.createElement(RefField, {
|
|
1929
|
-
ast: refProps.ast,
|
|
1930
|
-
array: refProps.isArray,
|
|
1931
|
-
type,
|
|
1932
|
-
format,
|
|
1933
|
-
label,
|
|
1934
|
-
placeholder,
|
|
1935
|
-
readonly,
|
|
1936
|
-
inputOnly: inline,
|
|
1937
|
-
onQueryRefOptions,
|
|
1938
|
-
createOptionLabel,
|
|
1939
|
-
createOptionIcon,
|
|
1940
|
-
onCreate,
|
|
1941
|
-
createSchema,
|
|
1942
|
-
createInitialValuePath,
|
|
1943
|
-
...inputProps
|
|
1944
|
-
});
|
|
1945
|
-
}
|
|
1946
|
-
if (array) {
|
|
1947
|
-
return /* @__PURE__ */ React12.createElement(ArrayField, {
|
|
1948
|
-
property,
|
|
1949
|
-
path,
|
|
1950
|
-
inputProps,
|
|
1951
|
-
readonly,
|
|
1952
|
-
Custom
|
|
1953
|
-
});
|
|
1668
|
+
// src/components/Form/fields/SelectOptionField.tsx
|
|
1669
|
+
import React13, { useCallback as useCallback11, useEffect as useEffect6, useRef as useRef3, useState as useState4 } from "react";
|
|
1670
|
+
import { PublicKey } from "@dxos/keys";
|
|
1671
|
+
import { IconButton as IconButton3, Input as Input8, Tag, useTranslation as useTranslation7 } from "@dxos/react-ui";
|
|
1672
|
+
import { List } from "@dxos/react-ui-list";
|
|
1673
|
+
import { HuePicker } from "@dxos/react-ui-pickers";
|
|
1674
|
+
import { hues, osTranslations, subtleHover } from "@dxos/ui-theme";
|
|
1675
|
+
var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueChange }) => {
|
|
1676
|
+
const { t } = useTranslation7(translationKey);
|
|
1677
|
+
const { status, error } = getStatus();
|
|
1678
|
+
const [selected, setSelectedId] = useState4(null);
|
|
1679
|
+
const [isNewOption, setIsNewOption] = useState4(false);
|
|
1680
|
+
const inputRef = useRef3(null);
|
|
1681
|
+
const options = getValue();
|
|
1682
|
+
useEffect6(() => {
|
|
1683
|
+
if (options === void 0) {
|
|
1684
|
+
onValueChange(type, []);
|
|
1954
1685
|
}
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
});
|
|
1686
|
+
}, [
|
|
1687
|
+
options,
|
|
1688
|
+
type,
|
|
1689
|
+
onValueChange
|
|
1690
|
+
]);
|
|
1691
|
+
const randomHue = () => {
|
|
1692
|
+
const usedHues = new Set(options?.map((option) => option.color) ?? []);
|
|
1693
|
+
const unusedHues = hues.filter((hue) => !usedHues.has(hue));
|
|
1694
|
+
if (unusedHues.length > 0) {
|
|
1695
|
+
return unusedHues[Math.floor(Math.random() * unusedHues.length)];
|
|
1966
1696
|
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1697
|
+
const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
|
|
1698
|
+
const availableHues = hues.filter((hue) => !lastThree.has(hue));
|
|
1699
|
+
return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
|
|
1700
|
+
};
|
|
1701
|
+
const handleAdd = useCallback11(() => {
|
|
1702
|
+
const newId = PublicKey.random().truncate();
|
|
1703
|
+
const newOption = {
|
|
1704
|
+
id: newId,
|
|
1705
|
+
title: "",
|
|
1706
|
+
color: randomHue()
|
|
1707
|
+
};
|
|
1708
|
+
onValueChange(type, [
|
|
1709
|
+
...options ?? [],
|
|
1710
|
+
newOption
|
|
1711
|
+
]);
|
|
1712
|
+
setSelectedId(newId);
|
|
1713
|
+
setIsNewOption(true);
|
|
1714
|
+
}, [
|
|
1715
|
+
options,
|
|
1716
|
+
type,
|
|
1717
|
+
onValueChange
|
|
1718
|
+
]);
|
|
1719
|
+
const handleDelete = useCallback11((id) => {
|
|
1720
|
+
const newOptions = options?.filter((option) => option.id !== id) ?? [];
|
|
1721
|
+
onValueChange(type, newOptions);
|
|
1722
|
+
setSelectedId(null);
|
|
1723
|
+
}, [
|
|
1724
|
+
options,
|
|
1725
|
+
type,
|
|
1726
|
+
onValueChange
|
|
1727
|
+
]);
|
|
1728
|
+
const handleMove = useCallback11((from, to) => {
|
|
1729
|
+
if (!options) {
|
|
1730
|
+
return;
|
|
1981
1731
|
}
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
1732
|
+
const newOptions = [
|
|
1733
|
+
...options
|
|
1734
|
+
];
|
|
1735
|
+
const [removed] = newOptions.splice(from, 1);
|
|
1736
|
+
newOptions.splice(to, 0, removed);
|
|
1737
|
+
onValueChange(type, newOptions);
|
|
1738
|
+
}, [
|
|
1739
|
+
options,
|
|
1740
|
+
type,
|
|
1741
|
+
onValueChange
|
|
1742
|
+
]);
|
|
1743
|
+
const handleClick = useCallback11((id) => {
|
|
1744
|
+
setSelectedId((current) => current === id ? null : id);
|
|
1745
|
+
}, []);
|
|
1746
|
+
const handleTitleChange = useCallback11((id) => (e) => {
|
|
1747
|
+
const newOptions = options?.map((o) => o.id === id ? {
|
|
1748
|
+
...o,
|
|
1749
|
+
title: e.target.value
|
|
1750
|
+
} : o);
|
|
1751
|
+
onValueChange(type, newOptions ?? []);
|
|
1752
|
+
}, [
|
|
1753
|
+
options,
|
|
1754
|
+
type,
|
|
1755
|
+
onValueChange
|
|
1756
|
+
]);
|
|
1757
|
+
const handleKeyDown = useCallback11((ev) => {
|
|
1758
|
+
if (ev.key === "Enter") {
|
|
1759
|
+
setSelectedId(null);
|
|
2001
1760
|
}
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
1761
|
+
}, []);
|
|
1762
|
+
const handleColorChange = useCallback11((id) => (hue) => {
|
|
1763
|
+
const newOptions = options?.map((o) => o.id === id ? {
|
|
1764
|
+
...o,
|
|
1765
|
+
color: hue
|
|
1766
|
+
} : o);
|
|
1767
|
+
onValueChange(type, newOptions ?? []);
|
|
1768
|
+
}, [
|
|
1769
|
+
options,
|
|
1770
|
+
type,
|
|
1771
|
+
onValueChange
|
|
1772
|
+
]);
|
|
1773
|
+
useEffect6(() => {
|
|
1774
|
+
if (selected && isNewOption && inputRef.current) {
|
|
1775
|
+
inputRef.current.focus();
|
|
1776
|
+
setIsNewOption(false);
|
|
1777
|
+
}
|
|
1778
|
+
}, [
|
|
1779
|
+
selected,
|
|
1780
|
+
isNewOption
|
|
1781
|
+
]);
|
|
1782
|
+
return /* @__PURE__ */ React13.createElement(Input8.Root, {
|
|
1783
|
+
validationValence: status
|
|
1784
|
+
}, /* @__PURE__ */ React13.createElement(FormFieldLabel, {
|
|
1785
|
+
error,
|
|
1786
|
+
readonly,
|
|
1787
|
+
label
|
|
1788
|
+
}), /* @__PURE__ */ React13.createElement("div", {
|
|
1789
|
+
role: "none"
|
|
1790
|
+
}, options && /* @__PURE__ */ React13.createElement(List.Root, {
|
|
1791
|
+
items: options,
|
|
1792
|
+
isItem: (_item) => true,
|
|
1793
|
+
onMove: readonly ? void 0 : handleMove,
|
|
1794
|
+
readonly: !!readonly
|
|
1795
|
+
}, ({ items }) => /* @__PURE__ */ React13.createElement("div", {
|
|
1796
|
+
role: "list",
|
|
1797
|
+
className: "is-full overflow-auto"
|
|
1798
|
+
}, items?.map((item) => /* @__PURE__ */ React13.createElement("div", {
|
|
1799
|
+
key: item.id
|
|
1800
|
+
}, /* @__PURE__ */ React13.createElement(List.Item, {
|
|
1801
|
+
role: "button",
|
|
1802
|
+
item,
|
|
1803
|
+
classNames: [
|
|
1804
|
+
subtleHover,
|
|
1805
|
+
"flex flex-col cursor-pointer rounded-sm"
|
|
1806
|
+
],
|
|
1807
|
+
"aria-expanded": selected === item.id
|
|
1808
|
+
}, /* @__PURE__ */ React13.createElement("div", {
|
|
1809
|
+
className: "flex items-center"
|
|
1810
|
+
}, /* @__PURE__ */ React13.createElement(List.ItemDragHandle, {
|
|
1811
|
+
disabled: !!readonly
|
|
1812
|
+
}), /* @__PURE__ */ React13.createElement(List.ItemTitle, {
|
|
1813
|
+
onClick: () => handleClick(item.id),
|
|
1814
|
+
classNames: "flex-1"
|
|
1815
|
+
}, /* @__PURE__ */ React13.createElement(Tag, {
|
|
1816
|
+
palette: item.color
|
|
1817
|
+
}, item.title || "\u200B")), /* @__PURE__ */ React13.createElement(IconButton3, {
|
|
1818
|
+
iconOnly: true,
|
|
1819
|
+
variant: "ghost",
|
|
1820
|
+
label: t(selected === item.id ? "collapse label" : "expand label", {
|
|
1821
|
+
ns: osTranslations
|
|
1822
|
+
}),
|
|
1823
|
+
icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
1824
|
+
onClick: () => handleClick(item.id)
|
|
1825
|
+
})), selected === item.id && /* @__PURE__ */ React13.createElement("div", {
|
|
1826
|
+
className: "pli-cardSpacingInline plb-cardSpacingBlock flex flex-col gap-1 density-fine"
|
|
1827
|
+
}, /* @__PURE__ */ React13.createElement(Input8.Label, {
|
|
1828
|
+
classNames: "text-xs"
|
|
1829
|
+
}, t("select option label")), /* @__PURE__ */ React13.createElement("div", {
|
|
1830
|
+
className: "grid grid-cols-[1fr_min-content_min-content] gap-1"
|
|
1831
|
+
}, /* @__PURE__ */ React13.createElement(Input8.TextInput, {
|
|
1832
|
+
disabled: !!readonly,
|
|
1833
|
+
placeholder: t("select option label placeholder"),
|
|
1834
|
+
ref: selected === item.id ? inputRef : void 0,
|
|
1835
|
+
value: item.title,
|
|
1836
|
+
onChange: handleTitleChange(item.id),
|
|
1837
|
+
onKeyDown: handleKeyDown,
|
|
1838
|
+
classNames: "flex-1"
|
|
1839
|
+
}), /* @__PURE__ */ React13.createElement(HuePicker, {
|
|
1840
|
+
disabled: !!readonly,
|
|
1841
|
+
value: item.color,
|
|
1842
|
+
onChange: handleColorChange(item.id)
|
|
1843
|
+
}), /* @__PURE__ */ React13.createElement(IconButton3, {
|
|
1844
|
+
disabled: !!readonly,
|
|
1845
|
+
icon: "ph--trash--fill",
|
|
1846
|
+
iconOnly: true,
|
|
1847
|
+
label: t("select option delete"),
|
|
1848
|
+
onClick: () => handleDelete(item.id)
|
|
1849
|
+
})))))), /* @__PURE__ */ React13.createElement(IconButton3, {
|
|
1850
|
+
variant: "ghost",
|
|
1851
|
+
icon: "ph--plus--regular",
|
|
1852
|
+
label: t("select option add"),
|
|
1853
|
+
onClick: handleAdd,
|
|
1854
|
+
disabled: !!readonly,
|
|
1855
|
+
classNames: "is-full"
|
|
1856
|
+
})))));
|
|
2006
1857
|
};
|
|
2007
|
-
var FormFields = /* @__PURE__ */ forwardRef2(({ classNames, schema, path, filter, sort, projection, readonly, lookupComponent, Custom, onQueryRefOptions, ...props }, forwardRef4) => {
|
|
2008
|
-
var _effect = _useSignals12();
|
|
2009
|
-
try {
|
|
2010
|
-
const values = useFormValues(path);
|
|
2011
|
-
const properties = useMemo6(() => {
|
|
2012
|
-
const props2 = getSchemaProperties2(schema.ast, values);
|
|
2013
|
-
if (projection) {
|
|
2014
|
-
const fieldProjections = projection.getFieldProjections();
|
|
2015
|
-
const hiddenProperties = new Set(projection.getHiddenProperties());
|
|
2016
|
-
const visibleProps = props2.filter((prop) => !hiddenProperties.has(prop.name));
|
|
2017
|
-
const orderedProps = [];
|
|
2018
|
-
for (const fieldProjection of fieldProjections) {
|
|
2019
|
-
const fieldPath = String(fieldProjection.field.path);
|
|
2020
|
-
const prop = visibleProps.find((p) => p.name === fieldPath);
|
|
2021
|
-
if (prop) {
|
|
2022
|
-
orderedProps.push(prop);
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
const projectionPaths = new Set(fieldProjections.map((fp) => String(fp.field.path)));
|
|
2026
|
-
const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name));
|
|
2027
|
-
orderedProps.push(...remainingProps);
|
|
2028
|
-
return orderedProps;
|
|
2029
|
-
}
|
|
2030
|
-
const filtered = filter ? filter(props2) : props2;
|
|
2031
|
-
return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
|
|
2032
|
-
}, [
|
|
2033
|
-
schema,
|
|
2034
|
-
values,
|
|
2035
|
-
filter,
|
|
2036
|
-
sort,
|
|
2037
|
-
projection?.fields
|
|
2038
|
-
]);
|
|
2039
|
-
return /* @__PURE__ */ React12.createElement("div", {
|
|
2040
|
-
role: "form",
|
|
2041
|
-
className: mx6("is-full", classNames),
|
|
2042
|
-
ref: forwardRef4
|
|
2043
|
-
}, properties.map((property) => {
|
|
2044
|
-
return /* @__PURE__ */ React12.createElement(FormField, {
|
|
2045
|
-
key: property.name,
|
|
2046
|
-
property,
|
|
2047
|
-
path: [
|
|
2048
|
-
...path ?? [],
|
|
2049
|
-
property.name
|
|
2050
|
-
],
|
|
2051
|
-
readonly,
|
|
2052
|
-
projection,
|
|
2053
|
-
onQueryRefOptions,
|
|
2054
|
-
lookupComponent,
|
|
2055
|
-
Custom,
|
|
2056
|
-
...props
|
|
2057
|
-
});
|
|
2058
|
-
}).filter(isTruthy));
|
|
2059
|
-
} finally {
|
|
2060
|
-
_effect.f();
|
|
2061
|
-
}
|
|
2062
|
-
});
|
|
2063
1858
|
|
|
2064
|
-
// src/components/Form/
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
}
|
|
1859
|
+
// src/components/Form/fields/TextField.tsx
|
|
1860
|
+
import React14, { useCallback as useCallback12 } from "react";
|
|
1861
|
+
import { Input as Input9 } from "@dxos/react-ui";
|
|
1862
|
+
var TextField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props }) => {
|
|
1863
|
+
const handleChange = useCallback12((event) => onValueChange(type, event.target.value), [
|
|
1864
|
+
type,
|
|
1865
|
+
onValueChange
|
|
1866
|
+
]);
|
|
1867
|
+
return /* @__PURE__ */ React14.createElement(FormFieldWrapper, {
|
|
1868
|
+
readonly,
|
|
1869
|
+
...props
|
|
1870
|
+
}, ({ value: value3 = "" }) => /* @__PURE__ */ React14.createElement(Input9.TextInput, {
|
|
1871
|
+
noAutoFill: true,
|
|
1872
|
+
disabled: !!readonly,
|
|
1873
|
+
placeholder,
|
|
1874
|
+
value: value3,
|
|
1875
|
+
onChange: handleChange,
|
|
1876
|
+
onBlur
|
|
1877
|
+
}));
|
|
1878
|
+
};
|
|
1879
|
+
|
|
1880
|
+
// src/components/Form/fields/TextAreaField.tsx
|
|
1881
|
+
import React15, { useCallback as useCallback13 } from "react";
|
|
1882
|
+
import { Input as Input10 } from "@dxos/react-ui";
|
|
1883
|
+
var TextAreaField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props }) => {
|
|
1884
|
+
const handleChange = useCallback13((event) => onValueChange(type, event.target.value), [
|
|
1885
|
+
type,
|
|
1886
|
+
onValueChange
|
|
1887
|
+
]);
|
|
1888
|
+
return /* @__PURE__ */ React15.createElement(FormFieldWrapper, {
|
|
1889
|
+
readonly,
|
|
1890
|
+
...props
|
|
1891
|
+
}, ({ value: value3 = "" }) => /* @__PURE__ */ React15.createElement(Input10.TextArea, {
|
|
1892
|
+
rows: 3,
|
|
1893
|
+
disabled: !!readonly,
|
|
1894
|
+
placeholder,
|
|
1895
|
+
value: value3,
|
|
1896
|
+
onChange: handleChange,
|
|
1897
|
+
onBlur
|
|
1898
|
+
}));
|
|
1899
|
+
};
|
|
1900
|
+
|
|
1901
|
+
// src/components/Form/fields/TupleField.tsx
|
|
1902
|
+
import React16 from "react";
|
|
1903
|
+
import { Input as Input11 } from "@dxos/react-ui";
|
|
1904
|
+
import { mx as mx4 } from "@dxos/ui-theme";
|
|
1905
|
+
import { safeParseFloat as safeParseFloat3 } from "@dxos/util";
|
|
1906
|
+
var gridCols = [
|
|
1907
|
+
"grid-cols-1",
|
|
1908
|
+
"grid-cols-2",
|
|
1909
|
+
"grid-cols-3",
|
|
1910
|
+
"grid-cols-4"
|
|
1911
|
+
];
|
|
1912
|
+
var TupleField = ({ binding, type, readonly, label, getStatus, getValue, onValueChange, onBlur }) => {
|
|
1913
|
+
const { status, error } = getStatus();
|
|
1914
|
+
const values = getValue() ?? {};
|
|
1915
|
+
return /* @__PURE__ */ React16.createElement(Input11.Root, {
|
|
1916
|
+
validationValence: status
|
|
1917
|
+
}, /* @__PURE__ */ React16.createElement(FormFieldLabel, {
|
|
1918
|
+
error,
|
|
1919
|
+
readonly,
|
|
1920
|
+
label
|
|
1921
|
+
}), /* @__PURE__ */ React16.createElement("div", {
|
|
1922
|
+
className: mx4("grid gap-2", gridCols[binding.length - 1])
|
|
1923
|
+
}, binding.map((prop) => /* @__PURE__ */ React16.createElement(Input11.TextInput, {
|
|
1924
|
+
key: prop,
|
|
1925
|
+
type: "number",
|
|
1926
|
+
disabled: !!readonly,
|
|
1927
|
+
value: values[prop],
|
|
1928
|
+
onChange: (event) => {
|
|
1929
|
+
onValueChange(type, {
|
|
1930
|
+
...values,
|
|
1931
|
+
[prop]: safeParseFloat3(event.target.value, 0)
|
|
1932
|
+
});
|
|
1933
|
+
},
|
|
1934
|
+
onBlur
|
|
1935
|
+
}))));
|
|
2119
1936
|
};
|
|
2120
1937
|
|
|
2121
1938
|
// src/components/FieldEditor/FieldEditor.tsx
|
|
2122
|
-
var
|
|
2123
|
-
var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
1939
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
|
|
1940
|
+
var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCancel }) => {
|
|
1941
|
+
const { t } = useTranslation8(translationKey);
|
|
1942
|
+
const [props, setProps] = useState5(projection.getFieldProjection(field.id).props);
|
|
1943
|
+
useEffect7(() => setProps(projection.getFieldProjection(field.id).props), [
|
|
1944
|
+
field,
|
|
1945
|
+
projection
|
|
1946
|
+
]);
|
|
1947
|
+
const [schemas, setSchemas] = useState5([]);
|
|
1948
|
+
useAsyncEffect(async () => {
|
|
1949
|
+
if (!registry) {
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
const subscription = registry.query().subscribe((query) => setSchemas(query.results), {
|
|
1953
|
+
fire: true
|
|
1954
|
+
});
|
|
1955
|
+
const schemas2 = await registry.query().run();
|
|
1956
|
+
setSchemas(schemas2);
|
|
1957
|
+
return () => subscription?.();
|
|
1958
|
+
}, [
|
|
1959
|
+
registry
|
|
1960
|
+
]);
|
|
1961
|
+
const [referenceSchema, setReferenceSchema] = useState5();
|
|
1962
|
+
useEffect7(() => {
|
|
1963
|
+
setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
|
|
1964
|
+
}, [
|
|
1965
|
+
schemas,
|
|
1966
|
+
props?.referenceSchema
|
|
1967
|
+
]);
|
|
1968
|
+
const [{ fieldSchema }, setFieldSchema] = useState5({
|
|
1969
|
+
fieldSchema: getFormatSchema(props?.format)
|
|
1970
|
+
});
|
|
1971
|
+
const fieldMap = useMemo7(() => ({
|
|
1972
|
+
["format"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
|
|
1973
|
+
...props2,
|
|
1974
|
+
options: FormatEnums.filter((value3) => value3 !== Format4.TypeFormat.None).map((value3) => ({
|
|
1975
|
+
value: value3,
|
|
1976
|
+
label: t(`format ${value3}`)
|
|
1977
|
+
}))
|
|
1978
|
+
}),
|
|
1979
|
+
["referenceSchema"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
|
|
1980
|
+
...props2,
|
|
1981
|
+
options: schemas.map((schema) => ({
|
|
1982
|
+
value: schema.typename
|
|
1983
|
+
}))
|
|
1984
|
+
}),
|
|
1985
|
+
["referencePath"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
|
|
1986
|
+
...props2,
|
|
1987
|
+
options: referenceSchema ? getFormProperties(referenceSchema.ast).sort((a, b) => a.name.toString().localeCompare(b.name.toString())).map((p) => ({
|
|
1988
|
+
value: p.name.toString()
|
|
1989
|
+
})) : []
|
|
1990
|
+
}),
|
|
1991
|
+
["options"]: (props2) => /* @__PURE__ */ React17.createElement(SelectOptionField, props2)
|
|
1992
|
+
}), [
|
|
1993
|
+
t,
|
|
1994
|
+
schemas,
|
|
1995
|
+
referenceSchema
|
|
1996
|
+
]);
|
|
1997
|
+
const propIsNotType = useCallback14((props2) => props2.filter((prop) => prop.name !== "type"), []);
|
|
1998
|
+
const handleValuesChanged = useCallback14((_props) => {
|
|
1999
|
+
setFieldSchema((prev) => {
|
|
2000
|
+
const fieldSchema2 = getFormatSchema(_props.format);
|
|
2001
|
+
if (prev.fieldSchema === fieldSchema2) {
|
|
2002
|
+
return prev;
|
|
2136
2003
|
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
}
|
|
2140
|
-
const schemas2 = await registry.query().run();
|
|
2141
|
-
setSchemas(schemas2);
|
|
2142
|
-
return () => subscription?.();
|
|
2143
|
-
}, [
|
|
2144
|
-
registry
|
|
2145
|
-
]);
|
|
2146
|
-
const [referenceSchema, setReferenceSchema] = useState6();
|
|
2147
|
-
useEffect8(() => {
|
|
2148
|
-
setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
|
|
2149
|
-
}, [
|
|
2150
|
-
schemas,
|
|
2151
|
-
props?.referenceSchema
|
|
2152
|
-
]);
|
|
2153
|
-
const [{ fieldSchema }, setFieldSchema] = useState6({
|
|
2154
|
-
fieldSchema: getFormatSchema(props?.format)
|
|
2004
|
+
return {
|
|
2005
|
+
fieldSchema: fieldSchema2
|
|
2006
|
+
};
|
|
2155
2007
|
});
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
const
|
|
2159
|
-
if (
|
|
2160
|
-
return
|
|
2008
|
+
setReferenceSchema((prev) => {
|
|
2009
|
+
if (_props.referenceSchema !== prev?.typename) {
|
|
2010
|
+
const newSchema = schemas.find((schema) => schema.typename === _props.referenceSchema);
|
|
2011
|
+
if (newSchema) {
|
|
2012
|
+
return newSchema;
|
|
2161
2013
|
}
|
|
2014
|
+
}
|
|
2015
|
+
return prev;
|
|
2016
|
+
});
|
|
2017
|
+
setProps((props2) => {
|
|
2018
|
+
const type = formatToType[_props.format];
|
|
2019
|
+
const additionalProps = formatToAdditionalPropertyAttributes[_props.format];
|
|
2020
|
+
if (props2.type !== type) {
|
|
2162
2021
|
return {
|
|
2163
|
-
|
|
2022
|
+
...props2,
|
|
2023
|
+
..._props,
|
|
2024
|
+
...additionalProps,
|
|
2025
|
+
type
|
|
2164
2026
|
};
|
|
2165
|
-
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
return {
|
|
2180
|
-
...props2,
|
|
2181
|
-
..._props,
|
|
2182
|
-
...additionalProps,
|
|
2183
|
-
type
|
|
2184
|
-
};
|
|
2027
|
+
}
|
|
2028
|
+
return _props;
|
|
2029
|
+
});
|
|
2030
|
+
}, [
|
|
2031
|
+
schemas,
|
|
2032
|
+
props.format,
|
|
2033
|
+
props.referenceSchema
|
|
2034
|
+
]);
|
|
2035
|
+
const handleValidate = useCallback14(({ property }) => {
|
|
2036
|
+
if (property && projection.getFields().find((f) => f.path === property && f.path !== field.path)) {
|
|
2037
|
+
return [
|
|
2038
|
+
{
|
|
2039
|
+
path: "property",
|
|
2040
|
+
message: `property is not unique: '${property}'`
|
|
2185
2041
|
}
|
|
2186
|
-
|
|
2042
|
+
];
|
|
2043
|
+
}
|
|
2044
|
+
}, [
|
|
2045
|
+
projection.getFields(),
|
|
2046
|
+
field
|
|
2047
|
+
]);
|
|
2048
|
+
const handleSave = useCallback14((props2) => {
|
|
2049
|
+
if (view) {
|
|
2050
|
+
Obj3.change(view, () => {
|
|
2051
|
+
projection.setFieldProjection({
|
|
2052
|
+
field,
|
|
2053
|
+
props: props2
|
|
2054
|
+
});
|
|
2187
2055
|
});
|
|
2188
|
-
}
|
|
2189
|
-
schemas,
|
|
2190
|
-
props.format,
|
|
2191
|
-
props.referenceSchema
|
|
2192
|
-
]);
|
|
2193
|
-
const handleValidate = useCallback12(({ property }) => {
|
|
2194
|
-
if (property && projection.fields.find((f) => f.path === property && f.path !== field.path)) {
|
|
2195
|
-
return [
|
|
2196
|
-
{
|
|
2197
|
-
path: "property",
|
|
2198
|
-
message: `property is not unique: '${property}'`
|
|
2199
|
-
}
|
|
2200
|
-
];
|
|
2201
|
-
}
|
|
2202
|
-
}, [
|
|
2203
|
-
projection.fields,
|
|
2204
|
-
field
|
|
2205
|
-
]);
|
|
2206
|
-
const handleSave = useCallback12((props2) => {
|
|
2056
|
+
} else {
|
|
2207
2057
|
projection.setFieldProjection({
|
|
2208
2058
|
field,
|
|
2209
2059
|
props: props2
|
|
2210
2060
|
});
|
|
2211
|
-
onSave();
|
|
2212
|
-
}, [
|
|
2213
|
-
projection,
|
|
2214
|
-
field,
|
|
2215
|
-
onSave
|
|
2216
|
-
]);
|
|
2217
|
-
const handleCancel = useCallback12(() => {
|
|
2218
|
-
requestAnimationFrame(() => onCancel?.());
|
|
2219
|
-
onSave();
|
|
2220
|
-
}, [
|
|
2221
|
-
onSave
|
|
2222
|
-
]);
|
|
2223
|
-
const custom = useMemo7(() => ({
|
|
2224
|
-
["format"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
|
|
2225
|
-
...props2,
|
|
2226
|
-
options: FormatEnums.filter((value2) => value2 !== FormatEnum5.None).map((value2) => ({
|
|
2227
|
-
value: value2,
|
|
2228
|
-
label: t(`format ${value2}`)
|
|
2229
|
-
}))
|
|
2230
|
-
}),
|
|
2231
|
-
["referenceSchema"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
|
|
2232
|
-
...props2,
|
|
2233
|
-
options: schemas.map((schema) => ({
|
|
2234
|
-
value: schema.typename
|
|
2235
|
-
}))
|
|
2236
|
-
}),
|
|
2237
|
-
["referencePath"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
|
|
2238
|
-
...props2,
|
|
2239
|
-
options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
|
|
2240
|
-
value: p.name
|
|
2241
|
-
})) : []
|
|
2242
|
-
}),
|
|
2243
|
-
["options"]: (props2) => /* @__PURE__ */ React14.createElement(SelectOptionInput, props2)
|
|
2244
|
-
}), [
|
|
2245
|
-
t,
|
|
2246
|
-
schemas,
|
|
2247
|
-
referenceSchema
|
|
2248
|
-
]);
|
|
2249
|
-
const propIsNotType = useCallback12((props2) => props2.filter((p) => p.name !== "type"), []);
|
|
2250
|
-
if (!fieldSchema) {
|
|
2251
|
-
log3.warn("invalid format", {
|
|
2252
|
-
props
|
|
2253
|
-
}, {
|
|
2254
|
-
F: __dxlog_file4,
|
|
2255
|
-
L: 180,
|
|
2256
|
-
S: void 0,
|
|
2257
|
-
C: (f, a) => f(...a)
|
|
2258
|
-
});
|
|
2259
|
-
return null;
|
|
2260
2061
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2062
|
+
onSave();
|
|
2063
|
+
}, [
|
|
2064
|
+
projection,
|
|
2065
|
+
field,
|
|
2066
|
+
view,
|
|
2067
|
+
onSave
|
|
2068
|
+
]);
|
|
2069
|
+
const handleCancel = useCallback14(() => {
|
|
2070
|
+
onSave();
|
|
2071
|
+
requestAnimationFrame(() => onCancel?.());
|
|
2072
|
+
}, [
|
|
2073
|
+
onSave
|
|
2074
|
+
]);
|
|
2075
|
+
if (!fieldSchema) {
|
|
2076
|
+
log2.warn("invalid format", {
|
|
2077
|
+
props
|
|
2078
|
+
}, {
|
|
2079
|
+
F: __dxlog_file2,
|
|
2080
|
+
L: 173,
|
|
2081
|
+
S: void 0,
|
|
2082
|
+
C: (f, a) => f(...a)
|
|
2278
2083
|
});
|
|
2279
|
-
|
|
2280
|
-
_effect.f();
|
|
2084
|
+
return null;
|
|
2281
2085
|
}
|
|
2086
|
+
return /* @__PURE__ */ React17.createElement(Form.Root, {
|
|
2087
|
+
key: field.id,
|
|
2088
|
+
fieldMap,
|
|
2089
|
+
autoFocus: true,
|
|
2090
|
+
readonly,
|
|
2091
|
+
schema: fieldSchema,
|
|
2092
|
+
values: props,
|
|
2093
|
+
exclude: propIsNotType,
|
|
2094
|
+
sort: [
|
|
2095
|
+
"property",
|
|
2096
|
+
"format"
|
|
2097
|
+
],
|
|
2098
|
+
onValuesChanged: handleValuesChanged,
|
|
2099
|
+
onValidate: handleValidate,
|
|
2100
|
+
onSave: handleSave,
|
|
2101
|
+
onCancel: handleCancel
|
|
2102
|
+
}, /* @__PURE__ */ React17.createElement(Form.Content, null, /* @__PURE__ */ React17.createElement(Form.FieldSet, null), /* @__PURE__ */ React17.createElement(Form.Actions, null)));
|
|
2103
|
+
};
|
|
2104
|
+
|
|
2105
|
+
// src/components/Settings/Settings.tsx
|
|
2106
|
+
import React18 from "react";
|
|
2107
|
+
import { Button as Button2, Input as Input12, ScrollArea as ScrollArea2, toLocalizedString, useTranslation as useTranslation9 } from "@dxos/react-ui";
|
|
2108
|
+
import { mx as mx5 } from "@dxos/ui-theme";
|
|
2109
|
+
var SETTINGS_ROOT_NAME = "Settings.Root";
|
|
2110
|
+
var SETTINGS_SECTION_NAME = "Settings.Section";
|
|
2111
|
+
var SETTINGS_SECTION_HEADING_NAME = "Settings.SectionHeading";
|
|
2112
|
+
var SETTINGS_GROUP_NAME = "Settings.Group";
|
|
2113
|
+
var SETTINGS_GROUP_BUTTON_NAME = "Settings.GroupButton";
|
|
2114
|
+
var SETTINGS_CONTAINER_NAME = "Settings.Container";
|
|
2115
|
+
var SETTINGS_FRAME_NAME = "Settings.Frame";
|
|
2116
|
+
var SETTINGS_FRAME_ITEM_NAME = "Settings.FrameItem";
|
|
2117
|
+
var SETTINGS_ITEM_NAME = "Settings.Item";
|
|
2118
|
+
var SETTINGS_ITEM_INPUT_NAME = "Settings.ItemInput";
|
|
2119
|
+
var styles = {
|
|
2120
|
+
title: "pbe-trimMd text-baseText text-lg",
|
|
2121
|
+
description: "text-base text-description",
|
|
2122
|
+
grid: "grid grid-cols-1 md:grid-cols-[3fr_2fr] gap-x-trimLg"
|
|
2123
|
+
};
|
|
2124
|
+
var SettingsRoot = ({ children }) => {
|
|
2125
|
+
return /* @__PURE__ */ React18.createElement(ScrollArea2.Root, {
|
|
2126
|
+
orientation: "vertical"
|
|
2127
|
+
}, /* @__PURE__ */ React18.createElement(ScrollArea2.Viewport, {
|
|
2128
|
+
classNames: "p-trimMd"
|
|
2129
|
+
}, children));
|
|
2130
|
+
};
|
|
2131
|
+
SettingsRoot.displayName = SETTINGS_ROOT_NAME;
|
|
2132
|
+
var SettingsSection = ({ title, description, children }) => {
|
|
2133
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(SettingsSectionHeading, {
|
|
2134
|
+
title,
|
|
2135
|
+
description
|
|
2136
|
+
}), /* @__PURE__ */ React18.createElement("div", {
|
|
2137
|
+
className: "is-full pbs-trimMd space-y-trimMd"
|
|
2138
|
+
}, children));
|
|
2139
|
+
};
|
|
2140
|
+
SettingsSection.displayName = SETTINGS_SECTION_NAME;
|
|
2141
|
+
var SettingsSectionHeading = ({ title, description }) => {
|
|
2142
|
+
const { t } = useTranslation9(translationKey);
|
|
2143
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("h2", {
|
|
2144
|
+
className: "pli-trimMd container-max-width text-xl mbs-trimMd mbe-trimMd"
|
|
2145
|
+
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React18.createElement("p", {
|
|
2146
|
+
className: "pli-trimMd mlb-trimMd container-max-width text-description"
|
|
2147
|
+
}, toLocalizedString(description, t)));
|
|
2148
|
+
};
|
|
2149
|
+
SettingsSectionHeading.displayName = SETTINGS_SECTION_HEADING_NAME;
|
|
2150
|
+
var SettingsGroupButton = ({ classNames, ...props }) => {
|
|
2151
|
+
return /* @__PURE__ */ React18.createElement(Button2, {
|
|
2152
|
+
...props,
|
|
2153
|
+
classNames: [
|
|
2154
|
+
"md:col-span-2",
|
|
2155
|
+
classNames
|
|
2156
|
+
]
|
|
2157
|
+
});
|
|
2158
|
+
};
|
|
2159
|
+
SettingsGroupButton.displayName = SETTINGS_GROUP_BUTTON_NAME;
|
|
2160
|
+
var SettingsGroup = ({ children, classNames }) => /* @__PURE__ */ React18.createElement("div", {
|
|
2161
|
+
role: "none",
|
|
2162
|
+
className: mx5("group container-max-width space-y-trimMd", classNames)
|
|
2163
|
+
}, children);
|
|
2164
|
+
SettingsGroup.displayName = SETTINGS_GROUP_NAME;
|
|
2165
|
+
var SettingsFrame = ({ children }) => /* @__PURE__ */ React18.createElement("div", {
|
|
2166
|
+
role: "none",
|
|
2167
|
+
className: mx5("container-max-width p-trimMd", "border border-separator rounded-md")
|
|
2168
|
+
}, children);
|
|
2169
|
+
SettingsFrame.displayName = SETTINGS_FRAME_NAME;
|
|
2170
|
+
var SettingsFrameItem = ({ title, description, children }) => {
|
|
2171
|
+
const { t } = useTranslation9(translationKey);
|
|
2172
|
+
return /* @__PURE__ */ React18.createElement("div", {
|
|
2173
|
+
role: "group",
|
|
2174
|
+
className: "min-is-0"
|
|
2175
|
+
}, /* @__PURE__ */ React18.createElement("h3", {
|
|
2176
|
+
className: "text-lg mbe-2"
|
|
2177
|
+
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React18.createElement("p", {
|
|
2178
|
+
className: "mlb-trimSm md:mbe-0 text-description"
|
|
2179
|
+
}, toLocalizedString(description, t)), children);
|
|
2180
|
+
};
|
|
2181
|
+
SettingsFrameItem.displayName = SETTINGS_FRAME_ITEM_NAME;
|
|
2182
|
+
var SettingsContainer = ({ classNames, children }) => {
|
|
2183
|
+
return /* @__PURE__ */ React18.createElement("div", {
|
|
2184
|
+
role: "none",
|
|
2185
|
+
className: mx5([
|
|
2186
|
+
"container-max-width",
|
|
2187
|
+
"*:first:!mbs-0 *:last:!mbe-0 pli-trimMd plb-trimMd",
|
|
2188
|
+
"border border-separator rounded-md",
|
|
2189
|
+
classNames
|
|
2190
|
+
])
|
|
2191
|
+
}, children);
|
|
2192
|
+
};
|
|
2193
|
+
SettingsContainer.displayName = SETTINGS_CONTAINER_NAME;
|
|
2194
|
+
var SettingsItem = ({ title, description = "", children }) => {
|
|
2195
|
+
const { t } = useTranslation9(translationKey);
|
|
2196
|
+
return /* @__PURE__ */ React18.createElement(SettingsContainer, {
|
|
2197
|
+
classNames: styles.grid
|
|
2198
|
+
}, /* @__PURE__ */ React18.createElement("h3", {
|
|
2199
|
+
className: mx5(styles.title, "md:col-span-2")
|
|
2200
|
+
}, toLocalizedString(title, t)), /* @__PURE__ */ React18.createElement("p", {
|
|
2201
|
+
className: styles.description
|
|
2202
|
+
}, toLocalizedString(description, t)), /* @__PURE__ */ React18.createElement("div", {
|
|
2203
|
+
role: "none",
|
|
2204
|
+
className: "text-end plb-1"
|
|
2205
|
+
}, children));
|
|
2206
|
+
};
|
|
2207
|
+
SettingsItem.displayName = SETTINGS_ITEM_NAME;
|
|
2208
|
+
var SettingsItemInput = ({ title, description = "", children }) => {
|
|
2209
|
+
const { t } = useTranslation9(translationKey);
|
|
2210
|
+
return /* @__PURE__ */ React18.createElement(Input12.Root, null, /* @__PURE__ */ React18.createElement(SettingsContainer, {
|
|
2211
|
+
classNames: styles.grid
|
|
2212
|
+
}, /* @__PURE__ */ React18.createElement(Input12.Label, {
|
|
2213
|
+
classNames: mx5(styles.title, "md:col-span-2")
|
|
2214
|
+
}, toLocalizedString(title, t)), /* @__PURE__ */ React18.createElement(Input12.DescriptionAndValidation, null, /* @__PURE__ */ React18.createElement(Input12.Description, {
|
|
2215
|
+
classNames: styles.description
|
|
2216
|
+
}, toLocalizedString(description, t))), /* @__PURE__ */ React18.createElement("div", {
|
|
2217
|
+
role: "none",
|
|
2218
|
+
className: "text-end plb-1"
|
|
2219
|
+
}, children)));
|
|
2220
|
+
};
|
|
2221
|
+
SettingsItemInput.displayName = SETTINGS_ITEM_INPUT_NAME;
|
|
2222
|
+
var Settings = {
|
|
2223
|
+
Root: SettingsRoot,
|
|
2224
|
+
Section: SettingsSection,
|
|
2225
|
+
SectionHeading: SettingsSectionHeading,
|
|
2226
|
+
Group: SettingsGroup,
|
|
2227
|
+
GroupButton: SettingsGroupButton,
|
|
2228
|
+
Container: SettingsContainer,
|
|
2229
|
+
Frame: SettingsFrame,
|
|
2230
|
+
FrameItem: SettingsFrameItem,
|
|
2231
|
+
Item: SettingsItem,
|
|
2232
|
+
ItemInput: SettingsItemInput
|
|
2282
2233
|
};
|
|
2283
2234
|
|
|
2284
2235
|
// src/components/ViewEditor/ViewEditor.tsx
|
|
2285
|
-
import {
|
|
2236
|
+
import { RegistryContext } from "@effect-atom/atom-react";
|
|
2286
2237
|
import * as Array2 from "effect/Array";
|
|
2287
|
-
import * as
|
|
2288
|
-
import * as
|
|
2289
|
-
import * as
|
|
2290
|
-
import
|
|
2291
|
-
import { QueryAST } from "@dxos/echo";
|
|
2292
|
-
import { EchoSchema,
|
|
2293
|
-
import {
|
|
2294
|
-
import {
|
|
2295
|
-
import { Callout, IconButton as IconButton4, Input as
|
|
2238
|
+
import * as Match2 from "effect/Match";
|
|
2239
|
+
import * as Option4 from "effect/Option";
|
|
2240
|
+
import * as Schema3 from "effect/Schema";
|
|
2241
|
+
import React19, { forwardRef as forwardRef3, useCallback as useCallback15, useContext, useImperativeHandle, useMemo as useMemo8, useState as useState6 } from "react";
|
|
2242
|
+
import { Filter as Filter2, Format as Format5, Obj as Obj4, Query, QueryAST } from "@dxos/echo";
|
|
2243
|
+
import { EchoSchema, isMutable, toJsonSchema } from "@dxos/echo/internal";
|
|
2244
|
+
import { invariant } from "@dxos/invariant";
|
|
2245
|
+
import { useObject } from "@dxos/react-client/echo";
|
|
2246
|
+
import { Callout, IconButton as IconButton4, Input as Input13, useTranslation as useTranslation10 } from "@dxos/react-ui";
|
|
2296
2247
|
import { QueryForm } from "@dxos/react-ui-components";
|
|
2297
2248
|
import { List as List2 } from "@dxos/react-ui-list";
|
|
2298
|
-
import {
|
|
2299
|
-
import {
|
|
2300
|
-
|
|
2301
|
-
var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
|
|
2249
|
+
import { FieldSchema, ProjectionModel, VIEW_FIELD_LIMIT, createEchoChangeCallback, getTypenameFromQuery } from "@dxos/schema";
|
|
2250
|
+
import { mx as mx6, osTranslations as osTranslations2, subtleHover as subtleHover2 } from "@dxos/ui-theme";
|
|
2251
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
|
|
2302
2252
|
var listGrid = "grid grid-cols-[min-content_1fr_min-content_min-content_min-content]";
|
|
2303
2253
|
var listItemGrid = "grid grid-cols-subgrid col-span-5";
|
|
2304
|
-
var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode = "schema", registry, readonly, showHeading = false, types, tags, onQueryChanged, onDelete
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
const
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
schema,
|
|
2314
|
-
JSON.stringify(view.projection)
|
|
2315
|
-
]);
|
|
2316
|
-
useImperativeHandle(forwardedRef, () => projectionModel, [
|
|
2317
|
-
projectionModel
|
|
2318
|
-
]);
|
|
2319
|
-
const [expandedField, setExpandedField] = useState7();
|
|
2320
|
-
const queueTarget = Match.value(view.query.ast).pipe(Match.when({
|
|
2321
|
-
type: "options"
|
|
2322
|
-
}, ({ options }) => {
|
|
2323
|
-
return Option.fromNullable(options.queues).pipe(Option.flatMap((queues) => Array2.head(queues)), Option.getOrUndefined);
|
|
2324
|
-
}), Match.orElse(() => void 0));
|
|
2325
|
-
const viewSchema = useMemo8(() => {
|
|
2326
|
-
const base = Schema2.Struct({
|
|
2327
|
-
query: mode === "schema" ? Format.URL.annotations({
|
|
2328
|
-
title: "Record type"
|
|
2329
|
-
}) : QueryAST.Query.annotations({
|
|
2330
|
-
title: "Query"
|
|
2331
|
-
})
|
|
2332
|
-
});
|
|
2333
|
-
if (mode === "query") {
|
|
2334
|
-
return Schema2.Struct({
|
|
2335
|
-
name: Schema2.optional(Schema2.String.annotations({
|
|
2336
|
-
title: "Name"
|
|
2337
|
-
})),
|
|
2338
|
-
...base.fields,
|
|
2339
|
-
target: Schema2.optional(Schema2.String.annotations({
|
|
2340
|
-
title: "Target Queue"
|
|
2341
|
-
}))
|
|
2342
|
-
}).pipe(Schema2.mutable);
|
|
2343
|
-
}
|
|
2344
|
-
return base.pipe(Schema2.mutable);
|
|
2345
|
-
}, [
|
|
2346
|
-
mode
|
|
2347
|
-
]);
|
|
2348
|
-
const viewValues = useMemo8(() => ({
|
|
2349
|
-
name: view.name,
|
|
2350
|
-
query: mode === "schema" ? getTypenameFromQuery(view.query.ast) : view.query.ast,
|
|
2351
|
-
target: queueTarget
|
|
2352
|
-
}), [
|
|
2353
|
-
view.name,
|
|
2354
|
-
mode,
|
|
2355
|
-
view.query.ast,
|
|
2356
|
-
queueTarget
|
|
2357
|
-
]);
|
|
2358
|
-
const handleToggleField = useCallback13((field) => {
|
|
2359
|
-
setExpandedField((prevExpandedFieldId) => prevExpandedFieldId === field.id ? void 0 : field.id);
|
|
2360
|
-
}, [
|
|
2361
|
-
readonly
|
|
2362
|
-
]);
|
|
2363
|
-
const handleAdd = useCallback13(() => {
|
|
2364
|
-
invariant3(!readonly, void 0, {
|
|
2365
|
-
F: __dxlog_file5,
|
|
2366
|
-
L: 131,
|
|
2367
|
-
S: void 0,
|
|
2368
|
-
A: [
|
|
2369
|
-
"!readonly",
|
|
2370
|
-
""
|
|
2371
|
-
]
|
|
2372
|
-
});
|
|
2373
|
-
const field = projectionModel.createFieldProjection();
|
|
2374
|
-
setExpandedField(field.id);
|
|
2375
|
-
}, [
|
|
2376
|
-
schema,
|
|
2377
|
-
projectionModel,
|
|
2378
|
-
readonly
|
|
2379
|
-
]);
|
|
2380
|
-
const handleUpdate = useCallback13((values) => {
|
|
2381
|
-
invariant3(!readonly, void 0, {
|
|
2382
|
-
F: __dxlog_file5,
|
|
2383
|
-
L: 138,
|
|
2384
|
-
S: void 0,
|
|
2385
|
-
A: [
|
|
2386
|
-
"!readonly",
|
|
2387
|
-
""
|
|
2388
|
-
]
|
|
2389
|
-
});
|
|
2390
|
-
requestAnimationFrame(() => {
|
|
2391
|
-
if ("name" in values && view.name !== values.name) {
|
|
2392
|
-
view.name = values.name;
|
|
2393
|
-
return;
|
|
2394
|
-
}
|
|
2395
|
-
const query = mode === "schema" ? Query.select(Filter2.typename(values.query)).ast : values.query;
|
|
2396
|
-
onQueryChanged?.(query, values.target);
|
|
2397
|
-
});
|
|
2398
|
-
}, [
|
|
2399
|
-
onQueryChanged,
|
|
2400
|
-
readonly,
|
|
2254
|
+
var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode = "schema", registry, readonly, showHeading = false, types, tags, onQueryChanged, onDelete }, forwardedRef) => {
|
|
2255
|
+
const atomRegistry = useContext(RegistryContext);
|
|
2256
|
+
const schemaReadonly = !isMutable(schema);
|
|
2257
|
+
const { t } = useTranslation10(translationKey);
|
|
2258
|
+
const projectionModel = useMemo8(() => {
|
|
2259
|
+
const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
|
|
2260
|
+
const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : void 0);
|
|
2261
|
+
const model = new ProjectionModel({
|
|
2262
|
+
registry: atomRegistry,
|
|
2401
2263
|
view,
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
""
|
|
2432
|
-
|
|
2433
|
-
});
|
|
2264
|
+
baseSchema: jsonSchema,
|
|
2265
|
+
change
|
|
2266
|
+
});
|
|
2267
|
+
return model;
|
|
2268
|
+
}, [
|
|
2269
|
+
atomRegistry,
|
|
2270
|
+
schema,
|
|
2271
|
+
view
|
|
2272
|
+
]);
|
|
2273
|
+
useImperativeHandle(forwardedRef, () => projectionModel, [
|
|
2274
|
+
projectionModel
|
|
2275
|
+
]);
|
|
2276
|
+
const queueTarget = Match2.value(view.query.ast).pipe(Match2.when({
|
|
2277
|
+
type: "options"
|
|
2278
|
+
}, ({ options }) => {
|
|
2279
|
+
return Option4.fromNullable(options.queues).pipe(Option4.flatMap((queues) => Array2.head(queues)), Option4.getOrUndefined);
|
|
2280
|
+
}), Match2.orElse(() => void 0));
|
|
2281
|
+
const viewSchema = useMemo8(() => {
|
|
2282
|
+
const base = Schema3.Struct({
|
|
2283
|
+
query: mode === "schema" ? Format5.URL.annotations({
|
|
2284
|
+
title: "Record type"
|
|
2285
|
+
}) : QueryAST.Query.annotations({
|
|
2286
|
+
title: "Query"
|
|
2287
|
+
})
|
|
2288
|
+
});
|
|
2289
|
+
if (mode === "tag") {
|
|
2290
|
+
return Schema3.Struct({
|
|
2291
|
+
...base.fields,
|
|
2292
|
+
target: Schema3.optional(Schema3.String.annotations({
|
|
2293
|
+
title: "Target Queue"
|
|
2294
|
+
}))
|
|
2295
|
+
}).pipe(Schema3.mutable);
|
|
2296
|
+
}
|
|
2297
|
+
return base.pipe(Schema3.mutable);
|
|
2298
|
+
}, [
|
|
2299
|
+
mode
|
|
2300
|
+
]);
|
|
2301
|
+
const viewValues = useMemo8(() => ({
|
|
2302
|
+
query: mode === "schema" ? getTypenameFromQuery(view.query.ast) : view.query.ast,
|
|
2303
|
+
target: queueTarget
|
|
2304
|
+
}), [
|
|
2305
|
+
mode,
|
|
2306
|
+
view.query.ast,
|
|
2307
|
+
queueTarget
|
|
2308
|
+
]);
|
|
2309
|
+
const fieldMap = useMemo8(() => mode === "tag" ? customFields({
|
|
2310
|
+
types,
|
|
2311
|
+
tags
|
|
2312
|
+
}) : void 0, [
|
|
2313
|
+
mode,
|
|
2314
|
+
types,
|
|
2315
|
+
tags
|
|
2316
|
+
]);
|
|
2317
|
+
const handleUpdate = useCallback15((values) => {
|
|
2318
|
+
requestAnimationFrame(() => {
|
|
2319
|
+
const query = mode === "schema" ? Query.select(Filter2.typename(values.query)).ast : values.query;
|
|
2320
|
+
onQueryChanged?.(query, values.target);
|
|
2321
|
+
});
|
|
2322
|
+
}, [
|
|
2323
|
+
onQueryChanged,
|
|
2324
|
+
view,
|
|
2325
|
+
queueTarget,
|
|
2326
|
+
mode
|
|
2327
|
+
]);
|
|
2328
|
+
const handleDelete = useCallback15((fieldId) => {
|
|
2329
|
+
invariant(!readonly, void 0, {
|
|
2330
|
+
F: __dxlog_file3,
|
|
2331
|
+
L: 155,
|
|
2332
|
+
S: void 0,
|
|
2333
|
+
A: [
|
|
2334
|
+
"!readonly",
|
|
2335
|
+
""
|
|
2336
|
+
]
|
|
2337
|
+
});
|
|
2338
|
+
onDelete?.(fieldId);
|
|
2339
|
+
}, [
|
|
2340
|
+
onDelete,
|
|
2341
|
+
readonly
|
|
2342
|
+
]);
|
|
2343
|
+
return /* @__PURE__ */ React19.createElement("div", {
|
|
2344
|
+
role: "none",
|
|
2345
|
+
className: mx6(classNames)
|
|
2346
|
+
}, schemaReadonly && !readonly && /* @__PURE__ */ React19.createElement(Callout.Root, {
|
|
2347
|
+
valence: "info",
|
|
2348
|
+
classNames: "mlb-cardSpacingBlock"
|
|
2349
|
+
}, /* @__PURE__ */ React19.createElement(Callout.Title, null, t("system schema description"))), /* @__PURE__ */ React19.createElement(Form.Root, {
|
|
2350
|
+
schema: viewSchema,
|
|
2351
|
+
values: viewValues,
|
|
2352
|
+
fieldMap,
|
|
2353
|
+
autoSave: true,
|
|
2354
|
+
onSave: handleUpdate
|
|
2355
|
+
}, /* @__PURE__ */ React19.createElement(Form.FieldSet, null), /* @__PURE__ */ React19.createElement(FormFieldLabel, {
|
|
2356
|
+
label: t("fields label"),
|
|
2357
|
+
asChild: true
|
|
2358
|
+
}), /* @__PURE__ */ React19.createElement(FieldList, {
|
|
2359
|
+
schema,
|
|
2360
|
+
view,
|
|
2361
|
+
registry,
|
|
2362
|
+
readonly,
|
|
2363
|
+
showHeading,
|
|
2364
|
+
onDelete: handleDelete
|
|
2365
|
+
})));
|
|
2366
|
+
});
|
|
2367
|
+
var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDelete }) => {
|
|
2368
|
+
const atomRegistry = useContext(RegistryContext);
|
|
2369
|
+
const schemaReadonly = !isMutable(schema);
|
|
2370
|
+
const { t } = useTranslation10(translationKey);
|
|
2371
|
+
const [viewSnapshot] = useObject(view);
|
|
2372
|
+
const projectionModel = useMemo8(() => {
|
|
2373
|
+
const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
|
|
2374
|
+
const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : void 0);
|
|
2375
|
+
const model = new ProjectionModel({
|
|
2376
|
+
registry: atomRegistry,
|
|
2377
|
+
view,
|
|
2378
|
+
baseSchema: jsonSchema,
|
|
2379
|
+
change
|
|
2380
|
+
});
|
|
2381
|
+
return model;
|
|
2382
|
+
}, [
|
|
2383
|
+
atomRegistry,
|
|
2384
|
+
schema,
|
|
2385
|
+
view
|
|
2386
|
+
]);
|
|
2387
|
+
const [expandedField, setExpandedField] = useState6();
|
|
2388
|
+
const handleAdd = useCallback15(() => {
|
|
2389
|
+
invariant(!readonly, void 0, {
|
|
2390
|
+
F: __dxlog_file3,
|
|
2391
|
+
L: 220,
|
|
2392
|
+
S: void 0,
|
|
2393
|
+
A: [
|
|
2394
|
+
"!readonly",
|
|
2395
|
+
""
|
|
2396
|
+
]
|
|
2397
|
+
});
|
|
2398
|
+
const field = projectionModel.createFieldProjection();
|
|
2399
|
+
setExpandedField(field.id);
|
|
2400
|
+
}, [
|
|
2401
|
+
projectionModel,
|
|
2402
|
+
readonly
|
|
2403
|
+
]);
|
|
2404
|
+
const handleToggleField = useCallback15((field) => {
|
|
2405
|
+
setExpandedField((prevExpandedFieldId) => prevExpandedFieldId === field.id ? void 0 : field.id);
|
|
2406
|
+
}, [
|
|
2407
|
+
readonly
|
|
2408
|
+
]);
|
|
2409
|
+
const handleDelete = useCallback15((fieldId) => {
|
|
2410
|
+
invariant(!readonly, void 0, {
|
|
2411
|
+
F: __dxlog_file3,
|
|
2412
|
+
L: 234,
|
|
2413
|
+
S: void 0,
|
|
2414
|
+
A: [
|
|
2415
|
+
"!readonly",
|
|
2416
|
+
""
|
|
2417
|
+
]
|
|
2418
|
+
});
|
|
2419
|
+
if (fieldId === expandedField) {
|
|
2420
|
+
setExpandedField(void 0);
|
|
2421
|
+
}
|
|
2422
|
+
onDelete?.(fieldId);
|
|
2423
|
+
}, [
|
|
2424
|
+
expandedField,
|
|
2425
|
+
onDelete,
|
|
2426
|
+
readonly
|
|
2427
|
+
]);
|
|
2428
|
+
const handleMove = useCallback15((fromIndex, toIndex) => {
|
|
2429
|
+
invariant(!readonly, void 0, {
|
|
2430
|
+
F: __dxlog_file3,
|
|
2431
|
+
L: 246,
|
|
2432
|
+
S: void 0,
|
|
2433
|
+
A: [
|
|
2434
|
+
"!readonly",
|
|
2435
|
+
""
|
|
2436
|
+
]
|
|
2437
|
+
});
|
|
2438
|
+
Obj4.change(view, (v) => {
|
|
2434
2439
|
const fields = [
|
|
2435
|
-
...
|
|
2440
|
+
...v.projection.fields
|
|
2436
2441
|
];
|
|
2437
2442
|
const [moved] = fields.splice(fromIndex, 1);
|
|
2438
2443
|
fields.splice(toIndex, 0, moved);
|
|
2439
|
-
|
|
2440
|
-
}
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
outerSpacing,
|
|
2481
|
-
Custom: custom
|
|
2482
|
-
}), /* @__PURE__ */ React15.createElement("div", {
|
|
2444
|
+
v.projection.fields = fields;
|
|
2445
|
+
});
|
|
2446
|
+
}, [
|
|
2447
|
+
view,
|
|
2448
|
+
readonly
|
|
2449
|
+
]);
|
|
2450
|
+
const handleClose = useCallback15(() => setExpandedField(void 0), []);
|
|
2451
|
+
const handleHide = useCallback15((fieldId) => {
|
|
2452
|
+
setExpandedField(void 0);
|
|
2453
|
+
projectionModel.hideFieldProjection(fieldId);
|
|
2454
|
+
}, [
|
|
2455
|
+
projectionModel
|
|
2456
|
+
]);
|
|
2457
|
+
const handleShow = useCallback15((property) => {
|
|
2458
|
+
setExpandedField(void 0);
|
|
2459
|
+
projectionModel.showFieldProjection(property);
|
|
2460
|
+
}, [
|
|
2461
|
+
projectionModel
|
|
2462
|
+
]);
|
|
2463
|
+
if (!viewSnapshot) {
|
|
2464
|
+
return null;
|
|
2465
|
+
}
|
|
2466
|
+
return /* @__PURE__ */ React19.createElement(List2.Root, {
|
|
2467
|
+
items: viewSnapshot.projection.fields,
|
|
2468
|
+
isItem: Schema3.is(FieldSchema),
|
|
2469
|
+
getId: (field) => field.id,
|
|
2470
|
+
onMove: readonly ? void 0 : handleMove,
|
|
2471
|
+
readonly
|
|
2472
|
+
}, ({ items: fields }) => /* @__PURE__ */ React19.createElement(React19.Fragment, null, showHeading && /* @__PURE__ */ React19.createElement("h3", {
|
|
2473
|
+
className: "text-sm"
|
|
2474
|
+
}, t("field path label")), /* @__PURE__ */ React19.createElement("div", {
|
|
2475
|
+
role: "list",
|
|
2476
|
+
className: listGrid
|
|
2477
|
+
}, fields?.map((field) => {
|
|
2478
|
+
const hidden = field.visible === false;
|
|
2479
|
+
return /* @__PURE__ */ React19.createElement(List2.Item, {
|
|
2480
|
+
key: field.id,
|
|
2481
|
+
item: field,
|
|
2482
|
+
classNames: listItemGrid,
|
|
2483
|
+
"aria-expanded": expandedField === field.id
|
|
2484
|
+
}, /* @__PURE__ */ React19.createElement("div", {
|
|
2483
2485
|
role: "none",
|
|
2484
|
-
className:
|
|
2485
|
-
}, /* @__PURE__ */
|
|
2486
|
-
|
|
2487
|
-
}
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
},
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
}, field.path), /* @__PURE__ */ React15.createElement(List2.ItemButton, {
|
|
2514
|
-
label: t(hidden ? "show field label" : "hide field label"),
|
|
2515
|
-
"data-testid": hidden ? "show-field-button" : "hide-field-button",
|
|
2516
|
-
icon: hidden ? "ph--eye-closed--regular" : "ph--eye--regular",
|
|
2517
|
-
autoHide: false,
|
|
2518
|
-
disabled: readonly || !hidden && projectionModel.fields.length <= 1,
|
|
2519
|
-
onClick: () => hidden ? handleShow(field.path) : handleHide(field.id)
|
|
2520
|
-
}), mode === "schema" && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(List2.ItemDeleteButton, {
|
|
2521
|
-
label: t("delete field label"),
|
|
2522
|
-
autoHide: false,
|
|
2523
|
-
disabled: readonly || schemaReadonly || view.projection.fields.length <= 1,
|
|
2524
|
-
onClick: () => handleDelete(field.id),
|
|
2525
|
-
"data-testid": "field.delete"
|
|
2526
|
-
}), /* @__PURE__ */ React15.createElement(IconButton4, {
|
|
2527
|
-
iconOnly: true,
|
|
2528
|
-
variant: "ghost",
|
|
2529
|
-
label: t("toggle expand label", {
|
|
2530
|
-
ns: "os"
|
|
2531
|
-
}),
|
|
2532
|
-
icon: expandedField === field.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
2533
|
-
onClick: () => handleToggleField(field)
|
|
2534
|
-
}))), expandedField === field.id && mode === "schema" && /* @__PURE__ */ React15.createElement("div", {
|
|
2535
|
-
role: "none",
|
|
2536
|
-
className: "col-span-5 mbs-1 mbe-1 border border-separator rounded-md"
|
|
2537
|
-
}, /* @__PURE__ */ React15.createElement(FieldEditor, {
|
|
2538
|
-
readonly: readonly || schemaReadonly ? "disabled-input" : false,
|
|
2539
|
-
projection: projectionModel,
|
|
2540
|
-
field,
|
|
2541
|
-
registry,
|
|
2542
|
-
onSave: handleClose
|
|
2543
|
-
})));
|
|
2544
|
-
}))))), !readonly && !expandedField && mode === "schema" && /* @__PURE__ */ React15.createElement("div", {
|
|
2486
|
+
className: mx6(subtleHover2, listItemGrid, "rounded-sm cursor-pointer min-bs-10")
|
|
2487
|
+
}, /* @__PURE__ */ React19.createElement(List2.ItemDragHandle, {
|
|
2488
|
+
disabled: readonly || schemaReadonly
|
|
2489
|
+
}), /* @__PURE__ */ React19.createElement(List2.ItemTitle, {
|
|
2490
|
+
classNames: hidden && "text-subdued",
|
|
2491
|
+
onClick: () => handleToggleField(field)
|
|
2492
|
+
}, field.path), /* @__PURE__ */ React19.createElement(List2.ItemButton, {
|
|
2493
|
+
label: t(hidden ? "show field label" : "hide field label"),
|
|
2494
|
+
"data-testid": hidden ? "show-field-button" : "hide-field-button",
|
|
2495
|
+
icon: hidden ? "ph--eye-closed--regular" : "ph--eye--regular",
|
|
2496
|
+
autoHide: false,
|
|
2497
|
+
disabled: readonly || !hidden && projectionModel.getFields().length <= 1,
|
|
2498
|
+
onClick: () => hidden ? handleShow(field.path) : handleHide(field.id)
|
|
2499
|
+
}), !readonly && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(List2.ItemDeleteButton, {
|
|
2500
|
+
label: t("delete field label"),
|
|
2501
|
+
autoHide: false,
|
|
2502
|
+
disabled: readonly || schemaReadonly || viewSnapshot.projection.fields.length <= 1,
|
|
2503
|
+
onClick: () => handleDelete(field.id),
|
|
2504
|
+
"data-testid": "field.delete"
|
|
2505
|
+
}), /* @__PURE__ */ React19.createElement(IconButton4, {
|
|
2506
|
+
iconOnly: true,
|
|
2507
|
+
variant: "ghost",
|
|
2508
|
+
label: t("toggle expand label", {
|
|
2509
|
+
ns: osTranslations2
|
|
2510
|
+
}),
|
|
2511
|
+
icon: expandedField === field.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
2512
|
+
onClick: () => handleToggleField(field),
|
|
2513
|
+
"data-testid": "field.toggle"
|
|
2514
|
+
}))), expandedField === field.id && !readonly && /* @__PURE__ */ React19.createElement("div", {
|
|
2545
2515
|
role: "none",
|
|
2546
|
-
className:
|
|
2547
|
-
}, /* @__PURE__ */
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
classNames: "is-full"
|
|
2516
|
+
className: "col-span-5 mbs-1 mbe-1 border border-separator rounded-md"
|
|
2517
|
+
}, /* @__PURE__ */ React19.createElement(FieldEditor, {
|
|
2518
|
+
readonly: readonly || schemaReadonly,
|
|
2519
|
+
registry,
|
|
2520
|
+
projection: projectionModel,
|
|
2521
|
+
field,
|
|
2522
|
+
onSave: handleClose
|
|
2554
2523
|
})));
|
|
2555
|
-
}
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
}
|
|
2524
|
+
})), !readonly && !expandedField && /* @__PURE__ */ React19.createElement("div", {
|
|
2525
|
+
role: "none",
|
|
2526
|
+
className: "mlb-cardSpacingBlock"
|
|
2527
|
+
}, /* @__PURE__ */ React19.createElement(IconButton4, {
|
|
2528
|
+
icon: "ph--plus--regular",
|
|
2529
|
+
label: t("add property button label"),
|
|
2530
|
+
onClick: handleAdd,
|
|
2531
|
+
disabled: viewSnapshot.projection.fields.length >= VIEW_FIELD_LIMIT,
|
|
2532
|
+
classNames: "is-full"
|
|
2533
|
+
}))));
|
|
2534
|
+
};
|
|
2559
2535
|
var customFields = ({ types, tags }) => ({
|
|
2560
|
-
query: (
|
|
2561
|
-
const handleChange =
|
|
2562
|
-
|
|
2536
|
+
query: ({ type, readonly, label, getValue, onValueChange }) => {
|
|
2537
|
+
const handleChange = useCallback15((query) => onValueChange(type, query.ast), [
|
|
2538
|
+
onValueChange
|
|
2563
2539
|
]);
|
|
2564
|
-
return /* @__PURE__ */
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2540
|
+
return /* @__PURE__ */ React19.createElement(Input13.Root, null, /* @__PURE__ */ React19.createElement(FormFieldLabel, {
|
|
2541
|
+
readonly,
|
|
2542
|
+
label
|
|
2543
|
+
}), /* @__PURE__ */ React19.createElement(QueryForm, {
|
|
2544
|
+
initialQuery: getValue(),
|
|
2568
2545
|
types,
|
|
2569
2546
|
tags,
|
|
2570
2547
|
onChange: handleChange
|
|
@@ -2572,43 +2549,40 @@ var customFields = ({ types, tags }) => ({
|
|
|
2572
2549
|
}
|
|
2573
2550
|
});
|
|
2574
2551
|
export {
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
ControlFrameItem,
|
|
2578
|
-
ControlGroup,
|
|
2579
|
-
ControlGroupButton,
|
|
2580
|
-
ControlItem,
|
|
2581
|
-
ControlItemInput,
|
|
2582
|
-
ControlPage,
|
|
2583
|
-
ControlSection,
|
|
2584
|
-
ControlSectionHeading,
|
|
2552
|
+
ArrayField,
|
|
2553
|
+
BooleanField,
|
|
2585
2554
|
FieldEditor,
|
|
2586
2555
|
Form,
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2556
|
+
FormFieldErrorBoundary,
|
|
2557
|
+
FormFieldLabel,
|
|
2558
|
+
FormFieldWrapper,
|
|
2559
|
+
GeoPointField,
|
|
2560
|
+
MarkdownField,
|
|
2561
|
+
NumberField,
|
|
2592
2562
|
ObjectPicker,
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2563
|
+
RefField,
|
|
2564
|
+
SelectField,
|
|
2565
|
+
SelectOptionField,
|
|
2566
|
+
Settings,
|
|
2567
|
+
TextAreaField,
|
|
2568
|
+
TextField,
|
|
2569
|
+
TupleField,
|
|
2597
2570
|
ViewEditor,
|
|
2598
2571
|
cellClassesForFieldType,
|
|
2599
|
-
controlItemClasses,
|
|
2600
|
-
findArrayElementType,
|
|
2601
2572
|
formatForDisplay,
|
|
2602
2573
|
formatForEditing,
|
|
2574
|
+
getDefaultValue,
|
|
2575
|
+
getFormProperties,
|
|
2603
2576
|
getRefProps,
|
|
2577
|
+
omitId,
|
|
2604
2578
|
parseValue,
|
|
2605
2579
|
pathNotUniqueError,
|
|
2580
|
+
setValueEchoAware,
|
|
2606
2581
|
translations,
|
|
2607
|
-
useForm,
|
|
2608
2582
|
useFormContext,
|
|
2583
|
+
useFormFieldState,
|
|
2584
|
+
useFormHandler,
|
|
2609
2585
|
useFormValues,
|
|
2610
|
-
|
|
2611
|
-
useQueryRefOptions,
|
|
2612
|
-
useRefQueryLookupHandler
|
|
2586
|
+
useKeyHandler
|
|
2613
2587
|
};
|
|
2614
2588
|
//# sourceMappingURL=index.mjs.map
|