@dxos/react-ui-form 0.8.1-staging.391c573 → 0.8.1-staging.5be625a
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 +508 -453
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +681 -625
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +508 -453
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +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/ViewEditor.d.ts +4 -4
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/components/Form/index.ts +1 -3
- package/src/components/ViewEditor/ViewEditor.tsx +43 -27
- package/src/hooks/useForm.ts +10 -1
- package/src/util/field.ts +1 -0
|
@@ -106,326 +106,54 @@ import { log as log2 } from "@dxos/log";
|
|
|
106
106
|
import { useTranslation as useTranslation5 } from "@dxos/react-ui";
|
|
107
107
|
import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
|
|
108
108
|
|
|
109
|
-
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
110
|
-
import React2, { createContext, useContext, useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
111
|
-
import { raise } from "@dxos/debug";
|
|
112
|
-
import { getValue as getValue2 } from "@dxos/echo-schema";
|
|
113
|
-
import { createJsonPath as createJsonPath2 } from "@dxos/effect";
|
|
114
|
-
|
|
115
|
-
// packages/ui/react-ui-form/src/hooks/useForm.ts
|
|
116
|
-
import { SchemaAST as AST } from "effect";
|
|
117
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
118
|
-
import { getValue, setValue } from "@dxos/echo-schema";
|
|
119
|
-
import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
|
|
120
|
-
import { invariant } from "@dxos/invariant";
|
|
121
|
-
import { log } from "@dxos/log";
|
|
122
|
-
import { validateSchema } from "@dxos/schema";
|
|
123
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
124
|
-
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
125
|
-
invariant(AST.isTypeLiteral(schema.ast), void 0, {
|
|
126
|
-
F: __dxlog_file,
|
|
127
|
-
L: 93,
|
|
128
|
-
S: void 0,
|
|
129
|
-
A: [
|
|
130
|
-
"AST.isTypeLiteral(schema.ast)",
|
|
131
|
-
""
|
|
132
|
-
]
|
|
133
|
-
});
|
|
134
|
-
const [values, setValues] = useState(initialValues);
|
|
135
|
-
useEffect(() => {
|
|
136
|
-
setValues(initialValues);
|
|
137
|
-
}, [
|
|
138
|
-
initialValues
|
|
139
|
-
]);
|
|
140
|
-
const [touched, setTouched] = useState(createKeySet(initialValues, false));
|
|
141
|
-
const [changed, setChanged] = useState(createKeySet(initialValues, false));
|
|
142
|
-
const [errors, setErrors] = useState({});
|
|
143
|
-
const [saving, setSaving] = useState(false);
|
|
144
|
-
const validate = useCallback((values2) => {
|
|
145
|
-
let errors2 = validateSchema(schema, values2) ?? [];
|
|
146
|
-
if (errors2.length === 0 && onValidate) {
|
|
147
|
-
const validatedValues = values2;
|
|
148
|
-
errors2 = onValidate(validatedValues) ?? [];
|
|
149
|
-
}
|
|
150
|
-
setErrors(flatMap(errors2));
|
|
151
|
-
const valid = errors2.length === 0;
|
|
152
|
-
return valid;
|
|
153
|
-
}, [
|
|
154
|
-
schema,
|
|
155
|
-
onValidate
|
|
156
|
-
]);
|
|
157
|
-
const [schemaDirty, setSchemaDirty] = useState(false);
|
|
158
|
-
useEffect(() => setSchemaDirty(true), [
|
|
159
|
-
schema
|
|
160
|
-
]);
|
|
161
|
-
useEffect(() => {
|
|
162
|
-
if (schemaDirty) {
|
|
163
|
-
validate(values);
|
|
164
|
-
setSchemaDirty(false);
|
|
165
|
-
}
|
|
166
|
-
}, [
|
|
167
|
-
values,
|
|
168
|
-
schemaDirty
|
|
169
|
-
]);
|
|
170
|
-
const formIsValid = useMemo(() => {
|
|
171
|
-
return Object.keys(errors).length === 0;
|
|
172
|
-
}, [
|
|
173
|
-
errors
|
|
174
|
-
]);
|
|
175
|
-
const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors.
|
|
176
|
-
!Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
|
|
177
|
-
touched,
|
|
178
|
-
errors,
|
|
179
|
-
saving
|
|
180
|
-
]);
|
|
181
|
-
const handleSave = useCallback(async () => {
|
|
182
|
-
if (validate(values)) {
|
|
183
|
-
setSaving(true);
|
|
184
|
-
try {
|
|
185
|
-
await onSave?.(values, {
|
|
186
|
-
changed
|
|
187
|
-
});
|
|
188
|
-
} finally {
|
|
189
|
-
setSaving(false);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}, [
|
|
193
|
-
values,
|
|
194
|
-
validate,
|
|
195
|
-
onSave,
|
|
196
|
-
changed
|
|
197
|
-
]);
|
|
198
|
-
const getStatus = useCallback((path) => {
|
|
199
|
-
const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
|
|
200
|
-
const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
|
|
201
|
-
return {
|
|
202
|
-
status: matchingError ? "error" : void 0,
|
|
203
|
-
error: matchingError ? matchingError[1] : void 0
|
|
204
|
-
};
|
|
205
|
-
}, [
|
|
206
|
-
errors
|
|
207
|
-
]);
|
|
208
|
-
const getFormValue = useCallback((path) => {
|
|
209
|
-
return getValue(values, createJsonPath(path));
|
|
210
|
-
}, [
|
|
211
|
-
values
|
|
212
|
-
]);
|
|
213
|
-
const onValueChange = useCallback((path, type, value) => {
|
|
214
|
-
const jsonPath = createJsonPath(path);
|
|
215
|
-
let parsedValue = value;
|
|
216
|
-
try {
|
|
217
|
-
if (type === "number") {
|
|
218
|
-
parsedValue = parseFloat(value) || 0;
|
|
219
|
-
}
|
|
220
|
-
} catch (err) {
|
|
221
|
-
log.catch(err, void 0, {
|
|
222
|
-
F: __dxlog_file,
|
|
223
|
-
L: 203,
|
|
224
|
-
S: void 0,
|
|
225
|
-
C: (f, a) => f(...a)
|
|
226
|
-
});
|
|
227
|
-
parsedValue = void 0;
|
|
228
|
-
}
|
|
229
|
-
const newValues = {
|
|
230
|
-
...setValue(values, jsonPath, parsedValue)
|
|
231
|
-
};
|
|
232
|
-
setValues(newValues);
|
|
233
|
-
setChanged((prev) => ({
|
|
234
|
-
...prev,
|
|
235
|
-
[jsonPath]: true
|
|
236
|
-
}));
|
|
237
|
-
onValuesChanged?.(newValues);
|
|
238
|
-
const isValid = validate(newValues);
|
|
239
|
-
if (isValid && onValid) {
|
|
240
|
-
onValid(newValues, {
|
|
241
|
-
changed
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
}, [
|
|
245
|
-
values,
|
|
246
|
-
onValuesChanged,
|
|
247
|
-
validate,
|
|
248
|
-
onValid,
|
|
249
|
-
changed
|
|
250
|
-
]);
|
|
251
|
-
const onTouched = useCallback((path) => {
|
|
252
|
-
const jsonPath = createJsonPath(path);
|
|
253
|
-
setTouched((touched2) => ({
|
|
254
|
-
...touched2,
|
|
255
|
-
[jsonPath]: true
|
|
256
|
-
}));
|
|
257
|
-
validate(values);
|
|
258
|
-
}, [
|
|
259
|
-
validate,
|
|
260
|
-
values
|
|
261
|
-
]);
|
|
262
|
-
return useMemo(() => ({
|
|
263
|
-
// State.
|
|
264
|
-
values,
|
|
265
|
-
errors,
|
|
266
|
-
touched,
|
|
267
|
-
changed,
|
|
268
|
-
canSave,
|
|
269
|
-
formIsValid,
|
|
270
|
-
// Actions.
|
|
271
|
-
handleSave,
|
|
272
|
-
// Field utils.
|
|
273
|
-
getStatus,
|
|
274
|
-
getValue: getFormValue,
|
|
275
|
-
onValueChange,
|
|
276
|
-
onTouched
|
|
277
|
-
}), [
|
|
278
|
-
values,
|
|
279
|
-
errors,
|
|
280
|
-
touched,
|
|
281
|
-
changed,
|
|
282
|
-
canSave,
|
|
283
|
-
formIsValid,
|
|
284
|
-
handleSave,
|
|
285
|
-
getStatus,
|
|
286
|
-
getFormValue,
|
|
287
|
-
onValueChange,
|
|
288
|
-
onTouched
|
|
289
|
-
]);
|
|
290
|
-
};
|
|
291
|
-
var createKeySet = (obj, value) => {
|
|
292
|
-
invariant(obj, void 0, {
|
|
293
|
-
F: __dxlog_file,
|
|
294
|
-
L: 265,
|
|
295
|
-
S: void 0,
|
|
296
|
-
A: [
|
|
297
|
-
"obj",
|
|
298
|
-
""
|
|
299
|
-
]
|
|
300
|
-
});
|
|
301
|
-
return Object.keys(obj).reduce((acc, key) => ({
|
|
302
|
-
...acc,
|
|
303
|
-
[key]: value
|
|
304
|
-
}), {});
|
|
305
|
-
};
|
|
306
|
-
var flatMap = (errors) => {
|
|
307
|
-
return errors.reduce((result, { path, message }) => {
|
|
308
|
-
const jsonPath = fromEffectValidationPath(path);
|
|
309
|
-
if (!(jsonPath in result)) {
|
|
310
|
-
result[jsonPath] = message;
|
|
311
|
-
}
|
|
312
|
-
return result;
|
|
313
|
-
}, {});
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
317
|
-
var FormContext = /* @__PURE__ */ createContext(void 0);
|
|
318
|
-
var useFormContext = () => {
|
|
319
|
-
return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
|
|
320
|
-
};
|
|
321
|
-
var useFormValues = (path = []) => {
|
|
322
|
-
const { values: formValues } = useFormContext();
|
|
323
|
-
const jsonPath = createJsonPath2(path);
|
|
324
|
-
return getValue2(formValues, jsonPath);
|
|
325
|
-
};
|
|
326
|
-
var useInputProps = (path = []) => {
|
|
327
|
-
const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
|
|
328
|
-
const stablePath = useMemo2(() => path, [
|
|
329
|
-
Array.isArray(path) ? path.join(".") : path
|
|
330
|
-
]);
|
|
331
|
-
return useMemo2(() => ({
|
|
332
|
-
getStatus: () => getStatus(stablePath),
|
|
333
|
-
getValue: () => getFormValue(stablePath),
|
|
334
|
-
onValueChange: (type, value) => onValueChange(stablePath, type, value),
|
|
335
|
-
onBlur: () => onTouched(stablePath)
|
|
336
|
-
}), [
|
|
337
|
-
getStatus,
|
|
338
|
-
getFormValue,
|
|
339
|
-
onValueChange,
|
|
340
|
-
onTouched,
|
|
341
|
-
stablePath
|
|
342
|
-
]);
|
|
343
|
-
};
|
|
344
|
-
var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
|
|
345
|
-
const form = useForm(formOptions);
|
|
346
|
-
useEffect2(() => {
|
|
347
|
-
if (!formRef?.current) {
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
const handleKeyDown = (event) => {
|
|
351
|
-
const keyIsEnter = event.key === "Enter";
|
|
352
|
-
const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
|
|
353
|
-
const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
|
|
354
|
-
const inputOptOut = event.target.hasAttribute("data-no-submit");
|
|
355
|
-
const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
|
|
356
|
-
const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
|
|
357
|
-
if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
|
|
358
|
-
if (!autoSave && form.canSave) {
|
|
359
|
-
form.handleSave();
|
|
360
|
-
}
|
|
361
|
-
if (autoSave && form.formIsValid) {
|
|
362
|
-
event.target.blur();
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
};
|
|
366
|
-
const formElement = formRef.current;
|
|
367
|
-
formElement.addEventListener("keydown", handleKeyDown);
|
|
368
|
-
return () => formElement.removeEventListener("keydown", handleKeyDown);
|
|
369
|
-
}, [
|
|
370
|
-
formRef,
|
|
371
|
-
form.canSave,
|
|
372
|
-
form.formIsValid,
|
|
373
|
-
form.handleSave,
|
|
374
|
-
autoSave
|
|
375
|
-
]);
|
|
376
|
-
return /* @__PURE__ */ React2.createElement(FormContext.Provider, {
|
|
377
|
-
value: form
|
|
378
|
-
}, children);
|
|
379
|
-
};
|
|
380
|
-
|
|
381
109
|
// packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
|
|
382
|
-
import
|
|
110
|
+
import React3, { useCallback, useState, useEffect, useMemo } from "react";
|
|
383
111
|
import { GeoLocation } from "@dxos/echo-schema";
|
|
384
112
|
import { Input as Input2, useTranslation } from "@dxos/react-ui";
|
|
385
113
|
import { safeParseFloat } from "@dxos/util";
|
|
386
114
|
|
|
387
115
|
// packages/ui/react-ui-form/src/components/Form/Input.tsx
|
|
388
|
-
import
|
|
116
|
+
import React2 from "react";
|
|
389
117
|
import { Icon, Tooltip } from "@dxos/react-ui";
|
|
390
118
|
import { errorText } from "@dxos/react-ui-theme";
|
|
391
119
|
var InputHeader = ({ children, error }) => {
|
|
392
|
-
return /* @__PURE__ */
|
|
120
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
393
121
|
role: "none",
|
|
394
122
|
className: "flex justify-between items-center mb-1"
|
|
395
|
-
}, children, error && /* @__PURE__ */
|
|
123
|
+
}, children, error && /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
396
124
|
asChild: true
|
|
397
|
-
}, /* @__PURE__ */
|
|
125
|
+
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
398
126
|
icon: "ph--warning--regular",
|
|
399
127
|
size: 4,
|
|
400
128
|
classNames: errorText
|
|
401
|
-
})), /* @__PURE__ */
|
|
129
|
+
})), /* @__PURE__ */ React2.createElement(Tooltip.Content, {
|
|
402
130
|
side: "bottom"
|
|
403
|
-
}, /* @__PURE__ */
|
|
131
|
+
}, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null), error)));
|
|
404
132
|
};
|
|
405
133
|
|
|
406
134
|
// packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
|
|
407
135
|
var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
408
136
|
const { t } = useTranslation(translationKey);
|
|
409
137
|
const { status, error } = getStatus();
|
|
410
|
-
const geoPoint =
|
|
138
|
+
const geoPoint = useMemo(() => getValue3() ?? [
|
|
411
139
|
0,
|
|
412
140
|
0
|
|
413
141
|
], [
|
|
414
142
|
getValue3
|
|
415
143
|
]);
|
|
416
|
-
const geoLocation =
|
|
144
|
+
const geoLocation = useMemo(() => GeoLocation.fromGeoPoint(geoPoint), [
|
|
417
145
|
geoPoint
|
|
418
146
|
]);
|
|
419
|
-
const [longitudeText, setLongitudeText] =
|
|
420
|
-
const [latitudeText, setLatitudeText] =
|
|
421
|
-
|
|
147
|
+
const [longitudeText, setLongitudeText] = useState(geoLocation.longitude?.toString());
|
|
148
|
+
const [latitudeText, setLatitudeText] = useState(geoLocation.latitude?.toString());
|
|
149
|
+
useEffect(() => {
|
|
422
150
|
const location = GeoLocation.fromGeoPoint(geoPoint);
|
|
423
151
|
setLongitudeText(location.longitude.toString());
|
|
424
152
|
setLatitudeText(location.latitude.toString());
|
|
425
153
|
}, [
|
|
426
154
|
geoPoint
|
|
427
155
|
]);
|
|
428
|
-
const handleCoordinateChange =
|
|
156
|
+
const handleCoordinateChange = useCallback((coordinateType, setText) => (event) => {
|
|
429
157
|
const inputText = event.target.value;
|
|
430
158
|
setText(inputText);
|
|
431
159
|
if (inputText !== "" && inputText !== "-") {
|
|
@@ -448,14 +176,14 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
448
176
|
onValueChange,
|
|
449
177
|
type
|
|
450
178
|
]);
|
|
451
|
-
return /* @__PURE__ */
|
|
179
|
+
return /* @__PURE__ */ React3.createElement(Input2.Root, {
|
|
452
180
|
validationValence: status
|
|
453
|
-
}, /* @__PURE__ */
|
|
181
|
+
}, /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
454
182
|
error
|
|
455
|
-
}, /* @__PURE__ */
|
|
183
|
+
}, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement("div", {
|
|
456
184
|
role: "none",
|
|
457
185
|
className: "grid grid-cols-2 gap-2"
|
|
458
|
-
}, /* @__PURE__ */
|
|
186
|
+
}, /* @__PURE__ */ React3.createElement(Input2.TextInput, {
|
|
459
187
|
type: "text",
|
|
460
188
|
pattern: "^-?[0-9]*\\.?[0-9]*$",
|
|
461
189
|
disabled,
|
|
@@ -463,7 +191,7 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
463
191
|
value: latitudeText,
|
|
464
192
|
onChange: handleCoordinateChange("latitude", setLatitudeText),
|
|
465
193
|
onBlur
|
|
466
|
-
}), /* @__PURE__ */
|
|
194
|
+
}), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
|
|
467
195
|
type: "text",
|
|
468
196
|
pattern: "^-?[0-9]*\\.?[0-9]*$",
|
|
469
197
|
disabled,
|
|
@@ -475,20 +203,20 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
475
203
|
};
|
|
476
204
|
|
|
477
205
|
// packages/ui/react-ui-form/src/components/Form/custom/SelectOptionsInput.tsx
|
|
478
|
-
import
|
|
206
|
+
import React4, { useCallback as useCallback2, useEffect as useEffect2, useState as useState2, useRef } from "react";
|
|
479
207
|
import { PublicKey } from "@dxos/keys";
|
|
480
208
|
import { Icon as Icon2, IconButton, Input as Input3, Tag, Toolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
481
209
|
import { List } from "@dxos/react-ui-list";
|
|
482
210
|
import { HuePicker } from "@dxos/react-ui-pickers";
|
|
483
211
|
import { hues, mx as mx2 } from "@dxos/react-ui-theme";
|
|
484
212
|
var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
|
|
485
|
-
const [selected, setSelectedId] =
|
|
486
|
-
const [isNewOption, setIsNewOption] =
|
|
213
|
+
const [selected, setSelectedId] = useState2(null);
|
|
214
|
+
const [isNewOption, setIsNewOption] = useState2(false);
|
|
487
215
|
const inputRef = useRef(null);
|
|
488
216
|
const { t } = useTranslation2(translationKey);
|
|
489
217
|
const { status, error } = getStatus();
|
|
490
218
|
const options = getValue3();
|
|
491
|
-
|
|
219
|
+
useEffect2(() => {
|
|
492
220
|
if (options === void 0) {
|
|
493
221
|
onValueChange(type, []);
|
|
494
222
|
}
|
|
@@ -507,7 +235,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
507
235
|
const availableHues = hues.filter((hue) => !lastThree.has(hue));
|
|
508
236
|
return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
|
|
509
237
|
};
|
|
510
|
-
const handleAdd =
|
|
238
|
+
const handleAdd = useCallback2(() => {
|
|
511
239
|
const newId = PublicKey.random().truncate();
|
|
512
240
|
const newOption = {
|
|
513
241
|
id: newId,
|
|
@@ -525,7 +253,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
525
253
|
type,
|
|
526
254
|
onValueChange
|
|
527
255
|
]);
|
|
528
|
-
const handleDelete =
|
|
256
|
+
const handleDelete = useCallback2((id) => {
|
|
529
257
|
const newOptions = options?.filter((option) => option.id !== id) ?? [];
|
|
530
258
|
onValueChange(type, newOptions);
|
|
531
259
|
setSelectedId(null);
|
|
@@ -534,7 +262,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
534
262
|
type,
|
|
535
263
|
onValueChange
|
|
536
264
|
]);
|
|
537
|
-
const handleMove =
|
|
265
|
+
const handleMove = useCallback2((from, to) => {
|
|
538
266
|
if (!options) {
|
|
539
267
|
return;
|
|
540
268
|
}
|
|
@@ -549,10 +277,10 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
549
277
|
type,
|
|
550
278
|
onValueChange
|
|
551
279
|
]);
|
|
552
|
-
const handleClick =
|
|
280
|
+
const handleClick = useCallback2((id) => {
|
|
553
281
|
setSelectedId((current) => current === id ? null : id);
|
|
554
282
|
}, []);
|
|
555
|
-
const handleTitleChange =
|
|
283
|
+
const handleTitleChange = useCallback2((id) => (e) => {
|
|
556
284
|
const newOptions = options?.map((o) => o.id === id ? {
|
|
557
285
|
...o,
|
|
558
286
|
title: e.target.value
|
|
@@ -563,12 +291,12 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
563
291
|
type,
|
|
564
292
|
onValueChange
|
|
565
293
|
]);
|
|
566
|
-
const handleKeyDown =
|
|
294
|
+
const handleKeyDown = useCallback2((e) => {
|
|
567
295
|
if (e.key === "Enter") {
|
|
568
296
|
setSelectedId(null);
|
|
569
297
|
}
|
|
570
298
|
}, []);
|
|
571
|
-
const handleColorChange =
|
|
299
|
+
const handleColorChange = useCallback2((id) => (hue) => {
|
|
572
300
|
const newOptions = options?.map((o) => o.id === id ? {
|
|
573
301
|
...o,
|
|
574
302
|
color: hue
|
|
@@ -579,7 +307,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
579
307
|
type,
|
|
580
308
|
onValueChange
|
|
581
309
|
]);
|
|
582
|
-
|
|
310
|
+
useEffect2(() => {
|
|
583
311
|
if (selected && isNewOption && inputRef.current) {
|
|
584
312
|
inputRef.current.focus();
|
|
585
313
|
setIsNewOption(false);
|
|
@@ -588,43 +316,43 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
588
316
|
selected,
|
|
589
317
|
isNewOption
|
|
590
318
|
]);
|
|
591
|
-
return /* @__PURE__ */
|
|
319
|
+
return /* @__PURE__ */ React4.createElement(Input3.Root, {
|
|
592
320
|
validationValence: status
|
|
593
|
-
}, /* @__PURE__ */
|
|
321
|
+
}, /* @__PURE__ */ React4.createElement(InputHeader, {
|
|
594
322
|
error
|
|
595
|
-
}, /* @__PURE__ */
|
|
323
|
+
}, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
|
|
596
324
|
role: "none"
|
|
597
|
-
}, options && /* @__PURE__ */
|
|
325
|
+
}, options && /* @__PURE__ */ React4.createElement(List.Root, {
|
|
598
326
|
items: options,
|
|
599
327
|
isItem: (item) => true,
|
|
600
328
|
onMove: handleMove
|
|
601
|
-
}, ({ items }) => /* @__PURE__ */
|
|
329
|
+
}, ({ items }) => /* @__PURE__ */ React4.createElement("div", {
|
|
602
330
|
role: "list",
|
|
603
331
|
className: "w-full overflow-auto"
|
|
604
|
-
}, items?.map((item) => /* @__PURE__ */
|
|
332
|
+
}, items?.map((item) => /* @__PURE__ */ React4.createElement("div", {
|
|
605
333
|
key: item.id
|
|
606
|
-
}, /* @__PURE__ */
|
|
334
|
+
}, /* @__PURE__ */ React4.createElement(List.Item, {
|
|
607
335
|
role: "button",
|
|
608
336
|
item,
|
|
609
337
|
classNames: mx2("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
|
|
610
338
|
"aria-expanded": selected === item.id
|
|
611
|
-
}, /* @__PURE__ */
|
|
339
|
+
}, /* @__PURE__ */ React4.createElement("div", {
|
|
612
340
|
className: "flex items-center"
|
|
613
|
-
}, /* @__PURE__ */
|
|
341
|
+
}, /* @__PURE__ */ React4.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React4.createElement(List.ItemTitle, {
|
|
614
342
|
onClick: () => handleClick(item.id),
|
|
615
343
|
classNames: "flex-1"
|
|
616
|
-
}, /* @__PURE__ */
|
|
344
|
+
}, /* @__PURE__ */ React4.createElement(Tag, {
|
|
617
345
|
palette: item.color
|
|
618
|
-
}, item.title || "\u200B")), /* @__PURE__ */
|
|
346
|
+
}, item.title || "\u200B")), /* @__PURE__ */ React4.createElement(Icon2, {
|
|
619
347
|
icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
620
348
|
onClick: () => handleClick(item.id)
|
|
621
|
-
})), selected === item.id && /* @__PURE__ */
|
|
349
|
+
})), selected === item.id && /* @__PURE__ */ React4.createElement("div", {
|
|
622
350
|
className: "mis-4 mbs-2 flex flex-col gap-1"
|
|
623
|
-
}, /* @__PURE__ */
|
|
351
|
+
}, /* @__PURE__ */ React4.createElement(Input3.Label, {
|
|
624
352
|
classNames: "text-xs"
|
|
625
|
-
}, t("select option label")), /* @__PURE__ */
|
|
353
|
+
}, t("select option label")), /* @__PURE__ */ React4.createElement("div", {
|
|
626
354
|
className: "flex flex-row items-center gap-1"
|
|
627
|
-
}, /* @__PURE__ */
|
|
355
|
+
}, /* @__PURE__ */ React4.createElement(Input3.TextInput, {
|
|
628
356
|
placeholder: t("select option label placeholder"),
|
|
629
357
|
ref: selected === item.id ? inputRef : void 0,
|
|
630
358
|
value: item.title,
|
|
@@ -632,33 +360,33 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
632
360
|
onKeyDown: handleKeyDown,
|
|
633
361
|
classNames: "flex-1",
|
|
634
362
|
"data-no-submit": true
|
|
635
|
-
}), /* @__PURE__ */
|
|
363
|
+
}), /* @__PURE__ */ React4.createElement(Toolbar.Root, {
|
|
636
364
|
classNames: "p-0 m-0 !is-auto"
|
|
637
|
-
}, /* @__PURE__ */
|
|
365
|
+
}, /* @__PURE__ */ React4.createElement(HuePicker, {
|
|
638
366
|
value: item.color,
|
|
639
367
|
onChange: handleColorChange(item.id)
|
|
640
|
-
})), /* @__PURE__ */
|
|
368
|
+
})), /* @__PURE__ */ React4.createElement(IconButton, {
|
|
641
369
|
icon: "ph--trash--fill",
|
|
642
370
|
iconOnly: true,
|
|
643
371
|
label: t("select option delete"),
|
|
644
372
|
onClick: () => handleDelete(item.id)
|
|
645
|
-
})))))), /* @__PURE__ */
|
|
373
|
+
})))))), /* @__PURE__ */ React4.createElement("div", {
|
|
646
374
|
role: "listitem"
|
|
647
|
-
}, /* @__PURE__ */
|
|
375
|
+
}, /* @__PURE__ */ React4.createElement("div", {
|
|
648
376
|
role: "button",
|
|
649
377
|
className: mx2("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
|
|
650
378
|
onClick: handleAdd
|
|
651
|
-
}, /* @__PURE__ */
|
|
379
|
+
}, /* @__PURE__ */ React4.createElement("div", {
|
|
652
380
|
className: "flex items-center gap-1"
|
|
653
|
-
}, /* @__PURE__ */
|
|
381
|
+
}, /* @__PURE__ */ React4.createElement(Icon2, {
|
|
654
382
|
icon: "ph--plus--regular"
|
|
655
|
-
}), /* @__PURE__ */
|
|
383
|
+
}), /* @__PURE__ */ React4.createElement("span", {
|
|
656
384
|
className: "text-sm"
|
|
657
385
|
}, t("select option add")))))))));
|
|
658
386
|
};
|
|
659
387
|
|
|
660
388
|
// packages/ui/react-ui-form/src/components/Form/custom/TupleInput.tsx
|
|
661
|
-
import
|
|
389
|
+
import React5 from "react";
|
|
662
390
|
import { Input as Input4 } from "@dxos/react-ui";
|
|
663
391
|
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
664
392
|
import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
|
|
@@ -671,13 +399,13 @@ var gridCols = [
|
|
|
671
399
|
var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
672
400
|
const { status, error } = getStatus();
|
|
673
401
|
const values = getValue3() ?? {};
|
|
674
|
-
return /* @__PURE__ */
|
|
402
|
+
return /* @__PURE__ */ React5.createElement(Input4.Root, {
|
|
675
403
|
validationValence: status
|
|
676
|
-
}, /* @__PURE__ */
|
|
404
|
+
}, /* @__PURE__ */ React5.createElement(InputHeader, {
|
|
677
405
|
error
|
|
678
|
-
}, /* @__PURE__ */
|
|
406
|
+
}, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement("div", {
|
|
679
407
|
className: mx3("grid gap-2", gridCols[binding.length - 1])
|
|
680
|
-
}, binding.map((prop) => /* @__PURE__ */
|
|
408
|
+
}, binding.map((prop) => /* @__PURE__ */ React5.createElement(Input4.TextInput, {
|
|
681
409
|
key: prop,
|
|
682
410
|
type: "number",
|
|
683
411
|
disabled,
|
|
@@ -689,120 +417,402 @@ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValu
|
|
|
689
417
|
onBlur
|
|
690
418
|
}))));
|
|
691
419
|
};
|
|
692
|
-
|
|
693
|
-
// packages/ui/react-ui-form/src/components/Form/Defaults.tsx
|
|
694
|
-
import
|
|
695
|
-
import { Input as Input5, Select } from "@dxos/react-ui";
|
|
696
|
-
var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
697
|
-
const { status, error } = getStatus();
|
|
698
|
-
return /* @__PURE__ */
|
|
699
|
-
validationValence: status
|
|
700
|
-
}, !inputOnly && /* @__PURE__ */
|
|
701
|
-
error
|
|
702
|
-
}, /* @__PURE__ */
|
|
703
|
-
disabled,
|
|
704
|
-
placeholder,
|
|
705
|
-
value: getValue3() ?? "",
|
|
706
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
707
|
-
onBlur
|
|
708
|
-
}), inputOnly && /* @__PURE__ */
|
|
420
|
+
|
|
421
|
+
// packages/ui/react-ui-form/src/components/Form/Defaults.tsx
|
|
422
|
+
import React6, { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
423
|
+
import { Input as Input5, Select } from "@dxos/react-ui";
|
|
424
|
+
var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
425
|
+
const { status, error } = getStatus();
|
|
426
|
+
return /* @__PURE__ */ React6.createElement(Input5.Root, {
|
|
427
|
+
validationValence: status
|
|
428
|
+
}, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
429
|
+
error
|
|
430
|
+
}, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Input5.TextInput, {
|
|
431
|
+
disabled,
|
|
432
|
+
placeholder,
|
|
433
|
+
value: getValue3() ?? "",
|
|
434
|
+
onChange: (event) => onValueChange(type, event.target.value),
|
|
435
|
+
onBlur
|
|
436
|
+
}), inputOnly && /* @__PURE__ */ React6.createElement(Input5.Validation, null, error));
|
|
437
|
+
};
|
|
438
|
+
var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
439
|
+
const { status, error } = getStatus();
|
|
440
|
+
return /* @__PURE__ */ React6.createElement(Input5.Root, {
|
|
441
|
+
validationValence: status
|
|
442
|
+
}, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
443
|
+
error
|
|
444
|
+
}, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Input5.TextInput, {
|
|
445
|
+
type: "number",
|
|
446
|
+
disabled,
|
|
447
|
+
placeholder,
|
|
448
|
+
value: getValue3() ?? 0,
|
|
449
|
+
onChange: (event) => onValueChange(type, event.target.value),
|
|
450
|
+
onBlur
|
|
451
|
+
}), inputOnly && /* @__PURE__ */ React6.createElement(Input5.DescriptionAndValidation, null, error));
|
|
452
|
+
};
|
|
453
|
+
var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
|
|
454
|
+
const { status, error } = getStatus();
|
|
455
|
+
const checked = Boolean(getValue3());
|
|
456
|
+
return /* @__PURE__ */ React6.createElement(Input5.Root, {
|
|
457
|
+
validationValence: status
|
|
458
|
+
}, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
459
|
+
error
|
|
460
|
+
}, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Input5.Switch, {
|
|
461
|
+
checked,
|
|
462
|
+
onCheckedChange: (value) => onValueChange(type, value)
|
|
463
|
+
}), inputOnly && /* @__PURE__ */ React6.createElement(Input5.DescriptionAndValidation, null, error));
|
|
464
|
+
};
|
|
465
|
+
var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
|
|
466
|
+
const { status, error } = getStatus();
|
|
467
|
+
return /* @__PURE__ */ React6.createElement(Input5.Root, {
|
|
468
|
+
validationValence: status
|
|
469
|
+
}, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
470
|
+
error
|
|
471
|
+
}, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Select.Root, {
|
|
472
|
+
value: getValue3(),
|
|
473
|
+
onValueChange: (value) => onValueChange(type, value)
|
|
474
|
+
}, /* @__PURE__ */ React6.createElement(Select.TriggerButton, {
|
|
475
|
+
classNames: "is-full",
|
|
476
|
+
disabled,
|
|
477
|
+
placeholder
|
|
478
|
+
}), /* @__PURE__ */ React6.createElement(Select.Portal, null, /* @__PURE__ */ React6.createElement(Select.Content, null, /* @__PURE__ */ React6.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
|
|
479
|
+
// NOTE: Numeric values are converted to and from strings.
|
|
480
|
+
/* @__PURE__ */ React6.createElement(Select.Option, {
|
|
481
|
+
key: String(value),
|
|
482
|
+
value: String(value)
|
|
483
|
+
}, label2 ?? String(value))
|
|
484
|
+
)))))), inputOnly && /* @__PURE__ */ React6.createElement(Input5.DescriptionAndValidation, null, error));
|
|
485
|
+
};
|
|
486
|
+
var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
487
|
+
const { status, error } = getStatus();
|
|
488
|
+
const textareaRef = useRef2(null);
|
|
489
|
+
const adjustHeight = useCallback3(() => {
|
|
490
|
+
const textarea = textareaRef.current;
|
|
491
|
+
if (textarea) {
|
|
492
|
+
textarea.style.blockSize = "auto";
|
|
493
|
+
textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
|
|
494
|
+
}
|
|
495
|
+
}, []);
|
|
496
|
+
useEffect3(() => {
|
|
497
|
+
adjustHeight();
|
|
498
|
+
}, [
|
|
499
|
+
adjustHeight
|
|
500
|
+
]);
|
|
501
|
+
useEffect3(() => {
|
|
502
|
+
adjustHeight();
|
|
503
|
+
}, [
|
|
504
|
+
getValue3(),
|
|
505
|
+
adjustHeight
|
|
506
|
+
]);
|
|
507
|
+
return /* @__PURE__ */ React6.createElement(Input5.Root, {
|
|
508
|
+
validationValence: status
|
|
509
|
+
}, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
510
|
+
error
|
|
511
|
+
}, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Input5.TextArea, {
|
|
512
|
+
ref: textareaRef,
|
|
513
|
+
disabled,
|
|
514
|
+
placeholder,
|
|
515
|
+
value: getValue3() ?? "",
|
|
516
|
+
classNames: "min-bs-auto max-h-40 overflow-auto",
|
|
517
|
+
onChange: (event) => onValueChange(type, event.target.value),
|
|
518
|
+
onBlur,
|
|
519
|
+
style: {
|
|
520
|
+
resize: "none"
|
|
521
|
+
},
|
|
522
|
+
spellCheck: false
|
|
523
|
+
}), inputOnly && /* @__PURE__ */ React6.createElement(Input5.Validation, null, error));
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
527
|
+
import React11, { useEffect as useEffect6, useMemo as useMemo6, useRef as useRef3 } from "react";
|
|
528
|
+
import { mx as mx7 } from "@dxos/react-ui-theme";
|
|
529
|
+
|
|
530
|
+
// packages/ui/react-ui-form/src/components/Form/FormActions.tsx
|
|
531
|
+
import React8 from "react";
|
|
532
|
+
import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
533
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
534
|
+
|
|
535
|
+
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
536
|
+
import React7, { createContext, useContext, useEffect as useEffect5, useMemo as useMemo3 } from "react";
|
|
537
|
+
import { raise } from "@dxos/debug";
|
|
538
|
+
import { getValue as getValue2 } from "@dxos/echo-schema";
|
|
539
|
+
import { createJsonPath as createJsonPath2 } from "@dxos/effect";
|
|
540
|
+
|
|
541
|
+
// packages/ui/react-ui-form/src/hooks/useForm.ts
|
|
542
|
+
import { SchemaAST as AST } from "effect";
|
|
543
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useState as useState3 } from "react";
|
|
544
|
+
import { getValue, setValue } from "@dxos/echo-schema";
|
|
545
|
+
import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
|
|
546
|
+
import { invariant } from "@dxos/invariant";
|
|
547
|
+
import { log } from "@dxos/log";
|
|
548
|
+
import { validateSchema } from "@dxos/schema";
|
|
549
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
550
|
+
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
551
|
+
invariant(AST.isTypeLiteral(schema.ast), void 0, {
|
|
552
|
+
F: __dxlog_file,
|
|
553
|
+
L: 93,
|
|
554
|
+
S: void 0,
|
|
555
|
+
A: [
|
|
556
|
+
"AST.isTypeLiteral(schema.ast)",
|
|
557
|
+
""
|
|
558
|
+
]
|
|
559
|
+
});
|
|
560
|
+
const [values, setValues] = useState3(initialValues);
|
|
561
|
+
useEffect4(() => {
|
|
562
|
+
setValues(initialValues);
|
|
563
|
+
}, [
|
|
564
|
+
initialValues
|
|
565
|
+
]);
|
|
566
|
+
const [touched, setTouched] = useState3(createKeySet(initialValues, false));
|
|
567
|
+
const [changed, setChanged] = useState3(createKeySet(initialValues, false));
|
|
568
|
+
const [errors, setErrors] = useState3({});
|
|
569
|
+
const [saving, setSaving] = useState3(false);
|
|
570
|
+
const validate = useCallback4((values2) => {
|
|
571
|
+
let errors2 = validateSchema(schema, values2) ?? [];
|
|
572
|
+
if (errors2.length === 0 && onValidate) {
|
|
573
|
+
const validatedValues = values2;
|
|
574
|
+
errors2 = onValidate(validatedValues) ?? [];
|
|
575
|
+
}
|
|
576
|
+
setErrors(flatMap(errors2));
|
|
577
|
+
const valid = errors2.length === 0;
|
|
578
|
+
return valid;
|
|
579
|
+
}, [
|
|
580
|
+
schema,
|
|
581
|
+
onValidate
|
|
582
|
+
]);
|
|
583
|
+
const [schemaDirty, setSchemaDirty] = useState3(false);
|
|
584
|
+
useEffect4(() => setSchemaDirty(true), [
|
|
585
|
+
schema
|
|
586
|
+
]);
|
|
587
|
+
useEffect4(() => {
|
|
588
|
+
if (schemaDirty) {
|
|
589
|
+
validate(values);
|
|
590
|
+
setSchemaDirty(false);
|
|
591
|
+
}
|
|
592
|
+
}, [
|
|
593
|
+
values,
|
|
594
|
+
schemaDirty
|
|
595
|
+
]);
|
|
596
|
+
const formIsValid = useMemo2(() => {
|
|
597
|
+
return Object.keys(errors).length === 0;
|
|
598
|
+
}, [
|
|
599
|
+
errors
|
|
600
|
+
]);
|
|
601
|
+
const canSave = useMemo2(() => !saving && // Check if any error paths that are touched have errors.
|
|
602
|
+
!Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
|
|
603
|
+
touched,
|
|
604
|
+
errors,
|
|
605
|
+
saving
|
|
606
|
+
]);
|
|
607
|
+
const handleSave = useCallback4(async () => {
|
|
608
|
+
if (validate(values)) {
|
|
609
|
+
setSaving(true);
|
|
610
|
+
try {
|
|
611
|
+
await onSave?.(values, {
|
|
612
|
+
changed
|
|
613
|
+
});
|
|
614
|
+
} finally {
|
|
615
|
+
setSaving(false);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}, [
|
|
619
|
+
values,
|
|
620
|
+
validate,
|
|
621
|
+
onSave,
|
|
622
|
+
changed
|
|
623
|
+
]);
|
|
624
|
+
const getStatus = useCallback4((path) => {
|
|
625
|
+
const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
|
|
626
|
+
const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
|
|
627
|
+
const isTouched = touched[jsonPath];
|
|
628
|
+
if (!isTouched) {
|
|
629
|
+
return {
|
|
630
|
+
status: void 0,
|
|
631
|
+
error: void 0
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
return {
|
|
635
|
+
status: matchingError ? "error" : void 0,
|
|
636
|
+
error: matchingError ? matchingError[1] : void 0
|
|
637
|
+
};
|
|
638
|
+
}, [
|
|
639
|
+
errors,
|
|
640
|
+
touched
|
|
641
|
+
]);
|
|
642
|
+
const getFormValue = useCallback4((path) => {
|
|
643
|
+
return getValue(values, createJsonPath(path));
|
|
644
|
+
}, [
|
|
645
|
+
values
|
|
646
|
+
]);
|
|
647
|
+
const onValueChange = useCallback4((path, type, value) => {
|
|
648
|
+
const jsonPath = createJsonPath(path);
|
|
649
|
+
let parsedValue = value;
|
|
650
|
+
try {
|
|
651
|
+
if (type === "number") {
|
|
652
|
+
parsedValue = parseFloat(value) || 0;
|
|
653
|
+
}
|
|
654
|
+
} catch (err) {
|
|
655
|
+
log.catch(err, void 0, {
|
|
656
|
+
F: __dxlog_file,
|
|
657
|
+
L: 212,
|
|
658
|
+
S: void 0,
|
|
659
|
+
C: (f, a) => f(...a)
|
|
660
|
+
});
|
|
661
|
+
parsedValue = void 0;
|
|
662
|
+
}
|
|
663
|
+
const newValues = {
|
|
664
|
+
...setValue(values, jsonPath, parsedValue)
|
|
665
|
+
};
|
|
666
|
+
setValues(newValues);
|
|
667
|
+
setChanged((prev) => ({
|
|
668
|
+
...prev,
|
|
669
|
+
[jsonPath]: true
|
|
670
|
+
}));
|
|
671
|
+
onValuesChanged?.(newValues);
|
|
672
|
+
const isValid = validate(newValues);
|
|
673
|
+
if (isValid && onValid) {
|
|
674
|
+
onValid(newValues, {
|
|
675
|
+
changed
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
}, [
|
|
679
|
+
values,
|
|
680
|
+
onValuesChanged,
|
|
681
|
+
validate,
|
|
682
|
+
onValid,
|
|
683
|
+
changed
|
|
684
|
+
]);
|
|
685
|
+
const onTouched = useCallback4((path) => {
|
|
686
|
+
const jsonPath = createJsonPath(path);
|
|
687
|
+
setTouched((touched2) => ({
|
|
688
|
+
...touched2,
|
|
689
|
+
[jsonPath]: true
|
|
690
|
+
}));
|
|
691
|
+
validate(values);
|
|
692
|
+
}, [
|
|
693
|
+
validate,
|
|
694
|
+
values
|
|
695
|
+
]);
|
|
696
|
+
return useMemo2(() => ({
|
|
697
|
+
// State.
|
|
698
|
+
values,
|
|
699
|
+
errors,
|
|
700
|
+
touched,
|
|
701
|
+
changed,
|
|
702
|
+
canSave,
|
|
703
|
+
formIsValid,
|
|
704
|
+
// Actions.
|
|
705
|
+
handleSave,
|
|
706
|
+
// Field utils.
|
|
707
|
+
getStatus,
|
|
708
|
+
getValue: getFormValue,
|
|
709
|
+
onValueChange,
|
|
710
|
+
onTouched
|
|
711
|
+
}), [
|
|
712
|
+
values,
|
|
713
|
+
errors,
|
|
714
|
+
touched,
|
|
715
|
+
changed,
|
|
716
|
+
canSave,
|
|
717
|
+
formIsValid,
|
|
718
|
+
handleSave,
|
|
719
|
+
getStatus,
|
|
720
|
+
getFormValue,
|
|
721
|
+
onValueChange,
|
|
722
|
+
onTouched
|
|
723
|
+
]);
|
|
724
|
+
};
|
|
725
|
+
var createKeySet = (obj, value) => {
|
|
726
|
+
invariant(obj, void 0, {
|
|
727
|
+
F: __dxlog_file,
|
|
728
|
+
L: 274,
|
|
729
|
+
S: void 0,
|
|
730
|
+
A: [
|
|
731
|
+
"obj",
|
|
732
|
+
""
|
|
733
|
+
]
|
|
734
|
+
});
|
|
735
|
+
return Object.keys(obj).reduce((acc, key) => ({
|
|
736
|
+
...acc,
|
|
737
|
+
[key]: value
|
|
738
|
+
}), {});
|
|
709
739
|
};
|
|
710
|
-
var
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
disabled,
|
|
719
|
-
placeholder,
|
|
720
|
-
value: getValue3() ?? 0,
|
|
721
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
722
|
-
onBlur
|
|
723
|
-
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
740
|
+
var flatMap = (errors) => {
|
|
741
|
+
return errors.reduce((result, { path, message }) => {
|
|
742
|
+
const jsonPath = fromEffectValidationPath(path);
|
|
743
|
+
if (!(jsonPath in result)) {
|
|
744
|
+
result[jsonPath] = message;
|
|
745
|
+
}
|
|
746
|
+
return result;
|
|
747
|
+
}, {});
|
|
724
748
|
};
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
731
|
-
error
|
|
732
|
-
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.Switch, {
|
|
733
|
-
checked,
|
|
734
|
-
onCheckedChange: (value) => onValueChange(type, value)
|
|
735
|
-
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
749
|
+
|
|
750
|
+
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
751
|
+
var FormContext = /* @__PURE__ */ createContext(void 0);
|
|
752
|
+
var useFormContext = () => {
|
|
753
|
+
return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
|
|
736
754
|
};
|
|
737
|
-
var
|
|
738
|
-
const {
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
742
|
-
error
|
|
743
|
-
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Select.Root, {
|
|
744
|
-
value: getValue3(),
|
|
745
|
-
onValueChange: (value) => onValueChange(type, value)
|
|
746
|
-
}, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
|
|
747
|
-
classNames: "is-full",
|
|
748
|
-
disabled,
|
|
749
|
-
placeholder
|
|
750
|
-
}), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
|
|
751
|
-
// NOTE: Numeric values are converted to and from strings.
|
|
752
|
-
/* @__PURE__ */ React7.createElement(Select.Option, {
|
|
753
|
-
key: String(value),
|
|
754
|
-
value: String(value)
|
|
755
|
-
}, label2 ?? String(value))
|
|
756
|
-
)))))), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
755
|
+
var useFormValues = (path = []) => {
|
|
756
|
+
const { values: formValues } = useFormContext();
|
|
757
|
+
const jsonPath = createJsonPath2(path);
|
|
758
|
+
return getValue2(formValues, jsonPath);
|
|
757
759
|
};
|
|
758
|
-
var
|
|
759
|
-
const {
|
|
760
|
-
const
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
760
|
+
var useInputProps = (path = []) => {
|
|
761
|
+
const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
|
|
762
|
+
const stablePath = useMemo3(() => path, [
|
|
763
|
+
Array.isArray(path) ? path.join(".") : path
|
|
764
|
+
]);
|
|
765
|
+
return useMemo3(() => ({
|
|
766
|
+
getStatus: () => getStatus(stablePath),
|
|
767
|
+
getValue: () => getFormValue(stablePath),
|
|
768
|
+
onValueChange: (type, value) => onValueChange(stablePath, type, value),
|
|
769
|
+
onBlur: () => onTouched(stablePath)
|
|
770
|
+
}), [
|
|
771
|
+
getStatus,
|
|
772
|
+
getFormValue,
|
|
773
|
+
onValueChange,
|
|
774
|
+
onTouched,
|
|
775
|
+
stablePath
|
|
772
776
|
]);
|
|
777
|
+
};
|
|
778
|
+
var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
|
|
779
|
+
const form = useForm(formOptions);
|
|
773
780
|
useEffect5(() => {
|
|
774
|
-
|
|
781
|
+
if (!formRef?.current) {
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
const handleKeyDown = (event) => {
|
|
785
|
+
const keyIsEnter = event.key === "Enter";
|
|
786
|
+
const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
|
|
787
|
+
const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
|
|
788
|
+
const inputOptOut = event.target.hasAttribute("data-no-submit");
|
|
789
|
+
const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
|
|
790
|
+
const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
|
|
791
|
+
if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
|
|
792
|
+
if (!autoSave && form.canSave) {
|
|
793
|
+
form.handleSave();
|
|
794
|
+
}
|
|
795
|
+
if (autoSave && form.formIsValid) {
|
|
796
|
+
event.target.blur();
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
const formElement = formRef.current;
|
|
801
|
+
formElement.addEventListener("keydown", handleKeyDown);
|
|
802
|
+
return () => formElement.removeEventListener("keydown", handleKeyDown);
|
|
775
803
|
}, [
|
|
776
|
-
|
|
777
|
-
|
|
804
|
+
formRef,
|
|
805
|
+
form.canSave,
|
|
806
|
+
form.formIsValid,
|
|
807
|
+
form.handleSave,
|
|
808
|
+
autoSave
|
|
778
809
|
]);
|
|
779
|
-
return /* @__PURE__ */ React7.createElement(
|
|
780
|
-
|
|
781
|
-
},
|
|
782
|
-
error
|
|
783
|
-
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.TextArea, {
|
|
784
|
-
ref: textareaRef,
|
|
785
|
-
disabled,
|
|
786
|
-
placeholder,
|
|
787
|
-
value: getValue3() ?? "",
|
|
788
|
-
classNames: "min-bs-auto max-h-40 overflow-auto",
|
|
789
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
790
|
-
onBlur,
|
|
791
|
-
style: {
|
|
792
|
-
resize: "none"
|
|
793
|
-
},
|
|
794
|
-
spellCheck: false
|
|
795
|
-
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.Validation, null, error));
|
|
810
|
+
return /* @__PURE__ */ React7.createElement(FormContext.Provider, {
|
|
811
|
+
value: form
|
|
812
|
+
}, children);
|
|
796
813
|
};
|
|
797
814
|
|
|
798
|
-
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
799
|
-
import React11, { useEffect as useEffect6, useMemo as useMemo6, useRef as useRef3 } from "react";
|
|
800
|
-
import { mx as mx7 } from "@dxos/react-ui-theme";
|
|
801
|
-
|
|
802
815
|
// packages/ui/react-ui-form/src/components/Form/FormActions.tsx
|
|
803
|
-
import React8 from "react";
|
|
804
|
-
import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
805
|
-
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
806
816
|
var FormActions = ({ onCancel, readonly }) => {
|
|
807
817
|
const { t } = useTranslation3(translationKey);
|
|
808
818
|
const { canSave, handleSave } = useFormContext();
|
|
@@ -1306,10 +1316,12 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1306
1316
|
// packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
|
|
1307
1317
|
import React13, { useCallback as useCallback7, useMemo as useMemo8, useState as useState5 } from "react";
|
|
1308
1318
|
import { AST as AST4, Format, S as S2 } from "@dxos/echo-schema";
|
|
1319
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1309
1320
|
import { IconButton as IconButton4, useTranslation as useTranslation6 } from "@dxos/react-ui";
|
|
1310
1321
|
import { List as List2 } from "@dxos/react-ui-list";
|
|
1311
1322
|
import { ghostHover, inputTextLabel, mx as mx8 } from "@dxos/react-ui-theme";
|
|
1312
1323
|
import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1324
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
|
|
1313
1325
|
var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
|
|
1314
1326
|
var ViewMetaSchema = S2.Struct({
|
|
1315
1327
|
name: S2.String.annotations({
|
|
@@ -1336,39 +1348,77 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1336
1348
|
}, [
|
|
1337
1349
|
view
|
|
1338
1350
|
]);
|
|
1339
|
-
const
|
|
1351
|
+
const handleSelect = useCallback7((field2) => {
|
|
1352
|
+
setField((f) => f === field2 ? void 0 : field2);
|
|
1353
|
+
}, []);
|
|
1354
|
+
const handleAdd = useCallback7(() => {
|
|
1355
|
+
invariant3(!schema.readonly, void 0, {
|
|
1356
|
+
F: __dxlog_file4,
|
|
1357
|
+
L: 76,
|
|
1358
|
+
S: void 0,
|
|
1359
|
+
A: [
|
|
1360
|
+
"!schema.readonly",
|
|
1361
|
+
""
|
|
1362
|
+
]
|
|
1363
|
+
});
|
|
1364
|
+
const field2 = projection.createFieldProjection();
|
|
1365
|
+
setField(field2);
|
|
1366
|
+
}, [
|
|
1367
|
+
schema,
|
|
1368
|
+
view
|
|
1369
|
+
]);
|
|
1370
|
+
const handleUpdate = useCallback7(({ name, typename }) => {
|
|
1371
|
+
invariant3(!schema.readonly, void 0, {
|
|
1372
|
+
F: __dxlog_file4,
|
|
1373
|
+
L: 83,
|
|
1374
|
+
S: void 0,
|
|
1375
|
+
A: [
|
|
1376
|
+
"!schema.readonly",
|
|
1377
|
+
""
|
|
1378
|
+
]
|
|
1379
|
+
});
|
|
1340
1380
|
requestAnimationFrame(() => {
|
|
1341
1381
|
if (view.name !== name) {
|
|
1342
1382
|
view.name = name;
|
|
1343
1383
|
}
|
|
1344
1384
|
if (view.query.typename !== typename) {
|
|
1345
|
-
onTypenameChanged(typename);
|
|
1385
|
+
onTypenameChanged?.(typename);
|
|
1346
1386
|
}
|
|
1347
1387
|
});
|
|
1348
1388
|
}, [
|
|
1349
|
-
view,
|
|
1350
1389
|
schema,
|
|
1390
|
+
view,
|
|
1351
1391
|
onTypenameChanged
|
|
1352
1392
|
]);
|
|
1353
|
-
const handleSelect = useCallback7((field2) => {
|
|
1354
|
-
setField((f) => f === field2 ? void 0 : field2);
|
|
1355
|
-
}, []);
|
|
1356
|
-
const handleAdd = useCallback7(() => {
|
|
1357
|
-
const field2 = projection.createFieldProjection();
|
|
1358
|
-
setField(field2);
|
|
1359
|
-
}, [
|
|
1360
|
-
view
|
|
1361
|
-
]);
|
|
1362
1393
|
const handleDelete = useCallback7((fieldId) => {
|
|
1394
|
+
invariant3(!schema.readonly, void 0, {
|
|
1395
|
+
F: __dxlog_file4,
|
|
1396
|
+
L: 99,
|
|
1397
|
+
S: void 0,
|
|
1398
|
+
A: [
|
|
1399
|
+
"!schema.readonly",
|
|
1400
|
+
""
|
|
1401
|
+
]
|
|
1402
|
+
});
|
|
1363
1403
|
if (fieldId === field?.id) {
|
|
1364
1404
|
setField(void 0);
|
|
1365
1405
|
}
|
|
1366
|
-
onDelete(fieldId);
|
|
1406
|
+
onDelete?.(fieldId);
|
|
1367
1407
|
}, [
|
|
1368
|
-
|
|
1369
|
-
field
|
|
1408
|
+
schema,
|
|
1409
|
+
field,
|
|
1410
|
+
onDelete
|
|
1370
1411
|
]);
|
|
1371
1412
|
const handleMove = useCallback7((fromIndex, toIndex) => {
|
|
1413
|
+
invariant3(!schema.readonly, void 0, {
|
|
1414
|
+
F: __dxlog_file4,
|
|
1415
|
+
L: 111,
|
|
1416
|
+
S: void 0,
|
|
1417
|
+
A: [
|
|
1418
|
+
"!schema.readonly",
|
|
1419
|
+
""
|
|
1420
|
+
]
|
|
1421
|
+
});
|
|
1372
1422
|
const fields = [
|
|
1373
1423
|
...view.fields
|
|
1374
1424
|
];
|
|
@@ -1376,6 +1426,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1376
1426
|
fields.splice(toIndex, 0, moved);
|
|
1377
1427
|
view.fields = fields;
|
|
1378
1428
|
}, [
|
|
1429
|
+
schema,
|
|
1379
1430
|
view.fields
|
|
1380
1431
|
]);
|
|
1381
1432
|
const handleClose = useCallback7(() => setField(void 0), []);
|
|
@@ -1399,7 +1450,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1399
1450
|
autoSave: true,
|
|
1400
1451
|
schema: ViewMetaSchema,
|
|
1401
1452
|
values: viewValues,
|
|
1402
|
-
onSave:
|
|
1453
|
+
onSave: schema.readonly ? void 0 : handleUpdate
|
|
1403
1454
|
}), /* @__PURE__ */ React13.createElement("div", null, /* @__PURE__ */ React13.createElement("div", {
|
|
1404
1455
|
role: "none",
|
|
1405
1456
|
className: "p-2"
|
|
@@ -1409,7 +1460,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1409
1460
|
items: view.fields,
|
|
1410
1461
|
isItem: S2.is(FieldSchema),
|
|
1411
1462
|
getId: (field2) => field2.id,
|
|
1412
|
-
onMove: handleMove
|
|
1463
|
+
onMove: schema.readonly ? void 0 : handleMove
|
|
1413
1464
|
}, ({ items: fields }) => /* @__PURE__ */ React13.createElement(React13.Fragment, null, showHeading && /* @__PURE__ */ React13.createElement("div", {
|
|
1414
1465
|
role: "heading",
|
|
1415
1466
|
className: grid
|
|
@@ -1430,7 +1481,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1430
1481
|
icon: "ph--eye-slash--regular",
|
|
1431
1482
|
disabled: view.fields.length <= 1,
|
|
1432
1483
|
onClick: () => handleHide(field2.id)
|
|
1433
|
-
}), /* @__PURE__ */ React13.createElement(List2.ItemDeleteButton, {
|
|
1484
|
+
}), !schema.readonly && /* @__PURE__ */ React13.createElement(List2.ItemDeleteButton, {
|
|
1434
1485
|
icon: "ph--trash--regular",
|
|
1435
1486
|
disabled: view.fields.length <= 1,
|
|
1436
1487
|
onClick: () => handleDelete(field2.id)
|
|
@@ -1465,7 +1516,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1465
1516
|
}, /* @__PURE__ */ React13.createElement(IconButton4, {
|
|
1466
1517
|
icon: "ph--plus--regular",
|
|
1467
1518
|
label: t("button add property"),
|
|
1468
|
-
onClick: handleAdd,
|
|
1519
|
+
onClick: schema.readonly ? void 0 : handleAdd,
|
|
1469
1520
|
// TODO(burdon): Show field limit in ux (not tooltip).
|
|
1470
1521
|
disabled: view.fields.length >= VIEW_FIELD_LIMIT
|
|
1471
1522
|
})));
|
|
@@ -1588,6 +1639,7 @@ var cellClassesForFieldType = ({ type, format }) => {
|
|
|
1588
1639
|
"text-right"
|
|
1589
1640
|
];
|
|
1590
1641
|
case FormatEnum3.JSON:
|
|
1642
|
+
case FormatEnum3.DID:
|
|
1591
1643
|
return [
|
|
1592
1644
|
"font-mono"
|
|
1593
1645
|
];
|
|
@@ -1736,6 +1788,7 @@ export {
|
|
|
1736
1788
|
DeprecatedFormInput,
|
|
1737
1789
|
FieldEditor,
|
|
1738
1790
|
Form,
|
|
1791
|
+
FormProvider,
|
|
1739
1792
|
GeoPointInput,
|
|
1740
1793
|
InputHeader,
|
|
1741
1794
|
MarkdownInput,
|
|
@@ -1753,6 +1806,8 @@ export {
|
|
|
1753
1806
|
pathNotUniqueError,
|
|
1754
1807
|
translations_default as translations,
|
|
1755
1808
|
useForm,
|
|
1756
|
-
|
|
1809
|
+
useFormContext,
|
|
1810
|
+
useFormValues,
|
|
1811
|
+
useInputProps
|
|
1757
1812
|
};
|
|
1758
1813
|
//# sourceMappingURL=index.mjs.map
|