@multiplatform.one/forms 7.36.0 → 7.37.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/AdaptivePopup/index.native.js +1 -1
- package/dist/cjs/AdaptivePopup/index.native.js.map +1 -1
- package/dist/cjs/Button/index.native.js +1 -1
- package/dist/cjs/Button/index.native.js.map +1 -1
- package/dist/cjs/Chip/index.native.js.map +1 -1
- package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js +1 -1
- package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
- package/dist/cjs/ContextualSaveBar/clientKnownIdentity.native.js.map +1 -1
- package/dist/cjs/ContextualSaveBar/commitImmediateField.native.js.map +1 -1
- package/dist/cjs/ContextualSaveBar/index.native.js +3 -3
- package/dist/cjs/ContextualSaveBar/index.native.js.map +1 -1
- package/dist/cjs/ContextualSaveBar/useUnsavedChangesGuard.native.js.map +1 -1
- package/dist/cjs/ControlGroup/index.native.js +1 -1
- package/dist/cjs/ControlGroup/index.native.js.map +1 -1
- package/dist/cjs/DescriptionList/index.native.js +2 -2
- package/dist/cjs/DescriptionList/index.native.js.map +1 -1
- package/dist/cjs/ErrorSummary.native.js.map +1 -1
- package/dist/cjs/FieldDisplay/editMode.native.js.map +1 -1
- package/dist/cjs/FieldDisplay/formatters.native.js.map +1 -1
- package/dist/cjs/FieldDisplay/index.native.js +1 -1
- package/dist/cjs/FieldDisplay/index.native.js.map +1 -1
- package/dist/cjs/FieldGroup.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/nestedAction.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/pointAnchor.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/useFloatingPanel.native.js.map +1 -1
- package/dist/cjs/Form/index.native.js +1 -1
- package/dist/cjs/Form/index.native.js.map +1 -1
- package/dist/cjs/Form/submissionController.native.js.map +1 -1
- package/dist/cjs/Form/validateOn.native.js.map +1 -1
- package/dist/cjs/FormGrid.native.js.map +1 -1
- package/dist/cjs/FormSection.native.js.map +1 -1
- package/dist/cjs/InputParts/index.native.js.map +1 -1
- package/dist/cjs/Label/index.native.js.map +1 -1
- package/dist/cjs/MediaPicker/base64.native.js.map +1 -1
- package/dist/cjs/MediaPicker/payload.native.js.map +1 -1
- package/dist/cjs/MediaPicker/types.native.js.map +1 -1
- package/dist/cjs/MediaPicker/useMediaPicker.native.js.map +1 -1
- package/dist/cjs/Skeleton/index.native.js.map +1 -1
- package/dist/cjs/Spinner/SpinnerGlyph.native.js.map +1 -1
- package/dist/cjs/Spinner/spinnerSize.native.js.map +1 -1
- package/dist/cjs/Table/index.native.js.map +1 -1
- package/dist/cjs/Wheel/{WheelEdgeFade.cjs → NativeWheel.cjs} +5 -5
- package/dist/cjs/Wheel/NativeWheel.native.js +408 -0
- package/dist/cjs/Wheel/NativeWheel.native.js.map +1 -0
- package/dist/cjs/Wheel/haptic.cjs +3 -4
- package/dist/cjs/Wheel/haptic.native.js +4 -5
- package/dist/cjs/Wheel/haptic.native.js.map +1 -1
- package/dist/cjs/Wheel/index.cjs +62 -218
- package/dist/cjs/Wheel/index.native.js +54 -228
- package/dist/cjs/Wheel/index.native.js.map +1 -1
- package/dist/cjs/Wheel/wheelShared.cjs +156 -0
- package/dist/cjs/Wheel/wheelShared.native.js +169 -0
- package/dist/cjs/Wheel/wheelShared.native.js.map +1 -0
- package/dist/cjs/actionLabel.native.js.map +1 -1
- package/dist/cjs/fieldDefaults.native.js.map +1 -1
- package/dist/cjs/fieldLayout.native.js +1 -1
- package/dist/cjs/fieldLayout.native.js.map +1 -1
- package/dist/cjs/fields/Barcode/BarcodePreview.native.js.map +1 -1
- package/dist/cjs/fields/Barcode/BarcodeScanner.native.js +1 -1
- package/dist/cjs/fields/Barcode/code128.native.js.map +1 -1
- package/dist/cjs/fields/Barcode/index.native.js +2 -2
- package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
- package/dist/cjs/fields/Barcode/qr.native.js.map +1 -1
- package/dist/cjs/fields/Barcode/scannerTypes.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/Checkbox.native.js +1 -1
- package/dist/cjs/fields/Checkbox/Checkbox.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/CheckboxBox.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/CheckboxCard.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/CheckboxGroup.native.js +1 -1
- package/dist/cjs/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/checkboxGroupContext.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/index.native.js.map +1 -1
- package/dist/cjs/fields/ColorPicker/index.native.js +3 -3
- package/dist/cjs/fields/ColorPicker/index.native.js.map +1 -1
- package/dist/cjs/fields/ColorPicker/parts.native.js +2 -2
- package/dist/cjs/fields/ColorPicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/Combobox/authorOptions.native.js.map +1 -1
- package/dist/cjs/fields/Combobox/index.native.js +6 -6
- package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/Calendar.native.js.map +1 -1
- 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.native.js +3 -3
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +2 -2
- package/dist/cjs/fields/DatePicker/MonthPicker.native.js +2 -2
- package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
- 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/catalog.native.js +2 -2
- package/dist/cjs/fields/DatePicker/catalog.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/fieldValueSync.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/index.native.js +2 -2
- package/dist/cjs/fields/DatePicker/parts.native.js +2 -2
- package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/utils.native.js.map +1 -1
- package/dist/cjs/fields/Duration/durationMath.native.js.map +1 -1
- package/dist/cjs/fields/Duration/index.native.js +3 -3
- package/dist/cjs/fields/Duration/index.native.js.map +1 -1
- package/dist/cjs/fields/FileUpload/filePickerTypes.native.js.map +1 -1
- package/dist/cjs/fields/FileUpload/index.native.js +2 -2
- package/dist/cjs/fields/FileUpload/index.native.js.map +1 -1
- package/dist/cjs/fields/FileUpload/nativePickerLoader.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/expoMapsLoader.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/geoValue.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/geocoder.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/geocoderContext.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/index.native.js +5 -5
- package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/mapMath.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/mapTypes.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/nativeSearchFocus.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/photonGeocoder.native.js.map +1 -1
- package/dist/cjs/fields/Icon/drawnSet.native.js.map +1 -1
- package/dist/cjs/fields/Icon/index.native.js +3 -3
- package/dist/cjs/fields/Icon/index.native.js.map +1 -1
- package/dist/cjs/fields/ImageField/index.native.js +2 -2
- package/dist/cjs/fields/ImageField/index.native.js.map +1 -1
- package/dist/cjs/fields/Input/index.native.js +2 -2
- package/dist/cjs/fields/Input/index.native.js.map +1 -1
- package/dist/cjs/fields/MentionInput/index.native.js +3 -3
- package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
- package/dist/cjs/fields/OTPInput/index.native.js +3 -3
- package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
- package/dist/cjs/fields/OTPInput/otpCellCss.native.js.map +1 -1
- package/dist/cjs/fields/PhoneInput/dialCodes.native.js.map +1 -1
- package/dist/cjs/fields/PhoneInput/index.native.js +3 -3
- package/dist/cjs/fields/PhoneInput/index.native.js.map +1 -1
- package/dist/cjs/fields/PhoneInput/phone.native.js.map +1 -1
- package/dist/cjs/fields/PhoneInput/regionNames.native.js.map +1 -1
- package/dist/cjs/fields/Progress/index.native.js +1 -1
- package/dist/cjs/fields/Progress/index.native.js.map +1 -1
- package/dist/cjs/fields/RadioGroup/index.native.js +1 -1
- package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/cjs/fields/Rating/index.native.js +1 -1
- package/dist/cjs/fields/Rating/index.native.js.map +1 -1
- package/dist/cjs/fields/Rating/ratingMath.native.js.map +1 -1
- package/dist/cjs/fields/Rating/types.native.js.map +1 -1
- package/dist/cjs/fields/SearchInput/index.native.js +2 -2
- package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/index.native.js +4 -4
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/Signature/index.native.js +2 -2
- package/dist/cjs/fields/Signature/index.native.js.map +1 -1
- package/dist/cjs/fields/Slider/index.native.js +1 -1
- package/dist/cjs/fields/Slider/index.native.js.map +1 -1
- package/dist/cjs/fields/Slider/jumpMotion.native.js.map +1 -1
- package/dist/cjs/fields/Stepper/index.native.js +2 -2
- package/dist/cjs/fields/Stepper/index.native.js.map +1 -1
- package/dist/cjs/fields/Stepper/resolveStepperPlacement.native.js.map +1 -1
- package/dist/cjs/fields/Switch/footprint.native.js.map +1 -1
- package/dist/cjs/fields/Switch/index.native.js +2 -2
- package/dist/cjs/fields/Switch/index.native.js.map +1 -1
- package/dist/cjs/fields/TextArea/index.native.js +2 -2
- package/dist/cjs/fields/TextArea/index.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/catalog.native.js +3 -3
- package/dist/cjs/fields/TimePicker/catalog.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/index.native.js +2 -2
- package/dist/cjs/fields/TimePicker/parts.native.js +1 -1
- package/dist/cjs/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
- package/dist/cjs/fields/TimeRangeScrubber/index.native.js +2 -2
- package/dist/cjs/fields/TimeRangeScrubber/index.native.js.map +1 -1
- package/dist/cjs/fields/ToggleGroup/index.native.js +1 -1
- package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/cjs/fields/nativeDateTime/dateTimePickerLoader.native.js.map +1 -1
- package/dist/cjs/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -1
- package/dist/cjs/fields/nativeSelect.native.js.map +1 -1
- package/dist/cjs/fields/selectedOrder.native.js.map +1 -1
- package/dist/cjs/formSpacing.native.js.map +1 -1
- package/dist/cjs/hooks/useFocusManagement.native.js.map +1 -1
- package/dist/cjs/index.native.js +43 -43
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/requiredMarking.native.js.map +1 -1
- package/dist/cjs/shared/TimeColumn.cjs +0 -9
- package/dist/cjs/shared/TimeColumn.native.js +1 -10
- package/dist/cjs/shared/TimeColumn.native.js.map +1 -1
- package/dist/cjs/shared/capabilityPreflight.native.js.map +1 -1
- package/dist/cjs/shared/colorRamps.native.js.map +1 -1
- package/dist/cjs/shared/devWarn.native.js.map +1 -1
- package/dist/cjs/shared/floatingList.native.js +1 -1
- package/dist/cjs/shared/floatingList.native.js.map +1 -1
- package/dist/cjs/shared/focusManagement.native.js.map +1 -1
- package/dist/cjs/shared/groupContext.native.js.map +1 -1
- package/dist/cjs/shared/i18n.native.js.map +1 -1
- package/dist/cjs/shared/instantMotion.native.js.map +1 -1
- package/dist/cjs/shared/nativeA11y.native.js.map +1 -1
- package/dist/cjs/shared/panelPortal.native.js.map +1 -1
- package/dist/cjs/shared/pickerTriggerContract.native.js.map +1 -1
- package/dist/cjs/shared/pressSlopProps.native.js.map +1 -1
- package/dist/cjs/shared/t.native.js.map +1 -1
- package/dist/cjs/shared/tableCellContext.native.js.map +1 -1
- package/dist/cjs/shared/useDragScroll.native.js.map +1 -1
- package/dist/cjs/shared/useKeyboardInset.native.js.map +1 -1
- package/dist/cjs/shared/useSheetEscapeDismiss.native.js.map +1 -1
- package/dist/cjs/shared/useWheelIncrement.native.js.map +1 -1
- package/dist/cjs/shared/utils.native.js +1 -1
- package/dist/cjs/shared/utils.native.js.map +1 -1
- package/dist/cjs/shared/zIndex.native.js.map +1 -1
- package/dist/cjs/themedPrimitives.native.js.map +1 -1
- package/dist/cjs/types.native.js.map +1 -1
- package/dist/cjs/utils/LinkCell.native.js.map +1 -1
- package/dist/esm/AdaptivePopup/index.native.js.map +1 -1
- package/dist/esm/Button/index.native.js.map +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.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/nestedAction.native.js.map +1 -1
- package/dist/esm/FloatingPanel/pointAnchor.native.js.map +1 -1
- package/dist/esm/FloatingPanel/useFloatingPanel.native.js.map +1 -1
- package/dist/esm/Form/index.native.js.map +1 -1
- package/dist/esm/Form/submissionController.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.native.js.map +1 -1
- package/dist/esm/Label/index.native.js.map +1 -1
- package/dist/esm/MediaPicker/base64.native.js.map +1 -1
- package/dist/esm/MediaPicker/payload.native.js.map +1 -1
- package/dist/esm/MediaPicker/types.native.js.map +1 -1
- package/dist/esm/MediaPicker/useMediaPicker.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/NativeWheel.mjs +5 -0
- package/dist/esm/Wheel/NativeWheel.mjs.map +1 -0
- package/dist/esm/Wheel/NativeWheel.native.js +380 -0
- package/dist/esm/Wheel/NativeWheel.native.js.map +1 -0
- package/dist/esm/Wheel/haptic.mjs +3 -4
- package/dist/esm/Wheel/haptic.mjs.map +1 -1
- package/dist/esm/Wheel/haptic.native.js +4 -5
- package/dist/esm/Wheel/haptic.native.js.map +1 -1
- package/dist/esm/Wheel/index.mjs +49 -205
- package/dist/esm/Wheel/index.mjs.map +1 -1
- package/dist/esm/Wheel/index.native.js +41 -215
- package/dist/esm/Wheel/index.native.js.map +1 -1
- package/dist/esm/Wheel/wheelShared.mjs +119 -0
- package/dist/esm/Wheel/wheelShared.mjs.map +1 -0
- package/dist/esm/Wheel/wheelShared.native.js +129 -0
- package/dist/esm/Wheel/wheelShared.native.js.map +1 -0
- package/dist/esm/actionLabel.native.js.map +1 -1
- package/dist/esm/fieldDefaults.native.js.map +1 -1
- 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.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.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/Calendar.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/MonthPicker.native.js.map +1 -1
- 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/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/expoMapsLoader.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/geoValue.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/geocoder.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/geocoderContext.native.js.map +1 -1
- 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.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/photonGeocoder.native.js.map +1 -1
- package/dist/esm/fields/Icon/drawnSet.native.js.map +1 -1
- 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.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.native.js.map +1 -1
- package/dist/esm/fields/PhoneInput/phone.native.js.map +1 -1
- package/dist/esm/fields/PhoneInput/regionNames.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.native.js.map +1 -1
- 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.native.js.map +1 -1
- package/dist/esm/fields/Stepper/resolveStepperPlacement.native.js.map +1 -1
- package/dist/esm/fields/Switch/footprint.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/dateTimePickerLoader.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.native.js.map +1 -1
- package/dist/esm/requiredMarking.native.js.map +1 -1
- package/dist/esm/shared/TimeColumn.mjs +0 -9
- package/dist/esm/shared/TimeColumn.mjs.map +1 -1
- package/dist/esm/shared/TimeColumn.native.js +0 -9
- 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.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/instantMotion.native.js.map +1 -1
- package/dist/esm/shared/nativeA11y.native.js.map +1 -1
- package/dist/esm/shared/panelPortal.native.js.map +1 -1
- package/dist/esm/shared/pickerTriggerContract.native.js.map +1 -1
- package/dist/esm/shared/pressSlopProps.native.js.map +1 -1
- 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/Wheel/NativeWheel.mjs +5 -0
- package/dist/jsx/Wheel/NativeWheel.mjs.map +1 -0
- package/dist/jsx/Wheel/NativeWheel.native.js +408 -0
- package/dist/jsx/Wheel/NativeWheel.native.js.map +1 -0
- package/dist/jsx/Wheel/haptic.mjs +3 -4
- package/dist/jsx/Wheel/haptic.mjs.map +1 -1
- package/dist/jsx/Wheel/haptic.native.js +4 -5
- package/dist/jsx/Wheel/haptic.native.js.map +1 -1
- package/dist/jsx/Wheel/index.mjs +49 -205
- package/dist/jsx/Wheel/index.mjs.map +1 -1
- package/dist/jsx/Wheel/index.native.js +54 -228
- package/dist/jsx/Wheel/index.native.js.map +1 -1
- package/dist/jsx/Wheel/wheelShared.mjs +119 -0
- package/dist/jsx/Wheel/wheelShared.mjs.map +1 -0
- package/dist/jsx/Wheel/wheelShared.native.js +169 -0
- package/dist/jsx/Wheel/wheelShared.native.js.map +1 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/shared/TimeColumn.mjs +0 -9
- package/dist/jsx/shared/TimeColumn.mjs.map +1 -1
- package/dist/jsx/shared/TimeColumn.native.js +0 -9
- package/dist/jsx/shared/TimeColumn.native.js.map +1 -1
- package/package.json +8 -8
- package/src/Wheel/NativeWheel.native.spec.tsx +181 -0
- package/src/Wheel/NativeWheel.native.tsx +430 -0
- package/src/Wheel/NativeWheel.tsx +6 -0
- package/src/Wheel/haptic.ts +9 -8
- package/src/Wheel/index.tsx +121 -363
- package/src/Wheel/wheelShared.spec.ts +53 -0
- package/src/Wheel/wheelShared.ts +222 -0
- package/src/shared/TimeColumn.tsx +0 -7
- package/types/Wheel/NativeWheel.d.ts +4 -0
- package/types/Wheel/NativeWheel.d.ts.map +1 -0
- package/types/Wheel/NativeWheel.native.d.ts +9 -0
- package/types/Wheel/NativeWheel.native.d.ts.map +1 -0
- package/types/Wheel/haptic.d.ts +4 -2
- package/types/Wheel/haptic.d.ts.map +1 -1
- package/types/Wheel/index.d.ts +4 -49
- package/types/Wheel/index.d.ts.map +1 -1
- package/types/Wheel/wheelShared.d.ts +87 -0
- package/types/Wheel/wheelShared.d.ts.map +1 -0
- package/types/shared/TimeColumn.d.ts.map +1 -1
- package/dist/cjs/Wheel/WheelEdgeFade.native.js +0 -116
- package/dist/cjs/Wheel/WheelEdgeFade.native.js.map +0 -1
- package/dist/esm/Wheel/WheelEdgeFade.mjs +0 -5
- package/dist/esm/Wheel/WheelEdgeFade.mjs.map +0 -1
- package/dist/esm/Wheel/WheelEdgeFade.native.js +0 -88
- package/dist/esm/Wheel/WheelEdgeFade.native.js.map +0 -1
- package/dist/jsx/Wheel/WheelEdgeFade.mjs +0 -5
- package/dist/jsx/Wheel/WheelEdgeFade.mjs.map +0 -1
- package/dist/jsx/Wheel/WheelEdgeFade.native.js +0 -116
- package/dist/jsx/Wheel/WheelEdgeFade.native.js.map +0 -1
- package/src/Wheel/WheelEdgeFade.native.tsx +0 -67
- package/src/Wheel/WheelEdgeFade.spec.tsx +0 -141
- package/src/Wheel/WheelEdgeFade.tsx +0 -7
- package/types/Wheel/WheelEdgeFade.d.ts +0 -8
- package/types/Wheel/WheelEdgeFade.d.ts.map +0 -1
- package/types/Wheel/WheelEdgeFade.native.d.ts +0 -8
- package/types/Wheel/WheelEdgeFade.native.d.ts.map +0 -1
package/src/Wheel/index.tsx
CHANGED
|
@@ -1,63 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { CSSProperties, ReactNode } from "react";
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
3
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import type { GetProps, SizeTokens } from "tamagui";
|
|
7
|
-
import { View, getTokens, isWeb, styled, Text } from "tamagui";
|
|
3
|
+
import type { GetProps } from "tamagui";
|
|
4
|
+
import { View, isWeb, styled, Text } from "tamagui";
|
|
8
5
|
import { t } from "../shared/t";
|
|
9
6
|
import { fireSelectionHaptic } from "./haptic";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
items: (T | WheelItem<T>)[];
|
|
25
|
-
/** Currently selected value */
|
|
26
|
-
value?: T;
|
|
27
|
-
/** Called when selection changes */
|
|
28
|
-
onChange?: (value: T) => void;
|
|
29
|
-
/** Number of visible items (should be odd for center alignment) */
|
|
30
|
-
visibleItems?: 3 | 5 | 7;
|
|
31
|
-
/** Height of each item */
|
|
32
|
-
itemHeight?: number;
|
|
33
|
-
/** Column width in px. Items are absolutely positioned, so this is the painted width. */
|
|
34
|
-
width?: number;
|
|
35
|
-
/** Custom render function for items */
|
|
36
|
-
renderItem?: (item: T, index: number, isSelected: boolean) => ReactNode;
|
|
37
|
-
/** Whether the wheel is disabled */
|
|
38
|
-
disabled?: boolean;
|
|
39
|
-
/** Size token for text */
|
|
40
|
-
size?: SizeTokens;
|
|
41
|
-
/**
|
|
42
|
-
* When true (and there are at least 2 items), scrolling wraps at the ends
|
|
43
|
-
* instead of rubber-banding. Uses virtual rows with modulo item indexing.
|
|
44
|
-
*/
|
|
45
|
-
loop?: boolean;
|
|
46
|
-
/**
|
|
47
|
-
* How the iOS selection fill rounds and insets. `"all"` is a standalone
|
|
48
|
-
* column; `"start"` / `"end"` / `"none"` join adjacent columns into one band.
|
|
49
|
-
*/
|
|
50
|
-
highlightEdges?: WheelHighlightEdges;
|
|
51
|
-
/** Stretch inside a row of columns (time picker). */
|
|
52
|
-
flex?: number;
|
|
53
|
-
/**
|
|
54
|
-
* Fires once each time a different item crosses the centre band (drag,
|
|
55
|
-
* flick, or snap). Native wires this to a selection haptic.
|
|
56
|
-
*/
|
|
57
|
-
onItemCross?: (value: T, index: number) => void;
|
|
58
|
-
/** Accessible name for the picker (web renders role="slider"). */
|
|
59
|
-
"aria-label"?: string;
|
|
60
|
-
}
|
|
7
|
+
import { NativeWheel } from "./NativeWheel";
|
|
8
|
+
import {
|
|
9
|
+
defaultColumnWidth,
|
|
10
|
+
drumPose,
|
|
11
|
+
drumReachRows,
|
|
12
|
+
getItemLabel,
|
|
13
|
+
getItemValue,
|
|
14
|
+
modIndex,
|
|
15
|
+
nearestRowForDataIndex,
|
|
16
|
+
useWheelLayout,
|
|
17
|
+
type WheelProps,
|
|
18
|
+
} from "./wheelShared";
|
|
19
|
+
|
|
20
|
+
export type { WheelHighlightEdges, WheelItem, WheelProps } from "./wheelShared";
|
|
61
21
|
|
|
62
22
|
// ── iOS Physics Constants ─────────────────────────────────────
|
|
63
23
|
// Based on Apple's UIScrollView deceleration behavior
|
|
@@ -74,22 +34,6 @@ type WheelPointer = {
|
|
|
74
34
|
locationY?: number;
|
|
75
35
|
};
|
|
76
36
|
|
|
77
|
-
/**
|
|
78
|
-
* Flutter CupertinoPicker / UIPickerView cylinder. diameterRatio 1.07 and
|
|
79
|
-
* squeeze 1.45 are the Cupertino defaults — a shallow drum, not a 70° fan.
|
|
80
|
-
*/
|
|
81
|
-
const diameterRatio = 1.07;
|
|
82
|
-
const squeeze = 1.45;
|
|
83
|
-
const perspectivePx = 400;
|
|
84
|
-
const defaultColumnWidth = 88;
|
|
85
|
-
|
|
86
|
-
/** Type scale for wheel numerals — iOS UIPickerView is ~21pt at default size. */
|
|
87
|
-
const wheelFontByStep: Record<-1 | 0 | 1, SizeTokens> = {
|
|
88
|
-
[-1]: "$6",
|
|
89
|
-
0: "$8",
|
|
90
|
-
1: "$9",
|
|
91
|
-
};
|
|
92
|
-
|
|
93
37
|
// The interactive wrapper is a raw <div>, so the non-removable focus-visible
|
|
94
38
|
// ring (W12 / DG-A11Y-01 / LC-71: 2px solid $outlineColor) has to come from
|
|
95
39
|
// an injected stylesheet — inline styles cannot express :focus-visible.
|
|
@@ -143,29 +87,6 @@ const SelectionIndicator = styled(View, {
|
|
|
143
87
|
|
|
144
88
|
// ── Helper functions ──────────────────────────────────────────
|
|
145
89
|
|
|
146
|
-
function normalizeItem<T>(item: T | WheelItem<T>): WheelItem<T> {
|
|
147
|
-
if (typeof item === "object" && item !== null && "value" in item) {
|
|
148
|
-
return item as WheelItem<T>;
|
|
149
|
-
}
|
|
150
|
-
return { value: item as T, label: String(item) };
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function getItemLabel<T>(item: T | WheelItem<T>): string {
|
|
154
|
-
const normalized = normalizeItem(item);
|
|
155
|
-
return normalized.label ?? String(normalized.value);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function getItemValue<T>(item: T | WheelItem<T>): T {
|
|
159
|
-
const normalized = normalizeItem(item);
|
|
160
|
-
return normalized.value;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** Non-negative modulo (JavaScript % can be negative for negative lhs). */
|
|
164
|
-
function modIndex(row: number, n: number): number {
|
|
165
|
-
if (n <= 0) return 0;
|
|
166
|
-
return ((row % n) + n) % n;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
90
|
/**
|
|
170
91
|
* Scroll offset that shows the same item as `targetOffset` (same row mod n), chosen so its
|
|
171
92
|
* value is closest to `referenceOffset` — shortest motion when animating from `referenceOffset`.
|
|
@@ -185,15 +106,6 @@ function equivalentOffsetNear(
|
|
|
185
106
|
return base + k * span;
|
|
186
107
|
}
|
|
187
108
|
|
|
188
|
-
/** Shortest steps on the item circle from current row to target data index. */
|
|
189
|
-
function nearestRowForDataIndex(currentRow: number, targetDataIndex: number, n: number): number {
|
|
190
|
-
const currentMod = modIndex(currentRow, n);
|
|
191
|
-
let delta = targetDataIndex - currentMod;
|
|
192
|
-
if (delta > n / 2) delta -= n;
|
|
193
|
-
if (delta < -n / 2) delta += n;
|
|
194
|
-
return currentRow + delta;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
109
|
// Rubber-band effect for over-scrolling (iOS style)
|
|
198
110
|
function rubberBand(offset: number, dimension: number): number {
|
|
199
111
|
const c = rubberBandConstant;
|
|
@@ -203,9 +115,9 @@ function rubberBand(offset: number, dimension: number): number {
|
|
|
203
115
|
}
|
|
204
116
|
|
|
205
117
|
/**
|
|
206
|
-
* Project a row onto the
|
|
207
|
-
*
|
|
208
|
-
*
|
|
118
|
+
* Project a row onto the UIPickerView drum (wheelShared drumPose). Row opacity
|
|
119
|
+
* stays 1 on web: the viewport mask fades the edges, so row text keeps the AA
|
|
120
|
+
* $color11 ramp.
|
|
209
121
|
*/
|
|
210
122
|
function getItemTransform(
|
|
211
123
|
index: number,
|
|
@@ -213,78 +125,39 @@ function getItemTransform(
|
|
|
213
125
|
itemHeight: number,
|
|
214
126
|
containerHeight: number,
|
|
215
127
|
): { translateY: number; rotateX: number; scale: number; opacity: number } {
|
|
216
|
-
const
|
|
217
|
-
const angle = (index * itemHeight - scrollOffset) / squeeze / Math.max(radius, 1);
|
|
218
|
-
const clamped = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, angle));
|
|
219
|
-
const centerTop = (containerHeight - itemHeight) / 2;
|
|
220
|
-
const translateY = centerTop + radius * Math.sin(clamped);
|
|
221
|
-
const rotateX = -(clamped * 180) / Math.PI;
|
|
222
|
-
const scale = Math.max(0.72, Math.min(1, Math.cos(clamped)));
|
|
128
|
+
const pose = drumPose(index - scrollOffset / itemHeight, itemHeight, containerHeight);
|
|
223
129
|
return {
|
|
224
|
-
translateY,
|
|
225
|
-
rotateX,
|
|
226
|
-
scale,
|
|
130
|
+
translateY: (containerHeight - itemHeight) / 2 + pose.offset,
|
|
131
|
+
rotateX: pose.rotateX,
|
|
132
|
+
scale: pose.scale,
|
|
227
133
|
opacity: 1,
|
|
228
134
|
};
|
|
229
135
|
}
|
|
230
136
|
|
|
231
|
-
|
|
232
|
-
if (typeof token === "number") return token;
|
|
233
|
-
const key = String(token).replace(/^\$/, "");
|
|
234
|
-
const val = (getTokens() as { [k: string]: Record<string, { val?: number }> })[scale]?.[key]?.val;
|
|
235
|
-
if (typeof val === "number") return val;
|
|
236
|
-
return scale === "radius" ? 9 : 8;
|
|
237
|
-
}
|
|
137
|
+
// ── Wheel Component ───────────────────────────────────────────
|
|
238
138
|
|
|
239
|
-
function
|
|
240
|
-
|
|
241
|
-
radiusToken: string | number,
|
|
242
|
-
pointy: boolean,
|
|
243
|
-
): CSSProperties {
|
|
244
|
-
const r = pointy ? 0 : tokenPx(radiusToken, "radius");
|
|
245
|
-
const inset = tokenPx("$2", "space");
|
|
246
|
-
const capStart = edges === "all" || edges === "start";
|
|
247
|
-
const capEnd = edges === "all" || edges === "end";
|
|
248
|
-
return {
|
|
249
|
-
borderStartStartRadius: capStart ? r : 0,
|
|
250
|
-
borderStartEndRadius: capEnd ? r : 0,
|
|
251
|
-
borderEndStartRadius: capStart ? r : 0,
|
|
252
|
-
borderEndEndRadius: capEnd ? r : 0,
|
|
253
|
-
marginInlineStart: capStart ? inset : 0,
|
|
254
|
-
marginInlineEnd: capEnd ? inset : 0,
|
|
255
|
-
};
|
|
139
|
+
export function Wheel<T = string | number>(props: WheelProps<T>) {
|
|
140
|
+
return isWeb ? <WebWheel {...props} /> : <NativeWheel {...props} />;
|
|
256
141
|
}
|
|
257
142
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
"aria-label": ariaLabel,
|
|
275
|
-
}: WheelProps<T>) {
|
|
276
|
-
const { knobProps } = useResolvedKnobs();
|
|
277
|
-
const size = sizeProp ?? wheelFontByStep[sizeTokenStep(knobProps.sizeToken)];
|
|
278
|
-
// Row geometry rides nestedControl (density-aware, 32px at medium — iOS
|
|
279
|
-
// UIPickerView item extent). Explicit itemHeight ejects.
|
|
280
|
-
const itemHeight = itemHeightProp ?? knobProps.nestedControl.px ?? 32;
|
|
143
|
+
function WebWheel<T = string | number>(props: WheelProps<T>) {
|
|
144
|
+
const {
|
|
145
|
+
items,
|
|
146
|
+
value,
|
|
147
|
+
onChange,
|
|
148
|
+
visibleItems = 5,
|
|
149
|
+
width: widthProp,
|
|
150
|
+
renderItem,
|
|
151
|
+
disabled = false,
|
|
152
|
+
loop = false,
|
|
153
|
+
flex,
|
|
154
|
+
onItemCross,
|
|
155
|
+
"aria-label": ariaLabel,
|
|
156
|
+
} = props;
|
|
157
|
+
const { knobProps, size, itemHeight, snapDurationMs, highlightStyle, highlightClassName } =
|
|
158
|
+
useWheelLayout(props);
|
|
281
159
|
const columnWidth = widthProp ?? defaultColumnWidth;
|
|
282
160
|
ensureWheelFocusStyles();
|
|
283
|
-
// LC-25: discrete snaps (keyboard / controlled value) tween; drag stays 1:1.
|
|
284
|
-
// knobProps.motion.control.transition is undefined at animation "none" (which also carries
|
|
285
|
-
// prefers-reduced-motion) — snaps must JUMP then, not fall back to a tween.
|
|
286
|
-
const motionTransition = knobProps.motion.control.transition as string | undefined;
|
|
287
|
-
const snapDurationMs = motionDurationMs(motionTransition);
|
|
288
161
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
289
162
|
const [scrollOffset, setScrollOffset] = useState(0);
|
|
290
163
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
@@ -640,51 +513,6 @@ export function Wheel<T = string | number>({
|
|
|
640
513
|
[snapToNearestRow, startMomentum, hitTestDataIndex, snapToIndex, disabled],
|
|
641
514
|
);
|
|
642
515
|
|
|
643
|
-
const disabledRef = useRef(disabled);
|
|
644
|
-
disabledRef.current = disabled;
|
|
645
|
-
const pointerDownRef = useRef(handlePointerDown);
|
|
646
|
-
pointerDownRef.current = handlePointerDown;
|
|
647
|
-
const pointerMoveRef = useRef(handlePointerMove);
|
|
648
|
-
pointerMoveRef.current = handlePointerMove;
|
|
649
|
-
const pointerUpRef = useRef(handlePointerUp);
|
|
650
|
-
pointerUpRef.current = handlePointerUp;
|
|
651
|
-
|
|
652
|
-
const panResponder = useMemo(() => {
|
|
653
|
-
if (isWeb) return { panHandlers: {} as Record<string, unknown> };
|
|
654
|
-
return PanResponder.create({
|
|
655
|
-
onStartShouldSetPanResponder: () => !disabledRef.current,
|
|
656
|
-
onMoveShouldSetPanResponder: (_, gesture) => Math.abs(gesture.dy) > 1,
|
|
657
|
-
onPanResponderTerminationRequest: () => false,
|
|
658
|
-
onShouldBlockNativeResponder: () => true,
|
|
659
|
-
onPanResponderGrant: (evt: GestureResponderEvent) => {
|
|
660
|
-
pointerDownRef.current({
|
|
661
|
-
clientY: evt.nativeEvent.pageY,
|
|
662
|
-
pointerId: 1,
|
|
663
|
-
});
|
|
664
|
-
},
|
|
665
|
-
onPanResponderMove: (evt: GestureResponderEvent) => {
|
|
666
|
-
pointerMoveRef.current({
|
|
667
|
-
clientY: evt.nativeEvent.pageY,
|
|
668
|
-
pointerId: 1,
|
|
669
|
-
});
|
|
670
|
-
},
|
|
671
|
-
onPanResponderRelease: (evt: GestureResponderEvent) => {
|
|
672
|
-
pointerUpRef.current({
|
|
673
|
-
clientY: evt.nativeEvent.pageY,
|
|
674
|
-
pointerId: 1,
|
|
675
|
-
locationY: evt.nativeEvent.locationY,
|
|
676
|
-
});
|
|
677
|
-
},
|
|
678
|
-
onPanResponderTerminate: (evt: GestureResponderEvent) => {
|
|
679
|
-
pointerUpRef.current({
|
|
680
|
-
clientY: evt.nativeEvent.pageY,
|
|
681
|
-
pointerId: 1,
|
|
682
|
-
locationY: evt.nativeEvent.locationY,
|
|
683
|
-
});
|
|
684
|
-
},
|
|
685
|
-
});
|
|
686
|
-
}, []);
|
|
687
|
-
|
|
688
516
|
// Handle mouse wheel
|
|
689
517
|
const handleWheel = useCallback(
|
|
690
518
|
(e: React.WheelEvent | WheelEvent) => {
|
|
@@ -797,36 +625,20 @@ export function Wheel<T = string | number>({
|
|
|
797
625
|
|
|
798
626
|
const renderRows = useMemo(() => {
|
|
799
627
|
if (n === 0) return [];
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}
|
|
807
|
-
return list;
|
|
628
|
+
const span = Math.ceil(drumReachRows(itemHeight, containerHeight));
|
|
629
|
+
const centerRow = Math.round(scrollOffset / itemHeight);
|
|
630
|
+
const first = loopEnabled ? centerRow - span : Math.max(0, centerRow - span);
|
|
631
|
+
const last = loopEnabled ? centerRow + span : Math.min(n - 1, centerRow + span);
|
|
632
|
+
const list: { virtualRow: number; dataIndex: number }[] = [];
|
|
633
|
+
for (let vr = first; vr <= last; vr++) {
|
|
634
|
+
list.push({ virtualRow: vr, dataIndex: modIndex(vr, n) });
|
|
808
635
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
n - 1,
|
|
812
|
-
Math.ceil((scrollOffset + containerHeight) / itemHeight) + paddingItems + 1,
|
|
813
|
-
);
|
|
814
|
-
return Array.from({ length: end - start + 1 }, (_, i) => {
|
|
815
|
-
const virtualRow = start + i;
|
|
816
|
-
return { virtualRow, dataIndex: virtualRow };
|
|
817
|
-
});
|
|
818
|
-
}, [n, loopEnabled, scrollOffset, itemHeight, paddingItems, containerHeight]);
|
|
636
|
+
return list;
|
|
637
|
+
}, [n, loopEnabled, scrollOffset, itemHeight, containerHeight]);
|
|
819
638
|
|
|
820
639
|
const itemColor = (isSelected: boolean) =>
|
|
821
640
|
disabled ? "$color10" : isSelected ? "$color12" : "$color11";
|
|
822
641
|
|
|
823
|
-
const radiusToken = knobProps.borderRadius.borderRadius as string | number;
|
|
824
|
-
const highlightStyle = highlightBandStyle(highlightEdges, radiusToken, Boolean(knobProps.pointy));
|
|
825
|
-
const highlightSmoothClass =
|
|
826
|
-
"className" in knobProps.borderRadius && typeof knobProps.borderRadius.className === "string"
|
|
827
|
-
? knobProps.borderRadius.className
|
|
828
|
-
: undefined;
|
|
829
|
-
|
|
830
642
|
const renderItemNode = (dataIndex: number, isSelected: boolean) => {
|
|
831
643
|
const item = items[dataIndex];
|
|
832
644
|
const itemValue = getItemValue(item);
|
|
@@ -859,7 +671,7 @@ export function Wheel<T = string | number>({
|
|
|
859
671
|
>
|
|
860
672
|
{/* iOS 14+ selection fill — LC-71 selected=fill, never hairline borders */}
|
|
861
673
|
<SelectionIndicator
|
|
862
|
-
className={
|
|
674
|
+
className={highlightClassName}
|
|
863
675
|
backgroundColor="$color4"
|
|
864
676
|
top={paddingItems * itemHeight}
|
|
865
677
|
height={itemHeight}
|
|
@@ -868,128 +680,74 @@ export function Wheel<T = string | number>({
|
|
|
868
680
|
/>
|
|
869
681
|
|
|
870
682
|
{/* Interactive container */}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
>
|
|
940
|
-
{renderItemNode(dataIndex, isSelected)}
|
|
941
|
-
</div>
|
|
942
|
-
);
|
|
943
|
-
})}
|
|
944
|
-
</div>
|
|
945
|
-
) : (
|
|
946
|
-
<View
|
|
947
|
-
width="100%"
|
|
948
|
-
height={containerHeight}
|
|
949
|
-
position="relative"
|
|
950
|
-
overflow="hidden"
|
|
951
|
-
cursor={disabled ? "not-allowed" : "grab"}
|
|
952
|
-
data-testid="wheel-wrapper"
|
|
953
|
-
data-disabled={disabled ? true : undefined}
|
|
954
|
-
aria-disabled={disabled || undefined}
|
|
955
|
-
{...panResponder.panHandlers}
|
|
956
|
-
>
|
|
957
|
-
{renderRows.map(({ virtualRow, dataIndex }) => {
|
|
958
|
-
const isSelected = dataIndex === liveDataIndex;
|
|
959
|
-
const transform = getItemTransform(
|
|
960
|
-
virtualRow,
|
|
961
|
-
scrollOffset,
|
|
962
|
-
itemHeight,
|
|
963
|
-
containerHeight,
|
|
964
|
-
);
|
|
965
|
-
|
|
966
|
-
if (Math.abs(transform.rotateX) > 85) return null;
|
|
967
|
-
|
|
968
|
-
return (
|
|
969
|
-
<View
|
|
970
|
-
key={`${dataIndex}-${virtualRow}`}
|
|
971
|
-
position="absolute"
|
|
972
|
-
left={0}
|
|
973
|
-
right={0}
|
|
974
|
-
height={itemHeight}
|
|
975
|
-
alignItems="center"
|
|
976
|
-
justifyContent="center"
|
|
977
|
-
opacity={transform.opacity}
|
|
978
|
-
pointerEvents="none"
|
|
979
|
-
y={transform.translateY}
|
|
980
|
-
scale={transform.scale}
|
|
981
|
-
rotateX={`${transform.rotateX}deg`}
|
|
982
|
-
data-testid="wheel-item"
|
|
983
|
-
data-index={dataIndex}
|
|
984
|
-
data-selected={isSelected ? true : undefined}
|
|
985
|
-
>
|
|
986
|
-
{renderItemNode(dataIndex, isSelected)}
|
|
987
|
-
</View>
|
|
988
|
-
);
|
|
989
|
-
})}
|
|
990
|
-
<WheelEdgeFade height={paddingItems * itemHeight} />
|
|
991
|
-
</View>
|
|
992
|
-
)}
|
|
683
|
+
<div
|
|
684
|
+
ref={containerRef}
|
|
685
|
+
className="mp1-wheel-wrapper"
|
|
686
|
+
tabIndex={disabled ? -1 : 0}
|
|
687
|
+
role="slider"
|
|
688
|
+
aria-label={ariaLabel ?? t("Value picker")}
|
|
689
|
+
aria-orientation="vertical"
|
|
690
|
+
aria-valuemin={0}
|
|
691
|
+
aria-valuemax={Math.max(0, n - 1)}
|
|
692
|
+
aria-valuenow={selectedIndex}
|
|
693
|
+
aria-valuetext={
|
|
694
|
+
items[selectedIndex] !== undefined ? getItemLabel(items[selectedIndex]) : undefined
|
|
695
|
+
}
|
|
696
|
+
aria-disabled={disabled || undefined}
|
|
697
|
+
data-disabled={disabled ? true : undefined}
|
|
698
|
+
style={{
|
|
699
|
+
width: "100%",
|
|
700
|
+
height: containerHeight,
|
|
701
|
+
position: "relative",
|
|
702
|
+
perspective: `${containerHeight * 4}px`,
|
|
703
|
+
perspectiveOrigin: "center center",
|
|
704
|
+
overflow: "hidden",
|
|
705
|
+
userSelect: "none",
|
|
706
|
+
touchAction: "none",
|
|
707
|
+
cursor: disabled ? "not-allowed" : "grab",
|
|
708
|
+
...wheelMaskStyle,
|
|
709
|
+
}}
|
|
710
|
+
onPointerDown={handlePointerDown as any}
|
|
711
|
+
onPointerMove={handlePointerMove as any}
|
|
712
|
+
onPointerUp={handlePointerUp as any}
|
|
713
|
+
onPointerCancel={handlePointerUp as any}
|
|
714
|
+
onKeyDown={handleKeyDown as any}
|
|
715
|
+
data-testid="wheel-wrapper"
|
|
716
|
+
>
|
|
717
|
+
{renderRows.map(({ virtualRow, dataIndex }) => {
|
|
718
|
+
const isSelected = dataIndex === liveDataIndex;
|
|
719
|
+
const transform = getItemTransform(virtualRow, scrollOffset, itemHeight, containerHeight);
|
|
720
|
+
|
|
721
|
+
if (Math.abs(transform.rotateX) > 85) return null;
|
|
722
|
+
|
|
723
|
+
return (
|
|
724
|
+
<div
|
|
725
|
+
key={`${dataIndex}-${virtualRow}`}
|
|
726
|
+
data-testid="wheel-item"
|
|
727
|
+
data-index={dataIndex}
|
|
728
|
+
data-selected={isSelected ? true : undefined}
|
|
729
|
+
aria-hidden={isSelected ? undefined : true}
|
|
730
|
+
style={{
|
|
731
|
+
position: "absolute",
|
|
732
|
+
left: 0,
|
|
733
|
+
right: 0,
|
|
734
|
+
height: itemHeight,
|
|
735
|
+
display: "flex",
|
|
736
|
+
alignItems: "center",
|
|
737
|
+
justifyContent: "center",
|
|
738
|
+
transform: `translateY(${transform.translateY}px) rotateX(${transform.rotateX}deg) scale(${transform.scale})`,
|
|
739
|
+
opacity: transform.opacity,
|
|
740
|
+
pointerEvents: "none",
|
|
741
|
+
transformOrigin: "center center",
|
|
742
|
+
transformStyle: "preserve-3d",
|
|
743
|
+
backfaceVisibility: "hidden",
|
|
744
|
+
}}
|
|
745
|
+
>
|
|
746
|
+
{renderItemNode(dataIndex, isSelected)}
|
|
747
|
+
</div>
|
|
748
|
+
);
|
|
749
|
+
})}
|
|
750
|
+
</div>
|
|
993
751
|
</WheelContainer>
|
|
994
752
|
);
|
|
995
753
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { drumPose, drumReachRows } from "./wheelShared";
|
|
3
|
+
|
|
4
|
+
describe("UIPickerView drum geometry", () => {
|
|
5
|
+
const itemHeight = 40;
|
|
6
|
+
|
|
7
|
+
for (const visibleItems of [3, 5, 7]) {
|
|
8
|
+
const frameHeight = itemHeight * visibleItems;
|
|
9
|
+
|
|
10
|
+
it(`never overlaps neighbouring rows (${visibleItems} visible)`, () => {
|
|
11
|
+
const reach = Math.floor(drumReachRows(itemHeight, frameHeight));
|
|
12
|
+
for (let d = -reach; d < reach; d++) {
|
|
13
|
+
const a = drumPose(d, itemHeight, frameHeight);
|
|
14
|
+
const b = drumPose(d + 1, itemHeight, frameHeight);
|
|
15
|
+
const halfA = (itemHeight * Math.cos((a.rotateX * Math.PI) / 180) * a.scale) / 2;
|
|
16
|
+
const halfB = (itemHeight * Math.cos((b.rotateX * Math.PI) / 180) * b.scale) / 2;
|
|
17
|
+
expect(b.offset - a.offset).toBeGreaterThanOrEqual(halfA + halfB - 1e-6);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it(`puts the frame edge at the drum's 80° line (${visibleItems} visible)`, () => {
|
|
22
|
+
const reach = drumReachRows(itemHeight, frameHeight);
|
|
23
|
+
for (let d = -reach; d <= reach; d += 0.25) {
|
|
24
|
+
const pose = drumPose(d, itemHeight, frameHeight);
|
|
25
|
+
if (Math.abs(pose.rotateX) > 80) continue;
|
|
26
|
+
expect(Math.abs(pose.offset)).toBeLessThanOrEqual(frameHeight / 2 + 1e-9);
|
|
27
|
+
}
|
|
28
|
+
expect(drumPose(reach + 0.01, itemHeight, frameHeight).opacity).toBe(0);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
it("seats the centred row flat, full size and opaque", () => {
|
|
33
|
+
expect(drumPose(0, itemHeight, 200)).toEqual({ offset: 0, rotateX: -0, scale: 1, opacity: 1 });
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("bends, shrinks and fades rows away from the centre", () => {
|
|
37
|
+
const near = drumPose(1, itemHeight, 200);
|
|
38
|
+
const far = drumPose(3, itemHeight, 200);
|
|
39
|
+
expect(far.rotateX).toBeLessThan(near.rotateX);
|
|
40
|
+
expect(near.rotateX).toBeLessThan(0);
|
|
41
|
+
expect(far.scale).toBeLessThan(near.scale);
|
|
42
|
+
expect(far.opacity).toBeLessThan(near.opacity);
|
|
43
|
+
expect(near.opacity).toBeLessThan(1);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("is symmetric above and below the band", () => {
|
|
47
|
+
const above = drumPose(-2, itemHeight, 200);
|
|
48
|
+
const below = drumPose(2, itemHeight, 200);
|
|
49
|
+
expect(above.offset).toBeCloseTo(-below.offset);
|
|
50
|
+
expect(above.rotateX).toBeCloseTo(-below.rotateX);
|
|
51
|
+
expect(above.opacity).toBeCloseTo(below.opacity);
|
|
52
|
+
});
|
|
53
|
+
});
|