@multiplatform.one/forms 7.5.0 → 7.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/AdaptivePopup/index.native.js +1 -1
- package/dist/cjs/AdaptivePopup/index.native.js.map +1 -1
- package/dist/cjs/Button/index.cjs +6 -10
- package/dist/cjs/Button/index.native.js +7 -11
- 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.cjs +0 -1
- package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js +1 -2
- 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.cjs +2 -1
- package/dist/cjs/FieldDisplay/index.native.js +10 -3
- package/dist/cjs/FieldDisplay/index.native.js.map +1 -1
- package/dist/cjs/FieldGroup.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/index.cjs +8 -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/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.cjs +64 -2
- package/dist/cjs/InputParts/index.native.js +70 -4
- package/dist/cjs/InputParts/index.native.js.map +1 -1
- package/dist/cjs/Label/index.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/haptic.native.js.map +1 -1
- package/dist/cjs/Wheel/index.native.js.map +1 -1
- 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.cjs +15 -9
- package/dist/cjs/fields/Barcode/BarcodePreview.native.js +15 -9
- 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/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.cjs +14 -11
- package/dist/cjs/fields/Combobox/index.native.js +21 -16
- 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.native.js +3 -3
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- 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/fieldValueSync.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/index.native.js +2 -2
- package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
- 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.cjs +11 -3
- package/dist/cjs/fields/FileUpload/index.native.js +22 -5
- 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/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/Icon/drawnSet.native.js.map +1 -1
- package/dist/cjs/fields/Icon/index.cjs +1 -0
- package/dist/cjs/fields/Icon/index.native.js +4 -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.cjs +175 -95
- package/dist/cjs/fields/Input/index.native.js +85 -6
- package/dist/cjs/fields/Input/index.native.js.map +1 -1
- package/dist/cjs/fields/MentionInput/index.cjs +6 -1
- package/dist/cjs/fields/MentionInput/index.native.js +9 -4
- package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
- package/dist/cjs/fields/OTPInput/index.cjs +7 -2
- package/dist/cjs/fields/OTPInput/index.native.js +10 -5
- 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 +4 -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/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/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/index.native.js +3 -3
- package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
- 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/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.native.js +1 -1
- 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/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.cjs +4 -14
- package/dist/cjs/shared/utils.native.js +7 -15
- 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.mjs +6 -9
- package/dist/esm/Button/index.mjs.map +1 -1
- package/dist/esm/Button/index.native.js +6 -9
- 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.mjs +0 -1
- package/dist/esm/ContextualSaveBar/UnsavedChangesDialog.mjs.map +1 -1
- package/dist/esm/ContextualSaveBar/UnsavedChangesDialog.native.js +0 -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.mjs +2 -1
- package/dist/esm/FieldDisplay/index.mjs.map +1 -1
- package/dist/esm/FieldDisplay/index.native.js +9 -2
- 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 +8 -1
- package/dist/esm/FloatingPanel/index.mjs.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/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 +64 -2
- package/dist/esm/InputParts/index.mjs.map +1 -1
- package/dist/esm/InputParts/index.native.js +70 -4
- 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.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.native.js.map +1 -1
- package/dist/esm/fields/Barcode/BarcodePreview.mjs +15 -9
- package/dist/esm/fields/Barcode/BarcodePreview.mjs.map +1 -1
- package/dist/esm/fields/Barcode/BarcodePreview.native.js +15 -9
- 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/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 +14 -11
- package/dist/esm/fields/Combobox/index.mjs.map +1 -1
- package/dist/esm/fields/Combobox/index.native.js +16 -11
- 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.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/fieldValueSync.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/index.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.mjs +11 -3
- package/dist/esm/fields/FileUpload/index.mjs.map +1 -1
- package/dist/esm/fields/FileUpload/index.native.js +20 -3
- 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/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/Icon/drawnSet.native.js.map +1 -1
- package/dist/esm/fields/Icon/index.mjs +1 -0
- package/dist/esm/fields/Icon/index.mjs.map +1 -1
- package/dist/esm/fields/Icon/index.native.js +1 -0
- 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 +177 -98
- package/dist/esm/fields/Input/index.mjs.map +1 -1
- package/dist/esm/fields/Input/index.native.js +85 -7
- package/dist/esm/fields/Input/index.native.js.map +1 -1
- package/dist/esm/fields/MentionInput/index.mjs +6 -1
- package/dist/esm/fields/MentionInput/index.mjs.map +1 -1
- package/dist/esm/fields/MentionInput/index.native.js +6 -1
- package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
- package/dist/esm/fields/OTPInput/index.mjs +7 -3
- package/dist/esm/fields/OTPInput/index.mjs.map +1 -1
- package/dist/esm/fields/OTPInput/index.native.js +7 -3
- 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.map +1 -1
- package/dist/esm/fields/PhoneInput/index.native.js +1 -0
- 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.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/index.native.js.map +1 -1
- package/dist/esm/fields/TextArea/index.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/index.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/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.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/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.mjs +4 -14
- package/dist/esm/shared/utils.mjs.map +1 -1
- package/dist/esm/shared/utils.native.js +6 -14
- 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/AdaptivePopup/index.native.js +1 -1
- package/dist/jsx/AdaptivePopup/index.native.js.map +1 -1
- package/dist/jsx/Button/index.mjs +6 -9
- package/dist/jsx/Button/index.mjs.map +1 -1
- package/dist/jsx/Button/index.native.js +7 -11
- package/dist/jsx/Button/index.native.js.map +1 -1
- package/dist/jsx/Chip/index.native.js.map +1 -1
- package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.mjs +0 -1
- package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.mjs.map +1 -1
- package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.native.js +1 -2
- package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
- package/dist/jsx/ContextualSaveBar/clientKnownIdentity.native.js.map +1 -1
- package/dist/jsx/ContextualSaveBar/commitImmediateField.native.js.map +1 -1
- package/dist/jsx/ContextualSaveBar/index.native.js +3 -3
- package/dist/jsx/ContextualSaveBar/index.native.js.map +1 -1
- package/dist/jsx/ContextualSaveBar/useUnsavedChangesGuard.native.js.map +1 -1
- package/dist/jsx/ControlGroup/index.native.js +1 -1
- package/dist/jsx/ControlGroup/index.native.js.map +1 -1
- package/dist/jsx/DescriptionList/index.native.js +2 -2
- package/dist/jsx/DescriptionList/index.native.js.map +1 -1
- package/dist/jsx/ErrorSummary.native.js.map +1 -1
- package/dist/jsx/FieldDisplay/editMode.native.js.map +1 -1
- package/dist/jsx/FieldDisplay/formatters.native.js.map +1 -1
- package/dist/jsx/FieldDisplay/index.mjs +2 -1
- package/dist/jsx/FieldDisplay/index.mjs.map +1 -1
- package/dist/jsx/FieldDisplay/index.native.js +10 -3
- package/dist/jsx/FieldDisplay/index.native.js.map +1 -1
- package/dist/jsx/FieldGroup.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/index.mjs +8 -1
- package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/useFloatingPanel.native.js.map +1 -1
- package/dist/jsx/Form/index.native.js +1 -1
- package/dist/jsx/Form/index.native.js.map +1 -1
- package/dist/jsx/Form/validateOn.native.js.map +1 -1
- package/dist/jsx/FormGrid.native.js.map +1 -1
- package/dist/jsx/FormSection.native.js.map +1 -1
- package/dist/jsx/InputParts/index.mjs +64 -2
- package/dist/jsx/InputParts/index.mjs.map +1 -1
- package/dist/jsx/InputParts/index.native.js +70 -4
- package/dist/jsx/InputParts/index.native.js.map +1 -1
- package/dist/jsx/Label/index.native.js.map +1 -1
- package/dist/jsx/Skeleton/index.native.js.map +1 -1
- package/dist/jsx/Spinner/SpinnerGlyph.native.js.map +1 -1
- package/dist/jsx/Spinner/spinnerSize.native.js.map +1 -1
- package/dist/jsx/Table/index.native.js.map +1 -1
- package/dist/jsx/Wheel/haptic.native.js.map +1 -1
- package/dist/jsx/Wheel/index.native.js.map +1 -1
- package/dist/jsx/actionLabel.native.js.map +1 -1
- package/dist/jsx/fieldDefaults.native.js.map +1 -1
- package/dist/jsx/fieldLayout.native.js +1 -1
- package/dist/jsx/fieldLayout.native.js.map +1 -1
- package/dist/jsx/fields/Barcode/BarcodePreview.mjs +15 -9
- package/dist/jsx/fields/Barcode/BarcodePreview.mjs.map +1 -1
- package/dist/jsx/fields/Barcode/BarcodePreview.native.js +15 -9
- package/dist/jsx/fields/Barcode/BarcodePreview.native.js.map +1 -1
- package/dist/jsx/fields/Barcode/BarcodeScanner.native.js +1 -1
- package/dist/jsx/fields/Barcode/code128.native.js.map +1 -1
- package/dist/jsx/fields/Barcode/index.native.js +2 -2
- package/dist/jsx/fields/Barcode/index.native.js.map +1 -1
- package/dist/jsx/fields/Barcode/qr.native.js.map +1 -1
- package/dist/jsx/fields/Barcode/scannerTypes.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/Checkbox.native.js +1 -1
- package/dist/jsx/fields/Checkbox/Checkbox.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxBox.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxCard.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxGroup.native.js +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/index.native.js.map +1 -1
- package/dist/jsx/fields/ColorPicker/index.native.js +3 -3
- package/dist/jsx/fields/ColorPicker/index.native.js.map +1 -1
- package/dist/jsx/fields/ColorPicker/parts.native.js +2 -2
- package/dist/jsx/fields/ColorPicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/Combobox/authorOptions.native.js.map +1 -1
- package/dist/jsx/fields/Combobox/index.mjs +14 -11
- package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
- package/dist/jsx/fields/Combobox/index.native.js +21 -16
- package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/Calendar.native.js.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.native.js +3 -3
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/MonthPicker.native.js +2 -2
- package/dist/jsx/fields/DatePicker/MonthPicker.native.js.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/fieldValueSync.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/index.native.js +2 -2
- package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.native.js +2 -2
- package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/utils.native.js.map +1 -1
- package/dist/jsx/fields/Duration/durationMath.native.js.map +1 -1
- package/dist/jsx/fields/Duration/index.native.js +3 -3
- package/dist/jsx/fields/Duration/index.native.js.map +1 -1
- package/dist/jsx/fields/FileUpload/filePickerTypes.native.js.map +1 -1
- package/dist/jsx/fields/FileUpload/index.mjs +11 -3
- package/dist/jsx/fields/FileUpload/index.mjs.map +1 -1
- package/dist/jsx/fields/FileUpload/index.native.js +22 -5
- package/dist/jsx/fields/FileUpload/index.native.js.map +1 -1
- package/dist/jsx/fields/FileUpload/nativePickerLoader.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/expoMapsLoader.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/index.native.js +5 -5
- package/dist/jsx/fields/Geolocation/index.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/mapMath.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/mapTypes.native.js.map +1 -1
- package/dist/jsx/fields/Icon/drawnSet.native.js.map +1 -1
- package/dist/jsx/fields/Icon/index.mjs +1 -0
- package/dist/jsx/fields/Icon/index.mjs.map +1 -1
- package/dist/jsx/fields/Icon/index.native.js +4 -3
- package/dist/jsx/fields/Icon/index.native.js.map +1 -1
- package/dist/jsx/fields/ImageField/index.native.js +2 -2
- package/dist/jsx/fields/ImageField/index.native.js.map +1 -1
- package/dist/jsx/fields/Input/index.mjs +177 -98
- package/dist/jsx/fields/Input/index.mjs.map +1 -1
- package/dist/jsx/fields/Input/index.native.js +85 -6
- package/dist/jsx/fields/Input/index.native.js.map +1 -1
- package/dist/jsx/fields/MentionInput/index.mjs +6 -1
- package/dist/jsx/fields/MentionInput/index.mjs.map +1 -1
- package/dist/jsx/fields/MentionInput/index.native.js +9 -4
- package/dist/jsx/fields/MentionInput/index.native.js.map +1 -1
- package/dist/jsx/fields/OTPInput/index.mjs +7 -3
- package/dist/jsx/fields/OTPInput/index.mjs.map +1 -1
- package/dist/jsx/fields/OTPInput/index.native.js +10 -5
- package/dist/jsx/fields/OTPInput/index.native.js.map +1 -1
- package/dist/jsx/fields/OTPInput/otpCellCss.native.js.map +1 -1
- package/dist/jsx/fields/PhoneInput/dialCodes.native.js.map +1 -1
- package/dist/jsx/fields/PhoneInput/index.mjs.map +1 -1
- package/dist/jsx/fields/PhoneInput/index.native.js +4 -3
- package/dist/jsx/fields/PhoneInput/index.native.js.map +1 -1
- package/dist/jsx/fields/PhoneInput/phone.native.js.map +1 -1
- package/dist/jsx/fields/Progress/index.native.js +1 -1
- package/dist/jsx/fields/Progress/index.native.js.map +1 -1
- package/dist/jsx/fields/RadioGroup/index.native.js +1 -1
- package/dist/jsx/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/jsx/fields/Rating/index.native.js +1 -1
- package/dist/jsx/fields/Rating/index.native.js.map +1 -1
- package/dist/jsx/fields/Rating/ratingMath.native.js.map +1 -1
- package/dist/jsx/fields/Rating/types.native.js.map +1 -1
- package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
- package/dist/jsx/fields/SearchInput/index.native.js +2 -2
- package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/index.native.js +4 -4
- package/dist/jsx/fields/Select/index.native.js.map +1 -1
- package/dist/jsx/fields/Signature/index.native.js +2 -2
- package/dist/jsx/fields/Signature/index.native.js.map +1 -1
- package/dist/jsx/fields/Slider/index.native.js +1 -1
- package/dist/jsx/fields/Slider/index.native.js.map +1 -1
- package/dist/jsx/fields/Slider/jumpMotion.native.js.map +1 -1
- package/dist/jsx/fields/Stepper/index.native.js +2 -2
- package/dist/jsx/fields/Stepper/index.native.js.map +1 -1
- package/dist/jsx/fields/Stepper/resolveStepperPlacement.native.js.map +1 -1
- package/dist/jsx/fields/Switch/index.native.js +2 -2
- package/dist/jsx/fields/Switch/index.native.js.map +1 -1
- package/dist/jsx/fields/TextArea/index.native.js +2 -2
- package/dist/jsx/fields/TextArea/index.native.js.map +1 -1
- package/dist/jsx/fields/TimePicker/index.native.js +3 -3
- package/dist/jsx/fields/TimePicker/index.native.js.map +1 -1
- package/dist/jsx/fields/TimePicker/parts.native.js +1 -1
- package/dist/jsx/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
- package/dist/jsx/fields/TimeRangeScrubber/index.native.js +2 -2
- package/dist/jsx/fields/TimeRangeScrubber/index.native.js.map +1 -1
- package/dist/jsx/fields/ToggleGroup/index.native.js +1 -1
- package/dist/jsx/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/jsx/fields/selectedOrder.native.js.map +1 -1
- package/dist/jsx/formSpacing.native.js.map +1 -1
- package/dist/jsx/hooks/useFocusManagement.native.js.map +1 -1
- package/dist/jsx/index.native.js +43 -43
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/requiredMarking.native.js.map +1 -1
- package/dist/jsx/shared/TimeColumn.native.js +1 -1
- package/dist/jsx/shared/TimeColumn.native.js.map +1 -1
- package/dist/jsx/shared/capabilityPreflight.native.js.map +1 -1
- package/dist/jsx/shared/colorRamps.native.js.map +1 -1
- package/dist/jsx/shared/devWarn.native.js.map +1 -1
- package/dist/jsx/shared/floatingList.native.js +1 -1
- package/dist/jsx/shared/floatingList.native.js.map +1 -1
- package/dist/jsx/shared/focusManagement.native.js.map +1 -1
- package/dist/jsx/shared/groupContext.native.js.map +1 -1
- package/dist/jsx/shared/i18n.native.js.map +1 -1
- package/dist/jsx/shared/t.native.js.map +1 -1
- package/dist/jsx/shared/tableCellContext.native.js.map +1 -1
- package/dist/jsx/shared/useDragScroll.native.js.map +1 -1
- package/dist/jsx/shared/useKeyboardInset.native.js.map +1 -1
- package/dist/jsx/shared/useSheetEscapeDismiss.native.js.map +1 -1
- package/dist/jsx/shared/useWheelIncrement.native.js.map +1 -1
- package/dist/jsx/shared/utils.mjs +4 -14
- package/dist/jsx/shared/utils.mjs.map +1 -1
- package/dist/jsx/shared/utils.native.js +7 -15
- package/dist/jsx/shared/utils.native.js.map +1 -1
- package/dist/jsx/shared/zIndex.native.js.map +1 -1
- package/dist/jsx/themedPrimitives.native.js.map +1 -1
- package/dist/jsx/types.native.js.map +1 -1
- package/dist/jsx/utils/LinkCell.native.js.map +1 -1
- package/package.json +7 -7
- package/src/Button/Button.density.spec.tsx +118 -32
- package/src/Button/Button.labelInk.spec.tsx +72 -19
- package/src/Button/Button.lc71.spec.tsx +10 -3
- package/src/Button/Button.stories.tsx +7 -6
- package/src/Button/index.tsx +22 -12
- package/src/ContextualSaveBar/UnsavedChangesDialog.tsx +0 -1
- package/src/FieldDisplay/FieldDisplay.spec.tsx +11 -2
- package/src/FieldDisplay/index.tsx +5 -0
- package/src/FloatingPanel/index.tsx +22 -1
- package/src/FloatingPanel/panelWidthContract.spec.ts +1 -0
- package/src/InputParts/index.tsx +100 -3
- package/src/fields/Barcode/BarcodePreview.spec.tsx +139 -5
- package/src/fields/Barcode/BarcodePreview.tsx +47 -15
- package/src/fields/Combobox/Combobox.spec.tsx +64 -1
- package/src/fields/Combobox/index.tsx +22 -11
- package/src/fields/FileUpload/FileUpload.spec.tsx +28 -0
- package/src/fields/FileUpload/index.tsx +26 -1
- package/src/fields/Icon/Icon.stories.tsx +1 -1
- package/src/fields/Icon/index.tsx +1 -0
- package/src/fields/Input/index.tsx +180 -81
- package/src/fields/MentionInput/index.tsx +9 -1
- package/src/fields/OTPInput/OtpInput.spec.tsx +36 -4
- package/src/fields/OTPInput/index.tsx +18 -3
- package/src/fields/OTPInput/otpCellHeightTouch.spec.ts +44 -0
- package/src/fields/PhoneInput/index.tsx +1 -0
- package/src/fields/SearchInput/index.tsx +5 -3
- package/src/shared/utils.spec.ts +46 -0
- package/src/shared/utils.ts +31 -16
- package/types/Button/index.d.ts +8 -3
- package/types/Button/index.d.ts.map +1 -1
- package/types/ContextualSaveBar/UnsavedChangesDialog.d.ts.map +1 -1
- package/types/FieldDisplay/index.d.ts.map +1 -1
- package/types/InputParts/index.d.ts +9 -5
- package/types/InputParts/index.d.ts.map +1 -1
- package/types/fields/Barcode/BarcodePreview.d.ts +20 -9
- package/types/fields/Barcode/BarcodePreview.d.ts.map +1 -1
- package/types/fields/Checkbox/index.d.ts +3 -3
- package/types/fields/Combobox/index.d.ts.map +1 -1
- package/types/fields/FileUpload/index.d.ts.map +1 -1
- package/types/fields/Icon/index.d.ts.map +1 -1
- package/types/fields/Input/index.d.ts +18 -6
- package/types/fields/Input/index.d.ts.map +1 -1
- package/types/fields/MentionInput/index.d.ts.map +1 -1
- package/types/fields/OTPInput/index.d.ts +12 -0
- package/types/fields/OTPInput/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/ToggleGroup/index.d.ts +1 -1
- package/types/shared/utils.d.ts.map +1 -1
package/src/InputParts/index.tsx
CHANGED
|
@@ -819,6 +819,7 @@ const InputAreaImpl = InputFrame.styleable<{
|
|
|
819
819
|
{...knobProps.body}
|
|
820
820
|
type={secureTextEntry ? "password" : props.type}
|
|
821
821
|
padding={0}
|
|
822
|
+
// size-recipe-escape: zero-reset — Input.Box owns the inset (LC-71); the inner field paints no padding
|
|
822
823
|
paddingHorizontal={0}
|
|
823
824
|
paddingVertical={0}
|
|
824
825
|
keyboardType={resolvedKeyboardType}
|
|
@@ -907,24 +908,115 @@ const InputButton = styled(TButton, {
|
|
|
907
908
|
} as const,
|
|
908
909
|
});
|
|
909
910
|
|
|
910
|
-
|
|
911
|
+
/**
|
|
912
|
+
* LC-71 RING-ANATOMY / LC-49 ONE-TAB-STOP — the `glyphRing` end cap.
|
|
913
|
+
*
|
|
914
|
+
* A bare Input.Button is DECORATIVE: the Box rings for it and it takes no
|
|
915
|
+
* tab stop of its own (Stepper carets, Select/Combobox chevrons). Pass
|
|
916
|
+
* `glyphRing` to promote it to the field's SECOND focusable — the Password
|
|
917
|
+
* reveal, the CopyField copy — where it must ring its own GLYPH, not the
|
|
918
|
+
* 44px hit box. A band on the box would double with the Box's composite
|
|
919
|
+
* ring; a band on the glyph is the chip-dismiss recipe
|
|
920
|
+
* (`.mp-chip-dismiss` + `.mp-chip-dismiss-ring`, keyboardFocusRing.ts).
|
|
921
|
+
*
|
|
922
|
+
* It renders a View rather than TButton because TButton swallows a consumer
|
|
923
|
+
* className and pins its own tabIndex, so the ring class never reaches the
|
|
924
|
+
* node that actually receives focus. SearchInput hand-rolled exactly this
|
|
925
|
+
* pair for that reason (fields/SearchInput/index.tsx:348-380) and left a
|
|
926
|
+
* note saying the classes "cannot ride Input.Button until glyphRing" lands.
|
|
927
|
+
* This is that pair made reusable, so the square comes from the size recipe
|
|
928
|
+
* (LC-70) instead of every call site measuring its own.
|
|
929
|
+
*/
|
|
930
|
+
const InputGlyphButton = styled(View, {
|
|
931
|
+
name: "InputGlyphButton",
|
|
932
|
+
context: InputContext,
|
|
933
|
+
justifyContent: "center",
|
|
934
|
+
alignItems: "center",
|
|
935
|
+
backgroundColor: "transparent",
|
|
936
|
+
borderWidth: 0,
|
|
937
|
+
borderRadius: 0,
|
|
938
|
+
cursor: "pointer",
|
|
939
|
+
flexShrink: 0,
|
|
940
|
+
outlineWidth: 0,
|
|
941
|
+
focusStyle: { outlineWidth: 0 },
|
|
942
|
+
focusVisibleStyle: { outlineWidth: 0 },
|
|
943
|
+
|
|
944
|
+
variants: {
|
|
945
|
+
scaleIcon: {
|
|
946
|
+
":number": {} as any,
|
|
947
|
+
},
|
|
948
|
+
size: {
|
|
949
|
+
...sizeRecipeEndCapVariants,
|
|
950
|
+
"...size": sizeRecipeEndCapFallback,
|
|
951
|
+
},
|
|
952
|
+
} as const,
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
const InputButtonImpl = InputButton.styleable<{ glyphRing?: boolean }>((buttonProps, ref) => {
|
|
911
956
|
const {
|
|
912
957
|
children,
|
|
913
958
|
color: colorProp,
|
|
959
|
+
glyphRing,
|
|
960
|
+
size: sizeProp,
|
|
961
|
+
tabIndex: tabIndexProp,
|
|
962
|
+
className,
|
|
914
963
|
...props
|
|
915
964
|
} = buttonProps as typeof buttonProps & {
|
|
916
965
|
color?: string;
|
|
966
|
+
glyphRing?: boolean;
|
|
967
|
+
size?: FontSizeTokens;
|
|
968
|
+
tabIndex?: number;
|
|
969
|
+
className?: string;
|
|
917
970
|
};
|
|
918
|
-
const { size, color: contextColor } = InputContext.useStyledContext();
|
|
971
|
+
const { size: contextSize, color: contextColor } = InputContext.useStyledContext();
|
|
919
972
|
const { knobProps } = useResolvedKnobs();
|
|
920
973
|
const theme = useTheme();
|
|
921
|
-
const
|
|
974
|
+
const size = (sizeProp ?? contextSize) as FontSizeTokens;
|
|
922
975
|
const paint = resolveGlyphPaint(theme as never, colorProp ?? contextColor);
|
|
923
976
|
const getThemedIcon = useGetThemedIcon({
|
|
924
977
|
size: knobProps.controlIcon.width,
|
|
925
978
|
color: paint as never,
|
|
926
979
|
});
|
|
927
980
|
|
|
981
|
+
if (glyphRing) {
|
|
982
|
+
// A real tab stop must square off the token it was HANDED, not the
|
|
983
|
+
// knob's: a $2 field inside a $4 knob would otherwise ship a 44px stop
|
|
984
|
+
// on a 32px frame. LC-77 keeps the sub-floor case pressable via the
|
|
985
|
+
// caller's hitSlop, never by inflating the cap.
|
|
986
|
+
const square = sizeRecipeForToken(String(size ?? "$true"), { touch: isTouchSurface() }).height;
|
|
987
|
+
const disabled = (props as { disabled?: boolean }).disabled === true;
|
|
988
|
+
if (isWeb) ensureCompositeFocusRing();
|
|
989
|
+
return (
|
|
990
|
+
<InputGlyphButton
|
|
991
|
+
ref={ref as never}
|
|
992
|
+
role="button"
|
|
993
|
+
size={size}
|
|
994
|
+
height={square}
|
|
995
|
+
width={square}
|
|
996
|
+
paddingHorizontal={0} // size-recipe-escape: square end-cap; pad lives on Input.Box
|
|
997
|
+
opacity={disabled ? 0.5 : 1}
|
|
998
|
+
{...props}
|
|
999
|
+
aria-disabled={disabled || undefined}
|
|
1000
|
+
tabIndex={tabIndexProp ?? (disabled ? -1 : 0)}
|
|
1001
|
+
className={
|
|
1002
|
+
isWeb
|
|
1003
|
+
? ["mp-chip-dismiss", className].filter(Boolean).join(" ")
|
|
1004
|
+
: (className ?? undefined)
|
|
1005
|
+
}
|
|
1006
|
+
data-end-cap={square}
|
|
1007
|
+
>
|
|
1008
|
+
<View
|
|
1009
|
+
className={isWeb ? "mp-chip-dismiss-ring" : undefined}
|
|
1010
|
+
alignItems="center"
|
|
1011
|
+
justifyContent="center"
|
|
1012
|
+
>
|
|
1013
|
+
{children}
|
|
1014
|
+
</View>
|
|
1015
|
+
</InputGlyphButton>
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
const square = knobProps.control.height;
|
|
928
1020
|
return (
|
|
929
1021
|
<InputButton
|
|
930
1022
|
ref={ref}
|
|
@@ -933,7 +1025,12 @@ const InputButtonImpl = InputButton.styleable((buttonProps, ref) => {
|
|
|
933
1025
|
width={square}
|
|
934
1026
|
paddingHorizontal={0} // size-recipe-escape: square end-cap; pad lives on Input.Box
|
|
935
1027
|
color={paint}
|
|
1028
|
+
// LC-49: the decorative cap is not a tab stop. tabIndex alone is not
|
|
1029
|
+
// enough — TButton re-derives focusability and stamps tabindex="0".
|
|
1030
|
+
focusable={false}
|
|
936
1031
|
tabIndex={-1}
|
|
1032
|
+
className={className}
|
|
1033
|
+
data-end-cap={square}
|
|
937
1034
|
{...props}
|
|
938
1035
|
>
|
|
939
1036
|
{getThemedIcon(children)}
|
|
@@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
|
|
|
2
2
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
3
3
|
import { BarcodePreview, barcodePreviewSymbology } from "./BarcodePreview";
|
|
4
4
|
import { countModules, encodeCode128B } from "./code128";
|
|
5
|
-
import { encodeQr } from "./qr";
|
|
5
|
+
import { QR_QUIET_ZONE_MODULES, encodeQr } from "./qr";
|
|
6
6
|
import { resolveHtml5FormatIds, resolveNativeBarcodeTypes } from "./scannerTypes";
|
|
7
7
|
|
|
8
8
|
/** Rebuild the module string ("1" = bar) from the encoder's runs. */
|
|
@@ -101,8 +101,13 @@ describe("barcodePreviewSymbology — scanner round trip", () => {
|
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
describe("BarcodePreview — qr format", () => {
|
|
104
|
+
/** The field's own default bound (Barcode/index.tsx): 36 comfortable, 24 compact. */
|
|
105
|
+
const formHeight = 36;
|
|
106
|
+
|
|
104
107
|
it("draws the QR matrix canvas-free (labeled image, real module rows)", () => {
|
|
105
|
-
const result = renderWithProviders(
|
|
108
|
+
const result = renderWithProviders(
|
|
109
|
+
<BarcodePreview value="SKU-001234" format="qr" height={formHeight} />,
|
|
110
|
+
);
|
|
106
111
|
const preview = result.container.querySelector('[data-testid="barcode-preview"]');
|
|
107
112
|
expect(preview).not.toBeNull();
|
|
108
113
|
expect(preview?.getAttribute("aria-label")).toContain("SKU-001234");
|
|
@@ -114,12 +119,16 @@ describe("BarcodePreview — qr format", () => {
|
|
|
114
119
|
});
|
|
115
120
|
|
|
116
121
|
it("draws QR for the Frappe fieldtype's qrcode token via the shared alias table", () => {
|
|
117
|
-
const result = renderWithProviders(
|
|
122
|
+
const result = renderWithProviders(
|
|
123
|
+
<BarcodePreview value="SKU-001234" format="qrcode" height={formHeight} />,
|
|
124
|
+
);
|
|
118
125
|
expect(result.container.querySelector('[data-testid="barcode-preview-qr"]')).not.toBeNull();
|
|
119
126
|
});
|
|
120
127
|
|
|
121
128
|
it("draws values the 1-D strip cannot encode (the closed asymmetry)", () => {
|
|
122
|
-
const result = renderWithProviders(
|
|
129
|
+
const result = renderWithProviders(
|
|
130
|
+
<BarcodePreview value="héllo" format="qr" height={formHeight} />,
|
|
131
|
+
);
|
|
123
132
|
expect(result.container.querySelector('[data-testid="barcode-preview-qr"]')).not.toBeNull();
|
|
124
133
|
});
|
|
125
134
|
|
|
@@ -130,7 +139,9 @@ describe("BarcodePreview — qr format", () => {
|
|
|
130
139
|
|
|
131
140
|
it("falls back to honest mono text past version 10 capacity", () => {
|
|
132
141
|
const long = "x".repeat(214);
|
|
133
|
-
const result = renderWithProviders(
|
|
142
|
+
const result = renderWithProviders(
|
|
143
|
+
<BarcodePreview value={long} format="qr" height={formHeight} />,
|
|
144
|
+
);
|
|
134
145
|
expect(result.container.querySelector('[data-testid="barcode-preview-qr"]')).toBeNull();
|
|
135
146
|
expect(result.container.textContent).toContain(long);
|
|
136
147
|
});
|
|
@@ -141,3 +152,126 @@ describe("BarcodePreview — qr format", () => {
|
|
|
141
152
|
expect(result.container.querySelector('[data-testid="barcode-preview"]')).not.toBeNull();
|
|
142
153
|
});
|
|
143
154
|
});
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Whole-pixel modules. Measured on the media-11 board at DPR 2 BEFORE this
|
|
158
|
+
* rule existed: bounds 33, 72 and 96 decoded and bounds 18, 24, 44 and 56 did
|
|
159
|
+
* not — not a size floor (33 read, 44 did not) but a resampling one. 33/33
|
|
160
|
+
* modules is exactly 1.000 px per module; 44/33 is 1.333, and a fractional
|
|
161
|
+
* module rounds to different widths across the grid. It reached the field's
|
|
162
|
+
* own default path: at height 36 / moduleWidth 1 a payload over 26 bytes
|
|
163
|
+
* clamps under one pixel per module and stops reading, which is precisely the
|
|
164
|
+
* scan-to-draw round trip MPO-53 AC-9 exists to close.
|
|
165
|
+
*/
|
|
166
|
+
describe("BarcodePreview — qr geometry is whole-pixel or nothing", () => {
|
|
167
|
+
const qrSquare = (ui: React.ReactElement) =>
|
|
168
|
+
renderWithProviders(ui).container.querySelector(
|
|
169
|
+
'[data-testid="barcode-preview-qr"]',
|
|
170
|
+
) as HTMLElement | null;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Tamagui compiles geometry to atomic classes (`_w-87px`, `_pt-12px`), not
|
|
174
|
+
* inline style, so the measurement reads the class list. Same numbers, and
|
|
175
|
+
* it is the class the browser actually applies.
|
|
176
|
+
*/
|
|
177
|
+
const px = (el: HTMLElement, prefix: string) => {
|
|
178
|
+
const hit = (el.getAttribute("class") ?? "")
|
|
179
|
+
.split(/\s+/)
|
|
180
|
+
.find((c) => c.startsWith(`_${prefix}-`));
|
|
181
|
+
return hit ? Number.parseFloat(hit.slice(prefix.length + 2)) : Number.NaN;
|
|
182
|
+
};
|
|
183
|
+
const edgeOf = (el: HTMLElement) => px(el, "w");
|
|
184
|
+
const quietOf = (el: HTMLElement) => px(el, "pt");
|
|
185
|
+
|
|
186
|
+
/** Modules per side including the 4-module quiet zone on each side. */
|
|
187
|
+
const totalModules = (value: string) => encodeQr(value)!.size + 2 * QR_QUIET_ZONE_MODULES;
|
|
188
|
+
|
|
189
|
+
it("draws at the natural size when moduleWidth fits under the bound", () => {
|
|
190
|
+
// 6 bytes → version 1 → 21 + 8 = 29 modules. moduleWidth 3 asks for 3px
|
|
191
|
+
// modules and the 120px bound allows 4, so 3 wins: 29 × 3 = 87.
|
|
192
|
+
const value = "SHC-42";
|
|
193
|
+
expect(totalModules(value)).toBe(29);
|
|
194
|
+
const square = qrSquare(
|
|
195
|
+
<BarcodePreview value={value} format="qr" height={120} moduleWidth={3} />,
|
|
196
|
+
);
|
|
197
|
+
expect(square).not.toBeNull();
|
|
198
|
+
expect(edgeOf(square!)).toBe(87);
|
|
199
|
+
expect(px(square!, "h")).toBe(87);
|
|
200
|
+
expect(quietOf(square!)).toBe(12); // 4 modules × 3px
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("treats the height bound as a CEILING, never a target", () => {
|
|
204
|
+
// 18 bytes → version 2 → 25 + 8 = 33 modules at moduleWidth 1 = 33px. A
|
|
205
|
+
// 44px bound does not stretch it to 44 and a fractional 1.333px module.
|
|
206
|
+
const value = "SHC-COMPOSE01-0417";
|
|
207
|
+
expect(totalModules(value)).toBe(33);
|
|
208
|
+
for (const height of [36, 44, 56]) {
|
|
209
|
+
const square = qrSquare(<BarcodePreview value={value} format="qr" height={height} />);
|
|
210
|
+
expect(edgeOf(square!)).toBe(33);
|
|
211
|
+
expect(quietOf(square!)).toBe(4);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("snaps the module DOWN to a whole pixel rather than draw a fractional one", () => {
|
|
216
|
+
// 33 modules under a 96px bound would be 2.909px per module. Snap to 2.
|
|
217
|
+
const square = qrSquare(
|
|
218
|
+
<BarcodePreview value="SHC-COMPOSE01-0417" format="qr" height={96} moduleWidth={9} />,
|
|
219
|
+
);
|
|
220
|
+
expect(edgeOf(square!)).toBe(66);
|
|
221
|
+
expect(quietOf(square!)).toBe(8);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("never draws a module narrower than one whole pixel — every bound, every payload", () => {
|
|
225
|
+
for (const value of ["SHC-42", "SHC-COMPOSE01-0417", "SHC-COMPOSE01-BACKUP-2026-08-28"]) {
|
|
226
|
+
for (const height of [18, 24, 29, 33, 36, 37, 44, 66, 96, 120]) {
|
|
227
|
+
for (const moduleWidth of [1, 2, 3]) {
|
|
228
|
+
const square = qrSquare(
|
|
229
|
+
<BarcodePreview value={value} format="qr" height={height} moduleWidth={moduleWidth} />,
|
|
230
|
+
);
|
|
231
|
+
if (!square) continue; // honest text fallback — asserted below
|
|
232
|
+
const edge = edgeOf(square);
|
|
233
|
+
const pad = quietOf(square);
|
|
234
|
+
const cell = edge / totalModules(value);
|
|
235
|
+
expect(Number.isInteger(cell)).toBe(true);
|
|
236
|
+
expect(cell).toBeGreaterThanOrEqual(1);
|
|
237
|
+
expect(cell).toBeLessThanOrEqual(moduleWidth);
|
|
238
|
+
expect(edge).toBeLessThanOrEqual(height); // LC-10 containment
|
|
239
|
+
expect(pad).toBe(cell * QR_QUIET_ZONE_MODULES);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("falls back to honest text under one whole pixel per module", () => {
|
|
246
|
+
// compact (24) cannot hold 33 modules at a whole pixel each.
|
|
247
|
+
const value = "SHC-COMPOSE01-0417";
|
|
248
|
+
const result = renderWithProviders(<BarcodePreview value={value} format="qr" height={24} />);
|
|
249
|
+
expect(result.container.querySelector('[data-testid="barcode-preview-qr"]')).toBeNull();
|
|
250
|
+
expect(result.container.textContent).toContain(value);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("falls back to honest text when the payload outgrows the form bound", () => {
|
|
254
|
+
// 31 bytes → version 3 → 29 + 8 = 37 modules, which does not fit 36px at
|
|
255
|
+
// one whole pixel each. This is the case that silently shipped unreadable.
|
|
256
|
+
const value = "SHC-COMPOSE01-BACKUP-2026-08-28";
|
|
257
|
+
expect(totalModules(value)).toBe(37);
|
|
258
|
+
const result = renderWithProviders(<BarcodePreview value={value} format="qr" height={36} />);
|
|
259
|
+
expect(result.container.querySelector('[data-testid="barcode-preview-qr"]')).toBeNull();
|
|
260
|
+
expect(result.container.textContent).toContain(value);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("draws nothing at all when the host already shows the value (textFallback false)", () => {
|
|
264
|
+
const value = "SHC-COMPOSE01-0417";
|
|
265
|
+
const result = renderWithProviders(
|
|
266
|
+
<BarcodePreview value={value} format="qr" height={24} textFallback={false} />,
|
|
267
|
+
);
|
|
268
|
+
expect(result.container.querySelector('[data-testid="barcode-preview-qr"]')).toBeNull();
|
|
269
|
+
expect(result.container.textContent).not.toContain(value);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it("leaves the 1-D strip's geometry untouched", () => {
|
|
273
|
+
const result = renderWithProviders(<BarcodePreview value="SKU-001234" height={18} />);
|
|
274
|
+
expect(result.container.querySelector('[data-testid="barcode-preview"]')).not.toBeNull();
|
|
275
|
+
expect(result.container.querySelector('[data-testid="barcode-preview-qr"]')).toBeNull();
|
|
276
|
+
});
|
|
277
|
+
});
|
|
@@ -11,15 +11,16 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Containment contract (LC-10): the symbol never exceeds its host. The strip
|
|
13
13
|
* caps width at 100% and bars shrink proportionally (preserving relative
|
|
14
|
-
* module widths) instead of painting past the frame; the QR square
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* height via the `height` prop (table cells keep it under the row height).
|
|
14
|
+
* module widths) instead of painting past the frame; the QR square is drawn at
|
|
15
|
+
* a WHOLE number of pixels per module, capped by `moduleWidth` and by the
|
|
16
|
+
* `height` bound — always square, never letterboxed or clipped. Hosts bound
|
|
17
|
+
* the height via the `height` prop (table cells keep it under the row height).
|
|
18
18
|
*
|
|
19
19
|
* Honest states: an empty value renders nothing (hosts show their own empty
|
|
20
20
|
* marker); a value the symbology cannot encode (non-ASCII for Code 128 B,
|
|
21
|
-
* over version 10 capacity for QR)
|
|
22
|
-
*
|
|
21
|
+
* over version 10 capacity for QR), or a QR whose modules would be under one
|
|
22
|
+
* whole pixel at the host's bound, falls back to the raw value as mono text —
|
|
23
|
+
* never a fake, truncated or unreadable symbol.
|
|
23
24
|
*/
|
|
24
25
|
|
|
25
26
|
import { Text, View, XStack, YStack } from "tamagui";
|
|
@@ -44,10 +45,11 @@ export interface BarcodePreviewProps {
|
|
|
44
45
|
value?: string;
|
|
45
46
|
/**
|
|
46
47
|
* Symbol height bound in px — content geometry, bounded by the host. The
|
|
47
|
-
* 1-D strip always fills it; the QR square uses it as a
|
|
48
|
+
* 1-D strip always fills it; the QR square uses it as a CEILING and draws at
|
|
49
|
+
* the largest whole-pixel module that fits under it.
|
|
48
50
|
*/
|
|
49
51
|
height?: number;
|
|
50
|
-
/** Width of one barcode module in px. */
|
|
52
|
+
/** Width of one barcode module in px. Fractional values floor for QR. */
|
|
51
53
|
moduleWidth?: number;
|
|
52
54
|
/** Render the human-readable value under the symbol. */
|
|
53
55
|
showText?: boolean;
|
|
@@ -56,6 +58,15 @@ export interface BarcodePreviewProps {
|
|
|
56
58
|
* alias of `qr` draws the QR matrix; others draw the Code 128 strip.
|
|
57
59
|
*/
|
|
58
60
|
format?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Render the raw value as mono text when the symbology cannot draw it —
|
|
63
|
+
* non-ASCII for Code 128 B, over capacity or under one whole pixel per
|
|
64
|
+
* module for QR. Default true, which is right for a standalone preview:
|
|
65
|
+
* disappearing silently would be worse than an honest string. A host that
|
|
66
|
+
* ALREADY shows the value beside the symbol (FieldDisplay) passes false, so
|
|
67
|
+
* an undrawable symbol contributes nothing instead of printing it twice.
|
|
68
|
+
*/
|
|
69
|
+
textFallback?: boolean;
|
|
59
70
|
}
|
|
60
71
|
|
|
61
72
|
/** Mono value text (LC-07 CODE-KNOB-IMMUNE) — both the honest fallback for
|
|
@@ -74,15 +85,22 @@ export function BarcodePreview({
|
|
|
74
85
|
moduleWidth = 1,
|
|
75
86
|
showText = false,
|
|
76
87
|
format,
|
|
88
|
+
textFallback = true,
|
|
77
89
|
}: BarcodePreviewProps) {
|
|
78
90
|
if (!value) return null;
|
|
79
91
|
if (barcodePreviewSymbology(format) === "qr") {
|
|
80
92
|
return (
|
|
81
|
-
<QrPreview
|
|
93
|
+
<QrPreview
|
|
94
|
+
value={value}
|
|
95
|
+
height={height}
|
|
96
|
+
moduleWidth={moduleWidth}
|
|
97
|
+
showText={showText}
|
|
98
|
+
textFallback={textFallback}
|
|
99
|
+
/>
|
|
82
100
|
);
|
|
83
101
|
}
|
|
84
102
|
const runs = encodeCode128B(value);
|
|
85
|
-
if (!runs) return <MonoValue value={value}
|
|
103
|
+
if (!runs) return textFallback ? <MonoValue value={value} /> : null;
|
|
86
104
|
const quietZone = moduleWidth * 10;
|
|
87
105
|
return (
|
|
88
106
|
<View
|
|
@@ -126,19 +144,33 @@ function QrPreview({
|
|
|
126
144
|
height,
|
|
127
145
|
moduleWidth,
|
|
128
146
|
showText,
|
|
147
|
+
textFallback,
|
|
129
148
|
}: {
|
|
130
149
|
value: string;
|
|
131
150
|
height: number;
|
|
132
151
|
moduleWidth: number;
|
|
133
152
|
showText: boolean;
|
|
153
|
+
textFallback: boolean;
|
|
134
154
|
}) {
|
|
135
155
|
const matrix = encodeQr(value);
|
|
136
|
-
if (!matrix) return <MonoValue value={value}
|
|
137
|
-
//
|
|
138
|
-
//
|
|
156
|
+
if (!matrix) return textFallback ? <MonoValue value={value} /> : null;
|
|
157
|
+
// A module must land on a WHOLE pixel. A fractional module width rounds to
|
|
158
|
+
// different widths across the grid, so a decoder cannot resample the symbol —
|
|
159
|
+
// measured on the media-11 board at DPR 2: the 33px square (1.000 px/module)
|
|
160
|
+
// decoded and the 44px one (1.333 px/module) did not, in either scheme. So
|
|
161
|
+
// the module is the largest whole pixel that fits, capped by `moduleWidth`
|
|
162
|
+
// and by the host's `height` bound (LC-10 — the square never exceeds its
|
|
163
|
+
// host, and the bound is a ceiling, never a target).
|
|
139
164
|
const totalModules = matrix.size + 2 * QR_QUIET_ZONE_MODULES;
|
|
140
|
-
const
|
|
141
|
-
|
|
165
|
+
const cell = Math.floor(Math.min(moduleWidth, height / totalModules));
|
|
166
|
+
// Under one whole pixel there is no readable symbol to draw at all. Fall
|
|
167
|
+
// back to the value as text, the same honest contract the over-capacity and
|
|
168
|
+
// non-ASCII cases have: a symbol no reader can resample is decoration, and
|
|
169
|
+
// decoration that looks like data is the one thing this component refuses to
|
|
170
|
+
// paint. This is what a `compact` bound (24) or a table-row bound does to
|
|
171
|
+
// anything past a short SKU.
|
|
172
|
+
if (cell < 1) return textFallback ? <MonoValue value={value} /> : null;
|
|
173
|
+
const edge = cell * totalModules;
|
|
142
174
|
const quietZone = cell * QR_QUIET_ZONE_MODULES;
|
|
143
175
|
const rows = qrRowRuns(matrix);
|
|
144
176
|
return (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { act, fireEvent } from "@testing-library/react";
|
|
2
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
3
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
4
4
|
import { Form } from "../../Form";
|
|
5
5
|
import { Combobox } from "./index";
|
|
@@ -313,5 +313,68 @@ describe("Combobox", () => {
|
|
|
313
313
|
expect(activeOption(result.container)?.textContent).toContain("Carrot");
|
|
314
314
|
expect(activeOption(result.container)?.getAttribute("role")).toBe("option");
|
|
315
315
|
});
|
|
316
|
+
|
|
317
|
+
// The sheet core (<= OVERLAY_BREAKPOINT, and every native render) used to
|
|
318
|
+
// build headers itself from source order, so interleaved groups emitted a
|
|
319
|
+
// REPEAT header and the rows stayed unclustered — two different lists from
|
|
320
|
+
// one set of props. Both cores now go through groupComboboxOptions.
|
|
321
|
+
it("the sheet renders the same headers and row order as the desktop panel", async () => {
|
|
322
|
+
function shot(root: HTMLElement) {
|
|
323
|
+
return {
|
|
324
|
+
headers: [...root.querySelectorAll("[data-combobox-group-header]")].map(
|
|
325
|
+
(el) => el.textContent,
|
|
326
|
+
),
|
|
327
|
+
rows: [...root.querySelectorAll('[role="option"]')].map((el) => ({
|
|
328
|
+
label: el.textContent,
|
|
329
|
+
index: el.getAttribute("data-combobox-index"),
|
|
330
|
+
})),
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
window.innerWidth = 1200;
|
|
335
|
+
const desktop = renderWithProviders(
|
|
336
|
+
<Combobox label="Produce" name="produce" options={groupedOptions} multiple open />,
|
|
337
|
+
);
|
|
338
|
+
await act(async () => {});
|
|
339
|
+
const onDesktop = shot(document.body);
|
|
340
|
+
desktop.unmount();
|
|
341
|
+
|
|
342
|
+
window.innerWidth = 500;
|
|
343
|
+
renderWithProviders(
|
|
344
|
+
<Combobox label="Produce" name="produce" options={groupedOptions} multiple open />,
|
|
345
|
+
);
|
|
346
|
+
await act(async () => {});
|
|
347
|
+
const onSheet = shot(document.body);
|
|
348
|
+
|
|
349
|
+
expect(onDesktop.headers).toEqual(["Fruit", "Vegetable"]);
|
|
350
|
+
expect(onSheet.headers).toEqual(onDesktop.headers);
|
|
351
|
+
expect(onSheet.rows).toEqual(onDesktop.rows);
|
|
352
|
+
// One header per group: a repeated label is the defect this guards.
|
|
353
|
+
expect(new Set(onSheet.headers).size).toBe(onSheet.headers.length);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// The sheet's activeIndex indexes the same grouped list the sheet renders,
|
|
357
|
+
// so arrows land on the row the user sees rather than the source-order row.
|
|
358
|
+
it("sheet ArrowDown follows the rendered row order, not source order", async () => {
|
|
359
|
+
window.innerWidth = 500;
|
|
360
|
+
renderWithProviders(
|
|
361
|
+
<Combobox label="Produce" name="produce" options={groupedOptions} multiple open />,
|
|
362
|
+
);
|
|
363
|
+
await act(async () => {});
|
|
364
|
+
|
|
365
|
+
const rows = [...document.body.querySelectorAll('[role="option"]')];
|
|
366
|
+
expect(rows.map((el) => el.textContent?.trim())).toEqual(["Apple", "Banana", "Carrot"]);
|
|
367
|
+
|
|
368
|
+
const search = document.body.querySelector("input");
|
|
369
|
+
expect(search).toBeTruthy();
|
|
370
|
+
// activeIndex starts at 0 (Apple); one ArrowDown must highlight the row
|
|
371
|
+
// rendered second (Banana), which is sortedFiltered[2], not [1].
|
|
372
|
+
await act(async () => {
|
|
373
|
+
fireEvent.keyDown(search!, { key: "ArrowDown" });
|
|
374
|
+
});
|
|
375
|
+
const active = document.body.querySelector('[data-active="true"]');
|
|
376
|
+
expect(active?.textContent).toContain("Banana");
|
|
377
|
+
expect(active?.getAttribute("data-combobox-index")).toBe("1");
|
|
378
|
+
});
|
|
316
379
|
});
|
|
317
380
|
});
|
|
@@ -1918,6 +1918,17 @@ function NativeComboboxCore({
|
|
|
1918
1918
|
return orderOptionsBySelected(filtered, current, selectedOrder);
|
|
1919
1919
|
}, [filtered, value, filter, selectedOrder]);
|
|
1920
1920
|
|
|
1921
|
+
// Same grouping the floating core uses (`groupComboboxOptions`, the mechanism
|
|
1922
|
+
// mpo-floating-measured.md §2.3 names as ours): rows cluster by group so each
|
|
1923
|
+
// group gets exactly ONE header. Rendering source order here emitted a repeat
|
|
1924
|
+
// header for interleaved groups and disagreed with the desktop panel for
|
|
1925
|
+
// identical props. `activeIndex` indexes `navigableOptions`, which IS the
|
|
1926
|
+
// render order, so arrows still land on the row the user sees (MPO-38 AC-6).
|
|
1927
|
+
const { flatOptions: navigableOptions } = useMemo(
|
|
1928
|
+
() => groupComboboxOptions(sortedFiltered),
|
|
1929
|
+
[sortedFiltered],
|
|
1930
|
+
);
|
|
1931
|
+
|
|
1921
1932
|
const searchCleanupRef = useRef<(() => void) | null>(null);
|
|
1922
1933
|
useEffect(() => {
|
|
1923
1934
|
if (!onSearch || !open) return;
|
|
@@ -1942,8 +1953,8 @@ function NativeComboboxCore({
|
|
|
1942
1953
|
}
|
|
1943
1954
|
}, [open]);
|
|
1944
1955
|
|
|
1945
|
-
const totalItems =
|
|
1946
|
-
const createOptionIndex = showCreateOption ?
|
|
1956
|
+
const totalItems = navigableOptions.length + (showCreateOption ? 1 : 0);
|
|
1957
|
+
const createOptionIndex = showCreateOption ? navigableOptions.length : -1;
|
|
1947
1958
|
const listboxId = comboboxListboxId(id);
|
|
1948
1959
|
const activeDescendant =
|
|
1949
1960
|
open && activeIndex != null && activeIndex >= 0 ? comboboxOptionId(id, activeIndex) : undefined;
|
|
@@ -2028,8 +2039,8 @@ function NativeComboboxCore({
|
|
|
2028
2039
|
e.preventDefault();
|
|
2029
2040
|
if (activeIndex === createOptionIndex && showCreateOption) {
|
|
2030
2041
|
handleCreate();
|
|
2031
|
-
} else if (activeIndex != null && activeIndex >= 0 &&
|
|
2032
|
-
handleSelect(
|
|
2042
|
+
} else if (activeIndex != null && activeIndex >= 0 && navigableOptions[activeIndex]) {
|
|
2043
|
+
handleSelect(navigableOptions[activeIndex]);
|
|
2033
2044
|
if (e.key === "Enter" || !multiple) setOpen(false);
|
|
2034
2045
|
}
|
|
2035
2046
|
}
|
|
@@ -2039,7 +2050,7 @@ function NativeComboboxCore({
|
|
|
2039
2050
|
createOptionIndex,
|
|
2040
2051
|
showCreateOption,
|
|
2041
2052
|
activeIndex,
|
|
2042
|
-
|
|
2053
|
+
navigableOptions,
|
|
2043
2054
|
handleCreate,
|
|
2044
2055
|
handleSelect,
|
|
2045
2056
|
multiple,
|
|
@@ -2066,8 +2077,8 @@ function NativeComboboxCore({
|
|
|
2066
2077
|
e.stopPropagation();
|
|
2067
2078
|
if (activeIndex === createOptionIndex && showCreateOption) {
|
|
2068
2079
|
handleCreate();
|
|
2069
|
-
} else if (activeIndex != null && activeIndex >= 0 &&
|
|
2070
|
-
handleSelect(
|
|
2080
|
+
} else if (activeIndex != null && activeIndex >= 0 && navigableOptions[activeIndex]) {
|
|
2081
|
+
handleSelect(navigableOptions[activeIndex]);
|
|
2071
2082
|
if (e.key === "Enter" || !multiple) setOpen(false);
|
|
2072
2083
|
} else {
|
|
2073
2084
|
setOpen(false);
|
|
@@ -2081,7 +2092,7 @@ function NativeComboboxCore({
|
|
|
2081
2092
|
activeIndex,
|
|
2082
2093
|
createOptionIndex,
|
|
2083
2094
|
showCreateOption,
|
|
2084
|
-
|
|
2095
|
+
navigableOptions,
|
|
2085
2096
|
handleCreate,
|
|
2086
2097
|
handleSelect,
|
|
2087
2098
|
multiple,
|
|
@@ -2138,12 +2149,12 @@ function NativeComboboxCore({
|
|
|
2138
2149
|
{searchError}
|
|
2139
2150
|
</Text>
|
|
2140
2151
|
</View>
|
|
2141
|
-
) :
|
|
2152
|
+
) : navigableOptions.length > 0 ? (
|
|
2142
2153
|
<>
|
|
2143
|
-
{
|
|
2154
|
+
{navigableOptions.map((option, i) => {
|
|
2144
2155
|
const selected = isSelectedFn(option.value);
|
|
2145
2156
|
const active = i === activeIndex;
|
|
2146
|
-
const prevGroup = i > 0 ?
|
|
2157
|
+
const prevGroup = i > 0 ? navigableOptions[i - 1].group : undefined;
|
|
2147
2158
|
const showGroupHeader = option.group && option.group !== prevGroup;
|
|
2148
2159
|
const optionRow = (
|
|
2149
2160
|
<View
|
|
@@ -134,6 +134,34 @@ describe("FileUpload", () => {
|
|
|
134
134
|
expect(dropzone?.getAttribute("data-kb-ring")).toBe("true");
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
+
// MPO-57 regression. `data-kb-ring="true"` proved the STATE, never the paint.
|
|
138
|
+
// The frame's LC-71 kill is a `:focus-visible` rule; a keyboard-origin focus
|
|
139
|
+
// matches `:focus-visible` too, so the base-state ring atom lost on
|
|
140
|
+
// specificity and the browser computed outline-width 0px while every
|
|
141
|
+
// assertion passed. Measured on the Storybook harness, not read off source.
|
|
142
|
+
// The ring must therefore also win INSIDE the focus-visible layer.
|
|
143
|
+
it("beats its own LC-71 focus-visible kill — the ring wins in the layer that suppresses it", () => {
|
|
144
|
+
const { container } = renderWithHouseThemes(
|
|
145
|
+
<FileUpload label="Attachment" name="attachment" />,
|
|
146
|
+
);
|
|
147
|
+
const zone = getZone(container);
|
|
148
|
+
fireEvent.keyDown(document.body, { key: "Tab", code: "Tab" });
|
|
149
|
+
fireEvent.focus(zone);
|
|
150
|
+
expect(zone.getAttribute("data-kb-ring")).toBe("true");
|
|
151
|
+
|
|
152
|
+
// Base-state ring (2px solid $outlineColor at offset 0).
|
|
153
|
+
expect(zone.className).toMatch(/_outlineWidth-2px/);
|
|
154
|
+
expect(zone.className).toMatch(/_outlineStyle-solid/);
|
|
155
|
+
expect(zone.className).toMatch(/_outlineOffset-0px/);
|
|
156
|
+
|
|
157
|
+
// …restated in the focus-visible layer, so the kill cannot outrank it.
|
|
158
|
+
expect(zone.className).toMatch(/_outlineWidth-0focus-visible-2px/);
|
|
159
|
+
expect(zone.className).toMatch(/_outlineStyle-0focus-visible-solid/);
|
|
160
|
+
// …and the zeroing atoms are gone from that layer while the ring is up.
|
|
161
|
+
expect(zone.className).not.toMatch(/_outlineWidth-0focus-visible-0px/);
|
|
162
|
+
expect(zone.className).not.toMatch(/_outlineStyle-0focus-visible-none/);
|
|
163
|
+
});
|
|
164
|
+
|
|
137
165
|
it("keeps Choose File out of the tab order so the dropzone is the one stop", () => {
|
|
138
166
|
const result = renderWithProviders(
|
|
139
167
|
<FileUpload label="Attachment" name="attachment" buttonText="Pick file" />,
|