@dxos/react-ui-form 0.7.5-main.9d26e3a → 0.7.5-main.b19bfc8

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.
Files changed (86) hide show
  1. package/dist/lib/browser/index.mjs +1020 -571
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +1046 -608
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +1020 -571
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +1 -2
  11. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/ArrayField.d.ts +15 -0
  13. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -0
  14. package/dist/types/src/components/Form/Defaults.d.ts +6 -7
  15. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.d.ts +13 -16
  17. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/Form.stories.d.ts +2 -1
  19. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  20. package/dist/types/src/components/Form/FormActions.d.ts +6 -0
  21. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -0
  22. package/dist/types/src/components/Form/FormContent.d.ts +25 -0
  23. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -0
  24. package/dist/types/src/components/Form/FormContext.d.ts +23 -0
  25. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -0
  26. package/dist/types/src/components/Form/Input.d.ts +7 -8
  27. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +1 -3
  29. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  30. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +3 -0
  31. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -0
  32. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +7 -0
  33. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -0
  34. package/dist/types/src/components/Form/custom/TupleInput.d.ts +2 -4
  35. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  36. package/dist/types/src/components/Form/custom/index.d.ts +1 -0
  37. package/dist/types/src/components/Form/custom/index.d.ts.map +1 -1
  38. package/dist/types/src/components/Form/factory.d.ts +2 -2
  39. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  40. package/dist/types/src/components/Form/index.d.ts +2 -0
  41. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  42. package/dist/types/src/components/ViewEditor/Test.stories.d.ts +1 -2
  43. package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +2 -2
  45. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  46. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/deprecated/Form.d.ts +1 -2
  48. package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
  49. package/dist/types/src/components/deprecated/Form.stories.d.ts +1 -2
  50. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
  51. package/dist/types/src/components/deprecated/FormInput.d.ts +6 -1
  52. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
  53. package/dist/types/src/components/testing.d.ts +3 -3
  54. package/dist/types/src/components/testing.d.ts.map +1 -1
  55. package/dist/types/src/hooks/useForm.d.ts +11 -11
  56. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  57. package/dist/types/src/translations.d.ts +6 -0
  58. package/dist/types/src/translations.d.ts.map +1 -1
  59. package/dist/types/src/util/field.d.ts.map +1 -1
  60. package/dist/types/src/util/formatting.d.ts.map +1 -1
  61. package/dist/types/tsconfig.tsbuildinfo +1 -1
  62. package/package.json +29 -27
  63. package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
  64. package/src/components/FieldEditor/FieldEditor.tsx +58 -40
  65. package/src/components/Form/ArrayField.tsx +111 -0
  66. package/src/components/Form/Defaults.tsx +78 -34
  67. package/src/components/Form/Form.stories.tsx +15 -5
  68. package/src/components/Form/Form.tsx +51 -327
  69. package/src/components/Form/FormActions.tsx +41 -0
  70. package/src/components/Form/FormContent.tsx +170 -0
  71. package/src/components/Form/FormContext.tsx +92 -0
  72. package/src/components/Form/Input.tsx +5 -6
  73. package/src/components/Form/custom/GeoPointInput.tsx +44 -23
  74. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +58 -0
  75. package/src/components/Form/custom/SelectOptionsInput.tsx +190 -0
  76. package/src/components/Form/custom/TupleInput.tsx +5 -9
  77. package/src/components/Form/custom/index.ts +1 -0
  78. package/src/components/Form/factory.tsx +6 -7
  79. package/src/components/Form/index.ts +3 -0
  80. package/src/components/ViewEditor/ViewEditor.stories.tsx +25 -4
  81. package/src/components/ViewEditor/ViewEditor.tsx +16 -8
  82. package/src/components/deprecated/FormInput.tsx +20 -7
  83. package/src/hooks/useForm.ts +63 -49
  84. package/src/translations.ts +9 -1
  85. package/src/util/field.ts +19 -1
  86. package/src/util/formatting.ts +29 -1
@@ -29,14 +29,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var node_exports = {};
30
30
  __export(node_exports, {
31
31
  BooleanInput: () => BooleanInput,
32
+ DeprecatedFormContainer: () => DeprecatedFormContainer,
32
33
  DeprecatedFormInput: () => DeprecatedFormInput,
33
34
  FieldEditor: () => FieldEditor,
34
35
  Form: () => Form,
35
- FormActions: () => FormActions,
36
36
  GeoPointInput: () => GeoPointInput,
37
37
  InputHeader: () => InputHeader,
38
+ MarkdownInput: () => MarkdownInput,
38
39
  NumberInput: () => NumberInput,
39
40
  SelectInput: () => SelectInput,
41
+ SelectOptionInput: () => SelectOptionInput,
40
42
  TextInput: () => TextInput,
41
43
  TupleInput: () => TupleInput,
42
44
  ViewEditor: () => ViewEditor,
@@ -47,53 +49,78 @@ __export(node_exports, {
47
49
  parseValue: () => parseValue,
48
50
  pathNotUniqueError: () => pathNotUniqueError,
49
51
  translations: () => translations_default,
50
- useForm: () => useForm
52
+ useForm: () => useForm,
53
+ useFormValues: () => useFormValues
51
54
  });
52
55
  module.exports = __toCommonJS(node_exports);
53
56
  var import_react = __toESM(require("react"));
54
57
  var import_react_ui = require("@dxos/react-ui");
58
+ var import_react_ui_theme = require("@dxos/react-ui-theme");
55
59
  var import_react2 = __toESM(require("react"));
56
60
  var import_echo_schema = require("@dxos/echo-schema");
57
61
  var import_log = require("@dxos/log");
58
62
  var import_react_ui2 = require("@dxos/react-ui");
59
63
  var import_schema = require("@dxos/schema");
60
64
  var import_react3 = __toESM(require("react"));
65
+ var import_debug = require("@dxos/debug");
66
+ var import_echo_schema2 = require("@dxos/echo-schema");
67
+ var import_effect = require("@dxos/effect");
68
+ var import_react4 = require("react");
69
+ var import_echo_schema3 = require("@dxos/echo-schema");
70
+ var import_effect2 = require("@dxos/effect");
71
+ var import_invariant = require("@dxos/invariant");
72
+ var import_log2 = require("@dxos/log");
73
+ var import_schema2 = require("@dxos/schema");
74
+ var import_react5 = __toESM(require("react"));
75
+ var import_echo_schema4 = require("@dxos/echo-schema");
61
76
  var import_react_ui3 = require("@dxos/react-ui");
62
77
  var import_util = require("@dxos/util");
63
- var import_react4 = __toESM(require("react"));
78
+ var import_react6 = __toESM(require("react"));
64
79
  var import_react_ui4 = require("@dxos/react-ui");
65
- var import_react_ui_theme = require("@dxos/react-ui-theme");
66
- var import_react5 = __toESM(require("react"));
67
- var import_react_ui5 = require("@dxos/react-ui");
68
80
  var import_react_ui_theme2 = require("@dxos/react-ui-theme");
69
- var import_util2 = require("@dxos/util");
70
- var import_react6 = __toESM(require("react"));
71
- var import_react_ui6 = require("@dxos/react-ui");
72
- var import_effect = require("effect");
73
- var import_String = require("effect/String");
74
81
  var import_react7 = __toESM(require("react"));
75
- var import_echo_schema2 = require("@dxos/echo-schema");
76
- var import_effect2 = require("@dxos/effect");
77
- var import_log2 = require("@dxos/log");
78
- var import_react_ui7 = require("@dxos/react-ui");
82
+ var import_keys = require("@dxos/keys");
83
+ var import_react_ui5 = require("@dxos/react-ui");
84
+ var import_react_ui_list = require("@dxos/react-ui-list");
85
+ var import_react_ui_pickers = require("@dxos/react-ui-pickers");
79
86
  var import_react_ui_theme3 = require("@dxos/react-ui-theme");
80
- var import_schema2 = require("@dxos/schema");
81
- var import_util3 = require("@dxos/util");
82
- var import_echo_schema3 = require("@dxos/echo-schema");
83
- var import_react8 = require("react");
84
- var import_echo_schema4 = require("@dxos/echo-schema");
85
- var import_invariant = require("@dxos/invariant");
86
- var import_log3 = require("@dxos/log");
87
- var import_schema3 = require("@dxos/schema");
87
+ var import_react8 = __toESM(require("react"));
88
+ var import_react_ui6 = require("@dxos/react-ui");
89
+ var import_react_ui_theme4 = require("@dxos/react-ui-theme");
90
+ var import_util2 = require("@dxos/util");
88
91
  var import_react9 = __toESM(require("react"));
89
- var import_echo_schema5 = require("@dxos/echo-schema");
92
+ var import_react_ui7 = require("@dxos/react-ui");
93
+ var import_react10 = __toESM(require("react"));
94
+ var import_react_ui_theme5 = require("@dxos/react-ui-theme");
95
+ var import_react11 = __toESM(require("react"));
90
96
  var import_react_ui8 = require("@dxos/react-ui");
91
- var import_react_ui_list = require("@dxos/react-ui-list");
92
- var import_react_ui_theme4 = require("@dxos/react-ui-theme");
93
- var import_schema4 = require("@dxos/schema");
94
- var import_util4 = require("@dxos/util");
97
+ var import_react_ui_theme6 = require("@dxos/react-ui-theme");
98
+ var import_effect3 = require("effect");
99
+ var import_String = require("effect/String");
100
+ var import_react12 = __toESM(require("react"));
101
+ var import_echo_schema5 = require("@dxos/echo-schema");
102
+ var import_effect4 = require("@dxos/effect");
103
+ var import_react_ui_theme7 = require("@dxos/react-ui-theme");
104
+ var import_schema3 = require("@dxos/schema");
105
+ var import_util3 = require("@dxos/util");
106
+ var import_effect5 = require("effect");
107
+ var import_String2 = require("effect/String");
108
+ var import_react13 = __toESM(require("react"));
95
109
  var import_echo_schema6 = require("@dxos/echo-schema");
110
+ var import_effect6 = require("@dxos/effect");
111
+ var import_invariant2 = require("@dxos/invariant");
112
+ var import_react_ui9 = require("@dxos/react-ui");
113
+ var import_react_ui_theme8 = require("@dxos/react-ui-theme");
114
+ var import_schema4 = require("@dxos/schema");
96
115
  var import_echo_schema7 = require("@dxos/echo-schema");
116
+ var import_react14 = __toESM(require("react"));
117
+ var import_echo_schema8 = require("@dxos/echo-schema");
118
+ var import_react_ui10 = require("@dxos/react-ui");
119
+ var import_react_ui_list2 = require("@dxos/react-ui-list");
120
+ var import_react_ui_theme9 = require("@dxos/react-ui-theme");
121
+ var import_schema5 = require("@dxos/schema");
122
+ var import_echo_schema9 = require("@dxos/echo-schema");
123
+ var import_echo_schema10 = require("@dxos/echo-schema");
97
124
  var translationKey = "react-ui-form";
98
125
  var translations_default = [
99
126
  {
@@ -124,12 +151,13 @@ var translations_default = [
124
151
  "format hostname": "Hostname",
125
152
  "format integer": "Integer",
126
153
  "format json": "JSON",
127
- "format latlng": "LatLng",
154
+ "format latlng": "Geopoint",
128
155
  "format markdown": "Markdown",
129
156
  "format percent": "Percent",
130
157
  "format ref": "Reference",
131
158
  "format regex": "RegExp",
132
159
  "format string": "String",
160
+ "format single-select": "Select",
133
161
  "format text": "Long text",
134
162
  "format time": "Time",
135
163
  "format timestamp": "Timestamp",
@@ -139,11 +167,26 @@ var translations_default = [
139
167
  "format uuid": "UUID",
140
168
  // Placeholders
141
169
  "placeholder latitude": "Latitude",
142
- "placeholder longitude": "Longitude"
170
+ "placeholder longitude": "Longitude",
171
+ // SelectOptionsInput
172
+ "select option label": "Label",
173
+ "select option label placeholder": "Option label",
174
+ "select option color": "Color",
175
+ "select option delete": "Delete",
176
+ "select option add": "Add option"
143
177
  }
144
178
  }
145
179
  }
146
180
  ];
181
+ var DeprecatedFormContainer = ({ children, classNames }) => {
182
+ return /* @__PURE__ */ import_react.default.createElement("div", {
183
+ role: "none",
184
+ className: "w-full p-4 justify-center overflow-x-hidden overflow-y-auto"
185
+ }, /* @__PURE__ */ import_react.default.createElement("div", {
186
+ role: "form",
187
+ className: (0, import_react_ui_theme.mx)("flex flex-col", import_react_ui_theme.textBlockWidth, classNames)
188
+ }, children));
189
+ };
147
190
  var DeprecatedFormInput = ({ label, description, secondary, children }) => {
148
191
  const primary = /* @__PURE__ */ import_react.default.createElement("div", {
149
192
  role: "none",
@@ -152,185 +195,48 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
152
195
  role: "none",
153
196
  className: "flex flex-col w-full"
154
197
  }, /* @__PURE__ */ import_react.default.createElement(import_react_ui.Input.Label, {
155
- classNames: "flex min-h-[40px] items-center"
198
+ classNames: "flex min-bs-[--rail-action] items-center",
199
+ style: {
200
+ fontSize: "unset"
201
+ }
156
202
  }, label), description && /* @__PURE__ */ import_react.default.createElement(import_react_ui.Input.DescriptionAndValidation, {
157
203
  classNames: "mbs-0.5"
158
204
  }, /* @__PURE__ */ import_react.default.createElement(import_react_ui.Input.Description, null, description))), /* @__PURE__ */ import_react.default.createElement("div", {
159
205
  role: "none"
160
206
  }, /* @__PURE__ */ import_react.default.createElement("div", {
161
207
  role: "none",
162
- className: "flex min-h-[40px] items-center"
208
+ className: "flex min-bs-[--rail-action] items-center"
163
209
  }, children))));
164
210
  if (secondary) {
165
211
  return /* @__PURE__ */ import_react.default.createElement("div", {
166
- role: "none",
167
- className: "flex flex-col w-full"
212
+ role: "none"
168
213
  }, primary, secondary);
169
214
  }
170
215
  return primary;
171
216
  };
