@dxos/react-ui-form 0.7.5-labs.8a82073 → 0.7.5-labs.c0e040f
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 +398 -323
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +381 -302
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +398 -323
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/Form/Defaults.d.ts +1 -0
- package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContext.d.ts +4 -1
- package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/factory.d.ts.map +1 -1
- package/dist/types/src/components/Form/index.d.ts +2 -0
- package/dist/types/src/components/Form/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +1 -0
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/components/Form/Defaults.tsx +59 -3
- package/src/components/Form/Form.tsx +8 -5
- package/src/components/Form/FormContent.tsx +9 -12
- package/src/components/Form/FormContext.tsx +48 -4
- package/src/components/Form/custom/SelectOptionsInput.tsx +5 -7
- package/src/components/Form/factory.tsx +3 -1
- package/src/components/Form/index.ts +3 -0
- package/src/components/ViewEditor/ViewEditor.tsx +2 -2
- package/src/hooks/useForm.ts +6 -0
|
@@ -101,34 +101,275 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
|
|
|
101
101
|
};
|
|
102
102
|
|
|
103
103
|
// packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
|
|
104
|
-
import React12, { useCallback as
|
|
104
|
+
import React12, { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo5, useState as useState3 } from "react";
|
|
105
105
|
import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
|
|
106
106
|
import { log as log2 } from "@dxos/log";
|
|
107
107
|
import { useTranslation as useTranslation5 } from "@dxos/react-ui";
|
|
108
108
|
import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
|
|
109
109
|
|
|
110
|
+
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
111
|
+
import React2, { createContext, useContext, useEffect as useEffect2 } from "react";
|
|
112
|
+
import { raise } from "@dxos/debug";
|
|
113
|
+
import { getValue as getValue2 } from "@dxos/echo-schema";
|
|
114
|
+
import { createJsonPath as createJsonPath2 } from "@dxos/effect";
|
|
115
|
+
|
|
116
|
+
// packages/ui/react-ui-form/src/hooks/useForm.ts
|
|
117
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
118
|
+
import { getValue, setValue } from "@dxos/echo-schema";
|
|
119
|
+
import { AST, createJsonPath, fromEffectValidationPath } from "@dxos/effect";
|
|
120
|
+
import { invariant } from "@dxos/invariant";
|
|
121
|
+
import { log } from "@dxos/log";
|
|
122
|
+
import { validateSchema } from "@dxos/schema";
|
|
123
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
124
|
+
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
125
|
+
invariant(AST.isTypeLiteral(schema.ast), void 0, {
|
|
126
|
+
F: __dxlog_file,
|
|
127
|
+
L: 92,
|
|
128
|
+
S: void 0,
|
|
129
|
+
A: [
|
|
130
|
+
"AST.isTypeLiteral(schema.ast)",
|
|
131
|
+
""
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
const [values, setValues] = useState(initialValues);
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
setValues(initialValues);
|
|
137
|
+
}, [
|
|
138
|
+
initialValues
|
|
139
|
+
]);
|
|
140
|
+
const [touched, setTouched] = useState(createKeySet(initialValues, false));
|
|
141
|
+
const [changed, setChanged] = useState(createKeySet(initialValues, false));
|
|
142
|
+
const [errors, setErrors] = useState({});
|
|
143
|
+
const [saving, setSaving] = useState(false);
|
|
144
|
+
const validate = useCallback((values2) => {
|
|
145
|
+
let errors2 = validateSchema(schema, values2) ?? [];
|
|
146
|
+
if (errors2.length === 0 && onValidate) {
|
|
147
|
+
const validatedValues = values2;
|
|
148
|
+
errors2 = onValidate(validatedValues) ?? [];
|
|
149
|
+
}
|
|
150
|
+
setErrors(flatMap(errors2));
|
|
151
|
+
const valid = errors2.length === 0;
|
|
152
|
+
return valid;
|
|
153
|
+
}, [
|
|
154
|
+
schema,
|
|
155
|
+
onValidate
|
|
156
|
+
]);
|
|
157
|
+
const [schemaDirty, setSchemaDirty] = useState(false);
|
|
158
|
+
useEffect(() => setSchemaDirty(true), [
|
|
159
|
+
schema
|
|
160
|
+
]);
|
|
161
|
+
useEffect(() => {
|
|
162
|
+
if (schemaDirty) {
|
|
163
|
+
validate(values);
|
|
164
|
+
setSchemaDirty(false);
|
|
165
|
+
}
|
|
166
|
+
}, [
|
|
167
|
+
values,
|
|
168
|
+
schemaDirty
|
|
169
|
+
]);
|
|
170
|
+
const formIsValid = useMemo(() => {
|
|
171
|
+
return Object.keys(errors).length === 0;
|
|
172
|
+
}, [
|
|
173
|
+
errors
|
|
174
|
+
]);
|
|
175
|
+
const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors
|
|
176
|
+
!Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
|
|
177
|
+
touched,
|
|
178
|
+
errors,
|
|
179
|
+
saving
|
|
180
|
+
]);
|
|
181
|
+
const handleSave = useCallback(async () => {
|
|
182
|
+
if (validate(values)) {
|
|
183
|
+
setSaving(true);
|
|
184
|
+
try {
|
|
185
|
+
await onSave?.(values, {
|
|
186
|
+
changed
|
|
187
|
+
});
|
|
188
|
+
} finally {
|
|
189
|
+
setSaving(false);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}, [
|
|
193
|
+
values,
|
|
194
|
+
validate,
|
|
195
|
+
onSave,
|
|
196
|
+
changed
|
|
197
|
+
]);
|
|
198
|
+
const getStatus = useCallback((path) => {
|
|
199
|
+
const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
|
|
200
|
+
const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
|
|
201
|
+
return {
|
|
202
|
+
status: matchingError ? "error" : void 0,
|
|
203
|
+
error: matchingError ? matchingError[1] : void 0
|
|
204
|
+
};
|
|
205
|
+
}, [
|
|
206
|
+
errors
|
|
207
|
+
]);
|
|
208
|
+
const getFormValue = (path) => {
|
|
209
|
+
return getValue(values, createJsonPath(path));
|
|
210
|
+
};
|
|
211
|
+
const onValueChange = (path, type, value) => {
|
|
212
|
+
const jsonPath = createJsonPath(path);
|
|
213
|
+
let parsedValue = value;
|
|
214
|
+
try {
|
|
215
|
+
if (type === "number") {
|
|
216
|
+
parsedValue = parseFloat(value) || 0;
|
|
217
|
+
}
|
|
218
|
+
} catch (err) {
|
|
219
|
+
log.catch(err, void 0, {
|
|
220
|
+
F: __dxlog_file,
|
|
221
|
+
L: 198,
|
|
222
|
+
S: void 0,
|
|
223
|
+
C: (f, a) => f(...a)
|
|
224
|
+
});
|
|
225
|
+
parsedValue = void 0;
|
|
226
|
+
}
|
|
227
|
+
const newValues = {
|
|
228
|
+
...setValue(values, jsonPath, parsedValue)
|
|
229
|
+
};
|
|
230
|
+
setValues(newValues);
|
|
231
|
+
setChanged((prev) => ({
|
|
232
|
+
...prev,
|
|
233
|
+
[jsonPath]: true
|
|
234
|
+
}));
|
|
235
|
+
onValuesChanged?.(newValues);
|
|
236
|
+
const isValid = validate(newValues);
|
|
237
|
+
if (isValid && onValid) {
|
|
238
|
+
onValid(newValues, {
|
|
239
|
+
changed
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
const onTouched = useCallback((path) => {
|
|
244
|
+
const jsonPath = createJsonPath(path);
|
|
245
|
+
setTouched((touched2) => ({
|
|
246
|
+
...touched2,
|
|
247
|
+
[jsonPath]: true
|
|
248
|
+
}));
|
|
249
|
+
validate(values);
|
|
250
|
+
}, [
|
|
251
|
+
validate,
|
|
252
|
+
values
|
|
253
|
+
]);
|
|
254
|
+
return {
|
|
255
|
+
// State.
|
|
256
|
+
values,
|
|
257
|
+
errors,
|
|
258
|
+
touched,
|
|
259
|
+
changed,
|
|
260
|
+
canSave,
|
|
261
|
+
handleSave,
|
|
262
|
+
formIsValid,
|
|
263
|
+
// Field utils.
|
|
264
|
+
getStatus,
|
|
265
|
+
getValue: getFormValue,
|
|
266
|
+
onValueChange,
|
|
267
|
+
onTouched
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
var createKeySet = (obj, value) => {
|
|
271
|
+
invariant(obj, void 0, {
|
|
272
|
+
F: __dxlog_file,
|
|
273
|
+
L: 241,
|
|
274
|
+
S: void 0,
|
|
275
|
+
A: [
|
|
276
|
+
"obj",
|
|
277
|
+
""
|
|
278
|
+
]
|
|
279
|
+
});
|
|
280
|
+
return Object.keys(obj).reduce((acc, key) => ({
|
|
281
|
+
...acc,
|
|
282
|
+
[key]: value
|
|
283
|
+
}), {});
|
|
284
|
+
};
|
|
285
|
+
var flatMap = (errors) => {
|
|
286
|
+
return errors.reduce((result, { path, message }) => {
|
|
287
|
+
const jsonPath = fromEffectValidationPath(path);
|
|
288
|
+
if (!(jsonPath in result)) {
|
|
289
|
+
result[jsonPath] = message;
|
|
290
|
+
}
|
|
291
|
+
return result;
|
|
292
|
+
}, {});
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
296
|
+
var FormContext = /* @__PURE__ */ createContext(void 0);
|
|
297
|
+
var useFormContext = () => {
|
|
298
|
+
return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
|
|
299
|
+
};
|
|
300
|
+
var useFormValues = (path = []) => {
|
|
301
|
+
const { values: formValues } = useFormContext();
|
|
302
|
+
const jsonPath = createJsonPath2(path);
|
|
303
|
+
return getValue2(formValues, jsonPath);
|
|
304
|
+
};
|
|
305
|
+
var useInputProps = (path = []) => {
|
|
306
|
+
const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
|
|
307
|
+
return {
|
|
308
|
+
getStatus: () => getStatus(path),
|
|
309
|
+
getValue: () => getFormValue(path),
|
|
310
|
+
onValueChange: (type, value) => onValueChange(path, type, value),
|
|
311
|
+
onBlur: () => onTouched(path)
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
|
|
315
|
+
const form = useForm(formOptions);
|
|
316
|
+
useEffect2(() => {
|
|
317
|
+
if (!formRef?.current) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const handleKeyDown = (event) => {
|
|
321
|
+
const keyIsEnter = event.key === "Enter";
|
|
322
|
+
const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
|
|
323
|
+
const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
|
|
324
|
+
const inputOptOut = event.target.hasAttribute("data-no-submit");
|
|
325
|
+
const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
|
|
326
|
+
const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
|
|
327
|
+
if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
|
|
328
|
+
if (!autoSave && form.canSave) {
|
|
329
|
+
form.handleSave();
|
|
330
|
+
}
|
|
331
|
+
if (autoSave && form.formIsValid) {
|
|
332
|
+
event.target.blur();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const formElement = formRef.current;
|
|
337
|
+
formElement.addEventListener("keydown", handleKeyDown);
|
|
338
|
+
return () => formElement.removeEventListener("keydown", handleKeyDown);
|
|
339
|
+
}, [
|
|
340
|
+
formRef,
|
|
341
|
+
form.canSave,
|
|
342
|
+
form.formIsValid,
|
|
343
|
+
form.handleSave,
|
|
344
|
+
autoSave
|
|
345
|
+
]);
|
|
346
|
+
return /* @__PURE__ */ React2.createElement(FormContext.Provider, {
|
|
347
|
+
value: form
|
|
348
|
+
}, children);
|
|
349
|
+
};
|
|
350
|
+
|
|
110
351
|
// packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
|
|
111
|
-
import
|
|
352
|
+
import React4 from "react";
|
|
112
353
|
import { Input as Input2, useTranslation } from "@dxos/react-ui";
|
|
113
354
|
import { safeParseFloat } from "@dxos/util";
|
|
114
355
|
|
|
115
356
|
// packages/ui/react-ui-form/src/components/Form/Input.tsx
|
|
116
|
-
import
|
|
357
|
+
import React3 from "react";
|
|
117
358
|
import { Icon, Tooltip } from "@dxos/react-ui";
|
|
118
359
|
import { errorText } from "@dxos/react-ui-theme";
|
|
119
360
|
var InputHeader = ({ children, error }) => {
|
|
120
|
-
return /* @__PURE__ */
|
|
361
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
121
362
|
role: "none",
|
|
122
363
|
className: "flex justify-between items-center mb-1"
|
|
123
|
-
}, children, error && /* @__PURE__ */
|
|
364
|
+
}, children, error && /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
|
124
365
|
asChild: true
|
|
125
|
-
}, /* @__PURE__ */
|
|
366
|
+
}, /* @__PURE__ */ React3.createElement(Icon, {
|
|
126
367
|
icon: "ph--warning--regular",
|
|
127
368
|
size: 4,
|
|
128
369
|
classNames: errorText
|
|
129
|
-
})), /* @__PURE__ */
|
|
370
|
+
})), /* @__PURE__ */ React3.createElement(Tooltip.Content, {
|
|
130
371
|
side: "bottom"
|
|
131
|
-
}, /* @__PURE__ */
|
|
372
|
+
}, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null), error)));
|
|
132
373
|
};
|
|
133
374
|
|
|
134
375
|
// packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
|
|
@@ -136,13 +377,13 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
136
377
|
const { t } = useTranslation(translationKey);
|
|
137
378
|
const { status, error } = getStatus();
|
|
138
379
|
const [lng = 0, lat = 0] = getValue3() ?? [];
|
|
139
|
-
return /* @__PURE__ */
|
|
380
|
+
return /* @__PURE__ */ React4.createElement(Input2.Root, {
|
|
140
381
|
validationValence: status
|
|
141
|
-
}, /* @__PURE__ */
|
|
382
|
+
}, /* @__PURE__ */ React4.createElement(InputHeader, {
|
|
142
383
|
error
|
|
143
|
-
}, /* @__PURE__ */
|
|
384
|
+
}, /* @__PURE__ */ React4.createElement(Input2.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
|
|
144
385
|
className: "grid grid-cols-2 gap-2"
|
|
145
|
-
}, /* @__PURE__ */
|
|
386
|
+
}, /* @__PURE__ */ React4.createElement(Input2.TextInput, {
|
|
146
387
|
type: "number",
|
|
147
388
|
disabled,
|
|
148
389
|
placeholder: t("placeholder longitude"),
|
|
@@ -152,7 +393,7 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
152
393
|
safeParseFloat(event.target.value, 0)
|
|
153
394
|
]),
|
|
154
395
|
onBlur
|
|
155
|
-
}), /* @__PURE__ */
|
|
396
|
+
}), /* @__PURE__ */ React4.createElement(Input2.TextInput, {
|
|
156
397
|
type: "number",
|
|
157
398
|
disabled,
|
|
158
399
|
placeholder: t("placeholder latitude"),
|
|
@@ -166,20 +407,20 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
166
407
|
};
|
|
167
408
|
|
|
168
409
|
// packages/ui/react-ui-form/src/components/Form/custom/SelectOptionsInput.tsx
|
|
169
|
-
import
|
|
410
|
+
import React5, { useCallback as useCallback2, useEffect as useEffect3, useState as useState2, useRef } from "react";
|
|
170
411
|
import { PublicKey } from "@dxos/keys";
|
|
171
412
|
import { Icon as Icon2, IconButton, Input as Input3, Tag, Toolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
172
413
|
import { List } from "@dxos/react-ui-list";
|
|
173
414
|
import { HuePickerToolbarButton } from "@dxos/react-ui-pickers";
|
|
174
|
-
import {
|
|
415
|
+
import { hues, mx as mx2 } from "@dxos/react-ui-theme";
|
|
175
416
|
var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
|
|
176
|
-
const [selected, setSelectedId] =
|
|
177
|
-
const [isNewOption, setIsNewOption] =
|
|
417
|
+
const [selected, setSelectedId] = useState2(null);
|
|
418
|
+
const [isNewOption, setIsNewOption] = useState2(false);
|
|
178
419
|
const inputRef = useRef(null);
|
|
179
420
|
const { t } = useTranslation2(translationKey);
|
|
180
421
|
const { status, error } = getStatus();
|
|
181
422
|
const options = getValue3();
|
|
182
|
-
|
|
423
|
+
useEffect3(() => {
|
|
183
424
|
if (options === void 0) {
|
|
184
425
|
onValueChange(type, []);
|
|
185
426
|
}
|
|
@@ -190,16 +431,15 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
190
431
|
]);
|
|
191
432
|
const randomHue = () => {
|
|
192
433
|
const usedHues = new Set(options?.map((option) => option.color) ?? []);
|
|
193
|
-
const
|
|
194
|
-
const unusedHues = hueKeys.filter((hue) => !usedHues.has(hue));
|
|
434
|
+
const unusedHues = hues.filter((hue) => !usedHues.has(hue));
|
|
195
435
|
if (unusedHues.length > 0) {
|
|
196
436
|
return unusedHues[Math.floor(Math.random() * unusedHues.length)];
|
|
197
437
|
}
|
|
198
438
|
const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
|
|
199
|
-
const availableHues =
|
|
200
|
-
return availableHues[Math.floor(Math.random() * availableHues.length)] ??
|
|
439
|
+
const availableHues = hues.filter((hue) => !lastThree.has(hue));
|
|
440
|
+
return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
|
|
201
441
|
};
|
|
202
|
-
const handleAdd =
|
|
442
|
+
const handleAdd = useCallback2(() => {
|
|
203
443
|
const newId = PublicKey.random().truncate();
|
|
204
444
|
const newOption = {
|
|
205
445
|
id: newId,
|
|
@@ -217,7 +457,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
217
457
|
type,
|
|
218
458
|
onValueChange
|
|
219
459
|
]);
|
|
220
|
-
const handleDelete =
|
|
460
|
+
const handleDelete = useCallback2((id) => {
|
|
221
461
|
const newOptions = options?.filter((option) => option.id !== id) ?? [];
|
|
222
462
|
onValueChange(type, newOptions);
|
|
223
463
|
setSelectedId(null);
|
|
@@ -226,7 +466,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
226
466
|
type,
|
|
227
467
|
onValueChange
|
|
228
468
|
]);
|
|
229
|
-
const handleMove =
|
|
469
|
+
const handleMove = useCallback2((from, to) => {
|
|
230
470
|
if (!options) {
|
|
231
471
|
return;
|
|
232
472
|
}
|
|
@@ -241,10 +481,10 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
241
481
|
type,
|
|
242
482
|
onValueChange
|
|
243
483
|
]);
|
|
244
|
-
const handleClick =
|
|
484
|
+
const handleClick = useCallback2((id) => {
|
|
245
485
|
setSelectedId((current) => current === id ? null : id);
|
|
246
486
|
}, []);
|
|
247
|
-
const handleTitleChange =
|
|
487
|
+
const handleTitleChange = useCallback2((id) => (e) => {
|
|
248
488
|
const newOptions = options?.map((o) => o.id === id ? {
|
|
249
489
|
...o,
|
|
250
490
|
title: e.target.value
|
|
@@ -255,12 +495,12 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
255
495
|
type,
|
|
256
496
|
onValueChange
|
|
257
497
|
]);
|
|
258
|
-
const handleKeyDown =
|
|
498
|
+
const handleKeyDown = useCallback2((e) => {
|
|
259
499
|
if (e.key === "Enter") {
|
|
260
500
|
setSelectedId(null);
|
|
261
501
|
}
|
|
262
502
|
}, []);
|
|
263
|
-
const handleColorChange =
|
|
503
|
+
const handleColorChange = useCallback2((id) => (hue) => {
|
|
264
504
|
const newOptions = options?.map((o) => o.id === id ? {
|
|
265
505
|
...o,
|
|
266
506
|
color: hue
|
|
@@ -271,7 +511,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
271
511
|
type,
|
|
272
512
|
onValueChange
|
|
273
513
|
]);
|
|
274
|
-
|
|
514
|
+
useEffect3(() => {
|
|
275
515
|
if (selected && isNewOption && inputRef.current) {
|
|
276
516
|
inputRef.current.focus();
|
|
277
517
|
setIsNewOption(false);
|
|
@@ -280,76 +520,77 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
|
|
|
280
520
|
selected,
|
|
281
521
|
isNewOption
|
|
282
522
|
]);
|
|
283
|
-
return /* @__PURE__ */
|
|
523
|
+
return /* @__PURE__ */ React5.createElement(Input3.Root, {
|
|
284
524
|
validationValence: status
|
|
285
|
-
}, /* @__PURE__ */
|
|
525
|
+
}, /* @__PURE__ */ React5.createElement(InputHeader, {
|
|
286
526
|
error
|
|
287
|
-
}, /* @__PURE__ */
|
|
527
|
+
}, /* @__PURE__ */ React5.createElement(Input3.Label, null, label)), /* @__PURE__ */ React5.createElement("div", {
|
|
288
528
|
role: "none"
|
|
289
|
-
}, options && /* @__PURE__ */
|
|
529
|
+
}, options && /* @__PURE__ */ React5.createElement(List.Root, {
|
|
290
530
|
items: options,
|
|
291
531
|
isItem: (item) => true,
|
|
292
532
|
onMove: handleMove
|
|
293
|
-
}, ({ items }) => /* @__PURE__ */
|
|
533
|
+
}, ({ items }) => /* @__PURE__ */ React5.createElement("div", {
|
|
294
534
|
role: "list",
|
|
295
535
|
className: "w-full overflow-auto"
|
|
296
|
-
}, items?.map((item) => /* @__PURE__ */
|
|
536
|
+
}, items?.map((item) => /* @__PURE__ */ React5.createElement("div", {
|
|
297
537
|
key: item.id
|
|
298
|
-
}, /* @__PURE__ */
|
|
538
|
+
}, /* @__PURE__ */ React5.createElement(List.Item, {
|
|
299
539
|
role: "button",
|
|
300
540
|
item,
|
|
301
541
|
classNames: mx2("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
|
|
302
542
|
"aria-expanded": selected === item.id
|
|
303
|
-
}, /* @__PURE__ */
|
|
543
|
+
}, /* @__PURE__ */ React5.createElement("div", {
|
|
304
544
|
className: "flex items-center"
|
|
305
|
-
}, /* @__PURE__ */
|
|
545
|
+
}, /* @__PURE__ */ React5.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React5.createElement(List.ItemTitle, {
|
|
306
546
|
onClick: () => handleClick(item.id),
|
|
307
547
|
classNames: "flex-1"
|
|
308
|
-
}, /* @__PURE__ */
|
|
548
|
+
}, /* @__PURE__ */ React5.createElement(Tag, {
|
|
309
549
|
palette: item.color
|
|
310
|
-
}, item.title || "\u200B")), /* @__PURE__ */
|
|
550
|
+
}, item.title || "\u200B")), /* @__PURE__ */ React5.createElement(Icon2, {
|
|
311
551
|
icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
312
552
|
onClick: () => handleClick(item.id)
|
|
313
|
-
})), selected === item.id && /* @__PURE__ */
|
|
553
|
+
})), selected === item.id && /* @__PURE__ */ React5.createElement("div", {
|
|
314
554
|
className: "mis-4 mbs-2 flex flex-col gap-1"
|
|
315
|
-
}, /* @__PURE__ */
|
|
555
|
+
}, /* @__PURE__ */ React5.createElement(Input3.Label, {
|
|
316
556
|
classNames: "text-xs"
|
|
317
|
-
}, t("select option label")), /* @__PURE__ */
|
|
557
|
+
}, t("select option label")), /* @__PURE__ */ React5.createElement("div", {
|
|
318
558
|
className: "flex flex-row items-center gap-1"
|
|
319
|
-
}, /* @__PURE__ */
|
|
559
|
+
}, /* @__PURE__ */ React5.createElement(Input3.TextInput, {
|
|
320
560
|
placeholder: t("select option label placeholder"),
|
|
321
561
|
ref: selected === item.id ? inputRef : void 0,
|
|
322
562
|
value: item.title,
|
|
323
563
|
onChange: handleTitleChange(item.id),
|
|
324
564
|
onKeyDown: handleKeyDown,
|
|
325
|
-
classNames: "flex-1"
|
|
326
|
-
|
|
565
|
+
classNames: "flex-1",
|
|
566
|
+
"data-no-submit": true
|
|
567
|
+
}), /* @__PURE__ */ React5.createElement(Toolbar.Root, {
|
|
327
568
|
classNames: "p-0 m-0 !is-auto"
|
|
328
|
-
}, /* @__PURE__ */
|
|
569
|
+
}, /* @__PURE__ */ React5.createElement(HuePickerToolbarButton, {
|
|
329
570
|
hue: item.color,
|
|
330
571
|
onChangeHue: handleColorChange(item.id)
|
|
331
|
-
})), /* @__PURE__ */
|
|
572
|
+
})), /* @__PURE__ */ React5.createElement(IconButton, {
|
|
332
573
|
icon: "ph--trash--fill",
|
|
333
574
|
iconOnly: true,
|
|
334
575
|
label: t("select option delete"),
|
|
335
576
|
onClick: () => handleDelete(item.id)
|
|
336
|
-
})))))), /* @__PURE__ */
|
|
577
|
+
})))))), /* @__PURE__ */ React5.createElement("div", {
|
|
337
578
|
role: "listitem"
|
|
338
|
-
}, /* @__PURE__ */
|
|
579
|
+
}, /* @__PURE__ */ React5.createElement("div", {
|
|
339
580
|
role: "button",
|
|
340
581
|
className: mx2("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
|
|
341
582
|
onClick: handleAdd
|
|
342
|
-
}, /* @__PURE__ */
|
|
583
|
+
}, /* @__PURE__ */ React5.createElement("div", {
|
|
343
584
|
className: "flex items-center gap-1"
|
|
344
|
-
}, /* @__PURE__ */
|
|
585
|
+
}, /* @__PURE__ */ React5.createElement(Icon2, {
|
|
345
586
|
icon: "ph--plus--regular"
|
|
346
|
-
}), /* @__PURE__ */
|
|
587
|
+
}), /* @__PURE__ */ React5.createElement("span", {
|
|
347
588
|
className: "text-sm"
|
|
348
589
|
}, t("select option add")))))))));
|
|
349
590
|
};
|
|
350
591
|
|
|
351
592
|
// packages/ui/react-ui-form/src/components/Form/custom/TupleInput.tsx
|
|
352
|
-
import
|
|
593
|
+
import React6 from "react";
|
|
353
594
|
import { Input as Input4 } from "@dxos/react-ui";
|
|
354
595
|
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
355
596
|
import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
|
|
@@ -362,13 +603,13 @@ var gridCols = [
|
|
|
362
603
|
var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
363
604
|
const { status, error } = getStatus();
|
|
364
605
|
const values = getValue3() ?? {};
|
|
365
|
-
return /* @__PURE__ */
|
|
606
|
+
return /* @__PURE__ */ React6.createElement(Input4.Root, {
|
|
366
607
|
validationValence: status
|
|
367
|
-
}, /* @__PURE__ */
|
|
608
|
+
}, /* @__PURE__ */ React6.createElement(InputHeader, {
|
|
368
609
|
error
|
|
369
|
-
}, /* @__PURE__ */
|
|
610
|
+
}, /* @__PURE__ */ React6.createElement(Input4.Label, null, label)), /* @__PURE__ */ React6.createElement("div", {
|
|
370
611
|
className: mx3("grid gap-2", gridCols[binding.length - 1])
|
|
371
|
-
}, binding.map((prop) => /* @__PURE__ */
|
|
612
|
+
}, binding.map((prop) => /* @__PURE__ */ React6.createElement(Input4.TextInput, {
|
|
372
613
|
key: prop,
|
|
373
614
|
type: "number",
|
|
374
615
|
disabled,
|
|
@@ -382,286 +623,118 @@ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValu
|
|
|
382
623
|
};
|
|
383
624
|
|
|
384
625
|
// packages/ui/react-ui-form/src/components/Form/Defaults.tsx
|
|
385
|
-
import
|
|
626
|
+
import React7, { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef2 } from "react";
|
|
386
627
|
import { Input as Input5, Select } from "@dxos/react-ui";
|
|
387
628
|
var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
388
629
|
const { status, error } = getStatus();
|
|
389
|
-
return /* @__PURE__ */
|
|
630
|
+
return /* @__PURE__ */ React7.createElement(Input5.Root, {
|
|
390
631
|
validationValence: status
|
|
391
|
-
}, !inputOnly && /* @__PURE__ */
|
|
632
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
392
633
|
error
|
|
393
|
-
}, /* @__PURE__ */
|
|
634
|
+
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.TextInput, {
|
|
394
635
|
disabled,
|
|
395
636
|
placeholder,
|
|
396
637
|
value: getValue3() ?? "",
|
|
397
638
|
onChange: (event) => onValueChange(type, event.target.value),
|
|
398
639
|
onBlur
|
|
399
|
-
}), inputOnly && /* @__PURE__ */
|
|
640
|
+
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.Validation, null, error));
|
|
400
641
|
};
|
|
401
642
|
var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
402
643
|
const { status, error } = getStatus();
|
|
403
|
-
return /* @__PURE__ */
|
|
644
|
+
return /* @__PURE__ */ React7.createElement(Input5.Root, {
|
|
404
645
|
validationValence: status
|
|
405
|
-
}, !inputOnly && /* @__PURE__ */
|
|
646
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
406
647
|
error
|
|
407
|
-
}, /* @__PURE__ */
|
|
648
|
+
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.TextInput, {
|
|
408
649
|
type: "number",
|
|
409
650
|
disabled,
|
|
410
651
|
placeholder,
|
|
411
652
|
value: getValue3() ?? 0,
|
|
412
653
|
onChange: (event) => onValueChange(type, event.target.value),
|
|
413
654
|
onBlur
|
|
414
|
-
}), inputOnly && /* @__PURE__ */
|
|
655
|
+
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
415
656
|
};
|
|
416
657
|
var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
|
|
417
658
|
const { status, error } = getStatus();
|
|
418
659
|
const checked = Boolean(getValue3());
|
|
419
|
-
return /* @__PURE__ */
|
|
660
|
+
return /* @__PURE__ */ React7.createElement(Input5.Root, {
|
|
420
661
|
validationValence: status
|
|
421
|
-
}, !inputOnly && /* @__PURE__ */
|
|
662
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
422
663
|
error
|
|
423
|
-
}, /* @__PURE__ */
|
|
664
|
+
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.Switch, {
|
|
424
665
|
checked,
|
|
425
666
|
onCheckedChange: (value) => onValueChange(type, value)
|
|
426
|
-
}), inputOnly && /* @__PURE__ */
|
|
667
|
+
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
427
668
|
};
|
|
428
669
|
var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
|
|
429
670
|
const { status, error } = getStatus();
|
|
430
|
-
return /* @__PURE__ */
|
|
671
|
+
return /* @__PURE__ */ React7.createElement(Input5.Root, {
|
|
431
672
|
validationValence: status
|
|
432
|
-
}, !inputOnly && /* @__PURE__ */
|
|
673
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
433
674
|
error
|
|
434
|
-
}, /* @__PURE__ */
|
|
675
|
+
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Select.Root, {
|
|
435
676
|
value: getValue3(),
|
|
436
677
|
onValueChange: (value) => onValueChange(type, value)
|
|
437
|
-
}, /* @__PURE__ */
|
|
678
|
+
}, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
|
|
438
679
|
classNames: "is-full",
|
|
439
680
|
disabled,
|
|
440
681
|
placeholder
|
|
441
|
-
}), /* @__PURE__ */
|
|
682
|
+
}), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
|
|
442
683
|
// NOTE: Numeric values are converted to and from strings.
|
|
443
|
-
/* @__PURE__ */
|
|
684
|
+
/* @__PURE__ */ React7.createElement(Select.Option, {
|
|
444
685
|
key: String(value),
|
|
445
686
|
value: String(value)
|
|
446
687
|
}, label2 ?? String(value))
|
|
447
|
-
)))))), inputOnly && /* @__PURE__ */
|
|
688
|
+
)))))), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
|
|
448
689
|
};
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
458
|
-
|
|
459
|
-
// packages/ui/react-ui-form/src/components/Form/FormContext.tsx
|
|
460
|
-
import React7, { createContext, useContext } from "react";
|
|
461
|
-
import { raise } from "@dxos/debug";
|
|
462
|
-
import { getValue as getValue2 } from "@dxos/echo-schema";
|
|
463
|
-
import { createJsonPath as createJsonPath2 } from "@dxos/effect";
|
|
464
|
-
|
|
465
|
-
// packages/ui/react-ui-form/src/hooks/useForm.ts
|
|
466
|
-
import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
|
|
467
|
-
import { getValue, setValue } from "@dxos/echo-schema";
|
|
468
|
-
import { AST, createJsonPath, fromEffectValidationPath } from "@dxos/effect";
|
|
469
|
-
import { invariant } from "@dxos/invariant";
|
|
470
|
-
import { log } from "@dxos/log";
|
|
471
|
-
import { validateSchema } from "@dxos/schema";
|
|
472
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
473
|
-
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
474
|
-
invariant(AST.isTypeLiteral(schema.ast), void 0, {
|
|
475
|
-
F: __dxlog_file,
|
|
476
|
-
L: 91,
|
|
477
|
-
S: void 0,
|
|
478
|
-
A: [
|
|
479
|
-
"AST.isTypeLiteral(schema.ast)",
|
|
480
|
-
""
|
|
481
|
-
]
|
|
482
|
-
});
|
|
483
|
-
const [values, setValues] = useState2(initialValues);
|
|
484
|
-
useEffect2(() => {
|
|
485
|
-
setValues(initialValues);
|
|
486
|
-
}, [
|
|
487
|
-
initialValues
|
|
488
|
-
]);
|
|
489
|
-
const [touched, setTouched] = useState2(createKeySet(initialValues, false));
|
|
490
|
-
const [changed, setChanged] = useState2(createKeySet(initialValues, false));
|
|
491
|
-
const [errors, setErrors] = useState2({});
|
|
492
|
-
const [saving, setSaving] = useState2(false);
|
|
493
|
-
const validate = useCallback2((values2) => {
|
|
494
|
-
let errors2 = validateSchema(schema, values2) ?? [];
|
|
495
|
-
if (errors2.length === 0 && onValidate) {
|
|
496
|
-
const validatedValues = values2;
|
|
497
|
-
errors2 = onValidate(validatedValues) ?? [];
|
|
498
|
-
}
|
|
499
|
-
setErrors(flatMap(errors2));
|
|
500
|
-
const valid = errors2.length === 0;
|
|
501
|
-
return valid;
|
|
502
|
-
}, [
|
|
503
|
-
schema,
|
|
504
|
-
onValidate
|
|
505
|
-
]);
|
|
506
|
-
const [schemaDirty, setSchemaDirty] = useState2(false);
|
|
507
|
-
useEffect2(() => setSchemaDirty(true), [
|
|
508
|
-
schema
|
|
509
|
-
]);
|
|
510
|
-
useEffect2(() => {
|
|
511
|
-
if (schemaDirty) {
|
|
512
|
-
validate(values);
|
|
513
|
-
setSchemaDirty(false);
|
|
514
|
-
}
|
|
515
|
-
}, [
|
|
516
|
-
values,
|
|
517
|
-
schemaDirty
|
|
518
|
-
]);
|
|
519
|
-
const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors
|
|
520
|
-
!Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
|
|
521
|
-
touched,
|
|
522
|
-
errors,
|
|
523
|
-
saving
|
|
524
|
-
]);
|
|
525
|
-
const handleSave = useCallback2(async () => {
|
|
526
|
-
if (validate(values)) {
|
|
527
|
-
setSaving(true);
|
|
528
|
-
try {
|
|
529
|
-
await onSave?.(values, {
|
|
530
|
-
changed
|
|
531
|
-
});
|
|
532
|
-
} finally {
|
|
533
|
-
setSaving(false);
|
|
534
|
-
}
|
|
690
|
+
var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
|
|
691
|
+
const { status, error } = getStatus();
|
|
692
|
+
const textareaRef = useRef2(null);
|
|
693
|
+
const adjustHeight = useCallback3(() => {
|
|
694
|
+
const textarea = textareaRef.current;
|
|
695
|
+
if (textarea) {
|
|
696
|
+
textarea.style.blockSize = "auto";
|
|
697
|
+
textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
|
|
535
698
|
}
|
|
699
|
+
}, []);
|
|
700
|
+
useEffect4(() => {
|
|
701
|
+
adjustHeight();
|
|
536
702
|
}, [
|
|
537
|
-
|
|
538
|
-
validate,
|
|
539
|
-
onSave,
|
|
540
|
-
changed
|
|
541
|
-
]);
|
|
542
|
-
const getStatus = useCallback2((path) => {
|
|
543
|
-
const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
|
|
544
|
-
const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
|
|
545
|
-
return {
|
|
546
|
-
status: matchingError ? "error" : void 0,
|
|
547
|
-
error: matchingError ? matchingError[1] : void 0
|
|
548
|
-
};
|
|
549
|
-
}, [
|
|
550
|
-
errors
|
|
703
|
+
adjustHeight
|
|
551
704
|
]);
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
};
|
|
555
|
-
const onValueChange = (path, type, value) => {
|
|
556
|
-
const jsonPath = createJsonPath(path);
|
|
557
|
-
let parsedValue = value;
|
|
558
|
-
try {
|
|
559
|
-
if (type === "number") {
|
|
560
|
-
parsedValue = parseFloat(value) || 0;
|
|
561
|
-
}
|
|
562
|
-
} catch (err) {
|
|
563
|
-
log.catch(err, void 0, {
|
|
564
|
-
F: __dxlog_file,
|
|
565
|
-
L: 193,
|
|
566
|
-
S: void 0,
|
|
567
|
-
C: (f, a) => f(...a)
|
|
568
|
-
});
|
|
569
|
-
parsedValue = void 0;
|
|
570
|
-
}
|
|
571
|
-
const newValues = {
|
|
572
|
-
...setValue(values, jsonPath, parsedValue)
|
|
573
|
-
};
|
|
574
|
-
setValues(newValues);
|
|
575
|
-
setChanged((prev) => ({
|
|
576
|
-
...prev,
|
|
577
|
-
[jsonPath]: true
|
|
578
|
-
}));
|
|
579
|
-
onValuesChanged?.(newValues);
|
|
580
|
-
const isValid = validate(newValues);
|
|
581
|
-
if (isValid && onValid) {
|
|
582
|
-
onValid(newValues, {
|
|
583
|
-
changed
|
|
584
|
-
});
|
|
585
|
-
}
|
|
586
|
-
};
|
|
587
|
-
const onTouched = useCallback2((path) => {
|
|
588
|
-
const jsonPath = createJsonPath(path);
|
|
589
|
-
setTouched((touched2) => ({
|
|
590
|
-
...touched2,
|
|
591
|
-
[jsonPath]: true
|
|
592
|
-
}));
|
|
593
|
-
validate(values);
|
|
705
|
+
useEffect4(() => {
|
|
706
|
+
adjustHeight();
|
|
594
707
|
}, [
|
|
595
|
-
|
|
596
|
-
|
|
708
|
+
getValue3(),
|
|
709
|
+
adjustHeight
|
|
597
710
|
]);
|
|
598
|
-
return {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
F: __dxlog_file,
|
|
616
|
-
L: 235,
|
|
617
|
-
S: void 0,
|
|
618
|
-
A: [
|
|
619
|
-
"obj",
|
|
620
|
-
""
|
|
621
|
-
]
|
|
622
|
-
});
|
|
623
|
-
return Object.keys(obj).reduce((acc, key) => ({
|
|
624
|
-
...acc,
|
|
625
|
-
[key]: value
|
|
626
|
-
}), {});
|
|
627
|
-
};
|
|
628
|
-
var flatMap = (errors) => {
|
|
629
|
-
return errors.reduce((result, { path, message }) => {
|
|
630
|
-
const jsonPath = fromEffectValidationPath(path);
|
|
631
|
-
if (!(jsonPath in result)) {
|
|
632
|
-
result[jsonPath] = message;
|
|
633
|
-
}
|
|
634
|
-
return result;
|
|
635
|
-
}, {});
|
|
711
|
+
return /* @__PURE__ */ React7.createElement(Input5.Root, {
|
|
712
|
+
validationValence: status
|
|
713
|
+
}, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
|
|
714
|
+
error
|
|
715
|
+
}, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.TextArea, {
|
|
716
|
+
ref: textareaRef,
|
|
717
|
+
disabled,
|
|
718
|
+
placeholder,
|
|
719
|
+
value: getValue3() ?? "",
|
|
720
|
+
classNames: "min-bs-auto overflow-hidden",
|
|
721
|
+
onChange: (event) => onValueChange(type, event.target.value),
|
|
722
|
+
onBlur,
|
|
723
|
+
style: {
|
|
724
|
+
resize: "none"
|
|
725
|
+
},
|
|
726
|
+
spellCheck: false
|
|
727
|
+
}), inputOnly && /* @__PURE__ */ React7.createElement(Input5.Validation, null, error));
|
|
636
728
|
};
|
|
637
729
|
|
|
638
|
-
// packages/ui/react-ui-form/src/components/Form/
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
|
|
642
|
-
};
|
|
643
|
-
var useFormValues = (path = []) => {
|
|
644
|
-
const { values: formValues } = useFormContext();
|
|
645
|
-
const jsonPath = createJsonPath2(path);
|
|
646
|
-
return getValue2(formValues, jsonPath);
|
|
647
|
-
};
|
|
648
|
-
var useInputProps = (path = []) => {
|
|
649
|
-
const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
|
|
650
|
-
return {
|
|
651
|
-
getStatus: () => getStatus(path),
|
|
652
|
-
getValue: () => getFormValue(path),
|
|
653
|
-
onValueChange: (type, value) => onValueChange(path, type, value),
|
|
654
|
-
onBlur: () => onTouched(path)
|
|
655
|
-
};
|
|
656
|
-
};
|
|
657
|
-
var FormProvider = ({ children, ...formOptions }) => {
|
|
658
|
-
const formHandler = useForm(formOptions);
|
|
659
|
-
return /* @__PURE__ */ React7.createElement(FormContext.Provider, {
|
|
660
|
-
value: formHandler
|
|
661
|
-
}, children);
|
|
662
|
-
};
|
|
730
|
+
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
731
|
+
import React11, { useEffect as useEffect5, useMemo as useMemo4, useRef as useRef3 } from "react";
|
|
732
|
+
import { mx as mx7 } from "@dxos/react-ui-theme";
|
|
663
733
|
|
|
664
734
|
// packages/ui/react-ui-form/src/components/Form/FormActions.tsx
|
|
735
|
+
import React8 from "react";
|
|
736
|
+
import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
737
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
665
738
|
var FormActions = ({ onCancel, readonly }) => {
|
|
666
739
|
const { t } = useTranslation3(translationKey);
|
|
667
740
|
const { canSave, handleSave } = useFormContext();
|
|
@@ -699,7 +772,7 @@ import { isNotFalsy } from "@dxos/util";
|
|
|
699
772
|
// packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
|
|
700
773
|
import { pipe } from "effect";
|
|
701
774
|
import { capitalize } from "effect/String";
|
|
702
|
-
import React9, { useCallback as
|
|
775
|
+
import React9, { useCallback as useCallback4, useMemo as useMemo2 } from "react";
|
|
703
776
|
import { AST as AST2 } from "@dxos/echo-schema";
|
|
704
777
|
import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
|
|
705
778
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
@@ -745,7 +818,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
|
|
|
745
818
|
type,
|
|
746
819
|
elementType
|
|
747
820
|
]);
|
|
748
|
-
const handleAdd =
|
|
821
|
+
const handleAdd = useCallback4(() => {
|
|
749
822
|
inputProps.onValueChange(type, [
|
|
750
823
|
...values,
|
|
751
824
|
newValue
|
|
@@ -757,7 +830,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
|
|
|
757
830
|
newValue,
|
|
758
831
|
values
|
|
759
832
|
]);
|
|
760
|
-
const handleRemove =
|
|
833
|
+
const handleRemove = useCallback4((index) => {
|
|
761
834
|
const newValues = values.filter((_, i) => i !== index);
|
|
762
835
|
inputProps.onValueChange(type, newValues);
|
|
763
836
|
}, [
|
|
@@ -817,6 +890,8 @@ var getInputComponent = (type, format) => {
|
|
|
817
890
|
switch (format) {
|
|
818
891
|
case FormatEnum.LatLng:
|
|
819
892
|
return GeoPointInput;
|
|
893
|
+
case FormatEnum.Markdown:
|
|
894
|
+
return MarkdownInput;
|
|
820
895
|
}
|
|
821
896
|
switch (type) {
|
|
822
897
|
case "string":
|
|
@@ -860,20 +935,15 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
|
|
|
860
935
|
const jsonPath = createJsonPath3(path ?? []);
|
|
861
936
|
const CustomComponent = Custom?.[jsonPath];
|
|
862
937
|
if (CustomComponent) {
|
|
863
|
-
return (
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
placeholder,
|
|
873
|
-
disabled: readonly,
|
|
874
|
-
...inputProps
|
|
875
|
-
}))
|
|
876
|
-
);
|
|
938
|
+
return /* @__PURE__ */ React10.createElement(CustomComponent, {
|
|
939
|
+
type,
|
|
940
|
+
format,
|
|
941
|
+
label,
|
|
942
|
+
inputOnly: inline,
|
|
943
|
+
placeholder,
|
|
944
|
+
disabled: readonly,
|
|
945
|
+
...inputProps
|
|
946
|
+
});
|
|
877
947
|
}
|
|
878
948
|
if (array) {
|
|
879
949
|
return /* @__PURE__ */ React10.createElement(ArrayField, {
|
|
@@ -963,13 +1033,14 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
|
|
|
963
1033
|
|
|
964
1034
|
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
965
1035
|
var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
|
|
1036
|
+
const formRef = useRef3(null);
|
|
966
1037
|
const onValid = useMemo4(() => autoSave ? onSave : void 0, [
|
|
967
1038
|
autoSave,
|
|
968
1039
|
onSave
|
|
969
1040
|
]);
|
|
970
|
-
|
|
971
|
-
if (autoFocus) {
|
|
972
|
-
const input =
|
|
1041
|
+
useEffect5(() => {
|
|
1042
|
+
if (autoFocus && formRef.current) {
|
|
1043
|
+
const input = formRef.current.querySelector("input");
|
|
973
1044
|
if (input) {
|
|
974
1045
|
input.focus();
|
|
975
1046
|
}
|
|
@@ -978,13 +1049,16 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
|
|
|
978
1049
|
autoFocus
|
|
979
1050
|
]);
|
|
980
1051
|
return /* @__PURE__ */ React11.createElement(FormProvider, {
|
|
1052
|
+
formRef,
|
|
981
1053
|
schema,
|
|
1054
|
+
autoSave,
|
|
982
1055
|
initialValues,
|
|
983
1056
|
onValuesChanged,
|
|
984
1057
|
onValidate,
|
|
985
1058
|
onValid,
|
|
986
1059
|
onSave
|
|
987
1060
|
}, /* @__PURE__ */ React11.createElement("div", {
|
|
1061
|
+
ref: formRef,
|
|
988
1062
|
role: "none",
|
|
989
1063
|
className: mx7("p-2", classNames),
|
|
990
1064
|
"data-testid": testId
|
|
@@ -1007,12 +1081,12 @@ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/c
|
|
|
1007
1081
|
var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
1008
1082
|
const { t } = useTranslation5(translationKey);
|
|
1009
1083
|
const [props, setProps] = useState3(projection.getFieldProjection(field.id).props);
|
|
1010
|
-
|
|
1084
|
+
useEffect6(() => setProps(projection.getFieldProjection(field.id).props), [
|
|
1011
1085
|
field,
|
|
1012
1086
|
projection
|
|
1013
1087
|
]);
|
|
1014
1088
|
const [schemas, setSchemas] = useState3([]);
|
|
1015
|
-
|
|
1089
|
+
useEffect6(() => {
|
|
1016
1090
|
if (!registry) {
|
|
1017
1091
|
return;
|
|
1018
1092
|
}
|
|
@@ -1031,7 +1105,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1031
1105
|
registry
|
|
1032
1106
|
]);
|
|
1033
1107
|
const [referenceSchema, setReferenceSchema] = useState3();
|
|
1034
|
-
|
|
1108
|
+
useEffect6(() => {
|
|
1035
1109
|
setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
|
|
1036
1110
|
}, [
|
|
1037
1111
|
schemas,
|
|
@@ -1040,7 +1114,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1040
1114
|
const [{ fieldSchema }, setFieldSchema] = useState3({
|
|
1041
1115
|
fieldSchema: getFormatSchema(props?.format)
|
|
1042
1116
|
});
|
|
1043
|
-
const handleValuesChanged =
|
|
1117
|
+
const handleValuesChanged = useCallback5((_props) => {
|
|
1044
1118
|
setFieldSchema((prev) => {
|
|
1045
1119
|
const fieldSchema2 = getFormatSchema(_props.format);
|
|
1046
1120
|
if (prev.fieldSchema === fieldSchema2) {
|
|
@@ -1075,7 +1149,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1075
1149
|
props.format,
|
|
1076
1150
|
props.referenceSchema
|
|
1077
1151
|
]);
|
|
1078
|
-
const handleValidate =
|
|
1152
|
+
const handleValidate = useCallback5(({ property }) => {
|
|
1079
1153
|
if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
|
|
1080
1154
|
return [
|
|
1081
1155
|
{
|
|
@@ -1088,7 +1162,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1088
1162
|
view.fields,
|
|
1089
1163
|
field
|
|
1090
1164
|
]);
|
|
1091
|
-
const handleSave =
|
|
1165
|
+
const handleSave = useCallback5((props2) => {
|
|
1092
1166
|
projection.setFieldProjection({
|
|
1093
1167
|
field,
|
|
1094
1168
|
props: props2
|
|
@@ -1099,7 +1173,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1099
1173
|
field,
|
|
1100
1174
|
onSave
|
|
1101
1175
|
]);
|
|
1102
|
-
const handleCancel =
|
|
1176
|
+
const handleCancel = useCallback5(() => {
|
|
1103
1177
|
requestAnimationFrame(() => onCancel?.());
|
|
1104
1178
|
onSave();
|
|
1105
1179
|
}, [
|
|
@@ -1131,7 +1205,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1131
1205
|
schemas,
|
|
1132
1206
|
referenceSchema
|
|
1133
1207
|
]);
|
|
1134
|
-
const propIsNotType =
|
|
1208
|
+
const propIsNotType = useCallback5((props2) => props2.filter((p) => p.name !== "type"), []);
|
|
1135
1209
|
if (!fieldSchema) {
|
|
1136
1210
|
log2.warn("invalid format", {
|
|
1137
1211
|
props
|
|
@@ -1162,7 +1236,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1162
1236
|
};
|
|
1163
1237
|
|
|
1164
1238
|
// packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
|
|
1165
|
-
import React13, { useCallback as
|
|
1239
|
+
import React13, { useCallback as useCallback6, useMemo as useMemo6, useState as useState4 } from "react";
|
|
1166
1240
|
import { AST as AST4, Format, S as S2 } from "@dxos/echo-schema";
|
|
1167
1241
|
import { IconButton as IconButton4, useTranslation as useTranslation6 } from "@dxos/react-ui";
|
|
1168
1242
|
import { List as List2 } from "@dxos/react-ui-list";
|
|
@@ -1173,7 +1247,7 @@ var ViewMetaSchema = S2.Struct({
|
|
|
1173
1247
|
name: S2.String.annotations({
|
|
1174
1248
|
[AST4.TitleAnnotationId]: "View"
|
|
1175
1249
|
}),
|
|
1176
|
-
typename: Format.
|
|
1250
|
+
typename: Format.URL.annotations({
|
|
1177
1251
|
[AST4.TitleAnnotationId]: "Typename"
|
|
1178
1252
|
})
|
|
1179
1253
|
}).pipe(S2.mutable);
|
|
@@ -1194,7 +1268,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1194
1268
|
}, [
|
|
1195
1269
|
view
|
|
1196
1270
|
]);
|
|
1197
|
-
const handleViewUpdate =
|
|
1271
|
+
const handleViewUpdate = useCallback6(({ name, typename }) => {
|
|
1198
1272
|
requestAnimationFrame(() => {
|
|
1199
1273
|
if (view.name !== name) {
|
|
1200
1274
|
view.name = name;
|
|
@@ -1208,16 +1282,16 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1208
1282
|
schema,
|
|
1209
1283
|
onTypenameChanged
|
|
1210
1284
|
]);
|
|
1211
|
-
const handleSelect =
|
|
1285
|
+
const handleSelect = useCallback6((field2) => {
|
|
1212
1286
|
setField((f) => f === field2 ? void 0 : field2);
|
|
1213
1287
|
}, []);
|
|
1214
|
-
const handleAdd =
|
|
1288
|
+
const handleAdd = useCallback6(() => {
|
|
1215
1289
|
const field2 = projection.createFieldProjection();
|
|
1216
1290
|
setField(field2);
|
|
1217
1291
|
}, [
|
|
1218
1292
|
view
|
|
1219
1293
|
]);
|
|
1220
|
-
const handleMove =
|
|
1294
|
+
const handleMove = useCallback6((fromIndex, toIndex) => {
|
|
1221
1295
|
const fields = [
|
|
1222
1296
|
...view.fields
|
|
1223
1297
|
];
|
|
@@ -1227,12 +1301,11 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1227
1301
|
}, [
|
|
1228
1302
|
view.fields
|
|
1229
1303
|
]);
|
|
1230
|
-
const handleClose =
|
|
1304
|
+
const handleClose = useCallback6(() => setField(void 0), []);
|
|
1231
1305
|
return /* @__PURE__ */ React13.createElement("div", {
|
|
1232
1306
|
role: "none",
|
|
1233
1307
|
className: mx8("flex flex-col w-full divide-y divide-separator", classNames)
|
|
1234
1308
|
}, /* @__PURE__ */ React13.createElement(Form, {
|
|
1235
|
-
autoFocus: true,
|
|
1236
1309
|
autoSave: true,
|
|
1237
1310
|
schema: ViewMetaSchema,
|
|
1238
1311
|
values: viewValues,
|
|
@@ -1509,6 +1582,7 @@ export {
|
|
|
1509
1582
|
Form,
|
|
1510
1583
|
GeoPointInput,
|
|
1511
1584
|
InputHeader,
|
|
1585
|
+
MarkdownInput,
|
|
1512
1586
|
NumberInput,
|
|
1513
1587
|
SelectInput,
|
|
1514
1588
|
SelectOptionInput,
|
|
@@ -1522,6 +1596,7 @@ export {
|
|
|
1522
1596
|
parseValue,
|
|
1523
1597
|
pathNotUniqueError,
|
|
1524
1598
|
translations_default as translations,
|
|
1525
|
-
useForm
|
|
1599
|
+
useForm,
|
|
1600
|
+
useFormValues
|
|
1526
1601
|
};
|
|
1527
1602
|
//# sourceMappingURL=index.mjs.map
|