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