@dxos/react-ui-form 0.8.1-main.ae460ac → 0.8.1-staging.31c3ee1
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 +672 -499
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +744 -565
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +672 -499
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/ControlSection.d.ts +20 -0
- package/dist/types/src/components/ControlSection.d.ts.map +1 -0
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +2 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/Form/ArrayField.d.ts +2 -1
- package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/Defaults.d.ts +6 -5
- package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +2 -2
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +9 -9
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormActions.d.ts +2 -1
- package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContent.d.ts +3 -2
- package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContext.d.ts +1 -1
- package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
- package/dist/types/src/components/Form/Input.d.ts +3 -3
- package/dist/types/src/components/Form/Input.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +2 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +2 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts +2 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/index.d.ts +1 -2
- package/dist/types/src/components/Form/index.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/Test.stories.d.ts +2 -1
- package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +6 -5
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/Form.d.ts +2 -1
- package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/Form.stories.d.ts +2 -1
- package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/FormInput.d.ts +2 -2
- package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +3 -3
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/field.d.ts +0 -1
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/package.json +26 -26
- package/src/components/ControlSection.tsx +113 -0
- package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
- package/src/components/Form/Form.stories.tsx +2 -2
- package/src/components/Form/Input.tsx +1 -1
- package/src/components/Form/custom/SelectOptionsInput.tsx +5 -1
- package/src/components/Form/index.ts +1 -3
- package/src/components/ViewEditor/ViewEditor.stories.tsx +1 -1
- package/src/components/ViewEditor/ViewEditor.tsx +105 -20
- package/src/components/index.ts +1 -1
- package/src/hooks/useForm.ts +10 -1
- package/src/translations.ts +1 -0
- package/src/util/field.ts +4 -4
- package/src/util/formatting.ts +9 -10
|
@@ -7,6 +7,7 @@ var translations_default = [
|
|
|
7
7
|
"en-US": {
|
|
8
8
|
[translationKey]: {
|
|
9
9
|
"fields label": "Fields",
|
|
10
|
+
"hidden fields label": "Hidden Fields",
|
|
10
11
|
// TODO(burdon): Standardize field/property.
|
|
11
12
|
"button add property": "Add property",
|
|
12
13
|
"field property label": "Property",
|
|
@@ -100,289 +101,81 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
|
|
|
100
101
|
return primary;
|
|
101
102
|
};
|
|
102
103
|
|
|
103
|
-
// packages/ui/react-ui-form/src/components/
|
|
104
|
-
import
|
|
105
|
-
import {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
import { getValue as getValue2 } from "@dxos/echo-schema";
|
|
114
|
-
import { createJsonPath as createJsonPath2 } from "@dxos/effect";
|
|
115
|
-
|
|
116
|
-
// packages/ui/react-ui-form/src/hooks/useForm.ts
|
|
117
|
-
import { SchemaAST as AST } from "effect";
|
|
118
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
119
|
-
import { getValue, setValue } from "@dxos/echo-schema";
|
|
120
|
-
import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
|
|
121
|
-
import { invariant } from "@dxos/invariant";
|
|
122
|
-
import { log } from "@dxos/log";
|
|
123
|
-
import { validateSchema } from "@dxos/schema";
|
|
124
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
125
|
-
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
126
|
-
invariant(AST.isTypeLiteral(schema.ast), void 0, {
|
|
127
|
-
F: __dxlog_file,
|
|
128
|
-
L: 93,
|
|
129
|
-
S: void 0,
|
|
130
|
-
A: [
|
|
131
|
-
"AST.isTypeLiteral(schema.ast)",
|
|
132
|
-
""
|
|
133
|
-
]
|
|
134
|
-
});
|
|
135
|
-
const [values, setValues] = useState(initialValues);
|
|
136
|
-
useEffect(() => {
|
|
137
|
-
setValues(initialValues);
|
|
138
|
-
}, [
|
|
139
|
-
initialValues
|
|
140
|
-
]);
|
|
141
|
-
const [touched, setTouched] = useState(createKeySet(initialValues, false));
|
|
142
|
-
const [changed, setChanged] = useState(createKeySet(initialValues, false));
|
|
143
|
-
const [errors, setErrors] = useState({});
|
|
144
|
-
const [saving, setSaving] = useState(false);
|
|
145
|
-
const validate = useCallback((values2) => {
|
|
146
|
-
let errors2 = validateSchema(schema, values2) ?? [];
|
|
147
|
-
if (errors2.length === 0 && onValidate) {
|
|
148
|
-
const validatedValues = values2;
|
|
149
|
-
errors2 = onValidate(validatedValues) ?? [];
|
|
150
|
-
}
|
|
151
|
-
setErrors(flatMap(errors2));
|
|
152
|
-
const valid = errors2.length === 0;
|
|
153
|
-
return valid;
|
|
154
|
-
}, [
|
|
155
|
-
schema,
|
|
156
|
-
onValidate
|
|
157
|
-
]);
|
|
158
|
-
const [schemaDirty, setSchemaDirty] = useState(false);
|
|
159
|
-
useEffect(() => setSchemaDirty(true), [
|
|
160
|
-
schema
|
|
161
|
-
]);
|
|
162
|
-
useEffect(() => {
|
|
163
|
-
if (schemaDirty) {
|
|
164
|
-
validate(values);
|
|
165
|
-
setSchemaDirty(false);
|
|
166
|
-
}
|
|
167
|
-
}, [
|
|
168
|
-
values,
|
|
169
|
-
schemaDirty
|
|
170
|
-
]);
|
|
171
|
-
const formIsValid = useMemo(() => {
|
|
172
|
-
return Object.keys(errors).length === 0;
|
|
173
|
-
}, [
|
|
174
|
-
errors
|
|
175
|
-
]);
|
|
176
|
-
const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors.
|
|
177
|
-
!Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
|
|
178
|
-
touched,
|
|
179
|
-
errors,
|
|
180
|
-
saving
|
|
181
|
-
]);
|
|
182
|
-
const handleSave = useCallback(async () => {
|
|
183
|
-
if (validate(values)) {
|
|
184
|
-
setSaving(true);
|
|
185
|
-
try {
|
|
186
|
-
await onSave?.(values, {
|
|
187
|
-
changed
|
|
188
|
-
});
|
|
189
|
-
} finally {
|
|
190
|
-
setSaving(false);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}, [
|
|
194
|
-
values,
|
|
195
|
-
validate,
|
|
196
|
-
onSave,
|
|
197
|
-
changed
|
|
198
|
-
]);
|
|
199
|
-
const getStatus = useCallback((path) => {
|
|
200
|
-
const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
|
|
201
|
-
const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
|
|
202
|
-
return {
|
|
203
|
-
status: matchingError ? "error" : void 0,
|
|
204
|
-
error: matchingError ? matchingError[1] : void 0
|
|
205
|
-
};
|
|
206
|
-
}, [
|
|
207
|
-
errors
|
|
208
|
-
]);
|
|
209
|
-
const getFormValue = useCallback((path) => {
|
|
210
|
-
return getValue(values, createJsonPath(path));
|
|
211
|
-
}, [
|
|
212
|
-
values
|
|
213
|
-
]);
|
|
214
|
-
const onValueChange = useCallback((path, type, value) => {
|
|
215
|
-
const jsonPath = createJsonPath(path);
|
|
216
|
-
let parsedValue = value;
|
|
217
|
-
try {
|
|
218
|
-
if (type === "number") {
|
|
219
|
-
parsedValue = parseFloat(value) || 0;
|
|
220
|
-
}
|
|
221
|
-
} catch (err) {
|
|
222
|
-
log.catch(err, void 0, {
|
|
223
|
-
F: __dxlog_file,
|
|
224
|
-
L: 203,
|
|
225
|
-
S: void 0,
|
|
226
|
-
C: (f, a) => f(...a)
|
|
227
|
-
});
|
|
228
|
-
parsedValue = void 0;
|
|
229
|
-
}
|
|
230
|
-
const newValues = {
|
|
231
|
-
...setValue(values, jsonPath, parsedValue)
|
|
232
|
-
};
|
|
233
|
-
setValues(newValues);
|
|
234
|
-
setChanged((prev) => ({
|
|
235
|
-
...prev,
|
|
236
|
-
[jsonPath]: true
|
|
237
|
-
}));
|
|
238
|
-
onValuesChanged?.(newValues);
|
|
239
|
-
const isValid = validate(newValues);
|
|
240
|
-
if (isValid && onValid) {
|
|
241
|
-
onValid(newValues, {
|
|
242
|
-
changed
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
}, [
|
|
246
|
-
values,
|
|
247
|
-
onValuesChanged,
|
|
248
|
-
validate,
|
|
249
|
-
onValid,
|
|
250
|
-
changed
|
|
251
|
-
]);
|
|
252
|
-
const onTouched = useCallback((path) => {
|
|
253
|
-
const jsonPath = createJsonPath(path);
|
|
254
|
-
setTouched((touched2) => ({
|
|
255
|
-
...touched2,
|
|
256
|
-
[jsonPath]: true
|
|
257
|
-
}));
|
|
258
|
-
validate(values);
|
|
259
|
-
}, [
|
|
260
|
-
validate,
|
|
261
|
-
values
|
|
262
|
-
]);
|
|
263
|
-
return useMemo(() => ({
|
|
264
|
-
// State.
|
|
265
|
-
values,
|
|
266
|
-
errors,
|
|
267
|
-
touched,
|
|
268
|
-
changed,
|
|
269
|
-
canSave,
|
|
270
|
-
formIsValid,
|
|
271
|
-
// Actions.
|
|
272
|
-
handleSave,
|
|
273
|
-
// Field utils.
|
|
274
|
-
getStatus,
|
|
275
|
-
getValue: getFormValue,
|
|
276
|
-
onValueChange,
|
|
277
|
-
onTouched
|
|
278
|
-
}), [
|
|
279
|
-
values,
|
|
280
|
-
errors,
|
|
281
|
-
touched,
|
|
282
|
-
changed,
|
|
283
|
-
canSave,
|
|
284
|
-
formIsValid,
|
|
285
|
-
handleSave,
|
|
286
|
-
getStatus,
|
|
287
|
-
getFormValue,
|
|
288
|
-
onValueChange,
|
|
289
|
-
onTouched
|
|
290
|
-
]);
|
|
291
|
-
};
|
|
292
|
-
var createKeySet = (obj, value) => {
|
|
293
|
-
invariant(obj, void 0, {
|
|
294
|
-
F: __dxlog_file,
|
|
295
|
-
L: 265,
|
|
296
|
-
S: void 0,
|
|
297
|
-
A: [
|
|
298
|
-
"obj",
|
|
299
|
-
""
|
|
300
|
-
]
|
|
301
|
-
});
|
|
302
|
-
return Object.keys(obj).reduce((acc, key) => ({
|
|
303
|
-
...acc,
|
|
304
|
-
[key]: value
|
|
305
|
-
}), {});
|
|
306
|
-
};
|
|
307
|
-
var flatMap = (errors) => {
|
|
308
|
-
return errors.reduce((result, { path, message }) => {
|
|
309
|
-
const jsonPath = fromEffectValidationPath(path);
|
|
310
|
-
if (!(jsonPath in result)) {
|
|
311
|
-
result[jsonPath] = message;
|
|
312
|
-
}
|
|
313
|
-
return result;
|
|
314
|
-
}, {});
|
|
104
|
+
// packages/ui/react-ui-form/src/components/ControlSection.tsx
|
|
105
|
+
import React2 from "react";
|
|
106
|
+
import { toLocalizedString, useTranslation, Input as Input2 } from "@dxos/react-ui";
|
|
107
|
+
var ControlSectionHeading = ({ title, description }) => {
|
|
108
|
+
const { t } = useTranslation(translationKey);
|
|
109
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("h2", {
|
|
110
|
+
className: "pli-4 container-max-width text-xl mbs-6 mbe-4"
|
|
111
|
+
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
|
|
112
|
+
className: "pli-4 mlb-4 container-max-width text-description"
|
|
113
|
+
}, toLocalizedString(description, t)));
|
|
315
114
|
};
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
115
|
+
var ControlSection = ({ title, description, children }) => {
|
|
116
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(ControlSectionHeading, {
|
|
117
|
+
title,
|
|
118
|
+
description
|
|
119
|
+
}), children);
|
|
321
120
|
};
|
|
322
|
-
var
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
121
|
+
var ControlGroup = ({ children }) => /* @__PURE__ */ React2.createElement("div", {
|
|
122
|
+
role: "none",
|
|
123
|
+
className: "group container-max-width grid grid-cols-1 md:grid-cols-[1fr_min-content] gap-4"
|
|
124
|
+
}, children);
|
|
125
|
+
var ControlFrame = ({ children }) => /* @__PURE__ */ React2.createElement("div", {
|
|
126
|
+
role: "none",
|
|
127
|
+
className: "p-4 border border-separator rounded-lg container-max-width grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-2 md:gap-8"
|
|
128
|
+
}, children);
|
|
129
|
+
var controlItemClasses = "p-4 border border-separator rounded-lg container-max-width grid md:col-span-2 grid-cols-subgrid items-center";
|
|
130
|
+
var controlItemTitleClasses = "text-lg font-normal mbe-2";
|
|
131
|
+
var controlItemDescriptionClasses = "text-base mlb-2 md:mbe-0 text-description";
|
|
132
|
+
var ControlItem = ({ title, description, children }) => {
|
|
133
|
+
const { t } = useTranslation(translationKey);
|
|
134
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
135
|
+
className: controlItemClasses
|
|
136
|
+
}, /* @__PURE__ */ React2.createElement("div", {
|
|
137
|
+
role: "none"
|
|
138
|
+
}, /* @__PURE__ */ React2.createElement("h3", {
|
|
139
|
+
className: controlItemTitleClasses
|
|
140
|
+
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
|
|
141
|
+
className: controlItemDescriptionClasses
|
|
142
|
+
}, toLocalizedString(description, t))), children);
|
|
326
143
|
};
|
|
327
|
-
var
|
|
328
|
-
const {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}),
|
|
338
|
-
getStatus,
|
|
339
|
-
getFormValue,
|
|
340
|
-
onValueChange,
|
|
341
|
-
onTouched,
|
|
342
|
-
stablePath
|
|
343
|
-
]);
|
|
144
|
+
var ControlItemInput = ({ title, description, children }) => {
|
|
145
|
+
const { t } = useTranslation(translationKey);
|
|
146
|
+
return /* @__PURE__ */ React2.createElement(Input2.Root, null, /* @__PURE__ */ React2.createElement("div", {
|
|
147
|
+
className: controlItemClasses
|
|
148
|
+
}, /* @__PURE__ */ React2.createElement("div", {
|
|
149
|
+
role: "none"
|
|
150
|
+
}, /* @__PURE__ */ React2.createElement(Input2.Label, {
|
|
151
|
+
classNames: controlItemTitleClasses
|
|
152
|
+
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement(Input2.DescriptionAndValidation, null, /* @__PURE__ */ React2.createElement(Input2.Description, {
|
|
153
|
+
classNames: controlItemDescriptionClasses
|
|
154
|
+
}, toLocalizedString(description, t)))), children));
|
|
344
155
|
};
|
|
345
|
-
var
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
const inputOptOut = event.target.hasAttribute("data-no-submit");
|
|
356
|
-
const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
|
|
357
|
-
const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
|
|
358
|
-
if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
|
|
359
|
-
if (!autoSave && form.canSave) {
|
|
360
|
-
form.handleSave();
|
|
361
|
-
}
|
|
362
|
-
if (autoSave && form.formIsValid) {
|
|
363
|
-
event.target.blur();
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
};
|
|
367
|
-
const formElement = formRef.current;
|
|
368
|
-
formElement.addEventListener("keydown", handleKeyDown);
|
|
369
|
-
return () => formElement.removeEventListener("keydown", handleKeyDown);
|
|
370
|
-
}, [
|
|
371
|
-
formRef,
|
|
372
|
-
form.canSave,
|
|
373
|
-
form.formIsValid,
|
|
374
|
-
form.handleSave,
|
|
375
|
-
autoSave
|
|
376
|
-
]);
|
|
377
|
-
return /* @__PURE__ */ React2.createElement(FormContext.Provider, {
|
|
378
|
-
value: form
|
|
379
|
-
}, children);
|
|
156
|
+
var ControlFrameItem = ({ title, description, children }) => {
|
|
157
|
+
const { t } = useTranslation(translationKey);
|
|
158
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
159
|
+
role: "group",
|
|
160
|
+
className: "min-is-0"
|
|
161
|
+
}, /* @__PURE__ */ React2.createElement("h3", {
|
|
162
|
+
className: "text-lg mbe-2"
|
|
163
|
+
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
|
|
164
|
+
className: "mlb-2 md:mbe-0 text-description"
|
|
165
|
+
}, toLocalizedString(description, t)), children);
|
|
380
166
|
};
|
|
381
167
|
|
|
168
|
+
// packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
|
|
169
|
+
import React13, { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo7, useState as useState4 } from "react";
|
|
170
|
+
import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
|
|
171
|
+
import { log as log2 } from "@dxos/log";
|
|
172
|
+
import { useTranslation as useTranslation6 } from "@dxos/react-ui";
|
|
173
|
+
import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
|
|
174
|
+
|
|
382
175
|
// packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
|
|
383
|
-
import React4, { useCallback
|
|
176
|
+
import React4, { useCallback, useState, useEffect, useMemo } from "react";
|
|
384
177
|
import { GeoLocation } from "@dxos/echo-schema";
|
|
385
|
-
import { Input as
|
|
178
|
+
import { Input as Input3, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
386
179
|
import { safeParseFloat } from "@dxos/util";
|
|
387
180
|
|
|
388
181
|
// packages/ui/react-ui-form/src/components/Form/Input.tsx
|
|
@@ -406,27 +199,27 @@ var InputHeader = ({ children, error }) => {
|
|
|
406
199
|
|
|
407
200
|
// packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
|
|
408
201
|
var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
409
|
-
const { t } =
|
|
202
|
+
const { t } = useTranslation2(translationKey);
|
|
410
203
|
const { status, error } = getStatus();
|
|
411
|
-
const geoPoint =
|
|
204
|
+
const geoPoint = useMemo(() => getValue3() ?? [
|
|
412
205
|
0,
|
|
413
206
|
0
|
|
414
207
|
], [
|
|
415
208
|
getValue3
|
|
416
209
|
]);
|
|
417
|
-
const geoLocation =
|
|
210
|
+
const geoLocation = useMemo(() => GeoLocation.fromGeoPoint(geoPoint), [
|
|
418
211
|
geoPoint
|
|
419
212
|
]);
|
|
420
|
-
const [longitudeText, setLongitudeText] =
|
|
421
|
-
const [latitudeText, setLatitudeText] =
|
|
422
|
-
|
|
213
|
+
const [longitudeText, setLongitudeText] = useState(geoLocation.longitude?.toString());
|
|
214
|
+
const [latitudeText, setLatitudeText] = useState(geoLocation.latitude?.toString());
|
|
215
|
+
useEffect(() => {
|
|
423
216
|
const location = GeoLocation.fromGeoPoint(geoPoint);
|
|
424
217
|
setLongitudeText(location.longitude.toString());
|
|
425
218
|
setLatitudeText(location.latitude.toString());
|
|
426
219
|
}, [
|
|
427
220
|
geoPoint
|
|
428
221
|
]);
|
|
429
|
-
const handleCoordinateChange =
|
|
222
|
+
const handleCoordinateChange = useCallback((coordinateType, setText) => (event) => {
|
|
430
223
|
const inputText = event.target.value;
|
|
431
224
|
setText(inputText);
|
|
432
225
|
if (inputText !== "" && inputText !== "-") {
|
|
@@ -449,14 +242,14 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
449
242
|
onValueChange,
|
|
450
243
|
type
|
|
451
244
|
]);
|
|
452
|
-
return /* @__PURE__ */ React4.createElement(
|
|
245
|
+
return /* @__PURE__ */ React4.createElement(Input3.Root, {
|
|
453
246
|
validationValence: status
|
|
454
247
|
}, /* @__PURE__ */ React4.createElement(InputHeader, {
|
|
455
248
|
error
|
|
456
|
-
}, /* @__PURE__ */ React4.createElement(
|
|
249
|
+
}, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
|
|
457
250
|
role: "none",
|
|
458
251
|
className: "grid grid-cols-2 gap-2"
|
|
459
|
-
}, /* @__PURE__ */ React4.createElement(
|
|
252
|
+
}, /* @__PURE__ */ React4.createElement(Input3.TextInput, {
|
|
460
253
|
type: "text",
|
|
461
254
|
pattern: "^-?[0-9]*\\.?[0-9]*$",
|
|
462
255
|
disabled,
|
|
@@ -464,7 +257,7 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
464
257
|
value: latitudeText,
|
|
465
258
|
onChange: handleCoordinateChange("latitude", setLatitudeText),
|
|
466
259
|
onBlur
|
|
467
|
-
}), /* @__PURE__ */ React4.createElement(
|
|
260
|
+
}), /* @__PURE__ */ React4.createElement(Input3.TextInput, {
|
|
468
261
|
type: "text",
|
|
469
262
|
pattern: "^-?[0-9]*\\.?[0-9]*$",
|
|
470
263
|
disabled,
|
|
@@ -476,20 +269,20 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
476
269
|
};
|
|
477
270
|
|
|
478
271
|
// packages/ui/react-ui-form/src/components/Form/custom/SelectOptionsInput.tsx
|
|
479
|
-
import React5, { useCallback as
|
|
272
|
+
import React5, { useCallback as useCallback2, useEffect as useEffect2, useState as useState2, useRef } from "react";
|
|
480
273
|
import { PublicKey } from "@dxos/keys";
|
|
481
|
-
import { Icon as Icon2, IconButton, Input as
|
|
274
|
+
import { Icon as Icon2, IconButton, Input as Input4, Tag, Toolbar, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
482
275
|
import { List } from "@dxos/react-ui-list";
|
|
483
276
|
import { HuePicker } from "@dxos/react-ui-pickers";
|
|
484
277
|
import { hues, mx as mx2 } from "@dxos/react-ui-theme";
|
|
485
278
|
var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
|
|
486
|
-
const [selected, setSelectedId] =
|
|
487
|
-
const [isNewOption, setIsNewOption] =
|
|
279
|
+
const [selected, setSelectedId] = useState2(null);
|
|
280
|
+
const [isNewOption, setIsNewOption] = useState2(false);
|
|
488
281
|
const inputRef = useRef(null);
|
|
489
|
-
const { t } =
|
|
282
|
+
const { t } = useTranslation3(translationKey);
|
|
490
283
|
const { status, error } = getStatus();
|
|
491
284
|
const options = getValue3();
|
|
492
|
-
|
|
285
|
+
useEffect2(() => {
|
|
493
286
|
if (options === void 0) {
|
|
494
287
|
onValueChange(type, []);
|
|
495
288
|
}
|
|
@@ -508,7 +301,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
508
301
|
const availableHues = hues.filter((hue) => !lastThree.has(hue));
|
|
509
302
|
return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
|
|
510
303
|
};
|
|
511
|
-
const handleAdd =
|
|
304
|
+
const handleAdd = useCallback2(() => {
|
|
512
305
|
const newId = PublicKey.random().truncate();
|
|
513
306
|
const newOption = {
|
|
514
307
|
id: newId,
|
|
@@ -526,7 +319,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
526
319
|
type,
|
|
527
320
|
onValueChange
|
|
528
321
|
]);
|
|
529
|
-
const handleDelete =
|
|
322
|
+
const handleDelete = useCallback2((id) => {
|
|
530
323
|
const newOptions = options?.filter((option) => option.id !== id) ?? [];
|
|
531
324
|
onValueChange(type, newOptions);
|
|
532
325
|
setSelectedId(null);
|
|
@@ -535,7 +328,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
535
328
|
type,
|
|
536
329
|
onValueChange
|
|
537
330
|
]);
|
|
538
|
-
const handleMove =
|
|
331
|
+
const handleMove = useCallback2((from, to) => {
|
|
539
332
|
if (!options) {
|
|
540
333
|
return;
|
|
541
334
|
}
|
|
@@ -550,10 +343,10 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
550
343
|
type,
|
|
551
344
|
onValueChange
|
|
552
345
|
]);
|
|
553
|
-
const handleClick =
|
|
346
|
+
const handleClick = useCallback2((id) => {
|
|
554
347
|
setSelectedId((current) => current === id ? null : id);
|
|
555
348
|
}, []);
|
|
556
|
-
const handleTitleChange =
|
|
349
|
+
const handleTitleChange = useCallback2((id) => (e) => {
|
|
557
350
|
const newOptions = options?.map((o) => o.id === id ? {
|
|
558
351
|
...o,
|
|
559
352
|
title: e.target.value
|
|
@@ -564,12 +357,12 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
564
357
|
type,
|
|
565
358
|
onValueChange
|
|
566
359
|
]);
|
|
567
|
-
const handleKeyDown =
|
|
360
|
+
const handleKeyDown = useCallback2((e) => {
|
|
568
361
|
if (e.key === "Enter") {
|
|
569
362
|
setSelectedId(null);
|
|
570
363
|
}
|
|
571
364
|
}, []);
|
|
572
|
-
const handleColorChange =
|
|
365
|
+
const handleColorChange = useCallback2((id) => (hue) => {
|
|
573
366
|
const newOptions = options?.map((o) => o.id === id ? {
|
|
574
367
|
...o,
|
|
575
368
|
color: hue
|
|
@@ -580,7 +373,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
580
373
|
type,
|
|
581
374
|
onValueChange
|
|
582
375
|
]);
|
|
583
|
-
|
|
376
|
+
useEffect2(() => {
|
|
584
377
|
if (selected && isNewOption && inputRef.current) {
|
|
585
378
|
inputRef.current.focus();
|
|
586
379
|
setIsNewOption(false);
|
|
@@ -589,11 +382,11 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
589
382
|
selected,
|
|
590
383
|
isNewOption
|
|
591
384
|
]);
|
|
592
|
-
return /* @__PURE__ */ React5.createElement(
|
|
385
|
+
return /* @__PURE__ */ React5.createElement(Input4.Root, {
|
|
593
386
|
validationValence: status
|
|
594
387
|
}, /* @__PURE__ */ React5.createElement(InputHeader, {
|
|
595
388
|
error
|
|
596
|
-
}, /* @__PURE__ */ React5.createElement(
|
|
389
|
+
}, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement("div", {
|
|
597
390
|
role: "none"
|
|
598
391
|
}, options && /* @__PURE__ */ React5.createElement(List.Root, {
|
|
599
392
|
items: options,
|
|
@@ -621,11 +414,11 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
621
414
|
onClick: () => handleClick(item.id)
|
|
622
415
|
})), selected === item.id && /* @__PURE__ */ React5.createElement("div", {
|
|
623
416
|
className: "mis-4 mbs-2 flex flex-col gap-1"
|
|
624
|
-
}, /* @__PURE__ */ React5.createElement(
|
|
417
|
+
}, /* @__PURE__ */ React5.createElement(Input4.Label, {
|
|
625
418
|
classNames: "text-xs"
|
|
626
419
|
}, t("select option label")), /* @__PURE__ */ React5.createElement("div", {
|
|
627
420
|
className: "flex flex-row items-center gap-1"
|
|
628
|
-
}, /* @__PURE__ */ React5.createElement(
|
|
421
|
+
}, /* @__PURE__ */ React5.createElement(Input4.TextInput, {
|
|
629
422
|
placeholder: t("select option label placeholder"),
|
|
630
423
|
ref: selected === item.id ? inputRef : void 0,
|
|
631
424
|
value: item.title,
|
|
@@ -637,7 +430,8 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
637
430
|
classNames: "p-0 m-0 !is-auto"
|
|
638
431
|
}, /* @__PURE__ */ React5.createElement(HuePicker, {
|
|
639
432
|
value: item.color,
|
|
640
|
-
onChange: handleColorChange(item.id)
|
|
433
|
+
onChange: handleColorChange(item.id),
|
|
434
|
+
rootVariant: "toolbar-button"
|
|
641
435
|
})), /* @__PURE__ */ React5.createElement(IconButton, {
|
|
642
436
|
icon: "ph--trash--fill",
|
|
643
437
|
iconOnly: true,
|
|
@@ -660,7 +454,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
660
454
|
|
|
661
455
|
// packages/ui/react-ui-form/src/components/Form/custom/TupleInput.tsx
|
|
662
456
|
import React6 from "react";
|
|
663
|
-
import { Input as
|
|
457
|
+
import { Input as Input5 } from "@dxos/react-ui";
|
|
664
458
|
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
665
459
|
import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
|
|
666
460
|
var gridCols = [
|
|
@@ -672,13 +466,13 @@ var gridCols = [
|
|
|
672
466
|
var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
673
467
|
const { status, error } = getStatus();
|
|
674
468
|
const values = getValue3() ?? {};
|
|
675
|
-
return /* @__PURE__ */ React6.createElement(
|
|
469
|
+
return /* @__PURE__ */ React6.createElement(Input5.Root, {
|
|
676
470
|
validationValence: status
|
|
677
471
|
}, /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
678
472
|
error
|
|
679
|
-
}, /* @__PURE__ */ React6.createElement(
|
|
473
|
+
}, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement("div", {
|
|
680
474
|
className: mx3("grid gap-2", gridCols[binding.length - 1])
|
|
681
|
-
}, binding.map((prop) => /* @__PURE__ */ React6.createElement(
|
|
475
|
+
}, binding.map((prop) => /* @__PURE__ */ React6.createElement(Input5.TextInput, {
|
|
682
476
|
key: prop,
|
|
683
477
|
type: "number",
|
|
684
478
|
disabled,
|
|
@@ -690,135 +484,417 @@ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValu
|
|
|
690
484
|
onBlur
|
|
691
485
|
}))));
|
|
692
486
|
};
|
|
693
|
-
|
|
694
|
-
// packages/ui/react-ui-form/src/components/Form/Defaults.tsx
|
|
695
|
-
import React7, { useCallback as
|
|
696
|
-
import { Input as
|
|
697
|
-
var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
698
|
-
const { status, error } = getStatus();
|
|
699
|
-
return /* @__PURE__ */ React7.createElement(
|
|
700
|
-
validationValence: status
|
|
701
|
-
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
702
|
-
error
|
|
703
|
-
}, /* @__PURE__ */ React7.createElement(
|
|
704
|
-
disabled,
|
|
705
|
-
placeholder,
|
|
706
|
-
value: getValue3() ?? "",
|
|
707
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
708
|
-
onBlur
|
|
709
|
-
}), inputOnly && /* @__PURE__ */ React7.createElement(
|
|
487
|
+
|
|
488
|
+
// packages/ui/react-ui-form/src/components/Form/Defaults.tsx
|
|
489
|
+
import React7, { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
490
|
+
import { Input as Input6, Select } from "@dxos/react-ui";
|
|
491
|
+
var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
492
|
+
const { status, error } = getStatus();
|
|
493
|
+
return /* @__PURE__ */ React7.createElement(Input6.Root, {
|
|
494
|
+
validationValence: status
|
|
495
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
496
|
+
error
|
|
497
|
+
}, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Input6.TextInput, {
|
|
498
|
+
disabled,
|
|
499
|
+
placeholder,
|
|
500
|
+
value: getValue3() ?? "",
|
|
501
|
+
onChange: (event) => onValueChange(type, event.target.value),
|
|
502
|
+
onBlur
|
|
503
|
+
}), inputOnly && /* @__PURE__ */ React7.createElement(Input6.Validation, null, error));
|
|
504
|
+
};
|
|
505
|
+
var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
506
|
+
const { status, error } = getStatus();
|
|
507
|
+
return /* @__PURE__ */ React7.createElement(Input6.Root, {
|
|
508
|
+
validationValence: status
|
|
509
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
510
|
+
error
|
|
511
|
+
}, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Input6.TextInput, {
|
|
512
|
+
type: "number",
|
|
513
|
+
disabled,
|
|
514
|
+
placeholder,
|
|
515
|
+
value: getValue3() ?? 0,
|
|
516
|
+
onChange: (event) => onValueChange(type, event.target.value),
|
|
517
|
+
onBlur
|
|
518
|
+
}), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
|
|
519
|
+
};
|
|
520
|
+
var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
|
|
521
|
+
const { status, error } = getStatus();
|
|
522
|
+
const checked = Boolean(getValue3());
|
|
523
|
+
return /* @__PURE__ */ React7.createElement(Input6.Root, {
|
|
524
|
+
validationValence: status
|
|
525
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
526
|
+
error
|
|
527
|
+
}, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Input6.Switch, {
|
|
528
|
+
checked,
|
|
529
|
+
onCheckedChange: (value) => onValueChange(type, value)
|
|
530
|
+
}), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
|
|
531
|
+
};
|
|
532
|
+
var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
|
|
533
|
+
const { status, error } = getStatus();
|
|
534
|
+
return /* @__PURE__ */ React7.createElement(Input6.Root, {
|
|
535
|
+
validationValence: status
|
|
536
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
537
|
+
error
|
|
538
|
+
}, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Select.Root, {
|
|
539
|
+
value: getValue3(),
|
|
540
|
+
onValueChange: (value) => onValueChange(type, value)
|
|
541
|
+
}, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
|
|
542
|
+
classNames: "is-full",
|
|
543
|
+
disabled,
|
|
544
|
+
placeholder
|
|
545
|
+
}), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
|
|
546
|
+
// NOTE: Numeric values are converted to and from strings.
|
|
547
|
+
/* @__PURE__ */ React7.createElement(Select.Option, {
|
|
548
|
+
key: String(value),
|
|
549
|
+
value: String(value)
|
|
550
|
+
}, label2 ?? String(value))
|
|
551
|
+
)))))), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
|
|
552
|
+
};
|
|
553
|
+
var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
554
|
+
const { status, error } = getStatus();
|
|
555
|
+
const textareaRef = useRef2(null);
|
|
556
|
+
const adjustHeight = useCallback3(() => {
|
|
557
|
+
const textarea = textareaRef.current;
|
|
558
|
+
if (textarea) {
|
|
559
|
+
textarea.style.blockSize = "auto";
|
|
560
|
+
textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
|
|
561
|
+
}
|
|
562
|
+
}, []);
|
|
563
|
+
useEffect3(() => {
|
|
564
|
+
adjustHeight();
|
|
565
|
+
}, [
|
|
566
|
+
adjustHeight
|
|
567
|
+
]);
|
|
568
|
+
useEffect3(() => {
|
|
569
|
+
adjustHeight();
|
|
570
|
+
}, [
|
|
571
|
+
getValue3(),
|
|
572
|
+
adjustHeight
|
|
573
|
+
]);
|
|
574
|
+
return /* @__PURE__ */ React7.createElement(Input6.Root, {
|
|
575
|
+
validationValence: status
|
|
576
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
577
|
+
error
|
|
578
|
+
}, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Input6.TextArea, {
|
|
579
|
+
ref: textareaRef,
|
|
580
|
+
disabled,
|
|
581
|
+
placeholder,
|
|
582
|
+
value: getValue3() ?? "",
|
|
583
|
+
classNames: "min-bs-auto max-h-40 overflow-auto",
|
|
584
|
+
onChange: (event) => onValueChange(type, event.target.value),
|
|
585
|
+
onBlur,
|
|
586
|
+
style: {
|
|
587
|
+
resize: "none"
|
|
588
|
+
},
|
|
589
|
+
spellCheck: false
|
|
590
|
+
}), inputOnly && /* @__PURE__ */ React7.createElement(Input6.Validation, null, error));
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
594
|
+
import React12, { useEffect as useEffect6, useMemo as useMemo6, useRef as useRef3 } from "react";
|
|
595
|
+
import { mx as mx7 } from "@dxos/react-ui-theme";
|
|
596
|
+
|
|
597
|
+
// packages/ui/react-ui-form/src/components/Form/FormActions.tsx
|
|
598
|
+
import React9 from "react";
|
|
599
|
+
import { IconButton as IconButton2, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
600
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
601
|
+
|
|
602
|
+
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
603
|
+
import React8, { createContext, useContext, useEffect as useEffect5, useMemo as useMemo3 } from "react";
|
|
604
|
+
import { raise } from "@dxos/debug";
|
|
605
|
+
import { getValue as getValue2 } from "@dxos/echo-schema";
|
|
606
|
+
import { createJsonPath as createJsonPath2 } from "@dxos/effect";
|
|
607
|
+
|
|
608
|
+
// packages/ui/react-ui-form/src/hooks/useForm.ts
|
|
609
|
+
import { SchemaAST as AST } from "effect";
|
|
610
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useState as useState3 } from "react";
|
|
611
|
+
import { getValue, setValue } from "@dxos/echo-schema";
|
|
612
|
+
import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
|
|
613
|
+
import { invariant } from "@dxos/invariant";
|
|
614
|
+
import { log } from "@dxos/log";
|
|
615
|
+
import { validateSchema } from "@dxos/schema";
|
|
616
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
617
|
+
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
618
|
+
invariant(AST.isTypeLiteral(schema.ast), void 0, {
|
|
619
|
+
F: __dxlog_file,
|
|
620
|
+
L: 93,
|
|
621
|
+
S: void 0,
|
|
622
|
+
A: [
|
|
623
|
+
"AST.isTypeLiteral(schema.ast)",
|
|
624
|
+
""
|
|
625
|
+
]
|
|
626
|
+
});
|
|
627
|
+
const [values, setValues] = useState3(initialValues);
|
|
628
|
+
useEffect4(() => {
|
|
629
|
+
setValues(initialValues);
|
|
630
|
+
}, [
|
|
631
|
+
initialValues
|
|
632
|
+
]);
|
|
633
|
+
const [touched, setTouched] = useState3(createKeySet(initialValues, false));
|
|
634
|
+
const [changed, setChanged] = useState3(createKeySet(initialValues, false));
|
|
635
|
+
const [errors, setErrors] = useState3({});
|
|
636
|
+
const [saving, setSaving] = useState3(false);
|
|
637
|
+
const validate = useCallback4((values2) => {
|
|
638
|
+
let errors2 = validateSchema(schema, values2) ?? [];
|
|
639
|
+
if (errors2.length === 0 && onValidate) {
|
|
640
|
+
const validatedValues = values2;
|
|
641
|
+
errors2 = onValidate(validatedValues) ?? [];
|
|
642
|
+
}
|
|
643
|
+
setErrors(flatMap(errors2));
|
|
644
|
+
const valid = errors2.length === 0;
|
|
645
|
+
return valid;
|
|
646
|
+
}, [
|
|
647
|
+
schema,
|
|
648
|
+
onValidate
|
|
649
|
+
]);
|
|
650
|
+
const [schemaDirty, setSchemaDirty] = useState3(false);
|
|
651
|
+
useEffect4(() => setSchemaDirty(true), [
|
|
652
|
+
schema
|
|
653
|
+
]);
|
|
654
|
+
useEffect4(() => {
|
|
655
|
+
if (schemaDirty) {
|
|
656
|
+
validate(values);
|
|
657
|
+
setSchemaDirty(false);
|
|
658
|
+
}
|
|
659
|
+
}, [
|
|
660
|
+
values,
|
|
661
|
+
schemaDirty
|
|
662
|
+
]);
|
|
663
|
+
const formIsValid = useMemo2(() => {
|
|
664
|
+
return Object.keys(errors).length === 0;
|
|
665
|
+
}, [
|
|
666
|
+
errors
|
|
667
|
+
]);
|
|
668
|
+
const canSave = useMemo2(() => !saving && // Check if any error paths that are touched have errors.
|
|
669
|
+
!Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
|
|
670
|
+
touched,
|
|
671
|
+
errors,
|
|
672
|
+
saving
|
|
673
|
+
]);
|
|
674
|
+
const handleSave = useCallback4(async () => {
|
|
675
|
+
if (validate(values)) {
|
|
676
|
+
setSaving(true);
|
|
677
|
+
try {
|
|
678
|
+
await onSave?.(values, {
|
|
679
|
+
changed
|
|
680
|
+
});
|
|
681
|
+
} finally {
|
|
682
|
+
setSaving(false);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}, [
|
|
686
|
+
values,
|
|
687
|
+
validate,
|
|
688
|
+
onSave,
|
|
689
|
+
changed
|
|
690
|
+
]);
|
|
691
|
+
const getStatus = useCallback4((path) => {
|
|
692
|
+
const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
|
|
693
|
+
const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
|
|
694
|
+
const isTouched = touched[jsonPath];
|
|
695
|
+
if (!isTouched) {
|
|
696
|
+
return {
|
|
697
|
+
status: void 0,
|
|
698
|
+
error: void 0
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
return {
|
|
702
|
+
status: matchingError ? "error" : void 0,
|
|
703
|
+
error: matchingError ? matchingError[1] : void 0
|
|
704
|
+
};
|
|
705
|
+
}, [
|
|
706
|
+
errors,
|
|
707
|
+
touched
|
|
708
|
+
]);
|
|
709
|
+
const getFormValue = useCallback4((path) => {
|
|
710
|
+
return getValue(values, createJsonPath(path));
|
|
711
|
+
}, [
|
|
712
|
+
values
|
|
713
|
+
]);
|
|
714
|
+
const onValueChange = useCallback4((path, type, value) => {
|
|
715
|
+
const jsonPath = createJsonPath(path);
|
|
716
|
+
let parsedValue = value;
|
|
717
|
+
try {
|
|
718
|
+
if (type === "number") {
|
|
719
|
+
parsedValue = parseFloat(value) || 0;
|
|
720
|
+
}
|
|
721
|
+
} catch (err) {
|
|
722
|
+
log.catch(err, void 0, {
|
|
723
|
+
F: __dxlog_file,
|
|
724
|
+
L: 212,
|
|
725
|
+
S: void 0,
|
|
726
|
+
C: (f, a) => f(...a)
|
|
727
|
+
});
|
|
728
|
+
parsedValue = void 0;
|
|
729
|
+
}
|
|
730
|
+
const newValues = {
|
|
731
|
+
...setValue(values, jsonPath, parsedValue)
|
|
732
|
+
};
|
|
733
|
+
setValues(newValues);
|
|
734
|
+
setChanged((prev) => ({
|
|
735
|
+
...prev,
|
|
736
|
+
[jsonPath]: true
|
|
737
|
+
}));
|
|
738
|
+
onValuesChanged?.(newValues);
|
|
739
|
+
const isValid = validate(newValues);
|
|
740
|
+
if (isValid && onValid) {
|
|
741
|
+
onValid(newValues, {
|
|
742
|
+
changed
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
}, [
|
|
746
|
+
values,
|
|
747
|
+
onValuesChanged,
|
|
748
|
+
validate,
|
|
749
|
+
onValid,
|
|
750
|
+
changed
|
|
751
|
+
]);
|
|
752
|
+
const onTouched = useCallback4((path) => {
|
|
753
|
+
const jsonPath = createJsonPath(path);
|
|
754
|
+
setTouched((touched2) => ({
|
|
755
|
+
...touched2,
|
|
756
|
+
[jsonPath]: true
|
|
757
|
+
}));
|
|
758
|
+
validate(values);
|
|
759
|
+
}, [
|
|
760
|
+
validate,
|
|
761
|
+
values
|
|
762
|
+
]);
|
|
763
|
+
return useMemo2(() => ({
|
|
764
|
+
// State.
|
|
765
|
+
values,
|
|
766
|
+
errors,
|
|
767
|
+
touched,
|
|
768
|
+
changed,
|
|
769
|
+
canSave,
|
|
770
|
+
formIsValid,
|
|
771
|
+
// Actions.
|
|
772
|
+
handleSave,
|
|
773
|
+
// Field utils.
|
|
774
|
+
getStatus,
|
|
775
|
+
getValue: getFormValue,
|
|
776
|
+
onValueChange,
|
|
777
|
+
onTouched
|
|
778
|
+
}), [
|
|
779
|
+
values,
|
|
780
|
+
errors,
|
|
781
|
+
touched,
|
|
782
|
+
changed,
|
|
783
|
+
canSave,
|
|
784
|
+
formIsValid,
|
|
785
|
+
handleSave,
|
|
786
|
+
getStatus,
|
|
787
|
+
getFormValue,
|
|
788
|
+
onValueChange,
|
|
789
|
+
onTouched
|
|
790
|
+
]);
|
|
791
|
+
};
|
|
792
|
+
var createKeySet = (obj, value) => {
|
|
793
|
+
invariant(obj, void 0, {
|
|
794
|
+
F: __dxlog_file,
|
|
795
|
+
L: 274,
|
|
796
|
+
S: void 0,
|
|
797
|
+
A: [
|
|
798
|
+
"obj",
|
|
799
|
+
""
|
|
800
|
+
]
|
|
801
|
+
});
|
|
802
|
+
return Object.keys(obj).reduce((acc, key) => ({
|
|
803
|
+
...acc,
|
|
804
|
+
[key]: value
|
|
805
|
+
}), {});
|
|
710
806
|
};
|
|
711
|
-
var
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
disabled,
|
|
720
|
-
placeholder,
|
|
721
|
-
value: getValue3() ?? 0,
|
|
722
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
723
|
-
onBlur
|
|
724
|
-
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
807
|
+
var flatMap = (errors) => {
|
|
808
|
+
return errors.reduce((result, { path, message }) => {
|
|
809
|
+
const jsonPath = fromEffectValidationPath(path);
|
|
810
|
+
if (!(jsonPath in result)) {
|
|
811
|
+
result[jsonPath] = message;
|
|
812
|
+
}
|
|
813
|
+
return result;
|
|
814
|
+
}, {});
|
|
725
815
|
};
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
732
|
-
error
|
|
733
|
-
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.Switch, {
|
|
734
|
-
checked,
|
|
735
|
-
onCheckedChange: (value) => onValueChange(type, value)
|
|
736
|
-
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
816
|
+
|
|
817
|
+
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
818
|
+
var FormContext = /* @__PURE__ */ createContext(void 0);
|
|
819
|
+
var useFormContext = () => {
|
|
820
|
+
return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
|
|
737
821
|
};
|
|
738
|
-
var
|
|
739
|
-
const {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
743
|
-
error
|
|
744
|
-
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Select.Root, {
|
|
745
|
-
value: getValue3(),
|
|
746
|
-
onValueChange: (value) => onValueChange(type, value)
|
|
747
|
-
}, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
|
|
748
|
-
classNames: "is-full",
|
|
749
|
-
disabled,
|
|
750
|
-
placeholder
|
|
751
|
-
}), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
|
|
752
|
-
// NOTE: Numeric values are converted to and from strings.
|
|
753
|
-
/* @__PURE__ */ React7.createElement(Select.Option, {
|
|
754
|
-
key: String(value),
|
|
755
|
-
value: String(value)
|
|
756
|
-
}, label2 ?? String(value))
|
|
757
|
-
)))))), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
822
|
+
var useFormValues = (path = []) => {
|
|
823
|
+
const { values: formValues } = useFormContext();
|
|
824
|
+
const jsonPath = createJsonPath2(path);
|
|
825
|
+
return getValue2(formValues, jsonPath);
|
|
758
826
|
};
|
|
759
|
-
var
|
|
760
|
-
const {
|
|
761
|
-
const
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
827
|
+
var useInputProps = (path = []) => {
|
|
828
|
+
const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
|
|
829
|
+
const stablePath = useMemo3(() => path, [
|
|
830
|
+
Array.isArray(path) ? path.join(".") : path
|
|
831
|
+
]);
|
|
832
|
+
return useMemo3(() => ({
|
|
833
|
+
getStatus: () => getStatus(stablePath),
|
|
834
|
+
getValue: () => getFormValue(stablePath),
|
|
835
|
+
onValueChange: (type, value) => onValueChange(stablePath, type, value),
|
|
836
|
+
onBlur: () => onTouched(stablePath)
|
|
837
|
+
}), [
|
|
838
|
+
getStatus,
|
|
839
|
+
getFormValue,
|
|
840
|
+
onValueChange,
|
|
841
|
+
onTouched,
|
|
842
|
+
stablePath
|
|
773
843
|
]);
|
|
844
|
+
};
|
|
845
|
+
var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
|
|
846
|
+
const form = useForm(formOptions);
|
|
774
847
|
useEffect5(() => {
|
|
775
|
-
|
|
848
|
+
if (!formRef?.current) {
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
const handleKeyDown = (event) => {
|
|
852
|
+
const keyIsEnter = event.key === "Enter";
|
|
853
|
+
const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
|
|
854
|
+
const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
|
|
855
|
+
const inputOptOut = event.target.hasAttribute("data-no-submit");
|
|
856
|
+
const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
|
|
857
|
+
const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
|
|
858
|
+
if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
|
|
859
|
+
if (!autoSave && form.canSave) {
|
|
860
|
+
form.handleSave();
|
|
861
|
+
}
|
|
862
|
+
if (autoSave && form.formIsValid) {
|
|
863
|
+
event.target.blur();
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
const formElement = formRef.current;
|
|
868
|
+
formElement.addEventListener("keydown", handleKeyDown);
|
|
869
|
+
return () => formElement.removeEventListener("keydown", handleKeyDown);
|
|
776
870
|
}, [
|
|
777
|
-
|
|
778
|
-
|
|
871
|
+
formRef,
|
|
872
|
+
form.canSave,
|
|
873
|
+
form.formIsValid,
|
|
874
|
+
form.handleSave,
|
|
875
|
+
autoSave
|
|
779
876
|
]);
|
|
780
|
-
return /* @__PURE__ */
|
|
781
|
-
|
|
782
|
-
},
|
|
783
|
-
error
|
|
784
|
-
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.TextArea, {
|
|
785
|
-
ref: textareaRef,
|
|
786
|
-
disabled,
|
|
787
|
-
placeholder,
|
|
788
|
-
value: getValue3() ?? "",
|
|
789
|
-
classNames: "min-bs-auto max-h-40 overflow-auto",
|
|
790
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
791
|
-
onBlur,
|
|
792
|
-
style: {
|
|
793
|
-
resize: "none"
|
|
794
|
-
},
|
|
795
|
-
spellCheck: false
|
|
796
|
-
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.Validation, null, error));
|
|
877
|
+
return /* @__PURE__ */ React8.createElement(FormContext.Provider, {
|
|
878
|
+
value: form
|
|
879
|
+
}, children);
|
|
797
880
|
};
|
|
798
881
|
|
|
799
|
-
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
800
|
-
import React11, { useEffect as useEffect6, useMemo as useMemo6, useRef as useRef3 } from "react";
|
|
801
|
-
import { mx as mx7 } from "@dxos/react-ui-theme";
|
|
802
|
-
|
|
803
882
|
// packages/ui/react-ui-form/src/components/Form/FormActions.tsx
|
|
804
|
-
import React8 from "react";
|
|
805
|
-
import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
806
|
-
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
807
883
|
var FormActions = ({ onCancel, readonly }) => {
|
|
808
|
-
const { t } =
|
|
884
|
+
const { t } = useTranslation4(translationKey);
|
|
809
885
|
const { canSave, handleSave } = useFormContext();
|
|
810
|
-
return /* @__PURE__ */
|
|
886
|
+
return /* @__PURE__ */ React9.createElement("div", {
|
|
811
887
|
role: "none",
|
|
812
888
|
className: "mt-2 flex justify-center"
|
|
813
|
-
}, /* @__PURE__ */
|
|
889
|
+
}, /* @__PURE__ */ React9.createElement("div", {
|
|
814
890
|
role: "none",
|
|
815
891
|
className: mx4(onCancel && !readonly && "grid grid-cols-2 gap-2")
|
|
816
|
-
}, onCancel && !readonly && /* @__PURE__ */
|
|
892
|
+
}, onCancel && !readonly && /* @__PURE__ */ React9.createElement(IconButton2, {
|
|
817
893
|
"data-testid": "cancel-button",
|
|
818
894
|
icon: "ph--x--regular",
|
|
819
895
|
label: t("button cancel"),
|
|
820
896
|
onClick: onCancel
|
|
821
|
-
}), handleSave && /* @__PURE__ */
|
|
897
|
+
}), handleSave && /* @__PURE__ */ React9.createElement(IconButton2, {
|
|
822
898
|
type: "submit",
|
|
823
899
|
"data-testid": "save-button",
|
|
824
900
|
disabled: !canSave,
|
|
@@ -831,7 +907,7 @@ var FormActions = ({ onCancel, readonly }) => {
|
|
|
831
907
|
// packages/ui/react-ui-form/src/components/Form/FormContent.tsx
|
|
832
908
|
import { pipe as pipe2 } from "effect";
|
|
833
909
|
import { capitalize as capitalize2 } from "effect/String";
|
|
834
|
-
import
|
|
910
|
+
import React11, { useMemo as useMemo5 } from "react";
|
|
835
911
|
import { AST as AST3, S } from "@dxos/echo-schema";
|
|
836
912
|
import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
|
|
837
913
|
import { mx as mx6 } from "@dxos/react-ui-theme";
|
|
@@ -841,17 +917,17 @@ import { isNotFalsy } from "@dxos/util";
|
|
|
841
917
|
// packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
|
|
842
918
|
import { pipe } from "effect";
|
|
843
919
|
import { capitalize } from "effect/String";
|
|
844
|
-
import
|
|
920
|
+
import React10, { useCallback as useCallback5, useMemo as useMemo4 } from "react";
|
|
845
921
|
import { AST as AST2 } from "@dxos/echo-schema";
|
|
846
922
|
import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
|
|
847
923
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
848
|
-
import { IconButton as IconButton3, useTranslation as
|
|
924
|
+
import { IconButton as IconButton3, useTranslation as useTranslation5 } from "@dxos/react-ui";
|
|
849
925
|
import { mx as mx5 } from "@dxos/react-ui-theme";
|
|
850
926
|
import { getSchemaProperties } from "@dxos/schema";
|
|
851
927
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
|
|
852
928
|
var padding = "px-2";
|
|
853
929
|
var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
|
|
854
|
-
const { t } =
|
|
930
|
+
const { t } = useTranslation5(translationKey);
|
|
855
931
|
const { ast, name, type, title } = property;
|
|
856
932
|
const values = useFormValues(path ?? []);
|
|
857
933
|
invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
|
|
@@ -910,20 +986,20 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
|
|
|
910
986
|
if (!elementType) {
|
|
911
987
|
return null;
|
|
912
988
|
}
|
|
913
|
-
return /* @__PURE__ */
|
|
989
|
+
return /* @__PURE__ */ React10.createElement("div", {
|
|
914
990
|
role: "none",
|
|
915
991
|
className: mx5(padding)
|
|
916
|
-
}, /* @__PURE__ */
|
|
992
|
+
}, /* @__PURE__ */ React10.createElement(InputHeader, null, label), /* @__PURE__ */ React10.createElement("div", {
|
|
917
993
|
role: "none",
|
|
918
994
|
className: "flex flex-col gap-1"
|
|
919
|
-
}, values.map((_value, index) => /* @__PURE__ */
|
|
995
|
+
}, values.map((_value, index) => /* @__PURE__ */ React10.createElement("div", {
|
|
920
996
|
key: index,
|
|
921
997
|
role: "none",
|
|
922
998
|
className: "flex items-center gap-1"
|
|
923
|
-
}, /* @__PURE__ */
|
|
999
|
+
}, /* @__PURE__ */ React10.createElement("div", {
|
|
924
1000
|
role: "none",
|
|
925
1001
|
className: "flex-1"
|
|
926
|
-
}, /* @__PURE__ */
|
|
1002
|
+
}, /* @__PURE__ */ React10.createElement(FormField, {
|
|
927
1003
|
property: {
|
|
928
1004
|
...property,
|
|
929
1005
|
array: false,
|
|
@@ -937,15 +1013,15 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
|
|
|
937
1013
|
inline: true,
|
|
938
1014
|
Custom,
|
|
939
1015
|
lookupComponent
|
|
940
|
-
})), /* @__PURE__ */
|
|
1016
|
+
})), /* @__PURE__ */ React10.createElement(IconButton3, {
|
|
941
1017
|
icon: "ph--trash--regular",
|
|
942
1018
|
iconOnly: true,
|
|
943
1019
|
label: t("button remove"),
|
|
944
1020
|
onClick: () => handleRemove(index)
|
|
945
|
-
})))), /* @__PURE__ */
|
|
1021
|
+
})))), /* @__PURE__ */ React10.createElement("div", {
|
|
946
1022
|
role: "none",
|
|
947
1023
|
className: "flex justify-between items-center plb-1"
|
|
948
|
-
}, /* @__PURE__ */
|
|
1024
|
+
}, /* @__PURE__ */ React10.createElement(IconButton3, {
|
|
949
1025
|
icon: "ph--plus--regular",
|
|
950
1026
|
iconOnly: true,
|
|
951
1027
|
label: t("button add"),
|
|
@@ -997,14 +1073,14 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
|
|
|
997
1073
|
}
|
|
998
1074
|
});
|
|
999
1075
|
if (FoundComponent) {
|
|
1000
|
-
return /* @__PURE__ */
|
|
1076
|
+
return /* @__PURE__ */ React11.createElement("div", {
|
|
1001
1077
|
role: "none"
|
|
1002
1078
|
}, FoundComponent);
|
|
1003
1079
|
}
|
|
1004
1080
|
const jsonPath = createJsonPath3(path ?? []);
|
|
1005
1081
|
const CustomComponent = Custom?.[jsonPath];
|
|
1006
1082
|
if (CustomComponent) {
|
|
1007
|
-
return /* @__PURE__ */
|
|
1083
|
+
return /* @__PURE__ */ React11.createElement(CustomComponent, {
|
|
1008
1084
|
type,
|
|
1009
1085
|
format,
|
|
1010
1086
|
label,
|
|
@@ -1015,7 +1091,7 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
|
|
|
1015
1091
|
});
|
|
1016
1092
|
}
|
|
1017
1093
|
if (array) {
|
|
1018
|
-
return /* @__PURE__ */
|
|
1094
|
+
return /* @__PURE__ */ React11.createElement(ArrayField, {
|
|
1019
1095
|
property,
|
|
1020
1096
|
path,
|
|
1021
1097
|
inputProps,
|
|
@@ -1025,9 +1101,9 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
|
|
|
1025
1101
|
}
|
|
1026
1102
|
const InputComponent = getInputComponent(type, format);
|
|
1027
1103
|
if (InputComponent) {
|
|
1028
|
-
return /* @__PURE__ */
|
|
1104
|
+
return /* @__PURE__ */ React11.createElement("div", {
|
|
1029
1105
|
role: "none"
|
|
1030
|
-
}, /* @__PURE__ */
|
|
1106
|
+
}, /* @__PURE__ */ React11.createElement(InputComponent, {
|
|
1031
1107
|
type,
|
|
1032
1108
|
format,
|
|
1033
1109
|
label,
|
|
@@ -1038,9 +1114,9 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
|
|
|
1038
1114
|
}));
|
|
1039
1115
|
}
|
|
1040
1116
|
if (options) {
|
|
1041
|
-
return /* @__PURE__ */
|
|
1117
|
+
return /* @__PURE__ */ React11.createElement("div", {
|
|
1042
1118
|
role: "none"
|
|
1043
|
-
}, /* @__PURE__ */
|
|
1119
|
+
}, /* @__PURE__ */ React11.createElement(SelectInput, {
|
|
1044
1120
|
type,
|
|
1045
1121
|
format,
|
|
1046
1122
|
disabled: readonly,
|
|
@@ -1058,9 +1134,9 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
|
|
|
1058
1134
|
const baseNode = findNode2(ast, isDiscriminatedUnion2);
|
|
1059
1135
|
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode2(ast, AST3.isTypeLiteral);
|
|
1060
1136
|
if (typeLiteral) {
|
|
1061
|
-
return /* @__PURE__ */
|
|
1137
|
+
return /* @__PURE__ */ React11.createElement("div", {
|
|
1062
1138
|
role: "none"
|
|
1063
|
-
}, !inline && /* @__PURE__ */
|
|
1139
|
+
}, !inline && /* @__PURE__ */ React11.createElement("div", null, label), /* @__PURE__ */ React11.createElement(FormFields, {
|
|
1064
1140
|
schema: S.make(typeLiteral),
|
|
1065
1141
|
path,
|
|
1066
1142
|
readonly,
|
|
@@ -1082,11 +1158,11 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
|
|
|
1082
1158
|
filter,
|
|
1083
1159
|
sort
|
|
1084
1160
|
]);
|
|
1085
|
-
return /* @__PURE__ */
|
|
1161
|
+
return /* @__PURE__ */ React11.createElement("div", {
|
|
1086
1162
|
role: "form",
|
|
1087
1163
|
className: mx6("flex flex-col w-full gap-2")
|
|
1088
1164
|
}, properties.map((property) => {
|
|
1089
|
-
return /* @__PURE__ */
|
|
1165
|
+
return /* @__PURE__ */ React11.createElement(FormField, {
|
|
1090
1166
|
key: property.name,
|
|
1091
1167
|
property,
|
|
1092
1168
|
path: [
|
|
@@ -1117,7 +1193,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
|
|
|
1117
1193
|
}, [
|
|
1118
1194
|
autoFocus
|
|
1119
1195
|
]);
|
|
1120
|
-
return /* @__PURE__ */
|
|
1196
|
+
return /* @__PURE__ */ React12.createElement(FormProvider, {
|
|
1121
1197
|
formRef,
|
|
1122
1198
|
schema,
|
|
1123
1199
|
autoSave,
|
|
@@ -1126,12 +1202,12 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
|
|
|
1126
1202
|
onValidate,
|
|
1127
1203
|
onValid,
|
|
1128
1204
|
onSave
|
|
1129
|
-
}, /* @__PURE__ */
|
|
1205
|
+
}, /* @__PURE__ */ React12.createElement("div", {
|
|
1130
1206
|
ref: formRef,
|
|
1131
1207
|
role: "none",
|
|
1132
1208
|
className: mx7("p-2", classNames),
|
|
1133
1209
|
"data-testid": testId
|
|
1134
|
-
}, /* @__PURE__ */
|
|
1210
|
+
}, /* @__PURE__ */ React12.createElement(FormFields, {
|
|
1135
1211
|
schema,
|
|
1136
1212
|
path,
|
|
1137
1213
|
readonly,
|
|
@@ -1139,7 +1215,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
|
|
|
1139
1215
|
sort,
|
|
1140
1216
|
lookupComponent,
|
|
1141
1217
|
Custom
|
|
1142
|
-
}), (onCancel || onSave) && !autoSave && /* @__PURE__ */
|
|
1218
|
+
}), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React12.createElement(FormActions, {
|
|
1143
1219
|
onCancel,
|
|
1144
1220
|
readonly
|
|
1145
1221
|
})));
|
|
@@ -1148,7 +1224,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
|
|
|
1148
1224
|
// packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
|
|
1149
1225
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
|
|
1150
1226
|
var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
1151
|
-
const { t } =
|
|
1227
|
+
const { t } = useTranslation6(translationKey);
|
|
1152
1228
|
const [props, setProps] = useState4(projection.getFieldProjection(field.id).props);
|
|
1153
1229
|
useEffect7(() => setProps(projection.getFieldProjection(field.id).props), [
|
|
1154
1230
|
field,
|
|
@@ -1249,26 +1325,26 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1249
1325
|
onSave
|
|
1250
1326
|
]);
|
|
1251
1327
|
const Custom = useMemo7(() => ({
|
|
1252
|
-
["format"]: (props2) => /* @__PURE__ */
|
|
1328
|
+
["format"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
|
|
1253
1329
|
...props2,
|
|
1254
1330
|
options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
|
|
1255
1331
|
value,
|
|
1256
1332
|
label: t(`format ${value}`)
|
|
1257
1333
|
}))
|
|
1258
1334
|
}),
|
|
1259
|
-
["referenceSchema"]: (props2) => /* @__PURE__ */
|
|
1335
|
+
["referenceSchema"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
|
|
1260
1336
|
...props2,
|
|
1261
1337
|
options: schemas.map((schema) => ({
|
|
1262
1338
|
value: schema.typename
|
|
1263
1339
|
}))
|
|
1264
1340
|
}),
|
|
1265
|
-
["referencePath"]: (props2) => /* @__PURE__ */
|
|
1341
|
+
["referencePath"]: (props2) => /* @__PURE__ */ React13.createElement(SelectInput, {
|
|
1266
1342
|
...props2,
|
|
1267
1343
|
options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
|
|
1268
1344
|
value: p.name
|
|
1269
1345
|
})) : []
|
|
1270
1346
|
}),
|
|
1271
|
-
["options"]: (props2) => /* @__PURE__ */
|
|
1347
|
+
["options"]: (props2) => /* @__PURE__ */ React13.createElement(SelectOptionInput, props2)
|
|
1272
1348
|
}), [
|
|
1273
1349
|
t,
|
|
1274
1350
|
schemas,
|
|
@@ -1286,7 +1362,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1286
1362
|
});
|
|
1287
1363
|
return null;
|
|
1288
1364
|
}
|
|
1289
|
-
return /* @__PURE__ */
|
|
1365
|
+
return /* @__PURE__ */ React13.createElement(Form, {
|
|
1290
1366
|
key: field.id,
|
|
1291
1367
|
autoFocus: true,
|
|
1292
1368
|
values: props,
|
|
@@ -1305,12 +1381,14 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1305
1381
|
};
|
|
1306
1382
|
|
|
1307
1383
|
// packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
|
|
1308
|
-
import
|
|
1384
|
+
import React14, { useCallback as useCallback7, useMemo as useMemo8, useState as useState5 } from "react";
|
|
1309
1385
|
import { AST as AST4, Format, S as S2 } from "@dxos/echo-schema";
|
|
1310
|
-
import {
|
|
1386
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1387
|
+
import { IconButton as IconButton4, useTranslation as useTranslation7 } from "@dxos/react-ui";
|
|
1311
1388
|
import { List as List2 } from "@dxos/react-ui-list";
|
|
1312
1389
|
import { ghostHover, inputTextLabel, mx as mx8 } from "@dxos/react-ui-theme";
|
|
1313
1390
|
import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1391
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
|
|
1314
1392
|
var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
|
|
1315
1393
|
var ViewMetaSchema = S2.Struct({
|
|
1316
1394
|
name: S2.String.annotations({
|
|
@@ -1321,8 +1399,8 @@ var ViewMetaSchema = S2.Struct({
|
|
|
1321
1399
|
})
|
|
1322
1400
|
}).pipe(S2.mutable);
|
|
1323
1401
|
var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
|
|
1324
|
-
const { t } =
|
|
1325
|
-
const projection = useMemo8(() => new ViewProjection(schema, view), [
|
|
1402
|
+
const { t } = useTranslation7(translationKey);
|
|
1403
|
+
const projection = useMemo8(() => new ViewProjection(schema.jsonSchema, view), [
|
|
1326
1404
|
schema,
|
|
1327
1405
|
view
|
|
1328
1406
|
]);
|
|
@@ -1337,30 +1415,77 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1337
1415
|
}, [
|
|
1338
1416
|
view
|
|
1339
1417
|
]);
|
|
1340
|
-
const
|
|
1418
|
+
const handleSelect = useCallback7((field2) => {
|
|
1419
|
+
setField((f) => f === field2 ? void 0 : field2);
|
|
1420
|
+
}, []);
|
|
1421
|
+
const handleAdd = useCallback7(() => {
|
|
1422
|
+
invariant3(!schema.readonly, void 0, {
|
|
1423
|
+
F: __dxlog_file4,
|
|
1424
|
+
L: 76,
|
|
1425
|
+
S: void 0,
|
|
1426
|
+
A: [
|
|
1427
|
+
"!schema.readonly",
|
|
1428
|
+
""
|
|
1429
|
+
]
|
|
1430
|
+
});
|
|
1431
|
+
const field2 = projection.createFieldProjection();
|
|
1432
|
+
setField(field2);
|
|
1433
|
+
}, [
|
|
1434
|
+
schema,
|
|
1435
|
+
view
|
|
1436
|
+
]);
|
|
1437
|
+
const handleUpdate = useCallback7(({ name, typename }) => {
|
|
1438
|
+
invariant3(!schema.readonly, void 0, {
|
|
1439
|
+
F: __dxlog_file4,
|
|
1440
|
+
L: 83,
|
|
1441
|
+
S: void 0,
|
|
1442
|
+
A: [
|
|
1443
|
+
"!schema.readonly",
|
|
1444
|
+
""
|
|
1445
|
+
]
|
|
1446
|
+
});
|
|
1341
1447
|
requestAnimationFrame(() => {
|
|
1342
1448
|
if (view.name !== name) {
|
|
1343
1449
|
view.name = name;
|
|
1344
1450
|
}
|
|
1345
1451
|
if (view.query.typename !== typename) {
|
|
1346
|
-
onTypenameChanged(typename);
|
|
1452
|
+
onTypenameChanged?.(typename);
|
|
1347
1453
|
}
|
|
1348
1454
|
});
|
|
1349
1455
|
}, [
|
|
1350
|
-
view,
|
|
1351
1456
|
schema,
|
|
1457
|
+
view,
|
|
1352
1458
|
onTypenameChanged
|
|
1353
1459
|
]);
|
|
1354
|
-
const
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1460
|
+
const handleDelete = useCallback7((fieldId) => {
|
|
1461
|
+
invariant3(!schema.readonly, void 0, {
|
|
1462
|
+
F: __dxlog_file4,
|
|
1463
|
+
L: 99,
|
|
1464
|
+
S: void 0,
|
|
1465
|
+
A: [
|
|
1466
|
+
"!schema.readonly",
|
|
1467
|
+
""
|
|
1468
|
+
]
|
|
1469
|
+
});
|
|
1470
|
+
if (fieldId === field?.id) {
|
|
1471
|
+
setField(void 0);
|
|
1472
|
+
}
|
|
1473
|
+
onDelete?.(fieldId);
|
|
1360
1474
|
}, [
|
|
1361
|
-
|
|
1475
|
+
schema,
|
|
1476
|
+
field,
|
|
1477
|
+
onDelete
|
|
1362
1478
|
]);
|
|
1363
1479
|
const handleMove = useCallback7((fromIndex, toIndex) => {
|
|
1480
|
+
invariant3(!schema.readonly, void 0, {
|
|
1481
|
+
F: __dxlog_file4,
|
|
1482
|
+
L: 111,
|
|
1483
|
+
S: void 0,
|
|
1484
|
+
A: [
|
|
1485
|
+
"!schema.readonly",
|
|
1486
|
+
""
|
|
1487
|
+
]
|
|
1488
|
+
});
|
|
1364
1489
|
const fields = [
|
|
1365
1490
|
...view.fields
|
|
1366
1491
|
];
|
|
@@ -1368,57 +1493,97 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1368
1493
|
fields.splice(toIndex, 0, moved);
|
|
1369
1494
|
view.fields = fields;
|
|
1370
1495
|
}, [
|
|
1496
|
+
schema,
|
|
1371
1497
|
view.fields
|
|
1372
1498
|
]);
|
|
1373
1499
|
const handleClose = useCallback7(() => setField(void 0), []);
|
|
1374
|
-
|
|
1500
|
+
const hiddenProperties = projection.getHiddenProperties();
|
|
1501
|
+
const handleHide = useCallback7((fieldId) => {
|
|
1502
|
+
setField(void 0);
|
|
1503
|
+
projection.hideFieldProjection(fieldId);
|
|
1504
|
+
}, [
|
|
1505
|
+
projection
|
|
1506
|
+
]);
|
|
1507
|
+
const handleShow = useCallback7((property) => {
|
|
1508
|
+
setField(void 0);
|
|
1509
|
+
projection.showFieldProjection(property);
|
|
1510
|
+
}, [
|
|
1511
|
+
projection
|
|
1512
|
+
]);
|
|
1513
|
+
return /* @__PURE__ */ React14.createElement("div", {
|
|
1375
1514
|
role: "none",
|
|
1376
1515
|
className: mx8("flex flex-col w-full divide-y divide-separator", classNames)
|
|
1377
|
-
}, /* @__PURE__ */
|
|
1516
|
+
}, /* @__PURE__ */ React14.createElement(Form, {
|
|
1378
1517
|
autoSave: true,
|
|
1379
1518
|
schema: ViewMetaSchema,
|
|
1380
1519
|
values: viewValues,
|
|
1381
|
-
onSave:
|
|
1382
|
-
}), /* @__PURE__ */
|
|
1520
|
+
onSave: schema.readonly ? void 0 : handleUpdate
|
|
1521
|
+
}), /* @__PURE__ */ React14.createElement("div", null, /* @__PURE__ */ React14.createElement("div", {
|
|
1383
1522
|
role: "none",
|
|
1384
1523
|
className: "p-2"
|
|
1385
|
-
}, /* @__PURE__ */
|
|
1524
|
+
}, /* @__PURE__ */ React14.createElement("label", {
|
|
1386
1525
|
className: mx8(inputTextLabel)
|
|
1387
|
-
}, t("fields label"))), /* @__PURE__ */
|
|
1526
|
+
}, t("fields label"))), /* @__PURE__ */ React14.createElement(List2.Root, {
|
|
1388
1527
|
items: view.fields,
|
|
1389
1528
|
isItem: S2.is(FieldSchema),
|
|
1390
1529
|
getId: (field2) => field2.id,
|
|
1391
|
-
onMove: handleMove
|
|
1392
|
-
}, ({ items: fields }) => /* @__PURE__ */
|
|
1530
|
+
onMove: schema.readonly ? void 0 : handleMove
|
|
1531
|
+
}, ({ items: fields }) => /* @__PURE__ */ React14.createElement(React14.Fragment, null, showHeading && /* @__PURE__ */ React14.createElement("div", {
|
|
1393
1532
|
role: "heading",
|
|
1394
1533
|
className: grid
|
|
1395
|
-
}, /* @__PURE__ */
|
|
1534
|
+
}, /* @__PURE__ */ React14.createElement("div", null), /* @__PURE__ */ React14.createElement("div", {
|
|
1396
1535
|
className: "flex items-center text-sm"
|
|
1397
|
-
}, t("field path label"))), /* @__PURE__ */
|
|
1536
|
+
}, t("field path label"))), /* @__PURE__ */ React14.createElement("div", {
|
|
1398
1537
|
role: "list",
|
|
1399
1538
|
className: "flex flex-col w-full"
|
|
1400
|
-
}, fields?.map((field2) => /* @__PURE__ */
|
|
1539
|
+
}, fields?.map((field2) => /* @__PURE__ */ React14.createElement(List2.Item, {
|
|
1401
1540
|
key: field2.id,
|
|
1402
1541
|
item: field2,
|
|
1403
1542
|
classNames: mx8(grid, ghostHover, "cursor-pointer")
|
|
1404
|
-
}, /* @__PURE__ */
|
|
1543
|
+
}, /* @__PURE__ */ React14.createElement(List2.ItemDragHandle, null), /* @__PURE__ */ React14.createElement(List2.ItemTitle, {
|
|
1405
1544
|
onClick: () => handleSelect(field2)
|
|
1406
|
-
}, field2.path), /* @__PURE__ */
|
|
1545
|
+
}, field2.path), /* @__PURE__ */ React14.createElement("div", {
|
|
1546
|
+
className: "flex items-center gap-2 -ml-4"
|
|
1547
|
+
}, /* @__PURE__ */ React14.createElement(List2.ItemButton, {
|
|
1548
|
+
icon: "ph--eye-slash--regular",
|
|
1549
|
+
disabled: view.fields.length <= 1,
|
|
1550
|
+
onClick: () => handleHide(field2.id)
|
|
1551
|
+
}), !schema.readonly && /* @__PURE__ */ React14.createElement(List2.ItemDeleteButton, {
|
|
1552
|
+
icon: "ph--trash--regular",
|
|
1407
1553
|
disabled: view.fields.length <= 1,
|
|
1408
|
-
onClick: () =>
|
|
1409
|
-
}))))))),
|
|
1554
|
+
onClick: () => handleDelete(field2.id)
|
|
1555
|
+
}))))))), hiddenProperties.length > 0 && /* @__PURE__ */ React14.createElement("div", null, /* @__PURE__ */ React14.createElement("div", {
|
|
1556
|
+
role: "none",
|
|
1557
|
+
className: "p-2"
|
|
1558
|
+
}, /* @__PURE__ */ React14.createElement("label", {
|
|
1559
|
+
className: mx8(inputTextLabel)
|
|
1560
|
+
}, t("hidden fields label"))), /* @__PURE__ */ React14.createElement(List2.Root, {
|
|
1561
|
+
items: hiddenProperties,
|
|
1562
|
+
isItem: (item) => typeof item === "string",
|
|
1563
|
+
getId: (property) => property
|
|
1564
|
+
}, ({ items: properties }) => /* @__PURE__ */ React14.createElement("div", {
|
|
1565
|
+
role: "list",
|
|
1566
|
+
className: "flex flex-col w-full"
|
|
1567
|
+
}, properties?.map((property) => /* @__PURE__ */ React14.createElement(List2.Item, {
|
|
1568
|
+
key: property,
|
|
1569
|
+
item: property,
|
|
1570
|
+
classNames: mx8(grid, ghostHover, "cursor-pointer")
|
|
1571
|
+
}, /* @__PURE__ */ React14.createElement("div", null), /* @__PURE__ */ React14.createElement(List2.ItemTitle, null, property), /* @__PURE__ */ React14.createElement(List2.ItemButton, {
|
|
1572
|
+
icon: "ph--eye--regular",
|
|
1573
|
+
onClick: () => handleShow(property)
|
|
1574
|
+
}))))))), field && /* @__PURE__ */ React14.createElement(FieldEditor, {
|
|
1410
1575
|
key: field.id,
|
|
1411
1576
|
view,
|
|
1412
1577
|
projection,
|
|
1413
1578
|
field,
|
|
1414
1579
|
registry,
|
|
1415
1580
|
onSave: handleClose
|
|
1416
|
-
}), !readonly && !field && /* @__PURE__ */
|
|
1581
|
+
}), !readonly && !field && /* @__PURE__ */ React14.createElement("div", {
|
|
1417
1582
|
className: "flex p-2 justify-center"
|
|
1418
|
-
}, /* @__PURE__ */
|
|
1583
|
+
}, /* @__PURE__ */ React14.createElement(IconButton4, {
|
|
1419
1584
|
icon: "ph--plus--regular",
|
|
1420
1585
|
label: t("button add property"),
|
|
1421
|
-
onClick: handleAdd,
|
|
1586
|
+
onClick: schema.readonly ? void 0 : handleAdd,
|
|
1422
1587
|
// TODO(burdon): Show field limit in ux (not tooltip).
|
|
1423
1588
|
disabled: view.fields.length >= VIEW_FIELD_LIMIT
|
|
1424
1589
|
})));
|
|
@@ -1529,18 +1694,21 @@ var cellClassesForFieldType = ({ type, format }) => {
|
|
|
1529
1694
|
switch (format) {
|
|
1530
1695
|
case FormatEnum3.Markdown:
|
|
1531
1696
|
return void 0;
|
|
1697
|
+
case FormatEnum3.Time:
|
|
1532
1698
|
case FormatEnum3.Timestamp:
|
|
1533
1699
|
case FormatEnum3.DateTime:
|
|
1534
1700
|
case FormatEnum3.Date:
|
|
1535
|
-
case FormatEnum3.
|
|
1701
|
+
case FormatEnum3.Duration:
|
|
1536
1702
|
return [
|
|
1537
|
-
"font-mono"
|
|
1703
|
+
"font-mono",
|
|
1704
|
+
"text-right"
|
|
1538
1705
|
];
|
|
1539
1706
|
case FormatEnum3.Currency:
|
|
1540
1707
|
return [
|
|
1541
1708
|
"text-right"
|
|
1542
1709
|
];
|
|
1543
1710
|
case FormatEnum3.JSON:
|
|
1711
|
+
case FormatEnum3.DID:
|
|
1544
1712
|
return [
|
|
1545
1713
|
"font-mono"
|
|
1546
1714
|
];
|
|
@@ -1548,15 +1716,13 @@ var cellClassesForFieldType = ({ type, format }) => {
|
|
|
1548
1716
|
return void 0;
|
|
1549
1717
|
}
|
|
1550
1718
|
};
|
|
1551
|
-
var cellClassesForRowSelection = (selected) => selected ? [
|
|
1552
|
-
"!bg-gridCellSelected"
|
|
1553
|
-
] : void 0;
|
|
1554
1719
|
var pathNotUniqueError = (path) => ({
|
|
1555
1720
|
path: "path",
|
|
1556
1721
|
message: `'${path}' is already present`
|
|
1557
1722
|
});
|
|
1558
1723
|
|
|
1559
1724
|
// packages/ui/react-ui-form/src/util/formatting.ts
|
|
1725
|
+
import { format as formatDate } from "date-fns/format";
|
|
1560
1726
|
import { FormatEnum as FormatEnum4, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
|
|
1561
1727
|
var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
|
|
1562
1728
|
const formatScalar = (type2) => {
|
|
@@ -1598,17 +1764,14 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
|
|
|
1598
1764
|
maximumFractionDigits: 2
|
|
1599
1765
|
});
|
|
1600
1766
|
}
|
|
1601
|
-
case FormatEnum4.
|
|
1602
|
-
|
|
1767
|
+
case FormatEnum4.Date: {
|
|
1768
|
+
return formatDate(new Date(value), "yyyy-MM-dd");
|
|
1769
|
+
}
|
|
1603
1770
|
case FormatEnum4.Time: {
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
return date.toLocaleDateString(locale);
|
|
1609
|
-
} else {
|
|
1610
|
-
return date.toLocaleTimeString(locale);
|
|
1611
|
-
}
|
|
1771
|
+
return formatDate(new Date(value), "HH:mm:ss");
|
|
1772
|
+
}
|
|
1773
|
+
case FormatEnum4.DateTime: {
|
|
1774
|
+
return formatDate(new Date(value), "yyyy-MM-dd HH:mm:ss");
|
|
1612
1775
|
}
|
|
1613
1776
|
case FormatEnum4.GeoPoint: {
|
|
1614
1777
|
if (value === null || value === void 0) {
|
|
@@ -1685,10 +1848,18 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
|
|
|
1685
1848
|
};
|
|
1686
1849
|
export {
|
|
1687
1850
|
BooleanInput,
|
|
1851
|
+
ControlFrame,
|
|
1852
|
+
ControlFrameItem,
|
|
1853
|
+
ControlGroup,
|
|
1854
|
+
ControlItem,
|
|
1855
|
+
ControlItemInput,
|
|
1856
|
+
ControlSection,
|
|
1857
|
+
ControlSectionHeading,
|
|
1688
1858
|
DeprecatedFormContainer,
|
|
1689
1859
|
DeprecatedFormInput,
|
|
1690
1860
|
FieldEditor,
|
|
1691
1861
|
Form,
|
|
1862
|
+
FormProvider,
|
|
1692
1863
|
GeoPointInput,
|
|
1693
1864
|
InputHeader,
|
|
1694
1865
|
MarkdownInput,
|
|
@@ -1699,13 +1870,15 @@ export {
|
|
|
1699
1870
|
TupleInput,
|
|
1700
1871
|
ViewEditor,
|
|
1701
1872
|
cellClassesForFieldType,
|
|
1702
|
-
|
|
1873
|
+
controlItemClasses,
|
|
1703
1874
|
formatForDisplay,
|
|
1704
1875
|
formatForEditing,
|
|
1705
1876
|
parseValue,
|
|
1706
1877
|
pathNotUniqueError,
|
|
1707
1878
|
translations_default as translations,
|
|
1708
1879
|
useForm,
|
|
1709
|
-
|
|
1880
|
+
useFormContext,
|
|
1881
|
+
useFormValues,
|
|
1882
|
+
useInputProps
|
|
1710
1883
|
};
|
|
1711
1884
|
//# sourceMappingURL=index.mjs.map
|