@dxos/react-ui-form 0.8.4-main.c85a9c8dae → 0.8.4-main.d05539e30a
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/LICENSE +102 -5
- package/dist/lib/browser/index.mjs +1028 -625
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/translations.mjs +82 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1028 -625
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/translations.mjs +84 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +63 -61
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +40 -12
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +76 -74
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormField.d.ts +11 -5
- package/dist/types/src/components/Form/FormField.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormFieldComponent.d.ts +8 -7
- package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormFieldSet.d.ts +5 -9
- package/dist/types/src/components/Form/FormFieldSet.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/ArrayField.d.ts +4 -4
- package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts +8 -1
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts +84 -0
- package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/fields/NumberField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/RefField.d.ts +15 -7
- package/dist/types/src/components/Form/fields/RefField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/SelectField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts +63 -61
- package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/TextField.d.ts +1 -1
- package/dist/types/src/components/Form/fields/TextField.d.ts.map +1 -1
- package/dist/types/src/components/Form/fields/TupleField.d.ts.map +1 -1
- package/dist/types/src/components/ObjectForm/ObjectForm.d.ts +9 -0
- package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -0
- package/dist/types/src/components/ObjectForm/index.d.ts +2 -0
- package/dist/types/src/components/ObjectForm/index.d.ts.map +1 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +26 -4
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +63 -61
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -1
- package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +9 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts +127 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts.map +1 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts +2 -0
- package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts.map +1 -0
- package/dist/types/src/components/ObjectProperties/index.d.ts +2 -0
- package/dist/types/src/components/ObjectProperties/index.d.ts.map +1 -0
- package/dist/types/src/components/Settings/Settings.d.ts +28 -33
- package/dist/types/src/components/Settings/Settings.d.ts.map +1 -1
- package/dist/types/src/components/Settings/Settings.stories.d.ts +64 -61
- package/dist/types/src/components/Settings/Settings.stories.d.ts.map +1 -1
- package/dist/types/src/components/Settings/SettingsFieldSet.d.ts +43 -0
- package/dist/types/src/components/Settings/SettingsFieldSet.d.ts.map +1 -0
- package/dist/types/src/components/Settings/SettingsItem.d.ts +16 -0
- package/dist/types/src/components/Settings/SettingsItem.d.ts.map +1 -0
- package/dist/types/src/components/Settings/SettingsSelectField.d.ts +18 -0
- package/dist/types/src/components/Settings/SettingsSelectField.d.ts.map +1 -0
- package/dist/types/src/components/Settings/index.d.ts +2 -0
- package/dist/types/src/components/Settings/index.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +3 -4
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +65 -63
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +4 -4
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useKeyHandler.d.ts +2 -1
- package/dist/types/src/hooks/useKeyHandler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +63 -61
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/field-type.d.ts +19 -0
- package/dist/types/src/util/field-type.d.ts.map +1 -0
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/properties.d.ts +7 -1
- package/dist/types/src/util/properties.d.ts.map +1 -1
- package/dist/types/src/util/properties.test.d.ts +2 -0
- package/dist/types/src/util/properties.test.d.ts.map +1 -0
- package/dist/types/src/util/refs.d.ts +1 -0
- package/dist/types/src/util/refs.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +43 -41
- package/src/components/FieldEditor/FieldEditor.stories.tsx +2 -2
- package/src/components/FieldEditor/FieldEditor.test.tsx +0 -1
- package/src/components/FieldEditor/FieldEditor.tsx +4 -3
- package/src/components/Form/AUDIT.md +17 -0
- package/src/components/Form/Form.stories.tsx +25 -38
- package/src/components/Form/Form.tsx +77 -48
- package/src/components/Form/FormField.tsx +27 -15
- package/src/components/Form/FormFieldComponent.tsx +6 -4
- package/src/components/Form/FormFieldSet.tsx +98 -77
- package/src/components/Form/fields/ArrayField.tsx +14 -8
- package/src/components/Form/fields/GeoPointField.tsx +8 -7
- package/src/components/Form/fields/MarkdownField.stories.tsx +206 -0
- package/src/components/Form/fields/MarkdownField.tsx +135 -45
- package/src/components/Form/fields/RefField.tsx +79 -39
- package/src/components/Form/fields/SelectOptionField.stories.tsx +8 -6
- package/src/components/Form/fields/SelectOptionField.tsx +12 -12
- package/src/components/Form/fields/TextField.tsx +2 -2
- package/src/components/Form/fields/TupleField.tsx +1 -1
- package/src/components/ObjectForm/ObjectForm.tsx +114 -0
- package/src/components/ObjectForm/index.ts +5 -0
- package/src/components/ObjectPicker/ObjectPicker.stories.tsx +12 -10
- package/src/components/ObjectPicker/ObjectPicker.tsx +92 -65
- package/src/components/ObjectProperties/ObjectProperties.stories.tsx +362 -0
- package/src/components/ObjectProperties/ObjectProperties.test.tsx +101 -0
- package/src/components/ObjectProperties/ObjectProperties.tsx +148 -0
- package/src/components/ObjectProperties/index.ts +5 -0
- package/src/components/Settings/AUDIT.md +51 -0
- package/src/components/Settings/Settings.stories.tsx +69 -21
- package/src/components/Settings/Settings.tsx +33 -183
- package/src/components/Settings/SettingsFieldSet.tsx +257 -0
- package/src/components/Settings/SettingsItem.tsx +58 -0
- package/src/components/Settings/SettingsSelectField.tsx +59 -0
- package/src/components/Settings/index.ts +2 -0
- package/src/components/ViewEditor/ViewEditor.stories.tsx +14 -15
- package/src/components/ViewEditor/ViewEditor.test.tsx +0 -1
- package/src/components/ViewEditor/ViewEditor.tsx +40 -36
- package/src/components/index.ts +2 -0
- package/src/components/testing.tsx +19 -11
- package/src/hooks/useKeyHandler.tsx +7 -7
- package/src/index.ts +0 -4
- package/src/translations.ts +66 -63
- package/src/util/field-type.ts +60 -0
- package/src/util/index.ts +1 -0
- package/src/util/properties.test.ts +63 -0
- package/src/util/properties.ts +14 -3
- package/src/util/refs.ts +7 -3
|
@@ -1,87 +1,11 @@
|
|
|
1
|
-
// src/translations.ts
|
|
2
|
-
var translationKey = "@dxos/react-ui-form";
|
|
3
|
-
var translations = [
|
|
4
|
-
{
|
|
5
|
-
"en-US": {
|
|
6
|
-
[translationKey]: {
|
|
7
|
-
"fields label": "Fields",
|
|
8
|
-
"hidden fields label": "Hidden Fields",
|
|
9
|
-
"empty readonly ref field label": "(none)",
|
|
10
|
-
// TODO(burdon): Standardize field/property.
|
|
11
|
-
"add property button label": "Add property",
|
|
12
|
-
"field property label": "Property",
|
|
13
|
-
"field property placeholder": "Property name",
|
|
14
|
-
"field format label": "Type",
|
|
15
|
-
"field path label": "Field path",
|
|
16
|
-
"add field": "Add field",
|
|
17
|
-
"delete field": "Delete field",
|
|
18
|
-
"field limit reached": "Maximum number of fields reached",
|
|
19
|
-
"boolean input true value": "Yes",
|
|
20
|
-
"boolean input false value": "No",
|
|
21
|
-
"show field label": "Show field",
|
|
22
|
-
"hide field label": "Hide field",
|
|
23
|
-
"delete field label": "Delete field",
|
|
24
|
-
"ref field combobox input placeholder": "Search\u2026",
|
|
25
|
-
"ref field placeholder_one": "Select\u2026",
|
|
26
|
-
"ref field placeholder_other": "Select items\u2026",
|
|
27
|
-
"example placeholder": "Example",
|
|
28
|
-
"latitude placeholder": "Latitude (e.g., 40.7128)",
|
|
29
|
-
"longitude placeholder": "Longitude (e.g., -74.0060)",
|
|
30
|
-
"cancel button label": "Cancel",
|
|
31
|
-
"save button label": "Save",
|
|
32
|
-
// FormatEnum
|
|
33
|
-
"format boolean": "Boolean",
|
|
34
|
-
"format currency": "Currency",
|
|
35
|
-
"format date": "Date",
|
|
36
|
-
"format date-time": "DateTime",
|
|
37
|
-
"format did": "DID",
|
|
38
|
-
"format duration": "Duration",
|
|
39
|
-
"format dxn": "DXN",
|
|
40
|
-
"format email": "Email",
|
|
41
|
-
"format formula": "Formula",
|
|
42
|
-
"format hostname": "Hostname",
|
|
43
|
-
"format integer": "Integer",
|
|
44
|
-
"format json": "JSON",
|
|
45
|
-
"format lnglat": "Geopoint",
|
|
46
|
-
"format markdown": "Markdown",
|
|
47
|
-
"format percent": "Percent",
|
|
48
|
-
"format ref": "Reference",
|
|
49
|
-
"format regex": "RegExp",
|
|
50
|
-
"format string": "String",
|
|
51
|
-
"format single-select": "Select",
|
|
52
|
-
"format multi-select": "Multi-select",
|
|
53
|
-
"format text": "Long text",
|
|
54
|
-
"format time": "Time",
|
|
55
|
-
"format timestamp": "Timestamp",
|
|
56
|
-
"format user": "User",
|
|
57
|
-
"format number": "Number",
|
|
58
|
-
"format uri": "URI",
|
|
59
|
-
"format url": "URL",
|
|
60
|
-
"format uuid": "UUID",
|
|
61
|
-
// GeoPointField.
|
|
62
|
-
"latitude label": "Latitude",
|
|
63
|
-
"longitude label": "Longitude",
|
|
64
|
-
// SelectOptionsField.
|
|
65
|
-
"select option label": "Label",
|
|
66
|
-
"select option label placeholder": "Option label",
|
|
67
|
-
"select option color": "Color",
|
|
68
|
-
"select option delete": "Delete",
|
|
69
|
-
"select option add": "Add option",
|
|
70
|
-
// System schema message.
|
|
71
|
-
"system schema title": "System type",
|
|
72
|
-
"system schema description": "System type: cannot add or remove fields."
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
];
|
|
77
|
-
|
|
78
1
|
// src/components/FieldEditor/FieldEditor.tsx
|
|
79
|
-
import React17, { useCallback as useCallback14, useEffect as
|
|
80
|
-
import { Obj as
|
|
2
|
+
import React17, { useCallback as useCallback14, useEffect as useEffect5, useMemo as useMemo8, useState as useState6 } from "react";
|
|
3
|
+
import { Obj as Obj3 } from "@dxos/echo";
|
|
81
4
|
import { Format as Format4, FormatEnums, formatToType } from "@dxos/echo/internal";
|
|
82
5
|
import { log as log2 } from "@dxos/log";
|
|
83
|
-
import { useAsyncEffect, useTranslation as
|
|
6
|
+
import { useAsyncEffect, useTranslation as useTranslation9 } from "@dxos/react-ui";
|
|
84
7
|
import { formatToAdditionalPropertyAttributes, getFormatSchema } from "@dxos/schema";
|
|
8
|
+
import { translationKey as translationKey9 } from "#translations";
|
|
85
9
|
|
|
86
10
|
// src/util/field.ts
|
|
87
11
|
import { Format, GeoLocation, TypeEnum } from "@dxos/echo/internal";
|
|
@@ -204,6 +128,46 @@ var pathNotUniqueError = (path) => ({
|
|
|
204
128
|
message: `'${path}' is already present`
|
|
205
129
|
});
|
|
206
130
|
|
|
131
|
+
// src/util/field-type.ts
|
|
132
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
133
|
+
import { getAnnotation, isLiteralUnion } from "@dxos/effect";
|
|
134
|
+
var detectFieldType = (ast) => {
|
|
135
|
+
if (isLiteralUnion(ast)) {
|
|
136
|
+
return "select";
|
|
137
|
+
}
|
|
138
|
+
if (SchemaAST.isTypeLiteral(ast)) {
|
|
139
|
+
return "struct";
|
|
140
|
+
}
|
|
141
|
+
switch (ast._tag) {
|
|
142
|
+
case "BooleanKeyword":
|
|
143
|
+
return "boolean";
|
|
144
|
+
case "StringKeyword":
|
|
145
|
+
return "string";
|
|
146
|
+
case "NumberKeyword":
|
|
147
|
+
return "number";
|
|
148
|
+
}
|
|
149
|
+
return void 0;
|
|
150
|
+
};
|
|
151
|
+
var getSelectOptionsFromAst = (ast) => {
|
|
152
|
+
if (!isLiteralUnion(ast)) {
|
|
153
|
+
return void 0;
|
|
154
|
+
}
|
|
155
|
+
return ast.types.flatMap((literalNode) => {
|
|
156
|
+
const value3 = literalNode.literal;
|
|
157
|
+
if (typeof value3 !== "string" && typeof value3 !== "number") {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
const title = getAnnotation(SchemaAST.TitleAnnotationId, false)(literalNode);
|
|
161
|
+
const label = title ?? (typeof value3 === "string" ? value3.charAt(0).toUpperCase() + value3.slice(1) : String(value3));
|
|
162
|
+
return [
|
|
163
|
+
{
|
|
164
|
+
value: value3,
|
|
165
|
+
label
|
|
166
|
+
}
|
|
167
|
+
];
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
|
|
207
171
|
// src/util/formatting.ts
|
|
208
172
|
import { format as formatDate } from "date-fns/format";
|
|
209
173
|
import { Format as Format2, GeoLocation as GeoLocation2, TypeEnum as TypeEnum2 } from "@dxos/echo/internal";
|
|
@@ -344,51 +308,62 @@ var formatForEditing = ({ type, format, value: value3, locale = void 0 }) => {
|
|
|
344
308
|
|
|
345
309
|
// src/util/properties.ts
|
|
346
310
|
import * as Option from "effect/Option";
|
|
311
|
+
import * as SchemaAST2 from "effect/SchemaAST";
|
|
347
312
|
import { Annotation } from "@dxos/echo";
|
|
348
313
|
import { getProperties } from "@dxos/effect";
|
|
349
314
|
var getFormProperties = (ast) => {
|
|
350
|
-
|
|
315
|
+
const hidden = new Set(SchemaAST2.getPropertySignatures(ast).filter((prop) => Annotation.FormInputAnnotation.getFromAst(prop.type).pipe(Option.getOrElse(() => true)) === false).map((prop) => prop.name));
|
|
316
|
+
return getProperties(ast).filter((prop) => !hidden.has(prop.name));
|
|
351
317
|
};
|
|
352
318
|
|
|
353
319
|
// src/util/refs.ts
|
|
354
320
|
import { Ref } from "@dxos/echo";
|
|
355
|
-
import {
|
|
321
|
+
import { ReferenceAnnotationId } from "@dxos/echo/internal";
|
|
322
|
+
import { findAnnotation, getArrayElementType, isArrayType } from "@dxos/effect";
|
|
356
323
|
var getRefProps = (ast) => {
|
|
357
324
|
if (isArrayType(ast)) {
|
|
358
325
|
const elementType = getArrayElementType(ast);
|
|
359
326
|
if (elementType) {
|
|
360
327
|
if (Ref.isRefType(elementType)) {
|
|
328
|
+
const typename = findAnnotation(elementType, ReferenceAnnotationId)?.typename;
|
|
361
329
|
return {
|
|
362
330
|
ast: elementType,
|
|
363
|
-
isArray: true
|
|
331
|
+
isArray: true,
|
|
332
|
+
typename
|
|
364
333
|
};
|
|
365
334
|
}
|
|
366
335
|
}
|
|
367
336
|
}
|
|
368
337
|
if (Ref.isRefType(ast)) {
|
|
338
|
+
const typename = findAnnotation(ast, ReferenceAnnotationId)?.typename;
|
|
369
339
|
return {
|
|
370
340
|
ast,
|
|
371
|
-
isArray: false
|
|
341
|
+
isArray: false,
|
|
342
|
+
typename
|
|
372
343
|
};
|
|
373
344
|
}
|
|
374
345
|
return void 0;
|
|
375
346
|
};
|
|
376
347
|
|
|
377
348
|
// src/components/Form/fields/ArrayField.tsx
|
|
378
|
-
import * as
|
|
379
|
-
import * as
|
|
349
|
+
import * as Option4 from "effect/Option";
|
|
350
|
+
import * as SchemaAST5 from "effect/SchemaAST";
|
|
380
351
|
import React5, { useCallback as useCallback3 } from "react";
|
|
381
352
|
import { findNode as findNode2, getArrayElementType as getArrayElementType2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2, isNestedType as isNestedType2 } from "@dxos/effect";
|
|
382
353
|
import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
354
|
+
import { translationKey as translationKey3 } from "#translations";
|
|
383
355
|
|
|
384
356
|
// src/components/Form/Form.tsx
|
|
385
357
|
import { createContext } from "@radix-ui/react-context";
|
|
358
|
+
import * as Option3 from "effect/Option";
|
|
386
359
|
import * as Schema2 from "effect/Schema";
|
|
387
|
-
import * as
|
|
388
|
-
import React4, { useEffect as
|
|
360
|
+
import * as SchemaAST4 from "effect/SchemaAST";
|
|
361
|
+
import React4, { useEffect as useEffect2, useMemo as useMemo4, useRef } from "react";
|
|
362
|
+
import { Annotation as EchoAnnotation } from "@dxos/echo";
|
|
389
363
|
import { createJsonPath as createJsonPath3, getValue as getValue$2 } from "@dxos/effect";
|
|
390
|
-
import { IconButton, ScrollArea, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
391
|
-
import { mx
|
|
364
|
+
import { IconButton, ScrollArea, useMergeRefs, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
365
|
+
import { composable, composableProps, mx, withColumn } from "@dxos/ui-theme";
|
|
366
|
+
import { translationKey as translationKey2 } from "#translations";
|
|
392
367
|
|
|
393
368
|
// src/hooks/useFormHandler.ts
|
|
394
369
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
@@ -426,12 +401,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
|
|
|
426
401
|
log("validate", {
|
|
427
402
|
values: values2,
|
|
428
403
|
errors: errors2
|
|
429
|
-
}, {
|
|
430
|
-
F: __dxlog_file,
|
|
431
|
-
L: 155,
|
|
432
|
-
S: void 0,
|
|
433
|
-
C: (f, a) => f(...a)
|
|
434
|
-
});
|
|
404
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 42, S: void 0 });
|
|
435
405
|
if (errors2.length === 0 && onValidate) {
|
|
436
406
|
const validatedValues = values2;
|
|
437
407
|
errors2 = onValidate(validatedValues) ?? [];
|
|
@@ -519,12 +489,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
|
|
|
519
489
|
log("onValueChange", {
|
|
520
490
|
path,
|
|
521
491
|
value: value3
|
|
522
|
-
}, {
|
|
523
|
-
F: __dxlog_file,
|
|
524
|
-
L: 254,
|
|
525
|
-
S: void 0,
|
|
526
|
-
C: (f, a) => f(...a)
|
|
527
|
-
});
|
|
492
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 138, S: void 0 });
|
|
528
493
|
const jsonPath = createJsonPath(path);
|
|
529
494
|
const pathArray = path;
|
|
530
495
|
let parsedValue = value3;
|
|
@@ -533,12 +498,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
|
|
|
533
498
|
parsedValue = parseFloat(value3) || 0;
|
|
534
499
|
}
|
|
535
500
|
} catch (err) {
|
|
536
|
-
log.catch(err, void 0, {
|
|
537
|
-
F: __dxlog_file,
|
|
538
|
-
L: 264,
|
|
539
|
-
S: void 0,
|
|
540
|
-
C: (f, a) => f(...a)
|
|
541
|
-
});
|
|
501
|
+
log.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 150, S: void 0 });
|
|
542
502
|
parsedValue = void 0;
|
|
543
503
|
}
|
|
544
504
|
const newValues = mergeAtPath(values, pathArray, parsedValue);
|
|
@@ -647,9 +607,9 @@ var flatMap = (errors) => {
|
|
|
647
607
|
};
|
|
648
608
|
|
|
649
609
|
// src/hooks/useKeyHandler.tsx
|
|
650
|
-
import { useCallback as useCallback2,
|
|
610
|
+
import { useCallback as useCallback2, useLayoutEffect } from "react";
|
|
651
611
|
import { addEventListener } from "@dxos/async";
|
|
652
|
-
var useKeyHandler = (
|
|
612
|
+
var useKeyHandler = (elRef, form) => {
|
|
653
613
|
const handleKeyDown = useCallback2((event) => {
|
|
654
614
|
switch (event.key) {
|
|
655
615
|
case "Enter": {
|
|
@@ -665,13 +625,14 @@ var useKeyHandler = (formElement, form) => {
|
|
|
665
625
|
form.onSave,
|
|
666
626
|
form.autoSave
|
|
667
627
|
]);
|
|
668
|
-
|
|
669
|
-
|
|
628
|
+
useLayoutEffect(() => {
|
|
629
|
+
const el = elRef.current;
|
|
630
|
+
if (!el) {
|
|
670
631
|
return;
|
|
671
632
|
}
|
|
672
|
-
return addEventListener(
|
|
633
|
+
return addEventListener(el, "keydown", handleKeyDown);
|
|
673
634
|
}, [
|
|
674
|
-
|
|
635
|
+
elRef,
|
|
675
636
|
handleKeyDown
|
|
676
637
|
]);
|
|
677
638
|
};
|
|
@@ -683,7 +644,6 @@ import { inputTextLabel } from "@dxos/ui-theme";
|
|
|
683
644
|
var FormFieldLabel = ({ label, error, readonly, asChild }) => {
|
|
684
645
|
const Label = readonly || asChild ? "span" : Input.Label;
|
|
685
646
|
return /* @__PURE__ */ React.createElement("div", {
|
|
686
|
-
role: "none",
|
|
687
647
|
className: "flex items-center justify-between"
|
|
688
648
|
}, /* @__PURE__ */ React.createElement(Label, {
|
|
689
649
|
className: inputTextLabel
|
|
@@ -707,7 +667,6 @@ var FormFieldWrapper = (props) => {
|
|
|
707
667
|
}
|
|
708
668
|
const str = String(value3 ?? "");
|
|
709
669
|
return /* @__PURE__ */ React.createElement("div", {
|
|
710
|
-
role: "none",
|
|
711
670
|
className: "contents"
|
|
712
671
|
}, /* @__PURE__ */ React.createElement(Input.Root, {
|
|
713
672
|
validationValence: status
|
|
@@ -738,7 +697,7 @@ var FormFieldErrorBoundary = class extends Component {
|
|
|
738
697
|
return /* @__PURE__ */ React.createElement("div", {
|
|
739
698
|
className: "flex gap-2 border border-rose-fill font-mono text-sm"
|
|
740
699
|
}, /* @__PURE__ */ React.createElement("span", {
|
|
741
|
-
className: "bg-rose-fill text-
|
|
700
|
+
className: "bg-rose-fill text-base-foreground px-1 font-thin"
|
|
742
701
|
}, "ERROR"), String(this.props.path?.join(".")));
|
|
743
702
|
}
|
|
744
703
|
return this.props.children;
|
|
@@ -751,20 +710,19 @@ var FormFieldErrorBoundary = class extends Component {
|
|
|
751
710
|
};
|
|
752
711
|
|
|
753
712
|
// src/components/Form/FormFieldSet.tsx
|
|
754
|
-
import React3, {
|
|
755
|
-
import { mx } from "@dxos/ui-theme";
|
|
756
|
-
import { isTruthy } from "@dxos/util";
|
|
713
|
+
import React3, { useMemo as useMemo3 } from "react";
|
|
757
714
|
|
|
758
715
|
// src/components/Form/FormField.tsx
|
|
759
716
|
import * as Match from "effect/Match";
|
|
760
717
|
import * as Option2 from "effect/Option";
|
|
761
718
|
import * as Schema from "effect/Schema";
|
|
762
|
-
import * as
|
|
719
|
+
import * as SchemaAST3 from "effect/SchemaAST";
|
|
763
720
|
import * as String2 from "effect/String";
|
|
764
721
|
import React2, { useMemo as useMemo2 } from "react";
|
|
765
722
|
import { Format as Format3 } from "@dxos/echo";
|
|
766
|
-
import { createJsonPath as createJsonPath2, findNode, getAnnotation, getDiscriminatedType, isArrayType as isArrayType2, isDiscriminatedUnion, isLiteralUnion, isNestedType } from "@dxos/effect";
|
|
723
|
+
import { createJsonPath as createJsonPath2, findNode, getAnnotation as getAnnotation2, getDiscriminatedType, isArrayType as isArrayType2, isDiscriminatedUnion, isLiteralUnion as isLiteralUnion2, isNestedType } from "@dxos/effect";
|
|
767
724
|
import { useTranslation } from "@dxos/react-ui";
|
|
725
|
+
import { translationKey } from "#translations";
|
|
768
726
|
var FormField = (props) => {
|
|
769
727
|
const {
|
|
770
728
|
type,
|
|
@@ -776,23 +734,25 @@ var FormField = (props) => {
|
|
|
776
734
|
readonly,
|
|
777
735
|
layout,
|
|
778
736
|
// RefFieldProps
|
|
737
|
+
createTypename,
|
|
779
738
|
createOptionLabel,
|
|
780
739
|
createOptionIcon,
|
|
781
740
|
createInitialValuePath,
|
|
741
|
+
createFieldMap: createFieldMap3,
|
|
782
742
|
db,
|
|
783
|
-
schemaHook,
|
|
784
|
-
getOptions
|
|
743
|
+
useSchema: schemaHook,
|
|
744
|
+
getOptions,
|
|
785
745
|
onCreate
|
|
786
746
|
} = props;
|
|
787
747
|
const { t } = useTranslation(translationKey);
|
|
788
|
-
const title =
|
|
789
|
-
const description =
|
|
790
|
-
const examples =
|
|
748
|
+
const title = getAnnotation2(SchemaAST3.TitleAnnotationId)(type);
|
|
749
|
+
const description = getAnnotation2(SchemaAST3.DescriptionAnnotationId)(type);
|
|
750
|
+
const examples = getAnnotation2(SchemaAST3.ExamplesAnnotationId)(type);
|
|
791
751
|
const label = useMemo2(() => title ?? String2.capitalize(name), [
|
|
792
752
|
title,
|
|
793
753
|
name
|
|
794
754
|
]);
|
|
795
|
-
const placeholder = useMemo2(() => examples?.length ? `${t("example
|
|
755
|
+
const placeholder = useMemo2(() => examples?.length ? `${t("example.placeholder")}: ${examples[0]}` : description ?? label, [
|
|
796
756
|
examples,
|
|
797
757
|
description,
|
|
798
758
|
label
|
|
@@ -805,6 +765,7 @@ var FormField = (props) => {
|
|
|
805
765
|
label,
|
|
806
766
|
placeholder,
|
|
807
767
|
layout,
|
|
768
|
+
db,
|
|
808
769
|
...fieldState
|
|
809
770
|
};
|
|
810
771
|
const jsonPath = createJsonPath2(path ?? []);
|
|
@@ -831,7 +792,7 @@ var FormField = (props) => {
|
|
|
831
792
|
if (Field) {
|
|
832
793
|
return /* @__PURE__ */ React2.createElement(Field, fieldProps);
|
|
833
794
|
}
|
|
834
|
-
const options =
|
|
795
|
+
const options = getSelectOptions(type);
|
|
835
796
|
if (options) {
|
|
836
797
|
const fieldProjections = projection?.getFieldProjections();
|
|
837
798
|
const fieldProjection = fieldProjections?.find((fp) => fp.field.path === name);
|
|
@@ -849,21 +810,23 @@ var FormField = (props) => {
|
|
|
849
810
|
}
|
|
850
811
|
const refProps = getRefProps(type);
|
|
851
812
|
if (refProps) {
|
|
813
|
+
const isCreateTarget = !createTypename || refProps.typename === createTypename;
|
|
852
814
|
return /* @__PURE__ */ React2.createElement(RefField, {
|
|
853
815
|
...fieldProps,
|
|
854
816
|
...refProps,
|
|
855
|
-
createOptionLabel,
|
|
856
|
-
createOptionIcon,
|
|
857
|
-
createInitialValuePath,
|
|
817
|
+
createOptionLabel: isCreateTarget ? createOptionLabel : void 0,
|
|
818
|
+
createOptionIcon: isCreateTarget ? createOptionIcon : void 0,
|
|
819
|
+
createInitialValuePath: isCreateTarget ? createInitialValuePath : void 0,
|
|
820
|
+
createFieldMap: isCreateTarget ? createFieldMap3 : void 0,
|
|
858
821
|
db,
|
|
859
|
-
schemaHook,
|
|
860
|
-
getOptions
|
|
822
|
+
useSchema: schemaHook,
|
|
823
|
+
getOptions,
|
|
861
824
|
onCreate
|
|
862
825
|
});
|
|
863
826
|
}
|
|
864
827
|
if (isNestedType(type)) {
|
|
865
828
|
const baseNode = findNode(type, isDiscriminatedUnion);
|
|
866
|
-
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, fieldState.getValue()) : findNode(type,
|
|
829
|
+
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, fieldState.getValue()) : findNode(type, SchemaAST3.isTypeLiteral);
|
|
867
830
|
if (typeLiteral) {
|
|
868
831
|
const schema = Schema.make(typeLiteral);
|
|
869
832
|
return /* @__PURE__ */ React2.createElement(FormFieldSet, {
|
|
@@ -879,8 +842,8 @@ var FormField = (props) => {
|
|
|
879
842
|
createOptionIcon,
|
|
880
843
|
createInitialValuePath,
|
|
881
844
|
db,
|
|
882
|
-
schemaHook,
|
|
883
|
-
getOptions
|
|
845
|
+
useSchema: schemaHook,
|
|
846
|
+
getOptions,
|
|
884
847
|
onCreate
|
|
885
848
|
});
|
|
886
849
|
}
|
|
@@ -904,8 +867,8 @@ var getFormField = ({ type, format }) => {
|
|
|
904
867
|
return BooleanField;
|
|
905
868
|
}
|
|
906
869
|
};
|
|
907
|
-
var
|
|
908
|
-
if (
|
|
870
|
+
var getSelectOptions = (ast) => {
|
|
871
|
+
if (isLiteralUnion2(ast)) {
|
|
909
872
|
return ast.types.map((type) => type.literal).filter((v) => v !== null);
|
|
910
873
|
}
|
|
911
874
|
return Format3.OptionsAnnotation.getFromAst(ast).pipe((annotation) => Option2.getOrUndefined(annotation));
|
|
@@ -913,47 +876,19 @@ var getOptions = (ast) => {
|
|
|
913
876
|
|
|
914
877
|
// src/components/Form/FormFieldSet.tsx
|
|
915
878
|
var FORM_FIELDSET_NAME = "Form.FieldSet";
|
|
916
|
-
var FormFieldSet =
|
|
879
|
+
var FormFieldSet = ({ label, schema, readonly, path, sort, exclude, projection, layout, ...props }) => {
|
|
917
880
|
const values = useFormValues(FORM_FIELDSET_NAME, path);
|
|
918
|
-
const properties =
|
|
919
|
-
if (!schema) {
|
|
920
|
-
return [];
|
|
921
|
-
}
|
|
922
|
-
const props2 = getFormProperties(schema.ast);
|
|
923
|
-
if (projection) {
|
|
924
|
-
const fieldProjections = projection.getFieldProjections();
|
|
925
|
-
const hiddenProperties = new Set(projection.getHiddenProperties());
|
|
926
|
-
const visibleProps = props2.filter((prop) => !hiddenProperties.has(prop.name.toString()));
|
|
927
|
-
const orderedProps = [];
|
|
928
|
-
for (const fieldProjection of fieldProjections) {
|
|
929
|
-
const fieldPath = String(fieldProjection.field.path);
|
|
930
|
-
const prop = visibleProps.find((p) => p.name === fieldPath);
|
|
931
|
-
if (prop) {
|
|
932
|
-
orderedProps.push(prop);
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
const projectionPaths = new Set(fieldProjections.map((projection2) => String(projection2.field.path)));
|
|
936
|
-
const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name.toString()));
|
|
937
|
-
orderedProps.push(...remainingProps);
|
|
938
|
-
return orderedProps;
|
|
939
|
-
}
|
|
940
|
-
const filtered = exclude ? exclude(props2) : props2;
|
|
941
|
-
return sort ? filtered.sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString())) : filtered;
|
|
942
|
-
}, [
|
|
881
|
+
const properties = useFormFieldSetProperties({
|
|
943
882
|
schema,
|
|
944
883
|
values,
|
|
945
884
|
exclude,
|
|
946
885
|
sort,
|
|
947
|
-
projection
|
|
948
|
-
|
|
886
|
+
projection
|
|
887
|
+
});
|
|
949
888
|
if ((readonly || layout === "static") && values == null) {
|
|
950
889
|
return null;
|
|
951
890
|
}
|
|
952
|
-
return /* @__PURE__ */ React3.createElement("
|
|
953
|
-
role: "form",
|
|
954
|
-
className: mx("w-full", layout === "inline" && "flex flex-col gap-2"),
|
|
955
|
-
ref: forwardRef4
|
|
956
|
-
}, layout !== "inline" && label && /* @__PURE__ */ React3.createElement(FormFieldLabel, {
|
|
891
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, layout !== "inline" && label && /* @__PURE__ */ React3.createElement(FormFieldLabel, {
|
|
957
892
|
label,
|
|
958
893
|
asChild: true
|
|
959
894
|
}), properties.map((property) => {
|
|
@@ -976,12 +911,52 @@ var FormFieldSet = /* @__PURE__ */ forwardRef(({ label, schema, readonly, path,
|
|
|
976
911
|
projection,
|
|
977
912
|
...props
|
|
978
913
|
}));
|
|
979
|
-
})
|
|
980
|
-
}
|
|
914
|
+
}));
|
|
915
|
+
};
|
|
981
916
|
FormFieldSet.displayName = FORM_FIELDSET_NAME;
|
|
917
|
+
var useFormFieldSetProperties = ({ schema, exclude, projection, values, sort }) => {
|
|
918
|
+
return useMemo3(() => {
|
|
919
|
+
if (!schema) {
|
|
920
|
+
return [];
|
|
921
|
+
}
|
|
922
|
+
const schemaProps = getFormProperties(schema.ast);
|
|
923
|
+
const filteredProps = exclude ? exclude(schemaProps) : schemaProps;
|
|
924
|
+
if (projection) {
|
|
925
|
+
const fieldProjections = projection.getFieldProjections();
|
|
926
|
+
const hiddenProperties = new Set(projection.getHiddenProperties());
|
|
927
|
+
const visibleProps = filteredProps.filter((prop) => !hiddenProperties.has(prop.name.toString()));
|
|
928
|
+
const orderedProps = [];
|
|
929
|
+
for (const fieldProjection of fieldProjections) {
|
|
930
|
+
const fieldPath = String(fieldProjection.field.path);
|
|
931
|
+
const prop = visibleProps.find((prop2) => prop2.name === fieldPath);
|
|
932
|
+
if (prop) {
|
|
933
|
+
orderedProps.push(prop);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
const projectionPaths = new Set(fieldProjections.map((projection2) => String(projection2.field.path)));
|
|
937
|
+
const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name.toString()));
|
|
938
|
+
orderedProps.push(...remainingProps);
|
|
939
|
+
return orderedProps;
|
|
940
|
+
}
|
|
941
|
+
return sort ? [
|
|
942
|
+
...filteredProps
|
|
943
|
+
].sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString())) : filteredProps;
|
|
944
|
+
}, [
|
|
945
|
+
schema,
|
|
946
|
+
values,
|
|
947
|
+
exclude,
|
|
948
|
+
sort,
|
|
949
|
+
projection
|
|
950
|
+
]);
|
|
951
|
+
};
|
|
982
952
|
|
|
983
953
|
// src/components/Form/Form.tsx
|
|
984
954
|
var omitId = (schema) => schema.pipe(Schema2.omit("id"));
|
|
955
|
+
var omitHiddenFormFields = (schema) => {
|
|
956
|
+
const properties = SchemaAST4.getPropertySignatures(schema.ast);
|
|
957
|
+
const hidden = properties.filter((prop) => Option3.getOrElse(EchoAnnotation.FormInputAnnotation.getFromAst(prop.type), () => true) === false).map((prop) => prop.name);
|
|
958
|
+
return hidden.length === 0 ? schema : schema.pipe(Schema2.omit(...hidden));
|
|
959
|
+
};
|
|
985
960
|
var [FormContextProvider, useFormContext] = createContext("Form");
|
|
986
961
|
var useFormValues = (componentName, path, defaultValue) => {
|
|
987
962
|
const stablePath = useMemo4(() => path ?? [], [
|
|
@@ -991,10 +966,10 @@ var useFormValues = (componentName, path, defaultValue) => {
|
|
|
991
966
|
const { form: { values, onValueChange } } = useFormContext(componentName);
|
|
992
967
|
const value3 = getValue$2(values, jsonPath);
|
|
993
968
|
const lastAppliedPathRef = useRef(null);
|
|
994
|
-
|
|
969
|
+
useEffect2(() => {
|
|
995
970
|
if (value3 == null && defaultValue && lastAppliedPathRef.current !== jsonPath) {
|
|
996
971
|
lastAppliedPathRef.current = jsonPath;
|
|
997
|
-
onValueChange(stablePath,
|
|
972
|
+
onValueChange(stablePath, SchemaAST4.stringKeyword, defaultValue());
|
|
998
973
|
}
|
|
999
974
|
}, [
|
|
1000
975
|
value3,
|
|
@@ -1038,29 +1013,35 @@ var FormRoot = ({ children, schema, values, onSave, onCancel, ...props }) => {
|
|
|
1038
1013
|
};
|
|
1039
1014
|
FormRoot.displayName = "Form.Root";
|
|
1040
1015
|
var FORM_VIEWPORT_NAME = "Form.Viewport";
|
|
1041
|
-
var FormViewport = ({ children,
|
|
1016
|
+
var FormViewport = composable(({ children, ...props }, forwardedRef) => {
|
|
1042
1017
|
return /* @__PURE__ */ React4.createElement(ScrollArea.Root, {
|
|
1018
|
+
...composableProps(props),
|
|
1043
1019
|
orientation: "vertical",
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
...props
|
|
1020
|
+
centered: true,
|
|
1021
|
+
padding: true,
|
|
1022
|
+
thin: true,
|
|
1023
|
+
ref: forwardedRef
|
|
1049
1024
|
}, /* @__PURE__ */ React4.createElement(ScrollArea.Viewport, null, children));
|
|
1050
|
-
};
|
|
1025
|
+
});
|
|
1051
1026
|
FormViewport.displayName = FORM_VIEWPORT_NAME;
|
|
1052
1027
|
var FORM_CONTENT_NAME = "Form.Content";
|
|
1053
|
-
var FormContent = ({
|
|
1028
|
+
var FormContent = composable(({ children, ...props }, forwardedRef) => {
|
|
1054
1029
|
const { form, testId } = useFormContext(FORM_CONTENT_NAME);
|
|
1055
|
-
const
|
|
1056
|
-
|
|
1030
|
+
const localRef = useRef(null);
|
|
1031
|
+
const mergedRef = useMergeRefs([
|
|
1032
|
+
forwardedRef,
|
|
1033
|
+
localRef
|
|
1034
|
+
]);
|
|
1035
|
+
useKeyHandler(localRef, form);
|
|
1057
1036
|
return /* @__PURE__ */ React4.createElement("div", {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1037
|
+
...composableProps(props, {
|
|
1038
|
+
role: "form",
|
|
1039
|
+
classNames: mx(withColumn.center(), "flex flex-col w-full pb-form-gap")
|
|
1040
|
+
}),
|
|
1041
|
+
"data-testid": testId,
|
|
1042
|
+
ref: mergedRef
|
|
1062
1043
|
}, children);
|
|
1063
|
-
};
|
|
1044
|
+
});
|
|
1064
1045
|
FormContent.displayName = FORM_CONTENT_NAME;
|
|
1065
1046
|
var FORM_FIELDSET_NAME2 = "Form.FieldSet";
|
|
1066
1047
|
var FormFieldSet2 = (props) => {
|
|
@@ -1074,18 +1055,17 @@ var FormFieldSet2 = (props) => {
|
|
|
1074
1055
|
FormFieldSet2.displayName = FORM_FIELDSET_NAME2;
|
|
1075
1056
|
var FORM_ACTIONS_NAME = "Form.Actions";
|
|
1076
1057
|
var FormActions = ({ classNames }) => {
|
|
1077
|
-
const { t } = useTranslation2(
|
|
1058
|
+
const { t } = useTranslation2(translationKey2);
|
|
1078
1059
|
const { form: { canSave, onSave, onCancel }, readonly, layout } = useFormContext(FORM_ACTIONS_NAME);
|
|
1079
1060
|
if (readonly || layout === "static") {
|
|
1080
1061
|
return null;
|
|
1081
1062
|
}
|
|
1082
1063
|
return /* @__PURE__ */ React4.createElement("div", {
|
|
1083
|
-
|
|
1084
|
-
className: mx2("grid grid-flow-col gap-2 auto-cols-fr py-form-padding", classNames)
|
|
1064
|
+
className: mx(withColumn.center(), "grid grid-flow-col gap-form-gap auto-cols-fr py-form-padding", classNames)
|
|
1085
1065
|
}, onCancel && /* @__PURE__ */ React4.createElement(IconButton, {
|
|
1086
1066
|
icon: "ph--x--regular",
|
|
1087
1067
|
iconEnd: true,
|
|
1088
|
-
label: t("cancel
|
|
1068
|
+
label: t("cancel-button.label"),
|
|
1089
1069
|
onClick: onCancel,
|
|
1090
1070
|
"data-testid": "cancel-button"
|
|
1091
1071
|
}), onSave && /* @__PURE__ */ React4.createElement(IconButton, {
|
|
@@ -1094,29 +1074,42 @@ var FormActions = ({ classNames }) => {
|
|
|
1094
1074
|
disabled: !canSave,
|
|
1095
1075
|
icon: "ph--check--regular",
|
|
1096
1076
|
iconEnd: true,
|
|
1097
|
-
label: t("save
|
|
1077
|
+
label: t("save-button.label"),
|
|
1098
1078
|
onClick: onSave,
|
|
1099
1079
|
"data-testid": "save-button"
|
|
1100
1080
|
}));
|
|
1101
1081
|
};
|
|
1102
1082
|
FormActions.displayName = FORM_ACTIONS_NAME;
|
|
1083
|
+
var FORM_SECTION_NAME = "Form.Section";
|
|
1084
|
+
var FormSection = composable(({ children, label, description, ...props }, forwardedRef) => {
|
|
1085
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
1086
|
+
...composableProps(props, {
|
|
1087
|
+
classNames: "flex flex-col pt-form-section-gap first:pt-0"
|
|
1088
|
+
}),
|
|
1089
|
+
ref: forwardedRef
|
|
1090
|
+
}, label && /* @__PURE__ */ React4.createElement("h2", {
|
|
1091
|
+
className: "text-lg"
|
|
1092
|
+
}, label), description && /* @__PURE__ */ React4.createElement("p", {
|
|
1093
|
+
className: "text-description"
|
|
1094
|
+
}, description), children);
|
|
1095
|
+
});
|
|
1096
|
+
FormSection.displayName = FORM_SECTION_NAME;
|
|
1103
1097
|
var FORM_SUBMIT_NAME = "Form.Submit";
|
|
1104
1098
|
var FormSubmit = ({ classNames, label, icon, disabled }) => {
|
|
1105
|
-
const { t } = useTranslation2(
|
|
1099
|
+
const { t } = useTranslation2(translationKey2);
|
|
1106
1100
|
const { form: { canSave, onSave }, readonly, layout } = useFormContext(FORM_SUBMIT_NAME);
|
|
1107
1101
|
if (readonly || layout === "static") {
|
|
1108
1102
|
return null;
|
|
1109
1103
|
}
|
|
1110
1104
|
return /* @__PURE__ */ React4.createElement("div", {
|
|
1111
|
-
|
|
1112
|
-
className: mx2("flex w-full pt-form-padding", classNames)
|
|
1105
|
+
className: mx("flex w-full pt-form-padding", classNames)
|
|
1113
1106
|
}, /* @__PURE__ */ React4.createElement(IconButton, {
|
|
1114
1107
|
classNames: "w-full",
|
|
1115
1108
|
type: "submit",
|
|
1116
1109
|
variant: "primary",
|
|
1117
1110
|
disabled: disabled ?? !canSave,
|
|
1118
1111
|
icon: icon ?? "ph--check--regular",
|
|
1119
|
-
label: label ?? t("save
|
|
1112
|
+
label: label ?? t("save-button.label"),
|
|
1120
1113
|
onClick: onSave,
|
|
1121
1114
|
"data-testid": "save-button"
|
|
1122
1115
|
}));
|
|
@@ -1126,6 +1119,7 @@ var Form = {
|
|
|
1126
1119
|
Root: FormRoot,
|
|
1127
1120
|
Viewport: FormViewport,
|
|
1128
1121
|
Content: FormContent,
|
|
1122
|
+
Section: FormSection,
|
|
1129
1123
|
FieldSet: FormFieldSet2,
|
|
1130
1124
|
Label: FormFieldLabel,
|
|
1131
1125
|
Actions: FormActions,
|
|
@@ -1134,18 +1128,18 @@ var Form = {
|
|
|
1134
1128
|
|
|
1135
1129
|
// src/components/Form/fields/ArrayField.tsx
|
|
1136
1130
|
var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps, ...props }) => {
|
|
1137
|
-
const { t } = useTranslation3(
|
|
1131
|
+
const { t } = useTranslation3(translationKey3);
|
|
1138
1132
|
const elementType = getArrayElementType2(type);
|
|
1139
1133
|
const { onValueChange } = inputProps;
|
|
1140
1134
|
const values = useFormValues(ArrayField.displayName, path, () => []);
|
|
1141
1135
|
const getDefaultObjectValue = (typeNode) => {
|
|
1142
1136
|
const baseNode = findNode2(typeNode, isDiscriminatedUnion2);
|
|
1143
|
-
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, {}) : findNode2(typeNode,
|
|
1137
|
+
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, {}) : findNode2(typeNode, SchemaAST5.isTypeLiteral);
|
|
1144
1138
|
if (!typeLiteral) {
|
|
1145
1139
|
return {};
|
|
1146
1140
|
}
|
|
1147
1141
|
return Object.fromEntries(getFormProperties(typeLiteral).map((prop) => {
|
|
1148
|
-
const defaultValue =
|
|
1142
|
+
const defaultValue = SchemaAST5.getDefaultAnnotation(prop.type).pipe((annotation) => Option4.getOrUndefined(annotation));
|
|
1149
1143
|
return [
|
|
1150
1144
|
prop.name,
|
|
1151
1145
|
defaultValue
|
|
@@ -1179,13 +1173,11 @@ var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps,
|
|
|
1179
1173
|
label,
|
|
1180
1174
|
asChild: true
|
|
1181
1175
|
}), /* @__PURE__ */ React5.createElement("div", {
|
|
1182
|
-
|
|
1183
|
-
className: "flex flex-col gap-2"
|
|
1176
|
+
className: "flex flex-col gap-form-gap"
|
|
1184
1177
|
}, values?.map((_, index) => {
|
|
1185
1178
|
return /* @__PURE__ */ React5.createElement("div", {
|
|
1186
|
-
role: "none",
|
|
1187
1179
|
key: index,
|
|
1188
|
-
className: "grid grid-cols-[1fr_min-content] gap-
|
|
1180
|
+
className: "grid grid-cols-[1fr_min-content] gap-form-gap last:mb-form-gap items-center"
|
|
1189
1181
|
}, /* @__PURE__ */ React5.createElement(FormField, {
|
|
1190
1182
|
autoFocus: index === values.length - 1,
|
|
1191
1183
|
type: elementType,
|
|
@@ -1197,22 +1189,20 @@ var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps,
|
|
|
1197
1189
|
layout: "inline",
|
|
1198
1190
|
...props
|
|
1199
1191
|
}), !readonly && layout !== "static" && /* @__PURE__ */ React5.createElement("div", {
|
|
1200
|
-
role: "none",
|
|
1201
1192
|
className: "flex flex-col h-full justify-end"
|
|
1202
1193
|
}, /* @__PURE__ */ React5.createElement("div", {
|
|
1203
|
-
role: "none",
|
|
1204
1194
|
className: "flex items-center h-[2rem]"
|
|
1205
1195
|
}, /* @__PURE__ */ React5.createElement(IconButton2, {
|
|
1206
1196
|
icon: "ph--x--regular",
|
|
1207
1197
|
iconOnly: true,
|
|
1208
|
-
label: t("button
|
|
1198
|
+
label: t("remove.button"),
|
|
1209
1199
|
onClick: () => handleDelete(index),
|
|
1210
1200
|
classNames: "self-center"
|
|
1211
1201
|
}))));
|
|
1212
1202
|
})), !readonly && layout !== "static" && /* @__PURE__ */ React5.createElement(IconButton2, {
|
|
1213
1203
|
classNames: "flex w-full",
|
|
1214
1204
|
icon: "ph--plus--regular",
|
|
1215
|
-
label: t("add
|
|
1205
|
+
label: t("add-item.button"),
|
|
1216
1206
|
onClick: handleAdd
|
|
1217
1207
|
}));
|
|
1218
1208
|
};
|
|
@@ -1260,12 +1250,13 @@ var BooleanField = ({ type, readonly, onValueChange, ...props }) => {
|
|
|
1260
1250
|
};
|
|
1261
1251
|
|
|
1262
1252
|
// src/components/Form/fields/GeoPointField.tsx
|
|
1263
|
-
import React7, { useCallback as useCallback5, useEffect as
|
|
1253
|
+
import React7, { useCallback as useCallback5, useEffect as useEffect3, useMemo as useMemo5, useState as useState2 } from "react";
|
|
1264
1254
|
import { GeoLocation as GeoLocation3 } from "@dxos/echo/internal";
|
|
1265
1255
|
import { Input as Input3, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
1266
1256
|
import { safeParseFloat } from "@dxos/util";
|
|
1257
|
+
import { translationKey as translationKey4 } from "#translations";
|
|
1267
1258
|
var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onValueChange, onBlur }) => {
|
|
1268
|
-
const { t } = useTranslation4(
|
|
1259
|
+
const { t } = useTranslation4(translationKey4);
|
|
1269
1260
|
const { status, error } = getStatus();
|
|
1270
1261
|
const geoPoint = useMemo5(() => getValue() ?? [
|
|
1271
1262
|
0,
|
|
@@ -1278,7 +1269,7 @@ var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onVal
|
|
|
1278
1269
|
]);
|
|
1279
1270
|
const [longitudeText, setLongitudeText] = useState2(value3.longitude?.toString());
|
|
1280
1271
|
const [latitudeText, setLatitudeText] = useState2(value3.latitude?.toString());
|
|
1281
|
-
|
|
1272
|
+
useEffect3(() => {
|
|
1282
1273
|
const location = GeoLocation3.fromGeoPoint(geoPoint);
|
|
1283
1274
|
setLongitudeText(location.longitude?.toString());
|
|
1284
1275
|
setLatitudeText(location.latitude?.toString());
|
|
@@ -1319,25 +1310,24 @@ var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onVal
|
|
|
1319
1310
|
label,
|
|
1320
1311
|
asChild: true
|
|
1321
1312
|
}), layout === "static" ? /* @__PURE__ */ React7.createElement(LatLng, value3) : /* @__PURE__ */ React7.createElement("div", {
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
}, /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("latitude label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
|
|
1313
|
+
className: "grid grid-cols-2 gap-form-gap"
|
|
1314
|
+
}, /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("latitude.label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
|
|
1325
1315
|
type: "number",
|
|
1326
1316
|
step: "0.00001",
|
|
1327
1317
|
min: "-90",
|
|
1328
1318
|
max: "90",
|
|
1329
1319
|
disabled: !!readonly,
|
|
1330
|
-
placeholder: t("latitude
|
|
1320
|
+
placeholder: t("latitude.placeholder"),
|
|
1331
1321
|
value: latitudeText ?? "",
|
|
1332
1322
|
onChange: handleChange("latitude", setLatitudeText),
|
|
1333
1323
|
onBlur
|
|
1334
|
-
}))), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("longitude
|
|
1324
|
+
}))), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("longitude.label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
|
|
1335
1325
|
type: "number",
|
|
1336
1326
|
step: "0.00001",
|
|
1337
1327
|
min: "-180",
|
|
1338
1328
|
max: "180",
|
|
1339
1329
|
disabled: !!readonly,
|
|
1340
|
-
placeholder: t("longitude
|
|
1330
|
+
placeholder: t("longitude.placeholder"),
|
|
1341
1331
|
value: longitudeText ?? "",
|
|
1342
1332
|
onChange: handleChange("longitude", setLongitudeText),
|
|
1343
1333
|
onBlur
|
|
@@ -1347,7 +1337,7 @@ var LatLng = ({ latitude = 0, longitude = 0 }) => {
|
|
|
1347
1337
|
const latHem = latitude >= 0 ? "N" : "S";
|
|
1348
1338
|
const lngHem = longitude >= 0 ? "E" : "W";
|
|
1349
1339
|
return /* @__PURE__ */ React7.createElement("span", {
|
|
1350
|
-
className: "inline-flex items-center gap-
|
|
1340
|
+
className: "inline-flex items-center gap-form-gap"
|
|
1351
1341
|
}, /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement("span", null, Math.abs(latitude).toFixed(5)), /* @__PURE__ */ React7.createElement("span", {
|
|
1352
1342
|
className: "text-subdued"
|
|
1353
1343
|
}, "\xB0", latHem)), /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement("span", null, Math.abs(longitude).toFixed(5)), /* @__PURE__ */ React7.createElement("span", {
|
|
@@ -1356,56 +1346,141 @@ var LatLng = ({ latitude = 0, longitude = 0 }) => {
|
|
|
1356
1346
|
};
|
|
1357
1347
|
|
|
1358
1348
|
// src/components/Form/fields/MarkdownField.tsx
|
|
1359
|
-
import
|
|
1360
|
-
import {
|
|
1361
|
-
|
|
1349
|
+
import { useAtomValue } from "@effect-atom/atom-react";
|
|
1350
|
+
import React8, { useCallback as useCallback6, useMemo as useMemo6 } from "react";
|
|
1351
|
+
import { Obj, Ref as Ref2 } from "@dxos/echo";
|
|
1352
|
+
import { AtomRef } from "@dxos/echo-atom";
|
|
1353
|
+
import { createDocAccessor } from "@dxos/echo-db";
|
|
1354
|
+
import { Button, Icon as Icon2, Input as Input4, useTranslation as useTranslation5 } from "@dxos/react-ui";
|
|
1355
|
+
import { Editor, useBasicMarkdownExtensions } from "@dxos/react-ui-editor";
|
|
1356
|
+
import { Text } from "@dxos/schema";
|
|
1357
|
+
import { createDataExtensions } from "@dxos/ui-editor";
|
|
1358
|
+
import { translationKey as translationKey5 } from "#translations";
|
|
1359
|
+
var editorClassNames = "transition-colors bg-input-surface focus-within:bg-focus-surface border border-separator rounded-xs p-1 px-2";
|
|
1360
|
+
var MarkdownField = ({ type, readonly, label, placeholder, layout, db, getStatus, getValue, onValueChange }) => {
|
|
1362
1361
|
const { status, error } = getStatus();
|
|
1363
|
-
const
|
|
1364
|
-
const adjustHeight = useCallback6(() => {
|
|
1365
|
-
const textarea = textareaRef.current;
|
|
1366
|
-
if (textarea) {
|
|
1367
|
-
textarea.style.blockSize = "auto";
|
|
1368
|
-
textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
|
|
1369
|
-
}
|
|
1370
|
-
}, []);
|
|
1371
|
-
useEffect5(() => {
|
|
1372
|
-
adjustHeight();
|
|
1373
|
-
}, [
|
|
1374
|
-
adjustHeight
|
|
1375
|
-
]);
|
|
1376
|
-
useEffect5(() => {
|
|
1377
|
-
adjustHeight();
|
|
1378
|
-
}, [
|
|
1379
|
-
getValue(),
|
|
1380
|
-
adjustHeight
|
|
1381
|
-
]);
|
|
1382
|
-
const handleChange = useCallback6((event) => onValueChange(type, event.target.value), [
|
|
1383
|
-
type,
|
|
1384
|
-
onValueChange
|
|
1385
|
-
]);
|
|
1362
|
+
const isRef = Ref2.isRefType(type);
|
|
1386
1363
|
const value3 = getValue();
|
|
1387
|
-
if ((readonly || layout === "static") &&
|
|
1364
|
+
if ((readonly || layout === "static") && value3 == null) {
|
|
1388
1365
|
return null;
|
|
1389
1366
|
}
|
|
1367
|
+
const renderEditor = () => {
|
|
1368
|
+
if (isRef) {
|
|
1369
|
+
const reference = value3;
|
|
1370
|
+
if (reference) {
|
|
1371
|
+
return /* @__PURE__ */ React8.createElement(RefMarkdownEditor, {
|
|
1372
|
+
reference,
|
|
1373
|
+
placeholder
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
if (readonly) {
|
|
1377
|
+
return null;
|
|
1378
|
+
}
|
|
1379
|
+
return /* @__PURE__ */ React8.createElement(CreateTextButton, {
|
|
1380
|
+
db,
|
|
1381
|
+
disabled: !db,
|
|
1382
|
+
onCreate: (ref) => onValueChange(type, ref)
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
return /* @__PURE__ */ React8.createElement(StringMarkdownEditor, {
|
|
1386
|
+
value: value3 ?? "",
|
|
1387
|
+
placeholder,
|
|
1388
|
+
readonly: !!readonly,
|
|
1389
|
+
onChange: (next) => onValueChange(type, next)
|
|
1390
|
+
});
|
|
1391
|
+
};
|
|
1392
|
+
const renderStatic = () => {
|
|
1393
|
+
if (isRef) {
|
|
1394
|
+
const reference = value3;
|
|
1395
|
+
return reference ? /* @__PURE__ */ React8.createElement(RefStaticText, {
|
|
1396
|
+
reference
|
|
1397
|
+
}) : null;
|
|
1398
|
+
}
|
|
1399
|
+
return /* @__PURE__ */ React8.createElement("p", {
|
|
1400
|
+
className: "whitespace-pre-wrap"
|
|
1401
|
+
}, value3 ?? "");
|
|
1402
|
+
};
|
|
1390
1403
|
return /* @__PURE__ */ React8.createElement(Input4.Root, {
|
|
1391
1404
|
validationValence: status
|
|
1392
1405
|
}, layout !== "inline" && /* @__PURE__ */ React8.createElement(FormFieldLabel, {
|
|
1393
1406
|
error,
|
|
1394
1407
|
readonly,
|
|
1395
1408
|
label
|
|
1396
|
-
}), layout === "static" ?
|
|
1397
|
-
|
|
1398
|
-
|
|
1409
|
+
}), layout === "static" ? renderStatic() : renderEditor(), layout === "full" && /* @__PURE__ */ React8.createElement(Input4.Validation, null, error));
|
|
1410
|
+
};
|
|
1411
|
+
var RefStaticText = ({ reference }) => {
|
|
1412
|
+
const text = useAtomValue(useMemo6(() => AtomRef.make(reference), [
|
|
1413
|
+
reference
|
|
1414
|
+
]));
|
|
1415
|
+
if (!text?.content) {
|
|
1416
|
+
return null;
|
|
1417
|
+
}
|
|
1418
|
+
return /* @__PURE__ */ React8.createElement("p", {
|
|
1419
|
+
className: "whitespace-pre-wrap"
|
|
1420
|
+
}, text.content);
|
|
1421
|
+
};
|
|
1422
|
+
var RefMarkdownEditor = ({ reference, placeholder }) => {
|
|
1423
|
+
const text = useAtomValue(useMemo6(() => AtomRef.make(reference), [
|
|
1424
|
+
reference
|
|
1425
|
+
]));
|
|
1426
|
+
const dataExtensions = useMemo6(() => text ? [
|
|
1427
|
+
createDataExtensions({
|
|
1428
|
+
id: reference.dxn.toString(),
|
|
1429
|
+
text: createDocAccessor(text, [
|
|
1430
|
+
"content"
|
|
1431
|
+
])
|
|
1432
|
+
})
|
|
1433
|
+
] : [], [
|
|
1434
|
+
text,
|
|
1435
|
+
reference
|
|
1436
|
+
]);
|
|
1437
|
+
const extensions = useBasicMarkdownExtensions({
|
|
1399
1438
|
placeholder,
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
})
|
|
1439
|
+
extensions: dataExtensions
|
|
1440
|
+
});
|
|
1441
|
+
if (!text) {
|
|
1442
|
+
return null;
|
|
1443
|
+
}
|
|
1444
|
+
return /* @__PURE__ */ React8.createElement(Editor.Root, null, /* @__PURE__ */ React8.createElement(Editor.View, {
|
|
1445
|
+
classNames: editorClassNames,
|
|
1446
|
+
extensions
|
|
1447
|
+
}));
|
|
1448
|
+
};
|
|
1449
|
+
var StringMarkdownEditor = ({ value: value3, placeholder, readonly, onChange }) => {
|
|
1450
|
+
const extensions = useBasicMarkdownExtensions({
|
|
1451
|
+
placeholder
|
|
1452
|
+
});
|
|
1453
|
+
const handleChange = useCallback6((next) => onChange(next), [
|
|
1454
|
+
onChange
|
|
1455
|
+
]);
|
|
1456
|
+
return /* @__PURE__ */ React8.createElement(Editor.Root, null, /* @__PURE__ */ React8.createElement(Editor.View, {
|
|
1457
|
+
classNames: editorClassNames,
|
|
1458
|
+
extensions,
|
|
1459
|
+
value: value3,
|
|
1460
|
+
onChange: readonly ? void 0 : handleChange
|
|
1461
|
+
}));
|
|
1462
|
+
};
|
|
1463
|
+
var CreateTextButton = ({ db, disabled, onCreate }) => {
|
|
1464
|
+
const { t } = useTranslation5(translationKey5);
|
|
1465
|
+
const handleClick = useCallback6(() => {
|
|
1466
|
+
if (!db) {
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1469
|
+
const text = db.add(Obj.make(Text.Text, {
|
|
1470
|
+
content: ""
|
|
1471
|
+
}));
|
|
1472
|
+
onCreate(Ref2.make(text));
|
|
1473
|
+
}, [
|
|
1474
|
+
db,
|
|
1475
|
+
onCreate
|
|
1476
|
+
]);
|
|
1477
|
+
return /* @__PURE__ */ React8.createElement(Button, {
|
|
1478
|
+
onClick: handleClick,
|
|
1479
|
+
disabled
|
|
1480
|
+
}, /* @__PURE__ */ React8.createElement(Icon2, {
|
|
1481
|
+
icon: "ph--plus--regular",
|
|
1482
|
+
size: 4
|
|
1483
|
+
}), /* @__PURE__ */ React8.createElement("span", null, t("create-text.label")));
|
|
1409
1484
|
};
|
|
1410
1485
|
|
|
1411
1486
|
// src/components/Form/fields/NumberField.tsx
|
|
@@ -1431,47 +1506,33 @@ var NumberField = ({ type, readonly, placeholder, onValueChange, onBlur, ...prop
|
|
|
1431
1506
|
};
|
|
1432
1507
|
|
|
1433
1508
|
// src/components/Form/fields/RefField.tsx
|
|
1509
|
+
import React11, { useCallback as useCallback9, useMemo as useMemo7, useState as useState4 } from "react";
|
|
1434
1510
|
import "@dxos/lit-ui/dx-tag-picker.pcss";
|
|
1435
|
-
import
|
|
1436
|
-
import {
|
|
1437
|
-
import { ReferenceAnnotationId } from "@dxos/echo/internal";
|
|
1438
|
-
import {
|
|
1439
|
-
import { findAnnotation } from "@dxos/effect";
|
|
1511
|
+
import { Entity, Filter, Obj as Obj2, Ref as Ref3, Type } from "@dxos/echo";
|
|
1512
|
+
import { useQuery, useSchema as defaultUseSchema } from "@dxos/echo-react";
|
|
1513
|
+
import { ReferenceAnnotationId as ReferenceAnnotationId2 } from "@dxos/echo/internal";
|
|
1514
|
+
import { findAnnotation as findAnnotation2 } from "@dxos/effect";
|
|
1440
1515
|
import { DXN } from "@dxos/keys";
|
|
1441
1516
|
import { DxAnchor } from "@dxos/lit-ui/react";
|
|
1442
|
-
import { Button, Icon as
|
|
1443
|
-
import {
|
|
1517
|
+
import { Button as Button2, Icon as Icon3, Input as Input6, useTranslation as useTranslation7 } from "@dxos/react-ui";
|
|
1518
|
+
import { ParentLabelAnnotationId } from "@dxos/schema";
|
|
1519
|
+
import { translationKey as translationKey7 } from "#translations";
|
|
1444
1520
|
|
|
1445
1521
|
// src/components/ObjectPicker/ObjectPicker.tsx
|
|
1446
|
-
import React10, { forwardRef
|
|
1447
|
-
import { Popover, useTranslation as
|
|
1448
|
-
import { Combobox
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
value: "__create__",
|
|
1454
|
-
label: t(createOptionLabel[0], {
|
|
1455
|
-
ns: createOptionLabel[1].ns,
|
|
1456
|
-
text: query
|
|
1457
|
-
}),
|
|
1458
|
-
icon: createOptionIcon,
|
|
1459
|
-
classNames: "flex items-center gap-2",
|
|
1460
|
-
closeOnSelect: false,
|
|
1461
|
-
onSelect: () => {
|
|
1462
|
-
onCreateItemSelect(query);
|
|
1463
|
-
}
|
|
1464
|
-
});
|
|
1465
|
-
};
|
|
1466
|
-
var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, onSelect, onCreate, ...props }, ref) => {
|
|
1467
|
-
const { t } = useTranslation5(translationKey);
|
|
1522
|
+
import React10, { forwardRef, useCallback as useCallback8, useState as useState3 } from "react";
|
|
1523
|
+
import { Popover, useTranslation as useTranslation6 } from "@dxos/react-ui";
|
|
1524
|
+
import { Combobox } from "@dxos/react-ui-list";
|
|
1525
|
+
import { useSearchListResults } from "@dxos/react-ui-search";
|
|
1526
|
+
import { translationKey as translationKey6 } from "#translations";
|
|
1527
|
+
var ObjectPickerContent = /* @__PURE__ */ forwardRef(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, createFieldMap: createFieldMap3, onSelect, onCreate, ...props }, forwardedRef) => {
|
|
1528
|
+
const { t } = useTranslation6(translationKey6);
|
|
1468
1529
|
const [showForm, setShowForm] = useState3(false);
|
|
1469
1530
|
const [formInitialValue, setFormInitialValue] = useState3("");
|
|
1470
|
-
const { results, handleSearch } = useSearchListResults({
|
|
1531
|
+
const { results, query, handleSearch } = useSearchListResults({
|
|
1471
1532
|
items: options
|
|
1472
1533
|
});
|
|
1473
|
-
const handleFormSave = useCallback8((values) => {
|
|
1474
|
-
onCreate?.(values);
|
|
1534
|
+
const handleFormSave = useCallback8(async (values) => {
|
|
1535
|
+
await onCreate?.(values);
|
|
1475
1536
|
setShowForm(false);
|
|
1476
1537
|
setFormInitialValue("");
|
|
1477
1538
|
}, [
|
|
@@ -1493,22 +1554,31 @@ var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, c
|
|
|
1493
1554
|
}, [
|
|
1494
1555
|
createSchema
|
|
1495
1556
|
]);
|
|
1557
|
+
if (showForm && createSchema) {
|
|
1558
|
+
return /* @__PURE__ */ React10.createElement(Combobox.Content, {
|
|
1559
|
+
...props,
|
|
1560
|
+
onKeyDownCapture: handleKeyDown,
|
|
1561
|
+
ref: forwardedRef
|
|
1562
|
+
}, /* @__PURE__ */ React10.createElement(Popover.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Root, {
|
|
1563
|
+
testId: "create-referenced-object-form",
|
|
1564
|
+
schema: createSchema,
|
|
1565
|
+
defaultValues: createInitialValuePath ? {
|
|
1566
|
+
[createInitialValuePath]: formInitialValue
|
|
1567
|
+
} : {},
|
|
1568
|
+
fieldMap: createFieldMap3,
|
|
1569
|
+
onSave: handleFormSave,
|
|
1570
|
+
onCancel: handleFormCancel
|
|
1571
|
+
}, /* @__PURE__ */ React10.createElement(Form.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Content, null, /* @__PURE__ */ React10.createElement(Form.FieldSet, null), /* @__PURE__ */ React10.createElement(Form.Actions, null))))), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
|
|
1572
|
+
}
|
|
1496
1573
|
return /* @__PURE__ */ React10.createElement(Combobox.Content, {
|
|
1497
1574
|
...props,
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
[createInitialValuePath]: formInitialValue
|
|
1506
|
-
} : {},
|
|
1507
|
-
onSave: handleFormSave,
|
|
1508
|
-
onCancel: handleFormCancel
|
|
1509
|
-
}, /* @__PURE__ */ React10.createElement(Form.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Content, null, /* @__PURE__ */ React10.createElement(Form.FieldSet, null), /* @__PURE__ */ React10.createElement(Form.Actions, null))))) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Combobox.Input, {
|
|
1510
|
-
placeholder: t("ref field combobox input placeholder"),
|
|
1511
|
-
autoFocus: true
|
|
1575
|
+
onKeyDownCapture: handleKeyDown,
|
|
1576
|
+
ref: forwardedRef
|
|
1577
|
+
}, /* @__PURE__ */ React10.createElement(Combobox.Input, {
|
|
1578
|
+
placeholder: t("ref-field-combobox-input.placeholder"),
|
|
1579
|
+
autoFocus: true,
|
|
1580
|
+
value: query,
|
|
1581
|
+
onValueChange: handleSearch
|
|
1512
1582
|
}), /* @__PURE__ */ React10.createElement(Combobox.List, null, results.map((option) => /* @__PURE__ */ React10.createElement(Combobox.Item, {
|
|
1513
1583
|
key: option.id,
|
|
1514
1584
|
value: option.id,
|
|
@@ -1516,16 +1586,34 @@ var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, c
|
|
|
1516
1586
|
checked: selectedIds?.includes(option.id),
|
|
1517
1587
|
onSelect: () => onSelect(option.id),
|
|
1518
1588
|
classNames: "flex items-center gap-2"
|
|
1519
|
-
})),
|
|
1589
|
+
})), createSchema && onCreate && /* @__PURE__ */ React10.createElement(CreateItem, {
|
|
1590
|
+
query,
|
|
1520
1591
|
createOptionLabel,
|
|
1521
|
-
createOptionIcon,
|
|
1522
|
-
onCreateItemSelect: (
|
|
1523
|
-
setFormInitialValue(
|
|
1592
|
+
createOptionIcon: createOptionIcon ?? "ph--plus--regular",
|
|
1593
|
+
onCreateItemSelect: (currentQuery) => {
|
|
1594
|
+
setFormInitialValue(currentQuery);
|
|
1524
1595
|
setShowForm(true);
|
|
1525
1596
|
}
|
|
1526
|
-
}))
|
|
1597
|
+
})), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
|
|
1527
1598
|
});
|
|
1528
|
-
|
|
1599
|
+
var CreateItem = ({ query, createOptionLabel, createOptionIcon, onCreateItemSelect }) => {
|
|
1600
|
+
const { t } = useTranslation6(translationKey6);
|
|
1601
|
+
const label = createOptionLabel ? t(createOptionLabel[0], {
|
|
1602
|
+
ns: createOptionLabel[1].ns,
|
|
1603
|
+
text: query
|
|
1604
|
+
}) : t("create-option.label");
|
|
1605
|
+
return /* @__PURE__ */ React10.createElement(Combobox.Item, {
|
|
1606
|
+
value: "__create__",
|
|
1607
|
+
label,
|
|
1608
|
+
icon: createOptionIcon,
|
|
1609
|
+
classNames: "flex items-center gap-2",
|
|
1610
|
+
closeOnSelect: false,
|
|
1611
|
+
onSelect: () => {
|
|
1612
|
+
onCreateItemSelect(query);
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1615
|
+
};
|
|
1616
|
+
ObjectPickerContent.displayName = "ObjectPicker.Content";
|
|
1529
1617
|
var ObjectPicker = {
|
|
1530
1618
|
Root: Combobox.Root,
|
|
1531
1619
|
Portal: Combobox.Portal,
|
|
@@ -1538,34 +1626,43 @@ var ObjectPicker = {
|
|
|
1538
1626
|
var isRefSnapshot = (val) => {
|
|
1539
1627
|
return typeof val === "object" && typeof val?.["/"] === "string";
|
|
1540
1628
|
};
|
|
1541
|
-
var defaultGetOptions = (results) => results.map((result) => {
|
|
1629
|
+
var defaultGetOptions = (results, { parentLabel } = {}) => results.map((result) => {
|
|
1542
1630
|
const id = Entity.getDXN(result).toString();
|
|
1543
|
-
const
|
|
1631
|
+
const parent = parentLabel ? Obj2.getParent(result) : void 0;
|
|
1632
|
+
const label = parent ? Entity.getLabel(parent) : Entity.getLabel(result);
|
|
1544
1633
|
return {
|
|
1545
1634
|
id,
|
|
1546
1635
|
label: label ?? id
|
|
1547
1636
|
};
|
|
1548
1637
|
});
|
|
1549
|
-
var
|
|
1638
|
+
var defaultUseResults = (db, typename) => useQuery(db, typename ? typename === Type.getTypename(Obj2.Unknown) ? Filter.everything() : Filter.typename(typename) : Filter.nothing());
|
|
1550
1639
|
var RefField = (props) => {
|
|
1551
|
-
const { type, readonly, label, placeholder, layout, getStatus, getValue, createOptionLabel, createOptionIcon, createInitialValuePath, db,
|
|
1552
|
-
const { t } =
|
|
1640
|
+
const { type, readonly, label, placeholder, layout, getStatus, getValue, createOptionLabel, createOptionIcon, createInitialValuePath, createFieldMap: createFieldMap3, db, useSchema: useSchema2 = defaultUseSchema, useResults = defaultUseResults, getOptions = defaultGetOptions, onCreate, onValueChange } = props;
|
|
1641
|
+
const { t } = useTranslation7(translationKey7);
|
|
1553
1642
|
const { status, error } = getStatus();
|
|
1554
|
-
const typename =
|
|
1643
|
+
const typename = useMemo7(() => type ? findAnnotation2(type, ReferenceAnnotationId2)?.typename : void 0, [
|
|
1555
1644
|
type
|
|
1556
1645
|
]);
|
|
1557
1646
|
const results = useResults(db, typename);
|
|
1558
|
-
const options =
|
|
1647
|
+
const options = useMemo7(() => {
|
|
1648
|
+
const parentLabel = type ? findAnnotation2(type, ParentLabelAnnotationId) === true : false;
|
|
1649
|
+
return getOptions(results, {
|
|
1650
|
+
parentLabel
|
|
1651
|
+
});
|
|
1652
|
+
}, [
|
|
1559
1653
|
results,
|
|
1560
|
-
|
|
1654
|
+
getOptions,
|
|
1655
|
+
type
|
|
1561
1656
|
]);
|
|
1562
1657
|
const handleGetValue = useCallback9(() => {
|
|
1563
1658
|
const formValue = getValue();
|
|
1659
|
+
const dxnToObjectId = (dxn) => dxn.split(":").pop() ?? dxn;
|
|
1564
1660
|
const unknownToRefOption = (value3) => {
|
|
1565
|
-
const isRef =
|
|
1661
|
+
const isRef = Ref3.isRef(value3);
|
|
1566
1662
|
if (isRef || isRefSnapshot(value3)) {
|
|
1567
1663
|
const dxnString = isRef ? value3.dxn.toString() : value3["/"];
|
|
1568
|
-
const
|
|
1664
|
+
const objectId = dxnToObjectId(dxnString);
|
|
1665
|
+
const matchingOption = options.find((option) => dxnToObjectId(option.id) === objectId);
|
|
1569
1666
|
if (matchingOption) {
|
|
1570
1667
|
return matchingOption;
|
|
1571
1668
|
}
|
|
@@ -1577,29 +1674,37 @@ var RefField = (props) => {
|
|
|
1577
1674
|
options,
|
|
1578
1675
|
getValue
|
|
1579
1676
|
]);
|
|
1580
|
-
const handleUpdate = useCallback9((id) => {
|
|
1581
|
-
const item2 = options.find((option) => option.id === id);
|
|
1582
|
-
const ref = item2 ? Ref2.fromDXN(DXN.parse(item2.id)) : void 0;
|
|
1583
|
-
onValueChange(type, ref);
|
|
1584
|
-
}, [
|
|
1585
|
-
options,
|
|
1586
|
-
type,
|
|
1587
|
-
onValueChange
|
|
1588
|
-
]);
|
|
1589
1677
|
const item = handleGetValue();
|
|
1590
|
-
const selectedIds =
|
|
1678
|
+
const selectedIds = useMemo7(() => item ? [
|
|
1591
1679
|
item.id
|
|
1592
1680
|
] : [], [
|
|
1593
1681
|
item
|
|
1594
1682
|
]);
|
|
1595
|
-
const createSchema =
|
|
1596
|
-
const
|
|
1597
|
-
|
|
1598
|
-
|
|
1683
|
+
const createSchema = useSchema2(db, typename);
|
|
1684
|
+
const [open, setOpen] = useState4(false);
|
|
1685
|
+
const handleCreate = useCallback9(async (values) => {
|
|
1686
|
+
if (!createSchema || !onCreate) {
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1689
|
+
const newObject = await onCreate(createSchema, values);
|
|
1690
|
+
if (newObject) {
|
|
1691
|
+
onValueChange(type, Ref3.make(newObject));
|
|
1599
1692
|
}
|
|
1693
|
+
setOpen(false);
|
|
1600
1694
|
}, [
|
|
1601
1695
|
createSchema,
|
|
1602
|
-
onCreate
|
|
1696
|
+
onCreate,
|
|
1697
|
+
type,
|
|
1698
|
+
onValueChange
|
|
1699
|
+
]);
|
|
1700
|
+
const handleUpdate = useCallback9((id) => {
|
|
1701
|
+
const item2 = options.find((option) => option.id === id);
|
|
1702
|
+
const ref = item2 ? Ref3.fromDXN(DXN.parse(item2.id)) : void 0;
|
|
1703
|
+
onValueChange(type, ref);
|
|
1704
|
+
}, [
|
|
1705
|
+
options,
|
|
1706
|
+
type,
|
|
1707
|
+
onValueChange
|
|
1603
1708
|
]);
|
|
1604
1709
|
const handleSelect = useCallback9((id) => {
|
|
1605
1710
|
if (item?.id === id) {
|
|
@@ -1621,40 +1726,46 @@ var RefField = (props) => {
|
|
|
1621
1726
|
readonly,
|
|
1622
1727
|
label
|
|
1623
1728
|
}), /* @__PURE__ */ React11.createElement("div", null, readonly ? !item ? /* @__PURE__ */ React11.createElement("p", {
|
|
1624
|
-
className:
|
|
1625
|
-
}, t("empty
|
|
1729
|
+
className: "text-description mb-2"
|
|
1730
|
+
}, t("empty-readonly-ref-field.label")) : /* @__PURE__ */ React11.createElement(DxAnchor, {
|
|
1626
1731
|
key: item.id,
|
|
1627
1732
|
dxn: item.id,
|
|
1628
1733
|
rootclassname: "me-1"
|
|
1629
|
-
}, item.label) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root,
|
|
1734
|
+
}, item.label) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root, {
|
|
1735
|
+
open,
|
|
1736
|
+
onOpenChange: setOpen
|
|
1737
|
+
}, /* @__PURE__ */ React11.createElement(ObjectPicker.Trigger, {
|
|
1630
1738
|
asChild: true,
|
|
1631
1739
|
classNames: "p-0"
|
|
1632
1740
|
}, item ? /* @__PURE__ */ React11.createElement("div", {
|
|
1633
|
-
className: "flex gap-
|
|
1741
|
+
className: "flex gap-form-gap w-full"
|
|
1634
1742
|
}, /* @__PURE__ */ React11.createElement(Input6.Root, {
|
|
1635
1743
|
key: item.id
|
|
1636
1744
|
}, /* @__PURE__ */ React11.createElement(Input6.TextInput, {
|
|
1637
1745
|
value: item.label,
|
|
1638
1746
|
readOnly: true,
|
|
1639
1747
|
classNames: "w-full"
|
|
1640
|
-
}))) : /* @__PURE__ */ React11.createElement(
|
|
1641
|
-
classNames: "w-full text-start gap-
|
|
1748
|
+
}))) : /* @__PURE__ */ React11.createElement(Button2, {
|
|
1749
|
+
classNames: "w-full text-start gap-form-gap"
|
|
1642
1750
|
}, /* @__PURE__ */ React11.createElement("div", {
|
|
1643
|
-
role: "none",
|
|
1644
1751
|
className: "grow overflow-hidden"
|
|
1645
1752
|
}, /* @__PURE__ */ React11.createElement("span", {
|
|
1646
|
-
className: "
|
|
1647
|
-
}, placeholder ?? t("ref
|
|
1753
|
+
className: "truncate text-description"
|
|
1754
|
+
}, placeholder ?? t("ref-field.placeholder"))), /* @__PURE__ */ React11.createElement(Icon3, {
|
|
1648
1755
|
size: 3,
|
|
1649
1756
|
icon: "ph--caret-down--bold"
|
|
1650
1757
|
}))), /* @__PURE__ */ React11.createElement(ObjectPicker.Portal, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Content, {
|
|
1651
1758
|
classNames: "dx-card-popover-width",
|
|
1652
1759
|
options,
|
|
1653
1760
|
selectedIds,
|
|
1654
|
-
|
|
1761
|
+
// Strip hidden (`FormInputAnnotation.set(false)`) fields so the
|
|
1762
|
+
// form's validator doesn't reject required-but-hidden fields
|
|
1763
|
+
// such as backing-object refs supplied by a `FactoryAnnotation`.
|
|
1764
|
+
createSchema: createSchema && omitHiddenFormFields(omitId(createSchema)),
|
|
1655
1765
|
createOptionLabel,
|
|
1656
1766
|
createOptionIcon,
|
|
1657
1767
|
createInitialValuePath,
|
|
1768
|
+
createFieldMap: createFieldMap3,
|
|
1658
1769
|
onCreate: handleCreate,
|
|
1659
1770
|
onSelect: handleSelect
|
|
1660
1771
|
})))), layout === "full" && /* @__PURE__ */ React11.createElement(Input6.DescriptionAndValidation, null, error));
|
|
@@ -1696,20 +1807,21 @@ var SelectField = ({ type, readonly, label, layout, placeholder, options, getSta
|
|
|
1696
1807
|
};
|
|
1697
1808
|
|
|
1698
1809
|
// src/components/Form/fields/SelectOptionField.tsx
|
|
1699
|
-
import React13, { useCallback as useCallback11, useEffect as
|
|
1810
|
+
import React13, { useCallback as useCallback11, useEffect as useEffect4, useRef as useRef2, useState as useState5 } from "react";
|
|
1700
1811
|
import { PublicKey } from "@dxos/keys";
|
|
1701
|
-
import { IconButton as IconButton3, Input as Input8, Tag, useTranslation as
|
|
1812
|
+
import { IconButton as IconButton3, Input as Input8, Tag, useTranslation as useTranslation8 } from "@dxos/react-ui";
|
|
1702
1813
|
import { List } from "@dxos/react-ui-list";
|
|
1703
1814
|
import { HuePicker } from "@dxos/react-ui-pickers";
|
|
1704
|
-
import { hues, osTranslations
|
|
1815
|
+
import { hues, osTranslations } from "@dxos/ui-theme";
|
|
1816
|
+
import { translationKey as translationKey8 } from "#translations";
|
|
1705
1817
|
var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueChange }) => {
|
|
1706
|
-
const { t } =
|
|
1818
|
+
const { t } = useTranslation8(translationKey8);
|
|
1707
1819
|
const { status, error } = getStatus();
|
|
1708
|
-
const [selected, setSelectedId] =
|
|
1709
|
-
const [isNewOption, setIsNewOption] =
|
|
1710
|
-
const inputRef =
|
|
1820
|
+
const [selected, setSelectedId] = useState5(null);
|
|
1821
|
+
const [isNewOption, setIsNewOption] = useState5(false);
|
|
1822
|
+
const inputRef = useRef2(null);
|
|
1711
1823
|
const options = getValue();
|
|
1712
|
-
|
|
1824
|
+
useEffect4(() => {
|
|
1713
1825
|
if (options === void 0) {
|
|
1714
1826
|
onValueChange(type, []);
|
|
1715
1827
|
}
|
|
@@ -1800,7 +1912,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
|
|
|
1800
1912
|
type,
|
|
1801
1913
|
onValueChange
|
|
1802
1914
|
]);
|
|
1803
|
-
|
|
1915
|
+
useEffect4(() => {
|
|
1804
1916
|
if (selected && isNewOption && inputRef.current) {
|
|
1805
1917
|
inputRef.current.focus();
|
|
1806
1918
|
setIsNewOption(false);
|
|
@@ -1815,9 +1927,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
|
|
|
1815
1927
|
error,
|
|
1816
1928
|
readonly,
|
|
1817
1929
|
label
|
|
1818
|
-
}), /* @__PURE__ */ React13.createElement("div", {
|
|
1819
|
-
role: "none"
|
|
1820
|
-
}, options && /* @__PURE__ */ React13.createElement(List.Root, {
|
|
1930
|
+
}), /* @__PURE__ */ React13.createElement("div", null, options && /* @__PURE__ */ React13.createElement(List.Root, {
|
|
1821
1931
|
items: options,
|
|
1822
1932
|
isItem: (_item) => true,
|
|
1823
1933
|
onMove: readonly ? void 0 : handleMove,
|
|
@@ -1830,10 +1940,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
|
|
|
1830
1940
|
}, /* @__PURE__ */ React13.createElement(List.Item, {
|
|
1831
1941
|
role: "button",
|
|
1832
1942
|
item,
|
|
1833
|
-
classNames:
|
|
1834
|
-
subtleHover,
|
|
1835
|
-
"flex flex-col cursor-pointer rounded-xs"
|
|
1836
|
-
],
|
|
1943
|
+
classNames: "flex flex-col cursor-pointer rounded-xs dx-hover",
|
|
1837
1944
|
"aria-expanded": selected === item.id
|
|
1838
1945
|
}, /* @__PURE__ */ React13.createElement("div", {
|
|
1839
1946
|
className: "flex items-center"
|
|
@@ -1847,20 +1954,20 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
|
|
|
1847
1954
|
}, item.title || "\u200B")), /* @__PURE__ */ React13.createElement(IconButton3, {
|
|
1848
1955
|
iconOnly: true,
|
|
1849
1956
|
variant: "ghost",
|
|
1850
|
-
label: t(selected === item.id ? "collapse
|
|
1957
|
+
label: t(selected === item.id ? "collapse.label" : "expand.label", {
|
|
1851
1958
|
ns: osTranslations
|
|
1852
1959
|
}),
|
|
1853
1960
|
icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
1854
1961
|
onClick: () => handleClick(item.id)
|
|
1855
1962
|
})), selected === item.id && /* @__PURE__ */ React13.createElement("div", {
|
|
1856
|
-
className: "flex flex-col p-form-padding gap-
|
|
1963
|
+
className: "flex flex-col p-form-padding gap-form-gap dx-density-fine"
|
|
1857
1964
|
}, /* @__PURE__ */ React13.createElement(Input8.Label, {
|
|
1858
1965
|
classNames: "text-xs"
|
|
1859
|
-
}, t("select
|
|
1860
|
-
className: "grid grid-cols-[1fr_min-content_min-content] gap-
|
|
1966
|
+
}, t("select-option.label")), /* @__PURE__ */ React13.createElement("div", {
|
|
1967
|
+
className: "grid grid-cols-[1fr_min-content_min-content] gap-form-gap"
|
|
1861
1968
|
}, /* @__PURE__ */ React13.createElement(Input8.TextInput, {
|
|
1862
1969
|
disabled: !!readonly,
|
|
1863
|
-
placeholder: t("select
|
|
1970
|
+
placeholder: t("select-option-label.placeholder"),
|
|
1864
1971
|
ref: selected === item.id ? inputRef : void 0,
|
|
1865
1972
|
value: item.title,
|
|
1866
1973
|
onChange: handleTitleChange(item.id),
|
|
@@ -1874,12 +1981,12 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
|
|
|
1874
1981
|
disabled: !!readonly,
|
|
1875
1982
|
icon: "ph--trash--fill",
|
|
1876
1983
|
iconOnly: true,
|
|
1877
|
-
label: t("select
|
|
1984
|
+
label: t("select-option-delete.button"),
|
|
1878
1985
|
onClick: () => handleDelete(item.id)
|
|
1879
1986
|
})))))), /* @__PURE__ */ React13.createElement(IconButton3, {
|
|
1880
1987
|
variant: "ghost",
|
|
1881
1988
|
icon: "ph--plus--regular",
|
|
1882
|
-
label: t("select
|
|
1989
|
+
label: t("select-option-add.button"),
|
|
1883
1990
|
onClick: handleAdd,
|
|
1884
1991
|
disabled: !!readonly,
|
|
1885
1992
|
classNames: "w-full"
|
|
@@ -1889,7 +1996,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
|
|
|
1889
1996
|
// src/components/Form/fields/TextField.tsx
|
|
1890
1997
|
import React14, { useCallback as useCallback12 } from "react";
|
|
1891
1998
|
import { Input as Input9 } from "@dxos/react-ui";
|
|
1892
|
-
var TextField = ({ type, readonly, placeholder,
|
|
1999
|
+
var TextField = ({ type, readonly, placeholder, onBlur, onValueChange, ...props }) => {
|
|
1893
2000
|
const handleChange = useCallback12((event) => onValueChange(type, event.target.value), [
|
|
1894
2001
|
type,
|
|
1895
2002
|
onValueChange
|
|
@@ -1902,8 +2009,8 @@ var TextField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props
|
|
|
1902
2009
|
disabled: !!readonly,
|
|
1903
2010
|
placeholder,
|
|
1904
2011
|
value: value3,
|
|
1905
|
-
|
|
1906
|
-
|
|
2012
|
+
onBlur,
|
|
2013
|
+
onChange: handleChange
|
|
1907
2014
|
}));
|
|
1908
2015
|
};
|
|
1909
2016
|
|
|
@@ -1931,7 +2038,7 @@ var TextAreaField = ({ type, readonly, placeholder, onValueChange, onBlur, ...pr
|
|
|
1931
2038
|
// src/components/Form/fields/TupleField.tsx
|
|
1932
2039
|
import React16 from "react";
|
|
1933
2040
|
import { Input as Input11 } from "@dxos/react-ui";
|
|
1934
|
-
import { mx as
|
|
2041
|
+
import { mx as mx2 } from "@dxos/ui-theme";
|
|
1935
2042
|
import { safeParseFloat as safeParseFloat3 } from "@dxos/util";
|
|
1936
2043
|
var gridCols = [
|
|
1937
2044
|
"grid-cols-1",
|
|
@@ -1949,7 +2056,7 @@ var TupleField = ({ binding, type, readonly, label, getStatus, getValue, onValue
|
|
|
1949
2056
|
readonly,
|
|
1950
2057
|
label
|
|
1951
2058
|
}), /* @__PURE__ */ React16.createElement("div", {
|
|
1952
|
-
className:
|
|
2059
|
+
className: mx2("grid gap-form-gap", gridCols[binding.length - 1])
|
|
1953
2060
|
}, binding.map((prop) => /* @__PURE__ */ React16.createElement(Input11.TextInput, {
|
|
1954
2061
|
key: prop,
|
|
1955
2062
|
type: "number",
|
|
@@ -1968,13 +2075,13 @@ var TupleField = ({ binding, type, readonly, label, getStatus, getValue, onValue
|
|
|
1968
2075
|
// src/components/FieldEditor/FieldEditor.tsx
|
|
1969
2076
|
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
|
|
1970
2077
|
var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCancel }) => {
|
|
1971
|
-
const { t } =
|
|
1972
|
-
const [props, setProps] =
|
|
1973
|
-
|
|
2078
|
+
const { t } = useTranslation9(translationKey9);
|
|
2079
|
+
const [props, setProps] = useState6(projection.getFieldProjection(field.id).props);
|
|
2080
|
+
useEffect5(() => setProps(projection.getFieldProjection(field.id).props), [
|
|
1974
2081
|
field,
|
|
1975
2082
|
projection
|
|
1976
2083
|
]);
|
|
1977
|
-
const [schemas, setSchemas] =
|
|
2084
|
+
const [schemas, setSchemas] = useState6([]);
|
|
1978
2085
|
useAsyncEffect(async () => {
|
|
1979
2086
|
if (!registry) {
|
|
1980
2087
|
return;
|
|
@@ -1988,22 +2095,22 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
|
|
|
1988
2095
|
}, [
|
|
1989
2096
|
registry
|
|
1990
2097
|
]);
|
|
1991
|
-
const [referenceSchema, setReferenceSchema] =
|
|
1992
|
-
|
|
2098
|
+
const [referenceSchema, setReferenceSchema] = useState6();
|
|
2099
|
+
useEffect5(() => {
|
|
1993
2100
|
setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
|
|
1994
2101
|
}, [
|
|
1995
2102
|
schemas,
|
|
1996
2103
|
props?.referenceSchema
|
|
1997
2104
|
]);
|
|
1998
|
-
const [{ fieldSchema }, setFieldSchema] =
|
|
2105
|
+
const [{ fieldSchema }, setFieldSchema] = useState6({
|
|
1999
2106
|
fieldSchema: getFormatSchema(props?.format)
|
|
2000
2107
|
});
|
|
2001
|
-
const fieldMap =
|
|
2108
|
+
const fieldMap = useMemo8(() => ({
|
|
2002
2109
|
["format"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
|
|
2003
2110
|
...props2,
|
|
2004
2111
|
options: FormatEnums.filter((value3) => value3 !== Format4.TypeFormat.None).map((value3) => ({
|
|
2005
2112
|
value: value3,
|
|
2006
|
-
label: t(`format
|
|
2113
|
+
label: t(`format.${value3}.label`)
|
|
2007
2114
|
}))
|
|
2008
2115
|
}),
|
|
2009
2116
|
["referenceSchema"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
|
|
@@ -2077,7 +2184,7 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
|
|
|
2077
2184
|
]);
|
|
2078
2185
|
const handleSave = useCallback14((props2) => {
|
|
2079
2186
|
if (view) {
|
|
2080
|
-
|
|
2187
|
+
Obj3.update(view, () => {
|
|
2081
2188
|
projection.setFieldProjection({
|
|
2082
2189
|
field,
|
|
2083
2190
|
props: props2
|
|
@@ -2105,12 +2212,7 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
|
|
|
2105
2212
|
if (!fieldSchema) {
|
|
2106
2213
|
log2.warn("invalid format", {
|
|
2107
2214
|
props
|
|
2108
|
-
}, {
|
|
2109
|
-
F: __dxlog_file2,
|
|
2110
|
-
L: 172,
|
|
2111
|
-
S: void 0,
|
|
2112
|
-
C: (f, a) => f(...a)
|
|
2113
|
-
});
|
|
2215
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 156, S: void 0 });
|
|
2114
2216
|
return null;
|
|
2115
2217
|
}
|
|
2116
2218
|
return /* @__PURE__ */ React17.createElement(Form.Root, {
|
|
@@ -2132,160 +2234,491 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
|
|
|
2132
2234
|
}, /* @__PURE__ */ React17.createElement(Form.Content, null, /* @__PURE__ */ React17.createElement(Form.FieldSet, null), /* @__PURE__ */ React17.createElement(Form.Actions, null)));
|
|
2133
2235
|
};
|
|
2134
2236
|
|
|
2135
|
-
// src/components/
|
|
2136
|
-
import
|
|
2137
|
-
import
|
|
2138
|
-
import {
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
var
|
|
2145
|
-
var
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
};
|
|
2162
|
-
|
|
2163
|
-
var SettingsSection = ({ title, description, children }) => {
|
|
2164
|
-
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(SettingsSectionHeading, {
|
|
2165
|
-
title,
|
|
2166
|
-
description
|
|
2167
|
-
}), /* @__PURE__ */ React18.createElement("div", {
|
|
2168
|
-
className: "w-full pt-trim-md space-y-trim-md"
|
|
2169
|
-
}, children));
|
|
2170
|
-
};
|
|
2171
|
-
SettingsSection.displayName = SETTINGS_SECTION_NAME;
|
|
2172
|
-
var SettingsSectionHeading = ({ title, description }) => {
|
|
2173
|
-
const { t } = useTranslation9(translationKey);
|
|
2174
|
-
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("h2", {
|
|
2175
|
-
className: "px-trim-md mt-trim-md mb-trim-md text-xl"
|
|
2176
|
-
}, toLocalizedString(title, t)), description && /* @__PURE__ */ React18.createElement("p", {
|
|
2177
|
-
className: "px-trim-md my-trim-md text-description"
|
|
2178
|
-
}, toLocalizedString(description, t)));
|
|
2237
|
+
// src/components/ObjectForm/ObjectForm.tsx
|
|
2238
|
+
import * as Schema3 from "effect/Schema";
|
|
2239
|
+
import React18, { useCallback as useCallback15, useMemo as useMemo9 } from "react";
|
|
2240
|
+
import { DXN as DXN2, Obj as Obj4, Ref as Ref4, Tag as Tag2, Type as Type2 } from "@dxos/echo";
|
|
2241
|
+
import { splitJsonPath } from "@dxos/echo/internal";
|
|
2242
|
+
import { invariant } from "@dxos/invariant";
|
|
2243
|
+
import { HuePicker as HuePicker2 } from "@dxos/react-ui-pickers";
|
|
2244
|
+
import { isNonNullable } from "@dxos/util";
|
|
2245
|
+
import { translationKey as translationKey10 } from "#translations";
|
|
2246
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ObjectForm/ObjectForm.tsx";
|
|
2247
|
+
var createFieldMap = {
|
|
2248
|
+
hue: ({ type, label, layout, getValue, onValueChange }) => {
|
|
2249
|
+
const handleChange = useCallback15((nextHue) => onValueChange(type, nextHue), [
|
|
2250
|
+
onValueChange,
|
|
2251
|
+
type
|
|
2252
|
+
]);
|
|
2253
|
+
const handleReset = useCallback15(() => onValueChange(type, void 0), [
|
|
2254
|
+
onValueChange,
|
|
2255
|
+
type
|
|
2256
|
+
]);
|
|
2257
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, layout !== "inline" && /* @__PURE__ */ React18.createElement(Form.Label, {
|
|
2258
|
+
label
|
|
2259
|
+
}), /* @__PURE__ */ React18.createElement(HuePicker2, {
|
|
2260
|
+
value: getValue(),
|
|
2261
|
+
onChange: handleChange,
|
|
2262
|
+
onReset: handleReset
|
|
2263
|
+
}));
|
|
2264
|
+
}
|
|
2179
2265
|
};
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2266
|
+
var ObjectForm = ({ object, schema }) => {
|
|
2267
|
+
const db = Obj4.getDatabase(object);
|
|
2268
|
+
const meta = Obj4.getMeta(object);
|
|
2269
|
+
const tags = (meta.tags ?? []).map((tag) => db?.makeRef(DXN2.parse(tag))).filter(isNonNullable);
|
|
2270
|
+
const values = useMemo9(() => ({
|
|
2271
|
+
tags,
|
|
2272
|
+
...object
|
|
2273
|
+
}), [
|
|
2274
|
+
object,
|
|
2275
|
+
tags
|
|
2276
|
+
]);
|
|
2277
|
+
const formSchema = useMemo9(() => omitId(Schema3.Struct({
|
|
2278
|
+
tags: Schema3.Array(Ref4.Ref(Tag2.Tag)).pipe(Schema3.optional)
|
|
2279
|
+
}).pipe(Schema3.extend(schema))), [
|
|
2280
|
+
schema
|
|
2281
|
+
]);
|
|
2282
|
+
const handleCreate = useCallback15((schema2, values2) => {
|
|
2283
|
+
invariant(db, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 49, S: void 0, A: ["db", ""] });
|
|
2284
|
+
invariant(Type2.isObjectSchema(schema2), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 50, S: void 0, A: ["Type.isObjectSchema(schema)", ""] });
|
|
2285
|
+
const newObject = db.add(Obj4.make(schema2, values2));
|
|
2286
|
+
if (Obj4.instanceOf(Tag2.Tag, newObject)) {
|
|
2287
|
+
Obj4.update(object, (object2) => {
|
|
2288
|
+
Obj4.getMeta(object2).tags = [
|
|
2289
|
+
...Obj4.getMeta(object2).tags ?? [],
|
|
2290
|
+
Obj4.getDXN(newObject).toString()
|
|
2291
|
+
];
|
|
2292
|
+
});
|
|
2293
|
+
}
|
|
2294
|
+
}, []);
|
|
2295
|
+
const handleChange = useCallback15(({ tags: tags2, ...values2 }, { isValid, changed }) => {
|
|
2296
|
+
if (!isValid) {
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
const changedPaths = Object.keys(changed).filter((path) => changed[path]);
|
|
2300
|
+
const hasTagsChange = changedPaths.some((path) => splitJsonPath(path)[0] === "tags");
|
|
2301
|
+
if (hasTagsChange) {
|
|
2302
|
+
Obj4.update(object, (object2) => {
|
|
2303
|
+
Obj4.getMeta(object2).tags = tags2?.map((tag) => tag.dxn.toString()) ?? [];
|
|
2304
|
+
});
|
|
2305
|
+
}
|
|
2306
|
+
const nonTagPaths = changedPaths.filter((path) => splitJsonPath(path)[0] !== "tags");
|
|
2307
|
+
if (nonTagPaths.length > 0) {
|
|
2308
|
+
Obj4.update(object, () => {
|
|
2309
|
+
for (const path of nonTagPaths) {
|
|
2310
|
+
const parts = splitJsonPath(path);
|
|
2311
|
+
const value3 = Obj4.getValue(values2, parts);
|
|
2312
|
+
Obj4.setValue(object, parts, value3);
|
|
2313
|
+
}
|
|
2314
|
+
});
|
|
2315
|
+
}
|
|
2316
|
+
}, [
|
|
2317
|
+
object
|
|
2318
|
+
]);
|
|
2319
|
+
return /* @__PURE__ */ React18.createElement(Form.Root, {
|
|
2320
|
+
schema: formSchema,
|
|
2321
|
+
defaultValues: values,
|
|
2322
|
+
createTypename: Type2.getTypename(Tag2.Tag),
|
|
2323
|
+
createOptionIcon: "ph--plus--regular",
|
|
2324
|
+
createOptionLabel: [
|
|
2325
|
+
"add-tag.label",
|
|
2326
|
+
{
|
|
2327
|
+
ns: translationKey10
|
|
2328
|
+
}
|
|
2329
|
+
],
|
|
2330
|
+
createInitialValuePath: "label",
|
|
2331
|
+
createFieldMap,
|
|
2332
|
+
db,
|
|
2333
|
+
onValuesChanged: handleChange,
|
|
2334
|
+
onCreate: handleCreate
|
|
2335
|
+
}, /* @__PURE__ */ React18.createElement(Form.Viewport, null, /* @__PURE__ */ React18.createElement(Form.Content, null, /* @__PURE__ */ React18.createElement(Form.FieldSet, null))));
|
|
2189
2336
|
};
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2337
|
+
|
|
2338
|
+
// src/components/ObjectProperties/ObjectProperties.tsx
|
|
2339
|
+
import * as Function from "effect/Function";
|
|
2340
|
+
import * as Option5 from "effect/Option";
|
|
2341
|
+
import * as Schema4 from "effect/Schema";
|
|
2342
|
+
import React19, { useCallback as useCallback16, useMemo as useMemo10 } from "react";
|
|
2343
|
+
import { DXN as DXN3, Obj as Obj5, Ref as Ref5, Tag as Tag3, Type as Type3 } from "@dxos/echo";
|
|
2344
|
+
import { useSchema } from "@dxos/echo-react";
|
|
2345
|
+
import { splitJsonPath as splitJsonPath2 } from "@dxos/echo/internal";
|
|
2346
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
2347
|
+
import { HuePicker as HuePicker3 } from "@dxos/react-ui-pickers";
|
|
2348
|
+
import { FactoryAnnotation } from "@dxos/schema";
|
|
2349
|
+
import { composable as composable2, composableProps as composableProps2 } from "@dxos/ui-theme";
|
|
2350
|
+
import { isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
2351
|
+
import { translationKey as translationKey11 } from "#translations";
|
|
2352
|
+
var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ObjectProperties/ObjectProperties.tsx";
|
|
2353
|
+
var ObjectProperties = composable2(({ children, object, ...props }, forwardedRef) => {
|
|
2354
|
+
const db = Obj5.getDatabase(object);
|
|
2355
|
+
const meta = Obj5.getMeta(object);
|
|
2356
|
+
const tags = (meta.tags ?? []).map((tag) => db?.makeRef(DXN3.parse(tag))).filter(isNonNullable2);
|
|
2357
|
+
const values = useMemo10(() => ({
|
|
2358
|
+
tags,
|
|
2359
|
+
...object
|
|
2360
|
+
}), [
|
|
2361
|
+
object,
|
|
2362
|
+
tags
|
|
2363
|
+
]);
|
|
2364
|
+
const typename = Obj5.getTypename(object) ?? void 0;
|
|
2365
|
+
const schemaFromRegistry = useSchema(db, typename);
|
|
2366
|
+
const rawSchema = Obj5.getSchema(object) ?? schemaFromRegistry;
|
|
2367
|
+
const formSchema = useMemo10(() => {
|
|
2368
|
+
return Function.pipe(rawSchema, Option5.fromNullable, Option5.map((schema) => omitId(BaseSchema.pipe(Schema4.extend(schema)))), Option5.getOrUndefined);
|
|
2369
|
+
}, [
|
|
2370
|
+
rawSchema
|
|
2371
|
+
]);
|
|
2372
|
+
const handleCreate = useCallback16((schema, values2) => {
|
|
2373
|
+
invariant2(db, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 51, S: void 0, A: ["db", ""] });
|
|
2374
|
+
invariant2(Type3.isObjectSchema(schema), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 52, S: void 0, A: ["Type.isObjectSchema(schema)", ""] });
|
|
2375
|
+
const factory = Option5.getOrUndefined(FactoryAnnotation.get(schema));
|
|
2376
|
+
const newObject = factory ? factory(values2) : Obj5.make(schema, values2);
|
|
2377
|
+
return db.add(newObject);
|
|
2378
|
+
}, [
|
|
2379
|
+
db
|
|
2380
|
+
]);
|
|
2381
|
+
const handleChange = useCallback16(({ tags: tags2, ...values2 }, { isValid, changed }) => {
|
|
2382
|
+
if (!isValid) {
|
|
2383
|
+
return;
|
|
2384
|
+
}
|
|
2385
|
+
const changedPaths = Object.keys(changed).filter((path) => changed[path]);
|
|
2386
|
+
const hasTagsChange = changedPaths.some((path) => splitJsonPath2(path)[0] === "tags");
|
|
2387
|
+
if (hasTagsChange) {
|
|
2388
|
+
Obj5.update(object, (object2) => {
|
|
2389
|
+
Obj5.getMeta(object2).tags = tags2?.map((tag) => tag.dxn.toString()) ?? [];
|
|
2390
|
+
});
|
|
2391
|
+
}
|
|
2392
|
+
const nonTagPaths = changedPaths.filter((path) => splitJsonPath2(path)[0] !== "tags");
|
|
2393
|
+
if (nonTagPaths.length > 0) {
|
|
2394
|
+
Obj5.update(object, () => {
|
|
2395
|
+
for (const path of nonTagPaths) {
|
|
2396
|
+
const parts = splitJsonPath2(path);
|
|
2397
|
+
const value3 = Obj5.getValue(values2, parts);
|
|
2398
|
+
Obj5.setValue(object, parts, value3);
|
|
2399
|
+
}
|
|
2400
|
+
});
|
|
2401
|
+
}
|
|
2402
|
+
}, [
|
|
2403
|
+
object
|
|
2404
|
+
]);
|
|
2405
|
+
if (!formSchema) {
|
|
2406
|
+
return null;
|
|
2407
|
+
}
|
|
2408
|
+
return /* @__PURE__ */ React19.createElement(Form.Root, {
|
|
2409
|
+
schema: formSchema,
|
|
2410
|
+
defaultValues: values,
|
|
2411
|
+
createTypename: Type3.getTypename(Tag3.Tag),
|
|
2412
|
+
createOptionIcon: "ph--plus--regular",
|
|
2413
|
+
createOptionLabel: [
|
|
2414
|
+
"add-tag.label",
|
|
2415
|
+
{
|
|
2416
|
+
ns: translationKey11
|
|
2417
|
+
}
|
|
2418
|
+
],
|
|
2419
|
+
createInitialValuePath: "label",
|
|
2420
|
+
createFieldMap: createFieldMap2,
|
|
2421
|
+
db,
|
|
2422
|
+
onValuesChanged: handleChange,
|
|
2423
|
+
onCreate: handleCreate
|
|
2424
|
+
}, /* @__PURE__ */ React19.createElement(Form.Viewport, {
|
|
2425
|
+
...composableProps2(props),
|
|
2426
|
+
ref: forwardedRef
|
|
2427
|
+
}, /* @__PURE__ */ React19.createElement(Form.Content, null, /* @__PURE__ */ React19.createElement(Form.FieldSet, null), children)));
|
|
2428
|
+
});
|
|
2429
|
+
var createFieldMap2 = {
|
|
2430
|
+
hue: ({ type, label, layout, getValue, onValueChange }) => {
|
|
2431
|
+
const handleChange = useCallback16((nextHue) => onValueChange(type, nextHue), [
|
|
2432
|
+
onValueChange,
|
|
2433
|
+
type
|
|
2434
|
+
]);
|
|
2435
|
+
const handleReset = useCallback16(() => onValueChange(type, void 0), [
|
|
2436
|
+
onValueChange,
|
|
2437
|
+
type
|
|
2438
|
+
]);
|
|
2439
|
+
return /* @__PURE__ */ React19.createElement(React19.Fragment, null, layout !== "inline" && /* @__PURE__ */ React19.createElement(Form.Label, {
|
|
2440
|
+
label
|
|
2441
|
+
}), /* @__PURE__ */ React19.createElement(HuePicker3, {
|
|
2442
|
+
value: getValue(),
|
|
2443
|
+
onChange: handleChange,
|
|
2444
|
+
onReset: handleReset
|
|
2445
|
+
}));
|
|
2446
|
+
}
|
|
2211
2447
|
};
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2448
|
+
var BaseSchema = Schema4.Struct({
|
|
2449
|
+
tags: Schema4.Array(Ref5.Ref(Tag3.Tag)).pipe(Schema4.optional)
|
|
2450
|
+
});
|
|
2451
|
+
|
|
2452
|
+
// src/components/Settings/Settings.tsx
|
|
2453
|
+
import React22 from "react";
|
|
2454
|
+
import { ScrollArea as ScrollArea2, toLocalizedString as toLocalizedString2, useTranslation as useTranslation11 } from "@dxos/react-ui";
|
|
2455
|
+
import { composable as composable3, composableProps as composableProps3, mx as mx4 } from "@dxos/ui-theme";
|
|
2456
|
+
import { translationKey as translationKey13 } from "#translations";
|
|
2457
|
+
|
|
2458
|
+
// src/components/Settings/SettingsFieldSet.tsx
|
|
2459
|
+
import * as SchemaAST6 from "effect/SchemaAST";
|
|
2460
|
+
import * as String3 from "effect/String";
|
|
2461
|
+
import React21, { useCallback as useCallback17, useMemo as useMemo11 } from "react";
|
|
2462
|
+
import { getAnnotation as getAnnotation3 } from "@dxos/effect";
|
|
2463
|
+
import { Input as Input13, Select as Select2 } from "@dxos/react-ui";
|
|
2464
|
+
|
|
2465
|
+
// src/components/Settings/SettingsItem.tsx
|
|
2466
|
+
import React20 from "react";
|
|
2467
|
+
import { Input as Input12, toLocalizedString, useTranslation as useTranslation10 } from "@dxos/react-ui";
|
|
2468
|
+
import { mx as mx3 } from "@dxos/ui-theme";
|
|
2469
|
+
import { translationKey as translationKey12 } from "#translations";
|
|
2470
|
+
var SETTINGS_PANEL_NAME = "Settings.Panel";
|
|
2471
|
+
var SETTINGS_ITEM_NAME = "Settings.Item";
|
|
2472
|
+
var SettingsPanel = ({ classNames, children }) => {
|
|
2473
|
+
return /* @__PURE__ */ React20.createElement("div", {
|
|
2474
|
+
className: mx3("flex flex-col gap-3 p-trim-md border border-separator rounded-sm", classNames)
|
|
2222
2475
|
}, children);
|
|
2223
2476
|
};
|
|
2224
|
-
|
|
2477
|
+
SettingsPanel.displayName = SETTINGS_PANEL_NAME;
|
|
2225
2478
|
var SettingsItem = ({ title, description = "", children }) => {
|
|
2226
|
-
const { t } =
|
|
2227
|
-
return /* @__PURE__ */
|
|
2228
|
-
classNames:
|
|
2229
|
-
}, /* @__PURE__ */
|
|
2230
|
-
|
|
2231
|
-
}, toLocalizedString(title, t)), /* @__PURE__ */
|
|
2232
|
-
|
|
2233
|
-
}, toLocalizedString(description, t)), /* @__PURE__ */
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
}, children));
|
|
2479
|
+
const { t } = useTranslation10(translationKey12);
|
|
2480
|
+
return /* @__PURE__ */ React20.createElement(Input12.Root, null, /* @__PURE__ */ React20.createElement(SettingsPanel, {
|
|
2481
|
+
classNames: "grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-x-trim-lg gap-y-0"
|
|
2482
|
+
}, /* @__PURE__ */ React20.createElement(Input12.Label, {
|
|
2483
|
+
classNames: "pb-trim-md text-base-foreground text-lg md:col-span-2"
|
|
2484
|
+
}, toLocalizedString(title, t)), /* @__PURE__ */ React20.createElement(Input12.DescriptionAndValidation, null, /* @__PURE__ */ React20.createElement(Input12.Description, {
|
|
2485
|
+
classNames: "text-base text-description"
|
|
2486
|
+
}, toLocalizedString(description, t))), /* @__PURE__ */ React20.createElement("div", {
|
|
2487
|
+
className: "text-end py-1"
|
|
2488
|
+
}, children)));
|
|
2237
2489
|
};
|
|
2238
2490
|
SettingsItem.displayName = SETTINGS_ITEM_NAME;
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2491
|
+
|
|
2492
|
+
// src/components/Settings/SettingsFieldSet.tsx
|
|
2493
|
+
var SettingsFieldSet = ({ schema, values, onValuesChanged, readonly, fieldMap, visible, sort, pathPrefix = "" }) => {
|
|
2494
|
+
const properties = useMemo11(() => {
|
|
2495
|
+
const props = getFormProperties(schema.ast);
|
|
2496
|
+
if (!sort) {
|
|
2497
|
+
return props;
|
|
2498
|
+
}
|
|
2499
|
+
const rank = (name) => {
|
|
2500
|
+
const idx = sort.indexOf(name);
|
|
2501
|
+
return idx === -1 ? Number.POSITIVE_INFINITY : idx;
|
|
2502
|
+
};
|
|
2503
|
+
return [
|
|
2504
|
+
...props
|
|
2505
|
+
].sort(({ name: a }, { name: b }) => rank(a.toString()) - rank(b.toString()));
|
|
2506
|
+
}, [
|
|
2507
|
+
schema,
|
|
2508
|
+
sort
|
|
2509
|
+
]);
|
|
2510
|
+
const handleChange = useCallback17((name, value3) => {
|
|
2511
|
+
onValuesChanged?.({
|
|
2512
|
+
...values,
|
|
2513
|
+
[name]: value3
|
|
2514
|
+
});
|
|
2515
|
+
}, [
|
|
2516
|
+
values,
|
|
2517
|
+
onValuesChanged
|
|
2518
|
+
]);
|
|
2519
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, properties.map((property) => {
|
|
2520
|
+
const name = property.name.toString();
|
|
2521
|
+
const path = pathPrefix ? `${pathPrefix}.${name}` : name;
|
|
2522
|
+
if (visible && !visible(path, values)) {
|
|
2523
|
+
return null;
|
|
2524
|
+
}
|
|
2525
|
+
const entry = fieldMap?.[name];
|
|
2526
|
+
return /* @__PURE__ */ React21.createElement(SettingsFieldItem, {
|
|
2527
|
+
key: name,
|
|
2528
|
+
path,
|
|
2529
|
+
property,
|
|
2530
|
+
value: values[name],
|
|
2531
|
+
onChange: (value3) => handleChange(name, value3),
|
|
2532
|
+
readonly,
|
|
2533
|
+
customField: typeof entry === "function" ? entry : void 0,
|
|
2534
|
+
nestedFieldMap: typeof entry === "object" ? entry : void 0,
|
|
2535
|
+
visible,
|
|
2536
|
+
sort
|
|
2537
|
+
});
|
|
2538
|
+
}));
|
|
2539
|
+
};
|
|
2540
|
+
SettingsFieldSet.displayName = "Settings.FieldSet";
|
|
2541
|
+
var SettingsFieldItem = ({ property, path, value: value3, onChange, readonly, customField, nestedFieldMap, visible, sort }) => {
|
|
2542
|
+
const { type } = property;
|
|
2543
|
+
const name = property.name.toString();
|
|
2544
|
+
const title = getAnnotation3(SchemaAST6.TitleAnnotationId)(type) ?? String3.capitalize(name);
|
|
2545
|
+
const description = getAnnotation3(SchemaAST6.DescriptionAnnotationId)(type);
|
|
2546
|
+
if (customField) {
|
|
2547
|
+
const CustomField = customField;
|
|
2548
|
+
return /* @__PURE__ */ React21.createElement(SettingsItem, {
|
|
2549
|
+
title,
|
|
2550
|
+
description
|
|
2551
|
+
}, /* @__PURE__ */ React21.createElement(CustomField, {
|
|
2552
|
+
value: value3,
|
|
2553
|
+
onChange,
|
|
2554
|
+
readonly
|
|
2555
|
+
}));
|
|
2556
|
+
}
|
|
2557
|
+
const fieldType = detectFieldType(type);
|
|
2558
|
+
switch (fieldType) {
|
|
2559
|
+
case "struct":
|
|
2560
|
+
return /* @__PURE__ */ React21.createElement(SettingsFieldSet, {
|
|
2561
|
+
schema: {
|
|
2562
|
+
ast: type
|
|
2563
|
+
},
|
|
2564
|
+
values: value3 ?? {},
|
|
2565
|
+
onValuesChanged: onChange,
|
|
2566
|
+
readonly,
|
|
2567
|
+
fieldMap: nestedFieldMap,
|
|
2568
|
+
visible,
|
|
2569
|
+
sort,
|
|
2570
|
+
pathPrefix: path
|
|
2571
|
+
});
|
|
2572
|
+
case "boolean":
|
|
2573
|
+
return /* @__PURE__ */ React21.createElement(SettingsItem, {
|
|
2574
|
+
title,
|
|
2575
|
+
description
|
|
2576
|
+
}, /* @__PURE__ */ React21.createElement(Input13.Switch, {
|
|
2577
|
+
disabled: readonly,
|
|
2578
|
+
checked: !!value3,
|
|
2579
|
+
onCheckedChange: (checked) => onChange(!!checked)
|
|
2580
|
+
}));
|
|
2581
|
+
case "select": {
|
|
2582
|
+
const options = getSelectOptionsFromAst(type) ?? [];
|
|
2583
|
+
return /* @__PURE__ */ React21.createElement(SettingsItem, {
|
|
2584
|
+
title,
|
|
2585
|
+
description
|
|
2586
|
+
}, /* @__PURE__ */ React21.createElement(Select2.Root, {
|
|
2587
|
+
disabled: readonly,
|
|
2588
|
+
value: value3 == null ? "" : globalThis.String(value3),
|
|
2589
|
+
onValueChange: (selected) => {
|
|
2590
|
+
const matched = options.find((option) => globalThis.String(option.value) === selected);
|
|
2591
|
+
onChange(matched?.value ?? selected);
|
|
2592
|
+
}
|
|
2593
|
+
}, /* @__PURE__ */ React21.createElement(Select2.TriggerButton, {
|
|
2594
|
+
disabled: readonly
|
|
2595
|
+
}), /* @__PURE__ */ React21.createElement(Select2.Portal, null, /* @__PURE__ */ React21.createElement(Select2.Content, null, /* @__PURE__ */ React21.createElement(Select2.Viewport, null, options.map((option) => /* @__PURE__ */ React21.createElement(Select2.Option, {
|
|
2596
|
+
key: globalThis.String(option.value),
|
|
2597
|
+
value: globalThis.String(option.value)
|
|
2598
|
+
}, option.label ?? globalThis.String(option.value)))), /* @__PURE__ */ React21.createElement(Select2.Arrow, null)))));
|
|
2599
|
+
}
|
|
2600
|
+
case "string":
|
|
2601
|
+
return /* @__PURE__ */ React21.createElement(SettingsItem, {
|
|
2602
|
+
title,
|
|
2603
|
+
description
|
|
2604
|
+
}, /* @__PURE__ */ React21.createElement(Input13.TextInput, {
|
|
2605
|
+
disabled: readonly,
|
|
2606
|
+
value: value3 ?? "",
|
|
2607
|
+
onChange: (event) => onChange(event.target.value)
|
|
2608
|
+
}));
|
|
2609
|
+
case "number":
|
|
2610
|
+
return /* @__PURE__ */ React21.createElement(SettingsItem, {
|
|
2611
|
+
title,
|
|
2612
|
+
description
|
|
2613
|
+
}, /* @__PURE__ */ React21.createElement(Input13.TextInput, {
|
|
2614
|
+
disabled: readonly,
|
|
2615
|
+
type: "number",
|
|
2616
|
+
value: value3 ?? "",
|
|
2617
|
+
onChange: (event) => {
|
|
2618
|
+
if (event.target.value === "") {
|
|
2619
|
+
onChange(void 0);
|
|
2620
|
+
return;
|
|
2621
|
+
}
|
|
2622
|
+
const parsed = Number(event.target.value);
|
|
2623
|
+
onChange(Number.isNaN(parsed) ? void 0 : parsed);
|
|
2624
|
+
}
|
|
2625
|
+
}));
|
|
2626
|
+
default:
|
|
2627
|
+
return null;
|
|
2628
|
+
}
|
|
2629
|
+
};
|
|
2630
|
+
|
|
2631
|
+
// src/components/Settings/Settings.tsx
|
|
2632
|
+
var SETTINGS_ROOT_NAME = "Settings.Root";
|
|
2633
|
+
var SETTINGS_VIEWPORT_NAME = "Settings.Viewport";
|
|
2634
|
+
var SETTINGS_SECTION_NAME = "Settings.Section";
|
|
2635
|
+
var SettingsRoot = ({ children, classNames }) => {
|
|
2636
|
+
return /* @__PURE__ */ React22.createElement("div", {
|
|
2637
|
+
className: mx4("flex flex-col gap-2", classNames)
|
|
2638
|
+
}, children);
|
|
2639
|
+
};
|
|
2640
|
+
SettingsRoot.displayName = SETTINGS_ROOT_NAME;
|
|
2641
|
+
var SettingsViewport = composable3(({ children, ...props }, forwardedRef) => {
|
|
2642
|
+
return /* @__PURE__ */ React22.createElement(ScrollArea2.Root, {
|
|
2643
|
+
...composableProps3(props),
|
|
2644
|
+
orientation: "vertical",
|
|
2645
|
+
centered: true,
|
|
2646
|
+
thin: true,
|
|
2647
|
+
ref: forwardedRef
|
|
2648
|
+
}, /* @__PURE__ */ React22.createElement(ScrollArea2.Viewport, {
|
|
2649
|
+
classNames: "px-4 pointer-coarse:px-2"
|
|
2650
|
+
}, /* @__PURE__ */ React22.createElement("div", {
|
|
2651
|
+
className: "dx-document flex flex-col gap-2 py-4"
|
|
2250
2652
|
}, children)));
|
|
2653
|
+
});
|
|
2654
|
+
SettingsViewport.displayName = SETTINGS_VIEWPORT_NAME;
|
|
2655
|
+
var SettingsSection = ({ title, description, children }) => {
|
|
2656
|
+
const { t } = useTranslation11(translationKey13);
|
|
2657
|
+
return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("h2", {
|
|
2658
|
+
className: "px-trim-md mt-trim-md text-xl"
|
|
2659
|
+
}, toLocalizedString2(title, t)), description && /* @__PURE__ */ React22.createElement("p", {
|
|
2660
|
+
className: "px-trim-md text-description"
|
|
2661
|
+
}, toLocalizedString2(description, t)), /* @__PURE__ */ React22.createElement("div", {
|
|
2662
|
+
className: "w-full pt-trim-md space-y-trim-md"
|
|
2663
|
+
}, children));
|
|
2251
2664
|
};
|
|
2252
|
-
|
|
2665
|
+
SettingsSection.displayName = SETTINGS_SECTION_NAME;
|
|
2253
2666
|
var Settings = {
|
|
2254
2667
|
Root: SettingsRoot,
|
|
2668
|
+
Viewport: SettingsViewport,
|
|
2255
2669
|
Section: SettingsSection,
|
|
2256
|
-
|
|
2257
|
-
Group: SettingsGroup,
|
|
2258
|
-
GroupButton: SettingsGroupButton,
|
|
2259
|
-
Container: SettingsContainer,
|
|
2260
|
-
Frame: SettingsFrame,
|
|
2261
|
-
FrameItem: SettingsFrameItem,
|
|
2670
|
+
Panel: SettingsPanel,
|
|
2262
2671
|
Item: SettingsItem,
|
|
2263
|
-
|
|
2672
|
+
FieldSet: SettingsFieldSet
|
|
2673
|
+
};
|
|
2674
|
+
|
|
2675
|
+
// src/components/Settings/SettingsSelectField.tsx
|
|
2676
|
+
import React23 from "react";
|
|
2677
|
+
import { Select as Select3 } from "@dxos/react-ui";
|
|
2678
|
+
var createSelectField = ({ options, defaultLabel = "Default" }) => {
|
|
2679
|
+
const normalized = options.map((option) => typeof option === "string" ? {
|
|
2680
|
+
value: option,
|
|
2681
|
+
label: option
|
|
2682
|
+
} : option);
|
|
2683
|
+
const hasDefault = defaultLabel !== null;
|
|
2684
|
+
const sentinel = hasDefault ? `__default__${Math.random().toString(36).slice(2)}` : "";
|
|
2685
|
+
return ({ value: value3, onChange, readonly }) => /* @__PURE__ */ React23.createElement(Select3.Root, {
|
|
2686
|
+
disabled: readonly,
|
|
2687
|
+
value: value3 ?? sentinel,
|
|
2688
|
+
onValueChange: (next) => onChange(hasDefault && next === sentinel ? void 0 : next)
|
|
2689
|
+
}, /* @__PURE__ */ React23.createElement(Select3.TriggerButton, {
|
|
2690
|
+
disabled: readonly
|
|
2691
|
+
}), /* @__PURE__ */ React23.createElement(Select3.Portal, null, /* @__PURE__ */ React23.createElement(Select3.Content, null, /* @__PURE__ */ React23.createElement(Select3.Viewport, null, hasDefault && /* @__PURE__ */ React23.createElement(Select3.Option, {
|
|
2692
|
+
value: sentinel
|
|
2693
|
+
}, defaultLabel), normalized.map((option) => /* @__PURE__ */ React23.createElement(Select3.Option, {
|
|
2694
|
+
key: option.value,
|
|
2695
|
+
value: option.value
|
|
2696
|
+
}, option.label ?? option.value))), /* @__PURE__ */ React23.createElement(Select3.Arrow, null))));
|
|
2264
2697
|
};
|
|
2265
2698
|
|
|
2266
2699
|
// src/components/ViewEditor/ViewEditor.tsx
|
|
2267
2700
|
import { RegistryContext } from "@effect-atom/atom-react";
|
|
2268
|
-
import * as
|
|
2701
|
+
import * as Array4 from "effect/Array";
|
|
2269
2702
|
import * as Match2 from "effect/Match";
|
|
2270
|
-
import * as
|
|
2271
|
-
import * as
|
|
2272
|
-
import
|
|
2273
|
-
import { Entity as Entity2, Feed, Filter as Filter2, Format as Format5, Obj as
|
|
2274
|
-
import { View } from "@dxos/echo";
|
|
2703
|
+
import * as Option6 from "effect/Option";
|
|
2704
|
+
import * as Schema5 from "effect/Schema";
|
|
2705
|
+
import React24, { forwardRef as forwardRef2, useCallback as useCallback18, useContext, useImperativeHandle, useMemo as useMemo12, useState as useState7 } from "react";
|
|
2706
|
+
import { Entity as Entity2, Feed, Filter as Filter2, Format as Format5, Obj as Obj6, Query, QueryAST, Ref as Ref6, View } from "@dxos/echo";
|
|
2275
2707
|
import { EchoSchema, isMutable, toJsonSchema } from "@dxos/echo/internal";
|
|
2276
|
-
import { invariant } from "@dxos/invariant";
|
|
2708
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2277
2709
|
import { useObject, useQuery as useQuery2 } from "@dxos/react-client/echo";
|
|
2278
|
-
import { IconButton as IconButton4, Input as
|
|
2710
|
+
import { IconButton as IconButton4, Input as Input14, Message, useTranslation as useTranslation12 } from "@dxos/react-ui";
|
|
2279
2711
|
import { QueryForm } from "@dxos/react-ui-components";
|
|
2280
2712
|
import { List as List2 } from "@dxos/react-ui-list";
|
|
2281
|
-
import { ProjectionModel, VIEW_FIELD_LIMIT, createEchoChangeCallback, getTypenameFromQuery } from "@dxos/schema";
|
|
2282
|
-
import { mx as
|
|
2283
|
-
|
|
2284
|
-
var
|
|
2713
|
+
import { ParentLabelAnnotation, ProjectionModel, VIEW_FIELD_LIMIT, createEchoChangeCallback, getTypenameFromQuery } from "@dxos/schema";
|
|
2714
|
+
import { mx as mx5, osTranslations as osTranslations2 } from "@dxos/ui-theme";
|
|
2715
|
+
import { translationKey as translationKey14 } from "#translations";
|
|
2716
|
+
var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
|
|
2717
|
+
var ViewEditor = /* @__PURE__ */ forwardRef2(({ classNames, schema, view, mode = "schema", registry, db, readonly, showHeading = false, types, tags, onQueryChanged, onDelete }, forwardedRef) => {
|
|
2285
2718
|
const atomRegistry = useContext(RegistryContext);
|
|
2286
2719
|
const schemaReadonly = !isMutable(schema);
|
|
2287
|
-
const { t } =
|
|
2288
|
-
const projectionModel =
|
|
2720
|
+
const { t } = useTranslation12(translationKey14);
|
|
2721
|
+
const projectionModel = useMemo12(() => {
|
|
2289
2722
|
const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
|
|
2290
2723
|
const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : void 0);
|
|
2291
2724
|
const model = new ProjectionModel({
|
|
@@ -2309,21 +2742,21 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
|
|
|
2309
2742
|
if (from._tag !== "scope") {
|
|
2310
2743
|
return void 0;
|
|
2311
2744
|
}
|
|
2312
|
-
return
|
|
2745
|
+
return Option6.fromNullable(from.scope.feeds).pipe(Option6.flatMap((feeds2) => Array4.head(feeds2)), Option6.map(String), Option6.getOrUndefined);
|
|
2313
2746
|
}), Match2.orElse(() => void 0));
|
|
2314
2747
|
const feeds = useQuery2(db, Filter2.type(Feed.Feed));
|
|
2315
|
-
const targetRef =
|
|
2748
|
+
const targetRef = useMemo12(() => {
|
|
2316
2749
|
if (!queueTarget) {
|
|
2317
2750
|
return void 0;
|
|
2318
2751
|
}
|
|
2319
2752
|
const feed = feeds.find((feed2) => Feed.getQueueDxn(feed2)?.toString() === queueTarget);
|
|
2320
|
-
return feed ?
|
|
2753
|
+
return feed ? Ref6.fromDXN(Entity2.getDXN(feed)) : void 0;
|
|
2321
2754
|
}, [
|
|
2322
2755
|
queueTarget,
|
|
2323
2756
|
feeds
|
|
2324
2757
|
]);
|
|
2325
|
-
const viewSchema =
|
|
2326
|
-
const base =
|
|
2758
|
+
const viewSchema = useMemo12(() => {
|
|
2759
|
+
const base = Schema5.Struct({
|
|
2327
2760
|
query: mode === "schema" ? Format5.URL.annotations({
|
|
2328
2761
|
title: "Record type"
|
|
2329
2762
|
}) : QueryAST.Query.annotations({
|
|
@@ -2331,18 +2764,19 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
|
|
|
2331
2764
|
})
|
|
2332
2765
|
});
|
|
2333
2766
|
if (mode === "tag") {
|
|
2334
|
-
return
|
|
2767
|
+
return Schema5.Struct({
|
|
2335
2768
|
...base.fields,
|
|
2336
|
-
|
|
2769
|
+
// TODO(wittjosiah): Replace Type.Feed with Dataset.Dataset when Ref.Ref supports unions.
|
|
2770
|
+
target: Ref6.Ref(Feed.Feed).pipe(Schema5.annotations({
|
|
2337
2771
|
title: "Target Feed"
|
|
2338
|
-
}))
|
|
2339
|
-
}).pipe(
|
|
2772
|
+
}), ParentLabelAnnotation.set(true), Schema5.optional)
|
|
2773
|
+
}).pipe(Schema5.mutable);
|
|
2340
2774
|
}
|
|
2341
|
-
return base.pipe(
|
|
2775
|
+
return base.pipe(Schema5.mutable);
|
|
2342
2776
|
}, [
|
|
2343
2777
|
mode
|
|
2344
2778
|
]);
|
|
2345
|
-
const viewValues =
|
|
2779
|
+
const viewValues = useMemo12(() => ({
|
|
2346
2780
|
query: mode === "schema" ? getTypenameFromQuery(view.query.ast) : view.query.ast,
|
|
2347
2781
|
target: targetRef
|
|
2348
2782
|
}), [
|
|
@@ -2350,7 +2784,7 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
|
|
|
2350
2784
|
view.query.ast,
|
|
2351
2785
|
targetRef
|
|
2352
2786
|
]);
|
|
2353
|
-
const fieldMap =
|
|
2787
|
+
const fieldMap = useMemo12(() => mode === "tag" ? customFields({
|
|
2354
2788
|
types,
|
|
2355
2789
|
tags
|
|
2356
2790
|
}) : void 0, [
|
|
@@ -2358,54 +2792,45 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
|
|
|
2358
2792
|
types,
|
|
2359
2793
|
tags
|
|
2360
2794
|
]);
|
|
2361
|
-
const handleUpdate =
|
|
2795
|
+
const handleUpdate = useCallback18((values) => {
|
|
2362
2796
|
const targetValue = values.target;
|
|
2363
|
-
let
|
|
2364
|
-
if (
|
|
2365
|
-
const
|
|
2366
|
-
const feed = feeds.find((feed2) =>
|
|
2797
|
+
let feedDXN;
|
|
2798
|
+
if (Ref6.isRef(targetValue)) {
|
|
2799
|
+
const targetDXN = targetValue.dxn.toString();
|
|
2800
|
+
const feed = feeds.find((feed2) => Obj6.getDXN(feed2).toString() === targetDXN);
|
|
2367
2801
|
if (feed) {
|
|
2368
|
-
|
|
2802
|
+
feedDXN = Feed.getQueueDxn(feed)?.toString();
|
|
2369
2803
|
}
|
|
2370
2804
|
}
|
|
2371
2805
|
const query = mode === "schema" ? Query.select(Filter2.typename(values.query)).ast : JSON.parse(JSON.stringify(values.query));
|
|
2372
|
-
onQueryChanged?.(query,
|
|
2806
|
+
onQueryChanged?.(query, feedDXN);
|
|
2373
2807
|
}, [
|
|
2374
2808
|
onQueryChanged,
|
|
2375
2809
|
mode,
|
|
2376
2810
|
feeds
|
|
2377
2811
|
]);
|
|
2378
|
-
const handleDelete =
|
|
2379
|
-
|
|
2380
|
-
F: __dxlog_file3,
|
|
2381
|
-
L: 174,
|
|
2382
|
-
S: void 0,
|
|
2383
|
-
A: [
|
|
2384
|
-
"!readonly",
|
|
2385
|
-
""
|
|
2386
|
-
]
|
|
2387
|
-
});
|
|
2812
|
+
const handleDelete = useCallback18((fieldId) => {
|
|
2813
|
+
invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 126, S: void 0, A: ["!readonly", ""] });
|
|
2388
2814
|
onDelete?.(fieldId);
|
|
2389
2815
|
}, [
|
|
2390
2816
|
onDelete,
|
|
2391
2817
|
readonly
|
|
2392
2818
|
]);
|
|
2393
|
-
return /* @__PURE__ */
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
}, schemaReadonly && !readonly && /* @__PURE__ */ React19.createElement(Message.Root, {
|
|
2819
|
+
return /* @__PURE__ */ React24.createElement("div", {
|
|
2820
|
+
className: mx5(classNames)
|
|
2821
|
+
}, schemaReadonly && !readonly && /* @__PURE__ */ React24.createElement(Message.Root, {
|
|
2397
2822
|
valence: "info",
|
|
2398
2823
|
classNames: "my-form-padding"
|
|
2399
|
-
}, /* @__PURE__ */
|
|
2824
|
+
}, /* @__PURE__ */ React24.createElement(Message.Title, null, t("system-schema.description"))), /* @__PURE__ */ React24.createElement(Form.Root, {
|
|
2400
2825
|
schema: viewSchema,
|
|
2401
2826
|
values: viewValues,
|
|
2402
2827
|
fieldMap,
|
|
2403
2828
|
db,
|
|
2404
2829
|
onValuesChanged: handleUpdate
|
|
2405
|
-
}, /* @__PURE__ */
|
|
2406
|
-
label: t("fields
|
|
2830
|
+
}, /* @__PURE__ */ React24.createElement(Form.FieldSet, null), /* @__PURE__ */ React24.createElement(FormFieldLabel, {
|
|
2831
|
+
label: t("fields.label"),
|
|
2407
2832
|
asChild: true
|
|
2408
|
-
}), /* @__PURE__ */
|
|
2833
|
+
}), /* @__PURE__ */ React24.createElement(FieldList, {
|
|
2409
2834
|
schema,
|
|
2410
2835
|
view,
|
|
2411
2836
|
registry,
|
|
@@ -2417,9 +2842,9 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
|
|
|
2417
2842
|
var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDelete }) => {
|
|
2418
2843
|
const atomRegistry = useContext(RegistryContext);
|
|
2419
2844
|
const schemaReadonly = !isMutable(schema);
|
|
2420
|
-
const { t } =
|
|
2845
|
+
const { t } = useTranslation12(translationKey14);
|
|
2421
2846
|
const [viewSnapshot] = useObject(view);
|
|
2422
|
-
const projectionModel =
|
|
2847
|
+
const projectionModel = useMemo12(() => {
|
|
2423
2848
|
const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
|
|
2424
2849
|
const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : void 0);
|
|
2425
2850
|
const model = new ProjectionModel({
|
|
@@ -2434,38 +2859,22 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
|
|
|
2434
2859
|
schema,
|
|
2435
2860
|
view
|
|
2436
2861
|
]);
|
|
2437
|
-
const [expandedField, setExpandedField] =
|
|
2438
|
-
const handleAdd =
|
|
2439
|
-
|
|
2440
|
-
F: __dxlog_file3,
|
|
2441
|
-
L: 239,
|
|
2442
|
-
S: void 0,
|
|
2443
|
-
A: [
|
|
2444
|
-
"!readonly",
|
|
2445
|
-
""
|
|
2446
|
-
]
|
|
2447
|
-
});
|
|
2862
|
+
const [expandedField, setExpandedField] = useState7();
|
|
2863
|
+
const handleAdd = useCallback18(() => {
|
|
2864
|
+
invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 181, S: void 0, A: ["!readonly", ""] });
|
|
2448
2865
|
const field = projectionModel.createFieldProjection();
|
|
2449
2866
|
setExpandedField(field.id);
|
|
2450
2867
|
}, [
|
|
2451
2868
|
projectionModel,
|
|
2452
2869
|
readonly
|
|
2453
2870
|
]);
|
|
2454
|
-
const handleToggleField =
|
|
2871
|
+
const handleToggleField = useCallback18((field) => {
|
|
2455
2872
|
setExpandedField((prevExpandedFieldId) => prevExpandedFieldId === field.id ? void 0 : field.id);
|
|
2456
2873
|
}, [
|
|
2457
2874
|
readonly
|
|
2458
2875
|
]);
|
|
2459
|
-
const handleDelete =
|
|
2460
|
-
|
|
2461
|
-
F: __dxlog_file3,
|
|
2462
|
-
L: 253,
|
|
2463
|
-
S: void 0,
|
|
2464
|
-
A: [
|
|
2465
|
-
"!readonly",
|
|
2466
|
-
""
|
|
2467
|
-
]
|
|
2468
|
-
});
|
|
2876
|
+
const handleDelete = useCallback18((fieldId) => {
|
|
2877
|
+
invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 194, S: void 0, A: ["!readonly", ""] });
|
|
2469
2878
|
if (fieldId === expandedField) {
|
|
2470
2879
|
setExpandedField(void 0);
|
|
2471
2880
|
}
|
|
@@ -2475,36 +2884,28 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
|
|
|
2475
2884
|
onDelete,
|
|
2476
2885
|
readonly
|
|
2477
2886
|
]);
|
|
2478
|
-
const handleMove =
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
L: 265,
|
|
2482
|
-
S: void 0,
|
|
2483
|
-
A: [
|
|
2484
|
-
"!readonly",
|
|
2485
|
-
""
|
|
2486
|
-
]
|
|
2487
|
-
});
|
|
2488
|
-
Obj3.change(view, (v) => {
|
|
2887
|
+
const handleMove = useCallback18((fromIndex, toIndex) => {
|
|
2888
|
+
invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 205, S: void 0, A: ["!readonly", ""] });
|
|
2889
|
+
Obj6.update(view, (view2) => {
|
|
2489
2890
|
const fields = [
|
|
2490
|
-
...
|
|
2891
|
+
...view2.projection.fields
|
|
2491
2892
|
];
|
|
2492
2893
|
const [moved] = fields.splice(fromIndex, 1);
|
|
2493
2894
|
fields.splice(toIndex, 0, moved);
|
|
2494
|
-
|
|
2895
|
+
view2.projection.fields = fields;
|
|
2495
2896
|
});
|
|
2496
2897
|
}, [
|
|
2497
2898
|
view,
|
|
2498
2899
|
readonly
|
|
2499
2900
|
]);
|
|
2500
|
-
const handleClose =
|
|
2501
|
-
const handleHide =
|
|
2901
|
+
const handleClose = useCallback18(() => setExpandedField(void 0), []);
|
|
2902
|
+
const handleHide = useCallback18((fieldId) => {
|
|
2502
2903
|
setExpandedField(void 0);
|
|
2503
2904
|
projectionModel.hideFieldProjection(fieldId);
|
|
2504
2905
|
}, [
|
|
2505
2906
|
projectionModel
|
|
2506
2907
|
]);
|
|
2507
|
-
const handleShow =
|
|
2908
|
+
const handleShow = useCallback18((property) => {
|
|
2508
2909
|
setExpandedField(void 0);
|
|
2509
2910
|
projectionModel.showFieldProjection(property);
|
|
2510
2911
|
}, [
|
|
@@ -2513,70 +2914,67 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
|
|
|
2513
2914
|
if (!viewSnapshot) {
|
|
2514
2915
|
return null;
|
|
2515
2916
|
}
|
|
2516
|
-
return /* @__PURE__ */
|
|
2917
|
+
return /* @__PURE__ */ React24.createElement(List2.Root, {
|
|
2517
2918
|
items: viewSnapshot.projection.fields,
|
|
2518
|
-
isItem:
|
|
2919
|
+
isItem: Schema5.is(View.FieldSchema),
|
|
2519
2920
|
getId: (field) => field.id,
|
|
2520
2921
|
onMove: readonly ? void 0 : handleMove,
|
|
2521
2922
|
readonly
|
|
2522
|
-
}, ({ items: fields }) => /* @__PURE__ */
|
|
2923
|
+
}, ({ items: fields }) => /* @__PURE__ */ React24.createElement(React24.Fragment, null, showHeading && /* @__PURE__ */ React24.createElement("h3", {
|
|
2523
2924
|
className: "text-sm"
|
|
2524
|
-
}, t("field
|
|
2925
|
+
}, t("field-path.label")), /* @__PURE__ */ React24.createElement("div", {
|
|
2525
2926
|
role: "list",
|
|
2526
2927
|
className: "grid grid-cols-[min-content_1fr_min-content_min-content_min-content]"
|
|
2527
2928
|
}, fields?.map((field) => {
|
|
2528
2929
|
const hidden = field.visible === false;
|
|
2529
|
-
return /* @__PURE__ */
|
|
2930
|
+
return /* @__PURE__ */ React24.createElement(List2.Item, {
|
|
2530
2931
|
key: field.id,
|
|
2531
2932
|
item: field,
|
|
2532
2933
|
classNames: "grid grid-cols-subgrid col-span-5",
|
|
2533
2934
|
"aria-expanded": expandedField === field.id
|
|
2534
|
-
}, /* @__PURE__ */
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
}, /* @__PURE__ */ React19.createElement(List2.ItemDragHandle, {
|
|
2935
|
+
}, /* @__PURE__ */ React24.createElement("div", {
|
|
2936
|
+
className: "grid grid-cols-subgrid col-span-5 rounded-xs cursor-pointer min-h-10 dx-hover"
|
|
2937
|
+
}, /* @__PURE__ */ React24.createElement(List2.ItemDragHandle, {
|
|
2538
2938
|
disabled: readonly || schemaReadonly
|
|
2539
|
-
}), /* @__PURE__ */
|
|
2939
|
+
}), /* @__PURE__ */ React24.createElement(List2.ItemTitle, {
|
|
2540
2940
|
classNames: hidden && "text-subdued",
|
|
2541
2941
|
onClick: () => handleToggleField(field)
|
|
2542
|
-
}, field.path), /* @__PURE__ */
|
|
2543
|
-
label: t(hidden ? "show
|
|
2942
|
+
}, field.path), /* @__PURE__ */ React24.createElement(List2.ItemIconButton, {
|
|
2943
|
+
label: t(hidden ? "show-field.label" : "hide-field.label"),
|
|
2544
2944
|
"data-testid": hidden ? "show-field-button" : "hide-field-button",
|
|
2545
2945
|
icon: hidden ? "ph--eye-closed--regular" : "ph--eye--regular",
|
|
2546
2946
|
autoHide: false,
|
|
2547
2947
|
disabled: readonly || !hidden && projectionModel.getFields().length <= 1,
|
|
2548
2948
|
onClick: () => hidden ? handleShow(field.path) : handleHide(field.id)
|
|
2549
|
-
}), !readonly && /* @__PURE__ */
|
|
2550
|
-
label: t("delete
|
|
2949
|
+
}), !readonly && /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement(List2.ItemDeleteButton, {
|
|
2950
|
+
label: t("delete-field.label"),
|
|
2551
2951
|
autoHide: false,
|
|
2552
2952
|
disabled: readonly || schemaReadonly || viewSnapshot.projection.fields.length <= 1,
|
|
2553
2953
|
onClick: () => handleDelete(field.id),
|
|
2554
2954
|
"data-testid": "field.delete"
|
|
2555
|
-
}), /* @__PURE__ */
|
|
2955
|
+
}), /* @__PURE__ */ React24.createElement(List2.ItemIconButton, {
|
|
2556
2956
|
iconOnly: true,
|
|
2557
2957
|
variant: "ghost",
|
|
2558
|
-
label: t("toggle
|
|
2958
|
+
label: t("toggle-expand.label", {
|
|
2559
2959
|
ns: osTranslations2
|
|
2560
2960
|
}),
|
|
2561
2961
|
icon: expandedField === field.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
2562
2962
|
onClick: () => handleToggleField(field),
|
|
2563
2963
|
"data-testid": "field.toggle"
|
|
2564
|
-
}))), expandedField === field.id && !readonly && /* @__PURE__ */
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
}, /* @__PURE__ */ React19.createElement(FieldEditor, {
|
|
2964
|
+
}))), expandedField === field.id && !readonly && /* @__PURE__ */ React24.createElement("div", {
|
|
2965
|
+
className: "col-span-full mt-1 mb-1 border border-separator rounded-md"
|
|
2966
|
+
}, /* @__PURE__ */ React24.createElement(FieldEditor, {
|
|
2568
2967
|
readonly: readonly || schemaReadonly,
|
|
2569
2968
|
registry,
|
|
2570
2969
|
projection: projectionModel,
|
|
2571
2970
|
field,
|
|
2572
2971
|
onSave: handleClose
|
|
2573
2972
|
})));
|
|
2574
|
-
})), !readonly && !expandedField && /* @__PURE__ */
|
|
2575
|
-
role: "none",
|
|
2973
|
+
})), !readonly && !expandedField && /* @__PURE__ */ React24.createElement("div", {
|
|
2576
2974
|
className: "my-form-padding"
|
|
2577
|
-
}, /* @__PURE__ */
|
|
2975
|
+
}, /* @__PURE__ */ React24.createElement(IconButton4, {
|
|
2578
2976
|
icon: "ph--plus--regular",
|
|
2579
|
-
label: t("add
|
|
2977
|
+
label: t("add-property-button.label"),
|
|
2580
2978
|
onClick: handleAdd,
|
|
2581
2979
|
disabled: viewSnapshot.projection.fields.length >= VIEW_FIELD_LIMIT,
|
|
2582
2980
|
classNames: "w-full"
|
|
@@ -2584,13 +2982,13 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
|
|
|
2584
2982
|
};
|
|
2585
2983
|
var customFields = ({ types, tags }) => ({
|
|
2586
2984
|
query: ({ type, readonly, label, getValue, onValueChange }) => {
|
|
2587
|
-
const handleChange =
|
|
2985
|
+
const handleChange = useCallback18((query) => onValueChange(type, query.ast), [
|
|
2588
2986
|
onValueChange
|
|
2589
2987
|
]);
|
|
2590
|
-
return /* @__PURE__ */
|
|
2988
|
+
return /* @__PURE__ */ React24.createElement(Input14.Root, null, /* @__PURE__ */ React24.createElement(FormFieldLabel, {
|
|
2591
2989
|
readonly,
|
|
2592
2990
|
label
|
|
2593
|
-
}), /* @__PURE__ */
|
|
2991
|
+
}), /* @__PURE__ */ React24.createElement(QueryForm, {
|
|
2594
2992
|
initialQuery: getValue(),
|
|
2595
2993
|
types,
|
|
2596
2994
|
tags,
|
|
@@ -2609,7 +3007,9 @@ export {
|
|
|
2609
3007
|
GeoPointField,
|
|
2610
3008
|
MarkdownField,
|
|
2611
3009
|
NumberField,
|
|
3010
|
+
ObjectForm,
|
|
2612
3011
|
ObjectPicker,
|
|
3012
|
+
ObjectProperties,
|
|
2613
3013
|
RefField,
|
|
2614
3014
|
SelectField,
|
|
2615
3015
|
SelectOptionField,
|
|
@@ -2619,15 +3019,18 @@ export {
|
|
|
2619
3019
|
TupleField,
|
|
2620
3020
|
ViewEditor,
|
|
2621
3021
|
cellClassesForFieldType,
|
|
3022
|
+
createSelectField,
|
|
3023
|
+
detectFieldType,
|
|
2622
3024
|
formatForDisplay,
|
|
2623
3025
|
formatForEditing,
|
|
2624
3026
|
getDefaultValue,
|
|
2625
3027
|
getFormProperties,
|
|
2626
3028
|
getRefProps,
|
|
3029
|
+
getSelectOptionsFromAst,
|
|
3030
|
+
omitHiddenFormFields,
|
|
2627
3031
|
omitId,
|
|
2628
3032
|
parseValue,
|
|
2629
3033
|
pathNotUniqueError,
|
|
2630
|
-
translations,
|
|
2631
3034
|
useFormContext,
|
|
2632
3035
|
useFormFieldState,
|
|
2633
3036
|
useFormHandler,
|