@object-ui/fields 17.3.0 → 17.6.0

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 (265) hide show
  1. package/CHANGELOG.md +1655 -0
  2. package/README.md +1 -12
  3. package/dist/FieldEditWidget.d.ts +23 -3
  4. package/dist/currency.d.ts +46 -0
  5. package/dist/field-type-alias.d.ts +35 -1
  6. package/dist/index.cjs +4 -4
  7. package/dist/index.css +651 -0
  8. package/dist/index.d.ts +474 -85
  9. package/dist/index.js +5418 -5023
  10. package/dist/widgets/AddressField.d.ts +4 -12
  11. package/dist/widgets/AutoNumberField.d.ts +1 -1
  12. package/dist/widgets/AvatarField.d.ts +1 -1
  13. package/dist/widgets/BooleanField.d.ts +1 -1
  14. package/dist/widgets/CapabilityMultiSelectField.d.ts +1 -1
  15. package/dist/widgets/CheckboxesField.d.ts +1 -1
  16. package/dist/widgets/CodeField.d.ts +1 -1
  17. package/dist/widgets/ColorField.d.ts +1 -1
  18. package/dist/widgets/CurrencyField.d.ts +1 -1
  19. package/dist/widgets/DateField.d.ts +1 -1
  20. package/dist/widgets/DateTimeField.d.ts +1 -1
  21. package/dist/widgets/EmailField.d.ts +1 -1
  22. package/dist/widgets/FileField.d.ts +18 -2
  23. package/dist/widgets/FilterConditionField.d.ts +28 -1
  24. package/dist/widgets/FormulaField.d.ts +1 -1
  25. package/dist/widgets/FullscreenFieldEditor.d.ts +49 -152
  26. package/dist/widgets/GeolocationField.d.ts +1 -1
  27. package/dist/widgets/GridField.d.ts +68 -6
  28. package/dist/widgets/ImageField.d.ts +1 -1
  29. package/dist/widgets/LocationField.d.ts +1 -1
  30. package/dist/widgets/LookupField.d.ts +1 -1
  31. package/dist/widgets/MasterDetailField.d.ts +1 -1
  32. package/dist/widgets/MultiSelectField.d.ts +1 -1
  33. package/dist/widgets/NumberField.d.ts +1 -1
  34. package/dist/widgets/ObjectField.d.ts +1 -1
  35. package/dist/widgets/ObjectRefField.d.ts +1 -1
  36. package/dist/widgets/OptionsEmptyState.d.ts +21 -1
  37. package/dist/widgets/PasswordField.d.ts +1 -1
  38. package/dist/widgets/PercentField.d.ts +1 -1
  39. package/dist/widgets/PhoneField.d.ts +1 -1
  40. package/dist/widgets/QRCodeField.d.ts +1 -1
  41. package/dist/widgets/RadioField.d.ts +1 -1
  42. package/dist/widgets/RatingField.d.ts +1 -1
  43. package/dist/widgets/RecipientPickerField.d.ts +1 -1
  44. package/dist/widgets/RecordPickerDialog.d.ts +34 -10
  45. package/dist/widgets/RichTextField.d.ts +37 -1
  46. package/dist/widgets/SelectField.d.ts +26 -6
  47. package/dist/widgets/SignatureField.d.ts +32 -2
  48. package/dist/widgets/SliderField.d.ts +37 -2
  49. package/dist/widgets/SummaryField.d.ts +1 -1
  50. package/dist/widgets/TagsField.d.ts +1 -1
  51. package/dist/widgets/TextAreaField.d.ts +6 -2
  52. package/dist/widgets/TextField.d.ts +1 -1
  53. package/dist/widgets/TimeField.d.ts +1 -1
  54. package/dist/widgets/UrlField.d.ts +1 -1
  55. package/dist/widgets/UserField.d.ts +1 -1
  56. package/dist/widgets/VectorField.d.ts +1 -1
  57. package/dist/widgets/_cell-renderer-bridge.d.ts +1 -1
  58. package/dist/widgets/address-format.d.ts +88 -0
  59. package/dist/widgets/file-size-guard.d.ts +41 -0
  60. package/dist/widgets/lookupColumnDisplay.d.ts +93 -0
  61. package/dist/widgets/nativeDateValue.d.ts +37 -0
  62. package/dist/widgets/richTextDisplay.d.ts +80 -0
  63. package/dist/widgets/toDomProps.d.ts +30 -10
  64. package/dist/widgets/toHostGroupProps.d.ts +189 -0
  65. package/dist/widgets/types.d.ts +8 -3
  66. package/dist/widgets/useRecordQuery.d.ts +7 -1
  67. package/package.json +17 -14
  68. package/dist/FieldEditWidget.test.d.ts +0 -8
  69. package/dist/__tests__/DateCellRenderer.test.d.ts +0 -0
  70. package/dist/__tests__/NumberCellRenderer.test.d.ts +0 -0
  71. package/dist/__tests__/cell-truncation.test.d.ts +0 -0
  72. package/dist/__tests__/field-carrier-sdui.test.d.ts +0 -0
  73. package/dist/__tests__/lookupCellDisplayField.test.d.ts +0 -0
  74. package/dist/__tests__/lookupCellDisplayName.test.d.ts +0 -0
  75. package/dist/__tests__/lookupCellReferenceKey.test.d.ts +0 -0
  76. package/dist/__tests__/registry-collision.test.d.ts +0 -0
  77. package/dist/__tests__/resolveFieldCurrency.test.d.ts +0 -1
  78. package/dist/__tests__/spec-symbol-batch7.test.d.ts +0 -8
  79. package/dist/__tests__/validation-feedback.test.d.ts +0 -0
  80. package/dist/__tests__/widget-aria-invalid-e2e.test.d.ts +0 -0
  81. package/dist/__tests__/widget-aria-invalid-registry-e2e.test.d.ts +0 -0
  82. package/dist/__tests__/widget-dom-leak-e2e.test.d.ts +0 -0
  83. package/dist/__tests__/widget-props-contract.test.d.ts +0 -8
  84. package/dist/coerce-safe-value.test.d.ts +0 -1
  85. package/dist/complex-widgets.test.d.ts +0 -1
  86. package/dist/datetime-widgets.test.d.ts +0 -1
  87. package/dist/field-type-coverage.test.d.ts +0 -1
  88. package/dist/standard-widgets.test.d.ts +0 -0
  89. package/dist/widgets/AddressField.uniqueIds.test.d.ts +0 -0
  90. package/dist/widgets/CapabilityMultiSelectField.test.d.ts +0 -0
  91. package/dist/widgets/CharacterCount.d.ts +0 -56
  92. package/dist/widgets/CheckboxesField.cascade.test.d.ts +0 -0
  93. package/dist/widgets/GeolocationField.uniqueIds.test.d.ts +0 -0
  94. package/dist/widgets/GridField.test.d.ts +0 -1
  95. package/dist/widgets/ImageLightbox.test.d.ts +0 -1
  96. package/dist/widgets/LookupField.dependsOn.test.d.ts +0 -8
  97. package/dist/widgets/LookupField.gateHintLabel.test.d.ts +0 -8
  98. package/dist/widgets/LookupField.hydration.test.d.ts +0 -1
  99. package/dist/widgets/LookupField.idField.test.d.ts +0 -1
  100. package/dist/widgets/MultiSelectField.cascade.test.d.ts +0 -0
  101. package/dist/widgets/OptionsEmptyState.no-provider.test.d.ts +0 -0
  102. package/dist/widgets/OptionsEmptyState.test.d.ts +0 -0
  103. package/dist/widgets/PeoplePicker.test.d.ts +0 -8
  104. package/dist/widgets/PeoplePickerComponents.test.d.ts +0 -8
  105. package/dist/widgets/RadioField.cascade.test.d.ts +0 -0
  106. package/dist/widgets/RecipientPickerField.test.d.ts +0 -0
  107. package/dist/widgets/RecordPickerDialog.filterOptions.test.d.ts +0 -8
  108. package/dist/widgets/RecordPickerDialog.selectLabel.test.d.ts +0 -8
  109. package/dist/widgets/SelectField.cascade.test.d.ts +0 -0
  110. package/dist/widgets/TagsField.placeholder.no-provider.test.d.ts +0 -0
  111. package/dist/widgets/TagsField.placeholder.test.d.ts +0 -0
  112. package/dist/widgets/UserFieldPicker.test.d.ts +0 -8
  113. package/dist/widgets/__tests__/FilterConditionField.matchAll.test.d.ts +0 -8
  114. package/dist/widgets/__tests__/FilterConditionField.operators.test.d.ts +0 -8
  115. package/dist/widgets/__tests__/FullscreenFieldEditor.i18n.test.d.ts +0 -0
  116. package/dist/widgets/__tests__/FullscreenFieldEditor.no-provider.test.d.ts +0 -0
  117. package/dist/widgets/__tests__/RichTextField.fullscreenDisabled.test.d.ts +0 -0
  118. package/dist/widgets/__tests__/RichTextField.mobileFullscreen.test.d.ts +0 -0
  119. package/dist/widgets/__tests__/TextAreaField.characterCount.announcements.test.d.ts +0 -0
  120. package/dist/widgets/__tests__/TextAreaField.characterCount.i18n.test.d.ts +0 -0
  121. package/dist/widgets/__tests__/TextAreaField.characterCount.no-provider.test.d.ts +0 -0
  122. package/dist/widgets/__tests__/TextAreaField.fullscreenCharacterCount.i18n.test.d.ts +0 -0
  123. package/dist/widgets/__tests__/TextAreaField.fullscreenCharacterCount.test.d.ts +0 -0
  124. package/dist/widgets/__tests__/TextAreaField.fullscreenDisabled.test.d.ts +0 -0
  125. package/dist/widgets/__tests__/TextAreaField.mobileFullscreen.test.d.ts +0 -0
  126. package/dist/widgets/deriveLookupColumns.test.d.ts +0 -1
  127. package/dist/widgets/file-value.test.d.ts +0 -1
  128. package/dist/widgets/personDisplay.test.d.ts +0 -8
  129. package/dist/widgets/recentLookups.test.d.ts +0 -1
  130. package/dist/widgets/useRecordQuery.test.d.ts +0 -8
  131. package/dist/widgets/useUploadingSignal.test.d.ts +0 -1
  132. package/src/FieldEditWidget.test.ts +0 -133
  133. package/src/FieldEditWidget.tsx +0 -191
  134. package/src/__tests__/DateCellRenderer.test.tsx +0 -73
  135. package/src/__tests__/NumberCellRenderer.test.tsx +0 -60
  136. package/src/__tests__/cell-truncation.test.tsx +0 -96
  137. package/src/__tests__/field-carrier-sdui.test.tsx +0 -169
  138. package/src/__tests__/lookupCellDisplayField.test.tsx +0 -107
  139. package/src/__tests__/lookupCellDisplayName.test.tsx +0 -119
  140. package/src/__tests__/lookupCellReferenceKey.test.tsx +0 -57
  141. package/src/__tests__/registry-collision.test.ts +0 -91
  142. package/src/__tests__/resolveFieldCurrency.test.ts +0 -20
  143. package/src/__tests__/spec-symbol-batch7.test.ts +0 -126
  144. package/src/__tests__/validation-feedback.test.tsx +0 -361
  145. package/src/__tests__/widget-aria-invalid-e2e.test.tsx +0 -265
  146. package/src/__tests__/widget-aria-invalid-registry-e2e.test.tsx +0 -338
  147. package/src/__tests__/widget-dom-leak-e2e.test.tsx +0 -598
  148. package/src/__tests__/widget-props-contract.test.tsx +0 -142
  149. package/src/coerce-safe-value.test.ts +0 -34
  150. package/src/complex-widgets.test.tsx +0 -908
  151. package/src/currency.ts +0 -14
  152. package/src/datetime-widgets.test.tsx +0 -93
  153. package/src/field-type-alias.ts +0 -100
  154. package/src/field-type-coverage.test.ts +0 -67
  155. package/src/index.tsx +0 -2503
  156. package/src/standard-widgets.test.tsx +0 -357
  157. package/src/widgets/AddressField.tsx +0 -132
  158. package/src/widgets/AddressField.uniqueIds.test.tsx +0 -92
  159. package/src/widgets/AutoNumberField.tsx +0 -18
  160. package/src/widgets/AvatarField.tsx +0 -117
  161. package/src/widgets/BooleanField.tsx +0 -52
  162. package/src/widgets/CapabilityMultiSelectField.test.tsx +0 -168
  163. package/src/widgets/CapabilityMultiSelectField.tsx +0 -229
  164. package/src/widgets/CharacterCount.tsx +0 -263
  165. package/src/widgets/CheckboxesField.cascade.test.tsx +0 -143
  166. package/src/widgets/CheckboxesField.tsx +0 -136
  167. package/src/widgets/CodeField.tsx +0 -41
  168. package/src/widgets/ColorField.tsx +0 -53
  169. package/src/widgets/CurrencyField.tsx +0 -95
  170. package/src/widgets/DateField.tsx +0 -31
  171. package/src/widgets/DateTimeField.tsx +0 -37
  172. package/src/widgets/EmailField.tsx +0 -37
  173. package/src/widgets/FileField.tsx +0 -494
  174. package/src/widgets/FilterConditionField.tsx +0 -454
  175. package/src/widgets/FormulaField.tsx +0 -33
  176. package/src/widgets/FullscreenFieldEditor.tsx +0 -271
  177. package/src/widgets/GeolocationField.tsx +0 -167
  178. package/src/widgets/GeolocationField.uniqueIds.test.tsx +0 -88
  179. package/src/widgets/GridField.test.tsx +0 -406
  180. package/src/widgets/GridField.tsx +0 -966
  181. package/src/widgets/ImageCropperDialog.tsx +0 -245
  182. package/src/widgets/ImageField.tsx +0 -255
  183. package/src/widgets/ImageLightbox.test.tsx +0 -52
  184. package/src/widgets/ImageLightbox.tsx +0 -108
  185. package/src/widgets/LocationField.tsx +0 -57
  186. package/src/widgets/LookupField.dependsOn.test.tsx +0 -233
  187. package/src/widgets/LookupField.gateHintLabel.test.tsx +0 -135
  188. package/src/widgets/LookupField.hydration.test.tsx +0 -136
  189. package/src/widgets/LookupField.idField.test.tsx +0 -61
  190. package/src/widgets/LookupField.tsx +0 -1291
  191. package/src/widgets/MarkdownContent.tsx +0 -19
  192. package/src/widgets/MasterDetailField.tsx +0 -131
  193. package/src/widgets/MultiSelectField.cascade.test.tsx +0 -143
  194. package/src/widgets/MultiSelectField.tsx +0 -142
  195. package/src/widgets/NumberField.tsx +0 -49
  196. package/src/widgets/ObjectField.tsx +0 -94
  197. package/src/widgets/ObjectRefField.tsx +0 -121
  198. package/src/widgets/OptionsEmptyState.no-provider.test.tsx +0 -88
  199. package/src/widgets/OptionsEmptyState.test.tsx +0 -169
  200. package/src/widgets/OptionsEmptyState.tsx +0 -83
  201. package/src/widgets/PasswordField.tsx +0 -49
  202. package/src/widgets/PeoplePicker.test.tsx +0 -360
  203. package/src/widgets/PeoplePicker.tsx +0 -579
  204. package/src/widgets/PeoplePickerComponents.test.tsx +0 -104
  205. package/src/widgets/PercentField.tsx +0 -95
  206. package/src/widgets/PersonRow.tsx +0 -117
  207. package/src/widgets/PhoneField.tsx +0 -37
  208. package/src/widgets/QRCodeField.tsx +0 -103
  209. package/src/widgets/RadioField.cascade.test.tsx +0 -141
  210. package/src/widgets/RadioField.tsx +0 -111
  211. package/src/widgets/RatingField.tsx +0 -81
  212. package/src/widgets/RecipientPickerField.test.tsx +0 -157
  213. package/src/widgets/RecipientPickerField.tsx +0 -188
  214. package/src/widgets/RecordPickerDialog.filterOptions.test.tsx +0 -611
  215. package/src/widgets/RecordPickerDialog.selectLabel.test.tsx +0 -112
  216. package/src/widgets/RecordPickerDialog.tsx +0 -1316
  217. package/src/widgets/RichTextField.tsx +0 -176
  218. package/src/widgets/SelectField.cascade.test.tsx +0 -138
  219. package/src/widgets/SelectField.tsx +0 -162
  220. package/src/widgets/SelectionTray.tsx +0 -110
  221. package/src/widgets/SignatureField.tsx +0 -140
  222. package/src/widgets/SliderField.tsx +0 -39
  223. package/src/widgets/SummaryField.tsx +0 -31
  224. package/src/widgets/TagsField.placeholder.no-provider.test.tsx +0 -68
  225. package/src/widgets/TagsField.placeholder.test.tsx +0 -95
  226. package/src/widgets/TagsField.tsx +0 -88
  227. package/src/widgets/TextAreaField.tsx +0 -213
  228. package/src/widgets/TextField.tsx +0 -45
  229. package/src/widgets/TimeField.tsx +0 -31
  230. package/src/widgets/UrlField.tsx +0 -46
  231. package/src/widgets/UserField.tsx +0 -58
  232. package/src/widgets/UserFieldPicker.test.tsx +0 -78
  233. package/src/widgets/VectorField.tsx +0 -29
  234. package/src/widgets/__tests__/FilterConditionField.matchAll.test.ts +0 -66
  235. package/src/widgets/__tests__/FilterConditionField.operators.test.ts +0 -142
  236. package/src/widgets/__tests__/FullscreenFieldEditor.i18n.test.tsx +0 -248
  237. package/src/widgets/__tests__/FullscreenFieldEditor.no-provider.test.tsx +0 -116
  238. package/src/widgets/__tests__/RichTextField.fullscreenDisabled.test.tsx +0 -244
  239. package/src/widgets/__tests__/RichTextField.mobileFullscreen.test.tsx +0 -195
  240. package/src/widgets/__tests__/TextAreaField.characterCount.announcements.test.tsx +0 -417
  241. package/src/widgets/__tests__/TextAreaField.characterCount.i18n.test.tsx +0 -287
  242. package/src/widgets/__tests__/TextAreaField.characterCount.no-provider.test.tsx +0 -160
  243. package/src/widgets/__tests__/TextAreaField.fullscreenCharacterCount.i18n.test.tsx +0 -161
  244. package/src/widgets/__tests__/TextAreaField.fullscreenCharacterCount.test.tsx +0 -346
  245. package/src/widgets/__tests__/TextAreaField.fullscreenDisabled.test.tsx +0 -246
  246. package/src/widgets/__tests__/TextAreaField.mobileFullscreen.test.tsx +0 -175
  247. package/src/widgets/_cell-renderer-bridge.ts +0 -19
  248. package/src/widgets/deriveLookupColumns.test.ts +0 -112
  249. package/src/widgets/deriveLookupColumns.ts +0 -108
  250. package/src/widgets/file-value.test.ts +0 -230
  251. package/src/widgets/file-value.ts +0 -246
  252. package/src/widgets/openNativePicker.ts +0 -18
  253. package/src/widgets/personDisplay.test.ts +0 -113
  254. package/src/widgets/personDisplay.ts +0 -92
  255. package/src/widgets/recentLookups.test.ts +0 -45
  256. package/src/widgets/recentLookups.ts +0 -47
  257. package/src/widgets/toDomProps.ts +0 -175
  258. package/src/widgets/types.ts +0 -242
  259. package/src/widgets/useCascadingOptions.ts +0 -46
  260. package/src/widgets/useFieldTranslation.ts +0 -150
  261. package/src/widgets/useRecordQuery.test.ts +0 -174
  262. package/src/widgets/useRecordQuery.ts +0 -264
  263. package/src/widgets/useUploadingSignal.test.tsx +0 -62
  264. package/src/widgets/useUploadingSignal.ts +0 -20
  265. package/src/withFieldCarrier.tsx +0 -75
