@dxos/react-ui-form 0.7.5-main.499c70c → 0.7.5-main.5ae2ba8

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 +1054 -575
  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 +1115 -647
  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 +1054 -575
  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 +96 -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 +116 -79
  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,44 @@ 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);
390
- };
391
- const onValueChange = (property, type, value) => {
302
+ const getFormValue = (0, import_react4.useCallback)((path) => {
303
+ return (0, import_echo_schema3.getValue)(values, (0, import_effect2.createJsonPath)(path));
304
+ }, [
305
+ values
306
+ ]);
307
+ const onValueChange = (0, import_react4.useCallback)((path, type, value) => {
308
+ const jsonPath = (0, import_effect2.createJsonPath)(path);
392
309
  let parsedValue = value;
393
310
  try {
394
311
  if (type === "number") {
395
312
  parsedValue = parseFloat(value) || 0;
396
313
  }
397
314
  } catch (err) {
398
- import_log3.log.catch(err, void 0, {
315
+ import_log2.log.catch(err, void 0, {
399
316
  F: __dxlog_file,
400
- L: 178,
317
+ L: 202,
401
318
  S: void 0,
402
319
  C: (f, a) => f(...a)
403
320
  });
404
321
  parsedValue = void 0;
405
322
  }
406
323
  const newValues = {
407
- ...(0, import_echo_schema4.setValue)(values, property, parsedValue)
324
+ ...(0, import_echo_schema3.setValue)(values, jsonPath, parsedValue)
408
325
  };
409
326
  setValues(newValues);
410
327
  setChanged((prev) => ({
411
328
  ...prev,
412
- [property]: true
329
+ [jsonPath]: true
413
330
  }));
414
331
  onValuesChanged?.(newValues);
415
332
  const isValid = validate(newValues);
@@ -418,349 +335,836 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
418
335
  changed
419
336
  });
420
337
  }
421
- };
422
- const onBlur = (0, import_react8.useCallback)((event) => {
423
- const { name } = event.target;
338
+ }, [
339
+ values,
340
+ onValuesChanged,
341
+ validate,
342
+ onValid,
343
+ changed
344
+ ]);
345
+ const onTouched = (0, import_react4.useCallback)((path) => {
346
+ const jsonPath = (0, import_effect2.createJsonPath)(path);
424
347
  setTouched((touched2) => ({
425
348
  ...touched2,
426
- [name]: true
349
+ [jsonPath]: true
427
350
  }));
428
- if (event.relatedTarget?.getAttribute("type") === "submit") {
429
- setTouched(createKeySet(values, true));
351
+ validate(values);
352
+ }, [
353
+ validate,
354
+ values
355
+ ]);
356
+ return (0, import_react4.useMemo)(() => ({
357
+ // State.
358
+ values,
359
+ errors,
360
+ touched,
361
+ changed,
362
+ canSave,
363
+ formIsValid,
364
+ // Actions.
365
+ handleSave,
366
+ // Field utils.
367
+ getStatus,
368
+ getValue: getFormValue,
369
+ onValueChange,
370
+ onTouched
371
+ }), [
372
+ values,
373
+ errors,
374
+ touched,
375
+ changed,
376
+ canSave,
377
+ formIsValid,
378
+ handleSave,
379
+ getStatus,
380
+ getFormValue,
381
+ onValueChange,
382
+ onTouched
383
+ ]);
384
+ };
385
+ var createKeySet = (obj, value) => {
386
+ (0, import_invariant.invariant)(obj, void 0, {
387
+ F: __dxlog_file,
388
+ L: 264,
389
+ S: void 0,
390
+ A: [
391
+ "obj",
392
+ ""
393
+ ]
394
+ });
395
+ return Object.keys(obj).reduce((acc, key) => ({
396
+ ...acc,
397
+ [key]: value
398
+ }), {});
399
+ };
400
+ var flatMap = (errors) => {
401
+ return errors.reduce((result, { path, message }) => {
402
+ const jsonPath = (0, import_effect2.fromEffectValidationPath)(path);
403
+ if (!(jsonPath in result)) {
404
+ result[jsonPath] = message;
405
+ }
406
+ return result;
407
+ }, {});
408
+ };
409
+ var FormContext = /* @__PURE__ */ (0, import_react3.createContext)(void 0);
410
+ var useFormContext = () => {
411
+ return (0, import_react3.useContext)(FormContext) ?? (0, import_debug.raise)(new Error("Missing FormContext"));
412
+ };
413
+ var useFormValues = (path = []) => {
414
+ const { values: formValues } = useFormContext();
415
+ const jsonPath = (0, import_effect.createJsonPath)(path);
416
+ return (0, import_echo_schema2.getValue)(formValues, jsonPath);
417
+ };
418
+ var useInputProps = (path = []) => {
419
+ const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
420
+ const stablePath = (0, import_react3.useMemo)(() => path, [
421
+ Array.isArray(path) ? path.join(".") : path
422
+ ]);
423
+ return (0, import_react3.useMemo)(() => ({
424
+ getStatus: () => getStatus(stablePath),
425
+ getValue: () => getFormValue(stablePath),
426
+ onValueChange: (type, value) => onValueChange(stablePath, type, value),
427
+ onBlur: () => onTouched(stablePath)
428
+ }), [
429
+ getStatus,
430
+ getFormValue,
431
+ onValueChange,
432
+ onTouched,
433
+ stablePath
434
+ ]);
435
+ };
436
+ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
437
+ const form = useForm(formOptions);
438
+ (0, import_react3.useEffect)(() => {
439
+ if (!formRef?.current) {
440
+ return;
441
+ }
442
+ const handleKeyDown = (event) => {
443
+ const keyIsEnter = event.key === "Enter";
444
+ const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
445
+ const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
446
+ const inputOptOut = event.target.hasAttribute("data-no-submit");
447
+ const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
448
+ const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
449
+ if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
450
+ if (!autoSave && form.canSave) {
451
+ form.handleSave();
452
+ }
453
+ if (autoSave && form.formIsValid) {
454
+ event.target.blur();
455
+ }
456
+ }
457
+ };
458
+ const formElement = formRef.current;
459
+ formElement.addEventListener("keydown", handleKeyDown);
460
+ return () => formElement.removeEventListener("keydown", handleKeyDown);
461
+ }, [
462
+ formRef,
463
+ form.canSave,
464
+ form.formIsValid,
465
+ form.handleSave,
466
+ autoSave
467
+ ]);
468
+ return /* @__PURE__ */ import_react3.default.createElement(FormContext.Provider, {
469
+ value: form
470
+ }, children);
471
+ };
472
+ var InputHeader = ({ children, error }) => {
473
+ return /* @__PURE__ */ import_react6.default.createElement("div", {
474
+ role: "none",
475
+ className: "flex justify-between items-center mb-1"
476
+ }, children, error && /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Root, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Trigger, {
477
+ asChild: true
478
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Icon, {
479
+ icon: "ph--warning--regular",
480
+ size: 4,
481
+ classNames: import_react_ui_theme2.errorText
482
+ })), /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Content, {
483
+ side: "bottom"
484
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui4.Tooltip.Arrow, null), error)));
485
+ };
486
+ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
487
+ const { t } = (0, import_react_ui3.useTranslation)(translationKey);
488
+ const { status, error } = getStatus();
489
+ const geoPoint = (0, import_react5.useMemo)(() => getValue3() ?? [
490
+ 0,
491
+ 0
492
+ ], [
493
+ getValue3
494
+ ]);
495
+ const geoLocation = (0, import_react5.useMemo)(() => import_echo_schema4.GeoLocation.fromGeoPoint(geoPoint), [
496
+ geoPoint
497
+ ]);
498
+ const [longitudeText, setLongitudeText] = (0, import_react5.useState)(geoLocation.longitude?.toString());
499
+ const [latitudeText, setLatitudeText] = (0, import_react5.useState)(geoLocation.latitude?.toString());
500
+ (0, import_react5.useEffect)(() => {
501
+ const location = import_echo_schema4.GeoLocation.fromGeoPoint(geoPoint);
502
+ setLongitudeText(location.longitude.toString());
503
+ setLatitudeText(location.latitude.toString());
504
+ }, [
505
+ geoPoint
506
+ ]);
507
+ const handleCoordinateChange = (0, import_react5.useCallback)((coordinateType, setText) => (event) => {
508
+ const inputText = event.target.value;
509
+ setText(inputText);
510
+ if (inputText !== "" && inputText !== "-") {
511
+ const coord = (0, import_util.safeParseFloat)(inputText);
512
+ if (coord !== void 0 && !isNaN(coord)) {
513
+ const currentLocation = import_echo_schema4.GeoLocation.fromGeoPoint(getValue3() ?? [
514
+ 0,
515
+ 0
516
+ ]);
517
+ const newLocation = {
518
+ ...currentLocation,
519
+ [coordinateType]: coord
520
+ };
521
+ const newValue = import_echo_schema4.GeoLocation.toGeoPoint(newLocation);
522
+ onValueChange(type, newValue);
523
+ }
524
+ }
525
+ }, [
526
+ getValue3,
527
+ onValueChange,
528
+ type
529
+ ]);
530
+ return /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.Root, {
531
+ validationValence: status
532
+ }, /* @__PURE__ */ import_react5.default.createElement(InputHeader, {
533
+ error
534
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.Label, null, label)), /* @__PURE__ */ import_react5.default.createElement("div", {
535
+ role: "none",
536
+ className: "grid grid-cols-2 gap-2"
537
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.TextInput, {
538
+ type: "text",
539
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
540
+ disabled,
541
+ placeholder: t("placeholder latitude"),
542
+ value: latitudeText,
543
+ onChange: handleCoordinateChange("latitude", setLatitudeText),
544
+ onBlur
545
+ }), /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Input.TextInput, {
546
+ type: "text",
547
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
548
+ disabled,
549
+ placeholder: t("placeholder longitude"),
550
+ value: longitudeText,
551
+ onChange: handleCoordinateChange("longitude", setLongitudeText),
552
+ onBlur
553
+ })));
554
+ };
555
+ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
556
+ const [selected, setSelectedId] = (0, import_react7.useState)(null);
557
+ const [isNewOption, setIsNewOption] = (0, import_react7.useState)(false);
558
+ const inputRef = (0, import_react7.useRef)(null);
559
+ const { t } = (0, import_react_ui5.useTranslation)(translationKey);
560
+ const { status, error } = getStatus();
561
+ const options = getValue3();
562
+ (0, import_react7.useEffect)(() => {
563
+ if (options === void 0) {
564
+ onValueChange(type, []);
565
+ }
566
+ }, [
567
+ options,
568
+ onValueChange,
569
+ type
570
+ ]);
571
+ const randomHue = () => {
572
+ const usedHues = new Set(options?.map((option) => option.color) ?? []);
573
+ const unusedHues = import_react_ui_theme3.hues.filter((hue) => !usedHues.has(hue));
574
+ if (unusedHues.length > 0) {
575
+ return unusedHues[Math.floor(Math.random() * unusedHues.length)];
576
+ }
577
+ const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
578
+ const availableHues = import_react_ui_theme3.hues.filter((hue) => !lastThree.has(hue));
579
+ return availableHues[Math.floor(Math.random() * availableHues.length)] ?? import_react_ui_theme3.hues[Math.floor(Math.random() * import_react_ui_theme3.hues.length)];
580
+ };
581
+ const handleAdd = (0, import_react7.useCallback)(() => {
582
+ const newId = import_keys.PublicKey.random().truncate();
583
+ const newOption = {
584
+ id: newId,
585
+ title: "",
586
+ color: randomHue()
587
+ };
588
+ onValueChange(type, [
589
+ ...options ?? [],
590
+ newOption
591
+ ]);
592
+ setSelectedId(newId);
593
+ setIsNewOption(true);
594
+ }, [
595
+ options,
596
+ type,
597
+ onValueChange
598
+ ]);
599
+ const handleDelete = (0, import_react7.useCallback)((id) => {
600
+ const newOptions = options?.filter((option) => option.id !== id) ?? [];
601
+ onValueChange(type, newOptions);
602
+ setSelectedId(null);
603
+ }, [
604
+ options,
605
+ type,
606
+ onValueChange
607
+ ]);
608
+ const handleMove = (0, import_react7.useCallback)((from, to) => {
609
+ if (!options) {
610
+ return;
611
+ }
612
+ const newOptions = [
613
+ ...options
614
+ ];
615
+ const [removed] = newOptions.splice(from, 1);
616
+ newOptions.splice(to, 0, removed);
617
+ onValueChange(type, newOptions);
618
+ }, [
619
+ options,
620
+ type,
621
+ onValueChange
622
+ ]);
623
+ const handleClick = (0, import_react7.useCallback)((id) => {
624
+ setSelectedId((current) => current === id ? null : id);
625
+ }, []);
626
+ const handleTitleChange = (0, import_react7.useCallback)((id) => (e) => {
627
+ const newOptions = options?.map((o) => o.id === id ? {
628
+ ...o,
629
+ title: e.target.value
630
+ } : o);
631
+ onValueChange(type, newOptions ?? []);
632
+ }, [
633
+ options,
634
+ type,
635
+ onValueChange
636
+ ]);
637
+ const handleKeyDown = (0, import_react7.useCallback)((e) => {
638
+ if (e.key === "Enter") {
639
+ setSelectedId(null);
640
+ }
641
+ }, []);
642
+ const handleColorChange = (0, import_react7.useCallback)((id) => (hue) => {
643
+ const newOptions = options?.map((o) => o.id === id ? {
644
+ ...o,
645
+ color: hue
646
+ } : o);
647
+ onValueChange(type, newOptions ?? []);
648
+ }, [
649
+ options,
650
+ type,
651
+ onValueChange
652
+ ]);
653
+ (0, import_react7.useEffect)(() => {
654
+ if (selected && isNewOption && inputRef.current) {
655
+ inputRef.current.focus();
656
+ setIsNewOption(false);
657
+ }
658
+ }, [
659
+ selected,
660
+ isNewOption
661
+ ]);
662
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Root, {
663
+ validationValence: status
664
+ }, /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
665
+ error
666
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement("div", {
667
+ role: "none"
668
+ }, options && /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.Root, {
669
+ items: options,
670
+ isItem: (item) => true,
671
+ onMove: handleMove
672
+ }, ({ items }) => /* @__PURE__ */ import_react7.default.createElement("div", {
673
+ role: "list",
674
+ className: "w-full overflow-auto"
675
+ }, items?.map((item) => /* @__PURE__ */ import_react7.default.createElement("div", {
676
+ key: item.id
677
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.Item, {
678
+ role: "button",
679
+ item,
680
+ classNames: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
681
+ "aria-expanded": selected === item.id
682
+ }, /* @__PURE__ */ import_react7.default.createElement("div", {
683
+ className: "flex items-center"
684
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.ItemDragHandle, null), /* @__PURE__ */ import_react7.default.createElement(import_react_ui_list.List.ItemTitle, {
685
+ onClick: () => handleClick(item.id),
686
+ classNames: "flex-1"
687
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Tag, {
688
+ palette: item.color
689
+ }, item.title || "\u200B")), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Icon, {
690
+ icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
691
+ onClick: () => handleClick(item.id)
692
+ })), selected === item.id && /* @__PURE__ */ import_react7.default.createElement("div", {
693
+ className: "mis-4 mbs-2 flex flex-col gap-1"
694
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.Label, {
695
+ classNames: "text-xs"
696
+ }, t("select option label")), /* @__PURE__ */ import_react7.default.createElement("div", {
697
+ className: "flex flex-row items-center gap-1"
698
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Input.TextInput, {
699
+ placeholder: t("select option label placeholder"),
700
+ ref: selected === item.id ? inputRef : void 0,
701
+ value: item.title,
702
+ onChange: handleTitleChange(item.id),
703
+ onKeyDown: handleKeyDown,
704
+ classNames: "flex-1",
705
+ "data-no-submit": true
706
+ }), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Toolbar.Root, {
707
+ classNames: "p-0 m-0 !is-auto"
708
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui_pickers.HuePicker, {
709
+ value: item.color,
710
+ onChange: handleColorChange(item.id)
711
+ })), /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.IconButton, {
712
+ icon: "ph--trash--fill",
713
+ iconOnly: true,
714
+ label: t("select option delete"),
715
+ onClick: () => handleDelete(item.id)
716
+ })))))), /* @__PURE__ */ import_react7.default.createElement("div", {
717
+ role: "listitem"
718
+ }, /* @__PURE__ */ import_react7.default.createElement("div", {
719
+ role: "button",
720
+ className: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
721
+ onClick: handleAdd
722
+ }, /* @__PURE__ */ import_react7.default.createElement("div", {
723
+ className: "flex items-center gap-1"
724
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui5.Icon, {
725
+ icon: "ph--plus--regular"
726
+ }), /* @__PURE__ */ import_react7.default.createElement("span", {
727
+ className: "text-sm"
728
+ }, t("select option add")))))))));
729
+ };
730
+ var gridCols = [
731
+ "grid-cols-1",
732
+ "grid-cols-2",
733
+ "grid-cols-3",
734
+ "grid-cols-4"
735
+ ];
736
+ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
737
+ const { status, error } = getStatus();
738
+ const values = getValue3() ?? {};
739
+ return /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.Root, {
740
+ validationValence: status
741
+ }, /* @__PURE__ */ import_react8.default.createElement(InputHeader, {
742
+ error
743
+ }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react8.default.createElement("div", {
744
+ className: (0, import_react_ui_theme4.mx)("grid gap-2", gridCols[binding.length - 1])
745
+ }, binding.map((prop) => /* @__PURE__ */ import_react8.default.createElement(import_react_ui6.Input.TextInput, {
746
+ key: prop,
747
+ type: "number",
748
+ disabled,
749
+ value: values[prop],
750
+ onChange: (event) => onValueChange(type, {
751
+ ...values,
752
+ [prop]: (0, import_util2.safeParseFloat)(event.target.value, 0)
753
+ }),
754
+ onBlur
755
+ }))));
756
+ };
757
+ var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
758
+ const { status, error } = getStatus();
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.TextInput, {
764
+ disabled,
765
+ placeholder,
766
+ value: getValue3() ?? "",
767
+ onChange: (event) => onValueChange(type, event.target.value),
768
+ onBlur
769
+ }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Validation, null, error));
770
+ };
771
+ var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
772
+ const { status, error } = getStatus();
773
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
774
+ validationValence: status
775
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
776
+ error
777
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.TextInput, {
778
+ type: "number",
779
+ disabled,
780
+ placeholder,
781
+ value: getValue3() ?? 0,
782
+ onChange: (event) => onValueChange(type, event.target.value),
783
+ onBlur
784
+ }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
785
+ };
786
+ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
787
+ const { status, error } = getStatus();
788
+ const checked = Boolean(getValue3());
789
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
790
+ validationValence: status
791
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
792
+ error
793
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Switch, {
794
+ checked,
795
+ onCheckedChange: (value) => onValueChange(type, value)
796
+ }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
797
+ };
798
+ var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
799
+ const { status, error } = getStatus();
800
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
801
+ validationValence: status
802
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
803
+ error
804
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Root, {
805
+ value: getValue3(),
806
+ onValueChange: (value) => onValueChange(type, value)
807
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.TriggerButton, {
808
+ classNames: "is-full",
809
+ disabled,
810
+ placeholder
811
+ }), /* @__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 }) => (
812
+ // NOTE: Numeric values are converted to and from strings.
813
+ /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Select.Option, {
814
+ key: String(value),
815
+ value: String(value)
816
+ }, label2 ?? String(value))
817
+ )))))), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
818
+ };
819
+ var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
820
+ const { status, error } = getStatus();
821
+ const textareaRef = (0, import_react9.useRef)(null);
822
+ const adjustHeight = (0, import_react9.useCallback)(() => {
823
+ const textarea = textareaRef.current;
824
+ if (textarea) {
825
+ textarea.style.blockSize = "auto";
826
+ textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
430
827
  }
431
- validate(values);
828
+ }, []);
829
+ (0, import_react9.useEffect)(() => {
830
+ adjustHeight();
432
831
  }, [
433
- validate,
434
- values
832
+ adjustHeight
435
833
  ]);
436
- return {
437
- // State.
438
- values,
439
- errors,
440
- touched,
441
- changed,
442
- canSave,
443
- handleSave,
444
- // Field utils.
445
- getStatus,
446
- getValue: getFormValue,
447
- onValueChange,
448
- onBlur
449
- };
834
+ (0, import_react9.useEffect)(() => {
835
+ adjustHeight();
836
+ }, [
837
+ getValue3(),
838
+ adjustHeight
839
+ ]);
840
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Root, {
841
+ validationValence: status
842
+ }, !inputOnly && /* @__PURE__ */ import_react9.default.createElement(InputHeader, {
843
+ error
844
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.TextArea, {
845
+ ref: textareaRef,
846
+ disabled,
847
+ placeholder,
848
+ value: getValue3() ?? "",
849
+ classNames: "min-bs-auto max-h-40 overflow-auto",
850
+ onChange: (event) => onValueChange(type, event.target.value),
851
+ onBlur,
852
+ style: {
853
+ resize: "none"
854
+ },
855
+ spellCheck: false
856
+ }), inputOnly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui7.Input.Validation, null, error));
450
857
  };
