@dxos/react-ui-form 0.7.1-staging.599df14

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 (93) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +4 -0
  3. package/dist/lib/browser/index.mjs +1008 -0
  4. package/dist/lib/browser/index.mjs.map +7 -0
  5. package/dist/lib/browser/meta.json +1 -0
  6. package/dist/lib/node/index.cjs +1028 -0
  7. package/dist/lib/node/index.cjs.map +7 -0
  8. package/dist/lib/node/meta.json +1 -0
  9. package/dist/lib/node-esm/index.mjs +1010 -0
  10. package/dist/lib/node-esm/index.mjs.map +7 -0
  11. package/dist/lib/node-esm/meta.json +1 -0
  12. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +16 -0
  13. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -0
  14. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +9 -0
  15. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -0
  16. package/dist/types/src/components/FieldEditor/index.d.ts +2 -0
  17. package/dist/types/src/components/FieldEditor/index.d.ts.map +1 -0
  18. package/dist/types/src/components/Form/Custom.d.ts +4 -0
  19. package/dist/types/src/components/Form/Custom.d.ts.map +1 -0
  20. package/dist/types/src/components/Form/Defaults.d.ts +7 -0
  21. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -0
  22. package/dist/types/src/components/Form/Form.d.ts +26 -0
  23. package/dist/types/src/components/Form/Form.d.ts.map +1 -0
  24. package/dist/types/src/components/Form/Form.stories.d.ts +38 -0
  25. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -0
  26. package/dist/types/src/components/Form/Input.d.ts +29 -0
  27. package/dist/types/src/components/Form/Input.d.ts.map +1 -0
  28. package/dist/types/src/components/Form/factory.d.ts +8 -0
  29. package/dist/types/src/components/Form/factory.d.ts.map +1 -0
  30. package/dist/types/src/components/Form/index.d.ts +5 -0
  31. package/dist/types/src/components/Form/index.d.ts.map +1 -0
  32. package/dist/types/src/components/ViewEditor/Test.stories.d.ts +10 -0
  33. package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -0
  34. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +18 -0
  35. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -0
  36. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +8 -0
  37. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -0
  38. package/dist/types/src/components/ViewEditor/index.d.ts +2 -0
  39. package/dist/types/src/components/ViewEditor/index.d.ts.map +1 -0
  40. package/dist/types/src/components/deprecated/Form.d.ts +15 -0
  41. package/dist/types/src/components/deprecated/Form.d.ts.map +1 -0
  42. package/dist/types/src/components/deprecated/Form.stories.d.ts +13 -0
  43. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -0
  44. package/dist/types/src/components/deprecated/FormInput.d.ts +11 -0
  45. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -0
  46. package/dist/types/src/components/deprecated/index.d.ts +2 -0
  47. package/dist/types/src/components/deprecated/index.d.ts.map +1 -0
  48. package/dist/types/src/components/index.d.ts +5 -0
  49. package/dist/types/src/components/index.d.ts.map +1 -0
  50. package/dist/types/src/components/testing.d.ts +7 -0
  51. package/dist/types/src/components/testing.d.ts.map +1 -0
  52. package/dist/types/src/hooks/index.d.ts +2 -0
  53. package/dist/types/src/hooks/index.d.ts.map +1 -0
  54. package/dist/types/src/hooks/useForm.d.ts +58 -0
  55. package/dist/types/src/hooks/useForm.d.ts.map +1 -0
  56. package/dist/types/src/index.d.ts +6 -0
  57. package/dist/types/src/index.d.ts.map +1 -0
  58. package/dist/types/src/translations.d.ts +46 -0
  59. package/dist/types/src/translations.d.ts.map +1 -0
  60. package/dist/types/src/util/field.d.ts +22 -0
  61. package/dist/types/src/util/field.d.ts.map +1 -0
  62. package/dist/types/src/util/formatting.d.ts +15 -0
  63. package/dist/types/src/util/formatting.d.ts.map +1 -0
  64. package/dist/types/src/util/index.d.ts +3 -0
  65. package/dist/types/src/util/index.d.ts.map +1 -0
  66. package/package.json +76 -0
  67. package/src/components/FieldEditor/FieldEditor.stories.tsx +56 -0
  68. package/src/components/FieldEditor/FieldEditor.tsx +167 -0
  69. package/src/components/FieldEditor/index.ts +5 -0
  70. package/src/components/Form/Custom.tsx +65 -0
  71. package/src/components/Form/Defaults.tsx +130 -0
  72. package/src/components/Form/Form.stories.tsx +137 -0
  73. package/src/components/Form/Form.tsx +176 -0
  74. package/src/components/Form/Input.tsx +56 -0
  75. package/src/components/Form/factory.tsx +32 -0
  76. package/src/components/Form/index.ts +8 -0
  77. package/src/components/ViewEditor/Test.stories.tsx +45 -0
  78. package/src/components/ViewEditor/ViewEditor.stories.tsx +73 -0
  79. package/src/components/ViewEditor/ViewEditor.tsx +158 -0
  80. package/src/components/ViewEditor/index.ts +5 -0
  81. package/src/components/deprecated/Form.stories.tsx +62 -0
  82. package/src/components/deprecated/Form.tsx +119 -0
  83. package/src/components/deprecated/FormInput.tsx +58 -0
  84. package/src/components/deprecated/index.ts +5 -0
  85. package/src/components/index.ts +9 -0
  86. package/src/components/testing.tsx +24 -0
  87. package/src/hooks/index.ts +5 -0
  88. package/src/hooks/useForm.ts +229 -0
  89. package/src/index.ts +11 -0
  90. package/src/translations.ts +59 -0
  91. package/src/util/field.ts +137 -0
  92. package/src/util/formatting.ts +132 -0
  93. package/src/util/index.ts +6 -0
