@dxos/react-ui-form 0.8.1-main.ba2dec9 → 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.
@@ -33,6 +33,7 @@ __export(node_exports, {
33
33
  DeprecatedFormInput: () => DeprecatedFormInput,
34
34
  FieldEditor: () => FieldEditor,
35
35
  Form: () => Form,
36
+ FormProvider: () => FormProvider,
36
37
  GeoPointInput: () => GeoPointInput,
37
38
  InputHeader: () => InputHeader,
38
39
  MarkdownInput: () => MarkdownInput,
@@ -50,7 +51,9 @@ __export(node_exports, {
50
51
  pathNotUniqueError: () => pathNotUniqueError,
51
52
  translations: () => translations_default,
52
53
  useForm: () => useForm,
53
- useFormValues: () => useFormValues
54
+ useFormContext: () => useFormContext,
55
+ useFormValues: () => useFormValues,
56
+ useInputProps: () => useInputProps
54
57
  });
55
58
  module.exports = __toCommonJS(node_exports);
56
59
  var import_react = __toESM(require("react"));
@@ -62,40 +65,40 @@ var import_log = require("@dxos/log");
62
65
  var import_react_ui2 = require("@dxos/react-ui");
63
66
  var import_schema = require("@dxos/schema");
64
67
  var import_react3 = __toESM(require("react"));
65
- var import_debug = require("@dxos/debug");
66
68
  var import_echo_schema2 = require("@dxos/echo-schema");
67
- var import_effect = require("@dxos/effect");
68
- var import_effect2 = require("effect");
69
- var import_react4 = require("react");
70
- var import_echo_schema3 = require("@dxos/echo-schema");
71
- var import_effect3 = require("@dxos/effect");
72
- var import_invariant = require("@dxos/invariant");
73
- var import_log2 = require("@dxos/log");
74
- var import_schema2 = require("@dxos/schema");
75
- var import_react5 = __toESM(require("react"));
76
- var import_echo_schema4 = require("@dxos/echo-schema");
77
69
  var import_react_ui3 = require("@dxos/react-ui");
78
70
  var import_util = require("@dxos/util");
79
- var import_react6 = __toESM(require("react"));
71
+ var import_react4 = __toESM(require("react"));
80
72
  var import_react_ui4 = require("@dxos/react-ui");
81
73
  var import_react_ui_theme2 = require("@dxos/react-ui-theme");
82
- var import_react7 = __toESM(require("react"));
74
+ var import_react5 = __toESM(require("react"));
83
75
  var import_keys = require("@dxos/keys");
84
76
  var import_react_ui5 = require("@dxos/react-ui");
85
77
  var import_react_ui_list = require("@dxos/react-ui-list");
86
78
  var import_react_ui_pickers = require("@dxos/react-ui-pickers");
87
79
  var import_react_ui_theme3 = require("@dxos/react-ui-theme");
88
- var import_react8 = __toESM(require("react"));
80
+ var import_react6 = __toESM(require("react"));
89
81
  var import_react_ui6 = require("@dxos/react-ui");
90
82
  var import_react_ui_theme4 = require("@dxos/react-ui-theme");
91
83
  var import_util2 = require("@dxos/util");
92
- var import_react9 = __toESM(require("react"));
84
+ var import_react7 = __toESM(require("react"));
93
85
  var import_react_ui7 = require("@dxos/react-ui");
94
- var import_react10 = __toESM(require("react"));
86
+ var import_react8 = __toESM(require("react"));
95
87
  var import_react_ui_theme5 = require("@dxos/react-ui-theme");
96
- var import_react11 = __toESM(require("react"));
88
+ var import_react9 = __toESM(require("react"));
97
89
  var import_react_ui8 = require("@dxos/react-ui");
98
90
  var import_react_ui_theme6 = require("@dxos/react-ui-theme");
91
+ var import_react10 = __toESM(require("react"));
92
+ var import_debug = require("@dxos/debug");
93
+ var import_echo_schema3 = require("@dxos/echo-schema");
94
+ var import_effect = require("@dxos/effect");
95
+ var import_effect2 = require("effect");
96
+ var import_react11 = require("react");
97
+ var import_echo_schema4 = require("@dxos/echo-schema");
98
+ var import_effect3 = require("@dxos/effect");
99
+ var import_invariant = require("@dxos/invariant");
100
+ var import_log2 = require("@dxos/log");
101
+ var import_schema2 = require("@dxos/schema");
99
102
  var import_effect4 = require("effect");
100
103
  var import_String = require("effect/String");
101
104
  var import_react12 = __toESM(require("react"));
@@ -116,6 +119,7 @@ var import_schema4 = require("@dxos/schema");
116
119
  var import_echo_schema7 = require("@dxos/echo-schema");
117
120
  var import_react14 = __toESM(require("react"));
118
121
  var import_echo_schema8 = require("@dxos/echo-schema");
122
+ var import_invariant3 = require("@dxos/invariant");
119
123
  var import_react_ui10 = require("@dxos/react-ui");
120
124
  var import_react_ui_list2 = require("@dxos/react-ui-list");
121
125
  var import_react_ui_theme9 = require("@dxos/react-ui-theme");
@@ -216,662 +220,670 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
216
220
  }
217
221
  return primary;
218
222
  };
219
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
220
- var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
221
- (0, import_invariant.invariant)(import_effect2.SchemaAST.isTypeLiteral(schema.ast), void 0, {
222
- F: __dxlog_file,
223
- L: 93,
224
- S: void 0,
225
- A: [
226
- "AST.isTypeLiteral(schema.ast)",
227
- ""
228
- ]
229
- });
230
- const [values, setValues] = (0, import_react4.useState)(initialValues);
231
- (0, import_react4.useEffect)(() => {
232
- setValues(initialValues);
223
+ var InputHeader = ({ children, error }) => {
224
+ return /* @__PURE__ */ import_react4.default.createElement("div", {
225
+ role: "none",
226
+ className: "flex justify-between items-center mb-1"
227
+ }, children, error && /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Root, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Trigger, {
228
+ asChild: true
229
+ }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Icon, {
230
+ icon: "ph--warning--regular",
231
+ size: 4,
232
+ classNames: import_react_ui_theme2.errorText
233
+ })), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Content, {
234
+ side: "bottom"
235
+ }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Arrow, null), error)));
236
+ };
237
+ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
238
+ const { t } = (0, import_react_ui3.useTranslation)(translationKey);
239
+ const { status, error } = getStatus();
240
+ const geoPoint = (0, import_react3.useMemo)(() => getValue3() ?? [
241
+ 0,
242
+ 0
243
+ ], [
244
+ getValue3
245
+ ]);
246
+ const geoLocation = (0, import_react3.useMemo)(() => import_echo_schema2.GeoLocation.fromGeoPoint(geoPoint), [
247
+ geoPoint
248
+ ]);
249
+ const [longitudeText, setLongitudeText] = (0, import_react3.useState)(geoLocation.longitude?.toString());
250
+ const [latitudeText, setLatitudeText] = (0, import_react3.useState)(geoLocation.latitude?.toString());
251
+ (0, import_react3.useEffect)(() => {
252
+ const location = import_echo_schema2.GeoLocation.fromGeoPoint(geoPoint);
253
+ setLongitudeText(location.longitude.toString());
254
+ setLatitudeText(location.latitude.toString());
233
255
  }, [
234
- initialValues
256
+ geoPoint
235
257
  ]);
