@dxos/react-ui-form 0.7.1-staging.8709ba7 → 0.7.2-staging.6d26b2a

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 (33) hide show
  1. package/dist/lib/browser/index.mjs +107 -81
  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 +100 -74
  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 +107 -81
  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/Form/Custom.d.ts +2 -1
  11. package/dist/types/src/components/Form/Custom.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/Defaults.d.ts +11 -4
  13. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.d.ts +5 -4
  15. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.stories.d.ts +1 -4
  17. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/Input.d.ts +3 -8
  19. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  20. package/dist/types/src/components/Form/factory.d.ts +2 -2
  21. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  22. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  23. package/dist/types/src/hooks/useForm.d.ts +5 -4
  24. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  25. package/package.json +22 -24
  26. package/src/components/Form/Custom.tsx +9 -9
  27. package/src/components/Form/Defaults.tsx +10 -5
  28. package/src/components/Form/Form.stories.tsx +2 -2
  29. package/src/components/Form/Form.tsx +43 -19
  30. package/src/components/Form/Input.tsx +3 -7
  31. package/src/components/Form/factory.tsx +4 -4
  32. package/src/components/ViewEditor/ViewEditor.stories.tsx +1 -2
  33. package/src/hooks/useForm.ts +7 -6
@@ -89,6 +89,8 @@ import { useTranslation as useTranslation3 } from "@dxos/react-ui";
89
89
  import { getFormatSchema, getSchemaProperties as getSchemaProperties2, sortProperties } from "@dxos/schema";
90
90
 
91
91
  // packages/ui/react-ui-form/src/components/Form/Form.tsx
92
+ import { pipe } from "effect";
93
+ import { capitalize } from "effect/String";
92
94
  import React5, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
93
95
  import { AST, S } from "@dxos/echo-schema";
94
96
  import { findNode, getDiscriminatedType, isDiscriminatedUnion } from "@dxos/effect";
@@ -98,12 +100,9 @@ import { mx } from "@dxos/react-ui-theme";
98
100
  import { getSchemaProperties } from "@dxos/schema";
99
101
  import { isNotFalsy } from "@dxos/util";
100
102
 
101
- // packages/ui/react-ui-form/src/components/Form/factory.tsx
102
- import { FormatEnum } from "@dxos/echo-schema";
103
-
104
- // packages/ui/react-ui-form/src/components/Form/Custom.tsx
103
+ // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
105
104
  import React3 from "react";
106
- import { Input as Input2, useTranslation } from "@dxos/react-ui";
105
+ import { Input as Input2, Select } from "@dxos/react-ui";
107
106
 
108
107
  // packages/ui/react-ui-form/src/components/Form/Input.tsx
109
108
  import React2 from "react";
@@ -124,57 +123,14 @@ var InputHeader = ({ children, error }) => {
124
123
  }, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null), error)));
125
124
  };
126
125
 
127
- // packages/ui/react-ui-form/src/components/Form/Custom.tsx
128
- var LatLngInput = ({ property, type, label, disabled, getStatus, getValue, onValueChange, onBlur }) => {
129
- const { t } = useTranslation(translationKey);
130
- const { status, error } = getStatus?.(property);
131
- const { lat = 0, lng = 0 } = getValue(property) ?? {};
132
- return /* @__PURE__ */ React3.createElement(Input2.Root, {
133
- validationValence: status
134
- }, /* @__PURE__ */ React3.createElement(InputHeader, {
135
- error
136
- }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement("div", {
137
- className: "grid grid-cols-2 gap-2"
138
- }, /* @__PURE__ */ React3.createElement(Input2.TextInput, {
139
- type: "number",
140
- disabled,
141
- placeholder: t("placeholder latitude"),
142
- value: lat,
143
- onChange: (event) => onValueChange(property, type, {
144
- lat: safeParseFloat(event.target.value, 0),
145
- lng
146
- }),
147
- onBlur
148
- }), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
149
- type: "number",
150
- disabled,
151
- placeholder: t("placeholder longitude"),
152
- value: lng,
153
- onChange: (event) => onValueChange(property, type, {
154
- lat,
155
- lng: safeParseFloat(event.target.value, 0)
156
- }),
157
- onBlur
158
- })));
159
- };
160
- var safeParseFloat = (str, defaultValue) => {
161
- try {
162
- return parseFloat(str);
163
- } catch {
164
- return defaultValue ?? 0;
165
- }
166
- };
167
-
168
126
  // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