package/src/currency.ts DELETED
@@ -1,14 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * Licensed under the MIT license found in the LICENSE file.
6
- */
7
-
8
- /**
9
- * `resolveFieldCurrency` now lives in `@object-ui/i18n` (co-located with
10
- * `useLocalization`, which supplies the tenant default). This module re-exports
11
- * it so the long-standing `@object-ui/fields` import path keeps working for
12
- * every field/cell renderer that already depends on it.
13
- */
14
- export { resolveFieldCurrency } from '@object-ui/i18n';
@@ -1,93 +0,0 @@
1
- import { render, screen, fireEvent } from '@testing-library/react';
2
- import { describe, it, expect, vi } from 'vitest';
3
- import { DateField } from './widgets/DateField';
4
- import { DateTimeField } from './widgets/DateTimeField';
5
- import { TimeField } from './widgets/TimeField';
6
- import type { FieldWidgetComponentProps } from './widgets/types';
7
-
8
- const mockField = {
9
- name: 'test_field',
10
- label: 'Test Field',
11
- type: 'date',
12
- } as any;
13
-
14
- const baseProps: FieldWidgetComponentProps<string> = {
15
- field: mockField,
16
- value: '',
17
- onChange: vi.fn(),
18
- readonly: false,
19
- };
20
-
21
- describe('Date/Time Widgets', () => {
22
- describe('DateField', () => {
23
- it('renders date input in edit mode', () => {
24
- const { container } = render(<DateField {...baseProps} />);
25
- const dateInput = container.querySelector('input[type="date"]');
26
- expect(dateInput).toBeInTheDocument();
27
- });
28
-
29
- it('calls onChange when value changes', () => {
30
- const { container } = render(<DateField {...baseProps} />);
31
- const input = container.querySelector('input[type="date"]') as HTMLInputElement;
32
- fireEvent.change(input, { target: { value: '2023-01-01' } });
33
- expect(baseProps.onChange).toHaveBeenCalledWith('2023-01-01');
34
- });
35
-
36
- it('renders formatted date in readonly mode', () => {
37
- render(<DateField {...baseProps} readonly value="2023-01-01" />);
38
- const date = new Date('2023-01-01');
39
- expect(screen.getByText(date.toLocaleDateString())).toBeInTheDocument();
40
- expect(document.querySelector('input')).not.toBeInTheDocument();
41
- });
42
-
43
- it('renders dash for empty readonly value', () => {
44
- render(<DateField {...baseProps} readonly value={''} />);
45
- expect(screen.getByText('—')).toBeInTheDocument();
46
- });
47
- });
48
-
49
- describe('DateTimeField', () => {
50
- it('renders datetime-local input in edit mode', () => {
51
- const { container } = render(<DateTimeField {...baseProps} />);
52
- const input = container.querySelector('input[type="datetime-local"]');
53
- expect(input).toBeInTheDocument();
54
- });
55
-
56
- it('calls onChange when value changes', () => {
57
- const { container } = render(<DateTimeField {...baseProps} />);
58
- const input = container.querySelector('input[type="datetime-local"]') as HTMLInputElement;
59
- fireEvent.change(input, { target: { value: '2023-01-01T12:00' } });
60
- expect(baseProps.onChange).toHaveBeenCalledWith('2023-01-01T12:00');
61
- });
62
-
63
- it('renders formatted datetime in readonly mode', () => {
64
- const val = '2023-01-01T12:00:00.000Z';
65
- render(<DateTimeField {...baseProps} readonly value={val} />);
66
- const date = new Date(val);
67
- const span = screen.getByText((content) => {
68
- return content.includes(date.toLocaleDateString());
69
- });
70
- expect(span).toBeInTheDocument();
71
- });
72
- });
73
-
74
- describe('TimeField', () => {
75
- it('renders time input in edit mode', () => {
76
- const { container } = render(<TimeField {...baseProps} />);
77
- const input = container.querySelector('input[type="time"]');
78
- expect(input).toBeInTheDocument();
79
- });
80
-
81
- it('calls onChange when value changes', () => {
82
- const { container } = render(<TimeField {...baseProps} />);
83
- const input = container.querySelector('input[type="time"]') as HTMLInputElement;
84
- fireEvent.change(input, { target: { value: '14:30' } });
85
- expect(baseProps.onChange).toHaveBeenCalledWith('14:30');
86
- });
87
-
88
- it('renders value directly in readonly mode', () => {
89
- render(<TimeField {...baseProps} readonly value="14:30" />);
90
- expect(screen.getByText('14:30')).toBeInTheDocument();
91
- });
92
- });
93
- });
@@ -1,100 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- /**
10
- * Map field type to form component type
11
- *
12
- * @param fieldType - The ObjectQL field type identifier to convert
13
- * (for example: `"text"`, `"number"`, `"date"`, `"lookup"`).
14
- * @returns The normalized form field type string used in the form schema
15
- * (for example: `"input"`, `"textarea"`, `"date-picker"`, `"select"`).
16
- */
17
- export function mapFieldTypeToFormType(fieldType: string): string {
18
- const typeMap: Record<string, string> = {
19
- // Text-based fields
20
- text: 'field:text',
21
- textarea: 'field:textarea',
22
- markdown: 'field:markdown', // Markdown editor (fallback to textarea)
23
- html: 'field:html', // Rich text editor (fallback to textarea)
24
- richtext: 'field:richtext', // WYSIWYG rich-text editor
25
- secret: 'field:password', // encrypted-at-rest value — mask input like a password
26
-
27
- // Numeric fields
28
- number: 'field:number',
29
- currency: 'field:currency',
30
- percent: 'field:percent',
31
- slider: 'field:slider',
32
- progress: 'field:slider', // bounded 0..100 progress — edit via slider
33
- rating: 'field:rating',
34
-
35
- // Date/Time fields
36
- date: 'field:date',
37
- datetime: 'field:datetime',
38
- time: 'field:time',
39
-
40
- // Boolean
41
- boolean: 'field:boolean',
42
- toggle: 'field:boolean', // toggle is a boolean rendered as a switch
43
-
44
- // Selection fields
45
- select: 'field:select',
46
- multiselect: 'field:multiselect',
47
- radio: 'field:radio',
48
- checkboxes: 'field:checkboxes',
49
- tags: 'field:tags',
50
- lookup: 'field:lookup',
51
- master_detail: 'field:master_detail',
52
- tree: 'field:lookup', // hierarchical reference — pick the parent via a lookup
53
- // `user` is a lookup specialized to sys_user; `owner` mirrors it (record
54
- // ownership). Both render via the UserField person-picker (delegates to the
55
- // lookup picker). Without these they would fall through to `field:text`.
56
- user: 'field:user',
57
- owner: 'field:owner',
58
-
59
- // Contact fields
60
- email: 'field:email',
61
- phone: 'field:phone',
62
- url: 'field:url',
63
-
64
- // File / media fields
65
- file: 'field:file',
66
- image: 'field:image',
67
- avatar: 'field:avatar',
68
- video: 'field:file', // uploads as a file
69
- audio: 'field:file', // uploads as a file
70
- signature: 'field:signature',
71
-
72
- // Special / enhanced fields
73
- password: 'field:password',
74
- location: 'field:location', // Location/map field (fallback to input)
75
- geolocation: 'field:geolocation',
76
- address: 'field:address',
77
- color: 'field:color',
78
- code: 'field:code',
79
- json: 'field:code', // JSON edited in the code editor
80
- qrcode: 'field:qrcode',
81
- vector: 'field:vector',
82
-
83
- // Embedded structured values (stored as JSON on the row)
84
- object: 'field:object',
85
- composite: 'field:object', // embedded object
86
- record: 'field:object', // name-keyed map
87
- repeater: 'field:grid', // embedded array of rows
88
-
89
- // Auto-generated/computed fields (typically read-only)
90
- formula: 'field:formula',
91
- summary: 'field:summary',
92
- // `@objectstack/spec` spells this `autonumber`; the widget map key is
93
- // `auto_number`. Map both spellings so a spec-typed field/param doesn't
94
- // fall through to the plain text input.
95
- autonumber: 'field:auto_number',
96
- auto_number: 'field:auto_number',
97
- };
98
-
99
- return typeMap[fieldType] || 'field:text';
100
- }
@@ -1,67 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * Regression guard for the field-type → renderer registries. These mappings
6
- * regressed once already: ~25 specialized field types silently fell back to a
7
- * plain text input (form) and the raw text cell renderer (read), because the
8
- * mapping tables were incomplete. This test locks them in so a dropped entry
9
- * fails CI instead of shipping a broken widget.
10
- */
11
- import { describe, it, expect } from 'vitest';
12
- import { mapFieldTypeToFormType, getCellRenderer, TextCellRenderer } from './index';
13
-
14
- /**
15
- * Field types that MUST resolve to a dedicated form widget — never the
16
- * `field:text` fallback. (Plain text-ish types like text/textarea are
17
- * intentionally excluded.)
18
- */
19
- const FORM_WIDGET_TYPES = [
20
- 'textarea', 'email', 'url', 'phone', 'password', 'secret',
21
- 'markdown', 'html', 'richtext',
22
- 'number', 'currency', 'percent', 'slider', 'progress', 'rating',
23
- 'date', 'datetime', 'time',
24
- 'boolean', 'toggle',
25
- 'select', 'multiselect', 'radio', 'checkboxes', 'tags',
26
- 'lookup', 'master_detail', 'tree',
27
- 'file', 'image', 'avatar', 'video', 'audio', 'signature',
28
- 'location', 'geolocation', 'address', 'color', 'code', 'json', 'qrcode', 'vector',
29
- 'object', 'composite', 'record', 'repeater',
30
- // `autonumber` is the spec `FieldType` spelling; `auto_number` is the widget
31
- // map key. Both must resolve to the AutoNumber widget, not text.
32
- 'formula', 'summary', 'auto_number', 'autonumber',
33
- ];
34
-
35
- /**
36
- * Field types that MUST resolve to a dedicated read/cell renderer — never the
37
- * generic text cell renderer. (markdown/html/richtext render formatted;
38
- * code/qrcode/time legitimately stay textual and are excluded.)
39
- */
40
- const CELL_RENDERER_TYPES = [
41
- 'email', 'url', 'phone', 'number', 'currency', 'percent', 'progress',
42
- 'boolean', 'toggle', 'date', 'datetime',
43
- 'select', 'multiselect', 'radio', 'checkboxes', 'tags',
44
- 'lookup', 'master_detail', 'tree',
45
- 'file', 'video', 'audio', 'image', 'avatar', 'signature',
46
- 'markdown', 'html', 'richtext',
47
- 'location', 'geolocation', 'address', 'color', 'json',
48
- 'formula', 'summary', 'user', 'owner',
49
- ];
50
-
51
- describe('field-type renderer coverage (regression guard)', () => {
52
- it.each(FORM_WIDGET_TYPES)('maps "%s" to a dedicated form widget (not field:text)', (type) => {
53
- const widget = mapFieldTypeToFormType(type);
54
- expect(widget).toMatch(/^field:/);
55
- expect(widget).not.toBe('field:text');
56
- });
57
-
58
- it.each(CELL_RENDERER_TYPES)('resolves "%s" to a dedicated cell renderer (not TextCellRenderer)', (type) => {
59
- const renderer = getCellRenderer(type);
60
- expect(renderer).toBeTypeOf('function');
61
- expect(renderer).not.toBe(TextCellRenderer);
62
- });
63
-
64
- it('falls back to field:text for unknown types', () => {
65
- expect(mapFieldTypeToFormType('something-unknown')).toBe('field:text');
66
- });
67
- });