236
- const [touched, setTouched] = (0, import_react4.useState)(createKeySet(initialValues, false));
237
- const [changed, setChanged] = (0, import_react4.useState)(createKeySet(initialValues, false));
238
- const [errors, setErrors] = (0, import_react4.useState)({});
239
- const [saving, setSaving] = (0, import_react4.useState)(false);
240
- const validate = (0, import_react4.useCallback)((values2) => {
241
- let errors2 = (0, import_schema2.validateSchema)(schema, values2) ?? [];
242
- if (errors2.length === 0 && onValidate) {
243
- const validatedValues = values2;
244
- errors2 = onValidate(validatedValues) ?? [];
258
+ const handleCoordinateChange = (0, import_react3.useCallback)((coordinateType, setText) => (event) => {
259
+ const inputText = event.target.value;
260
+ setText(inputText);
261
+ if (inputText !== "" && inputText !== "-") {
262
+ const coord = (0, import_util.safeParseFloat)(inputText);
263
+ if (coord !== void 0 && !isNaN(coord)) {
264
+ const currentLocation = import_echo_schema2.GeoLocation.fromGeoPoint(getValue3() ?? [
265
+ 0,
266
+ 0
267
+ ]);
268
+ const newLocation = {
269
+ ...currentLocation,
270
+ [coordinateType]: coord
271
+ };
272
+ const newValue = import_echo_schema2.GeoLocation.toGeoPoint(newLocation);
273
+ onValueChange(type, newValue);
274
+ }
245
275
  }
246
- setErrors(flatMap(errors2));
247
- const valid = errors2.length === 0;
248
- return valid;
249
276
  }, [
250
- schema,
251
- onValidate
252
- ]);
253
- const [schemaDirty, setSchemaDirty] = (0, import_react4.useState)(false);
254
- (0, import_react4.useEffect)(() => setSchemaDirty(true), [
255
- schema
277
+ getValue3,
278
+ onValueChange,
279
+ type
256
280
  ]);
257
- (0, import_react4.useEffect)(() => {
258
- if (schemaDirty) {
259
- validate(values);
260
- setSchemaDirty(false);
281
+ return /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.Root, {
282
+ validationValence: status
283
+ }, /* @__PURE__ */ import_react3.default.createElement(InputHeader, {
284
+ error
285
+ }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.Label, null, label)), /* @__PURE__ */ import_react3.default.createElement("div", {
286
+ role: "none",
287
+ className: "grid grid-cols-2 gap-2"
288
+ }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.TextInput, {
289
+ type: "text",
290
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
291
+ disabled,
292
+ placeholder: t("placeholder latitude"),
293
+ value: latitudeText,
294
+ onChange: handleCoordinateChange("latitude", setLatitudeText),
295
+ onBlur
296
+ }), /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.TextInput, {
297
+ type: "text",
298
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
299
+ disabled,
300
+ placeholder: t("placeholder longitude"),
301
+ value: longitudeText,
302
+ onChange: handleCoordinateChange("longitude", setLongitudeText),
303
+ onBlur
304
+ })));
305
+ };
306
+ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
307
+ const [selected, setSelectedId] = (0, import_react5.useState)(null);
308
+ const [isNewOption, setIsNewOption] = (0, import_react5.useState)(false);
309
+ const inputRef = (0, import_react5.useRef)(null);
310
+ const { t } = (0, import_react_ui5.useTranslation)(translationKey);
311
+ const { status, error } = getStatus();
312
+ const options = getValue3();
313
+ (0, import_react5.useEffect)(() => {
314
+ if (options === void 0) {
315
+ onValueChange(type, []);
261
316
  }
262
317
  }, [
263
- values,
264
- schemaDirty
318
+ options,
319
+ onValueChange,
320
+ type
265
321
  ]);
266
- const formIsValid = (0, import_react4.useMemo)(() => {
267
- return Object.keys(errors).length === 0;
322
+ const randomHue = () => {
323
+ const usedHues = new Set(options?.map((option) => option.color) ?? []);
324
+ const unusedHues = import_react_ui_theme3.hues.filter((hue) => !usedHues.has(hue));
325
+ if (unusedHues.length > 0) {
326
+ return unusedHues[Math.floor(Math.random() * unusedHues.length)];
327
+ }
328
+ const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
329
+ const availableHues = import_react_ui_theme3.hues.filter((hue) => !lastThree.has(hue));
330
+ return availableHues[Math.floor(Math.random() * availableHues.length)] ?? import_react_ui_theme3.hues[Math.floor(Math.random() * import_react_ui_theme3.hues.length)];
331
+ };
332
+ const handleAdd = (0, import_react5.useCallback)(() => {
333
+ const newId = import_keys.PublicKey.random().truncate();
334
+ const newOption = {
335
+ id: newId,
336
+ title: "",
337
+ color: randomHue()
338
+ };
339
+ onValueChange(type, [
340
+ ...options ?? [],
341
+ newOption
342
+ ]);
343
+ setSelectedId(newId);
344
+ setIsNewOption(true);
268
345
  }, [
269
- errors
346
+ options,
347
+ type,
348
+ onValueChange
270
349
  ]);
271
- const canSave = (0, import_react4.useMemo)(() => !saving && // Check if any error paths that are touched have errors.
272
- !Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
273
- touched,
274
- errors,
275
- saving
350
+ const handleDelete = (0, import_react5.useCallback)((id) => {
351
+ const newOptions = options?.filter((option) => option.id !== id) ?? [];
352
+ onValueChange(type, newOptions);
353
+ setSelectedId(null);
354
+ }, [
355
+ options,
356
+ type,
357
+ onValueChange
276
358
  ]);
277
- const handleSave = (0, import_react4.useCallback)(async () => {
278
- if (validate(values)) {
279
- setSaving(true);
280
- try {
281
- await onSave?.(values, {
282
- changed
283
- });
284
- } finally {
285
- setSaving(false);
286
- }
359
+ const handleMove = (0, import_react5.useCallback)((from, to) => {
360
+ if (!options) {
361
+ return;
287
362
  }
363
+ const newOptions = [
364
+ ...options
365
+ ];
366
+ const [removed] = newOptions.splice(from, 1);
367
+ newOptions.splice(to, 0, removed);
368
+ onValueChange(type, newOptions);
288
369
  }, [
289
- values,
290
- validate,
291
- onSave,
292
- changed
370
+ options,
371
+ type,
372
+ onValueChange
293
373
  ]);
294
- const getStatus = (0, import_react4.useCallback)((path) => {
295
- const jsonPath = Array.isArray(path) ? (0, import_effect3.createJsonPath)(path) : path;
296
- const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
297
- return {
298
- status: matchingError ? "error" : void 0,
299
- error: matchingError ? matchingError[1] : void 0
300
- };
374
+ const handleClick = (0, import_react5.useCallback)((id) => {
375
+ setSelectedId((current) => current === id ? null : id);
376
+ }, []);
377
+ const handleTitleChange = (0, import_react5.useCallback)((id) => (e) => {
378
+ const newOptions = options?.map((o) => o.id === id ? {
379
+ ...o,
380
+ title: e.target.value
381
+ } : o);
382
+ onValueChange(type, newOptions ?? []);
301
383
  }, [
302
- errors
384
+ options,
385
+ type,
386
+ onValueChange
303
387
  ]);
304
- const getFormValue = (0, import_react4.useCallback)((path) => {
305
- return (0, import_echo_schema3.getValue)(values, (0, import_effect3.createJsonPath)(path));
388
+ const handleKeyDown = (0, import_react5.useCallback)((e) => {
389
+ if (e.key === "Enter") {
390
+ setSelectedId(null);
391
+ }
392
+ }, []);
393
+ const handleColorChange = (0, import_react5.useCallback)((id) => (hue) => {
394
+ const newOptions = options?.map((o) => o.id === id ? {
395
+ ...o,
396
+ color: hue
397
+ } : o);
398
+ onValueChange(type, newOptions ?? []);
306
399
  }, [
307
- values
400
+ options,
401
+ type,
402
+ onValueChange
308
403
  ]);
309
- const onValueChange = (0, import_react4.useCallback)((path, type, value) => {
310
- const jsonPath = (0, import_effect3.createJsonPath)(path);
311
- let parsedValue = value;
312
- try {
313
- if (type === "number") {
314
- parsedValue = parseFloat(value) || 0;
315
- }
316
- } catch (err) {
317
- import_log2.log.catch(err, void 0, {
318
- F: __dxlog_file,
319
- L: 203,
320
- S: void 0,
321
- C: (f, a) => f(...a)
322
- });
323
- parsedValue = void 0;
324
- }
325
- const newValues = {
326
- ...(0, import_echo_schema3.setValue)(values, jsonPath, parsedValue)
327
- };
328
- setValues(newValues);
329
- setChanged((prev) => ({
330
- ...prev,
331
- [jsonPath]: true
332
- }));
333
- onValuesChanged?.(newValues);
334
- const isValid = validate(newValues);
335
- if (isValid && onValid) {
336
- onValid(newValues, {
337
- changed
338
- });
404
+ (0, import_react5.useEffect)(() => {
405
+ if (selected && isNewOption && inputRef.current) {
406
+ inputRef.current.focus();
407
+ setIsNewOption(false);
339
408
  }
340
409
  }, [
341
- values,
342
- onValuesChanged,
343
- validate,
344
- onValid,
345
- changed
410
+ selected,
411
+ isNewOption
346
412
  ]);
347
- const onTouched = (0, import_react4.useCallback)((path) => {
348
- const jsonPath = (0, import_effect3.createJsonPath)(path);
349
- setTouched((touched2) => ({
350
- ...touched2,
351
- [jsonPath]: true
352
- }));
353
- validate(values);
413
+ return /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Root, {
414
+ validationValence: status
415
+ }, /* @__PURE__ */ import_react5.default.createElement(InputHeader, {
416
+ error
417
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Label, null, label)), /* @__PURE__ */ import_react5.default.createElement("div", {
418
+ role: "none"
419
+ }, options && /* @__PURE__ */ import_react5.default.createElement(import_react_ui_list.List.Root, {
420
+ items: options,
421
+ isItem: (item) => true,
422
+ onMove: handleMove
423
+ }, ({ items }) => /* @__PURE__ */ import_react5.default.createElement("div", {
424
+ role: "list",
425
+ className: "w-full overflow-auto"
426
+ }, items?.map((item) => /* @__PURE__ */ import_react5.default.createElement("div", {
427
+ key: item.id
428
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui_list.List.Item, {
429
+ role: "button",
430
+ item,
431
+ classNames: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
432
+ "aria-expanded": selected === item.id
433
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
434
+ className: "flex items-center"
435
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui_list.List.ItemDragHandle, null), /* @__PURE__ */ import_react5.default.createElement(import_react_ui_list.List.ItemTitle, {
436
+ onClick: () => handleClick(item.id),
437
+ classNames: "flex-1"
438
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Tag, {
439
+ palette: item.color
440
+ }, item.title || "\u200B")), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Icon, {
441
+ icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
442
+ onClick: () => handleClick(item.id)
443
+ })), selected === item.id && /* @__PURE__ */ import_react5.default.createElement("div", {
444
+ className: "mis-4 mbs-2 flex flex-col gap-1"
445
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Label, {
446
+ classNames: "text-xs"
447
+ }, t("select option label")), /* @__PURE__ */ import_react5.default.createElement("div", {
448
+ className: "flex flex-row items-center gap-1"
449
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.TextInput, {
450
+ placeholder: t("select option label placeholder"),
451
+ ref: selected === item.id ? inputRef : void 0,
452
+ value: item.title,
453
+ onChange: handleTitleChange(item.id),
454
+ onKeyDown: handleKeyDown,
455
+ classNames: "flex-1",
456
+ "data-no-submit": true
457
+ }), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Toolbar.Root, {
458
+ classNames: "p-0 m-0 !is-auto"
459
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui_pickers.HuePicker, {
460
+ value: item.color,
461
+ onChange: handleColorChange(item.id)
462
+ })), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.IconButton, {
463
+ icon: "ph--trash--fill",
464
+ iconOnly: true,
465
+ label: t("select option delete"),
466
+ onClick: () => handleDelete(item.id)
467
+ })))))), /* @__PURE__ */ import_react5.default.createElement("div", {
468
+ role: "listitem"
469
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
470
+ role: "button",
471
+ className: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
472
+ onClick: handleAdd
473
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
474
+ className: "flex items-center gap-1"
475
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Icon, {
476
+ icon: "ph--plus--regular"
477
+ }), /* @__PURE__ */ import_react5.default.createElement("span", {
478
+ className: "text-sm"
479
+ }, t("select option add")))))))));
480
+ };
481
+ var gridCols = [
482
+ "grid-cols-1",
483
+ "grid-cols-2",
484
+ "grid-cols-3",
485
+ "grid-cols-4"
486
+ ];
487
+ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
488
+ const { status, error } = getStatus();
489
+ const values = getValue3() ?? {};
490
+ return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
491
+ validationValence: status
492
+ }, /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
493
+ error
494
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement("div", {
495
+ className: (0, import_react_ui_theme4.mx)("grid gap-2", gridCols[binding.length - 1])
496
+ }, binding.map((prop) => /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.TextInput, {
497
+ key: prop,
498
+ type: "number",
499
+ disabled,
500
+ value: values[prop],
501
+ onChange: (event) => onValueChange(type, {
502
+ ...values,
503
+ [prop]: (0, import_util2.safeParseFloat)(event.target.value, 0)
504
+ }),
505
+ onBlur
506
+ }))));
507
+ };
508
+ var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
509
+ const { status, error } = getStatus();
510
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
511
+ validationValence: status
512
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
513
+ error
514
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.TextInput, {
515
+ disabled,
516
+ placeholder,
517
+ value: getValue3() ?? "",
518
+ onChange: (event) => onValueChange(type, event.target.value),
519
+ onBlur
520
+ }), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Validation, null, error));
521
+ };
522
+ var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
523
+ const { status, error } = getStatus();
524
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
525
+ validationValence: status
526
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
527
+ error
528
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.TextInput, {
529
+ type: "number",
530
+ disabled,
531
+ placeholder,
532
+ value: getValue3() ?? 0,
533
+ onChange: (event) => onValueChange(type, event.target.value),
534
+ onBlur
535
+ }), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
536
+ };
537
+ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
538
+ const { status, error } = getStatus();
539
+ const checked = Boolean(getValue3());
540
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
541
+ validationValence: status
542
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
543
+ error
544
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Switch, {
545
+ checked,
546
+ onCheckedChange: (value) => onValueChange(type, value)
547
+ }), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
548
+ };
549
+ var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
550
+ const { status, error } = getStatus();
551
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
552
+ validationValence: status
553
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
554
+ error
555
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Root, {
556
+ value: getValue3(),
557
+ onValueChange: (value) => onValueChange(type, value)
558
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.TriggerButton, {
559
+ classNames: "is-full",
560
+ disabled,
561
+ placeholder
562
+ }), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Portal, null, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Content, null, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Viewport, null, options?.map(({ value, label: label2 }) => (
563
+ // NOTE: Numeric values are converted to and from strings.
564
+ /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Option, {
565
+ key: String(value),
566
+ value: String(value)
567
+ }, label2 ?? String(value))
568
+ )))))), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
569
+ };
570
+ var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
571
+ const { status, error } = getStatus();
572
+ const textareaRef = (0, import_react7.useRef)(null);
573
+ const adjustHeight = (0, import_react7.useCallback)(() => {
574
+ const textarea = textareaRef.current;
575
+ if (textarea) {
576
+ textarea.style.blockSize = "auto";
577
+ textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
578
+ }
579
+ }, []);
580
+ (0, import_react7.useEffect)(() => {
581
+ adjustHeight();
354
582
  }, [
355
- validate,
356
- values
583
+ adjustHeight
357
584
  ]);
