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