169
- import React4 from "react";
170
- import { Input as Input3, Select } from "@dxos/react-ui";
171
127
  var TextInput = ({ property, type, label, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
172
128
  const { status, error } = getStatus?.(property);
173
- return /* @__PURE__ */ React4.createElement(Input3.Root, {
129
+ return /* @__PURE__ */ React3.createElement(Input2.Root, {
174
130
  validationValence: status
175
- }, /* @__PURE__ */ React4.createElement(InputHeader, {
131
+ }, /* @__PURE__ */ React3.createElement(InputHeader, {
176
132
  error
177
- }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement(Input3.TextInput, {
133
+ }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
178
134
  disabled,
179
135
  placeholder,
180
136
  value: getValue(property) ?? "",
@@ -184,11 +140,11 @@ var TextInput = ({ property, type, label, disabled, placeholder, getStatus, getV
184
140
  };
185
141
  var NumberInput = ({ property, type, label, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
186
142
  const { status, error } = getStatus?.(property);
187
- return /* @__PURE__ */ React4.createElement(Input3.Root, {
143
+ return /* @__PURE__ */ React3.createElement(Input2.Root, {
188
144
  validationValence: status
189
- }, /* @__PURE__ */ React4.createElement(InputHeader, {
145
+ }, /* @__PURE__ */ React3.createElement(InputHeader, {
190
146
  error
191
- }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement(Input3.TextInput, {
147
+ }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
192
148
  type: "number",
193
149
  disabled,
194
150
  placeholder,
@@ -199,42 +155,88 @@ var NumberInput = ({ property, type, label, disabled, placeholder, getStatus, ge
199
155
  };
200
156
  var BooleanInput = ({ property, type, label, getStatus, getValue, onValueChange }) => {
201
157
  const { status, error } = getStatus?.(property);
202
- return /* @__PURE__ */ React4.createElement(Input3.Root, {
158
+ return /* @__PURE__ */ React3.createElement(Input2.Root, {
203
159
  validationValence: status
204
- }, /* @__PURE__ */ React4.createElement(InputHeader, {
160
+ }, /* @__PURE__ */ React3.createElement(InputHeader, {
205
161
  error
206
- }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement(Input3.Switch, {
162
+ }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Input2.Switch, {
207
163
  checked: getValue(property),
208
164
  onCheckedChange: (value) => onValueChange(property, type, value)
209
165
  }));
210
166
  };
211
167
  var SelectInput = ({ property, type, label, disabled, placeholder, options, getStatus, getValue, onValueChange }) => {
212
168
  const { status, error } = getStatus?.(property);
213
- return /* @__PURE__ */ React4.createElement(Input3.Root, {
169
+ return /* @__PURE__ */ React3.createElement(Input2.Root, {
214
170
  validationValence: status
215
- }, /* @__PURE__ */ React4.createElement(InputHeader, {
171
+ }, /* @__PURE__ */ React3.createElement(InputHeader, {
216
172
  error
217
- }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement(Select.Root, {
173
+ }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement(Select.Root, {
218
174
  value: getValue(property),
219
175
  onValueChange: (value) => onValueChange(property, type, value)
220
- }, /* @__PURE__ */ React4.createElement(Select.TriggerButton, {
176
+ }, /* @__PURE__ */ React3.createElement(Select.TriggerButton, {
221
177
  classNames: "is-full",
222
178
  disabled,
223
179
  placeholder
224
- }), /* @__PURE__ */ React4.createElement(Select.Portal, null, /* @__PURE__ */ React4.createElement(Select.Content, null, /* @__PURE__ */ React4.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
180
+ }), /* @__PURE__ */ React3.createElement(Select.Portal, null, /* @__PURE__ */ React3.createElement(Select.Content, null, /* @__PURE__ */ React3.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
225
181
  // NOTE: Numeric values are converted to and from strings.
226
- /* @__PURE__ */ React4.createElement(Select.Option, {
182
+ /* @__PURE__ */ React3.createElement(Select.Option, {
227
183
  key: String(value),
228
184
  value: String(value)
229
185
  }, label2 ?? String(value))
230
186
  )))))));
231
187
  };
232
188
 
189
+ // packages/ui/react-ui-form/src/components/Form/factory.tsx
190
+ import { FormatEnum } from "@dxos/echo-schema";
191
+
192
+ // packages/ui/react-ui-form/src/components/Form/Custom.tsx
193
+ import React4 from "react";
194
+ import { Input as Input3, useTranslation } from "@dxos/react-ui";
195
+ var GeiPointInput = ({ property, type, label, disabled, getStatus, getValue, onValueChange, onBlur }) => {
196
+ const { t } = useTranslation(translationKey);
197
+ const { status, error } = getStatus?.(property);
198
+ const [lng = 0, lat = 0] = getValue(property) ?? [];
199
+ return /* @__PURE__ */ React4.createElement(Input3.Root, {
200
+ validationValence: status
201
+ }, /* @__PURE__ */ React4.createElement(InputHeader, {
202
+ error
203
+ }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
204
+ className: "grid grid-cols-2 gap-2"
205
+ }, /* @__PURE__ */ React4.createElement(Input3.TextInput, {
206
+ type: "number",
207
+ disabled,
208
+ placeholder: t("placeholder longitude"),
209
+ value: lng,
210
+ onChange: (event) => onValueChange(property, type, [
211
+ lat,
212
+ safeParseFloat(event.target.value, 0)
213
+ ]),
214
+ onBlur
215
+ }), /* @__PURE__ */ React4.createElement(Input3.TextInput, {
216
+ type: "number",
217
+ disabled,
218
+ placeholder: t("placeholder latitude"),
219
+ value: lat,
220
+ onChange: (event) => onValueChange(property, type, [
221
+ safeParseFloat(event.target.value, 0),
222
+ lng
223
+ ]),
224
+ onBlur
225
+ })));
226
+ };
227
+ var safeParseFloat = (str, defaultValue) => {
228
+ try {
229
+ return parseFloat(str);
230
+ } catch {
231
+ return defaultValue ?? 0;
232
+ }
233
+ };
234
+
233
235
  // packages/ui/react-ui-form/src/components/Form/factory.tsx
234
236
  var getInputComponent = (type, format) => {
235
237
  switch (format) {
236
238
  case FormatEnum.LatLng:
237
- return LatLngInput;
239
+ return GeiPointInput;
238
240
  }
239
241
  switch (type) {
240
242
  case "string":
@@ -321,7 +323,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
321
323
  } catch (err) {
322
324
  log.catch(err, void 0, {
323
325
  F: __dxlog_file,
324
- L: 164,
326
+ L: 165,
325
327
  S: void 0,
326
328
  C: (f, a) => f(...a)
327
329
  });
@@ -376,7 +378,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
376
378
  var createKeySet = (obj, value) => {
377
379
  invariant(obj, void 0, {
378
380
  F: __dxlog_file,
379
- L: 215,
381
+ L: 216,
380
382
  S: void 0,
381
383
  A: [
382
384
  "obj",
@@ -414,11 +416,11 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
414
416
  onValid,
415
417
  onSubmit
416
418
  });
417
- const props = useMemo2(() => {
418
- const props2 = getSchemaProperties(schema.ast, values);
419
- const filtered = filter ? filter(props2) : props2;
420
- const findIndex = (props3, prop) => {
421
- const idx = props3.findIndex((p) => p === prop);
419
+ const properties = useMemo2(() => {
420
+ const props = getSchemaProperties(schema.ast, values);
421
+ const filtered = filter ? filter(props) : props;
422
+ const findIndex = (props2, prop) => {
423
+ const idx = props2.findIndex((p) => p === prop);
422
424
  return idx === -1 ? Infinity : idx;
423
425
  };
424
426
  return sort ? filtered.sort(({ name: a }, { name: b }) => findIndex(sort, a) - findIndex(sort, b)) : filtered;
@@ -433,7 +435,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
433
435
  errors
434
436
  }, {
435
437
  F: __dxlog_file2,
436
- L: 93,
438
+ L: 96,
437
439
  S: void 0,
438
440
  C: (f, a) => f(...a)
439
441
  });
@@ -444,16 +446,41 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
444
446
  return /* @__PURE__ */ React5.createElement("div", {
445
447
  role: "form",
446
448
  className: mx("flex flex-col w-full gap-2 py-2", classNames)
447
- }, props.map(({ prop, name, type, format, title, description, examples }) => {
449
+ }, properties.map((property) => {
450
+ const { ast, name, type, format, title, description, examples, options } = property;
448
451
  const key = [
449
452
  ...path,
450
453
  name
451
454
  ];
452
- const InputComponent = Custom?.[key.join(".")] ?? getInputComponent(type, format);
455
+ const label = pipe(title ?? name, capitalize);
456
+ const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
457
+ let InputComponent = Custom?.[key.join(".")];
458
+ if (!InputComponent) {
459
+ if (options) {
460
+ return /* @__PURE__ */ React5.createElement("div", {
461
+ key: name,
462
+ role: "none",
463
+ className: padding
464
+ }, /* @__PURE__ */ React5.createElement(SelectInput, {
465
+ type,
466
+ format,
467
+ property: name,
468
+ disabled: readonly,
469
+ label,
470
+ options: options.map((option) => ({
471
+ value: option,
472
+ label: String(option)
473
+ })),
474
+ placeholder,
475
+ ...inputProps
476
+ }));
477
+ }
478
+ InputComponent = getInputComponent(type, format);
479
+ }
453
480
  if (!InputComponent) {
454
481
  if (type === "object") {
455
- const baseNode = findNode(prop.type, isDiscriminatedUnion);
456
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(prop.type, AST.isTypeLiteral);
482
+ const baseNode = findNode(ast, isDiscriminatedUnion);
483
+ const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(ast, AST.isTypeLiteral);
457
484
  if (typeLiteral) {
458
485
  const schema2 = S.make(typeLiteral);
459
486
  return /* @__PURE__ */ React5.createElement("div", {
@@ -461,7 +488,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
461
488
  role: "none"
462
489
  }, /* @__PURE__ */ React5.createElement("div", {
463
490
  className: padding
464
- }, title ?? name), /* @__PURE__ */ React5.createElement(Form, {
491
+ }, label), /* @__PURE__ */ React5.createElement(Form, {
465
492
  schema: schema2,
466
493
  path: key,
467
494
  values: values[name] ?? {},
@@ -477,13 +504,12 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
477
504
  type
478
505
  }, {
479
506
  F: __dxlog_file2,
480
- L: 132,
507
+ L: 160,
481
508
  S: void 0,
482
509
  C: (f, a) => f(...a)
483
510
  });
484
511
  return null;
485
512
  }
486
- const placeholder = examples?.length ? `Example: ${examples[0]}` : description;
487
513
  return /* @__PURE__ */ React5.createElement("div", {
488
514
  key: name,
489
515
  role: "none",
@@ -493,7 +519,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
493
519
  format,
494
520
  property: name,
495
521
  disabled: readonly,
496
- label: title ?? name,
522
+ label,
497
523
  placeholder,
498
524
  ...inputProps
499
525
  }));
@@ -992,8 +1018,8 @@ export {
992
1018
  DeprecatedFormInput,
993
1019
  FieldEditor,
994
1020
  Form,
1021
+ GeiPointInput,
995
1022
  InputHeader,
996
- LatLngInput,
997
1023
  NumberInput,
998
1024
  SelectInput,
999
1025
  TextInput,