358
- return (0, import_react4.useMemo)(() => ({
359
- // State.
360
- values,
361
- errors,
362
- touched,
363
- changed,
364
- canSave,
365
- formIsValid,
366
- // Actions.
367
- handleSave,
368
- // Field utils.
369
- getStatus,
370
- getValue: getFormValue,
371
- onValueChange,
372
- onTouched
373
- }), [
374
- values,
375
- errors,
376
- touched,
377
- changed,
378
- canSave,
379
- formIsValid,
380
- handleSave,
381
- getStatus,
382
- getFormValue,
383
- onValueChange,
384
- onTouched
585
+ (0, import_react7.useEffect)(() => {
586
+ adjustHeight();
587
+ }, [
588
+ getValue3(),
589
+ adjustHeight
385
590
  ]);
591
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
592
+ validationValence: status
593
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
594
+ error
595
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.TextArea, {
596
+ ref: textareaRef,
597
+ disabled,
598
+ placeholder,
599
+ value: getValue3() ?? "",
600
+ classNames: "min-bs-auto max-h-40 overflow-auto",
601
+ onChange: (event) => onValueChange(type, event.target.value),
602
+ onBlur,
603
+ style: {
604
+ resize: "none"
605
+ },
606
+ spellCheck: false
607
+ }), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Validation, null, error));
386
608
  };