172
- var InputHeader = ({ children, error }) => {
173
- return /* @__PURE__ */ import_react4.default.createElement("div", {
174
- role: "none",
175
- className: "flex justify-between items-center mb-1"
176
- }, children, error && /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Root, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Trigger, {
177
- asChild: true
178
- }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Icon, {
179
- icon: "ph--warning--regular",
180
- size: 4,
181
- classNames: import_react_ui_theme.errorText
182
- })), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Content, {
183
- side: "bottom"
184
- }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Arrow, null), error)));
185
- };
186
- var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
187
- const { t } = (0, import_react_ui3.useTranslation)(translationKey);
188
- const { status, error } = getStatus?.(property);
189
- const [lng = 0, lat = 0] = getValue2(property) ?? [];
190
- return /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.Root, {
191
- validationValence: status
192
- }, /* @__PURE__ */ import_react3.default.createElement(InputHeader, {
193
- error
194
- }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.Label, null, label)), /* @__PURE__ */ import_react3.default.createElement("div", {
195
- className: "grid grid-cols-2 gap-2"
196
- }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.TextInput, {
197
- type: "number",
198
- disabled,
199
- placeholder: t("placeholder longitude"),
200
- value: lng,
201
- onChange: (event) => onValueChange(property, type, [
202
- lat,
203
- (0, import_util.safeParseFloat)(event.target.value, 0)
204
- ]),
205
- onBlur
206
- }), /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.TextInput, {
207
- type: "number",
208
- disabled,
209
- placeholder: t("placeholder latitude"),
210
- value: lat,
211
- onChange: (event) => onValueChange(property, type, [
212
- (0, import_util.safeParseFloat)(event.target.value, 0),
213
- lng
214
- ]),
215
- onBlur
216
- })));
217
- };
218
- var gridCols = [
219
- "grid-cols-1",
220
- "grid-cols-2",
221
- "grid-cols-3",
222
- "grid-cols-4"
223
- ];
224
- var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
225
- const { status, error } = getStatus?.(property);
226
- const values = getValue2(property) ?? {};
227
- return /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Root, {
228
- validationValence: status
229
- }, /* @__PURE__ */ import_react5.default.createElement(InputHeader, {
230
- error
231
- }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Label, null, label)), /* @__PURE__ */ import_react5.default.createElement("div", {
232
- className: (0, import_react_ui_theme2.mx)("grid gap-2", gridCols[binding.length - 1])
233
- }, binding.map((prop) => /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.TextInput, {
234
- key: prop,
235
- type: "number",
236
- disabled,
237
- value: values[prop],
238
- onChange: (event) => onValueChange(property, type, {
239
- ...values,
240
- [prop]: (0, import_util2.safeParseFloat)(event.target.value, 0)
241
- }),
242
- onBlur
243
- }))));
244
- };
245
- var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
246
- const { status, error } = getStatus?.(property);
247
- return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
248
- validationValence: status
249
- }, !inputOnly && /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
250
- error
251
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.TextInput, {
252
- disabled,
253
- placeholder,
254
- value: getValue2(property) ?? "",
255
- onChange: (event) => onValueChange(property, type, event.target.value),
256
- onBlur
257
- }), inputOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Validation, null, error));
258
- };
259
- var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
260
- const { status, error } = getStatus?.(property);
261
- return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
262
- validationValence: status
263
- }, !inputOnly && /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
264
- error
265
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.TextInput, {
266
- type: "number",
267
- disabled,
268
- placeholder,
269
- value: getValue2(property) ?? 0,
270
- onChange: (event) => onValueChange(property, type, event.target.value),
271
- onBlur
272
- }), inputOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.DescriptionAndValidation, null, error));
273
- };
274
- var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue: getValue2, onValueChange }) => {
275
- const { status, error } = getStatus?.(property);
276
- return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
277
- validationValence: status
278
- }, !inputOnly && /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
279
- error
280
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Switch, {
281
- checked: getValue2(property),
282
- onCheckedChange: (value) => onValueChange(property, type, value)
283
- }), inputOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.DescriptionAndValidation, null, error));
284
- };
285
- var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue2, onValueChange }) => {
286
- const { status, error } = getStatus?.(property);
287
- return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
288
- validationValence: status
289
- }, !inputOnly && /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
290
- error
291
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Root, {
292
- value: getValue2(property),
293
- onValueChange: (value) => onValueChange(property, type, value)
294
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.TriggerButton, {
295
- classNames: "is-full",
296
- disabled,
297
- placeholder
298
- }), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Portal, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Content, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Viewport, null, options?.map(({ value, label: label2 }) => (
299
- // NOTE: Numeric values are converted to and from strings.
300
- /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Option, {
301
- key: String(value),
302
- value: String(value)
303
- }, label2 ?? String(value))
304
- )))))), inputOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.DescriptionAndValidation, null, error));
305
- };
306
- var getInputComponent = (type, format) => {
307
- switch (format) {
308
- case import_echo_schema3.FormatEnum.LatLng:
309
- return GeoPointInput;
310
- }
311
- switch (type) {
312
- case "string":
313
- return TextInput;
314
- case "number":
315
- return NumberInput;
316
- case "boolean":
317
- return BooleanInput;
318
- }
319
- };
320
217
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
321
218
  var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