451
- var createKeySet = (obj, value) => {
452
- (0, import_invariant.invariant)(obj, void 0, {
453
- F: __dxlog_file,
454
- L: 229,
858
+ var FormActions = ({ onCancel, readonly }) => {
859
+ const { t } = (0, import_react_ui8.useTranslation)(translationKey);
860
+ const { canSave, handleSave } = useFormContext();
861
+ return /* @__PURE__ */ import_react11.default.createElement("div", {
862
+ role: "none",
863
+ className: "mt-2 flex justify-center"
864
+ }, /* @__PURE__ */ import_react11.default.createElement("div", {
865
+ role: "none",
866
+ className: (0, import_react_ui_theme6.mx)(onCancel && !readonly && "grid grid-cols-2 gap-2")
867
+ }, onCancel && !readonly && /* @__PURE__ */ import_react11.default.createElement(import_react_ui8.IconButton, {
868
+ "data-testid": "cancel-button",
869
+ icon: "ph--x--regular",
870
+ label: t("button cancel"),
871
+ onClick: onCancel
872
+ }), handleSave && /* @__PURE__ */ import_react11.default.createElement(import_react_ui8.IconButton, {
873
+ type: "submit",
874
+ "data-testid": "save-button",
875
+ disabled: !canSave,
876
+ icon: "ph--check--regular",
877
+ label: t("button save"),
878
+ onClick: handleSave
879
+ })));
880
+ };
881
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
882
+ var padding = "px-2";
883
+ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
884
+ const { t } = (0, import_react_ui9.useTranslation)(translationKey);
885
+ const { ast, name, type, title } = property;
886
+ const values = useFormValues(path ?? []);
887
+ (0, import_invariant2.invariant)(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
888
+ F: __dxlog_file2,
889
+ L: 37,
455
890
  S: void 0,
456
891
  A: [
457
- "obj",
458
- ""
892
+ "Array.isArray(values)",
893
+ "`Values at path ${path?.join('.')} must be an array.`"
459
894
  ]
460
895
  });
461
- return Object.keys(obj).reduce((acc, key) => ({
462
- ...acc,
463
- [key]: value
464
- }), {});
465
- };
466
- var flatMap = (errors) => {
467
- return errors.reduce((result, { path, message }) => {
468
- if (!(path in result)) {
469
- result[path] = message;
896
+ const label = title ?? (0, import_effect5.pipe)(name, import_String2.capitalize);
897
+ const tupleType = (0, import_effect6.findNode)(ast, import_echo_schema6.AST.isTupleType);
898
+ const elementType = tupleType?.rest[0]?.type;
899
+ const getDefaultObjectValue = (typeNode) => {
900
+ const baseNode = (0, import_effect6.findNode)(typeNode, import_effect6.isDiscriminatedUnion);
901
+ const typeLiteral = baseNode ? (0, import_effect6.getDiscriminatedType)(baseNode, {}) : (0, import_effect6.findNode)(typeNode, import_echo_schema6.AST.isTypeLiteral);
902
+ if (!typeLiteral) {
903
+ return {};
470
904
  }
471
- return result;
472
- }, {});
473
- };
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
905
+ return Object.fromEntries((0, import_schema4.getSchemaProperties)(typeLiteral, {}).map((prop) => [
906
+ prop.name,
907
+ prop.defaultValue
908
+ ]));
909
+ };
910
+ const newValue = (0, import_react13.useMemo)(() => {
911
+ if (type === "object" && elementType) {
912
+ return getDefaultObjectValue(elementType);
913
+ } else {
914
+ return import_effect6.SimpleType.getDefaultValue(type);
915
+ }
916
+ }, [
917
+ type,
918
+ elementType
480
919
  ]);
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;
495
- };
496
- return sort ? filtered.sort(({ name: a }, { name: b }) => findIndex(sort, a) - findIndex(sort, b)) : filtered;
920
+ const handleAdd = (0, import_react13.useCallback)(() => {
921
+ inputProps.onValueChange(type, [
922
+ ...values,
923
+ newValue
924
+ ]);
497
925
  }, [
498
- schema,
499
- filter,
926
+ type,
927
+ elementType,
928
+ inputProps,
929
+ newValue,
500
930
  values
501
931
  ]);
502
- (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
- });
512
- }
932
+ const handleRemove = (0, import_react13.useCallback)((index) => {
933
+ const newValues = values.filter((_, i) => i !== index);
934
+ inputProps.onValueChange(type, newValues);
513
935
  }, [
514
- errors
936
+ type,
937
+ inputProps,
938
+ values
515
939
  ]);
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
525
- ];
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
- }
566
- }
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;
599
- }
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
- }));
619
- };
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);
627
- 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
- })));
687
- }
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) {
940
+ if (!elementType) {
695
941
  return null;
696
942
  }
697
- return /* @__PURE__ */ import_react7.default.createElement("div", {
943
+ return /* @__PURE__ */ import_react13.default.createElement("div", {
698
944
  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", {
945
+ className: (0, import_react_ui_theme8.mx)(padding)
946
+ }, /* @__PURE__ */ import_react13.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react13.default.createElement("div", {
702
947
  role: "none",
703
948
  className: "flex flex-col gap-1"
704
- }, arrayValues.map((_, index) => /* @__PURE__ */ import_react7.default.createElement("div", {
949
+ }, values.map((_value, index) => /* @__PURE__ */ import_react13.default.createElement("div", {
705
950
  key: index,
706
951
  role: "none",
707
- className: "flex items-start gap-1"
708
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
952
+ className: "flex items-center gap-1"
953
+ }, /* @__PURE__ */ import_react13.default.createElement("div", {
709
954
  role: "none",
710
955
  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, {
956
+ }, /* @__PURE__ */ import_react13.default.createElement(FormField, {
957
+ property: {
958
+ ...property,
959
+ array: false,
960
+ ast: elementType
961
+ },
962
+ path: [
963
+ ...path ?? [],
964
+ index
965
+ ],
966
+ readonly,
967
+ inline: true,
968
+ Custom,
969
+ lookupComponent
970
+ })), /* @__PURE__ */ import_react13.default.createElement(import_react_ui9.IconButton, {
721
971
  icon: "ph--trash--regular",
722
972
  iconOnly: true,
723
973
  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", {
974
+ onClick: () => handleRemove(index)
975
+ })))), /* @__PURE__ */ import_react13.default.createElement("div", {
729
976
  role: "none",
730
977
  className: "flex justify-between items-center plb-1"
731
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
978
+ }, /* @__PURE__ */ import_react13.default.createElement(import_react_ui9.IconButton, {
732
979
  icon: "ph--plus--regular",
733
980
  iconOnly: true,
734
981
  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
- }
982
+ onClick: handleAdd
742
983
  })));
743
984
  };
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", {
985
+ var getInputComponent = (type, format) => {
986
+ switch (format) {
987
+ case import_echo_schema7.FormatEnum.GeoPoint:
988
+ return GeoPointInput;
989
+ case import_echo_schema7.FormatEnum.Markdown:
990
+ return MarkdownInput;
991
+ }
992
+ switch (type) {
993
+ case "string":
994
+ return TextInput;
995
+ case "number":
996
+ return NumberInput;
997
+ case "boolean":
998
+ return BooleanInput;
999
+ }
1000
+ };
1001
+ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom }) => {
1002
+ const inputProps = useInputProps(path);
1003
+ const { ast, name, type, format, title, description, options, examples, array } = property;
1004
+ const label = (0, import_react12.useMemo)(() => title ?? (0, import_effect3.pipe)(name, import_String.capitalize), [
1005
+ title,
1006
+ name
1007
+ ]);
1008
+ const placeholder = (0, import_react12.useMemo)(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1009
+ examples,
1010
+ description
1011
+ ]);
1012
+ const FoundComponent = lookupComponent?.({
1013
+ prop: name,
1014
+ schema: import_echo_schema5.S.make(ast),
1015
+ inputProps: {
1016
+ type,
1017
+ format,
1018
+ label,
1019
+ disabled: readonly,
1020
+ placeholder,
1021
+ ...inputProps
1022
+ }
1023
+ });
1024
+ if (FoundComponent) {
1025
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1026
+ role: "none"
1027
+ }, FoundComponent);
1028
+ }
1029
+ const jsonPath = (0, import_effect4.createJsonPath)(path ?? []);
1030
+ const CustomComponent = Custom?.[jsonPath];
1031
+ if (CustomComponent) {
1032
+ return /* @__PURE__ */ import_react12.default.createElement(CustomComponent, {
1033
+ type,
1034
+ format,
1035
+ label,
1036
+ inputOnly: inline,
1037
+ placeholder,
1038
+ disabled: readonly,
1039
+ ...inputProps
1040
+ });
1041
+ }
1042
+ if (array) {
1043
+ return /* @__PURE__ */ import_react12.default.createElement(ArrayField, {
1044
+ property,
1045
+ path,
1046
+ inputProps,
1047
+ readonly,
1048
+ Custom
1049
+ });
1050
+ }
1051
+ const InputComponent = getInputComponent(type, format);
1052
+ if (InputComponent) {
1053
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1054
+ role: "none"
1055
+ }, /* @__PURE__ */ import_react12.default.createElement(InputComponent, {
1056
+ type,
1057
+ format,
1058
+ label,
1059
+ inputOnly: inline,
1060
+ placeholder,
1061
+ disabled: readonly,
1062
+ ...inputProps
1063
+ }));
1064
+ }
1065
+ if (options) {
1066
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1067
+ role: "none"
1068
+ }, /* @__PURE__ */ import_react12.default.createElement(SelectInput, {
1069
+ type,
1070
+ format,
1071
+ disabled: readonly,
1072
+ inputOnly: inline,
1073
+ label,
1074
+ options: options.map((option) => ({
1075
+ value: option,
1076
+ label: String(option)
1077
+ })),
1078
+ placeholder,
1079
+ ...inputProps
1080
+ }));
1081
+ }
1082
+ if (type === "object") {
1083
+ const baseNode = (0, import_effect4.findNode)(ast, import_effect4.isDiscriminatedUnion);
1084
+ const typeLiteral = baseNode ? (0, import_effect4.getDiscriminatedType)(baseNode, inputProps.getValue()) : (0, import_effect4.findNode)(ast, import_echo_schema5.AST.isTypeLiteral);
1085
+ if (typeLiteral) {
1086
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1087
+ role: "none"
1088
+ }, !inline && /* @__PURE__ */ import_react12.default.createElement("div", null, label), /* @__PURE__ */ import_react12.default.createElement(FormFields, {
1089
+ schema: import_echo_schema5.S.make(typeLiteral),
1090
+ path,
1091
+ readonly,
1092
+ Custom
1093
+ }));
1094
+ }
1095
+ }
1096
+ return null;
1097
+ };
1098
+ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custom }) => {
1099
+ const values = useFormValues(path);
1100
+ const properties = (0, import_react12.useMemo)(() => {
1101
+ const props = (0, import_schema3.getSchemaProperties)(schema.ast, values);
1102
+ const filtered = filter ? filter(props) : props;
1103
+ return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
1104
+ }, [
1105
+ schema,
1106
+ values,
1107
+ filter,
1108
+ sort
1109
+ ]);
1110
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
1111
+ role: "form",
1112
+ className: (0, import_react_ui_theme7.mx)("flex flex-col w-full gap-2")
1113
+ }, properties.map((property) => {
1114
+ return /* @__PURE__ */ import_react12.default.createElement(FormField, {
1115
+ key: property.name,
1116
+ property,
1117
+ path: [
1118
+ ...path ?? [],
1119
+ property.name
1120
+ ],
1121
+ readonly,
1122
+ lookupComponent,
1123
+ Custom
1124
+ });
1125
+ }).filter(import_util3.isNotFalsy));
1126
+ };
1127
+ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
1128
+ const formRef = (0, import_react10.useRef)(null);
1129
+ const onValid = (0, import_react10.useMemo)(() => autoSave ? onSave : void 0, [
1130
+ autoSave,
1131
+ onSave
1132
+ ]);
1133
+ (0, import_react10.useEffect)(() => {
1134
+ if (autoFocus && formRef.current) {
1135
+ const input = formRef.current.querySelector("input");
1136
+ if (input) {
1137
+ input.focus();
1138
+ }
1139
+ }
1140
+ }, [
1141
+ autoFocus
1142
+ ]);
1143
+ return /* @__PURE__ */ import_react10.default.createElement(FormProvider, {
1144
+ formRef,
1145
+ schema,
1146
+ autoSave,
1147
+ initialValues,
1148
+ onValuesChanged,
1149
+ onValidate,
1150
+ onValid,
1151
+ onSave
1152
+ }, /* @__PURE__ */ import_react10.default.createElement("div", {
1153
+ ref: formRef,
750
1154
  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
1155
+ className: (0, import_react_ui_theme5.mx)("p-2", classNames),
1156
+ "data-testid": testId
1157
+ }, /* @__PURE__ */ import_react10.default.createElement(FormFields, {
1158
+ schema,
1159
+ path,
1160
+ readonly,
1161
+ filter,
1162
+ sort,
1163
+ lookupComponent,
1164
+ Custom
1165
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ import_react10.default.createElement(FormActions, {
1166
+ onCancel,
1167
+ readonly
764
1168
  })));
765
1169
  };
766
1170
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
@@ -790,9 +1194,9 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
790
1194
  }, [
791
1195
  registry
792
1196
  ]);