387
- var createKeySet = (obj, value) => {
388
- (0, import_invariant.invariant)(obj, void 0, {
609
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
610
+ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
611
+ (0, import_invariant.invariant)(import_effect2.SchemaAST.isTypeLiteral(schema.ast), void 0, {
389
612
  F: __dxlog_file,
390
- L: 265,
613
+ L: 93,
391
614
  S: void 0,
392
615
  A: [
393
- "obj",
616
+ "AST.isTypeLiteral(schema.ast)",
394
617
  ""
395
618
  ]
396
619
  });
397
- return Object.keys(obj).reduce((acc, key) => ({
398
- ...acc,
399
- [key]: value
400
- }), {});
401
- };
402
- var flatMap = (errors) => {
403
- return errors.reduce((result, { path, message }) => {
404
- const jsonPath = (0, import_effect3.fromEffectValidationPath)(path);
405
- if (!(jsonPath in result)) {
406
- result[jsonPath] = message;
407
- }
408
- return result;
409
- }, {});
410
- };
411
- var FormContext = /* @__PURE__ */ (0, import_react3.createContext)(void 0);
412
- var useFormContext = () => {
413
- return (0, import_react3.useContext)(FormContext) ?? (0, import_debug.raise)(new Error("Missing FormContext"));
414
- };
415
- var useFormValues = (path = []) => {
416
- const { values: formValues } = useFormContext();
417
- const jsonPath = (0, import_effect.createJsonPath)(path);
418
- return (0, import_echo_schema2.getValue)(formValues, jsonPath);
419
- };
420
- var useInputProps = (path = []) => {
421
- const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
422
- const stablePath = (0, import_react3.useMemo)(() => path, [
423
- Array.isArray(path) ? path.join(".") : path
424
- ]);
425
- return (0, import_react3.useMemo)(() => ({
426
- getStatus: () => getStatus(stablePath),
427
- getValue: () => getFormValue(stablePath),
428
- onValueChange: (type, value) => onValueChange(stablePath, type, value),
429
- onBlur: () => onTouched(stablePath)
430
- }), [
431
- getStatus,
432
- getFormValue,
433
- onValueChange,
434
- onTouched,
435
- stablePath
620
+ const [values, setValues] = (0, import_react11.useState)(initialValues);
621
+ (0, import_react11.useEffect)(() => {
622
+ setValues(initialValues);
623
+ }, [
624
+ initialValues
436
625
  ]);
437
- };
438
- var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
439
- const form = useForm(formOptions);
440
- (0, import_react3.useEffect)(() => {
441
- if (!formRef?.current) {
442
- return;
626
+ const [touched, setTouched] = (0, import_react11.useState)(createKeySet(initialValues, false));
627
+ const [changed, setChanged] = (0, import_react11.useState)(createKeySet(initialValues, false));
628
+ const [errors, setErrors] = (0, import_react11.useState)({});
629
+ const [saving, setSaving] = (0, import_react11.useState)(false);
630
+ const validate = (0, import_react11.useCallback)((values2) => {
631
+ let errors2 = (0, import_schema2.validateSchema)(schema, values2) ?? [];
632
+ if (errors2.length === 0 && onValidate) {
633
+ const validatedValues = values2;
634
+ errors2 = onValidate(validatedValues) ?? [];
443
635
  }
444
- const handleKeyDown = (event) => {
445
- const keyIsEnter = event.key === "Enter";
446
- const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
447
- const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
448
- const inputOptOut = event.target.hasAttribute("data-no-submit");
449
- const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
450
- const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
451
- if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
452
- if (!autoSave && form.canSave) {
453
- form.handleSave();
454
- }
455
- if (autoSave && form.formIsValid) {
456
- event.target.blur();
457
- }
458
- }
459
- };
460
- const formElement = formRef.current;
461
- formElement.addEventListener("keydown", handleKeyDown);
462
- return () => formElement.removeEventListener("keydown", handleKeyDown);
636
+ setErrors(flatMap(errors2));
637
+ const valid = errors2.length === 0;
638
+ return valid;
463
639
  }, [
464
- formRef,
465
- form.canSave,
466
- form.formIsValid,
467
- form.handleSave,
468
- autoSave
469
- ]);
470
- return /* @__PURE__ */ import_react3.default.createElement(FormContext.Provider, {
471
- value: form
472
- }, children);
473
- };
474
- var InputHeader = ({ children, error }) => {
475
- return /* @__PURE__ */ import_react6.default.createElement("div", {
476
- role: "none",
477
- className: "flex justify-between items-center mb-1"
478
- }, children, error && /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Root, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Trigger, {
479
- asChild: true
480
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Icon, {
481
- icon: "ph--warning--regular",
482
- size: 4,
483
- classNames: import_react_ui_theme2.errorText
484
- })), /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Content, {
485
- side: "bottom"
486
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Arrow, null), error)));
487
- };
488
- var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
489
- const { t } = (0, import_react_ui3.useTranslation)(translationKey);
490
- const { status, error } = getStatus();
491
- const geoPoint = (0, import_react5.useMemo)(() => getValue3() ?? [
492
- 0,
493
- 0
494
- ], [
495
- getValue3
640
+ schema,
641
+ onValidate
496
642
  ]);
497
- const geoLocation = (0, import_react5.useMemo)(() => import_echo_schema4.GeoLocation.fromGeoPoint(geoPoint), [
498
- geoPoint
643
+ const [schemaDirty, setSchemaDirty] = (0, import_react11.useState)(false);
644
+ (0, import_react11.useEffect)(() => setSchemaDirty(true), [
645
+ schema
499
646
  ]);
500
- const [longitudeText, setLongitudeText] = (0, import_react5.useState)(geoLocation.longitude?.toString());
501
- const [latitudeText, setLatitudeText] = (0, import_react5.useState)(geoLocation.latitude?.toString());
502
- (0, import_react5.useEffect)(() => {
503
- const location = import_echo_schema4.GeoLocation.fromGeoPoint(geoPoint);
504
- setLongitudeText(location.longitude.toString());
505
- setLatitudeText(location.latitude.toString());
647
+ (0, import_react11.useEffect)(() => {
648
+ if (schemaDirty) {
649
+ validate(values);
650
+ setSchemaDirty(false);
651
+ }
506
652
  }, [
507
- geoPoint
653
+ values,
654
+ schemaDirty
508
655
  ]);
509
- const handleCoordinateChange = (0, import_react5.useCallback)((coordinateType, setText) => (event) => {
510
- const inputText = event.target.value;
511
- setText(inputText);
512
- if (inputText !== "" && inputText !== "-") {
513
- const coord = (0, import_util.safeParseFloat)(inputText);
514
- if (coord !== void 0 && !isNaN(coord)) {
515
- const currentLocation = import_echo_schema4.GeoLocation.fromGeoPoint(getValue3() ?? [
516
- 0,
517
- 0
518
- ]);
519
- const newLocation = {
520
- ...currentLocation,
521
- [coordinateType]: coord
522
- };
523
- const newValue = import_echo_schema4.GeoLocation.toGeoPoint(newLocation);
524
- onValueChange(type, newValue);
525
- }
526
- }
656
+ const formIsValid = (0, import_react11.useMemo)(() => {
657
+ return Object.keys(errors).length === 0;
527
658
  }, [
528
- getValue3,
529
- onValueChange,
530
- type
659
+ errors
531
660
  ]);
532
- return /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.Root, {
533
- validationValence: status
534
- }, /* @__PURE__ */ import_react5.default.createElement(InputHeader, {
535
- error
536
- }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.Label, null, label)), /* @__PURE__ */ import_react5.default.createElement("div", {
537
- role: "none",
538
- className: "grid grid-cols-2 gap-2"
539
- }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.TextInput, {
540
- type: "text",
541
- pattern: "^-?[0-9]*\\.?[0-9]*$",
542
- disabled,
543
- placeholder: t("placeholder latitude"),
544
- value: latitudeText,
545
- onChange: handleCoordinateChange("latitude", setLatitudeText),
546
- onBlur
547
- }), /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.TextInput, {
548
- type: "text",
549
- pattern: "^-?[0-9]*\\.?[0-9]*$",
550
- disabled,
551
- placeholder: t("placeholder longitude"),
552
- value: longitudeText,
553
- onChange: handleCoordinateChange("longitude", setLongitudeText),
554
- onBlur
555
- })));
556
- };
557
- var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
558
- const [selected, setSelectedId] = (0, import_react7.useState)(null);
559
- const [isNewOption, setIsNewOption] = (0, import_react7.useState)(false);
560
- const inputRef = (0, import_react7.useRef)(null);
561
- const { t } = (0, import_react_ui5.useTranslation)(translationKey);
562
- const { status, error } = getStatus();
563
- const options = getValue3();
564
- (0, import_react7.useEffect)(() => {
565
- if (options === void 0) {
566
- onValueChange(type, []);
661
+ const canSave = (0, import_react11.useMemo)(() => !saving && // Check if any error paths that are touched have errors.
662
+ !Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
663
+ touched,
664
+ errors,
665
+ saving
666
+ ]);
667
+ const handleSave = (0, import_react11.useCallback)(async () => {
668
+ if (validate(values)) {
669
+ setSaving(true);
670
+ try {
671
+ await onSave?.(values, {
672
+ changed
673
+ });
674
+ } finally {
675
+ setSaving(false);
676
+ }
567
677
  }
568
678
  }, [
569
- options,
570
- onValueChange,
571
- type
679
+ values,
680
+ validate,
681
+ onSave,
682
+ changed
572
683
  ]);
573
- const randomHue = () => {
574
- const usedHues = new Set(options?.map((option) => option.color) ?? []);
575
- const unusedHues = import_react_ui_theme3.hues.filter((hue) => !usedHues.has(hue));
576
- if (unusedHues.length > 0) {
577
- return unusedHues[Math.floor(Math.random() * unusedHues.length)];
684
+ const getStatus = (0, import_react11.useCallback)((path) => {
685
+ const jsonPath = Array.isArray(path) ? (0, import_effect3.createJsonPath)(path) : path;
686
+ const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
687
+ const isTouched = touched[jsonPath];
688
+ if (!isTouched) {
689
+ return {
690
+ status: void 0,
691
+ error: void 0
692
+ };
578
693
  }
579
- const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
580
- const availableHues = import_react_ui_theme3.hues.filter((hue) => !lastThree.has(hue));
581
- return availableHues[Math.floor(Math.random() * availableHues.length)] ?? import_react_ui_theme3.hues[Math.floor(Math.random() * import_react_ui_theme3.hues.length)];
582
- };
583
- const handleAdd = (0, import_react7.useCallback)(() => {
584
- const newId = import_keys.PublicKey.random().truncate();
585
- const newOption = {
586
- id: newId,
587
- title: "",
588
- color: randomHue()
694
+ return {
695
+ status: matchingError ? "error" : void 0,
696
+ error: matchingError ? matchingError[1] : void 0
589
697
  };
590
- onValueChange(type, [
591
- ...options ?? [],
592
- newOption
593
- ]);
594
- setSelectedId(newId);
595
- setIsNewOption(true);
596
698
  }, [
597
- options,
598
- type,
599
- onValueChange
699
+ errors,
700
+ touched
600
701
  ]);
601
- const handleDelete = (0, import_react7.useCallback)((id) => {
602
- const newOptions = options?.filter((option) => option.id !== id) ?? [];
603
- onValueChange(type, newOptions);
604
- setSelectedId(null);
702
+ const getFormValue = (0, import_react11.useCallback)((path) => {
703
+ return (0, import_echo_schema4.getValue)(values, (0, import_effect3.createJsonPath)(path));
605
704
  }, [
606
- options,
607
- type,
608
- onValueChange
705
+ values
609
706
  ]);
610
- const handleMove = (0, import_react7.useCallback)((from, to) => {
611
- if (!options) {
612
- return;
707
+ const onValueChange = (0, import_react11.useCallback)((path, type, value) => {
708
+ const jsonPath = (0, import_effect3.createJsonPath)(path);
709
+ let parsedValue = value;
710
+ try {
711
+ if (type === "number") {
712
+ parsedValue = parseFloat(value) || 0;
713
+ }
714
+ } catch (err) {
715
+ import_log2.log.catch(err, void 0, {
716
+ F: __dxlog_file,
717
+ L: 212,
718
+ S: void 0,
719
+ C: (f, a) => f(...a)
720
+ });
721
+ parsedValue = void 0;
613
722
  }
614
- const newOptions = [
615
- ...options
616
- ];
617
- const [removed] = newOptions.splice(from, 1);
618
- newOptions.splice(to, 0, removed);
619
- onValueChange(type, newOptions);
620
- }, [
621
- options,
622
- type,
623
- onValueChange
624
- ]);
625
- const handleClick = (0, import_react7.useCallback)((id) => {
626
- setSelectedId((current) => current === id ? null : id);
627
- }, []);
628
- const handleTitleChange = (0, import_react7.useCallback)((id) => (e) => {
629
- const newOptions = options?.map((o) => o.id === id ? {
630
- ...o,
631
- title: e.target.value
632
- } : o);
633
- onValueChange(type, newOptions ?? []);
634
- }, [
635
- options,
636
- type,
637
- onValueChange
638
- ]);
639
- const handleKeyDown = (0, import_react7.useCallback)((e) => {
640
- if (e.key === "Enter") {
641
- setSelectedId(null);
723
+ const newValues = {
724
+ ...(0, import_echo_schema4.setValue)(values, jsonPath, parsedValue)
725
+ };
726
+ setValues(newValues);
727
+ setChanged((prev) => ({
728
+ ...prev,
729
+ [jsonPath]: true
730
+ }));
731
+ onValuesChanged?.(newValues);
732
+ const isValid = validate(newValues);
733
+ if (isValid && onValid) {
734
+ onValid(newValues, {
735
+ changed
736
+ });
642
737
  }
643
- }, []);
644
- const handleColorChange = (0, import_react7.useCallback)((id) => (hue) => {
645
- const newOptions = options?.map((o) => o.id === id ? {
646
- ...o,
647
- color: hue
648
- } : o);
649
- onValueChange(type, newOptions ?? []);
650
738
  }, [
651
- options,
652
- type,
653
- onValueChange
739
+ values,
740
+ onValuesChanged,
741
+ validate,
742
+ onValid,
743
+ changed
654
744
  ]);
655
- (0, import_react7.useEffect)(() => {
656
- if (selected && isNewOption && inputRef.current) {
657
- inputRef.current.focus();
658
- setIsNewOption(false);
659
- }
745
+ const onTouched = (0, import_react11.useCallback)((path) => {
746
+ const jsonPath = (0, import_effect3.createJsonPath)(path);
747
+ setTouched((touched2) => ({
748
+ ...touched2,
749
+ [jsonPath]: true
750
+ }));
751
+ validate(values);
660
752
  }, [
661
- selected,
662
- isNewOption
753
+ validate,
754
+ values
755
+ ]);
756
+ return (0, import_react11.useMemo)(() => ({
757
+ // State.
758
+ values,
759
+ errors,
760
+ touched,
761
+ changed,
762
+ canSave,
763
+ formIsValid,
764
+ // Actions.
765
+ handleSave,
766
+ // Field utils.
767
+ getStatus,
768
+ getValue: getFormValue,
769
+ onValueChange,
770
+ onTouched
771
+ }), [
772
+ values,
773
+ errors,
774
+ touched,
775
+ changed,
776
+ canSave,
777
+ formIsValid,
778
+ handleSave,
779
+ getStatus,
780
+ getFormValue,
781
+ onValueChange,
782
+ onTouched
663
783
  ]);
664
- return /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Root, {
665
- validationValence: status
666
- }, /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
667
- error
668
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement("div", {
669
- role: "none"
670
- }, options && /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.Root, {
671
- items: options,
672
- isItem: (item) => true,
673
- onMove: handleMove
674
- }, ({ items }) => /* @__PURE__ */ import_react7.default.createElement("div", {
675
- role: "list",
676
- className: "w-full overflow-auto"
677
- }, items?.map((item) => /* @__PURE__ */ import_react7.default.createElement("div", {
678
- key: item.id
679
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.Item, {
680
- role: "button",
681
- item,
682
- classNames: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
683
- "aria-expanded": selected === item.id
684
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
685
- className: "flex items-center"
686
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.ItemDragHandle, null), /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.ItemTitle, {
687
- onClick: () => handleClick(item.id),
688
- classNames: "flex-1"
689
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Tag, {
690
- palette: item.color
691
- }, item.title || "\u200B")), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Icon, {
692
- icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
693
- onClick: () => handleClick(item.id)
694
- })), selected === item.id && /* @__PURE__ */ import_react7.default.createElement("div", {
695
- className: "mis-4 mbs-2 flex flex-col gap-1"
696
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Label, {
697
- classNames: "text-xs"
698
- }, t("select option label")), /* @__PURE__ */ import_react7.default.createElement("div", {
699
- className: "flex flex-row items-center gap-1"
700
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.TextInput, {
701
- placeholder: t("select option label placeholder"),
702
- ref: selected === item.id ? inputRef : void 0,
703
- value: item.title,
704
- onChange: handleTitleChange(item.id),
705
- onKeyDown: handleKeyDown,
706
- classNames: "flex-1",
707
- "data-no-submit": true
708
- }), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Toolbar.Root, {
709
- classNames: "p-0 m-0 !is-auto"
710
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_pickers.HuePicker, {
711
- value: item.color,
712
- onChange: handleColorChange(item.id)
713
- })), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.IconButton, {
714
- icon: "ph--trash--fill",
715
- iconOnly: true,
716
- label: t("select option delete"),
717
- onClick: () => handleDelete(item.id)
718
- })))))), /* @__PURE__ */ import_react7.default.createElement("div", {
719
- role: "listitem"
720
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
721
- role: "button",
722
- className: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
723
- onClick: handleAdd
724
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
725
- className: "flex items-center gap-1"
726
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Icon, {
727
- icon: "ph--plus--regular"
728
- }), /* @__PURE__ */ import_react7.default.createElement("span", {
729
- className: "text-sm"
730
- }, t("select option add")))))))));
731
784
  };
732
- var gridCols = [
733
- "grid-cols-1",
734
- "grid-cols-2",
735
- "grid-cols-3",
736
- "grid-cols-4"
737
- ];
738
- var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
739
- const { status, error } = getStatus();
740
- const values = getValue3() ?? {};
741
- return /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.Root, {
742
- validationValence: status
743
- }, /* @__PURE__ */ import_react8.default.createElement(InputHeader, {
744
- error
745
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react8.default.createElement("div", {
746
- className: (0, import_react_ui_theme4.mx)("grid gap-2", gridCols[binding.length - 1])
747
- }, binding.map((prop) => /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.TextInput, {
748
- key: prop,
749
- type: "number",
750
- disabled,
751
- value: values[prop],
752
- onChange: (event) => onValueChange(type, {
753
- ...values,
754
- [prop]: (0, import_util2.safeParseFloat)(event.target.value, 0)
755
- }),
756
- onBlur
757
- }))));
785
+ var createKeySet = (obj, value) => {
786
+ (0, import_invariant.invariant)(obj, void 0, {
787
+ F: __dxlog_file,
788
+ L: 274,
789
+ S: void 0,
790
+ A: [
791
+ "obj",
792
+ ""
793
+ ]
794
+ });
795
+ return Object.keys(obj).reduce((acc, key) => ({
796
+ ...acc,
797
+ [key]: value
798
+ }), {});
758
799
  };
759
- var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
760
- const { status, error } = getStatus();
761
- return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
762
- validationValence: status
763
- }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
764
- error
765
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.TextInput, {
766
- disabled,
767
- placeholder,
768
- value: getValue3() ?? "",
769
- onChange: (event) => onValueChange(type, event.target.value),
770
- onBlur
771
- }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Validation, null, error));
800
+ var flatMap = (errors) => {
801
+ return errors.reduce((result, { path, message }) => {
802
+ const jsonPath = (0, import_effect3.fromEffectValidationPath)(path);
803
+ if (!(jsonPath in result)) {
804
+ result[jsonPath] = message;
805
+ }
806
+ return result;
807
+ }, {});
772
808
  };
773
- var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
774
- const { status, error } = getStatus();
775
- return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
776
- validationValence: status
777
- }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
778
- error
779
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.TextInput, {
780
- type: "number",
781
- disabled,
782
- placeholder,
783
- value: getValue3() ?? 0,
784
- onChange: (event) => onValueChange(type, event.target.value),
785
- onBlur
786
- }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
809
+ var FormContext = /* @__PURE__ */ (0, import_react10.createContext)(void 0);
810
+ var useFormContext = () => {
811
+ return (0, import_react10.useContext)(FormContext) ?? (0, import_debug.raise)(new Error("Missing FormContext"));
787
812
  };
788
- var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
789
- const { status, error } = getStatus();
790
- const checked = Boolean(getValue3());
791
- return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
792
- validationValence: status
793
- }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
794
- error
795
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Switch, {
796
- checked,
797
- onCheckedChange: (value) => onValueChange(type, value)
798
- }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
813
+ var useFormValues = (path = []) => {
814
+ const { values: formValues } = useFormContext();
815
+ const jsonPath = (0, import_effect.createJsonPath)(path);
816
+ return (0, import_echo_schema3.getValue)(formValues, jsonPath);
799
817
  };
800
- var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
801
- const { status, error } = getStatus();
802
- return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
803
- validationValence: status
804
- }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
805
- error
806
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Root, {
807
- value: getValue3(),
808
- onValueChange: (value) => onValueChange(type, value)
809
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.TriggerButton, {
810
- classNames: "is-full",
811
- disabled,
812
- placeholder
813
- }), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Portal, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Content, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Viewport, null, options?.map(({ value, label: label2 }) => (
814
- // NOTE: Numeric values are converted to and from strings.
815
- /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Option, {
816
- key: String(value),
817
- value: String(value)
818
- }, label2 ?? String(value))
819
- )))))), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
818
+ var useInputProps = (path = []) => {
819
+ const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
820
+ const stablePath = (0, import_react10.useMemo)(() => path, [
821
+ Array.isArray(path) ? path.join(".") : path
822
+ ]);
823
+ return (0, import_react10.useMemo)(() => ({
824
+ getStatus: () => getStatus(stablePath),
825
+ getValue: () => getFormValue(stablePath),
826
+ onValueChange: (type, value) => onValueChange(stablePath, type, value),
827
+ onBlur: () => onTouched(stablePath)
828
+ }), [
829
+ getStatus,
830
+ getFormValue,
831
+ onValueChange,
832
+ onTouched,
833
+ stablePath
834
+ ]);
820
835
  };
