@object-ui/fields 17.5.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 (229) hide show
  1. package/CHANGELOG.md +714 -0
  2. package/dist/FieldEditWidget.d.ts +16 -2
  3. package/dist/field-type-alias.d.ts +16 -0
  4. package/dist/index.cjs +4 -4
  5. package/dist/index.css +27 -9
  6. package/dist/index.d.ts +425 -72
  7. package/dist/index.js +2530 -2228
  8. package/dist/widgets/AddressField.d.ts +3 -3
  9. package/dist/widgets/AutoNumberField.d.ts +1 -1
  10. package/dist/widgets/AvatarField.d.ts +1 -1
  11. package/dist/widgets/BooleanField.d.ts +1 -1
  12. package/dist/widgets/CapabilityMultiSelectField.d.ts +1 -1
  13. package/dist/widgets/CheckboxesField.d.ts +1 -1
  14. package/dist/widgets/CodeField.d.ts +1 -1
  15. package/dist/widgets/ColorField.d.ts +1 -1
  16. package/dist/widgets/CurrencyField.d.ts +1 -1
  17. package/dist/widgets/DateField.d.ts +1 -1
  18. package/dist/widgets/DateTimeField.d.ts +1 -1
  19. package/dist/widgets/EmailField.d.ts +1 -1
  20. package/dist/widgets/FileField.d.ts +18 -2
  21. package/dist/widgets/FilterConditionField.d.ts +28 -1
  22. package/dist/widgets/FormulaField.d.ts +1 -1
  23. package/dist/widgets/FullscreenFieldEditor.d.ts +9 -2
  24. package/dist/widgets/GeolocationField.d.ts +1 -1
  25. package/dist/widgets/GridField.d.ts +56 -4
  26. package/dist/widgets/ImageField.d.ts +1 -1
  27. package/dist/widgets/LocationField.d.ts +1 -1
  28. package/dist/widgets/LookupField.d.ts +1 -1
  29. package/dist/widgets/MasterDetailField.d.ts +1 -1
  30. package/dist/widgets/MultiSelectField.d.ts +1 -1
  31. package/dist/widgets/NumberField.d.ts +1 -1
  32. package/dist/widgets/ObjectField.d.ts +1 -1
  33. package/dist/widgets/ObjectRefField.d.ts +1 -1
  34. package/dist/widgets/OptionsEmptyState.d.ts +13 -7
  35. package/dist/widgets/PasswordField.d.ts +1 -1
  36. package/dist/widgets/PercentField.d.ts +1 -1
  37. package/dist/widgets/PhoneField.d.ts +1 -1
  38. package/dist/widgets/QRCodeField.d.ts +1 -1
  39. package/dist/widgets/RadioField.d.ts +1 -1
  40. package/dist/widgets/RatingField.d.ts +1 -1
  41. package/dist/widgets/RecipientPickerField.d.ts +1 -1
  42. package/dist/widgets/RecordPickerDialog.d.ts +2 -4
  43. package/dist/widgets/RichTextField.d.ts +37 -1
  44. package/dist/widgets/SelectField.d.ts +1 -1
  45. package/dist/widgets/SignatureField.d.ts +32 -2
  46. package/dist/widgets/SliderField.d.ts +37 -2
  47. package/dist/widgets/SummaryField.d.ts +1 -1
  48. package/dist/widgets/TagsField.d.ts +1 -1
  49. package/dist/widgets/TextAreaField.d.ts +6 -2
  50. package/dist/widgets/TextField.d.ts +1 -1
  51. package/dist/widgets/TimeField.d.ts +1 -1
  52. package/dist/widgets/UrlField.d.ts +1 -1
  53. package/dist/widgets/UserField.d.ts +1 -1
  54. package/dist/widgets/VectorField.d.ts +1 -1
  55. package/dist/widgets/_cell-renderer-bridge.d.ts +1 -1
  56. package/dist/widgets/address-format.d.ts +27 -7
  57. package/dist/widgets/lookupColumnDisplay.d.ts +93 -0
  58. package/dist/widgets/richTextDisplay.d.ts +80 -0
  59. package/dist/widgets/toHostGroupProps.d.ts +119 -21
  60. package/dist/widgets/types.d.ts +8 -3
  61. package/package.json +9 -10
  62. package/dist/widgets/CharacterCount.d.ts +0 -56
  63. package/src/FieldEditWidget.test.ts +0 -133
  64. package/src/FieldEditWidget.tsx +0 -207
  65. package/src/__tests__/AddressCellRenderer.test.tsx +0 -166
  66. package/src/__tests__/CurrencyField.minorUnits.test.tsx +0 -191
  67. package/src/__tests__/CurrencyField.symbol.test.tsx +0 -198
  68. package/src/__tests__/DateCellRenderer.test.tsx +0 -82
  69. package/src/__tests__/NumberCellRenderer.grouping.test.tsx +0 -146
  70. package/src/__tests__/NumberCellRenderer.test.tsx +0 -60
  71. package/src/__tests__/PercentCellRenderer.locale.test.tsx +0 -152
  72. package/src/__tests__/PercentCellRenderer.test.tsx +0 -115
  73. package/src/__tests__/boolean-label-association-e2e.test.tsx +0 -298
  74. package/src/__tests__/capability-multiselect-retired.test.ts +0 -109
  75. package/src/__tests__/cell-truncation.test.tsx +0 -96
  76. package/src/__tests__/composite-group-label-e2e.test.tsx +0 -436
  77. package/src/__tests__/composite-group-label-readonly-e2e.test.tsx +0 -403
  78. package/src/__tests__/date-formatter-residue-4272.test.ts +0 -120
  79. package/src/__tests__/date-locale-channel.test.tsx +0 -305
  80. package/src/__tests__/field-carrier-sdui.test.tsx +0 -169
  81. package/src/__tests__/formatCurrency.centsDigit.test.tsx +0 -158
  82. package/src/__tests__/formatCurrency.minorUnits.test.tsx +0 -221
  83. package/src/__tests__/group-labelling-declaration.test.ts +0 -148
  84. package/src/__tests__/lookupCellDisplayField.test.tsx +0 -107
  85. package/src/__tests__/lookupCellDisplayName.test.tsx +0 -119
  86. package/src/__tests__/lookupCellRecordLink.test.tsx +0 -171
  87. package/src/__tests__/lookupCellReferenceKey.test.tsx +0 -57
  88. package/src/__tests__/percent-cell-vs-measure-4576.test.ts +0 -115
  89. package/src/__tests__/percent-formatter-locale-4553.test.ts +0 -147
  90. package/src/__tests__/percent-tie-halfup-4590.test.ts +0 -224
  91. package/src/__tests__/registry-collision.test.ts +0 -91
  92. package/src/__tests__/resolveFieldCurrency.test.ts +0 -20
  93. package/src/__tests__/select-label-association-e2e.test.tsx +0 -199
  94. package/src/__tests__/spec-symbol-batch7.test.ts +0 -126
  95. package/src/__tests__/validation-feedback.test.tsx +0 -361
  96. package/src/__tests__/widget-aria-invalid-e2e.test.tsx +0 -265
  97. package/src/__tests__/widget-aria-invalid-registry-e2e.test.tsx +0 -338
  98. package/src/__tests__/widget-dom-leak-e2e.test.tsx +0 -357
  99. package/src/__tests__/widget-props-contract.test.tsx +0 -142
  100. package/src/coerce-safe-value.test.ts +0 -34
  101. package/src/complex-widgets.test.tsx +0 -924
  102. package/src/currency.ts +0 -144
  103. package/src/datetime-widgets.test.tsx +0 -185
  104. package/src/field-type-alias.multiple.test.ts +0 -81
  105. package/src/field-type-alias.ts +0 -156
  106. package/src/field-type-coverage.test.ts +0 -67
  107. package/src/index.css +0 -44
  108. package/src/index.tsx +0 -2745
  109. package/src/standard-widgets.test.tsx +0 -364
  110. package/src/widgets/AddressField.postalCode.test.tsx +0 -257
  111. package/src/widgets/AddressField.tsx +0 -182
  112. package/src/widgets/AddressField.uniqueIds.test.tsx +0 -93
  113. package/src/widgets/AutoNumberField.tsx +0 -18
  114. package/src/widgets/AvatarField.tsx +0 -117
  115. package/src/widgets/BooleanField.tsx +0 -86
  116. package/src/widgets/CapabilityMultiSelectField.test.tsx +0 -168
  117. package/src/widgets/CapabilityMultiSelectField.tsx +0 -241
  118. package/src/widgets/CharacterCount.tsx +0 -263
  119. package/src/widgets/CheckboxesField.cascade.test.tsx +0 -143
  120. package/src/widgets/CheckboxesField.tsx +0 -169
  121. package/src/widgets/CodeField.tsx +0 -41
  122. package/src/widgets/ColorField.tsx +0 -53
  123. package/src/widgets/CurrencyField.tsx +0 -135
  124. package/src/widgets/DateField.tsx +0 -40
  125. package/src/widgets/DateTimeField.tsx +0 -46
  126. package/src/widgets/EmailField.tsx +0 -37
  127. package/src/widgets/FileField.tsx +0 -512
  128. package/src/widgets/FilterConditionField.tsx +0 -454
  129. package/src/widgets/FormulaField.tsx +0 -38
  130. package/src/widgets/FullscreenFieldEditor.tsx +0 -60
  131. package/src/widgets/GeolocationField.tsx +0 -193
  132. package/src/widgets/GeolocationField.uniqueIds.test.tsx +0 -88
  133. package/src/widgets/GridField.test.tsx +0 -632
  134. package/src/widgets/GridField.tsx +0 -1070
  135. package/src/widgets/ImageCropperDialog.tsx +0 -245
  136. package/src/widgets/ImageField.maxSize.test.tsx +0 -154
  137. package/src/widgets/ImageField.tsx +0 -305
  138. package/src/widgets/ImageLightbox.test.tsx +0 -52
  139. package/src/widgets/ImageLightbox.tsx +0 -108
  140. package/src/widgets/LocationField.tsx +0 -57
  141. package/src/widgets/LookupField.dependsOn.test.tsx +0 -233
  142. package/src/widgets/LookupField.gateHintLabel.test.tsx +0 -135
  143. package/src/widgets/LookupField.hydration.test.tsx +0 -136
  144. package/src/widgets/LookupField.idField.test.tsx +0 -61
  145. package/src/widgets/LookupField.tsx +0 -1295
  146. package/src/widgets/MarkdownContent.tsx +0 -19
  147. package/src/widgets/MasterDetailField.tsx +0 -131
  148. package/src/widgets/MultiSelectField.cascade.test.tsx +0 -143
  149. package/src/widgets/MultiSelectField.tsx +0 -196
  150. package/src/widgets/NumberField.tsx +0 -49
  151. package/src/widgets/ObjectField.tsx +0 -94
  152. package/src/widgets/ObjectRefField.tsx +0 -121
  153. package/src/widgets/OptionsEmptyState.no-provider.test.tsx +0 -88
  154. package/src/widgets/OptionsEmptyState.test.tsx +0 -169
  155. package/src/widgets/OptionsEmptyState.tsx +0 -99
  156. package/src/widgets/PasswordField.tsx +0 -49
  157. package/src/widgets/PeoplePicker.test.tsx +0 -360
  158. package/src/widgets/PeoplePicker.tsx +0 -579
  159. package/src/widgets/PeoplePickerComponents.test.tsx +0 -104
  160. package/src/widgets/PercentField.tsx +0 -95
  161. package/src/widgets/PersonRow.tsx +0 -117
  162. package/src/widgets/PhoneField.tsx +0 -37
  163. package/src/widgets/QRCodeField.tsx +0 -103
  164. package/src/widgets/RadioField.cascade.test.tsx +0 -141
  165. package/src/widgets/RadioField.tsx +0 -143
  166. package/src/widgets/RatingField.tsx +0 -94
  167. package/src/widgets/RecipientPickerField.test.tsx +0 -157
  168. package/src/widgets/RecipientPickerField.tsx +0 -188
  169. package/src/widgets/RecordPickerDialog.baseFilterShapes.test.tsx +0 -191
  170. package/src/widgets/RecordPickerDialog.dateLocale.test.tsx +0 -124
  171. package/src/widgets/RecordPickerDialog.filterOptions.test.tsx +0 -611
  172. package/src/widgets/RecordPickerDialog.selectLabel.test.tsx +0 -112
  173. package/src/widgets/RecordPickerDialog.tsx +0 -1365
  174. package/src/widgets/RichTextField.tsx +0 -176
  175. package/src/widgets/SelectField.cascade.test.tsx +0 -138
  176. package/src/widgets/SelectField.tsx +0 -193
  177. package/src/widgets/SelectionTray.tsx +0 -110
  178. package/src/widgets/SignatureField.tsx +0 -140
  179. package/src/widgets/SliderField.tsx +0 -39
  180. package/src/widgets/SummaryField.tsx +0 -31
  181. package/src/widgets/TagsField.placeholder.no-provider.test.tsx +0 -68
  182. package/src/widgets/TagsField.placeholder.test.tsx +0 -95
  183. package/src/widgets/TagsField.tsx +0 -88
  184. package/src/widgets/TextAreaField.tsx +0 -213
  185. package/src/widgets/TextField.tsx +0 -45
  186. package/src/widgets/TimeField.tsx +0 -31
  187. package/src/widgets/UrlField.tsx +0 -46
  188. package/src/widgets/UserField.tsx +0 -59
  189. package/src/widgets/UserFieldPicker.test.tsx +0 -78
  190. package/src/widgets/VectorField.tsx +0 -29
  191. package/src/widgets/__tests__/FilterConditionField.matchAll.test.ts +0 -66
  192. package/src/widgets/__tests__/FilterConditionField.operators.test.ts +0 -166
  193. package/src/widgets/__tests__/FullscreenFieldEditor.i18n.test.tsx +0 -248
  194. package/src/widgets/__tests__/FullscreenFieldEditor.no-provider.test.tsx +0 -116
  195. package/src/widgets/__tests__/RichTextField.fullscreenDisabled.test.tsx +0 -244
  196. package/src/widgets/__tests__/RichTextField.mobileFullscreen.test.tsx +0 -195
  197. package/src/widgets/__tests__/TextAreaField.characterCount.announcements.test.tsx +0 -417
  198. package/src/widgets/__tests__/TextAreaField.characterCount.i18n.test.tsx +0 -287
  199. package/src/widgets/__tests__/TextAreaField.characterCount.no-provider.test.tsx +0 -160
  200. package/src/widgets/__tests__/TextAreaField.fullscreenCharacterCount.i18n.test.tsx +0 -161
  201. package/src/widgets/__tests__/TextAreaField.fullscreenCharacterCount.test.tsx +0 -346
  202. package/src/widgets/__tests__/TextAreaField.fullscreenDisabled.test.tsx +0 -246
  203. package/src/widgets/__tests__/TextAreaField.mobileFullscreen.test.tsx +0 -175
  204. package/src/widgets/_cell-renderer-bridge.ts +0 -19
  205. package/src/widgets/address-format.ts +0 -120
  206. package/src/widgets/deriveLookupColumns.test.ts +0 -112
  207. package/src/widgets/deriveLookupColumns.ts +0 -108
  208. package/src/widgets/file-size-guard.ts +0 -55
  209. package/src/widgets/file-value.test.ts +0 -230
  210. package/src/widgets/file-value.ts +0 -246
  211. package/src/widgets/nativeDateValue.test.ts +0 -115
  212. package/src/widgets/nativeDateValue.ts +0 -112
  213. package/src/widgets/openNativePicker.ts +0 -18
  214. package/src/widgets/optionWidgets.gatedOptions.test.tsx +0 -267
  215. package/src/widgets/optionWidgets.unconfiguredOptions.test.tsx +0 -150
  216. package/src/widgets/personDisplay.test.ts +0 -113
  217. package/src/widgets/personDisplay.ts +0 -92
  218. package/src/widgets/recentLookups.test.ts +0 -45
  219. package/src/widgets/recentLookups.ts +0 -47
  220. package/src/widgets/toDomProps.ts +0 -204
  221. package/src/widgets/toHostGroupProps.ts +0 -102
  222. package/src/widgets/types.ts +0 -242
  223. package/src/widgets/useCascadingOptions.ts +0 -46
  224. package/src/widgets/useFieldTranslation.ts +0 -132
  225. package/src/widgets/useRecordQuery.test.ts +0 -174
  226. package/src/widgets/useRecordQuery.ts +0 -291
  227. package/src/widgets/useUploadingSignal.test.tsx +0 -62
  228. package/src/widgets/useUploadingSignal.ts +0 -20
  229. package/src/withFieldCarrier.tsx +0 -75