322
- const [values, setValues] = (0, import_react8.useState)(initialValues);
323
- (0, import_react8.useEffect)(() => {
219
+ (0, import_invariant.invariant)(import_effect2.AST.isTypeLiteral(schema.ast), void 0, {
220
+ F: __dxlog_file,
221
+ L: 92,
222
+ S: void 0,
223
+ A: [
224
+ "AST.isTypeLiteral(schema.ast)",
225
+ ""
226
+ ]
227
+ });
228
+ const [values, setValues] = (0, import_react4.useState)(initialValues);
229
+ (0, import_react4.useEffect)(() => {
324
230
  setValues(initialValues);
325
231
  }, [
326
232
  initialValues
327
233
  ]);
328
- const [touched, setTouched] = (0, import_react8.useState)(createKeySet(initialValues, false));
329
- const [changed, setChanged] = (0, import_react8.useState)(createKeySet(initialValues, false));
330
- const [errors, setErrors] = (0, import_react8.useState)({});
331
- const [saving, setSaving] = (0, import_react8.useState)(false);
332
- const validate = (0, import_react8.useCallback)((values2) => {
333
- let errors2 = (0, import_schema3.validateSchema)(schema, values2) ?? [];
234
+ const [touched, setTouched] = (0, import_react4.useState)(createKeySet(initialValues, false));
235
+ const [changed, setChanged] = (0, import_react4.useState)(createKeySet(initialValues, false));
236
+ const [errors, setErrors] = (0, import_react4.useState)({});
237
+ const [saving, setSaving] = (0, import_react4.useState)(false);
238
+ const validate = (0, import_react4.useCallback)((values2) => {
239
+ let errors2 = (0, import_schema2.validateSchema)(schema, values2) ?? [];
334
240
  if (errors2.length === 0 && onValidate) {
335
241
  const validatedValues = values2;
336
242
  errors2 = onValidate(validatedValues) ?? [];
@@ -342,11 +248,11 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
342
248
  schema,
343
249
  onValidate
344
250
  ]);
345
- const [schemaDirty, setSchemaDirty] = (0, import_react8.useState)(false);
346
- (0, import_react8.useEffect)(() => setSchemaDirty(true), [
251
+ const [schemaDirty, setSchemaDirty] = (0, import_react4.useState)(false);
252
+ (0, import_react4.useEffect)(() => setSchemaDirty(true), [
347
253
  schema
348
254
  ]);
349
- (0, import_react8.useEffect)(() => {
255
+ (0, import_react4.useEffect)(() => {
350
256
  if (schemaDirty) {
351
257
  validate(values);
352
258
  setSchemaDirty(false);
@@ -355,13 +261,18 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
355
261
  values,
356
262
  schemaDirty
357
263
  ]);
358
- const canSave = (0, import_react8.useMemo)(() => !saving && Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
359
- values,
264
+ const formIsValid = (0, import_react4.useMemo)(() => {
265
+ return Object.keys(errors).length === 0;
266
+ }, [
267
+ errors
268
+ ]);
269
+ const canSave = (0, import_react4.useMemo)(() => !saving && // Check if any error paths that are touched have errors
270
+ !Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
360
271
  touched,
361
272
  errors,
362
273
  saving
363
274
  ]);
364
- const handleSave = (0, import_react8.useCallback)(async () => {
275
+ const handleSave = (0, import_react4.useCallback)(async () => {
365
276
  if (validate(values)) {
366
277
  setSaving(true);
367
278
  try {
@@ -378,38 +289,42 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
378
289
  onSave,
379
290
  changed
380
291
  ]);
381
- const getStatus = (0, import_react8.useCallback)((property) => ({
382
- status: errors[property] ? "error" : void 0,
383
- error: errors[property] ? errors[property] : void 0
384
- }), [
385
- touched,
292
+ const getStatus = (0, import_react4.useCallback)((path) => {
293
+ const jsonPath = Array.isArray(path) ? (0, import_effect2.createJsonPath)(path) : path;
294
+ const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
295
+ return {
296
+ status: matchingError ? "error" : void 0,
297
+ error: matchingError ? matchingError[1] : void 0
298
+ };
299
+ }, [
386
300
  errors
387
301
  ]);
388
- const getFormValue = (property) => {
389
- return (0, import_echo_schema4.getValue)(values, property);
302
+ const getFormValue = (path) => {
303
+ return (0, import_echo_schema3.getValue)(values, (0, import_effect2.createJsonPath)(path));
390
304
  };
391
- const onValueChange = (property, type, value) => {
305
+ const onValueChange = (path, type, value) => {
306
+ const jsonPath = (0, import_effect2.createJsonPath)(path);
392
307
  let parsedValue = value;
393
308
  try {
394
309
  if (type === "number") {
395
310
  parsedValue = parseFloat(value) || 0;
396
311
  }
397
312
  } catch (err) {
398
- import_log3.log.catch(err, void 0, {
313
+ import_log2.log.catch(err, void 0, {
399
314
  F: __dxlog_file,
400
- L: 178,
315
+ L: 198,
401
316
  S: void 0,
402
317
  C: (f, a) => f(...a)
403
318
  });
404
319
  parsedValue = void 0;
405
320
  }
406
321
  const newValues = {
407
- ...(0, import_echo_schema4.setValue)(values, property, parsedValue)
322
+ ...(0, import_echo_schema3.setValue)(values, jsonPath, parsedValue)
408
323
  };
409
324
  setValues(newValues);
410
325
  setChanged((prev) => ({
411
326
  ...prev,
412
- [property]: true
327
+ [jsonPath]: true
413
328
  }));
414
329
  onValuesChanged?.(newValues);
415
330
  const isValid = validate(newValues);
@@ -419,15 +334,12 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
419
334
  });
420
335
  }
421
336
  };
422
- const onBlur = (0, import_react8.useCallback)((event) => {
423
- const { name } = event.target;
337
+ const onTouched = (0, import_react4.useCallback)((path) => {
338
+ const jsonPath = (0, import_effect2.createJsonPath)(path);
424
339
  setTouched((touched2) => ({
425
340
  ...touched2,
426
- [name]: true
341
+ [jsonPath]: true
427
342
  }));
428
- if (event.relatedTarget?.getAttribute("type") === "submit") {
429
- setTouched(createKeySet(values, true));
430
- }
431
343
  validate(values);
432
344
  }, [
433
345
  validate,
@@ -441,17 +353,18 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
441
353
  changed,
442
354
  canSave,
443
355
  handleSave,
356
+ formIsValid,
444
357
  // Field utils.
445
358
  getStatus,
446
359
  getValue: getFormValue,
447
360
  onValueChange,
448
- onBlur
361
+ onTouched
449
362
  };
450
363
  };
451
364
  var createKeySet = (obj, value) => {
452
365
  (0, import_invariant.invariant)(obj, void 0, {
453
366
  F: __dxlog_file,
454
- L: 229,
367
+ L: 241,
455
368
  S: void 0,
456
369
  A: [
457
370
  "obj",
@@ -465,302 +378,763 @@ var createKeySet = (obj, value) => {
465
378
  };
466
379
  var flatMap = (errors) => {
467
380
  return errors.reduce((result, { path, message }) => {
468
- if (!(path in result)) {
469
- result[path] = message;
381
+ const jsonPath = (0, import_effect2.fromEffectValidationPath)(path);
382
+ if (!(jsonPath in result)) {
383
+ result[jsonPath] = message;
470
384
  }
471
385
  return result;
472
386
  }, {});
473
387
  };
474
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
475
- var padding = "px-2";
476
- var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, Custom }) => {
477
- const onValid = (0, import_react7.useMemo)(() => autoSave ? onSave : void 0, [
478
- autoSave,
479
- onSave
480
- ]);
481
- const { canSave, values, errors, handleSave, ...inputProps } = useForm({
482
- schema,
483
- initialValues,
484
- onValuesChanged,
485
- onValidate,
486
- onValid,
487
- onSave
488
- });
489
- const properties = (0, import_react7.useMemo)(() => {
490
- const props = (0, import_schema2.getSchemaProperties)(schema.ast, values);
491
- const filtered = filter ? filter(props) : props;
492
- const findIndex = (props2, prop) => {
493
- const idx = props2.findIndex((p) => p === prop);
494
- return idx === -1 ? Infinity : idx;
388
+ var FormContext = /* @__PURE__ */ (0, import_react3.createContext)(void 0);
389
+ var useFormContext = () => {
390
+ return (0, import_react3.useContext)(FormContext) ?? (0, import_debug.raise)(new Error("Missing FormContext"));
391
+ };
392
+ var useFormValues = (path = []) => {
393
+ const { values: formValues } = useFormContext();
394
+ const jsonPath = (0, import_effect.createJsonPath)(path);
395
+ return (0, import_echo_schema2.getValue)(formValues, jsonPath);
396
+ };
397
+ var useInputProps = (path = []) => {
398
+ const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
399
+ return {
400
+ getStatus: () => getStatus(path),
401
+ getValue: () => getFormValue(path),
402
+ onValueChange: (type, value) => onValueChange(path, type, value),
403
+ onBlur: () => onTouched(path)
404
+ };
405
+ };
406
+ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
407
+ const form = useForm(formOptions);
408
+ (0, import_react3.useEffect)(() => {
409
+ if (!formRef?.current) {
410
+ return;
411
+ }
412
+ const handleKeyDown = (event) => {
413
+ const keyIsEnter = event.key === "Enter";
414
+ const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
415
+ const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
416
+ const inputOptOut = event.target.hasAttribute("data-no-submit");
417
+ const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
418
+ const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
419
+ if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
420
+ if (!autoSave && form.canSave) {
421
+ form.handleSave();
422
+ }
423
+ if (autoSave && form.formIsValid) {
424
+ event.target.blur();
425
+ }
426
+ }
495
427
  };
496
- return sort ? filtered.sort(({ name: a }, { name: b }) => findIndex(sort, a) - findIndex(sort, b)) : filtered;
428
+ const formElement = formRef.current;
429
+ formElement.addEventListener("keydown", handleKeyDown);
430
+ return () => formElement.removeEventListener("keydown", handleKeyDown);
497
431
  }, [
498
- schema,
499
- filter,
500
- values
432
+ formRef,
433
+ form.canSave,
434
+ form.formIsValid,
435
+ form.handleSave,
436
+ autoSave
437
+ ]);
438
+ return /* @__PURE__ */ import_react3.default.createElement(FormContext.Provider, {
439
+ value: form
440
+ }, children);
441
+ };
442
+ var InputHeader = ({ children, error }) => {
443
+ return /* @__PURE__ */ import_react6.default.createElement("div", {
444
+ role: "none",
445
+ className: "flex justify-between items-center mb-1"
446
+ }, children, error && /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Root, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Trigger, {
447
+ asChild: true
448
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Icon, {
449
+ icon: "ph--warning--regular",
450
+ size: 4,
451
+ classNames: import_react_ui_theme2.errorText
452
+ })), /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Content, {
453
+ side: "bottom"
454
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Arrow, null), error)));
455
+ };
456
+ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
457
+ const { t } = (0, import_react_ui3.useTranslation)(translationKey);
458
+ const { status, error } = getStatus();
459
+ const geoPoint = (0, import_react5.useMemo)(() => getValue3() ?? [
460
+ 0,
461
+ 0
462
+ ], [
463
+ getValue3
464
+ ]);
465
+ const geoLocation = (0, import_react5.useMemo)(() => import_echo_schema4.GeoLocation.fromGeoPoint(geoPoint), [
466
+ geoPoint
467
+ ]);
468
+ const [longitudeText, setLongitudeText] = (0, import_react5.useState)(geoLocation.longitude?.toString());
469
+ const [latitudeText, setLatitudeText] = (0, import_react5.useState)(geoLocation.latitude?.toString());
470
+ (0, import_react5.useEffect)(() => {
471
+ const location = import_echo_schema4.GeoLocation.fromGeoPoint(geoPoint);
472
+ setLongitudeText(location.longitude.toString());
473
+ setLatitudeText(location.latitude.toString());
474
+ }, [
475
+ geoPoint
476
+ ]);
477
+ const handleCoordinateChange = (0, import_react5.useCallback)((coordinateType, setText) => (event) => {
478
+ const inputText = event.target.value;
479
+ setText(inputText);
480
+ if (inputText !== "" && inputText !== "-") {
481
+ const coord = (0, import_util.safeParseFloat)(inputText);
482
+ if (coord !== void 0 && !isNaN(coord)) {
483
+ const currentLocation = import_echo_schema4.GeoLocation.fromGeoPoint(getValue3() ?? [
484
+ 0,
485
+ 0
486
+ ]);
487
+ const newLocation = {
488
+ ...currentLocation,
489
+ [coordinateType]: coord
490
+ };
491
+ const newValue = import_echo_schema4.GeoLocation.toGeoPoint(newLocation);
492
+ onValueChange(type, newValue);
493
+ }
494
+ }
495
+ }, [
496
+ getValue3,
497
+ onValueChange,
498
+ type
501
499
  ]);
500
+ return /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.Root, {
501
+ validationValence: status
502
+ }, /* @__PURE__ */ import_react5.default.createElement(InputHeader, {
503
+ error
504
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.Label, null, label)), /* @__PURE__ */ import_react5.default.createElement("div", {
505
+ role: "none",
506
+ className: "grid grid-cols-2 gap-2"
507
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.TextInput, {
508
+ type: "text",
509
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
510
+ disabled,
511
+ placeholder: t("placeholder latitude"),
512
+ value: latitudeText,
513
+ onChange: handleCoordinateChange("latitude", setLatitudeText),
514
+ onBlur
515
+ }), /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.TextInput, {
516
+ type: "text",
517
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
518
+ disabled,
519
+ placeholder: t("placeholder longitude"),
520
+ value: longitudeText,
521
+ onChange: handleCoordinateChange("longitude", setLongitudeText),
522
+ onBlur
523
+ })));
524
+ };
525
+ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
526
+ const [selected, setSelectedId] = (0, import_react7.useState)(null);
527
+ const [isNewOption, setIsNewOption] = (0, import_react7.useState)(false);
528
+ const inputRef = (0, import_react7.useRef)(null);
529
+ const { t } = (0, import_react_ui5.useTranslation)(translationKey);
530
+ const { status, error } = getStatus();
531
+ const options = getValue3();
502
532
  (0, import_react7.useEffect)(() => {
503
- if (errors && Object.keys(errors).length) {
504
- import_log2.log.warn("validation", {
505
- errors
506
- }, {
507
- F: __dxlog_file2,
508
- L: 99,
509
- S: void 0,
510
- C: (f, a) => f(...a)
511
- });
533
+ if (options === void 0) {
534
+ onValueChange(type, []);
512
535
  }
513
536
  }, [
514
- errors
537
+ options,
538
+ onValueChange,
539
+ type
515
540
  ]);
516
- return /* @__PURE__ */ import_react7.default.createElement("div", {
517
- role: "form",
518
- className: (0, import_react_ui_theme3.mx)("flex flex-col w-full gap-2 py-2", classNames),
519
- "data-testid": testId
520
- }, properties.map((property) => {
521
- const { ast, name, type, format, title, description, examples, options, array } = property;
522
- const key = [
523
- ...path,
524
- name
541
+ const randomHue = () => {
542
+ const usedHues = new Set(options?.map((option) => option.color) ?? []);
543
+ const unusedHues = import_react_ui_theme3.hues.filter((hue) => !usedHues.has(hue));
544
+ if (unusedHues.length > 0) {
545
+ return unusedHues[Math.floor(Math.random() * unusedHues.length)];
546
+ }
547
+ const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
548
+ const availableHues = import_react_ui_theme3.hues.filter((hue) => !lastThree.has(hue));
549
+ return availableHues[Math.floor(Math.random() * availableHues.length)] ?? import_react_ui_theme3.hues[Math.floor(Math.random() * import_react_ui_theme3.hues.length)];
550
+ };
551
+ const handleAdd = (0, import_react7.useCallback)(() => {
552
+ const newId = import_keys.PublicKey.random().truncate();
553
+ const newOption = {
554
+ id: newId,
555
+ title: "",
556
+ color: randomHue()
557
+ };
558
+ onValueChange(type, [
559
+ ...options ?? [],
560
+ newOption
561
+ ]);
562
+ setSelectedId(newId);
563
+ setIsNewOption(true);
564
+ }, [
565
+ options,
566
+ type,
567
+ onValueChange
568
+ ]);
569
+ const handleDelete = (0, import_react7.useCallback)((id) => {
570
+ const newOptions = options?.filter((option) => option.id !== id) ?? [];
571
+ onValueChange(type, newOptions);
572
+ setSelectedId(null);
573
+ }, [
574
+ options,
575
+ type,
576
+ onValueChange
577
+ ]);
578
+ const handleMove = (0, import_react7.useCallback)((from, to) => {
579
+ if (!options) {
580
+ return;
581
+ }
582
+ const newOptions = [
583
+ ...options
525
584
  ];
526
- const label = title ?? (0, import_effect.pipe)(name, import_String.capitalize);
527
- const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
528
- let InputComponent = Custom?.[key.join(".")];
529
- if (!InputComponent) {
530
- if (options) {
531
- return /* @__PURE__ */ import_react7.default.createElement("div", {
532
- key: name,
533
- role: "none",
534
- className: padding
535
- }, /* @__PURE__ */ import_react7.default.createElement(SelectInput, {
536
- type,
537
- format,
538
- property: name,
539
- disabled: readonly,
540
- label,
541
- options: options.map((option) => ({
542
- value: option,
543
- label: String(option)
544
- })),
545
- placeholder,
546
- ...inputProps
547
- }));
548
- }
549
- InputComponent = getInputComponent(type, format);
550
- if (array) {
551
- return /* @__PURE__ */ import_react7.default.createElement(ArrayField, {
552
- key: name,
553
- name,
554
- type,
555
- array: true,
556
- label,
557
- ast,
558
- values,
559
- format,
560
- readonly,
561
- placeholder,
562
- inputProps,
563
- Custom
564
- });
565
- }
585
+ const [removed] = newOptions.splice(from, 1);
586
+ newOptions.splice(to, 0, removed);
587
+ onValueChange(type, newOptions);
588
+ }, [
589
+ options,
590
+ type,
591
+ onValueChange
592
+ ]);
593
+ const handleClick = (0, import_react7.useCallback)((id) => {
594
+ setSelectedId((current) => current === id ? null : id);
595
+ }, []);
596
+ const handleTitleChange = (0, import_react7.useCallback)((id) => (e) => {
597
+ const newOptions = options?.map((o) => o.id === id ? {
598
+ ...o,
599
+ title: e.target.value
600
+ } : o);
601
+ onValueChange(type, newOptions ?? []);
602
+ }, [
603
+ options,
604
+ type,
605
+ onValueChange
606
+ ]);
607
+ const handleKeyDown = (0, import_react7.useCallback)((e) => {
608
+ if (e.key === "Enter") {
609
+ setSelectedId(null);
566
610
  }
567
- if (!InputComponent) {
568
- if (type === "object") {
569
- const baseNode = (0, import_effect2.findNode)(ast, import_effect2.isDiscriminatedUnion);
570
- const typeLiteral = baseNode ? (0, import_effect2.getDiscriminatedType)(baseNode, values[name]) : (0, import_effect2.findNode)(ast, import_echo_schema2.AST.isTypeLiteral);
571
- if (typeLiteral) {
572
- const schema2 = import_echo_schema2.S.make(typeLiteral);
573
- return /* @__PURE__ */ import_react7.default.createElement("div", {
574
- key: name,
575
- role: "none"
576
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
577
- className: padding
578
- }, label), /* @__PURE__ */ import_react7.default.createElement(Form, {
579
- schema: schema2,
580
- path: key,
581
- values: values[name] ?? {},
582
- onValuesChanged: (childValues) => {
583
- inputProps.onValueChange(name, "object", childValues);
584
- },
585
- Custom
586
- }));
587
- }
588
- }
589
- (0, import_log2.log)("no renderer for property", {
590
- name,
591
- type
592
- }, {
593
- F: __dxlog_file2,
594
- L: 184,
595
- S: void 0,
596
- C: (f, a) => f(...a)
597
- });
598
- return null;
611
+ }, []);
612
+ const handleColorChange = (0, import_react7.useCallback)((id) => (hue) => {
613
+ const newOptions = options?.map((o) => o.id === id ? {
614
+ ...o,
615
+ color: hue
616
+ } : o);
617
+ onValueChange(type, newOptions ?? []);
618
+ }, [
619
+ options,
620
+ type,
621
+ onValueChange
622
+ ]);
623
+ (0, import_react7.useEffect)(() => {
624
+ if (selected && isNewOption && inputRef.current) {
625
+ inputRef.current.focus();
626
+ setIsNewOption(false);
599
627
  }
600
- return /* @__PURE__ */ import_react7.default.createElement("div", {
601
- key: name,
602
- role: "none",
603
- className: padding
604
- }, /* @__PURE__ */ import_react7.default.createElement(InputComponent, {
605
- type,
606
- format,
607
- property: name,
608
- disabled: readonly,
609
- label,
610
- placeholder,
611
- ...inputProps
612
- }));
613
- }).filter(import_util3.isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ import_react7.default.createElement(FormActions, {
614
- onCancel,
615
- onSubmit: handleSave,
616
- canSubmit: canSave,
617
- readonly
618
- }));
628
+ }, [
629
+ selected,
630
+ isNewOption
631
+ ]);
632
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Root, {
633
+ validationValence: status
634
+ }, /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
635
+ error
636
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement("div", {
637
+ role: "none"
638
+ }, options && /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.Root, {
639
+ items: options,
640
+ isItem: (item) => true,
641
+ onMove: handleMove
642
+ }, ({ items }) => /* @__PURE__ */ import_react7.default.createElement("div", {
643
+ role: "list",
644
+ className: "w-full overflow-auto"
645
+ }, items?.map((item) => /* @__PURE__ */ import_react7.default.createElement("div", {
646
+ key: item.id
647
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.Item, {
648
+ role: "button",
649
+ item,
650
+ classNames: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
651
+ "aria-expanded": selected === item.id
652
+ }, /* @__PURE__ */ import_react7.default.createElement("div", {
653
+ className: "flex items-center"
654
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.ItemDragHandle, null), /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.ItemTitle, {
655
+ onClick: () => handleClick(item.id),
656
+ classNames: "flex-1"
657
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Tag, {
658
+ palette: item.color
659
+ }, item.title || "\u200B")), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Icon, {
660
+ icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
661
+ onClick: () => handleClick(item.id)
662
+ })), selected === item.id && /* @__PURE__ */ import_react7.default.createElement("div", {
663
+ className: "mis-4 mbs-2 flex flex-col gap-1"
664
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Label, {
665
+ classNames: "text-xs"
666
+ }, t("select option label")), /* @__PURE__ */ import_react7.default.createElement("div", {
667
+ className: "flex flex-row items-center gap-1"
668
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.TextInput, {
669
+ placeholder: t("select option label placeholder"),
670
+ ref: selected === item.id ? inputRef : void 0,
671
+ value: item.title,
672
+ onChange: handleTitleChange(item.id),
673
+ onKeyDown: handleKeyDown,
674
+ classNames: "flex-1",
675
+ "data-no-submit": true
676
+ }), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Toolbar.Root, {
677
+ classNames: "p-0 m-0 !is-auto"
678
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_pickers.HuePicker, {
679
+ value: item.color,
680
+ onChange: handleColorChange(item.id)
681
+ })), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.IconButton, {
682
+ icon: "ph--trash--fill",
683
+ iconOnly: true,
684
+ label: t("select option delete"),
685
+ onClick: () => handleDelete(item.id)
686
+ })))))), /* @__PURE__ */ import_react7.default.createElement("div", {
687
+ role: "listitem"
688
+ }, /* @__PURE__ */ import_react7.default.createElement("div", {
689
+ role: "button",
690
+ className: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
691
+ onClick: handleAdd
692
+ }, /* @__PURE__ */ import_react7.default.createElement("div", {
693
+ className: "flex items-center gap-1"
694
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Icon, {
695
+ icon: "ph--plus--regular"
696
+ }), /* @__PURE__ */ import_react7.default.createElement("span", {
697
+ className: "text-sm"
698
+ }, t("select option add")))))))));
619
699
  };
620
- var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholder, inputProps, Custom }) => {
621
- const { t } = (0, import_react_ui7.useTranslation)(translationKey);
622
- const arrayValues = values[name] ?? [];
623
- const key = [
624
- name
625
- ];
626
- const tupleType = (0, import_effect2.findNode)(ast, import_echo_schema2.AST.isTupleType);
700
+ var gridCols = [
701
+ "grid-cols-1",
702
+ "grid-cols-2",
703
+ "grid-cols-3",
704
+ "grid-cols-4"
705
+ ];
706
+ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
707
+ const { status, error } = getStatus();
708
+ const values = getValue3() ?? {};
709
+ return /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.Root, {
710
+ validationValence: status
711
+ }, /* @__PURE__ */ import_react8.default.createElement(InputHeader, {
712
+ error
713
+ }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react8.default.createElement("div", {
714
+ className: (0, import_react_ui_theme4.mx)("grid gap-2", gridCols[binding.length - 1])
715
+ }, binding.map((prop) => /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.TextInput, {
716
+ key: prop,
717
+ type: "number",
718
+ disabled,
719
+ value: values[prop],
720
+ onChange: (event) => onValueChange(type, {
721
+ ...values,
722
+ [prop]: (0, import_util2.safeParseFloat)(event.target.value, 0)
723
+ }),
724
+ onBlur
725
+ }))));
726
+ };
727
+ var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
728
+ const { status, error } = getStatus();
729
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
730
+ validationValence: status
731
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
732
+ error
733
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.TextInput, {
734
+ disabled,
735
+ placeholder,
736
+ value: getValue3() ?? "",
737
+ onChange: (event) => onValueChange(type, event.target.value),
738
+ onBlur
739
+ }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Validation, null, error));
740
+ };
741
+ var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
742
+ const { status, error } = getStatus();
743
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
744
+ validationValence: status
745
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
746
+ error
747
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.TextInput, {
748
+ type: "number",
749
+ disabled,
750
+ placeholder,
751
+ value: getValue3() ?? 0,
752
+ onChange: (event) => onValueChange(type, event.target.value),
753
+ onBlur
754
+ }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
755
+ };
756
+ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
757
+ const { status, error } = getStatus();
758
+ const checked = Boolean(getValue3());
759
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
760
+ validationValence: status
761
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
762
+ error
763
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Switch, {
764
+ checked,
765
+ onCheckedChange: (value) => onValueChange(type, value)
766
+ }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
767
+ };
768
+ var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
769
+ const { status, error } = getStatus();
770
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
771
+ validationValence: status
772
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
773
+ error
774
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Root, {
775
+ value: getValue3(),
776
+ onValueChange: (value) => onValueChange(type, value)
777
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.TriggerButton, {
778
+ classNames: "is-full",
779
+ disabled,
780
+ placeholder
781
+ }), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Portal, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Content, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Viewport, null, options?.map(({ value, label: label2 }) => (
782
+ // NOTE: Numeric values are converted to and from strings.
783
+ /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Option, {
784
+ key: String(value),
785
+ value: String(value)
786
+ }, label2 ?? String(value))
787
+ )))))), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
788
+ };
789
+ var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
790
+ const { status, error } = getStatus();
791
+ const textareaRef = (0, import_react9.useRef)(null);
792
+ const adjustHeight = (0, import_react9.useCallback)(() => {
793
+ const textarea = textareaRef.current;
794
+ if (textarea) {
795
+ textarea.style.blockSize = "auto";
796
+ textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
797
+ }
798
+ }, []);
799
+ (0, import_react9.useEffect)(() => {
800
+ adjustHeight();
801
+ }, [
802
+ adjustHeight
803
+ ]);
804
+ (0, import_react9.useEffect)(() => {
805
+ adjustHeight();
806
+ }, [
807
+ getValue3(),
808
+ adjustHeight
809
+ ]);
810
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
811
+ validationValence: status
812
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
813
+ error
814
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.TextArea, {
815
+ ref: textareaRef,
816
+ disabled,
817
+ placeholder,
818
+ value: getValue3() ?? "",
819
+ classNames: "min-bs-auto max-h-40 overflow-auto",
820
+ onChange: (event) => onValueChange(type, event.target.value),
821
+ onBlur,
822
+ style: {
823
+ resize: "none"
824
+ },
825
+ spellCheck: false
826
+ }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Validation, null, error));
827
+ };
828
+ var FormActions = ({ onCancel, readonly }) => {
829
+ const { t } = (0, import_react_ui8.useTranslation)(translationKey);
830
+ const { canSave, handleSave } = useFormContext();
831
+ return /* @__PURE__ */ import_react11.default.createElement("div", {
832
+ role: "none",
833
+ className: "mt-2 flex justify-center"
834
+ }, /* @__PURE__ */ import_react11.default.createElement("div", {
835
+ role: "none",
836
+ className: (0, import_react_ui_theme6.mx)(onCancel && !readonly && "grid grid-cols-2 gap-2")
837
+ }, onCancel && !readonly && /* @__PURE__ */ import_react11.default.createElement(import_react_ui8.IconButton, {
838
+ "data-testid": "cancel-button",
839
+ icon: "ph--x--regular",
840
+ label: t("button cancel"),
841
+ onClick: onCancel
842
+ }), handleSave && /* @__PURE__ */ import_react11.default.createElement(import_react_ui8.IconButton, {
843
+ type: "submit",
844
+ "data-testid": "save-button",
845
+ disabled: !canSave,
846
+ icon: "ph--check--regular",
847
+ label: t("button save"),
848
+ onClick: handleSave
849
+ })));
850
+ };
851
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
852
+ var padding = "px-2";
853
+ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
854
+ const { t } = (0, import_react_ui9.useTranslation)(translationKey);
855
+ const { ast, name, type, title } = property;
856
+ const values = useFormValues(path ?? []);
857
+ (0, import_invariant2.invariant)(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
858
+ F: __dxlog_file2,
859
+ L: 37,
860
+ S: void 0,
861
+ A: [
862
+ "Array.isArray(values)",
863
+ "`Values at path ${path?.join('.')} must be an array.`"
864
+ ]
865
+ });
866
+ const label = title ?? (0, import_effect5.pipe)(name, import_String2.capitalize);
867
+ const tupleType = (0, import_effect6.findNode)(ast, import_echo_schema6.AST.isTupleType);
627
868
  const elementType = tupleType?.rest[0]?.type;
