@multiplatform.one/forms 7.7.4 → 7.8.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/dist/cjs/Button/index.cjs +3 -36
- package/dist/cjs/Button/index.native.js +3 -36
- package/dist/cjs/Button/index.native.js.map +1 -1
- package/dist/cjs/Chip/index.cjs +1 -1
- package/dist/cjs/Chip/index.native.js +1 -1
- package/dist/cjs/Chip/index.native.js.map +1 -1
- package/dist/cjs/ContextualSaveBar/index.cjs +17 -10
- package/dist/cjs/ContextualSaveBar/index.native.js +18 -10
- package/dist/cjs/ContextualSaveBar/index.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/index.cjs +59 -14
- package/dist/cjs/FloatingPanel/index.native.js +16 -7
- package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/nestedAction.cjs +37 -0
- package/dist/cjs/FloatingPanel/nestedAction.native.js +42 -0
- package/dist/cjs/FloatingPanel/nestedAction.native.js.map +1 -0
- package/dist/cjs/InputParts/index.cjs +11 -7
- package/dist/cjs/InputParts/index.native.js +12 -10
- package/dist/cjs/InputParts/index.native.js.map +1 -1
- package/dist/cjs/Wheel/index.cjs +3 -3
- package/dist/cjs/Wheel/index.native.js +3 -3
- package/dist/cjs/Wheel/index.native.js.map +1 -1
- package/dist/cjs/fieldLayout.cjs +3 -3
- package/dist/cjs/fieldLayout.native.js +3 -3
- package/dist/cjs/fieldLayout.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.cjs +9 -2
- package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
- package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
- package/dist/cjs/fields/Combobox/index.cjs +74 -76
- package/dist/cjs/fields/Combobox/index.native.js +78 -86
- package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/Calendar.cjs +6 -1
- package/dist/cjs/fields/DatePicker/Calendar.native.js +6 -1
- package/dist/cjs/fields/DatePicker/Calendar.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DateRangePicker.cjs +2 -2
- package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +2 -2
- package/dist/cjs/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.cjs +15 -12
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +39 -14
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/MonthPicker.cjs +10 -3
- package/dist/cjs/fields/DatePicker/MonthPicker.native.js +10 -3
- package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/MultiDatePicker.cjs +2 -2
- package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +2 -2
- package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/index.native.js +3 -0
- package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/parts.cjs +26 -14
- package/dist/cjs/fields/DatePicker/parts.native.js +28 -14
- package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/GeolocationMap.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/geocoder.cjs +63 -0
- package/dist/cjs/fields/Geolocation/geocoder.native.js +68 -0
- package/dist/cjs/fields/Geolocation/geocoder.native.js.map +1 -0
- package/dist/cjs/fields/Geolocation/index.cjs +801 -152
- package/dist/cjs/fields/Geolocation/index.native.js +856 -167
- package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/nativeSearchFocus.cjs +44 -0
- package/dist/cjs/fields/Geolocation/nativeSearchFocus.native.js +47 -0
- package/dist/cjs/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
- package/dist/cjs/fields/Icon/drawnSet.cjs +14 -3
- package/dist/cjs/fields/Icon/drawnSet.native.js +18 -3
- package/dist/cjs/fields/Icon/drawnSet.native.js.map +1 -1
- package/dist/cjs/fields/Icon/index.cjs +102 -27
- package/dist/cjs/fields/Icon/index.native.js +115 -31
- package/dist/cjs/fields/Icon/index.native.js.map +1 -1
- package/dist/cjs/fields/Input/index.cjs +5 -12
- package/dist/cjs/fields/Input/index.native.js +5 -13
- package/dist/cjs/fields/Input/index.native.js.map +1 -1
- package/dist/cjs/fields/PhoneInput/index.cjs +2 -2
- package/dist/cjs/fields/PhoneInput/index.native.js +2 -2
- package/dist/cjs/fields/PhoneInput/index.native.js.map +1 -1
- package/dist/cjs/fields/SearchInput/index.cjs +8 -9
- package/dist/cjs/fields/SearchInput/index.native.js +8 -9
- package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/index.cjs +53 -18
- package/dist/cjs/fields/Select/index.native.js +63 -37
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/Stepper/index.cjs +144 -31
- package/dist/cjs/fields/Stepper/index.native.js +151 -31
- package/dist/cjs/fields/Stepper/index.native.js.map +1 -1
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.native.js +2 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/shared/focusManagement.cjs +24 -11
- package/dist/cjs/shared/focusManagement.native.js +24 -11
- package/dist/cjs/shared/focusManagement.native.js.map +1 -1
- package/dist/cjs/shared/pickerTriggerContract.cjs +38 -0
- package/dist/cjs/shared/pickerTriggerContract.native.js +41 -0
- package/dist/cjs/shared/pickerTriggerContract.native.js.map +1 -0
- package/dist/cjs/shared/pressSlopProps.cjs +68 -0
- package/dist/cjs/shared/pressSlopProps.native.js +72 -0
- package/dist/cjs/shared/pressSlopProps.native.js.map +1 -0
- package/dist/esm/AdaptivePopup/index.native.js.map +1 -1
- package/dist/esm/Button/index.mjs +1 -34
- package/dist/esm/Button/index.mjs.map +1 -1
- package/dist/esm/Button/index.native.js +1 -34
- package/dist/esm/Button/index.native.js.map +1 -1
- package/dist/esm/Chip/index.mjs +1 -1
- package/dist/esm/Chip/index.mjs.map +1 -1
- package/dist/esm/Chip/index.native.js +1 -1
- package/dist/esm/Chip/index.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/clientKnownIdentity.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/commitImmediateField.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/index.mjs +17 -10
- package/dist/esm/ContextualSaveBar/index.mjs.map +1 -1
- package/dist/esm/ContextualSaveBar/index.native.js +18 -10
- package/dist/esm/ContextualSaveBar/index.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/useUnsavedChangesGuard.native.js.map +1 -1
- package/dist/esm/ControlGroup/index.native.js.map +1 -1
- package/dist/esm/DescriptionList/index.native.js.map +1 -1
- package/dist/esm/ErrorSummary.native.js.map +1 -1
- package/dist/esm/FieldDisplay/editMode.native.js.map +1 -1
- package/dist/esm/FieldDisplay/formatters.native.js.map +1 -1
- package/dist/esm/FieldDisplay/index.native.js.map +1 -1
- package/dist/esm/FieldGroup.native.js.map +1 -1
- package/dist/esm/FloatingPanel/index.mjs +58 -15
- package/dist/esm/FloatingPanel/index.mjs.map +1 -1
- package/dist/esm/FloatingPanel/index.native.js +15 -8
- package/dist/esm/FloatingPanel/index.native.js.map +1 -1
- package/dist/esm/FloatingPanel/nestedAction.mjs +11 -0
- package/dist/esm/FloatingPanel/nestedAction.mjs.map +1 -0
- package/dist/esm/FloatingPanel/nestedAction.native.js +13 -0
- package/dist/esm/FloatingPanel/nestedAction.native.js.map +1 -0
- package/dist/esm/FloatingPanel/useFloatingPanel.native.js.map +1 -1
- package/dist/esm/Form/index.native.js.map +1 -1
- package/dist/esm/Form/validateOn.native.js.map +1 -1
- package/dist/esm/FormGrid.native.js.map +1 -1
- package/dist/esm/FormSection.native.js.map +1 -1
- package/dist/esm/InputParts/index.mjs +12 -8
- package/dist/esm/InputParts/index.mjs.map +1 -1
- package/dist/esm/InputParts/index.native.js +13 -11
- package/dist/esm/InputParts/index.native.js.map +1 -1
- package/dist/esm/Label/index.native.js.map +1 -1
- package/dist/esm/Skeleton/index.native.js.map +1 -1
- package/dist/esm/Spinner/SpinnerGlyph.native.js.map +1 -1
- package/dist/esm/Spinner/spinnerSize.native.js.map +1 -1
- package/dist/esm/Table/index.native.js.map +1 -1
- package/dist/esm/Wheel/haptic.native.js.map +1 -1
- package/dist/esm/Wheel/index.mjs +3 -3
- package/dist/esm/Wheel/index.mjs.map +1 -1
- package/dist/esm/Wheel/index.native.js +3 -3
- package/dist/esm/Wheel/index.native.js.map +1 -1
- package/dist/esm/actionLabel.native.js.map +1 -1
- package/dist/esm/fieldDefaults.native.js.map +1 -1
- package/dist/esm/fieldLayout.mjs +3 -3
- package/dist/esm/fieldLayout.mjs.map +1 -1
- package/dist/esm/fieldLayout.native.js +3 -3
- package/dist/esm/fieldLayout.native.js.map +1 -1
- package/dist/esm/fields/Barcode/BarcodePreview.native.js.map +1 -1
- package/dist/esm/fields/Barcode/code128.native.js.map +1 -1
- package/dist/esm/fields/Barcode/index.native.js.map +1 -1
- package/dist/esm/fields/Barcode/qr.native.js.map +1 -1
- package/dist/esm/fields/Barcode/scannerTypes.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/Checkbox.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxBox.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxCard.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxFieldFrame.mjs +8 -1
- package/dist/esm/fields/Checkbox/CheckboxFieldFrame.mjs.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
- package/dist/esm/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/checkboxGroupContext.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/index.native.js.map +1 -1
- package/dist/esm/fields/ColorPicker/index.native.js.map +1 -1
- package/dist/esm/fields/ColorPicker/parts.native.js.map +1 -1
- package/dist/esm/fields/Combobox/authorOptions.native.js.map +1 -1
- package/dist/esm/fields/Combobox/index.mjs +74 -76
- package/dist/esm/fields/Combobox/index.mjs.map +1 -1
- package/dist/esm/fields/Combobox/index.native.js +78 -86
- package/dist/esm/fields/Combobox/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/Calendar.mjs +6 -1
- package/dist/esm/fields/DatePicker/Calendar.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/Calendar.native.js +6 -1
- package/dist/esm/fields/DatePicker/Calendar.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.mjs +2 -2
- package/dist/esm/fields/DatePicker/DateRangePicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js +2 -2
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs +15 -12
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.native.js +39 -14
- package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/MonthPicker.mjs +10 -3
- package/dist/esm/fields/DatePicker/MonthPicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/MonthPicker.native.js +10 -3
- package/dist/esm/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/MultiDatePicker.mjs +2 -2
- package/dist/esm/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/MultiDatePicker.native.js +2 -2
- package/dist/esm/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/catalog.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/fieldValueSync.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/index.native.js +3 -0
- package/dist/esm/fields/DatePicker/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/parts.mjs +28 -16
- package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/parts.native.js +30 -16
- package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/utils.native.js.map +1 -1
- package/dist/esm/fields/Duration/durationMath.native.js.map +1 -1
- package/dist/esm/fields/Duration/index.native.js.map +1 -1
- package/dist/esm/fields/FileUpload/filePickerTypes.native.js.map +1 -1
- package/dist/esm/fields/FileUpload/index.native.js.map +1 -1
- package/dist/esm/fields/FileUpload/nativePickerLoader.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/GeolocationMap.mjs.map +1 -1
- package/dist/esm/fields/Geolocation/GeolocationMap.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/expoMapsLoader.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/geoValue.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/geocoder.mjs +33 -0
- package/dist/esm/fields/Geolocation/geocoder.mjs.map +1 -0
- package/dist/esm/fields/Geolocation/geocoder.native.js +35 -0
- package/dist/esm/fields/Geolocation/geocoder.native.js.map +1 -0
- package/dist/esm/fields/Geolocation/index.mjs +792 -149
- package/dist/esm/fields/Geolocation/index.mjs.map +1 -1
- package/dist/esm/fields/Geolocation/index.native.js +847 -164
- package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/mapMath.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/mapTypes.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/nativeSearchFocus.mjs +19 -0
- package/dist/esm/fields/Geolocation/nativeSearchFocus.mjs.map +1 -0
- package/dist/esm/fields/Geolocation/nativeSearchFocus.native.js +19 -0
- package/dist/esm/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
- package/dist/esm/fields/Icon/drawnSet.mjs +14 -3
- package/dist/esm/fields/Icon/drawnSet.mjs.map +1 -1
- package/dist/esm/fields/Icon/drawnSet.native.js +18 -3
- package/dist/esm/fields/Icon/drawnSet.native.js.map +1 -1
- package/dist/esm/fields/Icon/index.mjs +93 -18
- package/dist/esm/fields/Icon/index.mjs.map +1 -1
- package/dist/esm/fields/Icon/index.native.js +106 -22
- package/dist/esm/fields/Icon/index.native.js.map +1 -1
- package/dist/esm/fields/ImageField/index.native.js.map +1 -1
- package/dist/esm/fields/Input/index.mjs +5 -12
- package/dist/esm/fields/Input/index.mjs.map +1 -1
- package/dist/esm/fields/Input/index.native.js +5 -13
- package/dist/esm/fields/Input/index.native.js.map +1 -1
- package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
- package/dist/esm/fields/OTPInput/index.native.js.map +1 -1
- package/dist/esm/fields/OTPInput/otpCellCss.native.js.map +1 -1
- package/dist/esm/fields/PhoneInput/dialCodes.native.js.map +1 -1
- package/dist/esm/fields/PhoneInput/index.mjs +2 -2
- package/dist/esm/fields/PhoneInput/index.mjs.map +1 -1
- package/dist/esm/fields/PhoneInput/index.native.js +2 -2
- package/dist/esm/fields/PhoneInput/index.native.js.map +1 -1
- package/dist/esm/fields/PhoneInput/phone.native.js.map +1 -1
- package/dist/esm/fields/Progress/index.native.js.map +1 -1
- package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/esm/fields/Rating/index.native.js.map +1 -1
- package/dist/esm/fields/Rating/ratingMath.native.js.map +1 -1
- package/dist/esm/fields/Rating/types.native.js.map +1 -1
- package/dist/esm/fields/SearchInput/index.mjs +9 -10
- package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
- package/dist/esm/fields/SearchInput/index.native.js +9 -10
- package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
- package/dist/esm/fields/Select/index.mjs +54 -19
- package/dist/esm/fields/Select/index.mjs.map +1 -1
- package/dist/esm/fields/Select/index.native.js +64 -38
- package/dist/esm/fields/Select/index.native.js.map +1 -1
- package/dist/esm/fields/Signature/index.native.js.map +1 -1
- package/dist/esm/fields/Slider/index.native.js.map +1 -1
- package/dist/esm/fields/Slider/jumpMotion.native.js.map +1 -1
- package/dist/esm/fields/Stepper/index.mjs +145 -32
- package/dist/esm/fields/Stepper/index.mjs.map +1 -1
- package/dist/esm/fields/Stepper/index.native.js +152 -32
- package/dist/esm/fields/Stepper/index.native.js.map +1 -1
- package/dist/esm/fields/Stepper/resolveStepperPlacement.native.js.map +1 -1
- package/dist/esm/fields/Switch/index.native.js.map +1 -1
- package/dist/esm/fields/TextArea/index.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/catalog.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/esm/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
- package/dist/esm/fields/TimeRangeScrubber/index.native.js.map +1 -1
- package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -1
- package/dist/esm/fields/nativeSelect.native.js.map +1 -1
- package/dist/esm/fields/selectedOrder.native.js.map +1 -1
- package/dist/esm/formSpacing.native.js.map +1 -1
- package/dist/esm/hooks/useFocusManagement.native.js.map +1 -1
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/requiredMarking.native.js.map +1 -1
- package/dist/esm/shared/TimeColumn.native.js.map +1 -1
- package/dist/esm/shared/capabilityPreflight.native.js.map +1 -1
- package/dist/esm/shared/colorRamps.native.js.map +1 -1
- package/dist/esm/shared/devWarn.native.js.map +1 -1
- package/dist/esm/shared/floatingList.native.js.map +1 -1
- package/dist/esm/shared/focusManagement.mjs +24 -11
- package/dist/esm/shared/focusManagement.mjs.map +1 -1
- package/dist/esm/shared/focusManagement.native.js +24 -11
- package/dist/esm/shared/focusManagement.native.js.map +1 -1
- package/dist/esm/shared/groupContext.native.js.map +1 -1
- package/dist/esm/shared/i18n.native.js.map +1 -1
- package/dist/esm/shared/pickerTriggerContract.mjs +13 -0
- package/dist/esm/shared/pickerTriggerContract.mjs.map +1 -0
- package/dist/esm/shared/pickerTriggerContract.native.js +13 -0
- package/dist/esm/shared/pickerTriggerContract.native.js.map +1 -0
- package/dist/esm/shared/pressSlopProps.mjs +43 -0
- package/dist/esm/shared/pressSlopProps.mjs.map +1 -0
- package/dist/esm/shared/pressSlopProps.native.js +44 -0
- package/dist/esm/shared/pressSlopProps.native.js.map +1 -0
- package/dist/esm/shared/t.native.js.map +1 -1
- package/dist/esm/shared/tableCellContext.native.js.map +1 -1
- package/dist/esm/shared/useDragScroll.native.js.map +1 -1
- package/dist/esm/shared/useKeyboardInset.native.js.map +1 -1
- package/dist/esm/shared/useSheetEscapeDismiss.native.js.map +1 -1
- package/dist/esm/shared/useWheelIncrement.native.js.map +1 -1
- package/dist/esm/shared/utils.native.js.map +1 -1
- package/dist/esm/shared/zIndex.native.js.map +1 -1
- package/dist/esm/themedPrimitives.native.js.map +1 -1
- package/dist/esm/types.native.js.map +1 -1
- package/dist/esm/utils/LinkCell.native.js.map +1 -1
- package/dist/jsx/Button/index.mjs +1 -34
- package/dist/jsx/Button/index.mjs.map +1 -1
- package/dist/jsx/Button/index.native.js +3 -36
- package/dist/jsx/Button/index.native.js.map +1 -1
- package/dist/jsx/Chip/index.mjs +1 -1
- package/dist/jsx/Chip/index.mjs.map +1 -1
- package/dist/jsx/Chip/index.native.js +1 -1
- package/dist/jsx/Chip/index.native.js.map +1 -1
- package/dist/jsx/ContextualSaveBar/index.mjs +17 -10
- package/dist/jsx/ContextualSaveBar/index.mjs.map +1 -1
- package/dist/jsx/ContextualSaveBar/index.native.js +18 -10
- package/dist/jsx/ContextualSaveBar/index.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/index.mjs +58 -15
- package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/index.native.js +16 -7
- package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/nestedAction.mjs +11 -0
- package/dist/jsx/FloatingPanel/nestedAction.mjs.map +1 -0
- package/dist/jsx/FloatingPanel/nestedAction.native.js +42 -0
- package/dist/jsx/FloatingPanel/nestedAction.native.js.map +1 -0
- package/dist/jsx/InputParts/index.mjs +12 -8
- package/dist/jsx/InputParts/index.mjs.map +1 -1
- package/dist/jsx/InputParts/index.native.js +12 -10
- package/dist/jsx/InputParts/index.native.js.map +1 -1
- package/dist/jsx/Wheel/index.mjs +3 -3
- package/dist/jsx/Wheel/index.mjs.map +1 -1
- package/dist/jsx/Wheel/index.native.js +3 -3
- package/dist/jsx/Wheel/index.native.js.map +1 -1
- package/dist/jsx/fieldLayout.mjs +3 -3
- package/dist/jsx/fieldLayout.mjs.map +1 -1
- package/dist/jsx/fieldLayout.native.js +3 -3
- package/dist/jsx/fieldLayout.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.mjs +8 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.mjs.map +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
- package/dist/jsx/fields/Combobox/index.mjs +74 -76
- package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
- package/dist/jsx/fields/Combobox/index.native.js +78 -86
- package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/Calendar.mjs +6 -1
- package/dist/jsx/fields/DatePicker/Calendar.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/Calendar.native.js +6 -1
- package/dist/jsx/fields/DatePicker/Calendar.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DateRangePicker.mjs +2 -2
- package/dist/jsx/fields/DatePicker/DateRangePicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/DateRangePicker.native.js +2 -2
- package/dist/jsx/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs +15 -12
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +39 -14
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/MonthPicker.mjs +10 -3
- package/dist/jsx/fields/DatePicker/MonthPicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/MonthPicker.native.js +10 -3
- package/dist/jsx/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs +2 -2
- package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js +2 -2
- package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/index.native.js +3 -0
- package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.mjs +28 -16
- package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.native.js +28 -14
- package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/GeolocationMap.mjs.map +1 -1
- package/dist/jsx/fields/Geolocation/GeolocationMap.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/geocoder.mjs +33 -0
- package/dist/jsx/fields/Geolocation/geocoder.mjs.map +1 -0
- package/dist/jsx/fields/Geolocation/geocoder.native.js +68 -0
- package/dist/jsx/fields/Geolocation/geocoder.native.js.map +1 -0
- package/dist/jsx/fields/Geolocation/index.mjs +792 -149
- package/dist/jsx/fields/Geolocation/index.mjs.map +1 -1
- package/dist/jsx/fields/Geolocation/index.native.js +856 -167
- package/dist/jsx/fields/Geolocation/index.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/nativeSearchFocus.mjs +19 -0
- package/dist/jsx/fields/Geolocation/nativeSearchFocus.mjs.map +1 -0
- package/dist/jsx/fields/Geolocation/nativeSearchFocus.native.js +47 -0
- package/dist/jsx/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
- package/dist/jsx/fields/Icon/drawnSet.mjs +14 -3
- package/dist/jsx/fields/Icon/drawnSet.mjs.map +1 -1
- package/dist/jsx/fields/Icon/drawnSet.native.js +18 -3
- package/dist/jsx/fields/Icon/drawnSet.native.js.map +1 -1
- package/dist/jsx/fields/Icon/index.mjs +93 -18
- package/dist/jsx/fields/Icon/index.mjs.map +1 -1
- package/dist/jsx/fields/Icon/index.native.js +115 -31
- package/dist/jsx/fields/Icon/index.native.js.map +1 -1
- package/dist/jsx/fields/Input/index.mjs +5 -12
- package/dist/jsx/fields/Input/index.mjs.map +1 -1
- package/dist/jsx/fields/Input/index.native.js +5 -13
- package/dist/jsx/fields/Input/index.native.js.map +1 -1
- package/dist/jsx/fields/PhoneInput/index.mjs +2 -2
- package/dist/jsx/fields/PhoneInput/index.mjs.map +1 -1
- package/dist/jsx/fields/PhoneInput/index.native.js +2 -2
- package/dist/jsx/fields/PhoneInput/index.native.js.map +1 -1
- package/dist/jsx/fields/SearchInput/index.mjs +9 -10
- package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
- package/dist/jsx/fields/SearchInput/index.native.js +8 -9
- package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/index.mjs +54 -19
- package/dist/jsx/fields/Select/index.mjs.map +1 -1
- package/dist/jsx/fields/Select/index.native.js +63 -37
- package/dist/jsx/fields/Select/index.native.js.map +1 -1
- package/dist/jsx/fields/Stepper/index.mjs +145 -32
- package/dist/jsx/fields/Stepper/index.mjs.map +1 -1
- package/dist/jsx/fields/Stepper/index.native.js +151 -31
- package/dist/jsx/fields/Stepper/index.native.js.map +1 -1
- package/dist/jsx/index.js +2 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +2 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +2 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/shared/focusManagement.mjs +24 -11
- package/dist/jsx/shared/focusManagement.mjs.map +1 -1
- package/dist/jsx/shared/focusManagement.native.js +24 -11
- package/dist/jsx/shared/focusManagement.native.js.map +1 -1
- package/dist/jsx/shared/pickerTriggerContract.mjs +13 -0
- package/dist/jsx/shared/pickerTriggerContract.mjs.map +1 -0
- package/dist/jsx/shared/pickerTriggerContract.native.js +41 -0
- package/dist/jsx/shared/pickerTriggerContract.native.js.map +1 -0
- package/dist/jsx/shared/pressSlopProps.mjs +43 -0
- package/dist/jsx/shared/pressSlopProps.mjs.map +1 -0
- package/dist/jsx/shared/pressSlopProps.native.js +72 -0
- package/dist/jsx/shared/pressSlopProps.native.js.map +1 -0
- package/package.json +8 -7
- package/src/Button/Button.labelInk.spec.tsx +21 -18
- package/src/Button/Button.outlinedChannel.spec.tsx +46 -0
- package/src/Button/Button.sizeLadder.spec.tsx +4 -3
- package/src/Button/Button.stories.tsx +20 -0
- package/src/Button/index.tsx +26 -39
- package/src/Chip/Chip.spec.tsx +3 -1
- package/src/Chip/index.tsx +1 -5
- package/src/ContextualSaveBar/ContextualSaveBar.spec.tsx +33 -0
- package/src/ContextualSaveBar/ContextualSaveBar.stories.tsx +19 -0
- package/src/ContextualSaveBar/index.tsx +12 -8
- package/src/ContextualSaveBar/nativeFlow.spec.tsx +20 -0
- package/src/FieldLayout.stories.tsx +41 -0
- package/src/FloatingPanel/FloatingPanel.native.spec.tsx +54 -0
- package/src/FloatingPanel/FloatingPanel.spec.tsx +109 -0
- package/src/FloatingPanel/index.native.tsx +24 -7
- package/src/FloatingPanel/index.tsx +80 -13
- package/src/FloatingPanel/nestedAction.spec.ts +36 -0
- package/src/FloatingPanel/nestedAction.ts +15 -0
- package/src/FloatingPanel/panelWidthContract.spec.ts +12 -15
- package/src/FormsIntegration.stories.tsx +2 -6
- package/src/InputParts/index.tsx +20 -6
- package/src/InputParts/layoutGap.spec.tsx +43 -0
- package/src/Wheel/Wheel.spec.tsx +16 -0
- package/src/Wheel/index.tsx +3 -3
- package/src/fieldLayout.spec.tsx +42 -1
- package/src/fieldLayout.tsx +9 -9
- package/src/fields/Checkbox/CheckboxFieldFrame.spec.tsx +18 -0
- package/src/fields/Checkbox/CheckboxFieldFrame.tsx +6 -1
- package/src/fields/Combobox/Combobox.spec.tsx +48 -1
- package/src/fields/Combobox/index.tsx +90 -80
- package/src/fields/DatePicker/Calendar.tsx +4 -1
- package/src/fields/DatePicker/DatePicker.stories.tsx +22 -1
- package/src/fields/DatePicker/DateRangePicker.tsx +4 -2
- package/src/fields/DatePicker/DatetimePicker.catalog.tsx +21 -19
- package/src/fields/DatePicker/DatetimePicker.native.spec.tsx +144 -0
- package/src/fields/DatePicker/DatetimePicker.native.tsx +57 -32
- package/src/fields/DatePicker/DatetimePicker.stories.tsx +22 -0
- package/src/fields/DatePicker/MonthPicker.tsx +8 -3
- package/src/fields/DatePicker/MultiDatePicker.tsx +4 -2
- package/src/fields/DatePicker/index.native.tsx +1 -0
- package/src/fields/DatePicker/parts.spec.tsx +56 -0
- package/src/fields/DatePicker/parts.tsx +33 -12
- package/src/fields/Geolocation/Geolocation.spec.tsx +287 -35
- package/src/fields/Geolocation/Geolocation.stories.tsx +141 -7
- package/src/fields/Geolocation/GeolocationMap.native.tsx +3 -0
- package/src/fields/Geolocation/GeolocationMap.tsx +4 -0
- package/src/fields/Geolocation/geocoder.spec.ts +59 -0
- package/src/fields/Geolocation/geocoder.ts +84 -0
- package/src/fields/Geolocation/geocoderSeam.spec.tsx +203 -0
- package/src/fields/Geolocation/index.tsx +912 -180
- package/src/fields/Geolocation/nativeSearchFocus.spec.ts +34 -0
- package/src/fields/Geolocation/nativeSearchFocus.ts +19 -0
- package/src/fields/Geolocation/salvage.spec.tsx +398 -0
- package/src/fields/Geolocation/storyProviders.spec.tsx +44 -0
- package/src/fields/Icon/Icon.spec.tsx +215 -1
- package/src/fields/Icon/Icon.stories.tsx +9 -1
- package/src/fields/Icon/drawnSet.tsx +39 -4
- package/src/fields/Icon/index.tsx +118 -18
- package/src/fields/Input/Input.copy.spec.tsx +1 -0
- package/src/fields/Input/Input.spec.tsx +50 -0
- package/src/fields/Input/Input.stories.tsx +1 -1
- package/src/fields/Input/index.tsx +7 -13
- package/src/fields/PhoneInput/index.tsx +2 -2
- package/src/fields/SearchInput/SearchInput.spec.tsx +14 -0
- package/src/fields/SearchInput/index.tsx +5 -6
- package/src/fields/Select/Select.spec.tsx +54 -0
- package/src/fields/Select/index.tsx +63 -33
- package/src/fields/Stepper/Stepper.spec.tsx +34 -1
- package/src/fields/Stepper/index.tsx +193 -33
- package/src/fields/pickerActivation.spec.tsx +105 -0
- package/src/fields/pickerDensity.spec.tsx +86 -0
- package/src/fields/pickerRows.spec.tsx +66 -0
- package/src/index.ts +9 -0
- package/src/shared/focusManagement.spec.tsx +68 -0
- package/src/shared/focusManagement.ts +20 -10
- package/src/shared/pickerTriggerContract.ts +13 -0
- package/src/shared/pressSlopProps.spec.ts +39 -0
- package/src/shared/pressSlopProps.ts +52 -0
- package/types/Button/index.d.ts +22 -3
- package/types/Button/index.d.ts.map +1 -1
- package/types/Chip/index.d.ts.map +1 -1
- package/types/ContextualSaveBar/index.d.ts +1 -1
- package/types/ContextualSaveBar/index.d.ts.map +1 -1
- package/types/FloatingPanel/index.d.ts +11 -1
- package/types/FloatingPanel/index.d.ts.map +1 -1
- package/types/FloatingPanel/index.native.d.ts +2 -1
- package/types/FloatingPanel/index.native.d.ts.map +1 -1
- package/types/FloatingPanel/nestedAction.d.ts +13 -0
- package/types/FloatingPanel/nestedAction.d.ts.map +1 -0
- package/types/InputParts/index.d.ts.map +1 -1
- package/types/fields/Checkbox/CheckboxFieldFrame.d.ts +46 -2
- package/types/fields/Checkbox/CheckboxFieldFrame.d.ts.map +1 -1
- package/types/fields/Checkbox/index.d.ts +3 -3
- package/types/fields/Combobox/index.d.ts +3 -1
- package/types/fields/Combobox/index.d.ts.map +1 -1
- package/types/fields/DatePicker/Calendar.d.ts.map +1 -1
- package/types/fields/DatePicker/DateRangePicker.d.ts.map +1 -1
- package/types/fields/DatePicker/DatetimePicker.catalog.d.ts.map +1 -1
- package/types/fields/DatePicker/DatetimePicker.native.d.ts.map +1 -1
- package/types/fields/DatePicker/MonthPicker.d.ts.map +1 -1
- package/types/fields/DatePicker/MultiDatePicker.d.ts.map +1 -1
- package/types/fields/DatePicker/index.native.d.ts.map +1 -1
- package/types/fields/DatePicker/parts.d.ts.map +1 -1
- package/types/fields/Geolocation/GeolocationMap.d.ts +4 -0
- package/types/fields/Geolocation/GeolocationMap.d.ts.map +1 -1
- package/types/fields/Geolocation/GeolocationMap.native.d.ts +3 -0
- package/types/fields/Geolocation/GeolocationMap.native.d.ts.map +1 -1
- package/types/fields/Geolocation/geocoder.d.ts +53 -0
- package/types/fields/Geolocation/geocoder.d.ts.map +1 -0
- package/types/fields/Geolocation/index.d.ts +18 -2
- package/types/fields/Geolocation/index.d.ts.map +1 -1
- package/types/fields/Geolocation/nativeSearchFocus.d.ts +8 -0
- package/types/fields/Geolocation/nativeSearchFocus.d.ts.map +1 -0
- package/types/fields/Icon/drawnSet.d.ts.map +1 -1
- package/types/fields/Icon/index.d.ts.map +1 -1
- package/types/fields/Input/index.d.ts.map +1 -1
- package/types/fields/PhoneInput/index.d.ts.map +1 -1
- package/types/fields/RadioGroup/index.d.ts +2 -2
- package/types/fields/SearchInput/index.d.ts.map +1 -1
- package/types/fields/Select/index.d.ts.map +1 -1
- package/types/fields/Stepper/index.d.ts.map +1 -1
- package/types/fields/ToggleGroup/index.d.ts +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/shared/focusManagement.d.ts +2 -2
- package/types/shared/focusManagement.d.ts.map +1 -1
- package/types/shared/pickerTriggerContract.d.ts +18 -0
- package/types/shared/pickerTriggerContract.d.ts.map +1 -0
- package/types/shared/pressSlopProps.d.ts +8 -0
- package/types/shared/pressSlopProps.d.ts.map +1 -0
- package/src/router.d.ts +0 -16
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ReactNode, UIEvent } from "react";
|
|
1
|
+
import type { ReactNode, RefObject, UIEvent } from "react";
|
|
2
2
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
3
3
|
import {
|
|
4
4
|
OVERLAY_ATTACH_GAP,
|
|
@@ -15,6 +15,9 @@ import { useSheetEscapeDismiss } from "../shared/useSheetEscapeDismiss";
|
|
|
15
15
|
import { useFloatingPanel, panelTransition, panelViewportPadding } from "./useFloatingPanel";
|
|
16
16
|
import type { PanelWidthMode } from "./useFloatingPanel";
|
|
17
17
|
import { zIndex } from "../shared/zIndex";
|
|
18
|
+
import { isNestedPanelAction, type PanelActionEvent } from "./nestedAction";
|
|
19
|
+
|
|
20
|
+
export { floatingPanelActionProps, isNestedPanelAction } from "./nestedAction";
|
|
18
21
|
|
|
19
22
|
// Re-export hook for Select / Combobox / external consumers
|
|
20
23
|
export {
|
|
@@ -37,6 +40,10 @@ export type {
|
|
|
37
40
|
export interface FloatingPanelProps {
|
|
38
41
|
open: boolean;
|
|
39
42
|
onOpenChange: (open: boolean) => void;
|
|
43
|
+
/** Native only: the modal is presented and its inputs can receive focus. */
|
|
44
|
+
onNativeShow?: () => void;
|
|
45
|
+
/** Suppress delayed trigger focus when a consumer handles close focus itself. Web only. */
|
|
46
|
+
skipReturnFocusRef?: RefObject<boolean>;
|
|
40
47
|
trigger: ReactNode;
|
|
41
48
|
/**
|
|
42
49
|
* Optional control rendered beside the trigger but OUTSIDE the native press
|
|
@@ -120,6 +127,11 @@ export interface FloatingPanelProps {
|
|
|
120
127
|
* the strings must live on the Pressable itself. Web ignores this.
|
|
121
128
|
*/
|
|
122
129
|
triggerA11y?: { label?: string; value?: string; hint?: string };
|
|
130
|
+
/**
|
|
131
|
+
* Stretch keeps the whole field pressable by default. Content lets an
|
|
132
|
+
* adornment trigger hug its content inside a composite field.
|
|
133
|
+
*/
|
|
134
|
+
triggerSizing?: "stretch" | "content";
|
|
123
135
|
/**
|
|
124
136
|
* How the trigger opens the panel. `"press"` (default) is click/tap.
|
|
125
137
|
* `"contextmenu"` is the ContextMenu gesture: web `contextmenu` (right-click
|
|
@@ -231,8 +243,10 @@ export function FloatingPanel(props: FloatingPanelProps) {
|
|
|
231
243
|
function FloatingPanelSheet({
|
|
232
244
|
open,
|
|
233
245
|
onOpenChange,
|
|
246
|
+
skipReturnFocusRef,
|
|
234
247
|
trigger,
|
|
235
248
|
triggerEnd,
|
|
249
|
+
triggerSizing = "stretch",
|
|
236
250
|
children,
|
|
237
251
|
scrollable,
|
|
238
252
|
disabled,
|
|
@@ -260,7 +274,7 @@ function FloatingPanelSheet({
|
|
|
260
274
|
// DG-A11Y-04 / Axiom 7: Sheet has no focus scope — move focus into the
|
|
261
275
|
// frame on open, trap Tab while open, return focus to the trigger on close.
|
|
262
276
|
const sheetFrameRef = useRef<HTMLElement | null>(null);
|
|
263
|
-
useSheetModalFocus(open, sheetFrameRef);
|
|
277
|
+
useSheetModalFocus(open, sheetFrameRef, skipReturnFocusRef);
|
|
264
278
|
useKeyboardFocusIntoPanel(open, sheetFrameRef);
|
|
265
279
|
|
|
266
280
|
const framePadding = contentPadding === "none" ? "$0" : knobProps.panelPadding.padding;
|
|
@@ -283,7 +297,10 @@ function FloatingPanelSheet({
|
|
|
283
297
|
// shut the sheet it had just opened. Nothing is lost: the sheet is modal, so
|
|
284
298
|
// its overlay covers the trigger and the toggle could only ever have run
|
|
285
299
|
// with `open === false`.
|
|
286
|
-
const openFromTrigger = () =>
|
|
300
|
+
const openFromTrigger = (event?: PanelActionEvent) => {
|
|
301
|
+
if (event && isNestedPanelAction(event)) return;
|
|
302
|
+
handleOpenChange(true);
|
|
303
|
+
};
|
|
287
304
|
const isContextMenu = openOn === "contextmenu";
|
|
288
305
|
const triggerActivation = isWeb
|
|
289
306
|
? isContextMenu
|
|
@@ -298,9 +315,13 @@ function FloatingPanelSheet({
|
|
|
298
315
|
|
|
299
316
|
return (
|
|
300
317
|
<>
|
|
301
|
-
<View
|
|
318
|
+
<View
|
|
319
|
+
flexDirection="row"
|
|
320
|
+
alignItems="center"
|
|
321
|
+
width={triggerSizing === "content" ? "auto" : "100%"}
|
|
322
|
+
>
|
|
302
323
|
<View
|
|
303
|
-
flex={1}
|
|
324
|
+
flex={triggerSizing === "content" ? undefined : 1}
|
|
304
325
|
minWidth={0}
|
|
305
326
|
{...(isContextMenu ? undefined : { onPress: openFromTrigger })}
|
|
306
327
|
cursor={disabled ? "not-allowed" : "pointer"}
|
|
@@ -361,6 +382,7 @@ function FloatingPanelSheet({
|
|
|
361
382
|
function FloatingPanelWeb({
|
|
362
383
|
open,
|
|
363
384
|
onOpenChange,
|
|
385
|
+
skipReturnFocusRef,
|
|
364
386
|
trigger,
|
|
365
387
|
children,
|
|
366
388
|
disabled,
|
|
@@ -379,6 +401,7 @@ function FloatingPanelWeb({
|
|
|
379
401
|
const growDownOnlyRef = useRef(false);
|
|
380
402
|
const lastScrollTopRef = useRef(0);
|
|
381
403
|
const keyboardOpenRef = useRef(false);
|
|
404
|
+
const contentRef = useRef<HTMLElement | null>(null);
|
|
382
405
|
|
|
383
406
|
const repositionFnRef = useRef<(() => void) | null>(null);
|
|
384
407
|
|
|
@@ -405,7 +428,7 @@ function FloatingPanelWeb({
|
|
|
405
428
|
// Escape (or outside click on empty space) closes the panel while focus is
|
|
406
429
|
// inside it, focus falls to <body>. Return it to the pre-open element
|
|
407
430
|
// (the trigger's focusable). Deliberate focus moves elsewhere are kept.
|
|
408
|
-
useReturnFocusOnClose(open);
|
|
431
|
+
useReturnFocusOnClose(open, skipReturnFocusRef);
|
|
409
432
|
useKeyboardFocusIntoPanel(open && panel.mounted, panel.refs.floating, keyboardOpenRef);
|
|
410
433
|
useEffect(() => {
|
|
411
434
|
if (!open) keyboardOpenRef.current = false;
|
|
@@ -573,6 +596,29 @@ function FloatingPanelWeb({
|
|
|
573
596
|
repositionOverlay();
|
|
574
597
|
}, [open, panel.mounted, repositionOverlay, panel.y]);
|
|
575
598
|
|
|
599
|
+
useLayoutEffect(() => {
|
|
600
|
+
const content = contentRef.current;
|
|
601
|
+
if (!open || !panel.mounted || !isFill || !content || typeof ResizeObserver === "undefined") {
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
// Matching the trigger width can rewrap content after the panel's first
|
|
605
|
+
// height measurement. Observe the content, not the clamped viewport, so a
|
|
606
|
+
// later open or result change uses its actual height without a resize loop.
|
|
607
|
+
let frame = 0;
|
|
608
|
+
const observer = new ResizeObserver(() => {
|
|
609
|
+
if (frame) cancelAnimationFrame(frame);
|
|
610
|
+
frame = requestAnimationFrame(() => {
|
|
611
|
+
frame = 0;
|
|
612
|
+
repositionOverlay();
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
observer.observe(content);
|
|
616
|
+
return () => {
|
|
617
|
+
observer.disconnect();
|
|
618
|
+
if (frame) cancelAnimationFrame(frame);
|
|
619
|
+
};
|
|
620
|
+
}, [open, panel.mounted, isFill, repositionOverlay]);
|
|
621
|
+
|
|
576
622
|
const handleScroll = useCallback(
|
|
577
623
|
(event: UIEvent) => {
|
|
578
624
|
const el = event.target as HTMLElement;
|
|
@@ -633,8 +679,8 @@ function FloatingPanelWeb({
|
|
|
633
679
|
// (`p-results/trigger-slot/detail.json`): a pointer click carries the click
|
|
634
680
|
// count, `element.click()` and native keyboard activation carry 0.
|
|
635
681
|
const openFromSynthesizedClick = useCallback(
|
|
636
|
-
(event: { detail: number }) => {
|
|
637
|
-
if (disabled || isContextMenu || event.detail !== 0) return;
|
|
682
|
+
(event: { detail: number } & PanelActionEvent) => {
|
|
683
|
+
if (disabled || isContextMenu || event.detail !== 0 || isNestedPanelAction(event)) return;
|
|
638
684
|
// detail 0 is keyboard/programmatic activation (LC-50). Count it as
|
|
639
685
|
// keyboard-origin so the first inner control rings (LC-71).
|
|
640
686
|
keyboardOpenRef.current = true;
|
|
@@ -652,14 +698,26 @@ function FloatingPanelWeb({
|
|
|
652
698
|
[disabled, onOpenChange],
|
|
653
699
|
);
|
|
654
700
|
|
|
701
|
+
const referenceProps = getReferenceProps({
|
|
702
|
+
ref: panel.setReferenceRef,
|
|
703
|
+
onClickCapture: openFromSynthesizedClick,
|
|
704
|
+
...(isContextMenu ? { onContextMenu: openFromContextMenu } : {}),
|
|
705
|
+
});
|
|
706
|
+
// Guard the composed floating-ui openers, after hook handlers are merged.
|
|
707
|
+
// Declining leaves each action's own events and focus defaults intact.
|
|
708
|
+
for (const name of ["onMouseDown", "onClick", "onKeyDown", "onKeyUp"] as const) {
|
|
709
|
+
const handler = referenceProps[name];
|
|
710
|
+
if (typeof handler === "function") {
|
|
711
|
+
referenceProps[name] = (event: PanelActionEvent) => {
|
|
712
|
+
if (!isNestedPanelAction(event)) handler(event);
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
655
717
|
return (
|
|
656
718
|
<>
|
|
657
719
|
<View
|
|
658
|
-
{...
|
|
659
|
-
ref: panel.setReferenceRef,
|
|
660
|
-
onClickCapture: openFromSynthesizedClick,
|
|
661
|
-
...(isContextMenu ? { onContextMenu: openFromContextMenu } : {}),
|
|
662
|
-
})}
|
|
720
|
+
{...referenceProps}
|
|
663
721
|
cursor={disabled ? "not-allowed" : "pointer"}
|
|
664
722
|
opacity={disabled ? 0.5 : 1}
|
|
665
723
|
// The cover contract is stated as a relation between the panel's top
|
|
@@ -693,6 +751,14 @@ function FloatingPanelWeb({
|
|
|
693
751
|
transformOrigin: panelTransformOrigin(panel.placement),
|
|
694
752
|
},
|
|
695
753
|
onScroll: handleScroll,
|
|
754
|
+
onTransitionEnd: (event) => {
|
|
755
|
+
if (
|
|
756
|
+
event.target === event.currentTarget &&
|
|
757
|
+
(event.propertyName === "height" || event.propertyName === "max-height")
|
|
758
|
+
) {
|
|
759
|
+
panel.updateArrows(event.currentTarget);
|
|
760
|
+
}
|
|
761
|
+
},
|
|
696
762
|
})}
|
|
697
763
|
data-testid="floating-panel-viewport"
|
|
698
764
|
data-fp-panel=""
|
|
@@ -714,6 +780,7 @@ function FloatingPanelWeb({
|
|
|
714
780
|
arrowScrollDirRef={panel.arrowScrollDirRef}
|
|
715
781
|
/>
|
|
716
782
|
<View
|
|
783
|
+
ref={contentRef as any}
|
|
717
784
|
{...(contentPadding !== "none" ? panel.knobProps.panelPadding : undefined)}
|
|
718
785
|
{...(contentPadding !== "none" ? panel.knobProps.gapLg : undefined)}
|
|
719
786
|
>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { isNestedPanelAction } from "./nestedAction";
|
|
3
|
+
|
|
4
|
+
describe("independent actions inside panel triggers", () => {
|
|
5
|
+
it("recognizes an SVG descendant of a marked action", () => {
|
|
6
|
+
const wrapper = document.createElement("div");
|
|
7
|
+
wrapper.innerHTML = '<button data-floating-panel-action="true"><svg><path /></svg></button>';
|
|
8
|
+
expect(
|
|
9
|
+
isNestedPanelAction({
|
|
10
|
+
nativeEvent: { target: wrapper.querySelector("path") },
|
|
11
|
+
currentTarget: wrapper,
|
|
12
|
+
}),
|
|
13
|
+
).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("does not let a marker above the wrapper suppress an ordinary opener", () => {
|
|
17
|
+
const outer = document.createElement("div");
|
|
18
|
+
outer.setAttribute("data-floating-panel-action", "true");
|
|
19
|
+
outer.innerHTML = "<div><button>Open</button></div>";
|
|
20
|
+
expect(
|
|
21
|
+
isNestedPanelAction({
|
|
22
|
+
target: outer.querySelector("button"),
|
|
23
|
+
currentTarget: outer.firstElementChild,
|
|
24
|
+
}),
|
|
25
|
+
).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("keeps unmarked buttons and non-DOM events as ordinary trigger presses", () => {
|
|
29
|
+
const wrapper = document.createElement("div");
|
|
30
|
+
wrapper.innerHTML = "<button>Open</button>";
|
|
31
|
+
expect(isNestedPanelAction({ target: wrapper.firstElementChild, currentTarget: wrapper })).toBe(
|
|
32
|
+
false,
|
|
33
|
+
);
|
|
34
|
+
expect(isNestedPanelAction({})).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const floatingPanelActionProps = { "data-floating-panel-action": "true" } as const;
|
|
2
|
+
|
|
3
|
+
export interface PanelActionEvent {
|
|
4
|
+
target?: unknown;
|
|
5
|
+
currentTarget?: unknown;
|
|
6
|
+
nativeEvent?: { target?: unknown };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Marked actions inside a trigger keep their own press and keyboard behavior. */
|
|
10
|
+
export function isNestedPanelAction(event: PanelActionEvent): boolean {
|
|
11
|
+
const target = (event.nativeEvent?.target ?? event.target) as Element | null;
|
|
12
|
+
const wrapper = event.currentTarget as Element | null;
|
|
13
|
+
const action = target?.closest?.('[data-floating-panel-action="true"]');
|
|
14
|
+
return !!action && !!wrapper?.contains?.(action);
|
|
15
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* trigger.
|
|
2
|
+
* Text listboxes match the field width; intrinsic editors size to their content.
|
|
4
3
|
*
|
|
5
4
|
* The runtime half is covered in `useFloatingPanel.spec.tsx`. This is the
|
|
6
5
|
* source half, and it exists because the defect it guards is invisible at
|
|
@@ -8,11 +7,9 @@
|
|
|
8
7
|
* DatePicker measured 262px of calendar under a 289px trigger purely because
|
|
9
8
|
* the call site said `fitContent`.
|
|
10
9
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* absurd; those are listed explicitly so the exemption is a decision rather
|
|
15
|
-
* than an oversight.
|
|
10
|
+
* Calendar grids take fit-content (MPO-262): a full-width field wrapper is
|
|
11
|
+
* unrelated to seven day columns and must not create a mostly empty popup.
|
|
12
|
+
* Text listboxes retain at-least-trigger; icon/button launchers may also hug.
|
|
16
13
|
*/
|
|
17
14
|
import { readFileSync } from "node:fs";
|
|
18
15
|
import { dirname, resolve } from "node:path";
|
|
@@ -22,13 +19,9 @@ import { describe, expect, it } from "vitest";
|
|
|
22
19
|
const fieldsDir = resolve(dirname(fileURLToPath(import.meta.url)), "..", "fields");
|
|
23
20
|
|
|
24
21
|
/** Pickers whose trigger is a form FIELD: the panel may never be narrower. */
|
|
25
|
-
const fieldShapedPickers = [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"TimePicker/catalog.tsx",
|
|
29
|
-
"ColorPicker/parts.tsx",
|
|
30
|
-
"Icon/index.tsx",
|
|
31
|
-
];
|
|
22
|
+
const fieldShapedPickers = ["TimePicker/catalog.tsx", "ColorPicker/parts.tsx", "Icon/index.tsx"];
|
|
23
|
+
|
|
24
|
+
const intrinsicGridPickers = ["DatePicker/parts.tsx", "DatePicker/DatetimePicker.catalog.tsx"];
|
|
32
25
|
|
|
33
26
|
/** Panels opened from an icon/button trigger, where fit-content is correct. */
|
|
34
27
|
const buttonShapedPickers = ["Geolocation/index.tsx"];
|
|
@@ -37,7 +30,11 @@ function read(relative: string): string {
|
|
|
37
30
|
return readFileSync(resolve(fieldsDir, relative), "utf8");
|
|
38
31
|
}
|
|
39
32
|
|
|
40
|
-
describe("FloatingPanel width contract (MPO-38)", () => {
|
|
33
|
+
describe("FloatingPanel width contract (MPO-38, MPO-262)", () => {
|
|
34
|
+
it.each(intrinsicGridPickers)("%s hugs its calendar grid", (relative) => {
|
|
35
|
+
expect(read(relative)).toContain('widthMode="fit-content"');
|
|
36
|
+
});
|
|
37
|
+
|
|
41
38
|
it.each(fieldShapedPickers)("%s declares at-least-trigger", (relative) => {
|
|
42
39
|
const source = read(relative);
|
|
43
40
|
expect(source).toContain('widthMode="at-least-trigger"');
|
|
@@ -212,9 +212,7 @@ export const multiStepRegistration: Story = {
|
|
|
212
212
|
/>
|
|
213
213
|
|
|
214
214
|
<FormActions>
|
|
215
|
-
<Button
|
|
216
|
-
Back
|
|
217
|
-
</Button>
|
|
215
|
+
<Button onPress={() => setStep("personal")}>Back</Button>
|
|
218
216
|
<Button onPress={() => setStep("verification")}>Next: Verification</Button>
|
|
219
217
|
</FormActions>
|
|
220
218
|
</FormSection>
|
|
@@ -240,9 +238,7 @@ export const multiStepRegistration: Story = {
|
|
|
240
238
|
/>
|
|
241
239
|
|
|
242
240
|
<FormActions>
|
|
243
|
-
<Button
|
|
244
|
-
Back
|
|
245
|
-
</Button>
|
|
241
|
+
<Button onPress={() => setStep("contact")}>Back</Button>
|
|
246
242
|
<form.Subscribe selector={(state) => [state.canSubmit, state.isSubmitting]}>
|
|
247
243
|
{([canSubmit, isSubmitting]) => (
|
|
248
244
|
<Button action="submit" disabled={!canSubmit || isSubmitting}>
|
package/src/InputParts/index.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getFontSized } from "@tamagui/get-font-sized";
|
|
2
2
|
import type { SizeVariantSpreadFunction } from "@tamagui/web";
|
|
3
|
-
import { useEffect, useState, type ReactNode } from "react";
|
|
3
|
+
import { useCallback, useEffect, useState, type ReactNode } from "react";
|
|
4
4
|
import type { ComponentProps, Ref, RefObject } from "react";
|
|
5
5
|
import { Pressable as RNPressable } from "react-native";
|
|
6
6
|
import type {
|
|
@@ -443,7 +443,10 @@ const InputGroupImpl = InputGroupFrame.styleable<{
|
|
|
443
443
|
// paints outside overflow:hidden, so the ring clip can stay.
|
|
444
444
|
const paintsRing = !grouped && !inTableCell;
|
|
445
445
|
const hasElevation = knobProps.elevation != null;
|
|
446
|
-
const
|
|
446
|
+
const hasWebPressSlop =
|
|
447
|
+
isWeb && (props as { "data-mp-press-slop"?: string })["data-mp-press-slop"] != null;
|
|
448
|
+
const boxOverflow: BoxOverflow =
|
|
449
|
+
paintsRing && !(hasElevation && !isWeb) && !hasWebPressSlop ? "hidden" : "visible";
|
|
447
450
|
const ringMode = boxRingMode(boxOverflow, paintsRing);
|
|
448
451
|
if (isWeb) {
|
|
449
452
|
ensureCompositeFocusRing();
|
|
@@ -536,6 +539,7 @@ const InputGroupImpl = InputGroupFrame.styleable<{
|
|
|
536
539
|
minWidth={0}
|
|
537
540
|
elevation={undefined}
|
|
538
541
|
{...props}
|
|
542
|
+
{...controlFragment}
|
|
539
543
|
{...passthroughSizeProps}
|
|
540
544
|
{...insetPadProps}
|
|
541
545
|
{...sizeRecipeEscapeOverride}
|
|
@@ -1031,6 +1035,16 @@ const InputButtonImpl = InputButton.styleable<{ glyphRing?: boolean }>((buttonPr
|
|
|
1031
1035
|
size: knobProps.controlIcon.width,
|
|
1032
1036
|
color: paint as never,
|
|
1033
1037
|
});
|
|
1038
|
+
const decorativeRef = useCallback(
|
|
1039
|
+
(node: TamaguiElement | null) => {
|
|
1040
|
+
// Tamagui 2.7.6 Button stamps tabIndex=0 after consumer props.
|
|
1041
|
+
// Correct the host at hydration; decorative caps share the field stop.
|
|
1042
|
+
if (isWeb && node && "tabIndex" in node) node.tabIndex = tabIndexProp ?? -1;
|
|
1043
|
+
if (typeof ref === "function") ref(node);
|
|
1044
|
+
else if (ref) ref.current = node;
|
|
1045
|
+
},
|
|
1046
|
+
[ref, tabIndexProp],
|
|
1047
|
+
);
|
|
1034
1048
|
|
|
1035
1049
|
if (glyphRing) {
|
|
1036
1050
|
// A real tab stop must square off the token it was HANDED, not the
|
|
@@ -1073,7 +1087,7 @@ const InputButtonImpl = InputButton.styleable<{ glyphRing?: boolean }>((buttonPr
|
|
|
1073
1087
|
const square = knobProps.control.height;
|
|
1074
1088
|
return (
|
|
1075
1089
|
<InputButton
|
|
1076
|
-
ref={
|
|
1090
|
+
ref={decorativeRef}
|
|
1077
1091
|
size={size}
|
|
1078
1092
|
height={square}
|
|
1079
1093
|
width={square}
|
|
@@ -1162,9 +1176,8 @@ export const InputContainerFrame = styled(View, {
|
|
|
1162
1176
|
|
|
1163
1177
|
variants: {
|
|
1164
1178
|
size: {
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
}),
|
|
1179
|
+
// Size is shared with the child parts; layout spacing belongs to space.
|
|
1180
|
+
"...size": () => ({}),
|
|
1168
1181
|
},
|
|
1169
1182
|
color: {
|
|
1170
1183
|
"...color": () => ({}),
|
|
@@ -1190,6 +1203,7 @@ const InputContainerImpl = InputContainerFrame.styleable((props, forwardedRef) =
|
|
|
1190
1203
|
ref={forwardedRef}
|
|
1191
1204
|
size={knobProps.sizeToken}
|
|
1192
1205
|
{...knobProps.body}
|
|
1206
|
+
{...knobProps.gap}
|
|
1193
1207
|
// LC-06/LC-10 (UX-P12): inside a table cell the field root must adopt
|
|
1194
1208
|
// the cell width — the raw web <input> carries an intrinsic width that
|
|
1195
1209
|
// otherwise floors the whole column at ~200px and lays out past the
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createRef } from "react";
|
|
2
|
+
import { Preset } from "@multiplatform.one/theme";
|
|
3
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
4
|
+
import { cleanup } from "@testing-library/react";
|
|
5
|
+
import { afterEach, expect, it } from "vitest";
|
|
6
|
+
import { Input } from "./index";
|
|
7
|
+
|
|
8
|
+
afterEach(cleanup);
|
|
9
|
+
|
|
10
|
+
function measure(size: "small" | "medium", space: "small" | "large", gap?: number) {
|
|
11
|
+
const ref = createRef<HTMLElement>();
|
|
12
|
+
const { getByTestId } = renderWithProviders(
|
|
13
|
+
<Preset overrides={{ size, space }}>
|
|
14
|
+
<Input testID="root" ref={ref as never} {...(gap === undefined ? {} : { gap })}>
|
|
15
|
+
<Input.Label>Location</Input.Label>
|
|
16
|
+
<Input.Box>
|
|
17
|
+
<Input.Area placeholder="Location" />
|
|
18
|
+
</Input.Box>
|
|
19
|
+
</Input>
|
|
20
|
+
</Preset>,
|
|
21
|
+
);
|
|
22
|
+
const root = getByTestId("root");
|
|
23
|
+
expect(ref.current).toBe(root);
|
|
24
|
+
// Happy DOM leaves token-backed CSS gaps unresolved; browser coverage reads
|
|
25
|
+
// the actual pixels. Keep this test checking the rendered gap owner.
|
|
26
|
+
const value =
|
|
27
|
+
getComputedStyle(root).gap || [...root.classList].find((name) => name.startsWith("_gap-"));
|
|
28
|
+
expect(value).toBeTruthy();
|
|
29
|
+
cleanup();
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
it("lets space change the multi-slot layout gap at a fixed control size", () => {
|
|
34
|
+
expect(measure("medium", "small")).not.toBe(measure("medium", "large"));
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("keeps the layout gap stable when only control size changes", () => {
|
|
38
|
+
expect(measure("small", "small")).toBe(measure("medium", "small"));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("preserves the consumer gap eject and forwarded root ref", () => {
|
|
42
|
+
expect(measure("medium", "large", 11)).toBe("11px");
|
|
43
|
+
});
|
package/src/Wheel/Wheel.spec.tsx
CHANGED
|
@@ -7,6 +7,22 @@ import { Wheel } from "./index";
|
|
|
7
7
|
afterEach(cleanup);
|
|
8
8
|
|
|
9
9
|
describe("Wheel contrast contract", () => {
|
|
10
|
+
it("uses the selected-text weight and keeps rounding on the selection band", () => {
|
|
11
|
+
renderWithProviders(
|
|
12
|
+
<Preset overrides={{ borderRadius: "full" }}>
|
|
13
|
+
<Wheel items={[1, 2, 3, 4, 5]} value={3} visibleItems={5} />
|
|
14
|
+
</Preset>,
|
|
15
|
+
);
|
|
16
|
+
const wheel = screen.getByTestId("wheel");
|
|
17
|
+
const selected = wheel.querySelector('[data-selected="true"]')?.firstElementChild;
|
|
18
|
+
expect(selected).toBeTruthy();
|
|
19
|
+
expect(["700", "bold"]).toContain(getComputedStyle(selected as Element).fontWeight);
|
|
20
|
+
expect(["", "0px"]).toContain(getComputedStyle(wheel).borderTopLeftRadius);
|
|
21
|
+
expect(getComputedStyle(screen.getByTestId("wheel-selection")).borderStartStartRadius).not.toBe(
|
|
22
|
+
"0px",
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
10
26
|
it("keeps inactive item text on the AA $color11 ramp (not opacity-dimmed)", () => {
|
|
11
27
|
renderWithProviders(
|
|
12
28
|
<Wheel items={[1, 2, 3, 4, 5]} value={3} onChange={() => {}} visibleItems={5} />,
|
package/src/Wheel/index.tsx
CHANGED
|
@@ -112,7 +112,7 @@ function ensureWheelFocusStyles() {
|
|
|
112
112
|
const style = document.createElement("style");
|
|
113
113
|
style.id = WHEEL_FOCUS_STYLE_ID;
|
|
114
114
|
style.textContent =
|
|
115
|
-
".mp1-wheel-wrapper:focus-visible { outline: 2px solid var(--outlineColor,
|
|
115
|
+
".mp1-wheel-wrapper:focus-visible { outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText)); outline-offset: -2px; }";
|
|
116
116
|
document.head.appendChild(style);
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -847,7 +847,7 @@ export function Wheel<T = string | number>({
|
|
|
847
847
|
<Text
|
|
848
848
|
{...knobProps.body}
|
|
849
849
|
fontSize={size}
|
|
850
|
-
fontWeight={isSelected && !disabled ? "
|
|
850
|
+
fontWeight={isSelected && !disabled ? "bold" : knobProps.textWeight.fontWeight}
|
|
851
851
|
color={itemColor(isSelected)}
|
|
852
852
|
numberOfLines={1}
|
|
853
853
|
ellipsizeMode="tail"
|
|
@@ -865,7 +865,7 @@ export function Wheel<T = string | number>({
|
|
|
865
865
|
width={flex ? "100%" : columnWidth}
|
|
866
866
|
minWidth={flex ? 0 : columnWidth}
|
|
867
867
|
flex={flex}
|
|
868
|
-
{
|
|
868
|
+
borderRadius={0}
|
|
869
869
|
data-testid="wheel"
|
|
870
870
|
data-disabled={disabled ? true : undefined}
|
|
871
871
|
aria-disabled={disabled || undefined}
|
package/src/fieldLayout.spec.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
2
2
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
3
3
|
import { Preset } from "@multiplatform.one/theme";
|
|
4
4
|
import { Input as TamaguiInput } from "tamagui";
|
|
5
|
-
import { FieldLayout } from "./fieldLayout";
|
|
5
|
+
import { FieldLayout, useFieldDescribedBy } from "./fieldLayout";
|
|
6
6
|
import { __resetDevWarnSeen } from "./shared/devWarn";
|
|
7
7
|
|
|
8
8
|
function classIncludes(container: HTMLElement, fragment: string): boolean {
|
|
@@ -188,6 +188,47 @@ describe("FieldLayout error precedence (Axiom 5 eject-last)", () => {
|
|
|
188
188
|
});
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
+
describe("FieldLayout message-before-control anatomy", () => {
|
|
192
|
+
function Control() {
|
|
193
|
+
return <input id="ordered" aria-describedby={useFieldDescribedBy()} />;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
for (const mode of ["top", "side", "compact"] as const) {
|
|
197
|
+
it(`${mode}: helper and replacement error precede the control and describe only the rendered slot`, () => {
|
|
198
|
+
const renderField = (error?: string) => (
|
|
199
|
+
<Preset overrides={{ fieldLabelPlacement: mode === "side" ? "side" : "top" }}>
|
|
200
|
+
<FieldLayout
|
|
201
|
+
id="ordered"
|
|
202
|
+
label="Email"
|
|
203
|
+
compactSpacing={mode === "compact"}
|
|
204
|
+
helperText="Use your work address"
|
|
205
|
+
error={error}
|
|
206
|
+
>
|
|
207
|
+
<Control />
|
|
208
|
+
</FieldLayout>
|
|
209
|
+
</Preset>
|
|
210
|
+
);
|
|
211
|
+
const result = renderWithProviders(renderField());
|
|
212
|
+
const assertSlot = (id: string, text: string) => {
|
|
213
|
+
const input = result.container.querySelector("input")!;
|
|
214
|
+
const message = result.container.querySelector(`#${id}`)!;
|
|
215
|
+
expect(message.textContent).toBe(text);
|
|
216
|
+
expect(
|
|
217
|
+
message.compareDocumentPosition(input) & Node.DOCUMENT_POSITION_FOLLOWING,
|
|
218
|
+
).toBeTruthy();
|
|
219
|
+
expect(input.getAttribute("aria-describedby")).toBe(id);
|
|
220
|
+
expect(
|
|
221
|
+
result.container.querySelectorAll("[id$='-description'], [id$='-error']"),
|
|
222
|
+
).toHaveLength(1);
|
|
223
|
+
};
|
|
224
|
+
assertSlot("ordered-description", "Use your work address");
|
|
225
|
+
result.rerender(renderField("Enter an email address"));
|
|
226
|
+
assertSlot("ordered-error", "Enter an email address");
|
|
227
|
+
expect(result.container.textContent).not.toContain("Use your work address");
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
191
232
|
describe("FieldLayout banned-error-word DEV warn", () => {
|
|
192
233
|
let warnSpy: ReturnType<typeof vi.spyOn>;
|
|
193
234
|
|
package/src/fieldLayout.tsx
CHANGED
|
@@ -218,13 +218,13 @@ export function FieldLayout({
|
|
|
218
218
|
...(width !== undefined ? { width } : {}),
|
|
219
219
|
};
|
|
220
220
|
|
|
221
|
-
const describedBy =
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
221
|
+
const describedBy = id
|
|
222
|
+
? errorMessage
|
|
223
|
+
? `${id}-error`
|
|
224
|
+
: helperText
|
|
225
|
+
? `${id}-description`
|
|
226
|
+
: undefined
|
|
227
|
+
: undefined;
|
|
228
228
|
|
|
229
229
|
const a11yLabel = typeof label === "string" ? `${label}${requiredSuffix}` : ariaLabel;
|
|
230
230
|
const a11yDescription = errorMessage ?? helperText;
|
|
@@ -293,9 +293,9 @@ export function FieldLayout({
|
|
|
293
293
|
|
|
294
294
|
const controlColumn = (
|
|
295
295
|
<YStack flex={sideLabel ? 1 : undefined} {...gapProps}>
|
|
296
|
-
{children}
|
|
297
296
|
{helperNode}
|
|
298
297
|
{errorNode}
|
|
298
|
+
{children}
|
|
299
299
|
</YStack>
|
|
300
300
|
);
|
|
301
301
|
|
|
@@ -330,9 +330,9 @@ export function FieldLayout({
|
|
|
330
330
|
) : (
|
|
331
331
|
<>
|
|
332
332
|
{labelNode}
|
|
333
|
-
{children}
|
|
334
333
|
{helperNode}
|
|
335
334
|
{errorNode}
|
|
335
|
+
{children}
|
|
336
336
|
</>
|
|
337
337
|
)}
|
|
338
338
|
</YStack>
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
import { cleanup } from "@testing-library/react";
|
|
12
12
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
13
13
|
import { afterEach, describe, expect, it } from "vitest";
|
|
14
|
+
import { createRef } from "react";
|
|
15
|
+
import { FieldLayout } from "../../fieldLayout";
|
|
14
16
|
import { CheckboxFieldFrame } from "./CheckboxFieldFrame";
|
|
15
17
|
|
|
16
18
|
afterEach(cleanup);
|
|
@@ -31,6 +33,22 @@ function frame(container: HTMLElement): HTMLElement {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
describe("CheckboxFieldFrame", () => {
|
|
36
|
+
it("links the rendered field message, forwards its ref, and preserves an explicit description", () => {
|
|
37
|
+
const ref = createRef<any>();
|
|
38
|
+
const fixture = (override?: { "aria-describedby": string | undefined }) => (
|
|
39
|
+
<FieldLayout id="consent" helperText="Read the terms" error="Accept the terms">
|
|
40
|
+
<CheckboxFieldFrame id="consent" checked={false} ref={ref} {...override} />
|
|
41
|
+
</FieldLayout>
|
|
42
|
+
);
|
|
43
|
+
const result = renderWithProviders(fixture());
|
|
44
|
+
expect(frame(result.container).getAttribute("aria-describedby")).toBe("consent-error");
|
|
45
|
+
expect(ref.current).toBe(frame(result.container));
|
|
46
|
+
result.rerender(fixture({ "aria-describedby": "consumer-description" }));
|
|
47
|
+
expect(frame(result.container).getAttribute("aria-describedby")).toBe("consumer-description");
|
|
48
|
+
result.rerender(fixture({ "aria-describedby": undefined }));
|
|
49
|
+
expect(frame(result.container).getAttribute("aria-describedby")).toBeNull();
|
|
50
|
+
});
|
|
51
|
+
|
|
34
52
|
it("still renders a real role=checkbox, so the styling never costs the semantics", () => {
|
|
35
53
|
const { container } = renderWithProviders(<CheckboxFieldFrame checked={false} />);
|
|
36
54
|
expect(frame(container)).toBeTruthy();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Checkbox as TamaguiCheckbox, styled } from "tamagui";
|
|
2
|
+
import { useFieldDescribedBy } from "../../fieldLayout";
|
|
2
3
|
|
|
3
4
|
/** Hit-target frame. The painted box is CheckboxGlyphBox (LC-71). */
|
|
4
|
-
|
|
5
|
+
const CheckboxFieldFrameBase = styled(TamaguiCheckbox, {
|
|
5
6
|
backgroundColor: "transparent",
|
|
6
7
|
borderColor: "transparent",
|
|
7
8
|
borderWidth: 0,
|
|
@@ -21,3 +22,7 @@ export const CheckboxFieldFrame = styled(TamaguiCheckbox, {
|
|
|
21
22
|
},
|
|
22
23
|
activeStyle: { backgroundColor: "transparent", borderColor: "transparent" },
|
|
23
24
|
});
|
|
25
|
+
|
|
26
|
+
export const CheckboxFieldFrame = CheckboxFieldFrameBase.styleable((props, ref) => (
|
|
27
|
+
<CheckboxFieldFrameBase aria-describedby={useFieldDescribedBy()} {...props} ref={ref} />
|
|
28
|
+
));
|