793
- const [schema, setSchema] = (0, import_react2.useState)();
1197
+ const [referenceSchema, setReferenceSchema] = (0, import_react2.useState)();
794
1198
  (0, import_react2.useEffect)(() => {
795
- setSchema(schemas.find((schema2) => schema2.typename === props?.referenceSchema));
1199
+ setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
796
1200
  }, [
797
1201
  schemas,
798
1202
  props?.referenceSchema
@@ -810,9 +1214,15 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
810
1214
  fieldSchema: fieldSchema2
811
1215
  };
812
1216
  });
813
- if (_props.referenceSchema !== props.referenceSchema) {
814
- setSchema(schemas.find((schema2) => schema2.typename === _props.referenceSchema));
815
- }
1217
+ setReferenceSchema((prev) => {
1218
+ if (_props.referenceSchema !== prev?.typename) {
1219
+ const newSchema = schemas.find((schema) => schema.typename === _props.referenceSchema);
1220
+ if (newSchema) {
1221
+ return newSchema;
1222
+ }
1223
+ }
1224
+ return prev;
1225
+ });
816
1226
  setProps((props2) => {
817
1227
  const type = import_echo_schema.formatToType[_props.format];
818
1228
  if (props2.type !== type) {
@@ -822,7 +1232,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
822
1232
  type
823
1233
  };
824
1234
  }
825
- return props2;
1235
+ return _props;
826
1236
  });