628
- if (type === "object" && elementType) {
629
- const baseNode = (0, import_effect2.findNode)(elementType, import_effect2.isDiscriminatedUnion);
630
- const typeLiteral = baseNode ? (0, import_effect2.getDiscriminatedType)(baseNode, values[name]) : (0, import_effect2.findNode)(elementType, import_echo_schema2.AST.isTypeLiteral);
631
- if (typeLiteral) {
632
- const schema = import_echo_schema2.S.make(typeLiteral);
633
- return /* @__PURE__ */ import_react7.default.createElement("div", {
634
- key: name,
635
- role: "none",
636
- className: (0, import_react_ui_theme3.mx)(padding)
637
- }, /* @__PURE__ */ import_react7.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react7.default.createElement("div", {
638
- role: "none",
639
- className: "flex flex-col gap-1"
640
- }, arrayValues.map((value, index) => {
641
- return /* @__PURE__ */ import_react7.default.createElement("div", {
642
- key: index,
643
- role: "none",
644
- className: "flex items-center gap-1"
645
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
646
- role: "none",
647
- className: "flex-1"
648
- }, /* @__PURE__ */ import_react7.default.createElement(Form, {
649
- schema,
650
- path: [
651
- ...key,
652
- `[${index}]`
653
- ],
654
- values: value,
655
- onValuesChanged: (childValues) => {
656
- const newValues = [
657
- ...arrayValues
658
- ];
659
- newValues[index] = childValues;
660
- inputProps.onValueChange(name, "object", newValues);
661
- },
662
- Custom
663
- })), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
664
- icon: "ph--trash--regular",
665
- iconOnly: true,
666
- label: t("button remove"),
667
- onClick: () => {
668
- const newValues = arrayValues.filter((_, i) => i !== index);
669
- inputProps.onValueChange(name, type, newValues);
670
- }
671
- }));
672
- })), /* @__PURE__ */ import_react7.default.createElement("div", {
673
- role: "none",
674
- className: "flex justify-between items-center plb-1"
675
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
676
- icon: "ph--plus--regular",
677
- iconOnly: true,
678
- label: t("button add"),
679
- onClick: () => {
680
- const newValues = [
681
- ...arrayValues,
682
- {}
683
- ];
684
- inputProps.onValueChange(name, type, newValues);
685
- }
686
- })));
869
+ const getDefaultObjectValue = (typeNode) => {
870
+ const baseNode = (0, import_effect6.findNode)(typeNode, import_effect6.isDiscriminatedUnion);
871
+ const typeLiteral = baseNode ? (0, import_effect6.getDiscriminatedType)(baseNode, {}) : (0, import_effect6.findNode)(typeNode, import_echo_schema6.AST.isTypeLiteral);
872
+ if (!typeLiteral) {
873
+ return {};
687
874
  }
688
- return /* @__PURE__ */ import_react7.default.createElement("div", {
689
- key: name,
690
- role: "none"
691
- }, "Nested form not supported in arrays, yet.");
692
- }
693
- const InputComponent = getInputComponent(type, format);
694
- if (!InputComponent) {
875
+ return Object.fromEntries((0, import_schema4.getSchemaProperties)(typeLiteral, {}).map((prop) => [
876
+ prop.name,
877
+ prop.defaultValue
878
+ ]));
879
+ };
880
+ const newValue = (0, import_react13.useMemo)(() => {
881
+ if (type === "object" && elementType) {
882
+ return getDefaultObjectValue(elementType);
883
+ } else {
884
+ return import_effect6.SimpleType.getDefaultValue(type);
885
+ }
886
+ }, [
887
+ type,
888
+ elementType
889
+ ]);
890
+ const handleAdd = (0, import_react13.useCallback)(() => {
891
+ inputProps.onValueChange(type, [
892
+ ...values,
893
+ newValue
894
+ ]);
895
+ }, [
896
+ type,
897
+ elementType,
898
+ inputProps,
899
+ newValue,
900
+ values
901
+ ]);
902
+ const handleRemove = (0, import_react13.useCallback)((index) => {
903
+ const newValues = values.filter((_, i) => i !== index);
904
+ inputProps.onValueChange(type, newValues);
905
+ }, [
906
+ type,
907
+ inputProps,
908
+ values
909
+ ]);
910
+ if (!elementType) {
695
911
  return null;
696
912
  }