@@ -1,7 +1,7 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
3
- import { AddressValue } from './address-format';
4
- export type { AddressValue } from './address-format';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
+ import { AddressValue } from './address-format.js';
4
+ export type { AddressValue } from './address-format.js';
5
5
  /**
6
6
  * Address field widget - provides a structured address input
7
7
  * Supports street, city, state, postal code, and country
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * AutoNumberField - Read-only auto-generated field
5
5
  * Values are automatically generated by the system and cannot be edited
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Avatar field widget - provides an avatar/profile picture uploader
5
5
  * Supports image URLs or file uploads
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * BooleanField - Toggle input supporting switch and checkbox variants
5
5
  * Renders as Switch or Checkbox based on field widget configuration
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Parse the stored value into the selected capability-name list. The canonical
5
5
  * storage is a JSON-string array; we also tolerate an already-parsed array (in
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * CheckboxesField - select zero or more values from a fixed option set, rendered
5
5
  * as a list of checkboxes. The stored value is a string[]. Used for the
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Code field widget - provides a code editor with syntax highlighting
5
5
  * Uses a simple textarea with monospace font
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Color field widget - provides a color picker input
5
5
  * Supports hex color values (e.g., #ff0000)
@@ -1,3 +1,3 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  export declare function CurrencyField({ value, onChange, field, readonly, error, className, ...props }: FieldWidgetComponentProps<number>): React.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * DateField - Date picker input widget
5
5
  * Uses native date input and displays locale-formatted date in readonly mode
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * DateTimeField - Combined date and time picker widget
5
5
  * Displays both date and time in locale format when readonly
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * EmailField - Email address input with mailto link in readonly mode
5
5
  * Renders as a clickable mailto link when readonly, standard email input otherwise
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * FileField - File upload widget with drag-and-drop support
5
5
  * Supports single and multiple file uploads with configurable accepted file types.
@@ -15,7 +15,7 @@ export declare function FileField({ value, onChange, field, readonly, onUploadin
15
15
  * drag-and-drop zone — a grid cell has no room for one; the per-row expand
16
16
  * form still offers the full-size FileField.
17
17
  */