827
1237
  }, [
828
1238
  schemas,
@@ -859,12 +1269,39 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
859
1269
  }, [
860
1270
  onSave
861
1271
  ]);
1272
+ const Custom = (0, import_react2.useMemo)(() => ({
1273
+ ["format"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
1274
+ ...props2,
1275
+ options: import_echo_schema.FormatEnums.filter((value) => value !== import_echo_schema.FormatEnum.None).map((value) => ({
1276
+ value,
1277
+ label: t(`format ${value}`)
1278
+ }))
1279
+ }),
1280
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
1281
+ ...props2,
1282
+ options: schemas.map((schema) => ({
1283
+ value: schema.typename
1284
+ }))
1285
+ }),
1286
+ ["referencePath"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
1287
+ ...props2,
1288
+ options: referenceSchema ? (0, import_schema.getSchemaProperties)(referenceSchema.ast).sort(import_schema.sortProperties).map((p) => ({
1289
+ value: p.name
1290
+ })) : []
1291
+ }),
1292
+ ["options"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectOptionInput, props2)
1293
+ }), [
1294
+ t,
1295
+ schemas,
1296
+ referenceSchema
1297
+ ]);
1298
+ const propIsNotType = (0, import_react2.useCallback)((props2) => props2.filter((p) => p.name !== "type"), []);
862
1299
  if (!fieldSchema) {
863
1300
  import_log.log.warn("invalid format", {
864
1301
  props
865
1302
  }, {
866
1303
  F: __dxlog_file3,
867
- L: 126,
1304
+ L: 174,
868
1305
  S: void 0,
869
1306
  C: (f, a) => f(...a)
870
1307
  });
@@ -875,7 +1312,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
875
1312
  autoFocus: true,
876
1313
  values: props,
877
1314
  schema: fieldSchema,
878
- filter: (props2) => props2.filter((p) => p.name !== "type"),
1315
+ filter: propIsNotType,
879
1316
  sort: [
880
1317
  "property",
881
1318
  "format"
@@ -884,46 +1321,26 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
884
1321
  onValidate: handleValidate,
885
1322
  onSave: handleSave,
886
1323
  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
- }
1324
+ Custom
908
1325
  });