821
- var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
822
- const { status, error } = getStatus();
823
- const textareaRef = (0, import_react9.useRef)(null);
824
- const adjustHeight = (0, import_react9.useCallback)(() => {
825
- const textarea = textareaRef.current;
826
- if (textarea) {
827
- textarea.style.blockSize = "auto";
828
- textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
836
+ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
837
+ const form = useForm(formOptions);
838
+ (0, import_react10.useEffect)(() => {
839
+ if (!formRef?.current) {
840
+ return;
829
841
  }
830
- }, []);
831
- (0, import_react9.useEffect)(() => {
832
- adjustHeight();
833
- }, [
834
- adjustHeight
835
- ]);
836
- (0, import_react9.useEffect)(() => {
837
- adjustHeight();
842
+ const handleKeyDown = (event) => {
843
+ const keyIsEnter = event.key === "Enter";
844
+ const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
845
+ const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
846
+ const inputOptOut = event.target.hasAttribute("data-no-submit");
847
+ const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
848
+ const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
849
+ if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
850
+ if (!autoSave && form.canSave) {
851
+ form.handleSave();
852
+ }
853
+ if (autoSave && form.formIsValid) {
854
+ event.target.blur();
855
+ }
856
+ }
857
+ };
858
+ const formElement = formRef.current;
859
+ formElement.addEventListener("keydown", handleKeyDown);
860
+ return () => formElement.removeEventListener("keydown", handleKeyDown);
838
861
  }, [
839
- getValue3(),
840
- adjustHeight
862
+ formRef,
863
+ form.canSave,
864
+ form.formIsValid,
865
+ form.handleSave,
866
+ autoSave
841
867
  ]);
842
- return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
843
- validationValence: status
844
- }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
845
- error
846
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.TextArea, {
847
- ref: textareaRef,
848
- disabled,
849
- placeholder,
850
- value: getValue3() ?? "",
851
- classNames: "min-bs-auto max-h-40 overflow-auto",
852
- onChange: (event) => onValueChange(type, event.target.value),
853
- onBlur,
854
- style: {
855
- resize: "none"
856
- },
857
- spellCheck: false
858
- }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Validation, null, error));
868
+ return /* @__PURE__ */ import_react10.default.createElement(FormContext.Provider, {
869
+ value: form
870
+ }, children);
859
871
  };