697
- return /* @__PURE__ */ import_react7.default.createElement("div", {
913
+ return /* @__PURE__ */ import_react13.default.createElement("div", {
698
914
  role: "none",
699
- key: "meta-input",
700
- className: (0, import_react_ui_theme3.mx)(padding)
701
- }, /* @__PURE__ */ import_react7.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react7.default.createElement("div", {
915
+ className: (0, import_react_ui_theme8.mx)(padding)
916
+ }, /* @__PURE__ */ import_react13.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react13.default.createElement("div", {
702
917
  role: "none",
703
918
  className: "flex flex-col gap-1"
704
- }, arrayValues.map((_, index) => /* @__PURE__ */ import_react7.default.createElement("div", {
919
+ }, values.map((_value, index) => /* @__PURE__ */ import_react13.default.createElement("div", {
705
920
  key: index,
706
921
  role: "none",
707
- className: "flex items-start gap-1"
708
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
922
+ className: "flex items-center gap-1"
923
+ }, /* @__PURE__ */ import_react13.default.createElement("div", {
709
924
  role: "none",
710
925
  className: "flex-1"
711
- }, /* @__PURE__ */ import_react7.default.createElement(InputComponent, {
712
- type,
713
- format,
714
- label,
715
- inputOnly: true,
716
- property: `${name}[${index}]`,
717
- disabled: readonly,
718
- placeholder,
719
- ...inputProps
720
- })), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
926
+ }, /* @__PURE__ */ import_react13.default.createElement(FormField, {
927
+ property: {
928
+ ...property,
929
+ array: false,
930
+ ast: elementType
931
+ },
932
+ path: [
933
+ ...path ?? [],
934
+ index
935
+ ],
936
+ readonly,
937
+ inline: true,
938
+ Custom,
939
+ lookupComponent
940
+ })), /* @__PURE__ */ import_react13.default.createElement(import_react_ui9.IconButton, {
721
941
  icon: "ph--trash--regular",
722
942
  iconOnly: true,
723
943
  label: t("button remove"),
724
- onClick: () => {
725
- const newValues = arrayValues.filter((_2, i) => i !== index);
726
- inputProps.onValueChange(name, type, newValues);
727
- }
728
- })))), /* @__PURE__ */ import_react7.default.createElement("div", {
944
+ onClick: () => handleRemove(index)
945
+ })))), /* @__PURE__ */ import_react13.default.createElement("div", {
729
946
  role: "none",
730
947
  className: "flex justify-between items-center plb-1"
731
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
948
+ }, /* @__PURE__ */ import_react13.default.createElement(import_react_ui9.IconButton, {
732
949
  icon: "ph--plus--regular",
733
950
  iconOnly: true,
734
951
  label: t("button add"),
735
- onClick: () => {
736
- const newValues = [
737
- ...arrayValues,
738
- import_effect2.SimpleType.getDefaultValue(type)
739
- ];
740
- inputProps.onValueChange(name, type, newValues);
741
- }
952
+ onClick: handleAdd
742
953
  })));
743
954
  };
