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