860
872
  var FormActions = ({ onCancel, readonly }) => {
861
873
  const { t } = (0, import_react_ui8.useTranslation)(translationKey);
862
874
  const { canSave, handleSave } = useFormContext();
863
- return /* @__PURE__ */ import_react11.default.createElement("div", {
875
+ return /* @__PURE__ */ import_react9.default.createElement("div", {
864
876
  role: "none",
865
877
  className: "mt-2 flex justify-center"
866
- }, /* @__PURE__ */ import_react11.default.createElement("div", {
878
+ }, /* @__PURE__ */ import_react9.default.createElement("div", {
867
879
  role: "none",
868
880
  className: (0, import_react_ui_theme6.mx)(onCancel && !readonly && "grid grid-cols-2 gap-2")
869
- }, onCancel && !readonly && /* @__PURE__ */ import_react11.default.createElement(import_react_ui8.IconButton, {
881
+ }, onCancel && !readonly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.IconButton, {
870
882
  "data-testid": "cancel-button",
871
883
  icon: "ph--x--regular",
872
884
  label: t("button cancel"),
873
885
  onClick: onCancel
874
- }), handleSave && /* @__PURE__ */ import_react11.default.createElement(import_react_ui8.IconButton, {
886
+ }), handleSave && /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.IconButton, {
875
887
  type: "submit",
876
888
  "data-testid": "save-button",
877
889
  disabled: !canSave,
@@ -1127,12 +1139,12 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
1127
1139
  }).filter(import_util3.isNotFalsy));
1128
1140
  };
1129
1141
  var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
1130
- const formRef = (0, import_react10.useRef)(null);
1131
- const onValid = (0, import_react10.useMemo)(() => autoSave ? onSave : void 0, [
1142
+ const formRef = (0, import_react8.useRef)(null);
1143
+ const onValid = (0, import_react8.useMemo)(() => autoSave ? onSave : void 0, [
1132
1144
  autoSave,
1133
1145
  onSave
1134
1146
  ]);
1135
- (0, import_react10.useEffect)(() => {
1147
+ (0, import_react8.useEffect)(() => {
1136
1148
  if (autoFocus && formRef.current) {
1137
1149
  const input = formRef.current.querySelector("input");
1138
1150
  if (input) {
@@ -1142,7 +1154,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
1142
1154
  }, [
1143
1155
  autoFocus
1144
1156
  ]);
1145
- return /* @__PURE__ */ import_react10.default.createElement(FormProvider, {
1157
+ return /* @__PURE__ */ import_react8.default.createElement(FormProvider, {
1146
1158
  formRef,
1147
1159
  schema,
1148
1160
  autoSave,
@@ -1151,12 +1163,12 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
1151
1163
  onValidate,
1152
1164
  onValid,
1153
1165
  onSave
1154
- }, /* @__PURE__ */ import_react10.default.createElement("div", {
1166
+ }, /* @__PURE__ */ import_react8.default.createElement("div", {
1155
1167
  ref: formRef,
1156
1168
  role: "none",
1157
1169
  className: (0, import_react_ui_theme5.mx)("p-2", classNames),
1158
1170
  "data-testid": testId
1159
- }, /* @__PURE__ */ import_react10.default.createElement(FormFields, {
1171
+ }, /* @__PURE__ */ import_react8.default.createElement(FormFields, {
1160
1172
  schema,
1161
1173
  path,
1162
1174
  readonly,
@@ -1164,7 +1176,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
1164
1176
  sort,
1165
1177
  lookupComponent,
1166
1178
  Custom
1167
- }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ import_react10.default.createElement(FormActions, {
1179
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ import_react8.default.createElement(FormActions, {
1168
1180
  onCancel,
1169
1181
  readonly
1170
1182
  })));
@@ -1326,6 +1338,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1326
1338
  Custom
1327
1339
  });
1328
1340
  };
1341
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
1329
1342
  var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
1330
1343
  var ViewMetaSchema = import_echo_schema8.S.Struct({
1331
1344
  name: import_echo_schema8.S.String.annotations({
@@ -1352,39 +1365,77 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1352
1365
  }, [
1353
1366
  view
1354
1367
  ]);
1355
- const handleViewUpdate = (0, import_react14.useCallback)(({ name, typename }) => {
1368
+ const handleSelect = (0, import_react14.useCallback)((field2) => {
1369
+ setField((f) => f === field2 ? void 0 : field2);
1370
+ }, []);
1371
+ const handleAdd = (0, import_react14.useCallback)(() => {
1372
+ (0, import_invariant3.invariant)(!schema.readonly, void 0, {
1373
+ F: __dxlog_file4,
1374
+ L: 76,
1375
+ S: void 0,
1376
+ A: [
1377
+ "!schema.readonly",
1378
+ ""
1379
+ ]
1380
+ });
1381
+ const field2 = projection.createFieldProjection();
1382
+ setField(field2);
1383
+ }, [
1384
+ schema,
1385
+ view
1386
+ ]);
1387
+ const handleUpdate = (0, import_react14.useCallback)(({ name, typename }) => {
1388
+ (0, import_invariant3.invariant)(!schema.readonly, void 0, {
1389
+ F: __dxlog_file4,
1390
+ L: 83,
1391
+ S: void 0,
1392
+ A: [
1393
+ "!schema.readonly",
1394
+ ""
1395
+ ]
1396
+ });
1356
1397
  requestAnimationFrame(() => {
1357
1398
  if (view.name !== name) {
1358
1399
  view.name = name;
1359
1400
  }
1360
1401
  if (view.query.typename !== typename) {
1361
- onTypenameChanged(typename);
1402
+ onTypenameChanged?.(typename);
1362
1403
  }
1363
1404
  });
1364
1405
  }, [
1365
- view,
1366
1406
  schema,
1407
+ view,
1367
1408
  onTypenameChanged
1368
1409
  ]);
1369
- const handleSelect = (0, import_react14.useCallback)((field2) => {
1370
- setField((f) => f === field2 ? void 0 : field2);
1371
- }, []);
1372
- const handleAdd = (0, import_react14.useCallback)(() => {
1373
- const field2 = projection.createFieldProjection();
1374
- setField(field2);
1375
- }, [
1376
- view
1377
- ]);
1378
1410
  const handleDelete = (0, import_react14.useCallback)((fieldId) => {
1411
+ (0, import_invariant3.invariant)(!schema.readonly, void 0, {
1412
+ F: __dxlog_file4,
1413
+ L: 99,
1414
+ S: void 0,
1415
+ A: [
1416
+ "!schema.readonly",
1417
+ ""
1418
+ ]
1419
+ });
1379
1420
  if (fieldId === field?.id) {
1380
1421
  setField(void 0);
1381
1422
  }
1382
- onDelete(fieldId);
1423
+ onDelete?.(fieldId);
1383
1424
  }, [
1384
- onDelete,
1385
- field
1425
+ schema,
1426
+ field,
1427
+ onDelete
1386
1428
  ]);
1387
1429
  const handleMove = (0, import_react14.useCallback)((fromIndex, toIndex) => {
1430
+ (0, import_invariant3.invariant)(!schema.readonly, void 0, {
1431
+ F: __dxlog_file4,
1432
+ L: 111,
1433
+ S: void 0,
1434
+ A: [
1435
+ "!schema.readonly",
1436
+ ""
1437
+ ]
1438
+ });
1388
1439
  const fields = [
1389
1440
  ...view.fields
1390
1441
  ];
@@ -1392,6 +1443,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1392
1443
  fields.splice(toIndex, 0, moved);
1393
1444
  view.fields = fields;
1394
1445
  }, [
1446
+ schema,
1395
1447
  view.fields
1396
1448
  ]);
1397
1449
  const handleClose = (0, import_react14.useCallback)(() => setField(void 0), []);
@@ -1415,7 +1467,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1415
1467
  autoSave: true,
1416
1468
  schema: ViewMetaSchema,
1417
1469
  values: viewValues,
1418
- onSave: handleViewUpdate
1470
+ onSave: schema.readonly ? void 0 : handleUpdate
1419
1471
  }), /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("div", {
1420
1472
  role: "none",
1421
1473
  className: "p-2"
@@ -1425,7 +1477,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1425
1477
  items: view.fields,
1426
1478
  isItem: import_echo_schema8.S.is(import_schema5.FieldSchema),
1427
1479
  getId: (field2) => field2.id,
1428
- onMove: handleMove
1480
+ onMove: schema.readonly ? void 0 : handleMove
1429
1481
  }, ({ items: fields }) => /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, showHeading && /* @__PURE__ */ import_react14.default.createElement("div", {
1430
1482
  role: "heading",
1431
1483
  className: grid
@@ -1446,7 +1498,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1446
1498
  icon: "ph--eye-slash--regular",
1447
1499
  disabled: view.fields.length <= 1,
1448
1500
  onClick: () => handleHide(field2.id)
1449
- }), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemDeleteButton, {
1501
+ }), !schema.readonly && /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemDeleteButton, {
1450
1502
  icon: "ph--trash--regular",
1451
1503
  disabled: view.fields.length <= 1,
1452
1504
  onClick: () => handleDelete(field2.id)
@@ -1481,7 +1533,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1481
1533
  }, /* @__PURE__ */ import_react14.default.createElement(import_react_ui10.IconButton, {
1482
1534
  icon: "ph--plus--regular",
1483
1535
  label: t("button add property"),
1484
- onClick: handleAdd,
1536
+ onClick: schema.readonly ? void 0 : handleAdd,
1485
1537
  // TODO(burdon): Show field limit in ux (not tooltip).
1486
1538
  disabled: view.fields.length >= import_schema5.VIEW_FIELD_LIMIT
1487
1539
  })));
@@ -1601,6 +1653,7 @@ var cellClassesForFieldType = ({ type, format }) => {
1601
1653
  "text-right"
1602
1654
  ];
1603
1655
  case import_echo_schema9.FormatEnum.JSON:
1656
+ case import_echo_schema9.FormatEnum.DID:
1604
1657
  return [
1605
1658
  "font-mono"
1606
1659
  ];
@@ -1747,6 +1800,7 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1747
1800
  DeprecatedFormInput,
1748
1801
  FieldEditor,
1749
1802
  Form,
1803
+ FormProvider,
1750
1804
  GeoPointInput,
1751
1805
  InputHeader,
1752
1806
  MarkdownInput,
@@ -1764,6 +1818,8 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1764
1818
  pathNotUniqueError,
1765
1819
  translations,
1766
1820
  useForm,
1767
- useFormValues
1821
+ useFormContext,
1822
+ useFormValues,
1823
+ useInputProps
1768
1824
  });
1769
1825
  //# sourceMappingURL=index.cjs.map