18
- export declare function FileCell({ value, onChange, disabled, multiple, accept, maxSize, 'aria-label': ariaLabel, 'data-cell': dataCell, }: {
18
+ export declare function FileCell({ value, onChange, disabled, multiple, accept, maxSize, error, 'aria-label': ariaLabel, 'data-cell': dataCell, }: {
19
19
  value: any;
20
20
  onChange: (value: any) => void;
21
21
  disabled?: boolean;
@@ -24,6 +24,22 @@ export declare function FileCell({ value, onChange, disabled, multiple, accept,
24
24
  accept?: string;
25
25
  /** Max file size in bytes (oversize picks are rejected with an inline error). */
26
26
  maxSize?: number;
27
+ /**
28
+ * The active validation message for this cell, named as
29
+ * `@objectstack/spec/ui`'s `FieldWidgetPropsSchema` names it — the same
30
+ * published slot `FieldWidgetComponentProps` declares and `LookupField` /
31
+ * `FileField` above already consume (objectui#5431, completing #3318's
32
+ * per-cell delivery). NOT the per-pick upload `errors` this component
33
+ * computes itself — this is the HOST's verdict on the cell's value.
34
+ *
35
+ * **Producer**: `GridField`, for a required-but-empty `file` cell.
36
+ * **Consumer**: drives `aria-invalid` on the picker button — the focusable
37
+ * control assistive tech reads a control state from (objectui#5223; a mark
38
+ * on the non-focusable wrapper is exactly what the registry sweep forbids).
39
+ * The message TEXT stays with the cell's `title` in `GridField`; rendering
40
+ * it here would double-display it.
41
+ */
42
+ error?: string;
27
43
  'aria-label'?: string;
28
44
  /** Focus-grid coordinate (see GridField keyboard navigation). */
29
45
  'data-cell'?: string;
@@ -1,11 +1,38 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  interface BuilderCondition {
4
4
  id: string;
5
5
  field: string;
6
6
  operator: string;
7
7
  value: any;
8
8
  }
9
+ /**
10
+ * Opt-in FilterBuilder operators this widget offers (objectui#4023,
11
+ * objectui#4736).
12
+ *
13
+ * The shared dropdown withholds these because two of its three consumers
14
+ * persist into dialects that cannot carry them (see `OPT_IN_OPERATORS` in
15
+ * `@object-ui/components`'s `filter-builder.tsx`). THIS widget can: its value
16
+ * is a MongoDB-style `FieldOperatorsSchema` criteria that the server's engine
17
+ * evaluates directly — never lowered through the array/triplet AST and never
18
+ * folded into a `ViewFilterRule` — so the spec's `FILTER_OPERATORS` is the only
19
+ * vocabulary it has to satisfy.
20
+ *
21
+ * - `containsCaseInsensitive` authors `$icontains`, executable on every
22
+ * driver and evaluation face the platform ships (objectstack#5702 +
23
+ * objectstack#6520).
24
+ * - `exists` / `notExists` author `$exists`, which `condToMongo` has emitted
25
+ * and `kvToCondition` has read back since objectui#2942. Naming them here
26
+ * is what KEEPS them reachable now that the shared dropdown no longer
27
+ * offers them to the list and view surfaces, whose dialects have no
28
+ * existence operator at all (objectui#4736).
29
+ *
30
+ * Module scope, not an inline literal: a fresh array each render would reset
31
+ * `FilterBuilder`'s memo inputs on every keystroke.
32
+ *
33
+ * @internal exported for tests
34
+ */
35
+ export declare const FILTER_CONDITION_EXTRA_OPERATORS: readonly string[];
9
36
  /**
10
37
  * Builder condition → `$`-operator criteria. Exported for tests: this is the
11
38
  * chokepoint where a builder token becomes a spec `FieldOperatorsSchema` key,
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * FormulaField - Read-only computed field
5
5
  * Values are computed on the backend and cannot be edited
@@ -36,8 +36,15 @@ import { FullscreenEditorProps } from '@object-ui/components';
36
36
  * primitive already answers it (no affordance at all).
37
37
  *
38
38
  * Everything else — `value` / `onCommit` / `label` / `testIdPrefix` /
39
- * `disabled` / `children` / `footer` — passes straight through, so the hosts and
40
- * their pins are unchanged. `testIdPrefix` still namespaces this package's ids
39
+ * `disabled` / `error` / `children` / `footer` — passes straight through, so the
40
+ * hosts and their pins are unchanged. `error` is REQUIRED by the primitive
41
+ * (objectui#4824) and stays required here: both hosts already destructure it off
42
+ * the widget props contract (objectui#3222), and it is what the primitive turns
43
+ * into the dialog control's `aria-invalid` / `aria-errormessage` and into the
44
+ * dialog-local message node. A host that omits it gets a dialog announcing
45
+ * `aria-invalid="false"` for an invalid field, which is the defect #4824
46
+ * measured — so the type system asks for it rather than trusting the next
47
+ * author to remember. `testIdPrefix` still namespaces this package's ids
41
48
  * (`textarea-`, `richtext-`), distinct from the built-in branch's
42
49
  * `form-textarea-`, so a test can still say which render path it found.
43
50
  */
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Geolocation data structure
5
5
  */
@@ -1,8 +1,45 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * GridField / LineItemsField — editable child-grid ("line items") widget.
5
5
  *
6
+ * ## Where the host's label and help text land, and why (objectui#4857)
7
+ *
8
+ * This widget forwarded nothing a host handed it, so the field's visible label
9
+ * pointed `for` at an id no element carried and the help text had zero
10
+ * consumers. Measured on `origin/main` at `e71c854ce`, a real form, editable
11
+ * state, `description` set:
12
+ *
13
+ * ```
14
+ * bare (no columns) for=DANGLING hostIdEl=NONE consumers=0 focusables=[button]
15
+ * columns + one row for=DANGLING hostIdEl=NONE consumers=0 focusables=[drag,
16
+ * input(Item), input(Qty), button(Duplicate row),
17
+ * button(Remove row), input(Item), input(Qty), button(Add)]
18
+ * ```
19
+ *
20
+ * The bare row's single focusable is the auxiliary "Add line" BUTTON — labelable,
21
+ * but routing the host id (and so the label's `for`) onto it would make the
22
+ * field's label NAME the add-row action and make a click on the label insert a
23
+ * row. Every realistic config is a composite: many cell inputs, each with its
24
+ * own `aria-label`, under one container. So this widget declares
25
+ * `labelling: 'group'` (see `FIELD_WIDGET_LABELLING` in `../index`) — the
26
+ * objectui#3961 composite shape, like `address` — and the CONTAINER consumes the
27
+ * host's keys:
28
+ *
29
+ * - editable / list mode: the root div takes the DOM pass-through minus `name`
30
+ * (DOM-legal on form controls only — the objectui#3291 leak) and minus
31
+ * `aria-invalid` (control-channel state; this grid reports validity per CELL,
32
+ * with its own inline marks), answering `role="group"` only when a host
33
+ * actually named it — `CheckboxesField`'s split, key for key.
34
+ *
35
+ * That strip STANDS (objectui#3318 upheld it rather than overturning it):
36
+ * the container is not a control, so the host's state is not re-routed onto
37
+ * it. What #3318 added is the other half the strip implied but nobody had
38
+ * built — the host's failure now DRIVES the per-cell channel this comment
39
+ * already claimed as the reporting path. See `hostFailedEmpty`.
40
+ * - readonly: the table replaces the inputs entirely, so that surface takes the
41
+ * name AND the description via `toHostGroupProps` — `'instead-of-the-inputs'`.
42
+ *
6
43
  * A controlled component: `value` is an array of row objects, `onChange`
7
44
  * receives the next array. It renders one editable cell per configured
8
45
  * column, supports add / delete row, and shows a running total of a numeric
@@ -10,7 +47,7 @@ import { FieldWidgetComponentProps } from './types';
10
47
  * engine behind the master-detail subform (see ADR-0001).
11
48
  *
12
49
  * Column config (a subset of `GridColumnDefinition`):
13
- * { field, label?, type?, options?, width?, required?, prefix?, step? }
50
+ * { name, label?, type?, options?, width?, required?, prefix?, step? }
14
51
  * type ∈ 'text' | 'number' | 'currency' | 'date' | 'datetime' | 'time'
15
52
  * | 'select' | 'lookup' | 'file'
16
53
  *
@@ -18,7 +55,22 @@ import { FieldWidgetComponentProps } from './types';
18
55
  * columns, min_rows, max_rows, allow_add, allow_delete, total_field
19
56
  */
20
57
  export interface GridColumn {
21
- field: string;
58
+ /**
59
+ * The column's field name — the key it reads and writes on each row object.
60
+ *
61
+ * Spelled `name`, exactly as the declared `GridColumnDefinition`
62
+ * (`@object-ui/types`) and the grid docs page say (objectui#3951). This
63
+ * widget used to read a divergent `field` key, so metadata authored against
64
+ * the published type rendered every cell empty plus a React key warning.
65
+ * There is deliberately no tolerant alias bridging the retired spelling to
66
+ * this one: a single spelling, enforced at the producer — AGENTS.md #0.1.
67
+ *
68
+ * (Wording note: do not restate that rule as an alternation expression over
69
+ * the two key names. `column-identity.ratchet.test.ts` (objectui#3104) scans
70
+ * these files line by line and cannot tell prose from code, so spelling the
71
+ * shape out here registers as a new dual read and fails the gate.)
72
+ */
73
+ name: string;
22
74
  label?: string;
23
75
  /**
24
76
  * Cell control + read/write adapter for the column.
@@ -114,7 +166,7 @@ export declare function lookupAutofillPatch(columns: GridColumn[], col: GridColu
114
166
  export declare function computeRow(columns: GridColumn[], row: Row): Row;
115
167
  /** Sum a numeric column across rows (ignoring blanks/NaN). */
116
168
  export declare function sumColumn(rows: Row[], field: string): number;
117
- export declare function GridField({ value, onChange, field, readonly, disabled, className, onRowExpand, displayMode, onAdd, ...props }: FieldWidgetComponentProps<Row[]> & {
169
+ export declare function GridField({ value, onChange, field, readonly, disabled, className, error, onRowExpand, displayMode, onAdd, ...props }: FieldWidgetComponentProps<Row[]> & {
118
170
  /** When provided, each row shows an "expand" button that opens the row in a
119
171
  * full form (the host — e.g. MasterDetailForm — renders the drawer/modal and
120
172
  * writes the edited values back). Lets a "fat" child be edited in a real form
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * ImageField - Image upload widget with preview thumbnails
5
5
  * Supports single and multiple image uploads with drag-and-drop and preview display
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * LocationField - Geographic coordinate input for latitude and longitude
5
5
  * Stores location as { latitude, longitude } object and displays as comma-separated pair
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  export interface LookupOption {
4
4
  value: string | number;
5
5
  label: string;
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Master-Detail relationship data structure
5
5
  */
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * MultiSelectField - select zero or more values from a fixed option set.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * NumberField - Numeric input with optional decimal precision
5
5
  * Supports min/max/step constraints and configurable decimal precision
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * ObjectField - JSON object editor
5
5
  * Allows editing structured JSON data
@@ -1,4 +1,4 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  export declare function ObjectRefField({ value, onChange, readonly, className, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
4
4
  export default ObjectRefField;
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { HostGroupProps } from './toHostGroupProps';
2
+ import { HostGroupProps } from './toHostGroupProps.js';
3
3
  /**
4
4
  * The "this option list cannot be filled" state shared by every fixed-option
5
5
  * widget (`SelectField` single, `MultiSelectField`, `RadioField`,
@@ -46,13 +46,19 @@ export interface OptionsEmptyStateProps {
46
46
  * The host label's IDREF plumbing, when this box is the whole rendered surface
47
47
  * of a group-labelled field (objectui#3990) — a `checkboxes` / `radio` /
48
48
  * `multiselect` whose option list came back empty renders NOTHING but this
49
- * box, so the visible label named zero elements until it landed here.
49
+ * box, so the visible label named zero elements until it landed here. Its
50
+ * help text described zero elements for the same reason, which is why the
51
+ * callers ask `toHostGroupProps` for the `'instead-of-the-inputs'` surface:
52
+ * there is no option control in this state to announce the description on
53
+ * (objectui#4005).
50
54
  *
51
- * A closed three-key type rather than an open props tail: only `id`,
52
- * `aria-labelledby` and the `role` that makes them meaningful may reach this
53
- * element, and reopening a spread is what objectui#3291 exists to prevent.
54
- * Absent for the single `SelectField` — it is not group-labelled, its label
55
- * still uses a plain `for`, and it must keep emitting no such attributes.
55
+ * A closed type rather than an open props tail: only `id`, `aria-labelledby`,
56
+ * `aria-describedby` and the `role` that makes them meaningful may reach this
57
+ * element, and reopening a spread is what objectui#3291 exists to prevent —
58
+ * `aria-invalid` / `aria-required` are control-channel state and stay off this
59
+ * surface. Absent for the single `SelectField` — it is not group-labelled, its
60
+ * label still uses a plain `for`, and it must keep emitting no such
61
+ * attributes.
56
62
  */
57
63
  hostGroupProps?: HostGroupProps;
58
64
  }
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * PasswordField - Secure password input with visibility toggle
5
5
  * Includes show/hide toggle button and masks value in readonly mode
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * PercentField - Percentage input with configurable decimal precision
5
5
  * Stores values as decimals (0-1) and displays as percentages (0-100%)
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * PhoneField - Telephone number input with tel link in readonly mode
5
5
  * Renders as a clickable tel link when readonly, standard phone input otherwise
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * QR Code field widget - generates QR codes from text
5
5
  * Uses a simple SVG-based QR code generator
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * RadioField - choose exactly one value from a fixed option set, rendered as a
5
5
  * radio group. The stored value is the selected option value (string). Used for
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Rating field widget - provides a star rating input
5
5
  * Supports numeric values from 0 to max (default 5)
@@ -1,4 +1,4 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  export declare function RecipientPickerField({ value, onChange, readonly, className, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
4
4
  export default RecipientPickerField;
@@ -1,13 +1,11 @@
1
1
  import { default as React } from 'react';
2
2
  import { DataSource, LookupColumnDef, LookupFilterDef } from '@object-ui/types';
3
+ import { LookupCellRendererResolver } from './lookupColumnDisplay.js';
3
4
  /**
4
5
  * Cell renderer function signature — matches getCellRenderer from @object-ui/fields.
5
6
  * Accepts a field type and returns a React component that renders a formatted cell.
6
7
  */
7
- export type CellRendererResolver = (fieldType: string) => React.FC<{
8
- value: any;
9
- field: any;
10
- }>;
8
+ export type CellRendererResolver = LookupCellRendererResolver;
11
9
  /**
12
10
  * Filter column definition used by the inline filter bar.
13
11
  * A subset of LookupColumnDef enriched with filter-specific metadata.
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Rich text field with markdown/HTML support
5
5
  * For now, this is a simple textarea. A full implementation would use
@@ -22,5 +22,41 @@ import { FieldWidgetComponentProps } from './types';
22
22
  * tolerant fallback in one of them. The affordance and dialog themselves come
23
23
  * from the shared `FullscreenFieldEditor`, so one form-level setting keeps
24
24
  * producing one behaviour across both widgets.
25
+ *
26
+ * ## Readonly display (objectui#5498)
27
+ *
28
+ * The readonly early return used to render `{value}` as a React TEXT CHILD,
29
+ * so a readonly field of any of the three types showed the user the markup
30
+ * SOURCE of their own content — a `markdown` field's asterisks and hashes, a
31
+ * `richtext` field's tags. The `prose` classes on that wrapper were the tell:
32
+ * they exist to style RENDERED rich content and there was none to style. Every
33
+ * other read surface — grid, kanban card, gallery, related list, dashboard
34
+ * record panel, record detail read mode — dispatches through `getCellRenderer`
35
+ * and renders the same stored bytes FORMATTED, so one field disagreed with
36
+ * itself depending on which surface it was read on, and this branch was the
37
+ * one disagreeing with the platform.
38
+ *
39
+ * It now renders through {@link richTextCellRenderer} — literally the same
40
+ * components `getCellRenderer` resolves, one table shared by both (see
41
+ * `./richTextDisplay.tsx`), so the html/richtext path carries that renderer's
42
+ * `sanitizeHtml` trust boundary rather than a second hand-rolled escape, and a
43
+ * future change to either pipeline moves both surfaces at once.
44
+ *
45
+ * ## Host plumbing (objectui#4810)
46
+ *
47
+ * The editable branch had no `toDomProps` at all, so everything
48
+ * `<FormControl>`'s Radix `Slot` hands down — the field's `id`, the
49
+ * `aria-describedby` naming its `<FormDescription>` and `<FormMessage>` —
50
+ * arrived as props and landed on no element. Measured on a real form: the
51
+ * visible label's `for` pointed at an id nothing carried (`for=DANGLING`) and
52
+ * the rendered description had zero consumers, for all three registry keys
53
+ * (`markdown` / `html` / `richtext`) since they are this one widget.
54
+ *
55
+ * The fix is objectui#3318's standing recipe — `toDomProps(props)` spread onto
56
+ * the REAL focusable control, which here is the `<Textarea>` inside
57
+ * `RichTextEditorSurface`, never the wrapper `<div>`s (a non-focusable wrapper
58
+ * carrying the id would satisfy `document.getElementById` and still leave the
59
+ * label inert). Only the inline surface receives it; see `domProps` there for
60
+ * why the dialog's copy must not.
25
61
  */
26
62
  export declare function RichTextField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * SelectField - dropdown selection widget.
5
5
  *
@@ -1,7 +1,37 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Signature field widget - provides a signature pad for capturing signatures
5
5
  * Outputs signature as a base64 PNG image
6
+ *
7
+ * ## Naming, and the half that is deliberately absent (objectui#3318)
8
+ *
9
+ * This widget forwarded nothing a host handed it — every branch below wrote its
10
+ * attributes by hand — so its visible label pointed `for` at an id no element
11
+ * in the row carried, and the rendered help text had zero consumers. Measured
12
+ * on `origin/main`, a real form, this field required and freshly failed:
13
+ *
14
+ * ```
15
+ * signature labelFor=…-form-item -> DANGLING descConsumers=0 ids=[]
16
+ * ```
17
+ *
18
+ * The name and the description arrive here, on the container, through
19
+ * {@link toHostGroupProps} — the objectui#3961 route for a widget whose surface
20
+ * no `<label for>` can reach (`<canvas>` is not a labelable element), and which
21
+ * therefore declares `labelling: 'group'` in `FIELD_WIDGET_LABELLING`.
22
+ * `'instead-of-the-inputs'` because this field renders no input of its own for
23
+ * the description to land on: the Clear button is auxiliary — it acts on the
24
+ * value, it is not the value's control — the same reading that put
25
+ * `geolocation`'s focusable "View on map" link on that side of the split.
26
+ *
27
+ * `aria-invalid` and `aria-required` are NOT here, and their absence is a
28
+ * verdict rather than an omission. The drawing surface has no keyboard path at
29
+ * all (measured: this row offers zero focusable elements while empty — the only
30
+ * candidate, Clear, is `disabled` until something has been drawn), so there is
31
+ * no element assistive technology would read a control state from. Marking the
32
+ * container instead would announce a state with no control behind it — the
33
+ * non-focusable-wrapper move objectui#3291 and #3318 both draw the line
34
+ * against. The type is recorded in that sweep's NOT_APPLICABLE ledger with a
35
+ * guard that turns red the day a real control appears here.
6
36
  */
7
- export declare function SignatureField({ value, onChange, readonly }: FieldWidgetComponentProps<string>): React.JSX.Element;
37
+ export declare function SignatureField({ value, onChange, readonly, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
@@ -1,7 +1,42 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * Slider field widget - provides a range slider input
5
5
  * Supports numeric values with configurable min, max, and step
6
+ *
7
+ * ## Where the host's facts go, and why (objectui#3318)
8
+ *
9
+ * This widget used to read exactly two keys off its props (`disabled`,
10
+ * `className`) and forward nothing else, so everything `<FormControl>`'s Slot
11
+ * delivered was dropped on the floor. Measured on `origin/main`, a real form
12
+ * with a required slider that had just failed validation:
13
+ *
14
+ * ```
15
+ * ariaInvalidTrue=[] labelFor=…-form-item -> DANGLING
16
+ * descConsumers=0 ids=[] <- no element of the row carried an id at all
17
+ * ```
18
+ *
19
+ * Three channels, one cause. The DOM pass-through now goes to the THUMB — the
20
+ * `span[role="slider"]` a keyboard user lands on, which is where ARIA state
21
+ * belongs — through the `thumbProps` the primitive grew for this
22
+ * (`lib/slider-thumb.ts`; the shadcn `ui/slider.tsx` renders its thumb
23
+ * internally and exports only `Slider`, so it cannot be addressed from here
24
+ * the way objectui#3306 addressed `SelectTrigger`).
25
+ *
26
+ * The split of which keys stay on Root is `SelectField`'s, key for key:
27
+ *
28
+ * - `name`: Root owns the hidden input that takes part in form submission; on
29
+ * a `span` it is not even DOM-legal, and is exactly the leak objectui#3291
30
+ * sweeps for.
31
+ * - `disabled`: Root is the single authority (it disables the thumb and the
32
+ * hidden input together); forwarding the raw prop to the thumb as well would
33
+ * give the state a second, OR-merged author.
34
+ *
35
+ * The visible label reaches the thumb by IDREF, not by `for`: a
36
+ * `span[role="slider"]` is not one of HTML's labelable elements, so this widget
37
+ * is declared `labelling: 'group'` for the same reason `file` is — see
38
+ * `FIELD_WIDGET_LABELLING` in `../index` and objectui#3961. No extra
39
+ * `role="group"` wrapper: there is one control here, and `slider` is a role
40
+ * that carries a name perfectly well on its own.
6
41
  */
7
- export declare function SliderField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<number>): React.JSX.Element;
42
+ export declare function SliderField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<number>): React.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { FieldWidgetComponentProps } from './types';
2
+ import { FieldWidgetComponentProps } from './types.js';
3
3
  /**
4
4
  * SummaryField - Read-only aggregation field
5
5
  * Values are aggregated from related records and cannot be edited