@@ -0,0 +1,59 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export const translationKey = 'react-ui-form';
6
+
7
+ export default [
8
+ {
9
+ 'en-US': {
10
+ [translationKey]: {
11
+ 'fields label': 'Fields',
12
+
13
+ // TODO(burdon): Standardize field/property.
14
+ 'button add property': 'Add property',
15
+ 'field property label': 'Property',
16
+ 'field property placeholder': 'Property name',
17
+ 'field format label': 'Type',
18
+ 'field path label': 'Field path',
19
+ 'add field': 'Add field',
20
+ 'delete field': 'Delete field',
21
+ 'field limit reached': 'Maximum number of fields reached',
22
+
23
+ // TODO(burdon): Factor out?
24
+ 'button cancel': 'Cancel',
25
+ 'button save': 'Save',
26
+
27
+ // FormatEnum
28
+ 'format boolean': 'Boolean',
29
+ 'format currency': 'Currency',
30
+ 'format date': 'Date',
31
+ 'format date-time': 'DateTime',
32
+ 'format did': 'DID',
33
+ 'format duration': 'Duration',
34
+ 'format email': 'Email',
35
+ 'format formula': 'Formula',
36
+ 'format hostname': 'Hostname',
37
+ 'format integer': 'Integer',
38
+ 'format json': 'JSON',
39
+ 'format latlng': 'LatLng',
40
+ 'format markdown': 'Markdown',
41
+ 'format percent': 'Percent',
42
+ 'format ref': 'Reference',
43
+ 'format regex': 'RegExp',
44
+ 'format string': 'String',
45
+ 'format text': 'Long text',
46
+ 'format time': 'Time',
47
+ 'format timestamp': 'Timestamp',
48
+ 'format user': 'User',
49
+ 'format number': 'Number',
50
+ 'format uri': 'URI',
51
+ 'format uuid': 'UUID',
52
+
53
+ // Placeholders
54
+ 'placeholder latitude': 'Latitude',
55
+ 'placeholder longitude': 'Longitude',
56
+ },
57
+ },
58
+ },
59
+ ];
@@ -0,0 +1,137 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { FormatEnum, TypeEnum } from '@dxos/echo-schema';
6
+ import { type ValidationError } from '@dxos/schema';
7
+
8
+ /**
9
+ * Parse value by field value type.
10
+ * Used by Table, Sheet, etc.
11
+ * Handles various data types including booleans, numbers, dates, and strings.
12
+ * Returns undefined for empty or null inputs.
13
+ */
14
+ export type ParseProps = {
15
+ type?: TypeEnum;
16
+ format?: FormatEnum;
17
+ value: any;
18
+ };
19
+
20
+ export const parseValue = ({ type, format, value }: ParseProps) => {
21
+ if (value === undefined || value === null || value === '') {
22
+ return undefined;
23
+ }
24
+
25
+ const parseScalar = (type?: TypeEnum) => {
26
+ switch (type) {
27
+ case TypeEnum.Boolean: {
28
+ if (typeof value === 'string') {
29
+ const lowercaseValue = value.toLowerCase();
30
+ if (lowercaseValue === '0' || lowercaseValue === 'false') {
31
+ return false;
32
+ } else if (lowercaseValue === '1' || lowercaseValue === 'true') {
33
+ return true;
34
+ }
35
+ }
36
+ return Boolean(value);
37
+ }
38
+
39
+ case TypeEnum.Number: {
40
+ const cleaned = typeof value === 'string' ? value.replace(/[^0-9.-]+/g, '') : value;
41
+ const num = Number(cleaned);
42
+ return Number.isNaN(num) ? null : num;
43
+ }
44
+
45
+ case TypeEnum.String:
46
+ case TypeEnum.Ref:
47
+ return String(value);
48
+
49
+ default: {
50
+ return value;
51
+ }
52
+ }
53
+ };
54
+
55
+ if (!format) {
56
+ return parseScalar(type);
57
+ }
58
+
59
+ switch (format) {
60
+ case FormatEnum.Boolean:
61
+ return parseScalar(TypeEnum.Boolean);
62
+
63
+ case FormatEnum.Number:
64
+ case FormatEnum.Percent:
65
+ case FormatEnum.Currency:
66
+ return parseScalar(TypeEnum.Number);
67
+
68
+ case FormatEnum.String:
69
+ case FormatEnum.Markdown: {
70
+ return parseScalar(TypeEnum.String);
71
+ }
72
+
73
+ case FormatEnum.Ref:
74
+ throw new Error(`unexpected format: ${FormatEnum.Ref}`);
75
+
76
+ case FormatEnum.DateTime:
77
+ case FormatEnum.Date:
78
+ case FormatEnum.Time:
79
+ case FormatEnum.Timestamp: {
80
+ const date = new Date(value as string | number);
81
+ return isNaN(date.getTime()) ? null : date;
82
+ }
83
+
84
+ default: {
85
+ return value;
86
+ }
87
+ }
88
+ };
89
+
90
+ // TODO(burdon): Type and format.
91
+ export type CellClassesForFieldTypeProps = {
92
+ type?: TypeEnum;
93
+ format?: FormatEnum;
94
+ };
95
+
96
+ export const cellClassesForFieldType = ({ type, format }: CellClassesForFieldTypeProps): string[] | undefined => {
97
+ if (!format) {
98
+ switch (type) {
99
+ case TypeEnum.Number:
100
+ return ['text-right', 'font-mono'];
101
+ case TypeEnum.Boolean:
102
+ return ['text-right', 'font-mono'];
103
+ case TypeEnum.String:
104
+ return undefined;
105
+ case TypeEnum.Ref:
106
+ return undefined;
107
+
108
+ default: {
109
+ return undefined;
110
+ }
111
+ }
112
+ }
113
+
114
+ switch (format) {
115
+ case FormatEnum.Markdown:
116
+ return undefined;
117
+ case FormatEnum.Timestamp:
118
+ case FormatEnum.DateTime:
119
+ case FormatEnum.Date:
120
+ case FormatEnum.Time:
121
+ return ['font-mono'];
122
+ case FormatEnum.Currency:
123
+ return ['text-right'];
124
+ case FormatEnum.JSON:
125
+ return ['font-mono'];
126
+ default:
127
+ return undefined;
128
+ }
129
+ };
130
+
131
+ export const cellClassesForRowSelection = (selected: boolean) => (selected ? ['!bg-gridCellSelected'] : undefined);
132
+
133
+ // TODO(ZaymonFC): How to do this with translations?
134
+ export const pathNotUniqueError = (path: string): ValidationError => ({
135
+ path: 'path',
136
+ message: `'${path}' is already present`,
137
+ });
@@ -0,0 +1,132 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { FormatEnum, TypeEnum } from '@dxos/echo-schema';
6
+
7
+ type ValueFormatProps = {
8
+ type: TypeEnum;
9
+ format?: FormatEnum | undefined;
10
+ value: any;
11
+ locale?: string | undefined;
12
+ };
13
+
14
+ /**
15
+ * Format value by type.
16
+ * Used by Table, Sheet, etc.
17
+ */
18
+ // TODO(burdon): Move to react-ui-form.
19
+ // TODO(burdon): Formatting is different from kind format (e.g., percent is not a data format).
20
+ export const formatForDisplay = ({ type, format, value, locale = undefined }: ValueFormatProps): string => {
21
+ const formatScalar = (type: TypeEnum) => {
22
+ switch (type) {
23
+ case TypeEnum.Boolean:
24
+ return (value as boolean).toLocaleString().toUpperCase();
25
+ case TypeEnum.Number:
26
+ return value.toLocaleString(locale);
27
+ case TypeEnum.String:
28
+ case TypeEnum.Ref:
29
+ return String(value);
30
+
31
+ default: {
32
+ return String(value);
33
+ }
34
+ }
35
+ };
36
+
37
+ if (!format) {
38
+ return formatScalar(type);
39
+ }
40
+
41
+ switch (format) {
42
+ case FormatEnum.Boolean: {
43
+ return formatScalar(TypeEnum.Boolean);
44
+ }
45
+ case FormatEnum.Number: {
46
+ return formatScalar(TypeEnum.Number);
47
+ }
48
+ case FormatEnum.String:
49
+ case FormatEnum.Ref: {
50
+ return formatScalar(TypeEnum.String);
51
+ }
52
+ case FormatEnum.Percent: {
53
+ return `${(value as number) * 100}%`;
54
+ }
55
+ case FormatEnum.Currency: {
56
+ // TODO(burdon): Get from property annotation.
57
+ return (value as number).toLocaleString(locale, {
58
+ style: 'currency',
59
+ currency: 'USD',
60
+ minimumFractionDigits: 2,
61
+ maximumFractionDigits: 2,
62
+ });
63
+ }
64
+ case FormatEnum.DateTime:
65
+ case FormatEnum.Date:
66
+ case FormatEnum.Time: {
67
+ const date = new Date(value as number);
68
+ if (format === FormatEnum.DateTime) {
69
+ return date.toLocaleString(locale);
70
+ } else if (format === FormatEnum.Date) {
71
+ return date.toLocaleDateString(locale);
72
+ } else {
73
+ return date.toLocaleTimeString(locale);
74
+ }
75
+ }
76
+ default: {
77
+ if (value === null || value === 'undefined') {
78
+ return '';
79
+ }
80
+ return String(value);
81
+ }
82
+ }
83
+ };
84
+
85
+ export const formatForEditing = ({ type, format, value, locale = undefined }: ValueFormatProps): string => {
86
+ const formatScalar = (type: TypeEnum) => {
87
+ switch (type) {
88
+ case TypeEnum.Boolean:
89
+ case TypeEnum.Number:
90
+ case TypeEnum.String:
91
+ case TypeEnum.Ref:
92
+ return String(value);
93
+
94
+ default:
95
+ return String(value);
96
+ }
97
+ };
98
+
99
+ if (!format) {
100
+ return formatScalar(type);
101
+ }
102
+
103
+ switch (format) {
104
+ case FormatEnum.Boolean:
105
+ case FormatEnum.Number:
106
+ case FormatEnum.String:
107
+ case FormatEnum.Ref: {
108
+ return formatScalar(type);
109
+ }
110
+ case FormatEnum.Percent: {
111
+ return String(value * 100);
112
+ }
113
+ case FormatEnum.Currency: {
114
+ return String(value);
115
+ }
116
+ case FormatEnum.DateTime: {
117
+ const date = new Date(value as number);
118
+ return date.toISOString();
119
+ }
120
+ case FormatEnum.Date: {
121
+ const date = new Date(value as number);
122
+ return date.toISOString().split('T')[0];
123
+ }
124
+ case FormatEnum.Time: {
125
+ const date = new Date(value as number);
126
+ return date.toISOString().split('T')[1].split('.')[0];
127
+ }
128
+ default: {
129
+ return String(value);
130
+ }
131
+ }
132
+ };
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './field';
6
+ export * from './formatting';