909
1326
  };
910
1327
  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"
1328
+ var ViewMetaSchema = import_echo_schema8.S.Struct({
1329
+ name: import_echo_schema8.S.String.annotations({
1330
+ [import_echo_schema8.AST.TitleAnnotationId]: "View"
914
1331
  }),
915
- typename: import_echo_schema5.Format.DXN.annotations({
916
- [import_echo_schema5.AST.TitleAnnotationId]: "Typename"
1332
+ typename: import_echo_schema8.Format.URL.annotations({
1333
+ [import_echo_schema8.AST.TitleAnnotationId]: "Typename"
917
1334
  })
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), [
1335
+ }).pipe(import_echo_schema8.S.mutable);
1336
+ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
1337
+ const { t } = (0, import_react_ui10.useTranslation)(translationKey);
1338
+ const projection = (0, import_react14.useMemo)(() => new import_schema5.ViewProjection(schema, view), [
922
1339
  schema,
923
1340
  view
924
1341
  ]);
925
- const [field, setField] = (0, import_react9.useState)();
926
- const viewValues = (0, import_react9.useMemo)(() => {
1342
+ const [field, setField] = (0, import_react14.useState)();
1343
+ const viewValues = (0, import_react14.useMemo)(() => {
927
1344
  return {
928
1345
  name: view.name,
929
1346
  // TODO(burdon): Need to warn user of possible consequences of editing.
@@ -933,82 +1350,90 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
933
1350
  }, [
934
1351
  view
935
1352
  ]);
936
- const handleViewUpdate = (0, import_react9.useCallback)(({ name, typename }) => {
1353
+ const handleViewUpdate = (0, import_react14.useCallback)(({ name, typename }) => {
937
1354
  requestAnimationFrame(() => {
938
- view.name = name;
939
- view.query.type = typename;
940
- schema.updateTypename(typename);
1355
+ if (view.name !== name) {
1356
+ view.name = name;
1357
+ }
1358
+ if (view.query.type !== typename) {
1359
+ onTypenameChanged(typename);
1360
+ }
941
1361
  });
942
1362
  }, [
943
1363
  view,
944
- schema
1364
+ schema,
1365
+ onTypenameChanged
945
1366
  ]);
946
- const handleSelect = (0, import_react9.useCallback)((field2) => {
1367
+ const handleSelect = (0, import_react14.useCallback)((field2) => {
947
1368
  setField((f) => f === field2 ? void 0 : field2);
948
1369
  }, []);
949
- const handleAdd = (0, import_react9.useCallback)(() => {
1370
+ const handleAdd = (0, import_react14.useCallback)(() => {
950
1371
  const field2 = projection.createFieldProjection();
951
1372
  setField(field2);
952
1373
  }, [
953
1374
  view
954
1375
  ]);
955
- const handleMove = (0, import_react9.useCallback)((fromIndex, toIndex) => {
956
- (0, import_util4.arrayMove)(view.fields, fromIndex, toIndex);
1376
+ const handleMove = (0, import_react14.useCallback)((fromIndex, toIndex) => {
1377
+ const fields = [
1378
+ ...view.fields
1379
+ ];
1380
+ const [moved] = fields.splice(fromIndex, 1);
1381
+ fields.splice(toIndex, 0, moved);
1382
+ view.fields = fields;
957
1383
  }, [
958
1384
  view.fields
959
1385
  ]);
960
- const handleClose = (0, import_react9.useCallback)(() => setField(void 0), []);
961
- return /* @__PURE__ */ import_react9.default.createElement("div", {
1386
+ const handleClose = (0, import_react14.useCallback)(() => setField(void 0), []);
1387
+ return /* @__PURE__ */ import_react14.default.createElement("div", {
962
1388
  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,
1389
+ className: (0, import_react_ui_theme9.mx)("flex flex-col w-full divide-y divide-separator", classNames)
1390
+ }, /* @__PURE__ */ import_react14.default.createElement(Form, {
966
1391
  autoSave: true,
967
1392
  schema: ViewMetaSchema,
968
1393
  values: viewValues,
969
1394
  onSave: handleViewUpdate
970
- }), /* @__PURE__ */ import_react9.default.createElement("div", null, /* @__PURE__ */ import_react9.default.createElement("div", {
1395
+ }), /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("div", {
971
1396
  role: "none",
972
1397
  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, {
1398
+ }, /* @__PURE__ */ import_react14.default.createElement("label", {
1399
+ className: (0, import_react_ui_theme9.mx)(import_react_ui_theme9.inputTextLabel)
1400
+ }, t("fields label"))), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.Root, {
976
1401
  items: view.fields,
977
- isItem: import_echo_schema5.S.is(import_schema4.FieldSchema),
1402
+ isItem: import_echo_schema8.S.is(import_schema5.FieldSchema),
978
1403
  getId: (field2) => field2.id,
979
1404
  onMove: handleMove
980
- }, ({ items: fields }) => /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, showHeading && /* @__PURE__ */ import_react9.default.createElement("div", {
1405
+ }, ({ items: fields }) => /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, showHeading && /* @__PURE__ */ import_react14.default.createElement("div", {
981
1406
  role: "heading",
982
1407
  className: grid
983
- }, /* @__PURE__ */ import_react9.default.createElement("div", null), /* @__PURE__ */ import_react9.default.createElement("div", {
1408
+ }, /* @__PURE__ */ import_react14.default.createElement("div", null), /* @__PURE__ */ import_react14.default.createElement("div", {
984
1409
  className: "flex items-center text-sm"
985
- }, t("field path label"))), /* @__PURE__ */ import_react9.default.createElement("div", {
1410
+ }, t("field path label"))), /* @__PURE__ */ import_react14.default.createElement("div", {
986
1411
  role: "list",
987
1412
  className: "flex flex-col w-full"
988
- }, fields?.map((field2) => /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.Item, {
1413
+ }, fields?.map((field2) => /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.Item, {
989
1414
  key: field2.id,
990
1415
  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, {
1416
+ classNames: (0, import_react_ui_theme9.mx)(grid, import_react_ui_theme9.ghostHover, "cursor-pointer")
1417
+ }, /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemDragHandle, null), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemTitle, {
993
1418
  onClick: () => handleSelect(field2)
994
- }, field2.path), /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.ItemDeleteButton, {
1419
+ }, field2.path), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemDeleteButton, {
995
1420
  disabled: view.fields.length <= 1,
996
1421
  onClick: () => onDelete(field2.id)
997
- }))))))), field && /* @__PURE__ */ import_react9.default.createElement(FieldEditor, {
1422
+ }))))))), field && /* @__PURE__ */ import_react14.default.createElement(FieldEditor, {
998
1423
  key: field.id,
999
1424
  view,
1000
1425
  projection,
1001
1426
  field,
1002
1427
  registry,
1003
1428
  onSave: handleClose
1004
- }), !readonly && !field && /* @__PURE__ */ import_react9.default.createElement("div", {
1429
+ }), !readonly && !field && /* @__PURE__ */ import_react14.default.createElement("div", {
1005
1430
  className: "flex p-2 justify-center"
1006
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.IconButton, {
1431
+ }, /* @__PURE__ */ import_react14.default.createElement(import_react_ui10.IconButton, {
1007
1432
  icon: "ph--plus--regular",
1008
1433
  label: t("button add property"),
1009
1434
  onClick: handleAdd,
1010
1435
  // TODO(burdon): Show field limit in ux (not tooltip).
1011
- disabled: view.fields.length >= import_schema4.VIEW_FIELD_LIMIT
1436
+ disabled: view.fields.length >= import_schema5.VIEW_FIELD_LIMIT
1012
1437
  })));
1013
1438
  };
1014
1439
  var parseValue = ({ type, format, value }) => {
@@ -1017,7 +1442,7 @@ var parseValue = ({ type, format, value }) => {
1017
1442
  }
1018
1443
  const parseScalar = (type2) => {
1019
1444
  switch (type2) {
1020
- case import_echo_schema6.TypeEnum.Boolean: {
1445
+ case import_echo_schema9.TypeEnum.Boolean: {
1021
1446
  if (typeof value === "string") {
1022
1447
  const lowercaseValue = value.toLowerCase();
1023
1448
  if (lowercaseValue === "0" || lowercaseValue === "false") {
@@ -1028,13 +1453,13 @@ var parseValue = ({ type, format, value }) => {
1028
1453
  }
1029
1454
  return Boolean(value);
1030
1455
  }
1031
- case import_echo_schema6.TypeEnum.Number: {
1456
+ case import_echo_schema9.TypeEnum.Number: {
1032
1457
  const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1033
1458
  const num = Number(cleaned);
1034
1459
  return Number.isNaN(num) ? null : num;
1035
1460
  }
1036
- case import_echo_schema6.TypeEnum.String:
1037
- case import_echo_schema6.TypeEnum.Ref:
1461
+ case import_echo_schema9.TypeEnum.String:
1462
+ case import_echo_schema9.TypeEnum.Ref:
1038
1463
  return String(value);
1039
1464
  default: {
1040
1465
  return value;
@@ -1045,25 +1470,45 @@ var parseValue = ({ type, format, value }) => {
1045
1470
  return parseScalar(type);
1046
1471
  }
1047
1472
  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);
1473
+ case import_echo_schema9.FormatEnum.Boolean:
1474
+ return parseScalar(import_echo_schema9.TypeEnum.Boolean);
1475
+ case import_echo_schema9.FormatEnum.Number:
1476
+ case import_echo_schema9.FormatEnum.Percent:
1477
+ case import_echo_schema9.FormatEnum.Currency:
1478
+ return parseScalar(import_echo_schema9.TypeEnum.Number);
1479
+ case import_echo_schema9.FormatEnum.String:
1480
+ case import_echo_schema9.FormatEnum.Markdown: {
1481
+ return parseScalar(import_echo_schema9.TypeEnum.String);
1057
1482
  }
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: {
1483
+ case import_echo_schema9.FormatEnum.Ref:
1484
+ throw new Error(`unexpected format: ${import_echo_schema9.FormatEnum.Ref}`);
1485
+ case import_echo_schema9.FormatEnum.DateTime:
1486
+ case import_echo_schema9.FormatEnum.Date:
1487
+ case import_echo_schema9.FormatEnum.Time:
1488
+ case import_echo_schema9.FormatEnum.Timestamp: {
1064
1489
  const date = new Date(value);
1065
1490
  return isNaN(date.getTime()) ? null : date;
1066
1491
  }
1492
+ case import_echo_schema9.FormatEnum.GeoPoint: {
1493
+ if (typeof value === "string") {
1494
+ const cleaned = value.replace(/[^0-9.,-]+/g, "");
1495
+ const parts = cleaned.split(",");
1496
+ if (parts.length === 2) {
1497
+ const lat = parseFloat(parts[0]);
1498
+ const long = parseFloat(parts[1]);
1499
+ if (!isNaN(lat) && !isNaN(long)) {
1500
+ return import_echo_schema9.GeoLocation.toGeoPoint({
1501
+ latitude: lat,
1502
+ longitude: long
1503
+ });
1504
+ }
1505
+ }
1506
+ }
1507
+ return [
1508
+ 0,
1509
+ 0
1510
+ ];
1511
+ }
1067
1512
  default: {
1068
1513
  return value;
1069
1514
  }
@@ -1072,19 +1517,19 @@ var parseValue = ({ type, format, value }) => {
1072
1517
  var cellClassesForFieldType = ({ type, format }) => {
1073
1518
  if (!format) {
1074
1519
  switch (type) {
1075
- case import_echo_schema6.TypeEnum.Number:
1520
+ case import_echo_schema9.TypeEnum.Number:
1076
1521
  return [
1077
1522
  "text-right",
1078
1523
  "font-mono"
1079
1524
  ];
1080
- case import_echo_schema6.TypeEnum.Boolean:
1525
+ case import_echo_schema9.TypeEnum.Boolean:
1081
1526
  return [
1082
1527
  "text-right",
1083
1528
  "font-mono"
1084
1529
  ];
1085
- case import_echo_schema6.TypeEnum.String:
1530
+ case import_echo_schema9.TypeEnum.String:
1086
1531
  return void 0;
1087
- case import_echo_schema6.TypeEnum.Ref:
1532
+ case import_echo_schema9.TypeEnum.Ref:
1088
1533
  return void 0;
1089
1534
  default: {
1090
1535
  return void 0;
@@ -1092,20 +1537,20 @@ var cellClassesForFieldType = ({ type, format }) => {
1092
1537
  }
1093
1538
  }
1094
1539
  switch (format) {
1095
- case import_echo_schema6.FormatEnum.Markdown:
1540
+ case import_echo_schema9.FormatEnum.Markdown:
1096
1541
  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:
1542
+ case import_echo_schema9.FormatEnum.Timestamp:
1543
+ case import_echo_schema9.FormatEnum.DateTime:
1544
+ case import_echo_schema9.FormatEnum.Date:
1545
+ case import_echo_schema9.FormatEnum.Time:
1101
1546
  return [
1102
1547
  "font-mono"
1103
1548
  ];
1104
- case import_echo_schema6.FormatEnum.Currency:
1549
+ case import_echo_schema9.FormatEnum.Currency:
1105
1550
  return [
1106
1551
  "text-right"
1107
1552
  ];
1108
- case import_echo_schema6.FormatEnum.JSON:
1553
+ case import_echo_schema9.FormatEnum.JSON:
1109
1554
  return [
1110
1555
  "font-mono"
1111
1556
  ];
@@ -1123,12 +1568,12 @@ var pathNotUniqueError = (path) => ({
1123
1568
  var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1124
1569
  const formatScalar = (type2) => {
1125
1570
  switch (type2) {
1126
- case import_echo_schema7.TypeEnum.Boolean:
1571
+ case import_echo_schema10.TypeEnum.Boolean:
1127
1572
  return value.toLocaleString().toUpperCase();
1128
- case import_echo_schema7.TypeEnum.Number:
1573
+ case import_echo_schema10.TypeEnum.Number:
1129
1574
  return value.toLocaleString(locale);
1130
- case import_echo_schema7.TypeEnum.String:
1131
- case import_echo_schema7.TypeEnum.Ref:
1575
+ case import_echo_schema10.TypeEnum.String:
1576
+ case import_echo_schema10.TypeEnum.Ref:
1132
1577
  return String(value);
1133
1578
  default: {
1134
1579
  return String(value);
@@ -1139,20 +1584,20 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1139
1584
  return formatScalar(type);
1140
1585
  }
1141
1586
  switch (format) {
1142
- case import_echo_schema7.FormatEnum.Boolean: {
1143
- return formatScalar(import_echo_schema7.TypeEnum.Boolean);
1587
+ case import_echo_schema10.FormatEnum.Boolean: {
1588
+ return formatScalar(import_echo_schema10.TypeEnum.Boolean);
1144
1589
  }
1145
- case import_echo_schema7.FormatEnum.Number: {
1146
- return formatScalar(import_echo_schema7.TypeEnum.Number);
1590
+ case import_echo_schema10.FormatEnum.Number: {
1591
+ return formatScalar(import_echo_schema10.TypeEnum.Number);
1147
1592
  }
1148
- case import_echo_schema7.FormatEnum.String:
1149
- case import_echo_schema7.FormatEnum.Ref: {
1150
- return formatScalar(import_echo_schema7.TypeEnum.String);
1593
+ case import_echo_schema10.FormatEnum.String:
1594
+ case import_echo_schema10.FormatEnum.Ref: {
1595
+ return formatScalar(import_echo_schema10.TypeEnum.String);
1151
1596
  }
1152
- case import_echo_schema7.FormatEnum.Percent: {
1597
+ case import_echo_schema10.FormatEnum.Percent: {
1153
1598
  return `${value * 100}%`;
1154
1599
  }
1155
- case import_echo_schema7.FormatEnum.Currency: {
1600
+ case import_echo_schema10.FormatEnum.Currency: {
1156
1601
  return value.toLocaleString(locale, {
1157
1602
  style: "currency",
1158
1603
  currency: "USD",
@@ -1160,18 +1605,28 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1160
1605
  maximumFractionDigits: 2
1161
1606
  });
1162
1607
  }
1163
- case import_echo_schema7.FormatEnum.DateTime:
1164
- case import_echo_schema7.FormatEnum.Date:
1165
- case import_echo_schema7.FormatEnum.Time: {
1608
+ case import_echo_schema10.FormatEnum.DateTime:
1609
+ case import_echo_schema10.FormatEnum.Date:
1610
+ case import_echo_schema10.FormatEnum.Time: {
1166
1611
  const date = new Date(value);
1167
- if (format === import_echo_schema7.FormatEnum.DateTime) {
1612
+ if (format === import_echo_schema10.FormatEnum.DateTime) {
1168
1613
  return date.toLocaleString(locale);
1169
- } else if (format === import_echo_schema7.FormatEnum.Date) {
1614
+ } else if (format === import_echo_schema10.FormatEnum.Date) {
1170
1615
  return date.toLocaleDateString(locale);
1171
1616
  } else {
1172
1617
  return date.toLocaleTimeString(locale);
1173
1618
  }
1174
1619
  }
1620
+ case import_echo_schema10.FormatEnum.GeoPoint: {
1621
+ if (value === null || value === void 0) {
1622
+ return "";
1623
+ }
1624
+ if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1625
+ const { latitude, longitude } = import_echo_schema10.GeoLocation.fromGeoPoint(value);
1626
+ return `${latitude},${longitude}`;
1627
+ }
1628
+ return String(value);
1629
+ }
1175
1630
  default: {
1176
1631
  if (value === null || value === "undefined") {
1177
1632
  return "";
@@ -1183,10 +1638,10 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1183
1638
  var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1184
1639
  const formatScalar = (type2) => {
1185
1640
  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:
1641
+ case import_echo_schema10.TypeEnum.Boolean:
1642
+ case import_echo_schema10.TypeEnum.Number:
1643
+ case import_echo_schema10.TypeEnum.String:
1644
+ case import_echo_schema10.TypeEnum.Ref:
1190
1645
  return String(value);
1191
1646
  default:
1192
1647
  return String(value);
@@ -1196,30 +1651,40 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1196
1651
  return formatScalar(type);
1197
1652
  }
1198
1653
  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: {
1654
+ case import_echo_schema10.FormatEnum.Boolean:
1655
+ case import_echo_schema10.FormatEnum.Number:
1656
+ case import_echo_schema10.FormatEnum.String:
1657
+ case import_echo_schema10.FormatEnum.Ref: {
1203
1658
  return formatScalar(type);
1204
1659
  }
1205
- case import_echo_schema7.FormatEnum.Percent: {
1660
+ case import_echo_schema10.FormatEnum.Percent: {
1206
1661
  return String(value * 100);
1207
1662
  }
1208
- case import_echo_schema7.FormatEnum.Currency: {
1663
+ case import_echo_schema10.FormatEnum.Currency: {
1209
1664
  return String(value);
1210
1665
  }
1211
- case import_echo_schema7.FormatEnum.DateTime: {
1666
+ case import_echo_schema10.FormatEnum.DateTime: {
1212
1667
  const date = new Date(value);
1213
1668
  return date.toISOString();
1214
1669
  }
1215
- case import_echo_schema7.FormatEnum.Date: {
1670
+ case import_echo_schema10.FormatEnum.Date: {
1216
1671
  const date = new Date(value);
1217
1672
  return date.toISOString().split("T")[0];
1218
1673
  }
1219
- case import_echo_schema7.FormatEnum.Time: {
1674
+ case import_echo_schema10.FormatEnum.Time: {
1220
1675
  const date = new Date(value);
1221
1676
  return date.toISOString().split("T")[1].split(".")[0];
1222
1677
  }
1678
+ case import_echo_schema10.FormatEnum.GeoPoint: {
1679
+ if (value === null || value === void 0) {
1680
+ return "";
1681
+ }
1682
+ if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1683
+ const { latitude, longitude } = import_echo_schema10.GeoLocation.fromGeoPoint(value);
1684
+ return `${latitude},${longitude}`;
1685
+ }
1686
+ return String(value);
1687
+ }
1223
1688
  default: {
1224
1689
  return String(value);
1225
1690
  }
@@ -1228,14 +1693,16 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1228
1693
  // Annotate the CommonJS export names for ESM import in node:
1229
1694
  0 && (module.exports = {
1230
1695
  BooleanInput,
1696
+ DeprecatedFormContainer,
1231
1697
  DeprecatedFormInput,
1232
1698
  FieldEditor,
1233
1699
  Form,
1234
- FormActions,
1235
1700
  GeoPointInput,
1236
1701
  InputHeader,
1702
+ MarkdownInput,
1237
1703
  NumberInput,
1238
1704
  SelectInput,
1705
+ SelectOptionInput,
1239
1706
  TextInput,
1240
1707
  TupleInput,
1241
1708
  ViewEditor,
@@ -1246,6 +1713,7 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1246
1713
  parseValue,
1247
1714
  pathNotUniqueError,
1248
1715
  translations,
1249
- useForm
1716
+ useForm,
1717
+ useFormValues
1250
1718
  });
1251
1719
  //# sourceMappingURL=index.cjs.map