744
- var FormActions = ({ onCancel, onSubmit, canSubmit, readonly }) => {
745
- const { t } = (0, import_react_ui7.useTranslation)(translationKey);
746
- return /* @__PURE__ */ import_react7.default.createElement("div", {
747
- role: "none",
748
- className: "flex justify-center"
749
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
955
+ var getInputComponent = (type, format) => {
956
+ switch (format) {
957
+ case import_echo_schema7.FormatEnum.GeoPoint:
958
+ return GeoPointInput;
959
+ case import_echo_schema7.FormatEnum.Markdown:
960
+ return MarkdownInput;
961
+ }
962
+ switch (type) {
963
+ case "string":
964
+ return TextInput;
965
+ case "number":
966
+ return NumberInput;
967
+ case "boolean":
968
+ return BooleanInput;
969
+ }
970
+ };
971
+ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom }) => {
972
+ const inputProps = useInputProps(path);
973
+ const { ast, name, type, format, title, description, options, examples, array } = property;
974
+ const label = (0, import_react12.useMemo)(() => title ?? (0, import_effect3.pipe)(name, import_String.capitalize), [
975
+ title,
976
+ name
977
+ ]);
978
+ const placeholder = (0, import_react12.useMemo)(() => examples?.length ? `Example: "${examples[0]}"` : description, [
979
+ examples,
980
+ description
981
+ ]);
982
+ const FoundComponent = lookupComponent?.({
983
+ prop: name,
984
+ schema: import_echo_schema5.S.make(ast),
985
+ inputProps: {
986
+ type,
987
+ format,
988
+ label,
989
+ disabled: readonly,
990
+ placeholder,
991
+ ...inputProps
992
+ }
993
+ });
994
+ if (FoundComponent) {
995
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
996
+ role: "none"
997
+ }, FoundComponent);
998
+ }
999
+ const jsonPath = (0, import_effect4.createJsonPath)(path ?? []);
1000
+ const CustomComponent = Custom?.[jsonPath];
1001
+ if (CustomComponent) {
1002
+ return /* @__PURE__ */ import_react12.default.createElement(CustomComponent, {
1003
+ type,
1004
+ format,
1005
+ label,
1006
+ inputOnly: inline,
1007
+ placeholder,
1008
+ disabled: readonly,
1009
+ ...inputProps
1010
+ });
1011
+ }
1012
+ if (array) {
1013
+ return /* @__PURE__ */ import_react12.default.createElement(ArrayField, {
1014
+ property,
1015
+ path,
1016
+ inputProps,
1017
+ readonly,
1018
+ Custom
1019
+ });
1020
+ }
1021
+ const InputComponent = getInputComponent(type, format);
1022
+ if (InputComponent) {
1023
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1024
+ role: "none"
1025
+ }, /* @__PURE__ */ import_react12.default.createElement(InputComponent, {
1026
+ type,
1027
+ format,
1028
+ label,
1029
+ inputOnly: inline,
1030
+ placeholder,
1031
+ disabled: readonly,
1032
+ ...inputProps
1033
+ }));
1034
+ }
1035
+ if (options) {
1036
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1037
+ role: "none"
1038
+ }, /* @__PURE__ */ import_react12.default.createElement(SelectInput, {
1039
+ type,
1040
+ format,
1041
+ disabled: readonly,
1042
+ inputOnly: inline,
1043
+ label,
1044
+ options: options.map((option) => ({
1045
+ value: option,
1046
+ label: String(option)
1047
+ })),
1048
+ placeholder,
1049
+ ...inputProps
1050
+ }));
1051
+ }
1052
+ if (type === "object") {
1053
+ const baseNode = (0, import_effect4.findNode)(ast, import_effect4.isDiscriminatedUnion);
1054
+ const typeLiteral = baseNode ? (0, import_effect4.getDiscriminatedType)(baseNode, inputProps.getValue()) : (0, import_effect4.findNode)(ast, import_echo_schema5.AST.isTypeLiteral);
1055
+ if (typeLiteral) {
1056
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1057
+ role: "none"
1058
+ }, !inline && /* @__PURE__ */ import_react12.default.createElement("div", null, label), /* @__PURE__ */ import_react12.default.createElement(FormFields, {
1059
+ schema: import_echo_schema5.S.make(typeLiteral),
1060
+ path,
1061
+ readonly,
1062
+ Custom
1063
+ }));
1064
+ }
1065
+ }
1066
+ return null;
1067
+ };
1068
+ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custom }) => {
1069
+ const values = useFormValues(path);
1070
+ const properties = (0, import_react12.useMemo)(() => {
1071
+ const props = (0, import_schema3.getSchemaProperties)(schema.ast, values);
1072
+ const filtered = filter ? filter(props) : props;
1073
+ return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
1074
+ }, [
1075
+ schema,
1076
+ values,
1077
+ filter,
1078
+ sort
1079
+ ]);
1080
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1081
+ role: "form",
1082
+ className: (0, import_react_ui_theme7.mx)("flex flex-col w-full gap-2")
1083
+ }, properties.map((property) => {
1084
+ return /* @__PURE__ */ import_react12.default.createElement(FormField, {
1085
+ key: property.name,
1086
+ property,
1087
+ path: [
1088
+ ...path ?? [],
1089
+ property.name
1090
+ ],
1091
+ readonly,
1092
+ lookupComponent,
1093
+ Custom
1094
+ });
1095
+ }).filter(import_util3.isNotFalsy));
1096
+ };
1097
+ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
1098
+ const formRef = (0, import_react10.useRef)(null);
1099
+ const onValid = (0, import_react10.useMemo)(() => autoSave ? onSave : void 0, [
1100
+ autoSave,
1101
+ onSave
1102
+ ]);
1103
+ (0, import_react10.useEffect)(() => {
1104
+ if (autoFocus && formRef.current) {
1105
+ const input = formRef.current.querySelector("input");
1106
+ if (input) {
1107
+ input.focus();
1108
+ }
1109
+ }
1110
+ }, [
1111
+ autoFocus
1112
+ ]);
1113
+ return /* @__PURE__ */ import_react10.default.createElement(FormProvider, {
1114
+ formRef,
1115
+ schema,
1116
+ autoSave,
1117
+ initialValues,
1118
+ onValuesChanged,
1119
+ onValidate,
1120
+ onValid,
1121
+ onSave
1122
+ }, /* @__PURE__ */ import_react10.default.createElement("div", {
1123
+ ref: formRef,
750
1124
  role: "none",
751
- className: (0, import_react_ui_theme3.mx)(onCancel && !readonly && "grid grid-cols-2 gap-2")
752
- }, onCancel && !readonly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
753
- "data-testid": "cancel-button",
754
- icon: "ph--x--regular",
755
- label: t("button cancel"),
756
- onClick: onCancel
757
- }), onSubmit && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
758
- type: "submit",
759
- "data-testid": "save-button",
760
- disabled: !canSubmit,
761
- icon: "ph--check--regular",
762
- label: t("button save"),
763
- onClick: onSubmit
1125
+ className: (0, import_react_ui_theme5.mx)("p-2", classNames),
1126
+ "data-testid": testId
1127
+ }, /* @__PURE__ */ import_react10.default.createElement(FormFields, {
1128
+ schema,
1129
+ path,
1130
+ readonly,
1131
+ filter,
1132
+ sort,
1133
+ lookupComponent,
1134
+ Custom
1135
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ import_react10.default.createElement(FormActions, {
1136
+ onCancel,
1137
+ readonly
764
1138
  })));
765
1139
  };
766
1140
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
@@ -790,9 +1164,9 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
790
1164
  }, [
791
1165
  registry
792
1166
  ]);
793
- const [schema, setSchema] = (0, import_react2.useState)();
1167
+ const [referenceSchema, setReferenceSchema] = (0, import_react2.useState)();
794
1168
  (0, import_react2.useEffect)(() => {
795
- setSchema(schemas.find((schema2) => schema2.typename === props?.referenceSchema));
1169
+ setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
796
1170
  }, [
797
1171
  schemas,
798
1172
  props?.referenceSchema
@@ -810,9 +1184,15 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
810
1184
  fieldSchema: fieldSchema2
811
1185
  };
812
1186
  });
813
- if (_props.referenceSchema !== props.referenceSchema) {
814
- setSchema(schemas.find((schema2) => schema2.typename === _props.referenceSchema));
815
- }
1187
+ setReferenceSchema((prev) => {
1188
+ if (_props.referenceSchema !== prev?.typename) {
1189
+ const newSchema = schemas.find((schema) => schema.typename === _props.referenceSchema);
1190
+ if (newSchema) {
1191
+ return newSchema;
1192
+ }
1193
+ }
1194
+ return prev;
1195
+ });
816
1196
  setProps((props2) => {
817
1197
  const type = import_echo_schema.formatToType[_props.format];
818
1198
  if (props2.type !== type) {
@@ -822,7 +1202,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
822
1202
  type
823
1203
  };
824
1204
  }
825
- return props2;
1205
+ return _props;
826
1206
  });
827
1207
  }, [
828
1208
  schemas,
@@ -859,12 +1239,39 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
859
1239
  }, [
860
1240
  onSave
861
1241
  ]);
1242
+ const Custom = (0, import_react2.useMemo)(() => ({
1243
+ ["format"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
1244
+ ...props2,
1245
+ options: import_echo_schema.FormatEnums.filter((value) => value !== import_echo_schema.FormatEnum.None).map((value) => ({
1246
+ value,
1247
+ label: t(`format ${value}`)
1248
+ }))
1249
+ }),
1250
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
1251
+ ...props2,
1252
+ options: schemas.map((schema) => ({
1253
+ value: schema.typename
1254
+ }))
1255
+ }),
1256
+ ["referencePath"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
1257
+ ...props2,
1258
+ options: referenceSchema ? (0, import_schema.getSchemaProperties)(referenceSchema.ast).sort(import_schema.sortProperties).map((p) => ({
1259
+ value: p.name
1260
+ })) : []
1261
+ }),
1262
+ ["options"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectOptionInput, props2)
1263
+ }), [
1264
+ t,
1265
+ schemas,
1266
+ referenceSchema
1267
+ ]);
1268
+ const propIsNotType = (0, import_react2.useCallback)((props2) => props2.filter((p) => p.name !== "type"), []);
862
1269
  if (!fieldSchema) {
863
1270
  import_log.log.warn("invalid format", {
864
1271
  props
865
1272
  }, {
866
1273
  F: __dxlog_file3,
867
- L: 126,
1274
+ L: 174,
868
1275
  S: void 0,
869
1276
  C: (f, a) => f(...a)
870
1277
  });
@@ -875,7 +1282,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
875
1282
  autoFocus: true,
876
1283
  values: props,
877
1284
  schema: fieldSchema,
878
- filter: (props2) => props2.filter((p) => p.name !== "type"),
1285
+ filter: propIsNotType,
879
1286
  sort: [
880
1287
  "property",
881
1288
  "format"
@@ -884,46 +1291,26 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
884
1291
  onValidate: handleValidate,
885
1292
  onSave: handleSave,
886
1293
  onCancel: handleCancel,
887
- Custom: {
888
- ["format"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
889
- ...props2,
890
- options: import_echo_schema.FormatEnums.filter((value) => value !== import_echo_schema.FormatEnum.None).map((value) => ({
891
- value,
892
- label: t(`format ${value}`)
893
- }))
894
- }),
895
- ["referenceSchema"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
896
- ...props2,
897
- options: schemas.map((schema2) => ({
898
- value: schema2.typename
899
- }))
900
- }),
901
- ["referencePath"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
902
- ...props2,
903
- options: schema ? (0, import_schema.getSchemaProperties)(schema.ast).sort(import_schema.sortProperties).map((p) => ({
904
- value: p.name
905
- })) : []
906
- })
907
- }
1294
+ Custom
908
1295
  });
909
1296
  };
910
1297
  var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
