@dxos/react-ui-form 0.7.2 → 0.7.3-staging.0905f03
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 +228 -58
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +228 -57
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +228 -58
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +2 -2
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/Form/Defaults.d.ts +4 -4
- package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +11 -2
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +20 -5
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Input.d.ts +5 -4
- package/dist/types/src/components/Form/Input.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +19 -11
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/package.json +23 -22
- package/src/components/FieldEditor/FieldEditor.stories.tsx +3 -3
- package/src/components/FieldEditor/FieldEditor.tsx +8 -8
- package/src/components/Form/Defaults.tsx +28 -13
- package/src/components/Form/Form.stories.tsx +81 -19
- package/src/components/Form/Form.tsx +216 -29
- package/src/components/Form/Input.tsx +5 -4
- package/src/components/ViewEditor/ViewEditor.tsx +8 -7
- package/src/components/deprecated/Form.stories.tsx +4 -4
- package/src/hooks/useForm.ts +65 -32
|
@@ -93,7 +93,7 @@ import { pipe } from "effect";
|
|
|
93
93
|
import { capitalize } from "effect/String";
|
|
94
94
|
import React5, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
95
95
|
import { AST, S } from "@dxos/echo-schema";
|
|
96
|
-
import { findNode, getDiscriminatedType, isDiscriminatedUnion } from "@dxos/effect";
|
|
96
|
+
import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
|
|
97
97
|
import { log as log2 } from "@dxos/log";
|
|
98
98
|
import { IconButton, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
99
99
|
import { mx } from "@dxos/react-ui-theme";
|
|
@@ -124,11 +124,11 @@ var InputHeader = ({ children, error }) => {
|
|
|
124
124
|
};
|
|
125
125
|
|
|
126
126
|
// packages/ui/react-ui-form/src/components/Form/Defaults.tsx
|
|
127
|
-
var TextInput = ({ property, type, label, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
|
|
127
|
+
var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
|
|
128
128
|
const { status, error } = getStatus?.(property);
|
|
129
129
|
return /* @__PURE__ */ React3.createElement(Input2.Root, {
|
|
130
130
|
validationValence: status
|
|
131
|
-
}, /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
131
|
+
}, !inputOnly && /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
132
132
|
error
|
|
133
133
|
}, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
|
|
134
134
|
disabled,
|
|
@@ -136,13 +136,13 @@ var TextInput = ({ property, type, label, disabled, placeholder, getStatus, getV
|
|
|
136
136
|
value: getValue(property) ?? "",
|
|
137
137
|
onChange: (event) => onValueChange(property, type, event.target.value),
|
|
138
138
|
onBlur
|
|
139
|
-
}));
|
|
139
|
+
}), inputOnly && /* @__PURE__ */ React3.createElement(Input2.Validation, null, error));
|
|
140
140
|
};
|
|
141
|
-
var NumberInput = ({ property, type, label, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
|
|
141
|
+
var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
|
|
142
142
|
const { status, error } = getStatus?.(property);
|
|
143
143
|
return /* @__PURE__ */ React3.createElement(Input2.Root, {
|
|
144
144
|
validationValence: status
|
|
145
|
-
}, /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
145
|
+
}, !inputOnly && /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
146
146
|
error
|
|
147
147
|
}, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
|
|
148
148
|
type: "number",
|
|
@@ -151,24 +151,24 @@ var NumberInput = ({ property, type, label, disabled, placeholder, getStatus, ge
|
|
|
151
151
|
value: getValue(property) ?? 0,
|
|
152
152
|
onChange: (event) => onValueChange(property, type, event.target.value),
|
|
153
153
|
onBlur
|
|
154
|
-
}));
|
|
154
|
+
}), inputOnly && /* @__PURE__ */ React3.createElement(Input2.DescriptionAndValidation, null, error));
|
|
155
155
|
};
|
|
156
|
-
var BooleanInput = ({ property, type, label, getStatus, getValue, onValueChange }) => {
|
|
156
|
+
var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue, onValueChange }) => {
|
|
157
157
|
const { status, error } = getStatus?.(property);
|
|
158
158
|
return /* @__PURE__ */ React3.createElement(Input2.Root, {
|
|
159
159
|
validationValence: status
|
|
160
|
-
}, /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
160
|
+
}, !inputOnly && /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
161
161
|
error
|
|
162
162
|
}, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.Switch, {
|
|
163
163
|
checked: getValue(property),
|
|
164
164
|
onCheckedChange: (value) => onValueChange(property, type, value)
|
|
165
|
-
}));
|
|
165
|
+
}), inputOnly && /* @__PURE__ */ React3.createElement(Input2.DescriptionAndValidation, null, error));
|
|
166
166
|
};
|
|
167
|
-
var SelectInput = ({ property, type, label, disabled, placeholder, options, getStatus, getValue, onValueChange }) => {
|
|
167
|
+
var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue, onValueChange }) => {
|
|
168
168
|
const { status, error } = getStatus?.(property);
|
|
169
169
|
return /* @__PURE__ */ React3.createElement(Input2.Root, {
|
|
170
170
|
validationValence: status
|
|
171
|
-
}, /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
171
|
+
}, !inputOnly && /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
172
172
|
error
|
|
173
173
|
}, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Select.Root, {
|
|
174
174
|
value: getValue(property),
|
|
@@ -183,7 +183,7 @@ var SelectInput = ({ property, type, label, disabled, placeholder, options, getS
|
|
|
183
183
|
key: String(value),
|
|
184
184
|
value: String(value)
|
|
185
185
|
}, label2 ?? String(value))
|
|
186
|
-
)))))));
|
|
186
|
+
)))))), inputOnly && /* @__PURE__ */ React3.createElement(Input2.DescriptionAndValidation, null, error));
|
|
187
187
|
};
|
|
188
188
|
|
|
189
189
|
// packages/ui/react-ui-form/src/components/Form/factory.tsx
|
|
@@ -254,7 +254,7 @@ import { invariant } from "@dxos/invariant";
|
|
|
254
254
|
import { log } from "@dxos/log";
|
|
255
255
|
import { validateSchema } from "@dxos/schema";
|
|
256
256
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
257
|
-
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid,
|
|
257
|
+
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
258
258
|
const [values, setValues] = useState(initialValues);
|
|
259
259
|
useEffect(() => {
|
|
260
260
|
setValues(initialValues);
|
|
@@ -264,6 +264,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
264
264
|
const [touched, setTouched] = useState(createKeySet(initialValues, false));
|
|
265
265
|
const [changed, setChanged] = useState(createKeySet(initialValues, false));
|
|
266
266
|
const [errors, setErrors] = useState({});
|
|
267
|
+
const [saving, setSaving] = useState(false);
|
|
267
268
|
const validate = useCallback((values2) => {
|
|
268
269
|
let errors2 = validateSchema(schema, values2) ?? [];
|
|
269
270
|
if (errors2.length === 0 && onValidate) {
|
|
@@ -288,21 +289,27 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
288
289
|
values,
|
|
289
290
|
schemaDirty
|
|
290
291
|
]);
|
|
291
|
-
const
|
|
292
|
+
const canSave = useMemo(() => !saving && Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
|
|
292
293
|
values,
|
|
293
294
|
touched,
|
|
294
|
-
errors
|
|
295
|
+
errors,
|
|
296
|
+
saving
|
|
295
297
|
]);
|
|
296
|
-
const
|
|
298
|
+
const handleSave = useCallback(async () => {
|
|
297
299
|
if (validate(values)) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
300
|
+
setSaving(true);
|
|
301
|
+
try {
|
|
302
|
+
await onSave?.(values, {
|
|
303
|
+
changed
|
|
304
|
+
});
|
|
305
|
+
} finally {
|
|
306
|
+
setSaving(false);
|
|
307
|
+
}
|
|
301
308
|
}
|
|
302
309
|
}, [
|
|
303
310
|
values,
|
|
304
311
|
validate,
|
|
305
|
-
|
|
312
|
+
onSave
|
|
306
313
|
]);
|
|
307
314
|
const getStatus = useCallback((property) => ({
|
|
308
315
|
status: errors[property] ? "error" : void 0,
|
|
@@ -312,7 +319,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
312
319
|
errors
|
|
313
320
|
]);
|
|
314
321
|
const getValue = (property) => {
|
|
315
|
-
return values
|
|
322
|
+
return getByPath(values, property);
|
|
316
323
|
};
|
|
317
324
|
const onValueChange = (property, type, value) => {
|
|
318
325
|
let parsedValue = value;
|
|
@@ -323,16 +330,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
323
330
|
} catch (err) {
|
|
324
331
|
log.catch(err, void 0, {
|
|
325
332
|
F: __dxlog_file,
|
|
326
|
-
L:
|
|
333
|
+
L: 183,
|
|
327
334
|
S: void 0,
|
|
328
335
|
C: (f, a) => f(...a)
|
|
329
336
|
});
|
|
330
337
|
parsedValue = void 0;
|
|
331
338
|
}
|
|
332
|
-
const newValues =
|
|
333
|
-
...values,
|
|
334
|
-
[property]: parsedValue
|
|
335
|
-
};
|
|
339
|
+
const newValues = setByPath(values, property, parsedValue);
|
|
336
340
|
setValues(newValues);
|
|
337
341
|
setChanged((prev) => ({
|
|
338
342
|
...prev,
|
|
@@ -366,8 +370,8 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
366
370
|
errors,
|
|
367
371
|
touched,
|
|
368
372
|
changed,
|
|
369
|
-
|
|
370
|
-
|
|
373
|
+
canSave,
|
|
374
|
+
handleSave,
|
|
371
375
|
// Field utils.
|
|
372
376
|
getStatus,
|
|
373
377
|
getValue,
|
|
@@ -378,7 +382,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
378
382
|
var createKeySet = (obj, value) => {
|
|
379
383
|
invariant(obj, void 0, {
|
|
380
384
|
F: __dxlog_file,
|
|
381
|
-
L:
|
|
385
|
+
L: 234,
|
|
382
386
|
S: void 0,
|
|
383
387
|
A: [
|
|
384
388
|
"obj",
|
|
@@ -398,23 +402,36 @@ var flatMap = (errors) => {
|
|
|
398
402
|
return result;
|
|
399
403
|
}, {});
|
|
400
404
|
};
|
|
405
|
+
var getByPath = (obj, path) => {
|
|
406
|
+
const [key, index] = path.split(".");
|
|
407
|
+
return index === void 0 ? obj[key] : obj[key][parseInt(index)];
|
|
408
|
+
};
|
|
409
|
+
var setByPath = (obj, path, value) => {
|
|
410
|
+
const [key, index] = path.split(".");
|
|
411
|
+
const newValue = index === void 0 ? value : [
|
|
412
|
+
...obj[key]
|
|
413
|
+
].map((v, i) => i === parseInt(index) ? value : v);
|
|
414
|
+
return {
|
|
415
|
+
...obj,
|
|
416
|
+
[key]: newValue
|
|
417
|
+
};
|
|
418
|
+
};
|
|
401
419
|
|
|
402
420
|
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
403
421
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
|
|
404
422
|
var padding = "px-2";
|
|
405
|
-
var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, onValuesChanged, onValidate,
|
|
406
|
-
const
|
|
407
|
-
const onValid = useMemo2(() => autoSave ? onSubmit : void 0, [
|
|
423
|
+
var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, Custom }) => {
|
|
424
|
+
const onValid = useMemo2(() => autoSave ? onSave : void 0, [
|
|
408
425
|
autoSave,
|
|
409
|
-
|
|
426
|
+
onSave
|
|
410
427
|
]);
|
|
411
|
-
const {
|
|
428
|
+
const { canSave, values, errors, handleSave, ...inputProps } = useForm({
|
|
412
429
|
schema,
|
|
413
430
|
initialValues,
|
|
414
431
|
onValuesChanged,
|
|
415
432
|
onValidate,
|
|
416
433
|
onValid,
|
|
417
|
-
|
|
434
|
+
onSave
|
|
418
435
|
});
|
|
419
436
|
const properties = useMemo2(() => {
|
|
420
437
|
const props = getSchemaProperties(schema.ast, values);
|
|
@@ -435,7 +452,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
435
452
|
errors
|
|
436
453
|
}, {
|
|
437
454
|
F: __dxlog_file2,
|
|
438
|
-
L:
|
|
455
|
+
L: 100,
|
|
439
456
|
S: void 0,
|
|
440
457
|
C: (f, a) => f(...a)
|
|
441
458
|
});
|
|
@@ -445,14 +462,15 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
445
462
|
]);
|
|
446
463
|
return /* @__PURE__ */ React5.createElement("div", {
|
|
447
464
|
role: "form",
|
|
448
|
-
className: mx("flex flex-col w-full gap-2 py-2", classNames)
|
|
465
|
+
className: mx("flex flex-col w-full gap-2 py-2", classNames),
|
|
466
|
+
"data-testid": testId
|
|
449
467
|
}, properties.map((property) => {
|
|
450
|
-
const { ast, name, type, format, title, description, examples, options } = property;
|
|
468
|
+
const { ast, name, type, format, title, description, examples, options, array } = property;
|
|
451
469
|
const key = [
|
|
452
470
|
...path,
|
|
453
471
|
name
|
|
454
472
|
];
|
|
455
|
-
const label =
|
|
473
|
+
const label = title ?? pipe(name, capitalize);
|
|
456
474
|
const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
|
|
457
475
|
let InputComponent = Custom?.[key.join(".")];
|
|
458
476
|
if (!InputComponent) {
|
|
@@ -476,6 +494,22 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
476
494
|
}));
|
|
477
495
|
}
|
|
478
496
|
InputComponent = getInputComponent(type, format);
|
|
497
|
+
if (array) {
|
|
498
|
+
return /* @__PURE__ */ React5.createElement(ArrayField, {
|
|
499
|
+
key: name,
|
|
500
|
+
name,
|
|
501
|
+
type,
|
|
502
|
+
array: true,
|
|
503
|
+
label,
|
|
504
|
+
ast,
|
|
505
|
+
values,
|
|
506
|
+
format,
|
|
507
|
+
readonly,
|
|
508
|
+
placeholder,
|
|
509
|
+
inputProps,
|
|
510
|
+
Custom
|
|
511
|
+
});
|
|
512
|
+
}
|
|
479
513
|
}
|
|
480
514
|
if (!InputComponent) {
|
|
481
515
|
if (type === "object") {
|
|
@@ -504,7 +538,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
504
538
|
type
|
|
505
539
|
}, {
|
|
506
540
|
F: __dxlog_file2,
|
|
507
|
-
L:
|
|
541
|
+
L: 185,
|
|
508
542
|
S: void 0,
|
|
509
543
|
C: (f, a) => f(...a)
|
|
510
544
|
});
|
|
@@ -523,28 +557,163 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
523
557
|
placeholder,
|
|
524
558
|
...inputProps
|
|
525
559
|
}));
|
|
526
|
-
}).filter(isNotFalsy), (onCancel ||
|
|
560
|
+
}).filter(isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React5.createElement(FormActions, {
|
|
561
|
+
onCancel,
|
|
562
|
+
onSubmit: handleSave,
|
|
563
|
+
canSubmit: canSave,
|
|
564
|
+
readonly
|
|
565
|
+
}));
|
|
566
|
+
};
|
|
567
|
+
var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholder, inputProps, Custom }) => {
|
|
568
|
+
const { t } = useTranslation2(translationKey);
|
|
569
|
+
const arrayValues = values[name] ?? [];
|
|
570
|
+
const key = [
|
|
571
|
+
name
|
|
572
|
+
];
|
|
573
|
+
const tupleType = findNode(ast, AST.isTupleType);
|
|
574
|
+
const elementType = tupleType?.rest[0]?.type;
|
|
575
|
+
if (type === "object" && elementType) {
|
|
576
|
+
const baseNode = findNode(elementType, isDiscriminatedUnion);
|
|
577
|
+
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(elementType, AST.isTypeLiteral);
|
|
578
|
+
if (typeLiteral) {
|
|
579
|
+
const schema = S.make(typeLiteral);
|
|
580
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
581
|
+
key: name,
|
|
582
|
+
role: "none",
|
|
583
|
+
className: mx(padding)
|
|
584
|
+
}, /* @__PURE__ */ React5.createElement(InputHeader, null, label), /* @__PURE__ */ React5.createElement("div", {
|
|
585
|
+
role: "none",
|
|
586
|
+
className: "flex flex-col gap-1"
|
|
587
|
+
}, arrayValues.map((value, index) => {
|
|
588
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
589
|
+
key: index,
|
|
590
|
+
role: "none",
|
|
591
|
+
className: "flex items-center gap-1"
|
|
592
|
+
}, /* @__PURE__ */ React5.createElement("div", {
|
|
593
|
+
role: "none",
|
|
594
|
+
className: "flex-1"
|
|
595
|
+
}, /* @__PURE__ */ React5.createElement(Form, {
|
|
596
|
+
schema,
|
|
597
|
+
path: [
|
|
598
|
+
...key,
|
|
599
|
+
index.toString()
|
|
600
|
+
],
|
|
601
|
+
values: value,
|
|
602
|
+
onValuesChanged: (childValues) => {
|
|
603
|
+
const newValues = [
|
|
604
|
+
...arrayValues
|
|
605
|
+
];
|
|
606
|
+
newValues[index] = childValues;
|
|
607
|
+
inputProps.onValueChange(name, "object", newValues);
|
|
608
|
+
},
|
|
609
|
+
Custom
|
|
610
|
+
})), /* @__PURE__ */ React5.createElement(IconButton, {
|
|
611
|
+
icon: "ph--trash--regular",
|
|
612
|
+
iconOnly: true,
|
|
613
|
+
label: t("button remove"),
|
|
614
|
+
onClick: () => {
|
|
615
|
+
const newValues = arrayValues.filter((_, i) => i !== index);
|
|
616
|
+
inputProps.onValueChange(name, type, newValues);
|
|
617
|
+
}
|
|
618
|
+
}));
|
|
619
|
+
})), /* @__PURE__ */ React5.createElement("div", {
|
|
620
|
+
role: "none",
|
|
621
|
+
className: "flex justify-between items-center plb-1"
|
|
622
|
+
}, /* @__PURE__ */ React5.createElement(IconButton, {
|
|
623
|
+
icon: "ph--plus--regular",
|
|
624
|
+
iconOnly: true,
|
|
625
|
+
label: t("button add"),
|
|
626
|
+
onClick: () => {
|
|
627
|
+
const newValues = [
|
|
628
|
+
...arrayValues,
|
|
629
|
+
{}
|
|
630
|
+
];
|
|
631
|
+
inputProps.onValueChange(name, type, newValues);
|
|
632
|
+
}
|
|
633
|
+
})));
|
|
634
|
+
}
|
|
635
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
636
|
+
key: name,
|
|
637
|
+
role: "none"
|
|
638
|
+
}, "Nested form not supported in arrays, yet.");
|
|
639
|
+
}
|
|
640
|
+
const InputComponent = getInputComponent(type, format);
|
|
641
|
+
if (!InputComponent) {
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
645
|
+
role: "none",
|
|
646
|
+
key: "meta-input",
|
|
647
|
+
className: mx(padding)
|
|
648
|
+
}, /* @__PURE__ */ React5.createElement(InputHeader, null, label), /* @__PURE__ */ React5.createElement("div", {
|
|
649
|
+
role: "none",
|
|
650
|
+
className: "flex flex-col gap-1"
|
|
651
|
+
}, arrayValues.map((_, index) => /* @__PURE__ */ React5.createElement("div", {
|
|
652
|
+
key: index,
|
|
653
|
+
role: "none",
|
|
654
|
+
className: "flex items-start gap-1"
|
|
655
|
+
}, /* @__PURE__ */ React5.createElement("div", {
|
|
656
|
+
role: "none",
|
|
657
|
+
className: "flex-1"
|
|
658
|
+
}, /* @__PURE__ */ React5.createElement(InputComponent, {
|
|
659
|
+
type,
|
|
660
|
+
format,
|
|
661
|
+
label,
|
|
662
|
+
inputOnly: true,
|
|
663
|
+
property: `${name}.${index}`,
|
|
664
|
+
disabled: readonly,
|
|
665
|
+
placeholder,
|
|
666
|
+
...inputProps
|
|
667
|
+
})), /* @__PURE__ */ React5.createElement(IconButton, {
|
|
668
|
+
icon: "ph--trash--regular",
|
|
669
|
+
iconOnly: true,
|
|
670
|
+
label: t("button remove"),
|
|
671
|
+
onClick: () => {
|
|
672
|
+
const newValues = arrayValues.filter((_2, i) => i !== index);
|
|
673
|
+
inputProps.onValueChange(name, type, newValues);
|
|
674
|
+
}
|
|
675
|
+
})))), /* @__PURE__ */ React5.createElement("div", {
|
|
676
|
+
role: "none",
|
|
677
|
+
className: "flex justify-between items-center plb-1"
|
|
678
|
+
}, /* @__PURE__ */ React5.createElement(IconButton, {
|
|
679
|
+
icon: "ph--plus--regular",
|
|
680
|
+
iconOnly: true,
|
|
681
|
+
label: t("button add"),
|
|
682
|
+
onClick: () => {
|
|
683
|
+
const newValues = [
|
|
684
|
+
...arrayValues,
|
|
685
|
+
SimpleType.getDefaultValue(type)
|
|
686
|
+
];
|
|
687
|
+
inputProps.onValueChange(name, type, newValues);
|
|
688
|
+
}
|
|
689
|
+
})));
|
|
690
|
+
};
|
|
691
|
+
var FormActions = ({ onCancel, onSubmit, canSubmit, readonly }) => {
|
|
692
|
+
const { t } = useTranslation2(translationKey);
|
|
693
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
527
694
|
role: "none",
|
|
528
695
|
className: "flex justify-center"
|
|
529
696
|
}, /* @__PURE__ */ React5.createElement("div", {
|
|
530
697
|
role: "none",
|
|
531
698
|
className: mx(onCancel && !readonly && "grid grid-cols-2 gap-2")
|
|
532
699
|
}, onCancel && !readonly && /* @__PURE__ */ React5.createElement(IconButton, {
|
|
700
|
+
"data-testid": "cancel-button",
|
|
533
701
|
icon: "ph--x--regular",
|
|
534
702
|
label: t("button cancel"),
|
|
535
703
|
onClick: onCancel
|
|
536
704
|
}), onSubmit && /* @__PURE__ */ React5.createElement(IconButton, {
|
|
537
705
|
type: "submit",
|
|
706
|
+
"data-testid": "save-button",
|
|
538
707
|
disabled: !canSubmit,
|
|
539
708
|
icon: "ph--check--regular",
|
|
540
709
|
label: t("button save"),
|
|
541
|
-
onClick:
|
|
542
|
-
})))
|
|
710
|
+
onClick: onSubmit
|
|
711
|
+
})));
|
|
543
712
|
};
|
|
544
713
|
|
|
545
714
|
// packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
|
|
546
715
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
|
|
547
|
-
var FieldEditor = ({ view, projection, field, registry,
|
|
716
|
+
var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
548
717
|
const { t } = useTranslation3(translationKey);
|
|
549
718
|
const [props, setProps] = useState2(projection.getFieldProjection(field.id).props);
|
|
550
719
|
useEffect3(() => setProps(projection.getFieldProjection(field.id).props), [
|
|
@@ -615,22 +784,22 @@ var FieldEditor = ({ view, projection, field, registry, onClose, onCancel }) =>
|
|
|
615
784
|
view.fields,
|
|
616
785
|
field
|
|
617
786
|
]);
|
|
618
|
-
const
|
|
787
|
+
const handleSave = useCallback2((props2) => {
|
|
619
788
|
projection.setFieldProjection({
|
|
620
789
|
field,
|
|
621
790
|
props: props2
|
|
622
791
|
});
|
|
623
|
-
|
|
792
|
+
onSave();
|
|
624
793
|
}, [
|
|
625
794
|
projection,
|
|
626
795
|
field,
|
|
627
|
-
|
|
796
|
+
onSave
|
|
628
797
|
]);
|
|
629
798
|
const handleCancel = useCallback2(() => {
|
|
630
799
|
requestAnimationFrame(() => onCancel?.());
|
|
631
|
-
|
|
800
|
+
onSave();
|
|
632
801
|
}, [
|
|
633
|
-
|
|
802
|
+
onSave
|
|
634
803
|
]);
|
|
635
804
|
if (!fieldSchema) {
|
|
636
805
|
log3.warn("invalid format", {
|
|
@@ -655,7 +824,7 @@ var FieldEditor = ({ view, projection, field, registry, onClose, onCancel }) =>
|
|
|
655
824
|
],
|
|
656
825
|
onValuesChanged: handleValuesChanged,
|
|
657
826
|
onValidate: handleValidate,
|
|
658
|
-
|
|
827
|
+
onSave: handleSave,
|
|
659
828
|
onCancel: handleCancel,
|
|
660
829
|
Custom: {
|
|
661
830
|
["format"]: (props2) => /* @__PURE__ */ React6.createElement(SelectInput, {
|
|
@@ -694,7 +863,7 @@ var ViewMetaSchema = S2.Struct({
|
|
|
694
863
|
name: S2.String.annotations({
|
|
695
864
|
[AST2.TitleAnnotationId]: "View"
|
|
696
865
|
}),
|
|
697
|
-
|
|
866
|
+
typename: Format.DXN.annotations({
|
|
698
867
|
[AST2.TitleAnnotationId]: "Typename"
|
|
699
868
|
})
|
|
700
869
|
}).pipe(S2.mutable);
|
|
@@ -710,16 +879,16 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
710
879
|
name: view.name,
|
|
711
880
|
// TODO(burdon): Need to warn user of possible consequences of editing.
|
|
712
881
|
// TODO(burdon): Settings should have domain name owned by user.
|
|
713
|
-
|
|
882
|
+
typename: view.query.type
|
|
714
883
|
};
|
|
715
884
|
}, [
|
|
716
885
|
view
|
|
717
886
|
]);
|
|
718
|
-
const handleViewUpdate = useCallback3(({ name,
|
|
887
|
+
const handleViewUpdate = useCallback3(({ name, typename }) => {
|
|
719
888
|
requestAnimationFrame(() => {
|
|
720
889
|
view.name = name;
|
|
721
|
-
view.query.type =
|
|
722
|
-
schema.updateTypename(
|
|
890
|
+
view.query.type = typename;
|
|
891
|
+
schema.updateTypename(typename);
|
|
723
892
|
});
|
|
724
893
|
}, [
|
|
725
894
|
view,
|
|
@@ -748,7 +917,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
748
917
|
autoSave: true,
|
|
749
918
|
schema: ViewMetaSchema,
|
|
750
919
|
values: viewValues,
|
|
751
|
-
|
|
920
|
+
onSave: handleViewUpdate
|
|
752
921
|
}), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement("div", {
|
|
753
922
|
role: "none",
|
|
754
923
|
className: "p-2"
|
|
@@ -782,7 +951,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
782
951
|
projection,
|
|
783
952
|
field,
|
|
784
953
|
registry,
|
|
785
|
-
|
|
954
|
+
onSave: handleClose
|
|
786
955
|
}), !readonly && !field && /* @__PURE__ */ React7.createElement("div", {
|
|
787
956
|
className: "flex p-2 justify-center"
|
|
788
957
|
}, /* @__PURE__ */ React7.createElement(IconButton2, {
|
|
@@ -1018,6 +1187,7 @@ export {
|
|
|
1018
1187
|
DeprecatedFormInput,
|
|
1019
1188
|
FieldEditor,
|
|
1020
1189
|
Form,
|
|
1190
|
+
FormActions,
|
|
1021
1191
|
GeiPointInput,
|
|
1022
1192
|
InputHeader,
|
|
1023
1193
|
NumberInput,
|