@object-ui/fields 17.2.0 → 17.5.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.
- package/CHANGELOG.md +1533 -0
- package/README.md +1 -12
- package/dist/FieldEditWidget.d.ts +7 -1
- package/dist/currency.d.ts +46 -0
- package/dist/field-type-alias.d.ts +19 -1
- package/dist/index.cjs +5 -5
- package/dist/index.css +633 -0
- package/dist/index.d.ts +52 -12
- package/dist/index.js +5167 -4759
- package/dist/widgets/AddressField.d.ts +4 -12
- package/dist/widgets/AvatarField.d.ts +1 -1
- package/dist/widgets/CharacterCount.d.ts +56 -0
- package/dist/widgets/CheckboxesField.d.ts +1 -1
- package/dist/widgets/CodeField.d.ts +1 -1
- package/dist/widgets/ColorField.d.ts +1 -1
- package/dist/widgets/CurrencyField.d.ts +1 -1
- package/dist/widgets/EmailField.d.ts +1 -1
- package/dist/widgets/FileField.d.ts +1 -1
- package/dist/widgets/FilterConditionField.d.ts +1 -1
- package/dist/widgets/FullscreenFieldEditor.d.ts +45 -0
- package/dist/widgets/GeolocationField.d.ts +1 -1
- package/dist/widgets/GridField.d.ts +12 -2
- package/dist/widgets/ImageField.d.ts +1 -1
- package/dist/widgets/LocationField.d.ts +1 -1
- package/dist/widgets/LookupField.d.ts +1 -1
- package/dist/widgets/MultiSelectField.d.ts +1 -1
- package/dist/widgets/ObjectField.d.ts +1 -1
- package/dist/widgets/ObjectRefField.d.ts +1 -1
- package/dist/widgets/OptionsEmptyState.d.ts +59 -0
- package/dist/widgets/PercentField.d.ts +1 -1
- package/dist/widgets/PhoneField.d.ts +1 -1
- package/dist/widgets/QRCodeField.d.ts +1 -1
- package/dist/widgets/RadioField.d.ts +1 -1
- package/dist/widgets/RatingField.d.ts +1 -1
- package/dist/widgets/RecipientPickerField.d.ts +1 -1
- package/dist/widgets/RecordPickerDialog.d.ts +49 -7
- package/dist/widgets/RichTextField.d.ts +19 -1
- package/dist/widgets/SelectField.d.ts +25 -5
- package/dist/widgets/TagsField.d.ts +1 -1
- package/dist/widgets/TextAreaField.d.ts +44 -5
- package/dist/widgets/UrlField.d.ts +1 -1
- package/dist/widgets/address-format.d.ts +68 -0
- package/dist/widgets/file-size-guard.d.ts +41 -0
- package/dist/widgets/nativeDateValue.d.ts +37 -0
- package/dist/widgets/toDomProps.d.ts +111 -0
- package/dist/widgets/toHostGroupProps.d.ts +91 -0
- package/dist/widgets/types.d.ts +128 -33
- package/dist/widgets/useRecordQuery.d.ts +7 -1
- package/dist/withFieldCarrier.d.ts +56 -0
- package/package.json +20 -16
- package/src/FieldEditWidget.tsx +17 -1
- package/src/__tests__/AddressCellRenderer.test.tsx +166 -0
- package/src/__tests__/CurrencyField.minorUnits.test.tsx +191 -0
- package/src/__tests__/CurrencyField.symbol.test.tsx +198 -0
- package/src/__tests__/DateCellRenderer.test.tsx +9 -0
- package/src/__tests__/NumberCellRenderer.grouping.test.tsx +146 -0
- package/src/__tests__/PercentCellRenderer.locale.test.tsx +152 -0
- package/src/__tests__/PercentCellRenderer.test.tsx +115 -0
- package/src/__tests__/boolean-label-association-e2e.test.tsx +298 -0
- package/src/__tests__/capability-multiselect-retired.test.ts +109 -0
- package/src/__tests__/cell-truncation.test.tsx +96 -0
- package/src/__tests__/composite-group-label-e2e.test.tsx +436 -0
- package/src/__tests__/composite-group-label-readonly-e2e.test.tsx +403 -0
- package/src/__tests__/date-formatter-residue-4272.test.ts +120 -0
- package/src/__tests__/date-locale-channel.test.tsx +305 -0
- package/src/__tests__/field-carrier-sdui.test.tsx +169 -0
- package/src/__tests__/formatCurrency.centsDigit.test.tsx +158 -0
- package/src/__tests__/formatCurrency.minorUnits.test.tsx +221 -0
- package/src/__tests__/group-labelling-declaration.test.ts +148 -0
- package/src/__tests__/lookupCellRecordLink.test.tsx +171 -0
- package/src/__tests__/percent-cell-vs-measure-4576.test.ts +115 -0
- package/src/__tests__/percent-formatter-locale-4553.test.ts +147 -0
- package/src/__tests__/percent-tie-halfup-4590.test.ts +224 -0
- package/src/__tests__/select-label-association-e2e.test.tsx +199 -0
- package/src/__tests__/spec-symbol-batch7.test.ts +29 -15
- package/src/__tests__/validation-feedback.test.tsx +22 -13
- package/src/__tests__/widget-aria-invalid-e2e.test.tsx +265 -0
- package/src/__tests__/widget-aria-invalid-registry-e2e.test.tsx +338 -0
- package/src/__tests__/widget-dom-leak-e2e.test.tsx +357 -0
- package/src/__tests__/widget-props-contract.test.tsx +22 -9
- package/src/complex-widgets.test.tsx +22 -6
- package/src/currency.ts +130 -0
- package/src/datetime-widgets.test.tsx +94 -2
- package/src/field-type-alias.multiple.test.ts +81 -0
- package/src/field-type-alias.ts +58 -2
- package/src/index.css +44 -0
- package/src/index.tsx +558 -268
- package/src/standard-widgets.test.tsx +8 -1
- package/src/widgets/AddressField.postalCode.test.tsx +257 -0
- package/src/widgets/AddressField.tsx +107 -38
- package/src/widgets/AddressField.uniqueIds.test.tsx +93 -0
- package/src/widgets/AvatarField.tsx +9 -2
- package/src/widgets/BooleanField.tsx +44 -10
- package/src/widgets/CapabilityMultiSelectField.tsx +17 -5
- package/src/widgets/CharacterCount.tsx +263 -0
- package/src/widgets/CheckboxesField.tsx +66 -16
- package/src/widgets/CodeField.tsx +9 -2
- package/src/widgets/ColorField.tsx +11 -2
- package/src/widgets/CurrencyField.tsx +60 -19
- package/src/widgets/DateField.tsx +13 -4
- package/src/widgets/DateTimeField.tsx +14 -5
- package/src/widgets/EmailField.tsx +5 -5
- package/src/widgets/FileField.tsx +39 -11
- package/src/widgets/FilterConditionField.tsx +11 -0
- package/src/widgets/FormulaField.tsx +7 -2
- package/src/widgets/FullscreenFieldEditor.tsx +60 -0
- package/src/widgets/GeolocationField.tsx +49 -8
- package/src/widgets/GeolocationField.uniqueIds.test.tsx +88 -0
- package/src/widgets/GridField.test.tsx +226 -0
- package/src/widgets/GridField.tsx +115 -11
- package/src/widgets/ImageField.maxSize.test.tsx +154 -0
- package/src/widgets/ImageField.tsx +63 -6
- package/src/widgets/LocationField.tsx +9 -2
- package/src/widgets/LookupField.gateHintLabel.test.tsx +135 -0
- package/src/widgets/LookupField.hydration.test.tsx +1 -1
- package/src/widgets/LookupField.tsx +49 -10
- package/src/widgets/MasterDetailField.tsx +1 -1
- package/src/widgets/MultiSelectField.tsx +86 -16
- package/src/widgets/NumberField.tsx +3 -3
- package/src/widgets/ObjectField.tsx +17 -8
- package/src/widgets/ObjectRefField.tsx +10 -0
- package/src/widgets/OptionsEmptyState.no-provider.test.tsx +88 -0
- package/src/widgets/OptionsEmptyState.test.tsx +169 -0
- package/src/widgets/OptionsEmptyState.tsx +99 -0
- package/src/widgets/PasswordField.tsx +3 -3
- package/src/widgets/PeoplePicker.tsx +7 -1
- package/src/widgets/PercentField.tsx +5 -4
- package/src/widgets/PhoneField.tsx +5 -5
- package/src/widgets/QRCodeField.tsx +9 -2
- package/src/widgets/RadioField.tsx +58 -16
- package/src/widgets/RatingField.tsx +32 -4
- package/src/widgets/RecipientPickerField.tsx +18 -0
- package/src/widgets/RecordPickerDialog.baseFilterShapes.test.tsx +191 -0
- package/src/widgets/RecordPickerDialog.dateLocale.test.tsx +124 -0
- package/src/widgets/RecordPickerDialog.filterOptions.test.tsx +611 -0
- package/src/widgets/RecordPickerDialog.selectLabel.test.tsx +112 -0
- package/src/widgets/RecordPickerDialog.tsx +235 -21
- package/src/widgets/RichTextField.tsx +151 -24
- package/src/widgets/SelectField.tsx +84 -22
- package/src/widgets/SliderField.tsx +1 -1
- package/src/widgets/SummaryField.tsx +1 -1
- package/src/widgets/TagsField.placeholder.no-provider.test.tsx +68 -0
- package/src/widgets/TagsField.placeholder.test.tsx +95 -0
- package/src/widgets/TagsField.tsx +23 -2
- package/src/widgets/TextAreaField.tsx +171 -93
- package/src/widgets/TextField.tsx +3 -3
- package/src/widgets/TimeField.tsx +2 -2
- package/src/widgets/UrlField.tsx +5 -5
- package/src/widgets/UserField.tsx +4 -3
- package/src/widgets/VectorField.tsx +1 -1
- package/src/widgets/__tests__/FilterConditionField.operators.test.ts +25 -1
- package/src/widgets/__tests__/FullscreenFieldEditor.i18n.test.tsx +248 -0
- package/src/widgets/__tests__/FullscreenFieldEditor.no-provider.test.tsx +116 -0
- package/src/widgets/__tests__/RichTextField.fullscreenDisabled.test.tsx +244 -0
- package/src/widgets/__tests__/RichTextField.mobileFullscreen.test.tsx +195 -0
- package/src/widgets/__tests__/TextAreaField.characterCount.announcements.test.tsx +417 -0
- package/src/widgets/__tests__/TextAreaField.characterCount.i18n.test.tsx +287 -0
- package/src/widgets/__tests__/TextAreaField.characterCount.no-provider.test.tsx +160 -0
- package/src/widgets/__tests__/TextAreaField.fullscreenCharacterCount.i18n.test.tsx +161 -0
- package/src/widgets/__tests__/TextAreaField.fullscreenCharacterCount.test.tsx +346 -0
- package/src/widgets/__tests__/TextAreaField.fullscreenDisabled.test.tsx +246 -0
- package/src/widgets/__tests__/TextAreaField.mobileFullscreen.test.tsx +175 -0
- package/src/widgets/address-format.ts +120 -0
- package/src/widgets/file-size-guard.ts +55 -0
- package/src/widgets/nativeDateValue.test.ts +115 -0
- package/src/widgets/nativeDateValue.ts +112 -0
- package/src/widgets/optionWidgets.gatedOptions.test.tsx +267 -0
- package/src/widgets/optionWidgets.unconfiguredOptions.test.tsx +150 -0
- package/src/widgets/toDomProps.ts +204 -0
- package/src/widgets/toHostGroupProps.ts +102 -0
- package/src/widgets/types.ts +135 -35
- package/src/widgets/useFieldTranslation.ts +46 -4
- package/src/widgets/useRecordQuery.ts +30 -3
- package/src/withFieldCarrier.tsx +75 -0
- package/dist/FieldEditWidget.test.d.ts +0 -8
- package/dist/__tests__/DateCellRenderer.test.d.ts +0 -0
- package/dist/__tests__/NumberCellRenderer.test.d.ts +0 -0
- package/dist/__tests__/lookupCellDisplayField.test.d.ts +0 -0
- package/dist/__tests__/lookupCellDisplayName.test.d.ts +0 -0
- package/dist/__tests__/lookupCellReferenceKey.test.d.ts +0 -0
- package/dist/__tests__/registry-collision.test.d.ts +0 -0
- package/dist/__tests__/resolveFieldCurrency.test.d.ts +0 -1
- package/dist/__tests__/spec-symbol-batch7.test.d.ts +0 -8
- package/dist/__tests__/validation-feedback.test.d.ts +0 -0
- package/dist/__tests__/widget-props-contract.test.d.ts +0 -8
- package/dist/coerce-safe-value.test.d.ts +0 -1
- package/dist/complex-widgets.test.d.ts +0 -1
- package/dist/datetime-widgets.test.d.ts +0 -1
- package/dist/field-type-coverage.test.d.ts +0 -1
- package/dist/standard-widgets.test.d.ts +0 -0
- package/dist/widgets/CapabilityMultiSelectField.test.d.ts +0 -0
- package/dist/widgets/CheckboxesField.cascade.test.d.ts +0 -0
- package/dist/widgets/GridField.test.d.ts +0 -1
- package/dist/widgets/ImageLightbox.test.d.ts +0 -1
- package/dist/widgets/LookupField.dependsOn.test.d.ts +0 -8
- package/dist/widgets/LookupField.hydration.test.d.ts +0 -1
- package/dist/widgets/LookupField.idField.test.d.ts +0 -1
- package/dist/widgets/MultiSelectField.cascade.test.d.ts +0 -0
- package/dist/widgets/PeoplePicker.test.d.ts +0 -8
- package/dist/widgets/PeoplePickerComponents.test.d.ts +0 -8
- package/dist/widgets/RadioField.cascade.test.d.ts +0 -0
- package/dist/widgets/RecipientPickerField.test.d.ts +0 -0
- package/dist/widgets/SelectField.cascade.test.d.ts +0 -0
- package/dist/widgets/UserFieldPicker.test.d.ts +0 -8
- package/dist/widgets/__tests__/FilterConditionField.matchAll.test.d.ts +0 -8
- package/dist/widgets/__tests__/FilterConditionField.operators.test.d.ts +0 -8
- package/dist/widgets/deriveLookupColumns.test.d.ts +0 -1
- package/dist/widgets/file-value.test.d.ts +0 -1
- package/dist/widgets/personDisplay.test.d.ts +0 -8
- package/dist/widgets/recentLookups.test.d.ts +0 -1
- package/dist/widgets/useRecordQuery.test.d.ts +0 -8
- package/dist/widgets/useUploadingSignal.test.d.ts +0 -1
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { FieldWidgetComponentProps } from './types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*/
|
|
6
|
-
export interface AddressValue {
|
|
7
|
-
street?: string;
|
|
8
|
-
city?: string;
|
|
9
|
-
state?: string;
|
|
10
|
-
zipCode?: string;
|
|
11
|
-
country?: string;
|
|
12
|
-
}
|
|
3
|
+
import { AddressValue } from './address-format';
|
|
4
|
+
export type { AddressValue } from './address-format';
|
|
13
5
|
/**
|
|
14
6
|
* Address field widget - provides a structured address input
|
|
15
|
-
* Supports street, city, state,
|
|
7
|
+
* Supports street, city, state, postal code, and country
|
|
16
8
|
*/
|
|
17
|
-
export declare function AddressField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<AddressValue>): React.JSX.Element;
|
|
9
|
+
export declare function AddressField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<AddressValue>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* Avatar field widget - provides an avatar/profile picture uploader
|
|
5
5
|
* Supports image URLs or file uploads
|
|
6
6
|
*/
|
|
7
|
-
export declare function AvatarField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
7
|
+
export declare function AvatarField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface CharacterCountProps {
|
|
3
|
+
/**
|
|
4
|
+
* Length of the text this surface is counting. The inline surface passes the
|
|
5
|
+
* committed value's length; the fullscreen dialog passes the DRAFT's, which
|
|
6
|
+
* is the number that is true of what the user is looking at.
|
|
7
|
+
*/
|
|
8
|
+
length: number;
|
|
9
|
+
/**
|
|
10
|
+
* The declared cap. Callers render this component only when the field
|
|
11
|
+
* declares one, so it is non-optional here — a counter with no cap to count
|
|
12
|
+
* against has nothing to say and must not be mounted at all (an unconditional
|
|
13
|
+
* live region in every long-text field is the objectui#3408 defect back
|
|
14
|
+
* again).
|
|
15
|
+
*/
|
|
16
|
+
maxLength: number;
|
|
17
|
+
/**
|
|
18
|
+
* The description node's `id`, minted by the host from `useId()`.
|
|
19
|
+
*
|
|
20
|
+
* The host MUST also name it in the edited control's `aria-describedby` —
|
|
21
|
+
* this component renders the sentence, only the host knows which element is
|
|
22
|
+
* being described, and a description nothing references is a node no screen
|
|
23
|
+
* reader will ever reach. That association is asserted from the OUTSIDE (the
|
|
24
|
+
* tests resolve `aria-describedby` and concatenate the referenced nodes' text,
|
|
25
|
+
* exactly as an assistive technology does) rather than trusted here.
|
|
26
|
+
*
|
|
27
|
+
* Two surfaces of one widget therefore need two ids: the dialog's draft and
|
|
28
|
+
* the inline value diverge the moment the user types in the dialog, so one
|
|
29
|
+
* shared id would point both controls at whichever sentence rendered last.
|
|
30
|
+
*/
|
|
31
|
+
descriptionId: string;
|
|
32
|
+
/**
|
|
33
|
+
* Render node 3, the threshold-gated debounced `aria-live` status region.
|
|
34
|
+
*
|
|
35
|
+
* Required on purpose — see the component doc above. `false` removes the
|
|
36
|
+
* region from the DOM entirely (not merely empties it), which is the only
|
|
37
|
+
* form of "no live region" a test can tell apart from "a live region that
|
|
38
|
+
* happens to be silent right now".
|
|
39
|
+
*/
|
|
40
|
+
announceNearLimit: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Classes for the visible digits. Required because placement is entirely the
|
|
43
|
+
* surface's business — inline pins them to the textarea's bottom-right
|
|
44
|
+
* corner, the dialog lays them out as a footer item — and a default borrowed
|
|
45
|
+
* from either one would position the other wrongly while looking deliberate.
|
|
46
|
+
*/
|
|
47
|
+
className: string;
|
|
48
|
+
/**
|
|
49
|
+
* `data-testid` for the visible digits, namespaced per surface
|
|
50
|
+
* (`textarea-character-count`, `textarea-fullscreen-character-count`) so a
|
|
51
|
+
* test that finds digits can say WHICH surface it found them on. Same
|
|
52
|
+
* convention, same reason, as `FullscreenFieldEditor`'s `testIdPrefix`.
|
|
53
|
+
*/
|
|
54
|
+
testId: string;
|
|
55
|
+
}
|
|
56
|
+
export declare function CharacterCount({ length, maxLength, descriptionId, announceNearLimit, className, testId, }: CharacterCountProps): React.JSX.Element;
|
|
@@ -12,4 +12,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
12
12
|
* first" hint while a dependency is empty, and selections no longer offered
|
|
13
13
|
* (parent changed / predicate flipped) are pruned from the array.
|
|
14
14
|
*/
|
|
15
|
-
export declare function CheckboxesField({ value, onChange, field, readonly, className,
|
|
15
|
+
export declare function CheckboxesField({ value, onChange, field, readonly, className, dependentValues, dependsOn: dependsOnProp, emptyHint, dataSource: _dataSource, error, ...props }: FieldWidgetComponentProps<string[]>): React.JSX.Element;
|
|
@@ -5,4 +5,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
5
5
|
* Uses a simple textarea with monospace font
|
|
6
6
|
* For advanced code editing, use the @object-ui/plugin-editor component
|
|
7
7
|
*/
|
|
8
|
-
export declare function CodeField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
8
|
+
export declare function CodeField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* Color field widget - provides a color picker input
|
|
5
5
|
* Supports hex color values (e.g., #ff0000)
|
|
6
6
|
*/
|
|
7
|
-
export declare function ColorField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
7
|
+
export declare function ColorField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { FieldWidgetComponentProps } from './types';
|
|
3
|
-
export declare function CurrencyField({ value, onChange, field, readonly,
|
|
3
|
+
export declare function CurrencyField({ value, onChange, field, readonly, error, className, ...props }: FieldWidgetComponentProps<number>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
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
|
|
6
6
|
*/
|
|
7
|
-
export declare function EmailField({ value, onChange, field, readonly,
|
|
7
|
+
export declare function EmailField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -5,7 +5,7 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
5
5
|
* Supports single and multiple file uploads with configurable accepted file types.
|
|
6
6
|
* L2: File size validation, per-file progress indicators, error messages.
|
|
7
7
|
*/
|
|
8
|
-
export declare function FileField({ value, onChange, field, readonly, onUploadingChange, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
8
|
+
export declare function FileField({ value, onChange, field, readonly, onUploadingChange, error, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
9
9
|
/**
|
|
10
10
|
* FileCell — compact upload control for a line-item grid cell (objectui#2360).
|
|
11
11
|
*
|
|
@@ -32,5 +32,5 @@ export declare function kvToCondition(field: string, v: any, idx: number): Build
|
|
|
32
32
|
* @internal exported for tests
|
|
33
33
|
*/
|
|
34
34
|
export declare function isMatchAllCriteria(parsed: any): boolean;
|
|
35
|
-
export declare function FilterConditionField({ value, onChange, readonly, className, ...props }: FieldWidgetComponentProps<string | object>): React.JSX.Element;
|
|
35
|
+
export declare function FilterConditionField({ value, onChange, readonly, className, error, ...props }: FieldWidgetComponentProps<string | object>): React.JSX.Element;
|
|
36
36
|
export default FilterConditionField;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FullscreenEditorProps } from '@object-ui/components';
|
|
3
|
+
/**
|
|
4
|
+
* The fullscreen-edit affordance shared by every long-text widget in this
|
|
5
|
+
* package (`field:textarea` → `TextAreaField`, `field:markdown` / `field:html`
|
|
6
|
+
* → `RichTextField`).
|
|
7
|
+
*
|
|
8
|
+
* ## This is now a thin wrapper (objectui#3398)
|
|
9
|
+
*
|
|
10
|
+
* The affordance, the dialog, the draft/commit state machine and the
|
|
11
|
+
* `readOnly` / `disabled` semantics all live in `FullscreenEditor`
|
|
12
|
+
* (`@object-ui/components`). They used to live here AND, separately, in the
|
|
13
|
+
* form renderer's built-in `textarea` branch — one form-level promise
|
|
14
|
+
* (`ObjectFormSchema.mobile.fullscreenLongText`, projected onto every long-text
|
|
15
|
+
* field as `mobile_fullscreen`) answered twice, on the two render paths.
|
|
16
|
+
*
|
|
17
|
+
* Two copies of a state machine drift, and these did: objectui#3400 measured a
|
|
18
|
+
* read-only field editable through the built-in branch's dialog, objectui#3402
|
|
19
|
+
* measured the same hole for `disabled` here, and #3393 (label in the dialog
|
|
20
|
+
* title) and #3272 (i18n) each landed on one side before the other. The
|
|
21
|
+
* maintainer's ruling of 2026-08-10 was one implementation hoisted to the
|
|
22
|
+
* dependency-legal side — and the measured import graph allows exactly that
|
|
23
|
+
* direction: this package depends on `@object-ui/components`, which declares no
|
|
24
|
+
* dependency on `@object-ui/fields` in `dependencies` or `peerDependencies`.
|
|
25
|
+
*
|
|
26
|
+
* ## Why the wrapper survives the merge rather than being deleted
|
|
27
|
+
*
|
|
28
|
+
* It carries the one thing that is genuinely about THIS package: `readOnly` is
|
|
29
|
+
* not part of the contract here. Both hosts early-return a read-only DISPLAY
|
|
30
|
+
* before they compute the affordance (`TextAreaField.tsx`, `RichTextField.tsx`),
|
|
31
|
+
* so a `readOnly` reaching this component would be a prop with no producer on
|
|
32
|
+
* this path — the shape this package keeps deleting (objectui#3232/#3233). The
|
|
33
|
+
* `Omit` below is that statement in the type system, and it is why the hoist did
|
|
34
|
+
* not simply re-export the primitive. A future host that renders an editor for
|
|
35
|
+
* read-only fields must widen this type AND pass the prop together; the
|
|
36
|
+
* primitive already answers it (no affordance at all).
|
|
37
|
+
*
|
|
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
|
|
41
|
+
* (`textarea-`, `richtext-`), distinct from the built-in branch's
|
|
42
|
+
* `form-textarea-`, so a test can still say which render path it found.
|
|
43
|
+
*/
|
|
44
|
+
export type FullscreenFieldEditorProps = Omit<FullscreenEditorProps, 'readOnly'>;
|
|
45
|
+
export declare function FullscreenFieldEditor(props: FullscreenFieldEditorProps): React.JSX.Element;
|
|
@@ -12,4 +12,4 @@ export interface GeolocationValue {
|
|
|
12
12
|
* Geolocation field widget - provides a location picker with coordinates
|
|
13
13
|
* Supports manual entry and browser geolocation API
|
|
14
14
|
*/
|
|
15
|
-
export declare function GeolocationField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<GeolocationValue>): React.JSX.Element;
|
|
15
|
+
export declare function GeolocationField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<GeolocationValue>): React.JSX.Element;
|
|
@@ -11,7 +11,8 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
11
11
|
*
|
|
12
12
|
* Column config (a subset of `GridColumnDefinition`):
|
|
13
13
|
* { field, label?, type?, options?, width?, required?, prefix?, step? }
|
|
14
|
-
* type ∈ 'text' | 'number' | 'currency' | 'date' | '
|
|
14
|
+
* type ∈ 'text' | 'number' | 'currency' | 'date' | 'datetime' | 'time'
|
|
15
|
+
* | 'select' | 'lookup' | 'file'
|
|
15
16
|
*
|
|
16
17
|
* Field-level config (from `GridFieldMetadata`):
|
|
17
18
|
* columns, min_rows, max_rows, allow_add, allow_delete, total_field
|
|
@@ -19,7 +20,16 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
19
20
|
export interface GridColumn {
|
|
20
21
|
field: string;
|
|
21
22
|
label?: string;
|
|
22
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Cell control + read/write adapter for the column.
|
|
25
|
+
*
|
|
26
|
+
* `date` / `datetime` / `time` are three DISTINCT controls, not one
|
|
27
|
+
* (objectui#3569). Collapsing `datetime` onto the `date` control did not
|
|
28
|
+
* merely under-render it — `<input type="date">` hands back a bare
|
|
29
|
+
* `YYYY-MM-DD` on change, so touching the day of a `datetime` cell silently
|
|
30
|
+
* DELETED its time component from the record.
|
|
31
|
+
*/
|
|
32
|
+
type?: 'text' | 'number' | 'currency' | 'date' | 'datetime' | 'time' | 'select' | 'lookup' | 'file';
|
|
23
33
|
options?: Array<{
|
|
24
34
|
label: string;
|
|
25
35
|
value: string;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* ImageField - Image upload widget with preview thumbnails
|
|
5
5
|
* Supports single and multiple image uploads with drag-and-drop and preview display
|
|
6
6
|
*/
|
|
7
|
-
export declare function ImageField({ value, onChange, field, readonly, onUploadingChange, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
7
|
+
export declare function ImageField({ value, onChange, field, readonly, onUploadingChange, error, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* LocationField - Geographic coordinate input for latitude and longitude
|
|
5
5
|
* Stores location as { latitude, longitude } object and displays as comma-separated pair
|
|
6
6
|
*/
|
|
7
|
-
export declare function LocationField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
7
|
+
export declare function LocationField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
@@ -15,4 +15,4 @@ export interface LookupOption {
|
|
|
15
15
|
* from the referenced object using `DataSource.find()`.
|
|
16
16
|
* Falls back to static `options` when no DataSource is available.
|
|
17
17
|
*/
|
|
18
|
-
export declare function LookupField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
18
|
+
export declare function LookupField({ value, onChange, field, readonly, error: fieldError, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
@@ -14,4 +14,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
14
14
|
* parent first" hint while a dependency is empty, and selections no longer
|
|
15
15
|
* offered (parent changed / predicate flipped) are dropped from the array.
|
|
16
16
|
*/
|
|
17
|
-
export declare function MultiSelectField({ value, onChange, field, readonly, className,
|
|
17
|
+
export declare function MultiSelectField({ value, onChange, field, readonly, className, dependentValues, dependsOn: dependsOnProp, emptyHint, dataSource: _dataSource, error, ...props }: FieldWidgetComponentProps<string[]>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* ObjectField - JSON object editor
|
|
5
5
|
* Allows editing structured JSON data
|
|
6
6
|
*/
|
|
7
|
-
export declare function ObjectField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
7
|
+
export declare function ObjectField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<any>): React.JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { FieldWidgetComponentProps } from './types';
|
|
3
|
-
export declare function ObjectRefField({ value, onChange, readonly, className, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
3
|
+
export declare function ObjectRefField({ value, onChange, readonly, className, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
4
4
|
export default ObjectRefField;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { HostGroupProps } from './toHostGroupProps';
|
|
3
|
+
/**
|
|
4
|
+
* The "this option list cannot be filled" state shared by every fixed-option
|
|
5
|
+
* widget (`SelectField` single, `MultiSelectField`, `RadioField`,
|
|
6
|
+
* `CheckboxesField`) — objectui#3231.
|
|
7
|
+
*
|
|
8
|
+
* ## One producer, one consumer
|
|
9
|
+
*
|
|
10
|
+
* `emptyHint` is a declared prop on `FieldWidgetComponentProps`, computed by
|
|
11
|
+
* the form renderer (`form.tsx`, the `#2284` dependency gate) and forwarded to
|
|
12
|
+
* these widgets. **When the host supplies it, it wins**: the host resolves the
|
|
13
|
+
* controlling fields to their human LABELS ("Select Country first"), where a
|
|
14
|
+
* widget on its own only knows the raw metadata names ("Select country first").
|
|
15
|
+
* Absent a host hint — a standalone widget, the inline grid editor, an action
|
|
16
|
+
* param dialog — the widget falls back to its own copy.
|
|
17
|
+
*
|
|
18
|
+
* Each of the four widgets used to inline this box, destructure `emptyHint`
|
|
19
|
+
* into `_emptyHint` and throw it away, then render a hardcoded English literal.
|
|
20
|
+
* Four independent copies is precisely why they drifted together, so the box
|
|
21
|
+
* AND the copy live here only: adding a fifth option widget cannot re-introduce
|
|
22
|
+
* the gap without deliberately re-implementing it.
|
|
23
|
+
*
|
|
24
|
+
* ## Fallback copy is translated
|
|
25
|
+
*
|
|
26
|
+
* The fallback goes through `useFieldTranslation()` (`fields.options.*`,
|
|
27
|
+
* present in all ten locale packs) rather than an English string literal — the
|
|
28
|
+
* gate sentence is the SAME i18n key the form renderer uses, so the two can
|
|
29
|
+
* never say different things in the same locale.
|
|
30
|
+
*/
|
|
31
|
+
export interface OptionsEmptyStateProps {
|
|
32
|
+
/**
|
|
33
|
+
* Host-computed hint. Wins over the widget's own copy whenever it is a
|
|
34
|
+
* non-empty string — this is the whole point of the prop.
|
|
35
|
+
*/
|
|
36
|
+
emptyHint?: string;
|
|
37
|
+
/** The list is waiting on a `dependsOn` controlling field (vs. unconfigured). */
|
|
38
|
+
gated: boolean;
|
|
39
|
+
/** Controlling field names, used by the fallback gate sentence. */
|
|
40
|
+
dependsOnFields: readonly string[];
|
|
41
|
+
/** Widget-specific stable locator, e.g. `select-empty-${fieldName}`. */
|
|
42
|
+
testId?: string;
|
|
43
|
+
/** Widget-specific sizing (the dropdown is a fixed `h-9`, lists grow). */
|
|
44
|
+
className?: string;
|
|
45
|
+
/**
|
|
46
|
+
* The host label's IDREF plumbing, when this box is the whole rendered surface
|
|
47
|
+
* of a group-labelled field (objectui#3990) — a `checkboxes` / `radio` /
|
|
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.
|
|
50
|
+
*
|
|
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.
|
|
56
|
+
*/
|
|
57
|
+
hostGroupProps?: HostGroupProps;
|
|
58
|
+
}
|
|
59
|
+
export declare function OptionsEmptyState({ emptyHint, gated, dependsOnFields, testId, className, hostGroupProps, }: OptionsEmptyStateProps): React.JSX.Element;
|
|
@@ -5,4 +5,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
5
5
|
* Stores values as decimals (0-1) and displays as percentages (0-100%)
|
|
6
6
|
* Includes a slider for interactive control.
|
|
7
7
|
*/
|
|
8
|
-
export declare function PercentField({ value, onChange, field, readonly,
|
|
8
|
+
export declare function PercentField({ value, onChange, field, readonly, error, className, ...props }: FieldWidgetComponentProps<number>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
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
|
|
6
6
|
*/
|
|
7
|
-
export declare function PhoneField({ value, onChange, field, readonly,
|
|
7
|
+
export declare function PhoneField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* QR Code field widget - generates QR codes from text
|
|
5
5
|
* Uses a simple SVG-based QR code generator
|
|
6
6
|
*/
|
|
7
|
-
export declare function QRCodeField({ value, onChange, field, readonly, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
7
|
+
export declare function QRCodeField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -12,4 +12,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
12
12
|
* first" hint while a dependency is empty, and a value no longer offered (parent
|
|
13
13
|
* changed / predicate flipped) is cleared.
|
|
14
14
|
*/
|
|
15
|
-
export declare function RadioField({ value, onChange, field, readonly, className,
|
|
15
|
+
export declare function RadioField({ value, onChange, field, readonly, className, dependentValues, dependsOn: dependsOnProp, emptyHint, dataSource: _dataSource, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* Rating field widget - provides a star rating input
|
|
5
5
|
* Supports numeric values from 0 to max (default 5)
|
|
6
6
|
*/
|
|
7
|
-
export declare function RatingField({ value, onChange, field, readonly, className, ...props }: FieldWidgetComponentProps<number>): React.JSX.Element;
|
|
7
|
+
export declare function RatingField({ value, onChange, field, readonly, className, error, ...props }: FieldWidgetComponentProps<number>): React.JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { FieldWidgetComponentProps } from './types';
|
|
3
|
-
export declare function RecipientPickerField({ value, onChange, readonly, className, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
3
|
+
export declare function RecipientPickerField({ value, onChange, readonly, className, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
4
4
|
export default RecipientPickerField;
|
|
@@ -126,13 +126,39 @@ export interface RecordPickerDialogProps {
|
|
|
126
126
|
*/
|
|
127
127
|
lookupFilters?: LookupFilterDef[];
|
|
128
128
|
/**
|
|
129
|
-
* Hard filter
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
129
|
+
* Hard filter constraint applied to every query. Unlike `lookupFilters`,
|
|
130
|
+
* entries here never surface in the filter bar and cannot be overridden by
|
|
131
|
+
* user filter input.
|
|
132
|
+
*
|
|
133
|
+
* Two shapes, discriminated STRUCTURALLY (`Array.isArray`), because the two
|
|
134
|
+
* callers speak two legitimate vocabularies and neither should be bent into
|
|
135
|
+
* the other:
|
|
136
|
+
*
|
|
137
|
+
* - **`QueryParams.$filter` record form** (`{ account: 'a1' }`) — the
|
|
138
|
+
* dependent (cascading) lookup chain, where the parent field's value MUST
|
|
139
|
+
* scope the candidate set (#2215). Merged by KEY OVERWRITE, so a cascaded
|
|
140
|
+
* value REPLACES a stale `lookupFilters` entry on the same field instead of
|
|
141
|
+
* intersecting with it. That precedence is load-bearing: an `and` of both
|
|
142
|
+
* would ask for `account = 'stale' AND account = 'a1'` and return nothing.
|
|
143
|
+
* - **A spec `ViewFilterRule[]`** (`[{ field, operator, value? }]`) — an
|
|
144
|
+
* author's `record:related_list.add.picker.filter`, handed over VERBATIM
|
|
145
|
+
* (#3831). Lowered by `mergeFilterNodes`, the repo's single filter sink, so
|
|
146
|
+
* all 19 `VIEW_FILTER_OPERATORS` reach the wire — including the four
|
|
147
|
+
* (`before`, `after`, `is_empty`, `is_not_empty`) the record form has no
|
|
148
|
+
* `$op` for. No second operator vocabulary is introduced here: two already
|
|
149
|
+
* exist (the spec's `AST_OPERATOR_MAP`, data-objectstack's
|
|
150
|
+
* `FILTER_OPERATOR_ALIASES`) and #3948 is what a third costs.
|
|
151
|
+
*
|
|
152
|
+
* The discriminator is exact rather than heuristic — every AST node is an
|
|
153
|
+
* ARRAY and a rule is a plain OBJECT, the same predicate `toFilterNode` uses.
|
|
154
|
+
*
|
|
155
|
+
* Typed `unknown` rather than `Record< string, any >` on purpose: that type
|
|
156
|
+
* ACCEPTED a rule array (TypeScript lets an array satisfy a string index of
|
|
157
|
+
* `any`), the old object-spread merge then flattened it to
|
|
158
|
+
* `{"0": {...}, "1": {...}}`, and the query filtered on columns literally
|
|
159
|
+
* named `0`/`1` — type-check green, wrong query, no diagnostic anywhere.
|
|
134
160
|
*/
|
|
135
|
-
baseFilter?:
|
|
161
|
+
baseFilter?: unknown;
|
|
136
162
|
/**
|
|
137
163
|
* Cell renderer resolver function.
|
|
138
164
|
* When provided, columns with a `type` property will be rendered using the
|
|
@@ -140,6 +166,22 @@ export interface RecordPickerDialogProps {
|
|
|
140
166
|
* Typically pass `getCellRenderer` from @object-ui/fields.
|
|
141
167
|
*/
|
|
142
168
|
cellRenderer?: CellRendererResolver;
|
|
169
|
+
/**
|
|
170
|
+
* The referenced object's schema `fields` map (field name → field
|
|
171
|
+
* definition). When provided, cell renderers receive the FULL field
|
|
172
|
+
* metadata — `options`, `currency`, `scale`, `precision`, `format`,
|
|
173
|
+
* `reference_to`, … — exactly like the list view enriches its columns from
|
|
174
|
+
* the object schema. Without it a `select` column falls back to
|
|
175
|
+
* title-casing the raw stored value instead of resolving the option label
|
|
176
|
+
* (#3333: `manufacturing` rendered as "Manufacturing" instead of the
|
|
177
|
+
* authored option label).
|
|
178
|
+
*
|
|
179
|
+
* The filter bar reads the same map: a `select` filter column with no
|
|
180
|
+
* authored `options` takes them from the schema field here, so the filter
|
|
181
|
+
* panel's dropdown offers exactly the options the table cells render
|
|
182
|
+
* (#3336 — it used to open empty, leaving the field unfilterable).
|
|
183
|
+
*/
|
|
184
|
+
fieldsMeta?: Record<string, any>;
|
|
143
185
|
/**
|
|
144
186
|
* Filter bar column definitions.
|
|
145
187
|
* When provided, shows an inline filter bar below the search input.
|
|
@@ -185,4 +227,4 @@ export interface RecordPickerDialogProps {
|
|
|
185
227
|
* states, and single/multi-select. Responsive: mobile-friendly width
|
|
186
228
|
* via Tailwind breakpoints.
|
|
187
229
|
*/
|
|
188
|
-
export declare function RecordPickerDialog({ open, onOpenChange, title, multiple, dataSource, objectName, columns: columnsProp, displayField, titleFormat, idField, pageSize, value, onSelect, onSelectRecords, lookupFilters, baseFilter, cellRenderer, filterColumns, renderFilterBar, renderGrid, }: RecordPickerDialogProps): React.JSX.Element;
|
|
230
|
+
export declare function RecordPickerDialog({ open, onOpenChange, title, multiple, dataSource, objectName, columns: columnsProp, displayField, titleFormat, idField, pageSize, value, onSelect, onSelectRecords, lookupFilters, baseFilter, cellRenderer, fieldsMeta, filterColumns, renderFilterBar, renderGrid, }: RecordPickerDialogProps): React.JSX.Element;
|
|
@@ -4,5 +4,23 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* Rich text field with markdown/HTML support
|
|
5
5
|
* For now, this is a simple textarea. A full implementation would use
|
|
6
6
|
* a rich text editor like TipTap, Lexical, or Slate.
|
|
7
|
+
*
|
|
8
|
+
* Reached by forms as `field:markdown` and `field:html`; both resolve here.
|
|
9
|
+
*
|
|
10
|
+
* ## Fullscreen editing (objectui#3301)
|
|
11
|
+
*
|
|
12
|
+
* `ObjectForm` stamps `mobile_fullscreen` onto the metadata of every long-text
|
|
13
|
+
* field — textarea AND rich-text — when `ObjectFormSchema.mobile
|
|
14
|
+
* .fullscreenLongText` is set, and `ObjectFormSchema.mobile`'s own JSDoc has
|
|
15
|
+
* always promised "textarea/rich-text get an expand button". This widget never
|
|
16
|
+
* read the flag, so for `field:markdown` / `field:html` that promise did
|
|
17
|
+
* nothing at all: the producer stamped, and no consumer existed.
|
|
18
|
+
*
|
|
19
|
+
* The flag is read off `field` and nowhere else — the single metadata carrier
|
|
20
|
+
* since objectui#3233 — matching `TextAreaField` read for read, so a
|
|
21
|
+
* misspelled flag stays inert in both widgets rather than being caught by a
|
|
22
|
+
* tolerant fallback in one of them. The affordance and dialog themselves come
|
|
23
|
+
* from the shared `FullscreenFieldEditor`, so one form-level setting keeps
|
|
24
|
+
* producing one behaviour across both widgets.
|
|
7
25
|
*/
|
|
8
|
-
export declare function RichTextField({ value, onChange, field, readonly,
|
|
26
|
+
export declare function RichTextField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -5,11 +5,31 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
5
5
|
*
|
|
6
6
|
* A field declared `multiple: true` selects zero-or-more values (spec:
|
|
7
7
|
* `multiple` is valid on `select`), so it renders the multi-value chip picker
|
|
8
|
-
* — the same widget the `multiselect` type uses.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* — the same widget the `multiselect` type uses. Single-value selects keep the
|
|
9
|
+
* cascading dropdown below.
|
|
10
|
+
*
|
|
11
|
+
* The FORM no longer arrives here with `multiple` (objectui#3986):
|
|
12
|
+
* `mapFieldTypeToFormType` now resolves a `select` + `multiple: true` field to
|
|
13
|
+
* `field:multiselect`, so the object-form path renders `MultiSelectField`
|
|
14
|
+
* directly under its own registry id — which is what carries the
|
|
15
|
+
* `labelling: 'group'` declaration the host label needs. Deciding the widget at
|
|
16
|
+
* the type-resolution layer is what keeps the declaration and the render from
|
|
17
|
+
* disagreeing; a delegation invisible to the resolver could not.
|
|
18
|
+
*
|
|
19
|
+
* The branch below stays because it is NOT dead — measured entrances that reach
|
|
20
|
+
* it with `multiple` set, none of which consult that resolver:
|
|
21
|
+
*
|
|
22
|
+
* - **the inline grid editor** — `FieldEditWidget` looks `select` up in its own
|
|
23
|
+
* `EDIT_WIDGETS` table, which SHORT-CIRCUITS before the alias map is
|
|
24
|
+
* consulted, and forwards the whole metadata object as `field`;
|
|
25
|
+
* - **`ActionParamDialog`** — `paramToField` resolves through
|
|
26
|
+
* `resolveFormWidgetType`, which likewise returns `select` from
|
|
27
|
+
* `fieldWidgetMap` before reaching the alias map, and carries
|
|
28
|
+
* `multiple: param.multiple` on the field it builds;
|
|
29
|
+
* - **hand-written SDUI** — a `{ type: 'field:select' }` node whose metadata
|
|
30
|
+
* declares `multiple`, which addresses this widget by name.
|
|
31
|
+
*
|
|
32
|
+
* All three then inherit multi-select from here identically, with no drift.
|
|
13
33
|
*
|
|
14
34
|
* Both branches resolve per-option `visibleWhen` cascading / role-gating through
|
|
15
35
|
* the shared {@link useCascadingOptions} hook (#2715), so single and multi stay
|
|
@@ -5,4 +5,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
5
5
|
* comma) to add it; click a tag's × to remove it. The stored value is a
|
|
6
6
|
* string[]. Used for the `tags` field type.
|
|
7
7
|
*/
|
|
8
|
-
export declare function TagsField({ value, onChange, field, readonly, className, ...props }: FieldWidgetComponentProps<string[]>): React.JSX.Element;
|
|
8
|
+
export declare function TagsField({ value, onChange, field, readonly, className, error, ...props }: FieldWidgetComponentProps<string[]>): React.JSX.Element;
|
|
@@ -4,9 +4,48 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* TextAreaField - Multi-line text input widget
|
|
5
5
|
* Supports configurable row count and preserves whitespace in readonly mode.
|
|
6
6
|
*
|
|
7
|
-
* Mobile UX (round 3): when the
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* Mobile UX (round 3): when the FIELD METADATA carries `mobile_fullscreen:
|
|
8
|
+
* true`, an "expand" affordance opens a fullscreen edit dialog — much easier
|
|
9
|
+
* on phones than tapping a 4-row textarea trapped between other fields.
|
|
10
|
+
*
|
|
11
|
+
* That flag has exactly one producer: `ObjectForm` stamps it onto every
|
|
12
|
+
* long-text field when `ObjectFormSchema.mobile.fullscreenLongText` is set
|
|
13
|
+
* (`plugin-form/src/ObjectForm.tsx`). It reaches this widget on `field` — the
|
|
14
|
+
* single metadata carrier since objectui#3233. A `SchemaRenderer`-hosted node
|
|
15
|
+
* arrives there too: the registry adapter (`withFieldCarrier`) maps the SDUI
|
|
16
|
+
* `schema` node onto `field` before the widget sees it.
|
|
17
|
+
*
|
|
18
|
+
* The affordance, the dialog and the draft/commit semantics live in the shared
|
|
19
|
+
* `FullscreenFieldEditor` — the same producer stamps the same flag on
|
|
20
|
+
* rich-text fields, and `RichTextField` renders it from there too
|
|
21
|
+
* (objectui#3301). Only the EDITOR differs per widget; here it is a
|
|
22
|
+
* full-height `Textarea`.
|
|
23
|
+
*
|
|
24
|
+
* There is deliberately NO widget-prop override. A `mobileFullscreen`
|
|
25
|
+
* (camelCase) prop was read here and written by nobody in the repo, and the
|
|
26
|
+
* snake_case `mobile_fullscreen` prop cannot arrive either: the form renderer
|
|
27
|
+
* strips both `mobile_fullscreen` and `fullscreen` from the props it forwards
|
|
28
|
+
* to registered widgets (`stripRegisteredFieldProps` in
|
|
29
|
+
* `components/src/renderers/form/form.tsx`). Reading keys nobody produces
|
|
30
|
+
* documented a contract that never held and invited the next author to pass a
|
|
31
|
+
* silently-ignored prop, so the reads are gone (objectui#3232). If a host
|
|
32
|
+
* override is ever genuinely needed, declare ONE key on
|
|
33
|
+
* `FieldWidgetComponentProps`, stop stripping it, and have a host pass it.
|
|
34
|
+
*
|
|
35
|
+
* ## The character counter (objectui#3408, shared across surfaces in #3417)
|
|
36
|
+
*
|
|
37
|
+
* Both editing surfaces below — the inline `<Textarea>` and the fullscreen
|
|
38
|
+
* dialog's — render the SAME `CharacterCount`, which owns the three-node
|
|
39
|
+
* GOV.UK shape (decorative digits / accessible description / gated status
|
|
40
|
+
* region) and the debounce and threshold behind it. Until #3417 the fullscreen
|
|
41
|
+
* footer had its own hand-written copy that was digits and nothing else, which
|
|
42
|
+
* is what a second copy of a UI always costs: it drifts, and nothing reports
|
|
43
|
+
* the drift.
|
|
44
|
+
*
|
|
45
|
+
* This widget's remaining job is the part only it can do — mint the two
|
|
46
|
+
* description ids and name each one in the `aria-describedby` of the control
|
|
47
|
+
* it describes. The surfaces differ in exactly one behaviour, and it is
|
|
48
|
+
* declared rather than implied: `announceNearLimit`. Inline announces
|
|
49
|
+
* (unchanged since #3408); the fullscreen dialog does not.
|
|
11
50
|
*/
|
|
12
|
-
export declare function TextAreaField({ value, onChange, field, readonly,
|
|
51
|
+
export declare function TextAreaField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|
|
@@ -4,4 +4,4 @@ import { FieldWidgetComponentProps } from './types';
|
|
|
4
4
|
* UrlField - URL input with clickable link in readonly mode
|
|
5
5
|
* Validates URLs to only render http/https links for security
|
|
6
6
|
*/
|
|
7
|
-
export declare function UrlField({ value, onChange, field, readonly,
|
|
7
|
+
export declare function UrlField({ value, onChange, field, readonly, error, ...props }: FieldWidgetComponentProps<string>): React.JSX.Element;
|