@simplybusiness/mobius 10.4.3 → 10.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/cjs/components/AddressLookup/AddressLookup.js +39 -36
- package/dist/cjs/components/AddressLookup/AddressLookup.js.map +3 -3
- package/dist/cjs/components/AddressLookup/LoqateAddressLookupService.js +28 -40
- package/dist/cjs/components/AddressLookup/LoqateAddressLookupService.js.map +1 -1
- package/dist/cjs/components/AddressLookup/index.js +67 -76
- package/dist/cjs/components/AddressLookup/index.js.map +3 -3
- package/dist/cjs/components/Breadcrumbs/Breadcrumbs.js +3 -7
- package/dist/cjs/components/Breadcrumbs/Breadcrumbs.js.map +2 -2
- package/dist/cjs/components/Breadcrumbs/index.js +3 -7
- package/dist/cjs/components/Breadcrumbs/index.js.map +2 -2
- package/dist/cjs/components/Combobox/Combobox.js +35 -32
- package/dist/cjs/components/Combobox/Combobox.js.map +3 -3
- package/dist/cjs/components/Combobox/index.js +35 -32
- package/dist/cjs/components/Combobox/index.js.map +3 -3
- package/dist/cjs/components/DateField/DateField.js +11 -8
- package/dist/cjs/components/DateField/DateField.js.map +3 -3
- package/dist/cjs/components/DateField/index.js +11 -8
- package/dist/cjs/components/DateField/index.js.map +3 -3
- package/dist/cjs/components/DropdownMenu/Item.js +3 -6
- package/dist/cjs/components/DropdownMenu/Item.js.map +2 -2
- package/dist/cjs/components/DropdownMenu/index.js +3 -6
- package/dist/cjs/components/DropdownMenu/index.js.map +2 -2
- package/dist/cjs/components/MaskedField/MaskedField.js +11 -8
- package/dist/cjs/components/MaskedField/MaskedField.js.map +3 -3
- package/dist/cjs/components/MaskedField/index.js +13 -10
- package/dist/cjs/components/MaskedField/index.js.map +3 -3
- package/dist/cjs/components/NumberField/NumberField.js +10 -7
- package/dist/cjs/components/NumberField/NumberField.js.map +3 -3
- package/dist/cjs/components/NumberField/index.js +10 -7
- package/dist/cjs/components/NumberField/index.js.map +3 -3
- package/dist/cjs/components/PasswordField/PasswordField.js +9 -6
- package/dist/cjs/components/PasswordField/PasswordField.js.map +3 -3
- package/dist/cjs/components/PasswordField/index.js +9 -6
- package/dist/cjs/components/PasswordField/index.js.map +3 -3
- package/dist/cjs/components/StickyOnMobile/StickyOnMobile.js +49 -0
- package/dist/cjs/components/StickyOnMobile/StickyOnMobile.js.map +7 -0
- package/dist/cjs/components/StickyOnMobile/index.js +51 -0
- package/dist/cjs/components/StickyOnMobile/index.js.map +7 -0
- package/dist/cjs/components/TextField/TextField.js +6 -3
- package/dist/cjs/components/TextField/TextField.js.map +3 -3
- package/dist/cjs/components/TextField/adornmentWithClassName.js +3 -2
- package/dist/cjs/components/TextField/adornmentWithClassName.js.map +2 -2
- package/dist/cjs/components/TextField/index.js +6 -3
- package/dist/cjs/components/TextField/index.js.map +3 -3
- package/dist/cjs/components/index.js +343 -343
- package/dist/cjs/components/index.js.map +4 -4
- package/dist/cjs/index.js +343 -343
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs/meta.json +329 -107
- package/dist/esm/{chunk-NEFRXIFY.js → chunk-53QMWUHB.js} +2 -2
- package/dist/esm/chunk-53QMWUHB.js.map +7 -0
- package/dist/esm/{chunk-4HI2AOBC.js → chunk-6TSYA7CJ.js} +4 -7
- package/dist/esm/{chunk-4HI2AOBC.js.map → chunk-6TSYA7CJ.js.map} +2 -2
- package/dist/esm/{chunk-VHAA22YE.js → chunk-A7KFYNH6.js} +1 -3
- package/dist/esm/{chunk-IQKS662C.js → chunk-AKCNBW55.js} +8 -6
- package/dist/esm/chunk-AKCNBW55.js.map +7 -0
- package/dist/esm/{chunk-6JCU4CGA.js → chunk-AZUVQRYC.js} +4 -4
- package/dist/esm/{chunk-XNEQHHNV.js → chunk-C2QJDKXS.js} +2 -2
- package/dist/esm/chunk-CTY6LDFI.js +1 -0
- package/dist/esm/{chunk-KFHPI67N.js → chunk-GJBH37DH.js} +4 -4
- package/dist/esm/{chunk-IM3I5CZL.js → chunk-I6CFRGID.js} +4 -3
- package/dist/esm/{chunk-IM3I5CZL.js.map → chunk-I6CFRGID.js.map} +2 -2
- package/dist/esm/{chunk-LGZWQZLS.js → chunk-IF7FRSC2.js} +2 -2
- package/dist/esm/{chunk-OEDU5ZEA.js → chunk-KUH5AB5T.js} +2 -2
- package/dist/esm/chunk-L2X5IF3K.js +1 -0
- package/dist/esm/chunk-L2X5IF3K.js.map +7 -0
- package/dist/esm/{chunk-2HUMNED2.js → chunk-M3X3ECNH.js} +4 -4
- package/dist/esm/chunk-NXWWQSZA.js +82 -0
- package/dist/esm/{chunk-VVL4B2KD.js.map → chunk-NXWWQSZA.js.map} +1 -1
- package/dist/esm/{chunk-JFDDW3IV.js → chunk-P7TPNRU4.js} +4 -8
- package/dist/esm/{chunk-JFDDW3IV.js.map → chunk-P7TPNRU4.js.map} +2 -2
- package/dist/esm/{chunk-VZ3IWSK6.js → chunk-Q5RB4O4S.js} +7 -7
- package/dist/esm/{chunk-S4CU4XRB.js → chunk-RBB3WHBJ.js} +2 -2
- package/dist/esm/{chunk-GV36OVX7.js → chunk-TQWUPLN6.js} +2 -2
- package/dist/esm/{chunk-X4CMSAET.js → chunk-YEZ6KR3Q.js} +2 -2
- package/dist/esm/chunk-YWFAKGQQ.js +19 -0
- package/dist/esm/chunk-YWFAKGQQ.js.map +7 -0
- package/dist/esm/{chunk-P6YHEIFT.js → chunk-ZLAAOGRQ.js} +4 -4
- package/dist/esm/components/Accordion/Accordion.js +1 -1
- package/dist/esm/components/Accordion/AccordionLink.js +1 -1
- package/dist/esm/components/Accordion/AccordionList.js +1 -1
- package/dist/esm/components/Accordion/index.js +1 -1
- package/dist/esm/components/AddressLookup/AddressLookup.js +7 -7
- package/dist/esm/components/AddressLookup/LoqateAddressLookupError.js +1 -1
- package/dist/esm/components/AddressLookup/LoqateAddressLookupService.js +2 -2
- package/dist/esm/components/AddressLookup/__mocks__/LoqateAddressLookupService.js +1 -1
- package/dist/esm/components/AddressLookup/index.js +10 -10
- package/dist/esm/components/AddressLookup/utils.js +1 -1
- package/dist/esm/components/Alert/Alert.js +1 -1
- package/dist/esm/components/Alert/index.js +1 -1
- package/dist/esm/components/Box/Box.js +1 -1
- package/dist/esm/components/Box/index.js +1 -1
- package/dist/esm/components/Breadcrumbs/BreadcrumbItem.js +1 -1
- package/dist/esm/components/Breadcrumbs/Breadcrumbs.js +2 -2
- package/dist/esm/components/Breadcrumbs/index.js +3 -3
- package/dist/esm/components/Button/Button.js +1 -1
- package/dist/esm/components/Button/Loading.js +1 -1
- package/dist/esm/components/Button/Success.js +1 -1
- package/dist/esm/components/Button/index.js +1 -1
- package/dist/esm/components/Checkbox/Checkbox.js +1 -1
- package/dist/esm/components/Checkbox/CheckboxGroup.js +3 -3
- package/dist/esm/components/Checkbox/index.js +3 -3
- package/dist/esm/components/Combobox/Combobox.js +6 -6
- package/dist/esm/components/Combobox/Listbox.js +1 -1
- package/dist/esm/components/Combobox/Option.js +1 -1
- package/dist/esm/components/Combobox/fixtures.js +1 -1
- package/dist/esm/components/Combobox/index.js +6 -6
- package/dist/esm/components/Combobox/useComboboxHighlight.js +1 -1
- package/dist/esm/components/Combobox/useComboboxOptions.js +1 -1
- package/dist/esm/components/Combobox/utils.js +1 -1
- package/dist/esm/components/Container/Container.js +1 -1
- package/dist/esm/components/Container/index.js +1 -1
- package/dist/esm/components/DateField/DateField.js +6 -6
- package/dist/esm/components/DateField/index.js +6 -6
- package/dist/esm/components/DateField/validation.js +1 -1
- package/dist/esm/components/Divider/Divider.js +1 -1
- package/dist/esm/components/Divider/index.js +1 -1
- package/dist/esm/components/Drawer/Content.js +1 -1
- package/dist/esm/components/Drawer/Drawer.js +1 -1
- package/dist/esm/components/Drawer/DrawerContext.js +1 -1
- package/dist/esm/components/Drawer/Header.js +1 -1
- package/dist/esm/components/Drawer/index.js +4 -4
- package/dist/esm/components/Drawer/useDrawer.js +1 -1
- package/dist/esm/components/DropdownMenu/DropdownMenu.js +1 -1
- package/dist/esm/components/DropdownMenu/Item.js +2 -2
- package/dist/esm/components/DropdownMenu/index.js +3 -3
- package/dist/esm/components/ErrorMessage/ErrorMessage.js +1 -1
- package/dist/esm/components/ErrorMessage/index.js +1 -1
- package/dist/esm/components/ExpandableText/ExpandableText.js +1 -1
- package/dist/esm/components/ExpandableText/index.js +1 -1
- package/dist/esm/components/Fieldset/Fieldset.js +1 -1
- package/dist/esm/components/Fieldset/index.js +1 -1
- package/dist/esm/components/Flex/Flex.js +1 -1
- package/dist/esm/components/Flex/index.js +1 -1
- package/dist/esm/components/Flex/propUtils.js +1 -1
- package/dist/esm/components/Grid/Grid.js +1 -1
- package/dist/esm/components/Grid/Item.js +1 -1
- package/dist/esm/components/Grid/index.js +1 -1
- package/dist/esm/components/Icon/Icon.js +1 -1
- package/dist/esm/components/Icon/index.js +1 -1
- package/dist/esm/components/Image/Image.js +1 -1
- package/dist/esm/components/Image/index.js +1 -1
- package/dist/esm/components/Label/Label.js +1 -1
- package/dist/esm/components/Label/index.js +1 -1
- package/dist/esm/components/Link/Link.js +1 -1
- package/dist/esm/components/Link/index.js +1 -1
- package/dist/esm/components/LinkButton/LinkButton.js +1 -1
- package/dist/esm/components/LinkButton/index.js +1 -1
- package/dist/esm/components/List/List.js +1 -1
- package/dist/esm/components/List/ListItem.js +1 -1
- package/dist/esm/components/List/index.js +1 -1
- package/dist/esm/components/LoadingIndicator/LoadingIndicator.js +1 -1
- package/dist/esm/components/LoadingIndicator/index.js +1 -1
- package/dist/esm/components/Logo/Logo.js +1 -1
- package/dist/esm/components/Logo/index.js +1 -1
- package/dist/esm/components/MaskedField/MaskedField.js +5 -5
- package/dist/esm/components/MaskedField/index.js +6 -6
- package/dist/esm/components/Modal/Content.js +1 -1
- package/dist/esm/components/Modal/Header.js +1 -1
- package/dist/esm/components/Modal/Modal.js +1 -1
- package/dist/esm/components/Modal/ModalContext.js +1 -1
- package/dist/esm/components/Modal/index.js +1 -1
- package/dist/esm/components/Modal/useModal.js +1 -1
- package/dist/esm/components/NumberField/NumberField.js +6 -6
- package/dist/esm/components/NumberField/index.js +6 -6
- package/dist/esm/components/Option/Option.js +1 -1
- package/dist/esm/components/Option/index.js +1 -1
- package/dist/esm/components/PasswordField/PasswordField.js +6 -6
- package/dist/esm/components/PasswordField/ShowHideButton.js +1 -1
- package/dist/esm/components/PasswordField/index.js +6 -6
- package/dist/esm/components/Popover/Arrow.js +1 -1
- package/dist/esm/components/Popover/Popover.js +4 -4
- package/dist/esm/components/Popover/index.js +4 -4
- package/dist/esm/components/Popover/useAutoUpdate.js +1 -1
- package/dist/esm/components/Popover/useFloatingPosition.js +1 -1
- package/dist/esm/components/Popover/useOutsidePress.js +1 -1
- package/dist/esm/components/Progress/Progress.js +1 -1
- package/dist/esm/components/Progress/index.js +1 -1
- package/dist/esm/components/Radio/Radio.js +1 -1
- package/dist/esm/components/Radio/RadioGroup.js +4 -4
- package/dist/esm/components/Radio/index.js +6 -6
- package/dist/esm/components/SVG/SVG.js +1 -1
- package/dist/esm/components/SVG/index.js +1 -1
- package/dist/esm/components/Segment/Segment.js +1 -1
- package/dist/esm/components/Segment/SegmentGroup.js +1 -1
- package/dist/esm/components/Segment/index.js +1 -1
- package/dist/esm/components/Select/Select.js +4 -4
- package/dist/esm/components/Select/index.js +4 -4
- package/dist/esm/components/Slider/Slider.js +1 -1
- package/dist/esm/components/Slider/helpers.js +1 -1
- package/dist/esm/components/Slider/index.js +1 -1
- package/dist/esm/components/Stack/Stack.js +1 -1
- package/dist/esm/components/Stack/index.js +1 -1
- package/dist/esm/components/StickyOnMobile/StickyOnMobile.js +8 -0
- package/dist/esm/components/StickyOnMobile/StickyOnMobile.js.map +7 -0
- package/dist/esm/components/StickyOnMobile/index.js +9 -0
- package/dist/esm/components/StickyOnMobile/index.js.map +7 -0
- package/dist/esm/components/Switch/Switch.js +1 -1
- package/dist/esm/components/Switch/index.js +1 -1
- package/dist/esm/components/Table/Body.js +1 -1
- package/dist/esm/components/Table/Cell.js +1 -1
- package/dist/esm/components/Table/Foot.js +1 -1
- package/dist/esm/components/Table/Head.js +1 -1
- package/dist/esm/components/Table/HeaderCell.js +1 -1
- package/dist/esm/components/Table/Row.js +1 -1
- package/dist/esm/components/Table/Table.js +1 -1
- package/dist/esm/components/Table/index.js +1 -1
- package/dist/esm/components/Text/Text.js +1 -1
- package/dist/esm/components/Text/index.js +1 -1
- package/dist/esm/components/TextArea/TextArea.js +4 -4
- package/dist/esm/components/TextArea/index.js +4 -4
- package/dist/esm/components/TextAreaInput/TextAreaInput.js +1 -1
- package/dist/esm/components/TextAreaInput/index.js +1 -1
- package/dist/esm/components/TextField/TextField.js +5 -5
- package/dist/esm/components/TextField/adornmentWithClassName.js +2 -2
- package/dist/esm/components/TextField/index.js +5 -5
- package/dist/esm/components/TextOrHTML/TextOrHTML.js +1 -1
- package/dist/esm/components/TextOrHTML/index.js +1 -1
- package/dist/esm/components/Title/Title.js +1 -1
- package/dist/esm/components/Title/index.js +1 -1
- package/dist/esm/components/Toast/Toast.js +1 -1
- package/dist/esm/components/Toast/ToastOptionsDoc.js +1 -1
- package/dist/esm/components/Toast/Toaster.js +1 -1
- package/dist/esm/components/Toast/index.js +1 -1
- package/dist/esm/components/Toast/state.js +1 -1
- package/dist/esm/components/Trust/Trust.js +1 -1
- package/dist/esm/components/Trust/TrustpilotProvider.js +1 -1
- package/dist/esm/components/Trust/constants.js +1 -1
- package/dist/esm/components/Trust/index.js +1 -1
- package/dist/esm/components/VisuallyHidden/VisuallyHidden.js +1 -1
- package/dist/esm/components/VisuallyHidden/index.js +1 -1
- package/dist/esm/components/index.js +68 -63
- package/dist/esm/hooks/index.js +1 -1
- package/dist/esm/hooks/useBreakpoint/index.js +1 -1
- package/dist/esm/hooks/useBreakpoint/useBreakpoint.js +1 -1
- package/dist/esm/hooks/useButton/index.js +1 -1
- package/dist/esm/hooks/useButton/useButton.js +1 -1
- package/dist/esm/hooks/useDialog/index.js +1 -1
- package/dist/esm/hooks/useDialog/useDialog.js +1 -1
- package/dist/esm/hooks/useDialogPolyfill/index.js +1 -1
- package/dist/esm/hooks/useDialogPolyfill/useDialogPolyfill.js +1 -1
- package/dist/esm/hooks/useLabel/index.js +1 -1
- package/dist/esm/hooks/useLabel/useLabel.js +1 -1
- package/dist/esm/hooks/useTextField/index.js +1 -1
- package/dist/esm/hooks/useTextField/useTextField.js +1 -1
- package/dist/esm/hooks/useValidationClasses/index.js +1 -1
- package/dist/esm/hooks/useValidationClasses/useValidationClasses.js +1 -1
- package/dist/esm/index.js +68 -63
- package/dist/esm/meta.json +3460 -3303
- package/dist/esm/utils/StoryContainer.js +1 -1
- package/dist/esm/utils/changeCSS.js +1 -1
- package/dist/esm/utils/colours.js +1 -1
- package/dist/esm/utils/delay.js +1 -1
- package/dist/esm/utils/excludeControls.js +1 -1
- package/dist/esm/utils/filterUndefinedProps.js +1 -1
- package/dist/esm/utils/filterUnsetValues.js +1 -1
- package/dist/esm/utils/getSpacingValue.js +1 -1
- package/dist/esm/utils/htmlDialogPolyfill.js +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/dist/esm/utils/mergeRefs.js +1 -1
- package/dist/esm/utils/mockMatchMedia.js +1 -1
- package/dist/esm/utils/polyfill-tests.js +1 -1
- package/dist/esm/utils/sizeClasses.js +1 -1
- package/dist/esm/utils/sizeOptions.js +1 -1
- package/dist/esm/utils/spaceDelimitedList.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/components/Accordion/Accordion.d.ts +4 -4
- package/dist/types/components/Accordion/AccordionList.d.ts +4 -4
- package/dist/types/components/AddressLookup/AddressLookup.d.ts +4 -4
- package/dist/types/components/AddressLookup/LoqateAddressLookupService.d.ts +1 -1
- package/dist/types/components/Alert/Alert.d.ts +4 -4
- package/dist/types/components/Box/Box.d.ts +4 -4
- package/dist/types/components/Breadcrumbs/BreadcrumbItem.d.ts +4 -4
- package/dist/types/components/Breadcrumbs/Breadcrumbs.d.ts +4 -4
- package/dist/types/components/Button/Button.d.ts +4 -4
- package/dist/types/components/Checkbox/Checkbox.d.ts +4 -4
- package/dist/types/components/Checkbox/CheckboxGroup.d.ts +4 -4
- package/dist/types/components/Combobox/Combobox.d.ts +2 -5
- package/dist/types/components/Combobox/useComboboxOptions.d.ts +1 -1
- package/dist/types/components/Container/Container.d.ts +4 -4
- package/dist/types/components/DateField/DateField.d.ts +4 -4
- package/dist/types/components/Divider/Divider.d.ts +4 -4
- package/dist/types/components/Drawer/Content.d.ts +4 -4
- package/dist/types/components/Drawer/Drawer.d.ts +4 -4
- package/dist/types/components/Drawer/Header.d.ts +4 -4
- package/dist/types/components/DropdownMenu/DropdownMenu.d.ts +4 -4
- package/dist/types/components/DropdownMenu/Item.d.ts +4 -4
- package/dist/types/components/ErrorMessage/ErrorMessage.d.ts +4 -4
- package/dist/types/components/ExpandableText/ExpandableText.d.ts +4 -4
- package/dist/types/components/Fieldset/Fieldset.d.ts +4 -4
- package/dist/types/components/Flex/Flex.d.ts +4 -4
- package/dist/types/components/Grid/Grid.d.ts +4 -4
- package/dist/types/components/Grid/Item.d.ts +4 -4
- package/dist/types/components/Image/Image.d.ts +4 -4
- package/dist/types/components/Label/Label.d.ts +4 -4
- package/dist/types/components/Link/Link.d.ts +4 -4
- package/dist/types/components/List/List.d.ts +4 -4
- package/dist/types/components/List/ListItem.d.ts +4 -4
- package/dist/types/components/LoadingIndicator/LoadingIndicator.d.ts +4 -4
- package/dist/types/components/Logo/Logo.d.ts +4 -4
- package/dist/types/components/MaskedField/MaskedField.d.ts +4 -4
- package/dist/types/components/Modal/Content.d.ts +4 -4
- package/dist/types/components/Modal/Header.d.ts +4 -4
- package/dist/types/components/Modal/Modal.d.ts +4 -4
- package/dist/types/components/NumberField/NumberField.d.ts +4 -4
- package/dist/types/components/Option/Option.d.ts +4 -4
- package/dist/types/components/PasswordField/PasswordField.d.ts +4 -4
- package/dist/types/components/Progress/Progress.d.ts +4 -4
- package/dist/types/components/Radio/Radio.d.ts +4 -4
- package/dist/types/components/Radio/RadioGroup.d.ts +4 -4
- package/dist/types/components/SVG/SVG.d.ts +4 -4
- package/dist/types/components/Segment/Segment.d.ts +4 -4
- package/dist/types/components/Segment/SegmentGroup.d.ts +4 -4
- package/dist/types/components/Select/Select.d.ts +4 -4
- package/dist/types/components/Stack/Stack.d.ts +4 -4
- package/dist/types/components/StickyOnMobile/StickyOnMobile.d.ts +15 -0
- package/dist/types/components/StickyOnMobile/index.d.ts +1 -0
- package/dist/types/components/Switch/Switch.d.ts +4 -4
- package/dist/types/components/Table/Body.d.ts +4 -4
- package/dist/types/components/Table/Cell.d.ts +4 -4
- package/dist/types/components/Table/Foot.d.ts +4 -4
- package/dist/types/components/Table/Head.d.ts +4 -4
- package/dist/types/components/Table/HeaderCell.d.ts +4 -4
- package/dist/types/components/Table/Row.d.ts +4 -4
- package/dist/types/components/Table/Table.d.ts +4 -4
- package/dist/types/components/Text/Text.d.ts +4 -4
- package/dist/types/components/TextArea/TextArea.d.ts +4 -4
- package/dist/types/components/TextAreaInput/TextAreaInput.d.ts +4 -4
- package/dist/types/components/TextField/TextField.d.ts +1 -4
- package/dist/types/components/TextField/adornmentWithClassName.d.ts +3 -1
- package/dist/types/components/TextOrHTML/TextOrHTML.d.ts +4 -4
- package/dist/types/components/Title/Title.d.ts +4 -4
- package/dist/types/components/Toast/ToastOptionsDoc.d.ts +4 -8
- package/dist/types/components/Toast/Toaster.d.ts +4 -4
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/hooks/useButton/useButton.d.ts +5 -5
- package/dist/types/hooks/useLabel/useLabel.d.ts +1 -1
- package/package.json +22 -21
- package/src/components/Box/Box.test.tsx +1 -2
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +3 -7
- package/src/components/Button/Button.stories.tsx +1 -1
- package/src/components/Combobox/Combobox.tsx +2 -4
- package/src/components/DropdownMenu/DropdownMenu.stories.tsx +1 -1
- package/src/components/DropdownMenu/Item.tsx +3 -6
- package/src/components/Grid/Grid.stories.tsx +1 -1
- package/src/components/StickyOnMobile/StickyOnMobile.css +19 -0
- package/src/components/StickyOnMobile/StickyOnMobile.mdx +52 -0
- package/src/components/StickyOnMobile/StickyOnMobile.stories.tsx +99 -0
- package/src/components/StickyOnMobile/StickyOnMobile.test.tsx +100 -0
- package/src/components/StickyOnMobile/StickyOnMobile.tsx +37 -0
- package/src/components/StickyOnMobile/index.tsx +1 -0
- package/src/components/TextField/TextField.tsx +3 -1
- package/src/components/TextField/adornmentWithClassName.ts +4 -3
- package/src/components/index.tsx +1 -0
- package/src/hooks/useBreakpoint/useBreakpoint.test.tsx +4 -4
- package/src/styles.d.ts +2 -0
- package/dist/esm/chunk-IQKS662C.js.map +0 -7
- package/dist/esm/chunk-NEFRXIFY.js.map +0 -7
- package/dist/esm/chunk-NOQ27VLY.js +0 -1
- package/dist/esm/chunk-VVL4B2KD.js +0 -92
- /package/dist/esm/{chunk-NOQ27VLY.js.map → chunk-A7KFYNH6.js.map} +0 -0
- /package/dist/esm/{chunk-6JCU4CGA.js.map → chunk-AZUVQRYC.js.map} +0 -0
- /package/dist/esm/{chunk-XNEQHHNV.js.map → chunk-C2QJDKXS.js.map} +0 -0
- /package/dist/esm/{chunk-VHAA22YE.js.map → chunk-CTY6LDFI.js.map} +0 -0
- /package/dist/esm/{chunk-KFHPI67N.js.map → chunk-GJBH37DH.js.map} +0 -0
- /package/dist/esm/{chunk-LGZWQZLS.js.map → chunk-IF7FRSC2.js.map} +0 -0
- /package/dist/esm/{chunk-OEDU5ZEA.js.map → chunk-KUH5AB5T.js.map} +0 -0
- /package/dist/esm/{chunk-2HUMNED2.js.map → chunk-M3X3ECNH.js.map} +0 -0
- /package/dist/esm/{chunk-VZ3IWSK6.js.map → chunk-Q5RB4O4S.js.map} +0 -0
- /package/dist/esm/{chunk-S4CU4XRB.js.map → chunk-RBB3WHBJ.js.map} +0 -0
- /package/dist/esm/{chunk-GV36OVX7.js.map → chunk-TQWUPLN6.js.map} +0 -0
- /package/dist/esm/{chunk-X4CMSAET.js.map → chunk-YEZ6KR3Q.js.map} +0 -0
- /package/dist/esm/{chunk-P6YHEIFT.js.map → chunk-ZLAAOGRQ.js.map} +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import type { StickyOnMobileProps } from "./StickyOnMobile";
|
|
3
|
+
import { StickyOnMobile } from "./StickyOnMobile";
|
|
4
|
+
import { excludeControls } from "../../utils";
|
|
5
|
+
import { Button } from "../Button";
|
|
6
|
+
import { Stack } from "../Stack";
|
|
7
|
+
import { Text } from "../Text";
|
|
8
|
+
import { TextField } from "../TextField";
|
|
9
|
+
|
|
10
|
+
type StoryType = StoryObj<typeof StickyOnMobile>;
|
|
11
|
+
|
|
12
|
+
const meta: Meta<typeof StickyOnMobile> = {
|
|
13
|
+
title: "Layout/StickyOnMobile",
|
|
14
|
+
component: StickyOnMobile,
|
|
15
|
+
argTypes: {
|
|
16
|
+
...excludeControls("className", "style", "children"),
|
|
17
|
+
elementType: {
|
|
18
|
+
control: { type: "text" },
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
parameters: {
|
|
22
|
+
docs: {
|
|
23
|
+
description: {
|
|
24
|
+
component:
|
|
25
|
+
"A thin layout wrapper that pins a single child to the bottom of the viewport on mobile (≤ 768px) using `position: fixed` and renders in document flow on desktop. Designed to wrap CTAs such as the post-quote Combined Payments checkout button.",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const FillerContent = () => (
|
|
32
|
+
<Stack gap="sm">
|
|
33
|
+
{Array.from({ length: 12 }).map((_, i) => (
|
|
34
|
+
<Text key={i}>
|
|
35
|
+
Scroll the canvas on a mobile viewport (≤ 768px) — the Checkout button
|
|
36
|
+
below stays clamped to the bottom of the visible area while content
|
|
37
|
+
scrolls behind it. On desktop it just renders in flow.
|
|
38
|
+
</Text>
|
|
39
|
+
))}
|
|
40
|
+
</Stack>
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
export const Default: StoryType = {
|
|
44
|
+
render: (args: StickyOnMobileProps) => (
|
|
45
|
+
<Stack gap="lg">
|
|
46
|
+
<FillerContent />
|
|
47
|
+
<StickyOnMobile {...args}>
|
|
48
|
+
<Button type="button" variant="primary">
|
|
49
|
+
Checkout
|
|
50
|
+
</Button>
|
|
51
|
+
</StickyOnMobile>
|
|
52
|
+
</Stack>
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const KeyboardTest: StoryType = {
|
|
57
|
+
parameters: {
|
|
58
|
+
docs: {
|
|
59
|
+
description: {
|
|
60
|
+
story:
|
|
61
|
+
"Manual QA surface for soft-keyboard behaviour. Storybook viewport addon does NOT simulate the keyboard — open this on a real (or simulator) iPhone and Android, focus the input, and observe whether the sticky bar gets covered. iOS Safari is the case the ticket flags for Browserstack.",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
render: (args: StickyOnMobileProps) => (
|
|
66
|
+
<Stack gap="lg">
|
|
67
|
+
<FillerContent />
|
|
68
|
+
<TextField
|
|
69
|
+
label="Tap to open the keyboard"
|
|
70
|
+
name="keyboard-test"
|
|
71
|
+
placeholder="Type anything"
|
|
72
|
+
/>
|
|
73
|
+
<FillerContent />
|
|
74
|
+
<StickyOnMobile {...args}>
|
|
75
|
+
<Button type="button" variant="primary">
|
|
76
|
+
Checkout
|
|
77
|
+
</Button>
|
|
78
|
+
</StickyOnMobile>
|
|
79
|
+
</Stack>
|
|
80
|
+
),
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const AsFooterElement: StoryType = {
|
|
84
|
+
render: (args: StickyOnMobileProps) => (
|
|
85
|
+
<Stack gap="lg">
|
|
86
|
+
<FillerContent />
|
|
87
|
+
<StickyOnMobile {...args} elementType="footer">
|
|
88
|
+
<Button type="button" variant="primary">
|
|
89
|
+
Checkout
|
|
90
|
+
</Button>
|
|
91
|
+
</StickyOnMobile>
|
|
92
|
+
</Stack>
|
|
93
|
+
),
|
|
94
|
+
args: {
|
|
95
|
+
elementType: "footer",
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default meta;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createRef } from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { StickyOnMobile } from ".";
|
|
4
|
+
|
|
5
|
+
const CLASS_NAME = "mobius-sticky-on-mobile";
|
|
6
|
+
|
|
7
|
+
describe("StickyOnMobile", () => {
|
|
8
|
+
it("renders children", () => {
|
|
9
|
+
render(<StickyOnMobile>Sample text</StickyOnMobile>);
|
|
10
|
+
expect(screen.getByText("Sample text")).toBeInTheDocument();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("renders a div by default", () => {
|
|
14
|
+
render(<StickyOnMobile data-testid="bar">x</StickyOnMobile>);
|
|
15
|
+
expect(screen.getByTestId("bar").tagName).toBe("DIV");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("uses the provided elementType", () => {
|
|
19
|
+
render(
|
|
20
|
+
<StickyOnMobile elementType="footer" data-testid="bar">
|
|
21
|
+
x
|
|
22
|
+
</StickyOnMobile>,
|
|
23
|
+
);
|
|
24
|
+
expect(screen.getByTestId("bar").tagName).toBe("FOOTER");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("does not pass elementType through as a DOM attribute", () => {
|
|
28
|
+
render(
|
|
29
|
+
<StickyOnMobile elementType="footer" data-testid="bar">
|
|
30
|
+
x
|
|
31
|
+
</StickyOnMobile>,
|
|
32
|
+
);
|
|
33
|
+
expect(screen.getByTestId("bar")).not.toHaveAttribute(
|
|
34
|
+
"elementtype",
|
|
35
|
+
"footer",
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("forwards style attributes", () => {
|
|
40
|
+
render(
|
|
41
|
+
<StickyOnMobile style={{ backgroundColor: "red" }} data-testid="bar">
|
|
42
|
+
x
|
|
43
|
+
</StickyOnMobile>,
|
|
44
|
+
);
|
|
45
|
+
expect(screen.getByTestId("bar")).toHaveStyle({
|
|
46
|
+
"background-color": "rgb(255, 0, 0)",
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("spreads HTML attributes onto the element", () => {
|
|
51
|
+
render(
|
|
52
|
+
<StickyOnMobile data-testid="bar" aria-label="payment actions">
|
|
53
|
+
x
|
|
54
|
+
</StickyOnMobile>,
|
|
55
|
+
);
|
|
56
|
+
expect(screen.getByTestId("bar")).toHaveAttribute(
|
|
57
|
+
"aria-label",
|
|
58
|
+
"payment actions",
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("class names", () => {
|
|
63
|
+
it("applies the mobius base class", () => {
|
|
64
|
+
render(<StickyOnMobile data-testid="bar">x</StickyOnMobile>);
|
|
65
|
+
expect(screen.getByTestId("bar")).toHaveClass("mobius");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("applies the mobius-sticky-on-mobile class", () => {
|
|
69
|
+
render(<StickyOnMobile data-testid="bar">x</StickyOnMobile>);
|
|
70
|
+
expect(screen.getByTestId("bar")).toHaveClass(CLASS_NAME);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("merges a custom className", () => {
|
|
74
|
+
render(
|
|
75
|
+
<StickyOnMobile className="my-class" data-testid="bar">
|
|
76
|
+
x
|
|
77
|
+
</StickyOnMobile>,
|
|
78
|
+
);
|
|
79
|
+
expect(screen.getByTestId("bar")).toHaveClass("my-class");
|
|
80
|
+
expect(screen.getByTestId("bar")).toHaveClass(CLASS_NAME);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("forwards ref", () => {
|
|
85
|
+
const ref = createRef<HTMLDivElement>();
|
|
86
|
+
render(<StickyOnMobile ref={ref}>x</StickyOnMobile>);
|
|
87
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("breakpoint behaviour", () => {
|
|
91
|
+
// Behaviour at the 768px breakpoint is driven by a static @media query in
|
|
92
|
+
// StickyOnMobile.css. JSDOM does not evaluate @media rules, so these tests
|
|
93
|
+
// verify the *contract*: the class hook is applied unconditionally so the
|
|
94
|
+
// CSS can switch positioning based on viewport width.
|
|
95
|
+
it("applies the sticky class hook regardless of viewport (CSS handles the switch)", () => {
|
|
96
|
+
render(<StickyOnMobile data-testid="bar">x</StickyOnMobile>);
|
|
97
|
+
expect(screen.getByTestId("bar")).toHaveClass(CLASS_NAME);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RefAttributes,
|
|
3
|
+
ReactNode,
|
|
4
|
+
ElementType,
|
|
5
|
+
CSSProperties,
|
|
6
|
+
HTMLAttributes,
|
|
7
|
+
} from "react";
|
|
8
|
+
import classNames from "classnames/dedupe";
|
|
9
|
+
import "./StickyOnMobile.css";
|
|
10
|
+
|
|
11
|
+
export type StickyOnMobileElementType = HTMLElement;
|
|
12
|
+
|
|
13
|
+
export interface StickyOnMobileProps
|
|
14
|
+
extends
|
|
15
|
+
HTMLAttributes<StickyOnMobileElementType>,
|
|
16
|
+
RefAttributes<StickyOnMobileElementType> {
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
/** HTML element to render. Defaults to `div`. */
|
|
19
|
+
elementType?: ElementType;
|
|
20
|
+
className?: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const StickyOnMobile = ({ ref, ...props }: StickyOnMobileProps) => {
|
|
25
|
+
const { elementType: Element = "div", ...otherProps } = props;
|
|
26
|
+
|
|
27
|
+
const classes = classNames(
|
|
28
|
+
"mobius",
|
|
29
|
+
"mobius-sticky-on-mobile",
|
|
30
|
+
otherProps.className,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return <Element ref={ref} {...otherProps} className={classes} />;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
StickyOnMobile.displayName = "StickyOnMobile";
|
|
37
|
+
export { StickyOnMobile };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./StickyOnMobile";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import classNames from "classnames/dedupe";
|
|
4
|
+
import { memo } from "react";
|
|
4
5
|
import type {
|
|
5
6
|
HTMLInputTypeAttribute,
|
|
6
7
|
ReactElement,
|
|
@@ -52,7 +53,7 @@ export interface TextFieldProps
|
|
|
52
53
|
|
|
53
54
|
export type TextFieldRef = Ref<TextFieldElementType>;
|
|
54
55
|
|
|
55
|
-
const
|
|
56
|
+
const TextFieldInner = ({ ref, ...props }: TextFieldProps) => {
|
|
56
57
|
const {
|
|
57
58
|
isDisabled,
|
|
58
59
|
type = "text",
|
|
@@ -166,5 +167,6 @@ const TextField = ({ ref, ...props }: TextFieldProps) => {
|
|
|
166
167
|
);
|
|
167
168
|
};
|
|
168
169
|
|
|
170
|
+
const TextField = memo(TextFieldInner);
|
|
169
171
|
TextField.displayName = "TextField";
|
|
170
172
|
export { TextField };
|
|
@@ -9,11 +9,12 @@ export const adornmentWithClassName = (
|
|
|
9
9
|
) => {
|
|
10
10
|
if (!component) return null;
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const typedComponent = component as ReactElement<{ className?: string }>;
|
|
13
|
+
return cloneElement(typedComponent, {
|
|
13
14
|
className: classNames(
|
|
14
|
-
|
|
15
|
+
typedComponent.props.className,
|
|
15
16
|
validationClasses,
|
|
16
17
|
className,
|
|
17
18
|
),
|
|
18
|
-
}
|
|
19
|
+
});
|
|
19
20
|
};
|
package/src/components/index.tsx
CHANGED
|
@@ -139,7 +139,7 @@ describe("useBreakpoint", () => {
|
|
|
139
139
|
it.each([...expected])(
|
|
140
140
|
"it returns %s for breakpoint %s",
|
|
141
141
|
(expectedResult, breakpoint) => {
|
|
142
|
-
setWindowWidth(value
|
|
142
|
+
setWindowWidth(value);
|
|
143
143
|
|
|
144
144
|
const { result } = renderHook(() => useBreakpoint());
|
|
145
145
|
expect(result.current.up(breakpoint)).toBe(expectedResult);
|
|
@@ -222,7 +222,7 @@ describe("useBreakpoint", () => {
|
|
|
222
222
|
it.each([...expected])(
|
|
223
223
|
"it returns %s for breakpoint %s",
|
|
224
224
|
(expectedResult, breakpoint) => {
|
|
225
|
-
setWindowWidth(value
|
|
225
|
+
setWindowWidth(value);
|
|
226
226
|
|
|
227
227
|
const { result } = renderHook(() => useBreakpoint());
|
|
228
228
|
expect(result.current.down(breakpoint)).toBe(expectedResult);
|
|
@@ -340,7 +340,7 @@ describe("useBreakpoint", () => {
|
|
|
340
340
|
it.each([...expected])(
|
|
341
341
|
"it returns %s for breakpoint %s",
|
|
342
342
|
(expectedResult, breakpoint) => {
|
|
343
|
-
setWindowWidth(value
|
|
343
|
+
setWindowWidth(value);
|
|
344
344
|
|
|
345
345
|
const { result } = renderHook(() =>
|
|
346
346
|
useBreakpoint(customBreakpoints),
|
|
@@ -419,7 +419,7 @@ describe("useBreakpoint", () => {
|
|
|
419
419
|
it.each([...expected])(
|
|
420
420
|
"it returns %s for breakpoint %s",
|
|
421
421
|
(expectedResult, breakpoint) => {
|
|
422
|
-
setWindowWidth(value
|
|
422
|
+
setWindowWidth(value);
|
|
423
423
|
|
|
424
424
|
const { result } = renderHook(() => useBreakpoint());
|
|
425
425
|
expect(result.current.down(breakpoint)).toBe(expectedResult);
|
package/src/styles.d.ts
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/components/TextField/TextField.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\nimport classNames from \"classnames/dedupe\";\nimport type {\n HTMLInputTypeAttribute,\n ReactElement,\n ReactNode,\n Ref,\n RefAttributes,\n} from \"react\";\nimport type { UseTextFieldProps } from \"../../hooks\";\nimport { useTextField, useValidationClasses } from \"../../hooks\";\nimport type { DOMProps, FocusEvents } from \"../../types\";\nimport { ErrorMessage } from \"../ErrorMessage\";\nimport { Label } from \"../Label\";\nimport { Stack } from \"../Stack\";\nimport { adornmentWithClassName } from \"./adornmentWithClassName\";\nimport \"./TextField.css\";\n\nexport type TextFieldElementType = HTMLInputElement;\nexport interface TextFieldProps\n extends\n DOMProps,\n FocusEvents,\n UseTextFieldProps,\n RefAttributes<TextFieldElementType> {\n className?: string;\n errorMessage?: string;\n children?: ReactNode;\n label?: string;\n type?: Exclude<\n HTMLInputTypeAttribute,\n | \"button\"\n | \"checkbox\"\n | \"color\"\n | \"date\"\n | \"datetime-local\"\n | \"file\"\n | \"image\"\n | \"month\"\n | \"radio\"\n | \"range\"\n | \"reset\"\n | \"submit\"\n | \"week\"\n >;\n prefixInside?: ReactElement;\n prefixOutside?: ReactElement;\n suffixInside?: ReactElement;\n suffixOutside?: ReactElement;\n}\n\nexport type TextFieldRef = Ref<TextFieldElementType>;\n\nconst TextField = ({ ref, ...props }: TextFieldProps) => {\n const {\n isDisabled,\n type = \"text\",\n isInvalid,\n className,\n label,\n errorMessage,\n children,\n isRequired,\n prefixInside,\n prefixOutside,\n suffixInside,\n suffixOutside,\n autoComplete,\n isReadOnly,\n ...otherProps\n } = props;\n\n const resolvedAutoComplete =\n autoComplete ??\n (type === \"email\" ? \"email\" : type === \"tel\" ? \"tel\" : undefined);\n\n const { inputProps, labelProps, errorMessageProps } = useTextField({\n ...props,\n autoComplete: resolvedAutoComplete,\n \"aria-errormessage\": errorMessage,\n });\n\n const hidden = type === \"hidden\";\n\n const validationClasses = useValidationClasses({ isInvalid });\n\n const textfieldClasses = {\n \"--is-disabled\": isDisabled,\n \"--is-required\": typeof isRequired === \"boolean\" && isRequired,\n \"--is-optional\": typeof isRequired === \"boolean\" && !isRequired,\n \"--is-hidden\": hidden,\n [className || \"\"]: true,\n };\n\n const sharedClasses = classNames(validationClasses, textfieldClasses);\n\n const labelClasses = classNames(\n {\n \"--is-disabled\": isDisabled,\n },\n validationClasses,\n );\n\n const containerClasses = classNames(\n \"mobius\",\n \"mobius-text-field\",\n sharedClasses,\n );\n\n const inputClasses = classNames(\n \"mobius\",\n \"mobius-text-field__input\",\n sharedClasses,\n );\n\n const inputWrapperClasses = classNames(\n \"mobius-text-field__input-wrapper\",\n sharedClasses,\n );\n\n return (\n <Stack gap=\"xs\" className={containerClasses}>\n {label && !hidden && (\n <Label {...labelProps} className={labelClasses}>\n {label}\n </Label>\n )}\n <div className=\"mobius-text-field__inner-container\">\n {adornmentWithClassName(\n prefixOutside,\n labelClasses,\n \"mobius-text-field__prefix-outside\",\n )}\n <div className={inputWrapperClasses}>\n {adornmentWithClassName(\n prefixInside,\n labelClasses,\n \"mobius-text-field__prefix-inside\",\n )}\n <input\n {...otherProps}\n {...inputProps}\n ref={ref}\n type={type}\n className={inputClasses}\n />\n {adornmentWithClassName(\n suffixInside,\n labelClasses,\n \"mobius-text-field__suffix-inside\",\n )}\n </div>\n {adornmentWithClassName(\n suffixOutside,\n labelClasses,\n \"mobius-text-field__suffix-outside\",\n )}\n </div>\n {children && (\n <div className=\"mobius-text-field__children\">{children}</div>\n )}\n\n <ErrorMessage {...errorMessageProps} errorMessage={errorMessage} />\n </Stack>\n );\n};\n\nTextField.displayName = \"TextField\";\nexport { TextField };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAEA,OAAO,gBAAgB;AAevB,OAAO;AA2GC,cAUA,YAVA;AAtER,IAAM,YAAY,CAAC,EAAE,KAAK,GAAG,MAAM,MAAsB;AACvD,QAAM;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,uBACJ,iBACC,SAAS,UAAU,UAAU,SAAS,QAAQ,QAAQ;AAEzD,QAAM,EAAE,YAAY,YAAY,kBAAkB,IAAI,aAAa;AAAA,IACjE,GAAG;AAAA,IACH,cAAc;AAAA,IACd,qBAAqB;AAAA,EACvB,CAAC;AAED,QAAM,SAAS,SAAS;AAExB,QAAM,oBAAoB,qBAAqB,EAAE,UAAU,CAAC;AAE5D,QAAM,mBAAmB;AAAA,IACvB,iBAAiB;AAAA,IACjB,iBAAiB,OAAO,eAAe,aAAa;AAAA,IACpD,iBAAiB,OAAO,eAAe,aAAa,CAAC;AAAA,IACrD,eAAe;AAAA,IACf,CAAC,aAAa,EAAE,GAAG;AAAA,EACrB;AAEA,QAAM,gBAAgB,WAAW,mBAAmB,gBAAgB;AAEpE,QAAM,eAAe;AAAA,IACnB;AAAA,MACE,iBAAiB;AAAA,IACnB;AAAA,IACA;AAAA,EACF;AAEA,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,sBAAsB;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AAEA,SACE,qBAAC,SAAM,KAAI,MAAK,WAAW,kBACxB;AAAA,aAAS,CAAC,UACT,oBAAC,SAAO,GAAG,YAAY,WAAW,cAC/B,iBACH;AAAA,IAEF,qBAAC,SAAI,WAAU,sCACZ;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,qBAAC,SAAI,WAAW,qBACb;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACH,GAAG;AAAA,YACJ;AAAA,YACA;AAAA,YACA,WAAW;AAAA;AAAA,QACb;AAAA,QACC;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,SACF;AAAA,MACC;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,OACF;AAAA,IACC,YACC,oBAAC,SAAI,WAAU,+BAA+B,UAAS;AAAA,IAGzD,oBAAC,gBAAc,GAAG,mBAAmB,cAA4B;AAAA,KACnE;AAEJ;AAEA,UAAU,cAAc;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/components/Combobox/Combobox.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useOnUnmount } from \"@simplybusiness/mobius-hooks\";\nimport classNames from \"classnames/dedupe\";\nimport type React from \"react\";\nimport type { FocusEvent } from \"react\";\nimport { useEffect, useId, useRef, useState } from \"react\";\nimport { useBreakpoint } from \"../../hooks\";\nimport { TextField } from \"../TextField\";\nimport { VisuallyHidden } from \"../VisuallyHidden\";\nimport { Listbox } from \"./Listbox\"; // Import Listbox component\nimport type { ComboboxOption, ComboboxProps, ComboboxRef } from \"./types\";\nimport { useComboboxHighlight } from \"./useComboboxHighlight\";\nimport { useComboboxOptions } from \"./useComboboxOptions\";\nimport { getOptionLabel, getOptionValue, isOptionGroup } from \"./utils\";\nimport \"./Combobox.css\";\n\nconst ComboboxInner = <T extends ComboboxOption>({\n ref,\n ...props\n}: ComboboxProps<T>) => {\n const {\n id,\n defaultValue,\n value,\n options,\n asyncOptions,\n delay,\n minSearchLength,\n onSelected,\n className,\n placeholder,\n icon,\n onBlur,\n onFocus,\n onChange,\n // onSearched, // unused prop, consider removing\n optionComponent,\n optionTestIdPrefix,\n errorMessage,\n ...otherProps\n } = props;\n // Avoid re-fetching after selecting an option\n const skipNextDebounceRef = useRef(false);\n const fallbackRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState(defaultValue || \"\");\n const [isOpen, setIsOpen] = useState(false);\n const [isChanging, setIsChanging] = useState(false);\n const { filteredOptions, updateFilteredOptions, isLoading, error } =\n useComboboxOptions({\n options,\n asyncOptions,\n inputValue,\n delay,\n minSearchLength,\n skipNextDebounceRef,\n });\n const [validationError, setValidationError] = useState(\n error?.message || errorMessage,\n );\n const {\n highlightedIndex,\n highlightedGroupIndex,\n highlightNextOption,\n highlightPreviousOption,\n highlightFirstOption,\n highlightLastOption,\n clearHighlight,\n } = useComboboxHighlight(filteredOptions);\n\n const inputRef = ref || fallbackRef;\n const listboxId = useId();\n const statusId = useId();\n const blurTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const userInteractedRef = useRef(false);\n const justSelectedRef = useRef(false);\n const { down } = useBreakpoint();\n const isMobile = down(\"md\");\n\n useEffect(() => {\n setValidationError(error?.message || errorMessage);\n }, [error, errorMessage]);\n\n // Helper to create properly-typed empty value based on option type\n const getEmptyValue = (): T => {\n // Check first available option to determine if we're using string or object options\n const firstOption = filteredOptions\n ? isOptionGroup(filteredOptions)\n ? filteredOptions[0]?.options[0]\n : filteredOptions[0]\n : options\n ? isOptionGroup(options)\n ? options[0]?.options[0]\n : options[0]\n : undefined;\n\n // If options are strings, return empty string\n if (typeof firstOption === \"string\") {\n return \"\" as T;\n }\n\n // If options are objects, return empty object with same shape\n return { label: \"\", value: \"\" } as T;\n };\n\n const handleFocus = (e: FocusEvent) => {\n onFocus?.(e);\n if (!filteredOptions || filteredOptions.length === 0) return;\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n }\n\n // Check if this is natural focus (user click/Tab) or programmatic focus\n const isNaturalFocus =\n userInteractedRef.current || e.relatedTarget !== null;\n if (userInteractedRef.current) {\n userInteractedRef.current = false;\n }\n\n // Block opening only if programmatic focus right after selection\n if (justSelectedRef.current && !isNaturalFocus) {\n return;\n }\n\n // Open dropdown for natural focus\n if (isNaturalFocus) {\n setIsOpen(true);\n justSelectedRef.current = false;\n }\n };\n\n useEffect(() => {\n if (!inputRef || typeof inputRef === \"function\") return;\n const inputElement = inputRef.current;\n if (!inputElement) return;\n\n const handleMouseDown = () => {\n // Track that user clicked/interacted with input\n userInteractedRef.current = true;\n };\n\n inputElement.addEventListener(\"mousedown\", handleMouseDown);\n return () => {\n inputElement.removeEventListener(\"mousedown\", handleMouseDown);\n };\n }, [inputRef]);\n\n useOnUnmount(() => {\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n }\n });\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setValidationError(undefined);\n justSelectedRef.current = false;\n setIsChanging(true);\n // Only open immediately for sync options; async options controlled by useEffect\n if (!asyncOptions) {\n setIsOpen(true);\n }\n clearHighlight();\n onChange?.(e);\n };\n\n const handleOptionSelect = (option: T) => {\n const val = getOptionValue(option);\n\n // Allow empty values to pass through\n if (!val && val !== \"\") return;\n\n if (\n typeof option === \"object\" &&\n \"callback\" in option &&\n option.callback &&\n typeof option.callback === \"function\"\n ) {\n justSelectedRef.current = true;\n setTimeout(() => {\n if (inputRef && typeof inputRef !== \"function\" && inputRef.current) {\n inputRef.current.focus();\n }\n }, 0);\n const callbackPromise = option.callback();\n updateFilteredOptions(callbackPromise);\n callbackPromise\n .then(() => {\n setIsOpen(true);\n setIsChanging(true);\n })\n .catch(() => {\n // error handled inside updateFilteredOptions via setError\n });\n return;\n }\n\n // Prevent re-fetching options after selecting an option\n skipNextDebounceRef.current = true;\n justSelectedRef.current = true;\n\n setIsChanging(false);\n setValidationError(undefined);\n setIsOpen(false);\n setInputValue(val);\n onSelected?.(option);\n };\n\n const getFirstOption = () => {\n if (!filteredOptions) return undefined;\n if (isOptionGroup(filteredOptions)) {\n return filteredOptions[0]?.options[0];\n }\n\n return filteredOptions[0];\n };\n\n const getHighlightedOption = () => {\n if (!filteredOptions) return undefined;\n if (highlightedIndex === -1) return undefined;\n\n if (isOptionGroup(filteredOptions)) {\n const group = filteredOptions[highlightedGroupIndex];\n return group?.options[highlightedIndex];\n }\n\n return filteredOptions[highlightedIndex];\n };\n\n const getHighlightedOptionId = () => {\n const option = getHighlightedOption();\n if (!option) return undefined;\n\n if (isOptionGroup(filteredOptions)) {\n return `${listboxId}-option-${highlightedGroupIndex}-${highlightedIndex}`;\n }\n\n return `${listboxId}-option-${highlightedIndex}`;\n };\n\n const handleBlur = (e: FocusEvent<Element, Element>) => {\n // Force selection if user has matched an entry by typing (not already selected)\n // Defer this to allow natural focus flow to complete first\n if (!justSelectedRef.current) {\n const typedText = inputValue.trim();\n const typedTextLower = typedText.toLowerCase();\n const highlightedOption = getHighlightedOption();\n const label = getOptionLabel(highlightedOption);\n\n if (typedTextLower === label?.toLowerCase()) {\n // Exact match with an option\n setTimeout(() => {\n handleOptionSelect(highlightedOption as T);\n }, 0);\n } else if (typedText === \"\") {\n // Allow empty values\n setTimeout(() => {\n handleOptionSelect(getEmptyValue());\n }, 0);\n } else {\n // Invalid value (not in options and not empty)\n setValidationError(\n errorMessage || \"Please select an option from the list\",\n );\n setTimeout(() => {\n setInputValue(\"\");\n }, 0);\n }\n }\n\n blurTimeoutRef.current = setTimeout(() => {\n onBlur?.(e);\n setIsOpen(false);\n setIsChanging(false);\n }, 150);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n justSelectedRef.current = false;\n setIsOpen(true);\n highlightNextOption();\n break;\n case \"ArrowUp\":\n e.preventDefault();\n justSelectedRef.current = false;\n setIsOpen(true);\n highlightPreviousOption();\n break;\n case \"Home\":\n e.preventDefault();\n justSelectedRef.current = false;\n setIsOpen(true);\n highlightFirstOption();\n break;\n case \"End\":\n e.preventDefault();\n justSelectedRef.current = false;\n setIsOpen(true);\n highlightLastOption();\n break;\n case \"Enter\":\n e.preventDefault();\n if (isOpen) {\n const selectedOption = getHighlightedOption() || getFirstOption();\n if (selectedOption) {\n handleOptionSelect(selectedOption);\n }\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setInputValue(\"\");\n setIsOpen(false);\n clearHighlight();\n break;\n default:\n // Do nothing\n }\n };\n\n useEffect(() => {\n if (value) {\n setInputValue(value);\n }\n }, [value]);\n\n // Open and close the combobox based on async filtered options\n useEffect(() => {\n if (asyncOptions && isChanging) {\n setIsOpen(!!filteredOptions && filteredOptions.length > 0);\n }\n }, [filteredOptions, asyncOptions, isChanging]);\n\n const classes = classNames(\n \"mobius mobius-combobox\",\n {\n \"mobius-combobox--is-expanded\": isOpen,\n \"mobius-combobox--is-loading\": isLoading,\n \"mobius-combobox--is-mobile\": isMobile,\n },\n className,\n );\n\n const getStatusMessage = () => {\n if (isLoading) return \"Loading options\";\n if (!filteredOptions || filteredOptions.length === 0) {\n return isChanging ? \"No options found\" : \"\";\n }\n const count = isOptionGroup(filteredOptions)\n ? filteredOptions.reduce((sum, group) => sum + group.options.length, 0)\n : filteredOptions.length;\n return isOpen && isChanging\n ? `${count} option${count === 1 ? \"\" : \"s\"} available`\n : \"\";\n };\n\n return (\n <div id={id} data-testid=\"mobius-combobox__wrapper\" className={classes}>\n <VisuallyHidden\n role=\"status\"\n aria-live=\"polite\"\n id={statusId}\n elementType=\"div\"\n className=\"mobius-combobox__status\"\n >\n {getStatusMessage()}\n </VisuallyHidden>\n <TextField\n {...otherProps}\n className=\"mobius-combobox__input\"\n role=\"combobox\"\n value={inputValue}\n placeholder={placeholder}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n onChange={handleInputChange}\n autoComplete=\"off\"\n aria-describedby={isLoading ? statusId : undefined}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls={isOpen ? listboxId : undefined}\n aria-expanded={isOpen}\n aria-activedescendant={\n highlightedIndex === -1 ? undefined : getHighlightedOptionId()\n }\n prefixInside={icon}\n ref={inputRef}\n errorMessage={errorMessage || validationError || error?.message}\n />\n <Listbox\n id={listboxId}\n isOpen={isOpen}\n isLoading={isLoading}\n options={filteredOptions}\n highlightedIndex={highlightedIndex}\n highlightedGroupIndex={highlightedGroupIndex}\n onOptionSelect={handleOptionSelect}\n optionComponent={optionComponent}\n optionTestIdPrefix={optionTestIdPrefix}\n />\n </div>\n );\n};\n\nexport const Combobox = ComboboxInner as <T extends ComboboxOption>(\n props: ComboboxProps<T> & { ref?: ComboboxRef },\n) => React.JSX.Element;\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=chunk-NOQ27VLY.js.map
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LoqateAddressLookupError
|
|
3
|
-
} from "./chunk-EDSRI6SV.js";
|
|
4
|
-
import {
|
|
5
|
-
__privateAdd,
|
|
6
|
-
__privateGet,
|
|
7
|
-
__privateSet
|
|
8
|
-
} from "./chunk-VHAA22YE.js";
|
|
9
|
-
|
|
10
|
-
// src/components/AddressLookup/LoqateAddressLookupService.tsx
|
|
11
|
-
var LOQATE_BASE_URL = "https://api.addressy.com/Capture/Interactive";
|
|
12
|
-
var LOQATE_FIND_URL = "/Find/v1.00/json3.ws";
|
|
13
|
-
var LOQATE_RETRIEVE_URL = "/Retrieve/v1.2/json3.ws";
|
|
14
|
-
var DEFAULT_COUNTRIES = ["GB"];
|
|
15
|
-
var _baseUrl, _apiKey, _countries, _filters;
|
|
16
|
-
var LoqateAddressLookupService = class {
|
|
17
|
-
constructor({
|
|
18
|
-
baseUrl,
|
|
19
|
-
apiKey,
|
|
20
|
-
countries,
|
|
21
|
-
filters
|
|
22
|
-
}) {
|
|
23
|
-
/**
|
|
24
|
-
* Base URL for the Loqate API
|
|
25
|
-
*/
|
|
26
|
-
__privateAdd(this, _baseUrl);
|
|
27
|
-
/**
|
|
28
|
-
* API key for the Loqate API
|
|
29
|
-
*/
|
|
30
|
-
__privateAdd(this, _apiKey);
|
|
31
|
-
/**
|
|
32
|
-
* List of allowed country codes for the Loqate API
|
|
33
|
-
* 2 or 3 character ISO country codes
|
|
34
|
-
*/
|
|
35
|
-
__privateAdd(this, _countries);
|
|
36
|
-
/**
|
|
37
|
-
* Optional filters for the Loqate API
|
|
38
|
-
* E.g., { AdministrativeArea: "CA", PostalCode: "90210" }
|
|
39
|
-
*/
|
|
40
|
-
__privateAdd(this, _filters);
|
|
41
|
-
__privateSet(this, _apiKey, apiKey);
|
|
42
|
-
__privateSet(this, _baseUrl, baseUrl || LOQATE_BASE_URL);
|
|
43
|
-
__privateSet(this, _countries, countries || DEFAULT_COUNTRIES);
|
|
44
|
-
__privateSet(this, _filters, filters);
|
|
45
|
-
}
|
|
46
|
-
fetchFromApi(url) {
|
|
47
|
-
return fetch(`${__privateGet(this, _baseUrl)}${url}`).then((response) => response.json()).then((json) => {
|
|
48
|
-
if (json.Items?.some((item) => item.Error)) {
|
|
49
|
-
throw new LoqateAddressLookupError(json);
|
|
50
|
-
}
|
|
51
|
-
return json;
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Builds the Filters query parameter for Loqate API requests.
|
|
56
|
-
* - Filter keys (e.g., "AdministrativeArea", "PostalCode") are predefined by Loqate API (no need to encode)
|
|
57
|
-
* - Filter values (e.g., "New York", "90210") contain user input that may have special characters (need encoding)
|
|
58
|
-
*
|
|
59
|
-
* @returns Empty string if no filters, otherwise "&Filters=key1:value1&key2:value2" (Loqate's expected format for Filters)
|
|
60
|
-
*/
|
|
61
|
-
buildFiltersQuery() {
|
|
62
|
-
if (!__privateGet(this, _filters) || Object.keys(__privateGet(this, _filters)).length === 0) {
|
|
63
|
-
return "";
|
|
64
|
-
}
|
|
65
|
-
const encodedFilters = Object.entries(__privateGet(this, _filters)).map(([key, value]) => `${key}:${encodeURIComponent(value)}`).join("&");
|
|
66
|
-
return `&Filters=${encodedFilters}`;
|
|
67
|
-
}
|
|
68
|
-
search(searchTerm) {
|
|
69
|
-
let url = `${LOQATE_FIND_URL}?Key=${__privateGet(this, _apiKey)}&Text=${searchTerm}&Countries=${__privateGet(this, _countries)?.join(",")}`;
|
|
70
|
-
url += this.buildFiltersQuery();
|
|
71
|
-
return this.fetchFromApi(url);
|
|
72
|
-
}
|
|
73
|
-
findById(id) {
|
|
74
|
-
let url = `${LOQATE_FIND_URL}?Key=${__privateGet(this, _apiKey)}&Container=${id}&Countries=${__privateGet(this, _countries)?.join(",")}`;
|
|
75
|
-
url += this.buildFiltersQuery();
|
|
76
|
-
return this.fetchFromApi(url);
|
|
77
|
-
}
|
|
78
|
-
async get(id) {
|
|
79
|
-
const url = `${LOQATE_RETRIEVE_URL}?Key=${__privateGet(this, _apiKey)}&Id=${id}`;
|
|
80
|
-
const response = await this.fetchFromApi(url);
|
|
81
|
-
return response.Items[0];
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
_baseUrl = new WeakMap();
|
|
85
|
-
_apiKey = new WeakMap();
|
|
86
|
-
_countries = new WeakMap();
|
|
87
|
-
_filters = new WeakMap();
|
|
88
|
-
|
|
89
|
-
export {
|
|
90
|
-
LoqateAddressLookupService
|
|
91
|
-
};
|
|
92
|
-
//# sourceMappingURL=chunk-VVL4B2KD.js.map
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|