@multiplatform.one/forms 7.7.4 → 7.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Button/index.cjs +3 -36
- package/dist/cjs/Button/index.native.js +3 -36
- package/dist/cjs/Button/index.native.js.map +1 -1
- package/dist/cjs/Chip/index.cjs +1 -1
- package/dist/cjs/Chip/index.native.js +1 -1
- package/dist/cjs/Chip/index.native.js.map +1 -1
- package/dist/cjs/ContextualSaveBar/index.cjs +17 -10
- package/dist/cjs/ContextualSaveBar/index.native.js +18 -10
- package/dist/cjs/ContextualSaveBar/index.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/index.cjs +59 -14
- package/dist/cjs/FloatingPanel/index.native.js +16 -7
- package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/nestedAction.cjs +37 -0
- package/dist/cjs/FloatingPanel/nestedAction.native.js +42 -0
- package/dist/cjs/FloatingPanel/nestedAction.native.js.map +1 -0
- package/dist/cjs/InputParts/index.cjs +11 -7
- package/dist/cjs/InputParts/index.native.js +12 -10
- package/dist/cjs/InputParts/index.native.js.map +1 -1
- package/dist/cjs/Wheel/index.cjs +3 -3
- package/dist/cjs/Wheel/index.native.js +3 -3
- package/dist/cjs/Wheel/index.native.js.map +1 -1
- package/dist/cjs/fieldLayout.cjs +3 -3
- package/dist/cjs/fieldLayout.native.js +3 -3
- package/dist/cjs/fieldLayout.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.cjs +9 -2
- package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
- package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
- package/dist/cjs/fields/Combobox/index.cjs +74 -76
- package/dist/cjs/fields/Combobox/index.native.js +78 -86
- package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/Calendar.cjs +6 -1
- package/dist/cjs/fields/DatePicker/Calendar.native.js +6 -1
- package/dist/cjs/fields/DatePicker/Calendar.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DateRangePicker.cjs +2 -2
- package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +2 -2
- package/dist/cjs/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.cjs +15 -12
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +39 -14
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/MonthPicker.cjs +10 -3
- package/dist/cjs/fields/DatePicker/MonthPicker.native.js +10 -3
- package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/MultiDatePicker.cjs +2 -2
- package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +2 -2
- package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/index.native.js +3 -0
- package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/parts.cjs +26 -14
- package/dist/cjs/fields/DatePicker/parts.native.js +28 -14
- package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/GeolocationMap.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/geocoder.cjs +63 -0
- package/dist/cjs/fields/Geolocation/geocoder.native.js +68 -0
- package/dist/cjs/fields/Geolocation/geocoder.native.js.map +1 -0
- package/dist/cjs/fields/Geolocation/index.cjs +801 -152
- package/dist/cjs/fields/Geolocation/index.native.js +856 -167
- package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/nativeSearchFocus.cjs +44 -0
- package/dist/cjs/fields/Geolocation/nativeSearchFocus.native.js +47 -0
- package/dist/cjs/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
- package/dist/cjs/fields/Icon/drawnSet.cjs +14 -3
- package/dist/cjs/fields/Icon/drawnSet.native.js +18 -3
- package/dist/cjs/fields/Icon/drawnSet.native.js.map +1 -1
- package/dist/cjs/fields/Icon/index.cjs +102 -27
- package/dist/cjs/fields/Icon/index.native.js +115 -31
- package/dist/cjs/fields/Icon/index.native.js.map +1 -1
- package/dist/cjs/fields/Input/index.cjs +5 -12
- package/dist/cjs/fields/Input/index.native.js +5 -13
- package/dist/cjs/fields/Input/index.native.js.map +1 -1
- package/dist/cjs/fields/PhoneInput/index.cjs +2 -2
- package/dist/cjs/fields/PhoneInput/index.native.js +2 -2
- package/dist/cjs/fields/PhoneInput/index.native.js.map +1 -1
- package/dist/cjs/fields/SearchInput/index.cjs +8 -9
- package/dist/cjs/fields/SearchInput/index.native.js +8 -9
- package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/index.cjs +53 -18
- package/dist/cjs/fields/Select/index.native.js +63 -37
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/Stepper/index.cjs +144 -31
- package/dist/cjs/fields/Stepper/index.native.js +151 -31
- package/dist/cjs/fields/Stepper/index.native.js.map +1 -1
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.native.js +2 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/shared/focusManagement.cjs +24 -11
- package/dist/cjs/shared/focusManagement.native.js +24 -11
- package/dist/cjs/shared/focusManagement.native.js.map +1 -1
- package/dist/cjs/shared/pickerTriggerContract.cjs +38 -0
- package/dist/cjs/shared/pickerTriggerContract.native.js +41 -0
- package/dist/cjs/shared/pickerTriggerContract.native.js.map +1 -0
- package/dist/cjs/shared/pressSlopProps.cjs +68 -0
- package/dist/cjs/shared/pressSlopProps.native.js +72 -0
- package/dist/cjs/shared/pressSlopProps.native.js.map +1 -0
- package/dist/esm/AdaptivePopup/index.native.js.map +1 -1
- package/dist/esm/Button/index.mjs +1 -34
- package/dist/esm/Button/index.mjs.map +1 -1
- package/dist/esm/Button/index.native.js +1 -34
- package/dist/esm/Button/index.native.js.map +1 -1
- package/dist/esm/Chip/index.mjs +1 -1
- package/dist/esm/Chip/index.mjs.map +1 -1
- package/dist/esm/Chip/index.native.js +1 -1
- package/dist/esm/Chip/index.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/clientKnownIdentity.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/commitImmediateField.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/index.mjs +17 -10
- package/dist/esm/ContextualSaveBar/index.mjs.map +1 -1
- package/dist/esm/ContextualSaveBar/index.native.js +18 -10
- package/dist/esm/ContextualSaveBar/index.native.js.map +1 -1
- package/dist/esm/ContextualSaveBar/useUnsavedChangesGuard.native.js.map +1 -1
- package/dist/esm/ControlGroup/index.native.js.map +1 -1
- package/dist/esm/DescriptionList/index.native.js.map +1 -1
- package/dist/esm/ErrorSummary.native.js.map +1 -1
- package/dist/esm/FieldDisplay/editMode.native.js.map +1 -1
- package/dist/esm/FieldDisplay/formatters.native.js.map +1 -1
- package/dist/esm/FieldDisplay/index.native.js.map +1 -1
- package/dist/esm/FieldGroup.native.js.map +1 -1
- package/dist/esm/FloatingPanel/index.mjs +58 -15
- package/dist/esm/FloatingPanel/index.mjs.map +1 -1
- package/dist/esm/FloatingPanel/index.native.js +15 -8
- package/dist/esm/FloatingPanel/index.native.js.map +1 -1
- package/dist/esm/FloatingPanel/nestedAction.mjs +11 -0
- package/dist/esm/FloatingPanel/nestedAction.mjs.map +1 -0
- package/dist/esm/FloatingPanel/nestedAction.native.js +13 -0
- package/dist/esm/FloatingPanel/nestedAction.native.js.map +1 -0
- package/dist/esm/FloatingPanel/useFloatingPanel.native.js.map +1 -1
- package/dist/esm/Form/index.native.js.map +1 -1
- package/dist/esm/Form/validateOn.native.js.map +1 -1
- package/dist/esm/FormGrid.native.js.map +1 -1
- package/dist/esm/FormSection.native.js.map +1 -1
- package/dist/esm/InputParts/index.mjs +12 -8
- package/dist/esm/InputParts/index.mjs.map +1 -1
- package/dist/esm/InputParts/index.native.js +13 -11
- package/dist/esm/InputParts/index.native.js.map +1 -1
- package/dist/esm/Label/index.native.js.map +1 -1
- package/dist/esm/Skeleton/index.native.js.map +1 -1
- package/dist/esm/Spinner/SpinnerGlyph.native.js.map +1 -1
- package/dist/esm/Spinner/spinnerSize.native.js.map +1 -1
- package/dist/esm/Table/index.native.js.map +1 -1
- package/dist/esm/Wheel/haptic.native.js.map +1 -1
- package/dist/esm/Wheel/index.mjs +3 -3
- package/dist/esm/Wheel/index.mjs.map +1 -1
- package/dist/esm/Wheel/index.native.js +3 -3
- package/dist/esm/Wheel/index.native.js.map +1 -1
- package/dist/esm/actionLabel.native.js.map +1 -1
- package/dist/esm/fieldDefaults.native.js.map +1 -1
- package/dist/esm/fieldLayout.mjs +3 -3
- package/dist/esm/fieldLayout.mjs.map +1 -1
- package/dist/esm/fieldLayout.native.js +3 -3
- package/dist/esm/fieldLayout.native.js.map +1 -1
- package/dist/esm/fields/Barcode/BarcodePreview.native.js.map +1 -1
- package/dist/esm/fields/Barcode/code128.native.js.map +1 -1
- package/dist/esm/fields/Barcode/index.native.js.map +1 -1
- package/dist/esm/fields/Barcode/qr.native.js.map +1 -1
- package/dist/esm/fields/Barcode/scannerTypes.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/Checkbox.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxBox.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxCard.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxFieldFrame.mjs +8 -1
- package/dist/esm/fields/Checkbox/CheckboxFieldFrame.mjs.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
- package/dist/esm/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/checkboxGroupContext.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/index.native.js.map +1 -1
- package/dist/esm/fields/ColorPicker/index.native.js.map +1 -1
- package/dist/esm/fields/ColorPicker/parts.native.js.map +1 -1
- package/dist/esm/fields/Combobox/authorOptions.native.js.map +1 -1
- package/dist/esm/fields/Combobox/index.mjs +74 -76
- package/dist/esm/fields/Combobox/index.mjs.map +1 -1
- package/dist/esm/fields/Combobox/index.native.js +78 -86
- package/dist/esm/fields/Combobox/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/Calendar.mjs +6 -1
- package/dist/esm/fields/DatePicker/Calendar.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/Calendar.native.js +6 -1
- package/dist/esm/fields/DatePicker/Calendar.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.mjs +2 -2
- package/dist/esm/fields/DatePicker/DateRangePicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js +2 -2
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs +15 -12
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.native.js +39 -14
- package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/MonthPicker.mjs +10 -3
- package/dist/esm/fields/DatePicker/MonthPicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/MonthPicker.native.js +10 -3
- package/dist/esm/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/MultiDatePicker.mjs +2 -2
- package/dist/esm/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/MultiDatePicker.native.js +2 -2
- package/dist/esm/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/catalog.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/fieldValueSync.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/index.native.js +3 -0
- package/dist/esm/fields/DatePicker/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/parts.mjs +28 -16
- package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/parts.native.js +30 -16
- package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/utils.native.js.map +1 -1
- package/dist/esm/fields/Duration/durationMath.native.js.map +1 -1
- package/dist/esm/fields/Duration/index.native.js.map +1 -1
- package/dist/esm/fields/FileUpload/filePickerTypes.native.js.map +1 -1
- package/dist/esm/fields/FileUpload/index.native.js.map +1 -1
- package/dist/esm/fields/FileUpload/nativePickerLoader.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/GeolocationMap.mjs.map +1 -1
- package/dist/esm/fields/Geolocation/GeolocationMap.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/expoMapsLoader.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/geoValue.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/geocoder.mjs +33 -0
- package/dist/esm/fields/Geolocation/geocoder.mjs.map +1 -0
- package/dist/esm/fields/Geolocation/geocoder.native.js +35 -0
- package/dist/esm/fields/Geolocation/geocoder.native.js.map +1 -0
- package/dist/esm/fields/Geolocation/index.mjs +792 -149
- package/dist/esm/fields/Geolocation/index.mjs.map +1 -1
- package/dist/esm/fields/Geolocation/index.native.js +847 -164
- package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/mapMath.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/mapTypes.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/nativeSearchFocus.mjs +19 -0
- package/dist/esm/fields/Geolocation/nativeSearchFocus.mjs.map +1 -0
- package/dist/esm/fields/Geolocation/nativeSearchFocus.native.js +19 -0
- package/dist/esm/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
- package/dist/esm/fields/Icon/drawnSet.mjs +14 -3
- package/dist/esm/fields/Icon/drawnSet.mjs.map +1 -1
- package/dist/esm/fields/Icon/drawnSet.native.js +18 -3
- package/dist/esm/fields/Icon/drawnSet.native.js.map +1 -1
- package/dist/esm/fields/Icon/index.mjs +93 -18
- package/dist/esm/fields/Icon/index.mjs.map +1 -1
- package/dist/esm/fields/Icon/index.native.js +106 -22
- package/dist/esm/fields/Icon/index.native.js.map +1 -1
- package/dist/esm/fields/ImageField/index.native.js.map +1 -1
- package/dist/esm/fields/Input/index.mjs +5 -12
- package/dist/esm/fields/Input/index.mjs.map +1 -1
- package/dist/esm/fields/Input/index.native.js +5 -13
- package/dist/esm/fields/Input/index.native.js.map +1 -1
- package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
- package/dist/esm/fields/OTPInput/index.native.js.map +1 -1
- package/dist/esm/fields/OTPInput/otpCellCss.native.js.map +1 -1
- package/dist/esm/fields/PhoneInput/dialCodes.native.js.map +1 -1
- package/dist/esm/fields/PhoneInput/index.mjs +2 -2
- package/dist/esm/fields/PhoneInput/index.mjs.map +1 -1
- package/dist/esm/fields/PhoneInput/index.native.js +2 -2
- package/dist/esm/fields/PhoneInput/index.native.js.map +1 -1
- package/dist/esm/fields/PhoneInput/phone.native.js.map +1 -1
- package/dist/esm/fields/Progress/index.native.js.map +1 -1
- package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/esm/fields/Rating/index.native.js.map +1 -1
- package/dist/esm/fields/Rating/ratingMath.native.js.map +1 -1
- package/dist/esm/fields/Rating/types.native.js.map +1 -1
- package/dist/esm/fields/SearchInput/index.mjs +9 -10
- package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
- package/dist/esm/fields/SearchInput/index.native.js +9 -10
- package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
- package/dist/esm/fields/Select/index.mjs +54 -19
- package/dist/esm/fields/Select/index.mjs.map +1 -1
- package/dist/esm/fields/Select/index.native.js +64 -38
- package/dist/esm/fields/Select/index.native.js.map +1 -1
- package/dist/esm/fields/Signature/index.native.js.map +1 -1
- package/dist/esm/fields/Slider/index.native.js.map +1 -1
- package/dist/esm/fields/Slider/jumpMotion.native.js.map +1 -1
- package/dist/esm/fields/Stepper/index.mjs +145 -32
- package/dist/esm/fields/Stepper/index.mjs.map +1 -1
- package/dist/esm/fields/Stepper/index.native.js +152 -32
- package/dist/esm/fields/Stepper/index.native.js.map +1 -1
- package/dist/esm/fields/Stepper/resolveStepperPlacement.native.js.map +1 -1
- package/dist/esm/fields/Switch/index.native.js.map +1 -1
- package/dist/esm/fields/TextArea/index.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/catalog.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/esm/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
- package/dist/esm/fields/TimeRangeScrubber/index.native.js.map +1 -1
- package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -1
- package/dist/esm/fields/nativeSelect.native.js.map +1 -1
- package/dist/esm/fields/selectedOrder.native.js.map +1 -1
- package/dist/esm/formSpacing.native.js.map +1 -1
- package/dist/esm/hooks/useFocusManagement.native.js.map +1 -1
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/requiredMarking.native.js.map +1 -1
- package/dist/esm/shared/TimeColumn.native.js.map +1 -1
- package/dist/esm/shared/capabilityPreflight.native.js.map +1 -1
- package/dist/esm/shared/colorRamps.native.js.map +1 -1
- package/dist/esm/shared/devWarn.native.js.map +1 -1
- package/dist/esm/shared/floatingList.native.js.map +1 -1
- package/dist/esm/shared/focusManagement.mjs +24 -11
- package/dist/esm/shared/focusManagement.mjs.map +1 -1
- package/dist/esm/shared/focusManagement.native.js +24 -11
- package/dist/esm/shared/focusManagement.native.js.map +1 -1
- package/dist/esm/shared/groupContext.native.js.map +1 -1
- package/dist/esm/shared/i18n.native.js.map +1 -1
- package/dist/esm/shared/pickerTriggerContract.mjs +13 -0
- package/dist/esm/shared/pickerTriggerContract.mjs.map +1 -0
- package/dist/esm/shared/pickerTriggerContract.native.js +13 -0
- package/dist/esm/shared/pickerTriggerContract.native.js.map +1 -0
- package/dist/esm/shared/pressSlopProps.mjs +43 -0
- package/dist/esm/shared/pressSlopProps.mjs.map +1 -0
- package/dist/esm/shared/pressSlopProps.native.js +44 -0
- package/dist/esm/shared/pressSlopProps.native.js.map +1 -0
- package/dist/esm/shared/t.native.js.map +1 -1
- package/dist/esm/shared/tableCellContext.native.js.map +1 -1
- package/dist/esm/shared/useDragScroll.native.js.map +1 -1
- package/dist/esm/shared/useKeyboardInset.native.js.map +1 -1
- package/dist/esm/shared/useSheetEscapeDismiss.native.js.map +1 -1
- package/dist/esm/shared/useWheelIncrement.native.js.map +1 -1
- package/dist/esm/shared/utils.native.js.map +1 -1
- package/dist/esm/shared/zIndex.native.js.map +1 -1
- package/dist/esm/themedPrimitives.native.js.map +1 -1
- package/dist/esm/types.native.js.map +1 -1
- package/dist/esm/utils/LinkCell.native.js.map +1 -1
- package/dist/jsx/Button/index.mjs +1 -34
- package/dist/jsx/Button/index.mjs.map +1 -1
- package/dist/jsx/Button/index.native.js +3 -36
- package/dist/jsx/Button/index.native.js.map +1 -1
- package/dist/jsx/Chip/index.mjs +1 -1
- package/dist/jsx/Chip/index.mjs.map +1 -1
- package/dist/jsx/Chip/index.native.js +1 -1
- package/dist/jsx/Chip/index.native.js.map +1 -1
- package/dist/jsx/ContextualSaveBar/index.mjs +17 -10
- package/dist/jsx/ContextualSaveBar/index.mjs.map +1 -1
- package/dist/jsx/ContextualSaveBar/index.native.js +18 -10
- package/dist/jsx/ContextualSaveBar/index.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/index.mjs +58 -15
- package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/index.native.js +16 -7
- package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/nestedAction.mjs +11 -0
- package/dist/jsx/FloatingPanel/nestedAction.mjs.map +1 -0
- package/dist/jsx/FloatingPanel/nestedAction.native.js +42 -0
- package/dist/jsx/FloatingPanel/nestedAction.native.js.map +1 -0
- package/dist/jsx/InputParts/index.mjs +12 -8
- package/dist/jsx/InputParts/index.mjs.map +1 -1
- package/dist/jsx/InputParts/index.native.js +12 -10
- package/dist/jsx/InputParts/index.native.js.map +1 -1
- package/dist/jsx/Wheel/index.mjs +3 -3
- package/dist/jsx/Wheel/index.mjs.map +1 -1
- package/dist/jsx/Wheel/index.native.js +3 -3
- package/dist/jsx/Wheel/index.native.js.map +1 -1
- package/dist/jsx/fieldLayout.mjs +3 -3
- package/dist/jsx/fieldLayout.mjs.map +1 -1
- package/dist/jsx/fieldLayout.native.js +3 -3
- package/dist/jsx/fieldLayout.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.mjs +8 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.mjs.map +1 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
- package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
- package/dist/jsx/fields/Combobox/index.mjs +74 -76
- package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
- package/dist/jsx/fields/Combobox/index.native.js +78 -86
- package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/Calendar.mjs +6 -1
- package/dist/jsx/fields/DatePicker/Calendar.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/Calendar.native.js +6 -1
- package/dist/jsx/fields/DatePicker/Calendar.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DateRangePicker.mjs +2 -2
- package/dist/jsx/fields/DatePicker/DateRangePicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/DateRangePicker.native.js +2 -2
- package/dist/jsx/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs +15 -12
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +39 -14
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/MonthPicker.mjs +10 -3
- package/dist/jsx/fields/DatePicker/MonthPicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/MonthPicker.native.js +10 -3
- package/dist/jsx/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs +2 -2
- package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js +2 -2
- package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/index.native.js +3 -0
- package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.mjs +28 -16
- package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.native.js +28 -14
- package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/GeolocationMap.mjs.map +1 -1
- package/dist/jsx/fields/Geolocation/GeolocationMap.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/geocoder.mjs +33 -0
- package/dist/jsx/fields/Geolocation/geocoder.mjs.map +1 -0
- package/dist/jsx/fields/Geolocation/geocoder.native.js +68 -0
- package/dist/jsx/fields/Geolocation/geocoder.native.js.map +1 -0
- package/dist/jsx/fields/Geolocation/index.mjs +792 -149
- package/dist/jsx/fields/Geolocation/index.mjs.map +1 -1
- package/dist/jsx/fields/Geolocation/index.native.js +856 -167
- package/dist/jsx/fields/Geolocation/index.native.js.map +1 -1
- package/dist/jsx/fields/Geolocation/nativeSearchFocus.mjs +19 -0
- package/dist/jsx/fields/Geolocation/nativeSearchFocus.mjs.map +1 -0
- package/dist/jsx/fields/Geolocation/nativeSearchFocus.native.js +47 -0
- package/dist/jsx/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
- package/dist/jsx/fields/Icon/drawnSet.mjs +14 -3
- package/dist/jsx/fields/Icon/drawnSet.mjs.map +1 -1
- package/dist/jsx/fields/Icon/drawnSet.native.js +18 -3
- package/dist/jsx/fields/Icon/drawnSet.native.js.map +1 -1
- package/dist/jsx/fields/Icon/index.mjs +93 -18
- package/dist/jsx/fields/Icon/index.mjs.map +1 -1
- package/dist/jsx/fields/Icon/index.native.js +115 -31
- package/dist/jsx/fields/Icon/index.native.js.map +1 -1
- package/dist/jsx/fields/Input/index.mjs +5 -12
- package/dist/jsx/fields/Input/index.mjs.map +1 -1
- package/dist/jsx/fields/Input/index.native.js +5 -13
- package/dist/jsx/fields/Input/index.native.js.map +1 -1
- package/dist/jsx/fields/PhoneInput/index.mjs +2 -2
- package/dist/jsx/fields/PhoneInput/index.mjs.map +1 -1
- package/dist/jsx/fields/PhoneInput/index.native.js +2 -2
- package/dist/jsx/fields/PhoneInput/index.native.js.map +1 -1
- package/dist/jsx/fields/SearchInput/index.mjs +9 -10
- package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
- package/dist/jsx/fields/SearchInput/index.native.js +8 -9
- package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/index.mjs +54 -19
- package/dist/jsx/fields/Select/index.mjs.map +1 -1
- package/dist/jsx/fields/Select/index.native.js +63 -37
- package/dist/jsx/fields/Select/index.native.js.map +1 -1
- package/dist/jsx/fields/Stepper/index.mjs +145 -32
- package/dist/jsx/fields/Stepper/index.mjs.map +1 -1
- package/dist/jsx/fields/Stepper/index.native.js +151 -31
- package/dist/jsx/fields/Stepper/index.native.js.map +1 -1
- package/dist/jsx/index.js +2 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +2 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +2 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/shared/focusManagement.mjs +24 -11
- package/dist/jsx/shared/focusManagement.mjs.map +1 -1
- package/dist/jsx/shared/focusManagement.native.js +24 -11
- package/dist/jsx/shared/focusManagement.native.js.map +1 -1
- package/dist/jsx/shared/pickerTriggerContract.mjs +13 -0
- package/dist/jsx/shared/pickerTriggerContract.mjs.map +1 -0
- package/dist/jsx/shared/pickerTriggerContract.native.js +41 -0
- package/dist/jsx/shared/pickerTriggerContract.native.js.map +1 -0
- package/dist/jsx/shared/pressSlopProps.mjs +43 -0
- package/dist/jsx/shared/pressSlopProps.mjs.map +1 -0
- package/dist/jsx/shared/pressSlopProps.native.js +72 -0
- package/dist/jsx/shared/pressSlopProps.native.js.map +1 -0
- package/package.json +8 -7
- package/src/Button/Button.labelInk.spec.tsx +21 -18
- package/src/Button/Button.outlinedChannel.spec.tsx +46 -0
- package/src/Button/Button.sizeLadder.spec.tsx +4 -3
- package/src/Button/Button.stories.tsx +20 -0
- package/src/Button/index.tsx +26 -39
- package/src/Chip/Chip.spec.tsx +3 -1
- package/src/Chip/index.tsx +1 -5
- package/src/ContextualSaveBar/ContextualSaveBar.spec.tsx +33 -0
- package/src/ContextualSaveBar/ContextualSaveBar.stories.tsx +19 -0
- package/src/ContextualSaveBar/index.tsx +12 -8
- package/src/ContextualSaveBar/nativeFlow.spec.tsx +20 -0
- package/src/FieldLayout.stories.tsx +41 -0
- package/src/FloatingPanel/FloatingPanel.native.spec.tsx +54 -0
- package/src/FloatingPanel/FloatingPanel.spec.tsx +109 -0
- package/src/FloatingPanel/index.native.tsx +24 -7
- package/src/FloatingPanel/index.tsx +80 -13
- package/src/FloatingPanel/nestedAction.spec.ts +36 -0
- package/src/FloatingPanel/nestedAction.ts +15 -0
- package/src/FloatingPanel/panelWidthContract.spec.ts +12 -15
- package/src/FormsIntegration.stories.tsx +2 -6
- package/src/InputParts/index.tsx +20 -6
- package/src/InputParts/layoutGap.spec.tsx +43 -0
- package/src/Wheel/Wheel.spec.tsx +16 -0
- package/src/Wheel/index.tsx +3 -3
- package/src/fieldLayout.spec.tsx +42 -1
- package/src/fieldLayout.tsx +9 -9
- package/src/fields/Checkbox/CheckboxFieldFrame.spec.tsx +18 -0
- package/src/fields/Checkbox/CheckboxFieldFrame.tsx +6 -1
- package/src/fields/Combobox/Combobox.spec.tsx +48 -1
- package/src/fields/Combobox/index.tsx +90 -80
- package/src/fields/DatePicker/Calendar.tsx +4 -1
- package/src/fields/DatePicker/DatePicker.stories.tsx +22 -1
- package/src/fields/DatePicker/DateRangePicker.tsx +4 -2
- package/src/fields/DatePicker/DatetimePicker.catalog.tsx +21 -19
- package/src/fields/DatePicker/DatetimePicker.native.spec.tsx +144 -0
- package/src/fields/DatePicker/DatetimePicker.native.tsx +57 -32
- package/src/fields/DatePicker/DatetimePicker.stories.tsx +22 -0
- package/src/fields/DatePicker/MonthPicker.tsx +8 -3
- package/src/fields/DatePicker/MultiDatePicker.tsx +4 -2
- package/src/fields/DatePicker/index.native.tsx +1 -0
- package/src/fields/DatePicker/parts.spec.tsx +56 -0
- package/src/fields/DatePicker/parts.tsx +33 -12
- package/src/fields/Geolocation/Geolocation.spec.tsx +287 -35
- package/src/fields/Geolocation/Geolocation.stories.tsx +141 -7
- package/src/fields/Geolocation/GeolocationMap.native.tsx +3 -0
- package/src/fields/Geolocation/GeolocationMap.tsx +4 -0
- package/src/fields/Geolocation/geocoder.spec.ts +59 -0
- package/src/fields/Geolocation/geocoder.ts +84 -0
- package/src/fields/Geolocation/geocoderSeam.spec.tsx +203 -0
- package/src/fields/Geolocation/index.tsx +912 -180
- package/src/fields/Geolocation/nativeSearchFocus.spec.ts +34 -0
- package/src/fields/Geolocation/nativeSearchFocus.ts +19 -0
- package/src/fields/Geolocation/salvage.spec.tsx +398 -0
- package/src/fields/Geolocation/storyProviders.spec.tsx +44 -0
- package/src/fields/Icon/Icon.spec.tsx +215 -1
- package/src/fields/Icon/Icon.stories.tsx +9 -1
- package/src/fields/Icon/drawnSet.tsx +39 -4
- package/src/fields/Icon/index.tsx +118 -18
- package/src/fields/Input/Input.copy.spec.tsx +1 -0
- package/src/fields/Input/Input.spec.tsx +50 -0
- package/src/fields/Input/Input.stories.tsx +1 -1
- package/src/fields/Input/index.tsx +7 -13
- package/src/fields/PhoneInput/index.tsx +2 -2
- package/src/fields/SearchInput/SearchInput.spec.tsx +14 -0
- package/src/fields/SearchInput/index.tsx +5 -6
- package/src/fields/Select/Select.spec.tsx +54 -0
- package/src/fields/Select/index.tsx +63 -33
- package/src/fields/Stepper/Stepper.spec.tsx +34 -1
- package/src/fields/Stepper/index.tsx +193 -33
- package/src/fields/pickerActivation.spec.tsx +105 -0
- package/src/fields/pickerDensity.spec.tsx +86 -0
- package/src/fields/pickerRows.spec.tsx +66 -0
- package/src/index.ts +9 -0
- package/src/shared/focusManagement.spec.tsx +68 -0
- package/src/shared/focusManagement.ts +20 -10
- package/src/shared/pickerTriggerContract.ts +13 -0
- package/src/shared/pressSlopProps.spec.ts +39 -0
- package/src/shared/pressSlopProps.ts +52 -0
- package/types/Button/index.d.ts +22 -3
- package/types/Button/index.d.ts.map +1 -1
- package/types/Chip/index.d.ts.map +1 -1
- package/types/ContextualSaveBar/index.d.ts +1 -1
- package/types/ContextualSaveBar/index.d.ts.map +1 -1
- package/types/FloatingPanel/index.d.ts +11 -1
- package/types/FloatingPanel/index.d.ts.map +1 -1
- package/types/FloatingPanel/index.native.d.ts +2 -1
- package/types/FloatingPanel/index.native.d.ts.map +1 -1
- package/types/FloatingPanel/nestedAction.d.ts +13 -0
- package/types/FloatingPanel/nestedAction.d.ts.map +1 -0
- package/types/InputParts/index.d.ts.map +1 -1
- package/types/fields/Checkbox/CheckboxFieldFrame.d.ts +46 -2
- package/types/fields/Checkbox/CheckboxFieldFrame.d.ts.map +1 -1
- package/types/fields/Checkbox/index.d.ts +3 -3
- package/types/fields/Combobox/index.d.ts +3 -1
- package/types/fields/Combobox/index.d.ts.map +1 -1
- package/types/fields/DatePicker/Calendar.d.ts.map +1 -1
- package/types/fields/DatePicker/DateRangePicker.d.ts.map +1 -1
- package/types/fields/DatePicker/DatetimePicker.catalog.d.ts.map +1 -1
- package/types/fields/DatePicker/DatetimePicker.native.d.ts.map +1 -1
- package/types/fields/DatePicker/MonthPicker.d.ts.map +1 -1
- package/types/fields/DatePicker/MultiDatePicker.d.ts.map +1 -1
- package/types/fields/DatePicker/index.native.d.ts.map +1 -1
- package/types/fields/DatePicker/parts.d.ts.map +1 -1
- package/types/fields/Geolocation/GeolocationMap.d.ts +4 -0
- package/types/fields/Geolocation/GeolocationMap.d.ts.map +1 -1
- package/types/fields/Geolocation/GeolocationMap.native.d.ts +3 -0
- package/types/fields/Geolocation/GeolocationMap.native.d.ts.map +1 -1
- package/types/fields/Geolocation/geocoder.d.ts +53 -0
- package/types/fields/Geolocation/geocoder.d.ts.map +1 -0
- package/types/fields/Geolocation/index.d.ts +18 -2
- package/types/fields/Geolocation/index.d.ts.map +1 -1
- package/types/fields/Geolocation/nativeSearchFocus.d.ts +8 -0
- package/types/fields/Geolocation/nativeSearchFocus.d.ts.map +1 -0
- package/types/fields/Icon/drawnSet.d.ts.map +1 -1
- package/types/fields/Icon/index.d.ts.map +1 -1
- package/types/fields/Input/index.d.ts.map +1 -1
- package/types/fields/PhoneInput/index.d.ts.map +1 -1
- package/types/fields/RadioGroup/index.d.ts +2 -2
- package/types/fields/SearchInput/index.d.ts.map +1 -1
- package/types/fields/Select/index.d.ts.map +1 -1
- package/types/fields/Stepper/index.d.ts.map +1 -1
- package/types/fields/ToggleGroup/index.d.ts +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/shared/focusManagement.d.ts +2 -2
- package/types/shared/focusManagement.d.ts.map +1 -1
- package/types/shared/pickerTriggerContract.d.ts +18 -0
- package/types/shared/pickerTriggerContract.d.ts.map +1 -0
- package/types/shared/pressSlopProps.d.ts +8 -0
- package/types/shared/pressSlopProps.d.ts.map +1 -0
- package/src/router.d.ts +0 -16
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
clampLat,
|
|
4
|
+
clampLng,
|
|
5
|
+
formatCoordPair,
|
|
6
|
+
formatPlace,
|
|
7
|
+
parseLatLngPair,
|
|
8
|
+
resolveGeocoder,
|
|
9
|
+
} from "./geocoder";
|
|
10
|
+
|
|
11
|
+
import { parseGeoValue, formatGeoValue } from "./geoValue";
|
|
12
|
+
|
|
13
|
+
describe("geocoder seam helpers", () => {
|
|
14
|
+
it("parses and serializes the lat/lng JSON value", () => {
|
|
15
|
+
expect(parseGeoValue(undefined)).toBeNull();
|
|
16
|
+
expect(parseGeoValue("")).toBeNull();
|
|
17
|
+
expect(parseGeoValue("{")).toBeNull();
|
|
18
|
+
expect(parseGeoValue(JSON.stringify({ lat: 60.16952, lng: 24.93545 }))).toEqual({
|
|
19
|
+
lat: 60.16952,
|
|
20
|
+
lng: 24.93545,
|
|
21
|
+
});
|
|
22
|
+
expect(formatGeoValue({ lat: clampLat(91), lng: clampLng(200) }, "latlng")).toBe(
|
|
23
|
+
JSON.stringify({ lat: 90, lng: 180 }),
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("formats the subordinate pair at five decimals", () => {
|
|
28
|
+
expect(formatCoordPair(60.16952, 24.93545)).toBe("60.16952, 24.93545");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("parses a typed lat, lng pair and rejects out-of-range", () => {
|
|
32
|
+
expect(parseLatLngPair("60.169, 24.935")).toEqual({ lat: 60.169, lng: 24.935 });
|
|
33
|
+
expect(parseLatLngPair(" -33.8, 151.2 ")).toEqual({ lat: -33.8, lng: 151.2 });
|
|
34
|
+
expect(parseLatLngPair("mannerheim")).toBeNull();
|
|
35
|
+
expect(parseLatLngPair("91, 0")).toBeNull();
|
|
36
|
+
expect(parseLatLngPair("0, 200")).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("clamps latitude and longitude", () => {
|
|
40
|
+
expect(clampLat(100)).toBe(90);
|
|
41
|
+
expect(clampLng(-200)).toBe(-180);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("joins a described place for the input face", () => {
|
|
45
|
+
expect(formatPlace({ label: "Mannerheimintie 3", description: "00100 Helsinki" })).toBe(
|
|
46
|
+
"Mannerheimintie 3, 00100 Helsinki",
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("resolveGeocoder prefers explicit props over a geocoder object", () => {
|
|
51
|
+
const geocode = vi.fn();
|
|
52
|
+
const reverseGeocode = vi.fn();
|
|
53
|
+
const other = { geocode: vi.fn(), reverseGeocode: vi.fn() };
|
|
54
|
+
const resolved = resolveGeocoder({ geocode, reverseGeocode, geocoder: other });
|
|
55
|
+
expect(resolved.geocode).toBe(geocode);
|
|
56
|
+
expect(resolved.reverseGeocode).toBe(reverseGeocode);
|
|
57
|
+
expect(resolveGeocoder({}).geocode).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Geolocation geocoder seam (R4 / MPO-54).
|
|
3
|
+
*
|
|
4
|
+
* The field never holds provider credentials and never wires a default
|
|
5
|
+
* network provider. Consumers inject `geocode` / `reverseGeocode` (or a
|
|
6
|
+
* `Geocoder` object) and the field calls only what it was handed. With no
|
|
7
|
+
* geocoder injected, search is disabled and the map / locate / coordinate
|
|
8
|
+
* paths stay intact — the package never reaches a third party the consumer
|
|
9
|
+
* did not choose.
|
|
10
|
+
*
|
|
11
|
+
* This file is the seam and nothing else: no provider, no endpoint, no
|
|
12
|
+
* transport. A provider is whatever a consumer writes against `Geocoder` —
|
|
13
|
+
* an offline gazetteer, their own backend proxy holding a commercial key, or
|
|
14
|
+
* a self-hosted geocoder. See `geocoderSeam.spec.tsx` for both shapes.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { GeoValue } from "./geoValue";
|
|
18
|
+
|
|
19
|
+
export interface GeocodeResult {
|
|
20
|
+
lat: number;
|
|
21
|
+
lng: number;
|
|
22
|
+
/** Primary line — the place name. */
|
|
23
|
+
label: string;
|
|
24
|
+
/** Secondary line — locality / region. Omitted for a bare coordinate. */
|
|
25
|
+
description?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface GeocodeQuery {
|
|
29
|
+
query: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ReverseGeocodeQuery {
|
|
33
|
+
lat: number;
|
|
34
|
+
lng: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type GeocodeFn = (query: GeocodeQuery) => Promise<GeocodeResult[]>;
|
|
38
|
+
export type ReverseGeocodeFn = (query: ReverseGeocodeQuery) => Promise<GeocodeResult | null>;
|
|
39
|
+
|
|
40
|
+
export interface Geocoder {
|
|
41
|
+
geocode: GeocodeFn;
|
|
42
|
+
reverseGeocode: ReverseGeocodeFn;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const LAT_LNG_PAIR = /^\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*$/;
|
|
46
|
+
|
|
47
|
+
export function clampLat(val: number): number {
|
|
48
|
+
return Math.max(-90, Math.min(90, val));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function clampLng(val: number): number {
|
|
52
|
+
return Math.max(-180, Math.min(180, val));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Quiet mono disclosure / cell fallback — five decimals, board media-13. */
|
|
56
|
+
export function formatCoordPair(lat: number, lng: number): string {
|
|
57
|
+
return `${lat.toFixed(5)}, ${lng.toFixed(5)}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Expert path through the same search input: a typed `lat, lng` pair. */
|
|
61
|
+
export function parseLatLngPair(text: string): GeoValue | null {
|
|
62
|
+
const match = LAT_LNG_PAIR.exec(text);
|
|
63
|
+
if (!match) return null;
|
|
64
|
+
const lat = Number.parseFloat(match[1]);
|
|
65
|
+
const lng = Number.parseFloat(match[2]);
|
|
66
|
+
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
|
|
67
|
+
if (lat < -90 || lat > 90 || lng < -180 || lng > 180) return null;
|
|
68
|
+
return { lat, lng };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function formatPlace(result: Pick<GeocodeResult, "label" | "description">): string {
|
|
72
|
+
return result.description ? `${result.label}, ${result.description}` : result.label;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function resolveGeocoder(input: {
|
|
76
|
+
geocode?: GeocodeFn;
|
|
77
|
+
reverseGeocode?: ReverseGeocodeFn;
|
|
78
|
+
geocoder?: Geocoder;
|
|
79
|
+
}): { geocode?: GeocodeFn; reverseGeocode?: ReverseGeocodeFn } {
|
|
80
|
+
return {
|
|
81
|
+
geocode: input.geocode ?? input.geocoder?.geocode,
|
|
82
|
+
reverseGeocode: input.reverseGeocode ?? input.geocoder?.reverseGeocode,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R4 candidate A evidence — the seam alone is sufficient.
|
|
3
|
+
*
|
|
4
|
+
* Nothing here imports `createNominatimGeocoder`. Every provider in this file
|
|
5
|
+
* is written by hand the way a consumer would write one, typed only against
|
|
6
|
+
* the exported `Geocoder` / `GeocodeFn` / `ReverseGeocodeFn` contract. If this
|
|
7
|
+
* file is green with the adapter deleted from the package, candidate A ships.
|
|
8
|
+
*
|
|
9
|
+
* The two shapes a real consumer actually has:
|
|
10
|
+
* 1. a static/offline provider (no network at all)
|
|
11
|
+
* 2. a backend-proxy provider (the key lives on the consumer's server and
|
|
12
|
+
* never reaches the client — the only shape a KEYED provider can take
|
|
13
|
+
* in a component that must not hold credentials)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { describe, expect, it, vi } from "vitest";
|
|
17
|
+
import { fireEvent, waitFor } from "@testing-library/react";
|
|
18
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
19
|
+
import { Geolocation } from "./index";
|
|
20
|
+
import type { GeocodeResult, Geocoder } from "./geocoder";
|
|
21
|
+
|
|
22
|
+
const HELSINKI = JSON.stringify({ lat: 60.16952, lng: 24.93545 });
|
|
23
|
+
const SYDNEY = JSON.stringify({ lat: -33.8688, lng: 151.2093 });
|
|
24
|
+
|
|
25
|
+
function searchInput(container: HTMLElement) {
|
|
26
|
+
return (container.querySelector("[data-testid='geolocation-search']") ??
|
|
27
|
+
container.querySelector("[aria-label='Search for a location']")) as HTMLInputElement | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function typeSearch(container: HTMLElement, text: string) {
|
|
31
|
+
const input = searchInput(container);
|
|
32
|
+
expect(input).not.toBeNull();
|
|
33
|
+
fireEvent.change(input as HTMLInputElement, { target: { value: text } });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Consumer provider #1 — offline gazetteer. No network, no key, no adapter.
|
|
38
|
+
* This is the whole implementation; it is what candidate A asks a consumer to
|
|
39
|
+
* write, and it is 14 lines.
|
|
40
|
+
*/
|
|
41
|
+
const gazetteer: GeocodeResult[] = [
|
|
42
|
+
{ lat: 60.16952, lng: 24.93545, label: "Mannerheimintie 3", description: "Kamppi, Helsinki" },
|
|
43
|
+
{ lat: -33.8688, lng: 151.2093, label: "Sydney", description: "New South Wales, Australia" },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const offlineGeocoder = {
|
|
47
|
+
geocode: async ({ query }) =>
|
|
48
|
+
gazetteer.filter((place) => place.label.toLowerCase().includes(query.trim().toLowerCase())),
|
|
49
|
+
reverseGeocode: async ({ lat, lng }) =>
|
|
50
|
+
gazetteer.find(
|
|
51
|
+
(place) => Math.abs(place.lat - lat) < 0.01 && Math.abs(place.lng - lng) < 0.01,
|
|
52
|
+
) ?? null,
|
|
53
|
+
} satisfies Geocoder;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Consumer provider #2 — backend proxy. The consumer's own server holds the
|
|
57
|
+
* provider key; the component sees only `fetch`. This is the shape a keyed
|
|
58
|
+
* provider must take, and the reason the seam is the load-bearing half of R4
|
|
59
|
+
* under BOTH candidates.
|
|
60
|
+
*/
|
|
61
|
+
function createProxyGeocoder(options: {
|
|
62
|
+
endpoint: string;
|
|
63
|
+
fetch: typeof globalThis.fetch;
|
|
64
|
+
}): Geocoder {
|
|
65
|
+
const call = async (path: string, params: Record<string, string>): Promise<unknown> => {
|
|
66
|
+
const url = new URL(path, options.endpoint);
|
|
67
|
+
for (const [key, value] of Object.entries(params)) url.searchParams.set(key, value);
|
|
68
|
+
const response = await options.fetch(url.toString());
|
|
69
|
+
if (!response.ok) throw new Error(`proxy geocoder failed (${response.status})`);
|
|
70
|
+
return response.json();
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
geocode: async ({ query }) => (await call("search", { q: query })) as GeocodeResult[],
|
|
74
|
+
reverseGeocode: async ({ lat, lng }) =>
|
|
75
|
+
(await call("reverse", { lat: String(lat), lng: String(lng) })) as GeocodeResult | null,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
describe("R4 candidate A — a consumer-authored geocoder satisfies the seam", () => {
|
|
80
|
+
it("type-level: a hand-written object satisfies Geocoder with no package adapter", () => {
|
|
81
|
+
// `satisfies Geocoder` above is the compile-time assertion; this asserts the
|
|
82
|
+
// same contract at runtime so the evidence is not purely structural.
|
|
83
|
+
expect(typeof offlineGeocoder.geocode).toBe("function");
|
|
84
|
+
expect(typeof offlineGeocoder.reverseGeocode).toBe("function");
|
|
85
|
+
const proxy = createProxyGeocoder({ endpoint: "https://app.example/geo/", fetch: vi.fn() });
|
|
86
|
+
expect(typeof proxy.geocode).toBe("function");
|
|
87
|
+
expect(typeof proxy.reverseGeocode).toBe("function");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("offline provider drives the whole field: search, pick, value, address", async () => {
|
|
91
|
+
const onChange = vi.fn();
|
|
92
|
+
const result = renderWithProviders(
|
|
93
|
+
<Geolocation label="Location" geocoder={offlineGeocoder} onChange={onChange} />,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
typeSearch(result.container, "sydney");
|
|
97
|
+
await waitFor(() => {
|
|
98
|
+
expect(document.querySelector("[data-testid='geolocation-results']")).not.toBeNull();
|
|
99
|
+
expect(document.body.textContent).toContain("Sydney");
|
|
100
|
+
expect(document.body.textContent).toContain("New South Wales, Australia");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
fireEvent.click(document.querySelector("[data-testid='geolocation-result-0']") as Element);
|
|
104
|
+
await waitFor(() => {
|
|
105
|
+
expect(onChange).toHaveBeenCalledWith(SYDNEY);
|
|
106
|
+
});
|
|
107
|
+
expect(searchInput(result.container)?.value).toBe("Sydney, New South Wales, Australia");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("offline provider reverse-geocodes a set value into the address face", async () => {
|
|
111
|
+
const result = renderWithProviders(
|
|
112
|
+
<Geolocation label="Location" value={HELSINKI} geocoder={offlineGeocoder} />,
|
|
113
|
+
);
|
|
114
|
+
await waitFor(() => {
|
|
115
|
+
expect(searchInput(result.container)?.value).toBe("Mannerheimintie 3, Kamppi, Helsinki");
|
|
116
|
+
});
|
|
117
|
+
expect(result.container.textContent).toContain("60.16952, 24.93545");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("backend-proxy provider drives the same field through injected fetch only", async () => {
|
|
121
|
+
const fetchImpl = vi.fn(async (url: string) => {
|
|
122
|
+
const parsed = new URL(url);
|
|
123
|
+
if (parsed.pathname.endsWith("/search")) {
|
|
124
|
+
return {
|
|
125
|
+
ok: true,
|
|
126
|
+
json: async () => [
|
|
127
|
+
{
|
|
128
|
+
lat: 60.16952,
|
|
129
|
+
lng: 24.93545,
|
|
130
|
+
label: "Mannerheimintie 3",
|
|
131
|
+
description: "Kamppi, Helsinki",
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return { ok: true, json: async () => null };
|
|
137
|
+
});
|
|
138
|
+
const onChange = vi.fn();
|
|
139
|
+
const result = renderWithProviders(
|
|
140
|
+
<Geolocation
|
|
141
|
+
label="Location"
|
|
142
|
+
geocoder={createProxyGeocoder({
|
|
143
|
+
endpoint: "https://app.example/geo/",
|
|
144
|
+
fetch: fetchImpl as unknown as typeof globalThis.fetch,
|
|
145
|
+
})}
|
|
146
|
+
onChange={onChange}
|
|
147
|
+
/>,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
typeSearch(result.container, "manner");
|
|
151
|
+
await waitFor(() => {
|
|
152
|
+
expect(document.body.textContent).toContain("Mannerheimintie 3");
|
|
153
|
+
});
|
|
154
|
+
fireEvent.click(document.querySelector("[data-testid='geolocation-result-0']") as Element);
|
|
155
|
+
await waitFor(() => {
|
|
156
|
+
expect(onChange).toHaveBeenCalledWith(HELSINKI);
|
|
157
|
+
});
|
|
158
|
+
// No credential ever reaches the component: it only ever saw a fetch.
|
|
159
|
+
const calledUrl = String(fetchImpl.mock.calls[0]?.[0]);
|
|
160
|
+
expect(calledUrl).toContain("app.example");
|
|
161
|
+
expect(calledUrl).not.toContain("nominatim");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("swapping providers is a prop change — the component is untouched", async () => {
|
|
165
|
+
const first = renderWithProviders(
|
|
166
|
+
<Geolocation label="Location" value={HELSINKI} geocoder={offlineGeocoder} />,
|
|
167
|
+
);
|
|
168
|
+
await waitFor(() => {
|
|
169
|
+
expect(searchInput(first.container)?.value).toBe("Mannerheimintie 3, Kamppi, Helsinki");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const renamed: Geocoder = {
|
|
173
|
+
geocode: offlineGeocoder.geocode,
|
|
174
|
+
reverseGeocode: async () => ({ lat: 60.16952, lng: 24.93545, label: "HQ" }),
|
|
175
|
+
};
|
|
176
|
+
const second = renderWithProviders(
|
|
177
|
+
<Geolocation label="Location" value={HELSINKI} geocoder={renamed} />,
|
|
178
|
+
);
|
|
179
|
+
await waitFor(() => {
|
|
180
|
+
expect(searchInput(second.container)?.value).toBe("HQ");
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("a failing consumer provider degrades honestly — map and pair survive", async () => {
|
|
185
|
+
const broken: Geocoder = {
|
|
186
|
+
geocode: async () => {
|
|
187
|
+
throw new Error("consumer provider down");
|
|
188
|
+
},
|
|
189
|
+
reverseGeocode: async () => {
|
|
190
|
+
throw new Error("consumer provider down");
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
const result = renderWithProviders(
|
|
194
|
+
<Geolocation label="Location" value={HELSINKI} geocoder={broken} />,
|
|
195
|
+
);
|
|
196
|
+
typeSearch(result.container, "manner");
|
|
197
|
+
await waitFor(() => {
|
|
198
|
+
expect(result.container.querySelector("[data-testid='geolocation-map']")).not.toBeNull();
|
|
199
|
+
});
|
|
200
|
+
expect(result.container.querySelector("[data-testid='geolocation-coordline']")).not.toBeNull();
|
|
201
|
+
expect(result.container.textContent).toContain("60.16952, 24.93545");
|
|
202
|
+
});
|
|
203
|
+
});
|