911
- var ViewMetaSchema = import_echo_schema5.S.Struct({
912
- name: import_echo_schema5.S.String.annotations({
913
- [import_echo_schema5.AST.TitleAnnotationId]: "View"
1298
+ var ViewMetaSchema = import_echo_schema8.S.Struct({
1299
+ name: import_echo_schema8.S.String.annotations({
1300
+ [import_echo_schema8.AST.TitleAnnotationId]: "View"
914
1301
  }),
915
- typename: import_echo_schema5.Format.DXN.annotations({
916
- [import_echo_schema5.AST.TitleAnnotationId]: "Typename"
1302
+ typename: import_echo_schema8.Format.URL.annotations({
1303
+ [import_echo_schema8.AST.TitleAnnotationId]: "Typename"
917
1304
  })
918
- }).pipe(import_echo_schema5.S.mutable);
919
- var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onDelete }) => {
920
- const { t } = (0, import_react_ui8.useTranslation)(translationKey);
921
- const projection = (0, import_react9.useMemo)(() => new import_schema4.ViewProjection(schema, view), [
1305
+ }).pipe(import_echo_schema8.S.mutable);
1306
+ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
1307
+ const { t } = (0, import_react_ui10.useTranslation)(translationKey);
1308
+ const projection = (0, import_react14.useMemo)(() => new import_schema5.ViewProjection(schema, view), [
922
1309
  schema,
923
1310
  view
924
1311
  ]);
925
- const [field, setField] = (0, import_react9.useState)();
926
- const viewValues = (0, import_react9.useMemo)(() => {
1312
+ const [field, setField] = (0, import_react14.useState)();
1313
+ const viewValues = (0, import_react14.useMemo)(() => {
927
1314
  return {
928
1315
  name: view.name,
929
1316
  // TODO(burdon): Need to warn user of possible consequences of editing.
@@ -933,82 +1320,90 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
933
1320
  }, [
934
1321
  view
935
1322
  ]);
936
- const handleViewUpdate = (0, import_react9.useCallback)(({ name, typename }) => {
1323
+ const handleViewUpdate = (0, import_react14.useCallback)(({ name, typename }) => {
937
1324
  requestAnimationFrame(() => {
938
- view.name = name;
939
- view.query.type = typename;
940
- schema.updateTypename(typename);
1325
+ if (view.name !== name) {
1326
+ view.name = name;
1327
+ }
1328
+ if (view.query.type !== typename) {
1329
+ onTypenameChanged(typename);
1330
+ }
941
1331
  });
942
1332
  }, [
943
1333
  view,
944
- schema
1334
+ schema,
1335
+ onTypenameChanged
945
1336
  ]);
946
- const handleSelect = (0, import_react9.useCallback)((field2) => {
1337
+ const handleSelect = (0, import_react14.useCallback)((field2) => {
947
1338
  setField((f) => f === field2 ? void 0 : field2);
948
1339
  }, []);
949
- const handleAdd = (0, import_react9.useCallback)(() => {
1340
+ const handleAdd = (0, import_react14.useCallback)(() => {
950
1341
  const field2 = projection.createFieldProjection();
951
1342
  setField(field2);
952
1343
  }, [
953
1344
  view
954
1345
  ]);
955
- const handleMove = (0, import_react9.useCallback)((fromIndex, toIndex) => {
956
- (0, import_util4.arrayMove)(view.fields, fromIndex, toIndex);
1346
+ const handleMove = (0, import_react14.useCallback)((fromIndex, toIndex) => {
1347
+ const fields = [
1348
+ ...view.fields
1349
+ ];
1350
+ const [moved] = fields.splice(fromIndex, 1);
1351
+ fields.splice(toIndex, 0, moved);
1352
+ view.fields = fields;
957
1353
  }, [
958
1354
  view.fields
959
1355
  ]);
960
- const handleClose = (0, import_react9.useCallback)(() => setField(void 0), []);
961
- return /* @__PURE__ */ import_react9.default.createElement("div", {
1356
+ const handleClose = (0, import_react14.useCallback)(() => setField(void 0), []);
1357
+ return /* @__PURE__ */ import_react14.default.createElement("div", {
962
1358
  role: "none",
963
- className: (0, import_react_ui_theme4.mx)("flex flex-col w-full divide-y divide-separator", classNames)
964
- }, /* @__PURE__ */ import_react9.default.createElement(Form, {
965
- autoFocus: true,
1359
+ className: (0, import_react_ui_theme9.mx)("flex flex-col w-full divide-y divide-separator", classNames)
1360
+ }, /* @__PURE__ */ import_react14.default.createElement(Form, {
966
1361
  autoSave: true,
967
1362
  schema: ViewMetaSchema,
968
1363
  values: viewValues,
969
1364
  onSave: handleViewUpdate
970
- }), /* @__PURE__ */ import_react9.default.createElement("div", null, /* @__PURE__ */ import_react9.default.createElement("div", {
1365
+ }), /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("div", {
971
1366
  role: "none",
972
1367
  className: "p-2"
973
- }, /* @__PURE__ */ import_react9.default.createElement("label", {
974
- className: (0, import_react_ui_theme4.mx)(import_react_ui_theme4.inputTextLabel)
975
- }, t("fields label"))), /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.Root, {
1368
+ }, /* @__PURE__ */ import_react14.default.createElement("label", {
1369
+ className: (0, import_react_ui_theme9.mx)(import_react_ui_theme9.inputTextLabel)
1370
+ }, t("fields label"))), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.Root, {
976
1371
  items: view.fields,
977
- isItem: import_echo_schema5.S.is(import_schema4.FieldSchema),
1372
+ isItem: import_echo_schema8.S.is(import_schema5.FieldSchema),
978
1373
  getId: (field2) => field2.id,
979
1374
  onMove: handleMove
980
- }, ({ items: fields }) => /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, showHeading && /* @__PURE__ */ import_react9.default.createElement("div", {
1375
+ }, ({ items: fields }) => /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, showHeading && /* @__PURE__ */ import_react14.default.createElement("div", {
981
1376
  role: "heading",
982
1377
  className: grid
983
- }, /* @__PURE__ */ import_react9.default.createElement("div", null), /* @__PURE__ */ import_react9.default.createElement("div", {
1378
+ }, /* @__PURE__ */ import_react14.default.createElement("div", null), /* @__PURE__ */ import_react14.default.createElement("div", {
984
1379
  className: "flex items-center text-sm"
985
- }, t("field path label"))), /* @__PURE__ */ import_react9.default.createElement("div", {
1380
+ }, t("field path label"))), /* @__PURE__ */ import_react14.default.createElement("div", {
986
1381
  role: "list",
987
1382
  className: "flex flex-col w-full"
988
- }, fields?.map((field2) => /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.Item, {
1383
+ }, fields?.map((field2) => /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.Item, {
989
1384
  key: field2.id,
990
1385
  item: field2,
991
- classNames: (0, import_react_ui_theme4.mx)(grid, import_react_ui_theme4.ghostHover, "cursor-pointer")
992
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.ItemDragHandle, null), /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.ItemTitle, {
1386
+ classNames: (0, import_react_ui_theme9.mx)(grid, import_react_ui_theme9.ghostHover, "cursor-pointer")
1387
+ }, /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemDragHandle, null), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemTitle, {
993
1388
  onClick: () => handleSelect(field2)
994
- }, field2.path), /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.ItemDeleteButton, {
1389
+ }, field2.path), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemDeleteButton, {
995
1390
  disabled: view.fields.length <= 1,
996
1391
  onClick: () => onDelete(field2.id)
997
- }))))))), field && /* @__PURE__ */ import_react9.default.createElement(FieldEditor, {
1392
+ }))))))), field && /* @__PURE__ */ import_react14.default.createElement(FieldEditor, {
998
1393
  key: field.id,
999
1394
  view,
1000
1395
  projection,
1001
1396
  field,
1002
1397
  registry,
1003
1398
  onSave: handleClose
1004
- }), !readonly && !field && /* @__PURE__ */ import_react9.default.createElement("div", {
1399
+ }), !readonly && !field && /* @__PURE__ */ import_react14.default.createElement("div", {
1005
1400
  className: "flex p-2 justify-center"
1006
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.IconButton, {
1401
+ }, /* @__PURE__ */ import_react14.default.createElement(import_react_ui10.IconButton, {
1007
1402
  icon: "ph--plus--regular",
1008
1403
  label: t("button add property"),
1009
1404
  onClick: handleAdd,
1010
1405
  // TODO(burdon): Show field limit in ux (not tooltip).
1011
- disabled: view.fields.length >= import_schema4.VIEW_FIELD_LIMIT
1406
+ disabled: view.fields.length >= import_schema5.VIEW_FIELD_LIMIT
1012
1407
  })));
1013
1408
  };
1014
1409
  var parseValue = ({ type, format, value }) => {
@@ -1017,7 +1412,7 @@ var parseValue = ({ type, format, value }) => {
1017
1412
  }
1018
1413
  const parseScalar = (type2) => {
1019
1414
  switch (type2) {
1020
- case import_echo_schema6.TypeEnum.Boolean: {
1415
+ case import_echo_schema9.TypeEnum.Boolean: {
1021
1416
  if (typeof value === "string") {
1022
1417
  const lowercaseValue = value.toLowerCase();
1023
1418
  if (lowercaseValue === "0" || lowercaseValue === "false") {
@@ -1028,13 +1423,13 @@ var parseValue = ({ type, format, value }) => {
1028
1423
  }
1029
1424
  return Boolean(value);
1030
1425
  }
1031
- case import_echo_schema6.TypeEnum.Number: {
1426
+ case import_echo_schema9.TypeEnum.Number: {
1032
1427
  const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1033
1428
  const num = Number(cleaned);
1034
1429
  return Number.isNaN(num) ? null : num;
1035
1430
  }
1036
- case import_echo_schema6.TypeEnum.String:
1037
- case import_echo_schema6.TypeEnum.Ref:
1431
+ case import_echo_schema9.TypeEnum.String:
1432
+ case import_echo_schema9.TypeEnum.Ref:
1038
1433
  return String(value);
1039
1434
  default: {
1040
1435
  return value;
@@ -1045,25 +1440,45 @@ var parseValue = ({ type, format, value }) => {
1045
1440
  return parseScalar(type);
1046
1441
  }
1047
1442
  switch (format) {
1048
- case import_echo_schema6.FormatEnum.Boolean:
1049
- return parseScalar(import_echo_schema6.TypeEnum.Boolean);
1050
- case import_echo_schema6.FormatEnum.Number:
1051
- case import_echo_schema6.FormatEnum.Percent:
1052
- case import_echo_schema6.FormatEnum.Currency:
1053
- return parseScalar(import_echo_schema6.TypeEnum.Number);
1054
- case import_echo_schema6.FormatEnum.String:
1055
- case import_echo_schema6.FormatEnum.Markdown: {
1056
- return parseScalar(import_echo_schema6.TypeEnum.String);
1443
+ case import_echo_schema9.FormatEnum.Boolean:
1444
+ return parseScalar(import_echo_schema9.TypeEnum.Boolean);
1445
+ case import_echo_schema9.FormatEnum.Number:
1446
+ case import_echo_schema9.FormatEnum.Percent:
1447
+ case import_echo_schema9.FormatEnum.Currency:
1448
+ return parseScalar(import_echo_schema9.TypeEnum.Number);
1449
+ case import_echo_schema9.FormatEnum.String:
1450
+ case import_echo_schema9.FormatEnum.Markdown: {
1451
+ return parseScalar(import_echo_schema9.TypeEnum.String);
1057
1452
  }
1058
- case import_echo_schema6.FormatEnum.Ref:
1059
- throw new Error(`unexpected format: ${import_echo_schema6.FormatEnum.Ref}`);
1060
- case import_echo_schema6.FormatEnum.DateTime:
1061
- case import_echo_schema6.FormatEnum.Date:
1062
- case import_echo_schema6.FormatEnum.Time:
1063
- case import_echo_schema6.FormatEnum.Timestamp: {
1453
+ case import_echo_schema9.FormatEnum.Ref:
1454
+ throw new Error(`unexpected format: ${import_echo_schema9.FormatEnum.Ref}`);
1455
+ case import_echo_schema9.FormatEnum.DateTime:
1456
+ case import_echo_schema9.FormatEnum.Date:
1457
+ case import_echo_schema9.FormatEnum.Time:
1458
+ case import_echo_schema9.FormatEnum.Timestamp: {
1064
1459
  const date = new Date(value);
1065
1460
  return isNaN(date.getTime()) ? null : date;
1066
1461
  }
1462
+ case import_echo_schema9.FormatEnum.GeoPoint: {
1463
+ if (typeof value === "string") {
1464
+ const cleaned = value.replace(/[^0-9.,-]+/g, "");
1465
+ const parts = cleaned.split(",");
1466
+ if (parts.length === 2) {
1467
+ const lat = parseFloat(parts[0]);
1468
+ const long = parseFloat(parts[1]);
1469
+ if (!isNaN(lat) && !isNaN(long)) {
1470
+ return import_echo_schema9.GeoLocation.toGeoPoint({
1471
+ latitude: lat,
1472
+ longitude: long
1473
+ });
1474
+ }
1475
+ }
1476
+ }
1477
+ return [
1478
+ 0,
1479
+ 0
1480
+ ];
1481
+ }
1067
1482
  default: {
1068
1483
  return value;
1069
1484
  }
@@ -1072,19 +1487,19 @@ var parseValue = ({ type, format, value }) => {
1072
1487
  var cellClassesForFieldType = ({ type, format }) => {
1073
1488
  if (!format) {
1074
1489
  switch (type) {
1075
- case import_echo_schema6.TypeEnum.Number:
1490
+ case import_echo_schema9.TypeEnum.Number:
1076
1491
  return [
1077
1492
  "text-right",
1078
1493
  "font-mono"
1079
1494
  ];
1080
- case import_echo_schema6.TypeEnum.Boolean:
1495
+ case import_echo_schema9.TypeEnum.Boolean:
1081
1496
  return [
1082
1497
  "text-right",
1083
1498
  "font-mono"
1084
1499
  ];
1085
- case import_echo_schema6.TypeEnum.String:
1500
+ case import_echo_schema9.TypeEnum.String:
1086
1501
  return void 0;
1087
- case import_echo_schema6.TypeEnum.Ref:
1502
+ case import_echo_schema9.TypeEnum.Ref:
1088
1503
  return void 0;
1089
1504
  default: {
1090
1505
  return void 0;
@@ -1092,20 +1507,20 @@ var cellClassesForFieldType = ({ type, format }) => {
1092
1507
  }
1093
1508
  }
1094
1509
  switch (format) {
1095
- case import_echo_schema6.FormatEnum.Markdown:
1510
+ case import_echo_schema9.FormatEnum.Markdown:
1096
1511
  return void 0;
1097
- case import_echo_schema6.FormatEnum.Timestamp:
1098
- case import_echo_schema6.FormatEnum.DateTime:
1099
- case import_echo_schema6.FormatEnum.Date:
1100
- case import_echo_schema6.FormatEnum.Time:
1512
+ case import_echo_schema9.FormatEnum.Timestamp:
1513
+ case import_echo_schema9.FormatEnum.DateTime:
1514
+ case import_echo_schema9.FormatEnum.Date:
1515
+ case import_echo_schema9.FormatEnum.Time:
1101
1516
  return [
1102
1517
  "font-mono"
1103
1518
  ];
1104
- case import_echo_schema6.FormatEnum.Currency:
1519
+ case import_echo_schema9.FormatEnum.Currency:
1105
1520
  return [
1106
1521
  "text-right"
1107
1522
  ];
1108
- case import_echo_schema6.FormatEnum.JSON:
1523
+ case import_echo_schema9.FormatEnum.JSON:
1109
1524
  return [
1110
1525
  "font-mono"
1111
1526
  ];
@@ -1123,12 +1538,12 @@ var pathNotUniqueError = (path) => ({
1123
1538
  var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1124
1539
  const formatScalar = (type2) => {
1125
1540
  switch (type2) {
1126
- case import_echo_schema7.TypeEnum.Boolean:
1541
+ case import_echo_schema10.TypeEnum.Boolean:
1127
1542
  return value.toLocaleString().toUpperCase();
1128
- case import_echo_schema7.TypeEnum.Number:
1543
+ case import_echo_schema10.TypeEnum.Number:
1129
1544
  return value.toLocaleString(locale);
1130
- case import_echo_schema7.TypeEnum.String:
1131
- case import_echo_schema7.TypeEnum.Ref:
1545
+ case import_echo_schema10.TypeEnum.String:
1546
+ case import_echo_schema10.TypeEnum.Ref:
1132
1547
  return String(value);
1133
1548
  default: {
1134
1549
  return String(value);
@@ -1139,20 +1554,20 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1139
1554
  return formatScalar(type);
1140
1555
  }
1141
1556
  switch (format) {
1142
- case import_echo_schema7.FormatEnum.Boolean: {
1143
- return formatScalar(import_echo_schema7.TypeEnum.Boolean);
1557
+ case import_echo_schema10.FormatEnum.Boolean: {
1558
+ return formatScalar(import_echo_schema10.TypeEnum.Boolean);
1144
1559
  }
1145
- case import_echo_schema7.FormatEnum.Number: {
1146
- return formatScalar(import_echo_schema7.TypeEnum.Number);
1560
+ case import_echo_schema10.FormatEnum.Number: {
1561
+ return formatScalar(import_echo_schema10.TypeEnum.Number);
1147
1562
  }
1148
- case import_echo_schema7.FormatEnum.String:
1149
- case import_echo_schema7.FormatEnum.Ref: {
1150
- return formatScalar(import_echo_schema7.TypeEnum.String);
1563
+ case import_echo_schema10.FormatEnum.String:
1564
+ case import_echo_schema10.FormatEnum.Ref: {
1565
+ return formatScalar(import_echo_schema10.TypeEnum.String);
1151
1566
  }
1152
- case import_echo_schema7.FormatEnum.Percent: {
1567
+ case import_echo_schema10.FormatEnum.Percent: {
1153
1568
  return `${value * 100}%`;
1154
1569
  }
1155
- case import_echo_schema7.FormatEnum.Currency: {
1570
+ case import_echo_schema10.FormatEnum.Currency: {
1156
1571
  return value.toLocaleString(locale, {
1157
1572
  style: "currency",
1158
1573
  currency: "USD",
@@ -1160,18 +1575,28 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1160
1575
  maximumFractionDigits: 2
1161
1576
  });
1162
1577
  }
1163
- case import_echo_schema7.FormatEnum.DateTime:
1164
- case import_echo_schema7.FormatEnum.Date:
1165
- case import_echo_schema7.FormatEnum.Time: {
1578
+ case import_echo_schema10.FormatEnum.DateTime:
1579
+ case import_echo_schema10.FormatEnum.Date:
1580
+ case import_echo_schema10.FormatEnum.Time: {
1166
1581
  const date = new Date(value);
1167
- if (format === import_echo_schema7.FormatEnum.DateTime) {
1582
+ if (format === import_echo_schema10.FormatEnum.DateTime) {
1168
1583
  return date.toLocaleString(locale);
1169
- } else if (format === import_echo_schema7.FormatEnum.Date) {
1584
+ } else if (format === import_echo_schema10.FormatEnum.Date) {
1170
1585
  return date.toLocaleDateString(locale);
1171
1586
  } else {
1172
1587
  return date.toLocaleTimeString(locale);
1173
1588
  }
1174
1589
  }
1590
+ case import_echo_schema10.FormatEnum.GeoPoint: {
1591
+ if (value === null || value === void 0) {
1592
+ return "";
1593
+ }
1594
+ if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1595
+ const { latitude, longitude } = import_echo_schema10.GeoLocation.fromGeoPoint(value);
1596
+ return `${latitude},${longitude}`;
1597
+ }
1598
+ return String(value);
1599
+ }
1175
1600
  default: {
1176
1601
  if (value === null || value === "undefined") {
1177
1602
  return "";
@@ -1183,10 +1608,10 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1183
1608
  var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1184
1609
  const formatScalar = (type2) => {
1185
1610
  switch (type2) {
1186
- case import_echo_schema7.TypeEnum.Boolean:
1187
- case import_echo_schema7.TypeEnum.Number:
1188
- case import_echo_schema7.TypeEnum.String:
1189
- case import_echo_schema7.TypeEnum.Ref:
1611
+ case import_echo_schema10.TypeEnum.Boolean:
1612
+ case import_echo_schema10.TypeEnum.Number:
1613
+ case import_echo_schema10.TypeEnum.String:
1614
+ case import_echo_schema10.TypeEnum.Ref:
1190
1615
  return String(value);
1191
1616
  default:
1192
1617
  return String(value);
@@ -1196,30 +1621,40 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1196
1621
  return formatScalar(type);
1197
1622
  }
1198
1623
  switch (format) {
1199
- case import_echo_schema7.FormatEnum.Boolean:
1200
- case import_echo_schema7.FormatEnum.Number:
1201
- case import_echo_schema7.FormatEnum.String:
1202
- case import_echo_schema7.FormatEnum.Ref: {
1624
+ case import_echo_schema10.FormatEnum.Boolean:
1625
+ case import_echo_schema10.FormatEnum.Number:
1626
+ case import_echo_schema10.FormatEnum.String:
1627
+ case import_echo_schema10.FormatEnum.Ref: {
1203
1628
  return formatScalar(type);
1204
1629
  }
1205
- case import_echo_schema7.FormatEnum.Percent: {
1630
+ case import_echo_schema10.FormatEnum.Percent: {
1206
1631
  return String(value * 100);
1207
1632
  }
1208
- case import_echo_schema7.FormatEnum.Currency: {
1633
+ case import_echo_schema10.FormatEnum.Currency: {
1209
1634
  return String(value);
1210
1635
  }
1211
- case import_echo_schema7.FormatEnum.DateTime: {
1636
+ case import_echo_schema10.FormatEnum.DateTime: {
1212
1637
  const date = new Date(value);
1213
1638
  return date.toISOString();
1214
1639
  }
1215
- case import_echo_schema7.FormatEnum.Date: {
1640
+ case import_echo_schema10.FormatEnum.Date: {
1216
1641
  const date = new Date(value);
1217
1642
  return date.toISOString().split("T")[0];
1218
1643
  }
1219
- case import_echo_schema7.FormatEnum.Time: {
1644
+ case import_echo_schema10.FormatEnum.Time: {
1220
1645
  const date = new Date(value);
1221
1646
  return date.toISOString().split("T")[1].split(".")[0];
1222
1647
  }
1648
+ case import_echo_schema10.FormatEnum.GeoPoint: {
1649
+ if (value === null || value === void 0) {
1650
+ return "";
1651
+ }
1652
+ if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1653
+ const { latitude, longitude } = import_echo_schema10.GeoLocation.fromGeoPoint(value);
1654
+ return `${latitude},${longitude}`;
1655
+ }
1656
+ return String(value);
1657
+ }
1223
1658
  default: {
1224
1659
  return String(value);
1225
1660
  }
@@ -1228,14 +1663,16 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1228
1663
  // Annotate the CommonJS export names for ESM import in node:
1229
1664
  0 && (module.exports = {
1230
1665
  BooleanInput,
1666
+ DeprecatedFormContainer,
1231
1667
  DeprecatedFormInput,
1232
1668
  FieldEditor,
1233
1669
  Form,
1234
- FormActions,
1235
1670
  GeoPointInput,
1236
1671
  InputHeader,
1672
+ MarkdownInput,
1237
1673
  NumberInput,
1238
1674
  SelectInput,
1675
+ SelectOptionInput,
1239
1676
  TextInput,
1240
1677
  TupleInput,
1241
1678
  ViewEditor,
@@ -1246,6 +1683,7 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1246
1683
  parseValue,
1247
1684
  pathNotUniqueError,
1248
1685
  translations,
1249
- useForm
1686
+ useForm,
1687
+ useFormValues
1250
1688
  });
1251
1689
  //# sourceMappingURL=index.cjs.map