@simplybusiness/mobius 4.6.0 → 4.6.3
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 +20 -0
- package/dist/cjs/components/Alert/Alert.js +2 -2
- package/dist/cjs/components/Alert/Alert.js.map +1 -1
- package/dist/cjs/components/Popover/Popover.js +2 -1
- package/dist/cjs/components/Popover/Popover.js.map +1 -1
- package/dist/cjs/hooks/index.js +1 -0
- package/dist/cjs/hooks/index.js.map +1 -1
- package/dist/cjs/hooks/useDialog/useDialog.js +4 -2
- package/dist/cjs/hooks/useDialog/useDialog.js.map +1 -1
- package/dist/cjs/hooks/useDialogPolyfill/useDialogPolyfill.js +14 -18
- package/dist/cjs/hooks/useDialogPolyfill/useDialogPolyfill.js.map +1 -1
- package/dist/esm/components/Alert/Alert.js +3 -3
- package/dist/esm/components/Alert/Alert.js.map +1 -1
- package/dist/esm/components/Popover/Popover.js +2 -1
- package/dist/esm/components/Popover/Popover.js.map +1 -1
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/index.js.map +1 -1
- package/dist/esm/hooks/useDialog/useDialog.js +4 -2
- package/dist/esm/hooks/useDialog/useDialog.js.map +1 -1
- package/dist/esm/hooks/useDialogPolyfill/useDialogPolyfill.js +15 -19
- package/dist/esm/hooks/useDialogPolyfill/useDialogPolyfill.js.map +1 -1
- package/dist/types/hooks/index.d.ts +1 -0
- package/dist/types/hooks/useDialogPolyfill/useDialogPolyfill.d.ts +3 -1
- package/package.json +2 -2
- package/src/components/Alert/Alert.tsx +3 -3
- package/src/components/Button/Button.mdx +6 -2
- package/src/components/Drawer/Drawer.test.tsx +16 -4
- package/src/components/Modal/Modal.test.tsx +14 -4
- package/src/components/Popover/Popover.stories.tsx +3 -41
- package/src/components/Popover/Popover.tsx +6 -1
- package/src/hooks/index.tsx +1 -0
- package/src/hooks/useDialog/useDialog.ts +4 -2
- package/src/hooks/useDialogPolyfill/useDialogPolyfill.ts +22 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.6.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f49a94b: Icons: rename 'question' to 'circleQuestion'; add 'question'; rename 'info' to 'circleInfo'
|
|
8
|
+
- Updated dependencies [f49a94b]
|
|
9
|
+
- @simplybusiness/icons@4.3.1
|
|
10
|
+
|
|
11
|
+
## 4.6.2
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- a06350a: Fix `<TradeSelector>` in Safari 14
|
|
16
|
+
|
|
17
|
+
## 4.6.1
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- 0061f97: Add InsuranceBee partner theme
|
|
22
|
+
|
|
3
23
|
## 4.6.0
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
|
@@ -29,8 +29,8 @@ const Alert = /*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
|
|
|
29
29
|
"--has-header": header
|
|
30
30
|
}, otherProps.className);
|
|
31
31
|
const icon = {
|
|
32
|
-
info: _icons.
|
|
33
|
-
success: _icons.
|
|
32
|
+
info: _icons.circleInfo,
|
|
33
|
+
success: _icons.circleTick,
|
|
34
34
|
warning: _icons.warning,
|
|
35
35
|
error: _icons.error
|
|
36
36
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import { Ref, forwardRef, RefAttributes, ReactNode } from \"react\";\nimport classNames from \"classnames/dedupe\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import { Ref, forwardRef, RefAttributes, ReactNode } from \"react\";\nimport classNames from \"classnames/dedupe\";\nimport { circleInfo, circleTick, warning, error } from \"@simplybusiness/icons\";\nimport { DOMProps } from \"../../types/dom\";\nimport { ForwardedRefComponent } from \"../../types/components\";\nimport { Icon } from \"../Icon\";\n\nexport type AlertElementType = HTMLDivElement;\n\nexport interface AlertProps extends DOMProps, RefAttributes<AlertElementType> {\n children?: ReactNode;\n /** Custom class name for setting specific CSS */\n className?: string;\n elementType?: string | React.ElementType;\n variant?: \"info\" | \"success\" | \"warning\" | \"error\";\n show?: boolean;\n header?: string;\n}\n\nexport type AlertRef = Ref<AlertElementType>;\n\nconst Alert: ForwardedRefComponent<AlertProps, AlertElementType> = forwardRef(\n (props: AlertProps, ref: AlertRef) => {\n const {\n elementType: Element = \"div\",\n variant = \"info\",\n show = true,\n header,\n children,\n ...otherProps\n } = props;\n\n if (!show) return null;\n\n const classes = classNames(\n \"mobius\",\n \"mobius/Alert\",\n {\n \"--info\": variant === \"info\",\n \"--success\": variant === \"success\",\n \"--warning\": variant === \"warning\",\n \"--error\": variant === \"error\",\n \"--has-header\": header,\n },\n otherProps.className,\n );\n const icon = {\n info: circleInfo,\n success: circleTick,\n warning,\n error,\n };\n\n const headerClasses = classNames(\"mobius\", \"mobius/AlertHeader\");\n const iconClasses = classNames(\"mobius\", \"mobius/AlertIcon\");\n const contentClasses = classNames(\"mobius\", \"mobius/AlertContent\");\n\n return (\n <Element ref={ref} role=\"alert\" {...otherProps} className={classes}>\n <span className={iconClasses}>\n <Icon icon={icon[variant]} />\n </span>\n <div>\n {header && <p className={headerClasses}>{header}</p>}\n <div className={contentClasses}>{children}</div>\n </div>\n </Element>\n );\n },\n);\n\nAlert.displayName = \"Alert\";\nexport { Alert };\n"],"names":["Alert","forwardRef","props","ref","elementType","Element","variant","show","header","children","otherProps","classes","classNames","className","icon","info","circleInfo","success","circleTick","warning","error","headerClasses","iconClasses","contentClasses","role","span","Icon","div","p","displayName"],"mappings":";;;;+BAwESA;;;eAAAA;;;;uBAxEiD;+DACnC;uBACgC;sBAGlC;;;;;;AAgBrB,MAAMA,sBAA6DC,IAAAA,iBAAU,EAC3E,CAACC,OAAmBC;IAClB,MAAM,EACJC,aAAaC,UAAU,KAAK,EAC5BC,UAAU,MAAM,EAChBC,OAAO,IAAI,EACXC,MAAM,EACNC,QAAQ,EACR,GAAGC,YACJ,GAAGR;IAEJ,IAAI,CAACK,MAAM,OAAO;IAElB,MAAMI,UAAUC,IAAAA,eAAU,EACxB,UACA,gBACA;QACE,UAAUN,YAAY;QACtB,aAAaA,YAAY;QACzB,aAAaA,YAAY;QACzB,WAAWA,YAAY;QACvB,gBAAgBE;IAClB,GACAE,WAAWG,SAAS;IAEtB,MAAMC,OAAO;QACXC,MAAMC,iBAAU;QAChBC,SAASC,iBAAU;QACnBC,SAAAA,cAAO;QACPC,OAAAA,YAAK;IACP;IAEA,MAAMC,gBAAgBT,IAAAA,eAAU,EAAC,UAAU;IAC3C,MAAMU,cAAcV,IAAAA,eAAU,EAAC,UAAU;IACzC,MAAMW,iBAAiBX,IAAAA,eAAU,EAAC,UAAU;IAE5C,qBACE,sBAACP;QAAQF,KAAKA;QAAKqB,MAAK;QAAS,GAAGd,UAAU;QAAEG,WAAWF;;0BACzD,qBAACc;gBAAKZ,WAAWS;0BACf,cAAA,qBAACI,UAAI;oBAACZ,MAAMA,IAAI,CAACR,QAAQ;;;0BAE3B,sBAACqB;;oBACEnB,wBAAU,qBAACoB;wBAAEf,WAAWQ;kCAAgBb;;kCACzC,qBAACmB;wBAAId,WAAWU;kCAAiBd;;;;;;AAIzC;AAGFT,MAAM6B,WAAW,GAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Popover/Popover.tsx"],"sourcesContent":["import {\n FloatingArrow,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useDismiss,\n useFloating,\n useInteractions,\n} from \"@floating-ui/react\";\nimport { cross } from \"@simplybusiness/icons\";\nimport classNames from \"classnames\";\nimport {\n ReactElement,\n ReactNode,\n Ref,\n RefAttributes,\n cloneElement,\n useRef,\n useState,\n} from \"react\";\nimport { useWindowEvent } from \"../../hooks\";\nimport { DOMProps } from \"../../types\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\n\nexport type PopoverElementType = HTMLDivElement;\n\nexport interface PopoverProps\n extends DOMProps,\n RefAttributes<PopoverElementType> {\n children?: ReactNode;\n trigger: ReactElement;\n /** Callback that fires each time the accordion is opened */\n onOpen?: () => void;\n /** Callback that fires each time the accordion is closed */\n onClose?: () => void;\n /** Custom class name for setting specific CSS */\n className?: string;\n}\n\nexport type PopoverRef = Ref<PopoverElementType>;\n\nconst OFFSET_FROM_CONTENT_DEFAULT = 10;\n\nexport const Popover = (props: PopoverProps) => {\n const { trigger, children, onOpen, onClose, className } = props;\n const arrowRef = useRef(null);\n const [isOpen, setIsOpen] = useState(false);\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: setIsOpen,\n whileElementsMounted: autoUpdate,\n middleware: [\n arrow({\n element: arrowRef,\n }),\n offset(OFFSET_FROM_CONTENT_DEFAULT),\n shift(),\n flip(),\n ],\n });\n const dismiss = useDismiss(context, {\n bubbles: true,\n outsidePress: (event: MouseEvent) => {\n // Prevent 'onClose' from firing when clicking the toggle to close\n const toggle = refs.reference.current as HTMLElement;\n const isToggleClick = !toggle?.contains(event.target as HTMLElement);\n if (isToggleClick) {\n onClose?.();\n }\n return true;\n },\n });\n const { getReferenceProps, getFloatingProps } = useInteractions([dismiss]);\n\n const containerClasses = classNames(\n \"mobius\",\n \"mobius/PopoverContainer\",\n className,\n );\n\n const toggleVisibility = () => {\n if (isOpen) {\n setIsOpen(false);\n onClose?.();\n return;\n }\n\n setIsOpen(true);\n onOpen?.();\n };\n\n const triggerComponent = cloneElement(trigger, {\n ref: refs.setReference,\n className: classNames(trigger.props.className, \"mobius/PopoverToggle\"),\n onClick: toggleVisibility,\n ...getReferenceProps(),\n });\n\n useWindowEvent(\"keydown\", e => {\n if (e.key === \"Escape\") {\n onClose?.();\n e.preventDefault();\n e.stopPropagation();\n }\n });\n\n return (\n <>\n {triggerComponent}\n {isOpen && (\n <div\n className={containerClasses}\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n <div className=\"mobius/Popover\">\n <header className=\"mobius/PopoverHeader\">\n <Button\n type=\"button\"\n className=\"mobius/PopoverCloseButton\"\n onClick={toggleVisibility}\n aria-label=\"Close\"\n variant=\"ghost\"\n >\n <Icon\n icon={cross}\n size=\"md\"\n className=\"mobius/PopoverCloseIcon\"\n />\n </Button>\n </header>\n <div className=\"mobius/PopoverBody\">{children}</div>\n </div>\n <FloatingArrow
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Popover/Popover.tsx"],"sourcesContent":["import {\n FloatingArrow,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useDismiss,\n useFloating,\n useInteractions,\n} from \"@floating-ui/react\";\nimport { cross } from \"@simplybusiness/icons\";\nimport classNames from \"classnames\";\nimport {\n ReactElement,\n ReactNode,\n Ref,\n RefAttributes,\n cloneElement,\n useRef,\n useState,\n} from \"react\";\nimport { useWindowEvent } from \"../../hooks\";\nimport { DOMProps } from \"../../types\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\n\nexport type PopoverElementType = HTMLDivElement;\n\nexport interface PopoverProps\n extends DOMProps,\n RefAttributes<PopoverElementType> {\n children?: ReactNode;\n trigger: ReactElement;\n /** Callback that fires each time the accordion is opened */\n onOpen?: () => void;\n /** Callback that fires each time the accordion is closed */\n onClose?: () => void;\n /** Custom class name for setting specific CSS */\n className?: string;\n}\n\nexport type PopoverRef = Ref<PopoverElementType>;\n\nconst OFFSET_FROM_CONTENT_DEFAULT = 10;\n\nexport const Popover = (props: PopoverProps) => {\n const { trigger, children, onOpen, onClose, className } = props;\n const arrowRef = useRef(null);\n const [isOpen, setIsOpen] = useState(false);\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: setIsOpen,\n whileElementsMounted: autoUpdate,\n middleware: [\n arrow({\n element: arrowRef,\n }),\n offset(OFFSET_FROM_CONTENT_DEFAULT),\n shift(),\n flip(),\n ],\n });\n const dismiss = useDismiss(context, {\n bubbles: true,\n outsidePress: (event: MouseEvent) => {\n // Prevent 'onClose' from firing when clicking the toggle to close\n const toggle = refs.reference.current as HTMLElement;\n const isToggleClick = !toggle?.contains(event.target as HTMLElement);\n if (isToggleClick) {\n onClose?.();\n }\n return true;\n },\n });\n const { getReferenceProps, getFloatingProps } = useInteractions([dismiss]);\n\n const containerClasses = classNames(\n \"mobius\",\n \"mobius/PopoverContainer\",\n className,\n );\n\n const toggleVisibility = () => {\n if (isOpen) {\n setIsOpen(false);\n onClose?.();\n return;\n }\n\n setIsOpen(true);\n onOpen?.();\n };\n\n const triggerComponent = cloneElement(trigger, {\n ref: refs.setReference,\n className: classNames(trigger.props.className, \"mobius/PopoverToggle\"),\n onClick: toggleVisibility,\n ...getReferenceProps(),\n });\n\n useWindowEvent(\"keydown\", e => {\n if (e.key === \"Escape\") {\n onClose?.();\n e.preventDefault();\n e.stopPropagation();\n }\n });\n\n return (\n <>\n {triggerComponent}\n {isOpen && (\n <div\n className={containerClasses}\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n <div className=\"mobius/Popover\">\n <header className=\"mobius/PopoverHeader\">\n <Button\n type=\"button\"\n className=\"mobius/PopoverCloseButton\"\n onClick={toggleVisibility}\n aria-label=\"Close\"\n variant=\"ghost\"\n >\n <Icon\n icon={cross}\n size=\"md\"\n className=\"mobius/PopoverCloseIcon\"\n />\n </Button>\n </header>\n <div className=\"mobius/PopoverBody\">{children}</div>\n </div>\n <FloatingArrow\n ref={arrowRef}\n context={context}\n width={20}\n className=\"mobius/PopoverArrowIcon\"\n />\n </div>\n )}\n </>\n );\n};\n"],"names":["Popover","OFFSET_FROM_CONTENT_DEFAULT","props","trigger","children","onOpen","onClose","className","arrowRef","useRef","isOpen","setIsOpen","useState","refs","floatingStyles","context","useFloating","open","onOpenChange","whileElementsMounted","autoUpdate","middleware","arrow","element","offset","shift","flip","dismiss","useDismiss","bubbles","outsidePress","event","toggle","reference","current","isToggleClick","contains","target","getReferenceProps","getFloatingProps","useInteractions","containerClasses","classNames","toggleVisibility","triggerComponent","cloneElement","ref","setReference","onClick","useWindowEvent","e","key","preventDefault","stopPropagation","div","setFloating","style","header","Button","type","aria-label","variant","Icon","icon","cross","size","FloatingArrow","width"],"mappings":";;;;+BA8CaA;;;eAAAA;;;;uBApCN;uBACe;mEACC;wBAShB;uBACwB;wBAER;sBACF;;;;;;AAmBrB,MAAMC,8BAA8B;AAE7B,MAAMD,UAAU,CAACE;IACtB,MAAM,EAAEC,OAAO,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAEC,SAAS,EAAE,GAAGL;IAC1D,MAAMM,WAAWC,IAAAA,cAAM,EAAC;IACxB,MAAM,CAACC,QAAQC,UAAU,GAAGC,IAAAA,gBAAQ,EAAC;IACrC,MAAM,EAAEC,IAAI,EAAEC,cAAc,EAAEC,OAAO,EAAE,GAAGC,IAAAA,kBAAW,EAAC;QACpDC,MAAMP;QACNQ,cAAcP;QACdQ,sBAAsBC,iBAAU;QAChCC,YAAY;YACVC,IAAAA,YAAK,EAAC;gBACJC,SAASf;YACX;YACAgB,IAAAA,aAAM,EAACvB;YACPwB,IAAAA,YAAK;YACLC,IAAAA,WAAI;SACL;IACH;IACA,MAAMC,UAAUC,IAAAA,iBAAU,EAACb,SAAS;QAClCc,SAAS;QACTC,cAAc,CAACC;YACb,kEAAkE;YAClE,MAAMC,SAASnB,KAAKoB,SAAS,CAACC,OAAO;YACrC,MAAMC,gBAAgB,EAACH,mBAAAA,6BAAAA,OAAQI,QAAQ,CAACL,MAAMM,MAAM;YACpD,IAAIF,eAAe;gBACjB7B,oBAAAA,8BAAAA;YACF;YACA,OAAO;QACT;IACF;IACA,MAAM,EAAEgC,iBAAiB,EAAEC,gBAAgB,EAAE,GAAGC,IAAAA,sBAAe,EAAC;QAACb;KAAQ;IAEzE,MAAMc,mBAAmBC,IAAAA,mBAAU,EACjC,UACA,2BACAnC;IAGF,MAAMoC,mBAAmB;QACvB,IAAIjC,QAAQ;YACVC,UAAU;YACVL,oBAAAA,8BAAAA;YACA;QACF;QAEAK,UAAU;QACVN,mBAAAA,6BAAAA;IACF;IAEA,MAAMuC,iCAAmBC,IAAAA,oBAAY,EAAC1C,SAAS;QAC7C2C,KAAKjC,KAAKkC,YAAY;QACtBxC,WAAWmC,IAAAA,mBAAU,EAACvC,QAAQD,KAAK,CAACK,SAAS,EAAE;QAC/CyC,SAASL;QACT,GAAGL,mBAAmB;IACxB;IAEAW,IAAAA,qBAAc,EAAC,WAAWC,CAAAA;QACxB,IAAIA,EAAEC,GAAG,KAAK,UAAU;YACtB7C,oBAAAA,8BAAAA;YACA4C,EAAEE,cAAc;YAChBF,EAAEG,eAAe;QACnB;IACF;IAEA,qBACE;;YACGT;YACAlC,wBACC,sBAAC4C;gBACC/C,WAAWkC;gBACXK,KAAKjC,KAAK0C,WAAW;gBACrBC,OAAO1C;gBACN,GAAGyB,kBAAkB;;kCAEtB,sBAACe;wBAAI/C,WAAU;;0CACb,qBAACkD;gCAAOlD,WAAU;0CAChB,cAAA,qBAACmD,cAAM;oCACLC,MAAK;oCACLpD,WAAU;oCACVyC,SAASL;oCACTiB,cAAW;oCACXC,SAAQ;8CAER,cAAA,qBAACC,UAAI;wCACHC,MAAMC,YAAK;wCACXC,MAAK;wCACL1D,WAAU;;;;0CAIhB,qBAAC+C;gCAAI/C,WAAU;0CAAsBH;;;;kCAEvC,qBAAC8D,oBAAa;wBACZpB,KAAKtC;wBACLO,SAASA;wBACToD,OAAO;wBACP5D,WAAU;;;;;;AAMtB"}
|
package/dist/cjs/hooks/index.js
CHANGED
|
@@ -6,6 +6,7 @@ _export_star(require("./useBodyScrollLock"), exports);
|
|
|
6
6
|
_export_star(require("./useBreakpoint"), exports);
|
|
7
7
|
_export_star(require("./useButton"), exports);
|
|
8
8
|
_export_star(require("./useDialog"), exports);
|
|
9
|
+
_export_star(require("./useDialogPolyfill"), exports);
|
|
9
10
|
_export_star(require("./useLabel"), exports);
|
|
10
11
|
_export_star(require("./useOnClickOutside"), exports);
|
|
11
12
|
_export_star(require("./useTextField"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/index.tsx"],"sourcesContent":["export * from \"./useBodyScrollLock\";\nexport * from \"./useBreakpoint\";\nexport * from \"./useButton\";\nexport * from \"./useDialog\";\nexport * from \"./useLabel\";\nexport * from \"./useOnClickOutside\";\nexport * from \"./useTextField\";\nexport * from \"./useWindowEvent\";\n"],"names":[],"mappings":";;;;qBAAc;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA"}
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/index.tsx"],"sourcesContent":["export * from \"./useBodyScrollLock\";\nexport * from \"./useBreakpoint\";\nexport * from \"./useButton\";\nexport * from \"./useDialog\";\nexport * from \"./useDialogPolyfill\";\nexport * from \"./useLabel\";\nexport * from \"./useOnClickOutside\";\nexport * from \"./useTextField\";\nexport * from \"./useWindowEvent\";\n"],"names":[],"mappings":";;;;qBAAc;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA;qBACA"}
|
|
@@ -17,9 +17,9 @@ const FALLBACK_TRANSITION_DURATION = 0;
|
|
|
17
17
|
const useDialog = (props)=>{
|
|
18
18
|
const { ref, isOpen, transition, onOpen, onClose } = props;
|
|
19
19
|
const shouldTransition = (0, _utils.supportsDialog)() && transition.isEnabled;
|
|
20
|
+
const { polyfillDialog } = (0, _useDialogPolyfill.useDialogPolyfill)();
|
|
20
21
|
// Read CSS variable value as number
|
|
21
22
|
const TRANSITION_DURATION_IN_MS = ref.current && Number(getComputedStyle(ref.current).getPropertyValue(transition.CSSVariable).replace("ms", "")) || FALLBACK_TRANSITION_DURATION;
|
|
22
|
-
(0, _useDialogPolyfill.useDialogPolyfill)(ref);
|
|
23
23
|
(0, _useBodyScrollLock.useBodyScrollLock)({
|
|
24
24
|
enabled: isOpen
|
|
25
25
|
});
|
|
@@ -67,6 +67,7 @@ const useDialog = (props)=>{
|
|
|
67
67
|
async function toggleDialog() {
|
|
68
68
|
var _ref_current, _ref_current1;
|
|
69
69
|
if (isOpen && !((_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.open)) {
|
|
70
|
+
await polyfillDialog(ref);
|
|
70
71
|
open();
|
|
71
72
|
// Fix opening transition in Safari being skipped
|
|
72
73
|
// by wrapping with setTimeout
|
|
@@ -83,7 +84,8 @@ const useDialog = (props)=>{
|
|
|
83
84
|
handleClose,
|
|
84
85
|
isOpen,
|
|
85
86
|
open,
|
|
86
|
-
ref
|
|
87
|
+
ref,
|
|
88
|
+
polyfillDialog
|
|
87
89
|
]);
|
|
88
90
|
return {
|
|
89
91
|
open,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/hooks/useDialog/useDialog.ts"],"sourcesContent":["import {\n MutableRefObject,\n SyntheticEvent,\n useCallback,\n useEffect,\n} from \"react\";\nimport { useDialogPolyfill } from \"../useDialogPolyfill\";\nimport { useBodyScrollLock } from \"../useBodyScrollLock\";\nimport { supportsDialog } from \"../../utils\";\n\nexport type TransitionProps = {\n isEnabled: boolean;\n CSSVariable: string;\n};\n\nexport type useDialogProps = {\n ref: MutableRefObject<HTMLDialogElement | null>;\n transition: TransitionProps;\n isOpen: boolean;\n onOpen?: () => void;\n onClose?: () => void;\n};\n\nconst TRANSITION_CLASS_NAME = \"--transition\";\nconst FALLBACK_TRANSITION_DURATION = 0;\n\nexport const useDialog = (props: useDialogProps) => {\n const { ref, isOpen, transition, onOpen, onClose } = props;\n const shouldTransition = supportsDialog() && transition.isEnabled;\n\n // Read CSS variable value as number\n const TRANSITION_DURATION_IN_MS =\n (ref.current &&\n Number(\n getComputedStyle(ref.current)\n .getPropertyValue(transition.CSSVariable)\n .replace(\"ms\", \"\"),\n )) ||\n FALLBACK_TRANSITION_DURATION;\n\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/hooks/useDialog/useDialog.ts"],"sourcesContent":["import {\n MutableRefObject,\n SyntheticEvent,\n useCallback,\n useEffect,\n} from \"react\";\nimport { useDialogPolyfill } from \"../useDialogPolyfill\";\nimport { useBodyScrollLock } from \"../useBodyScrollLock\";\nimport { supportsDialog } from \"../../utils\";\n\nexport type TransitionProps = {\n isEnabled: boolean;\n CSSVariable: string;\n};\n\nexport type useDialogProps = {\n ref: MutableRefObject<HTMLDialogElement | null>;\n transition: TransitionProps;\n isOpen: boolean;\n onOpen?: () => void;\n onClose?: () => void;\n};\n\nconst TRANSITION_CLASS_NAME = \"--transition\";\nconst FALLBACK_TRANSITION_DURATION = 0;\n\nexport const useDialog = (props: useDialogProps) => {\n const { ref, isOpen, transition, onOpen, onClose } = props;\n const shouldTransition = supportsDialog() && transition.isEnabled;\n const { polyfillDialog } = useDialogPolyfill();\n\n // Read CSS variable value as number\n const TRANSITION_DURATION_IN_MS =\n (ref.current &&\n Number(\n getComputedStyle(ref.current)\n .getPropertyValue(transition.CSSVariable)\n .replace(\"ms\", \"\"),\n )) ||\n FALLBACK_TRANSITION_DURATION;\n\n useBodyScrollLock({ enabled: isOpen });\n\n const open = useCallback(() => {\n ref.current?.showModal();\n onOpen?.();\n }, [onOpen, ref]);\n\n const close = useCallback(() => {\n ref.current?.close();\n onClose?.();\n }, [onClose, ref]);\n\n // Add close handler, to enable closing transitions\n const handleClose = useCallback(\n (event?: SyntheticEvent<HTMLElement, Event>) => {\n if (event) {\n // Prevent default event coming from onCancel,\n // which is triggered by pressing ESC key\n event.preventDefault();\n // Ensure that nested `<dialog>` elements\n // don't close the parent\n event.stopPropagation();\n }\n\n if (shouldTransition) {\n ref.current?.classList.remove(TRANSITION_CLASS_NAME);\n // Delay close to allow exit transition\n setTimeout(() => close(), TRANSITION_DURATION_IN_MS);\n } else {\n close();\n }\n },\n [TRANSITION_DURATION_IN_MS, close, ref, shouldTransition],\n );\n\n useEffect(() => {\n async function toggleDialog() {\n if (isOpen && !ref.current?.open) {\n await polyfillDialog(ref);\n\n open();\n // Fix opening transition in Safari being skipped\n // by wrapping with setTimeout\n setTimeout(() => {\n ref.current?.classList.add(TRANSITION_CLASS_NAME);\n }, 0);\n } else if (!isOpen && ref.current?.open) {\n handleClose();\n }\n }\n\n toggleDialog();\n }, [handleClose, isOpen, open, ref, polyfillDialog]);\n\n return {\n open,\n close: handleClose,\n };\n};\n"],"names":["useDialog","TRANSITION_CLASS_NAME","FALLBACK_TRANSITION_DURATION","props","ref","isOpen","transition","onOpen","onClose","shouldTransition","supportsDialog","isEnabled","polyfillDialog","useDialogPolyfill","TRANSITION_DURATION_IN_MS","current","Number","getComputedStyle","getPropertyValue","CSSVariable","replace","useBodyScrollLock","enabled","open","useCallback","showModal","close","handleClose","event","preventDefault","stopPropagation","classList","remove","setTimeout","useEffect","toggleDialog","add"],"mappings":";;;;+BA0BaA;;;eAAAA;;;uBArBN;mCAC2B;mCACA;uBACH;AAe/B,MAAMC,wBAAwB;AAC9B,MAAMC,+BAA+B;AAE9B,MAAMF,YAAY,CAACG;IACxB,MAAM,EAAEC,GAAG,EAAEC,MAAM,EAAEC,UAAU,EAAEC,MAAM,EAAEC,OAAO,EAAE,GAAGL;IACrD,MAAMM,mBAAmBC,IAAAA,qBAAc,OAAMJ,WAAWK,SAAS;IACjE,MAAM,EAAEC,cAAc,EAAE,GAAGC,IAAAA,oCAAiB;IAE5C,oCAAoC;IACpC,MAAMC,4BACJ,AAACV,IAAIW,OAAO,IACVC,OACEC,iBAAiBb,IAAIW,OAAO,EACzBG,gBAAgB,CAACZ,WAAWa,WAAW,EACvCC,OAAO,CAAC,MAAM,QAErBlB;IAEFmB,IAAAA,oCAAiB,EAAC;QAAEC,SAASjB;IAAO;IAEpC,MAAMkB,OAAOC,IAAAA,kBAAW,EAAC;YACvBpB;SAAAA,eAAAA,IAAIW,OAAO,cAAXX,mCAAAA,aAAaqB,SAAS;QACtBlB,mBAAAA,6BAAAA;IACF,GAAG;QAACA;QAAQH;KAAI;IAEhB,MAAMsB,QAAQF,IAAAA,kBAAW,EAAC;YACxBpB;SAAAA,eAAAA,IAAIW,OAAO,cAAXX,mCAAAA,aAAasB,KAAK;QAClBlB,oBAAAA,8BAAAA;IACF,GAAG;QAACA;QAASJ;KAAI;IAEjB,mDAAmD;IACnD,MAAMuB,cAAcH,IAAAA,kBAAW,EAC7B,CAACI;QACC,IAAIA,OAAO;YACT,8CAA8C;YAC9C,yCAAyC;YACzCA,MAAMC,cAAc;YACpB,yCAAyC;YACzC,yBAAyB;YACzBD,MAAME,eAAe;QACvB;QAEA,IAAIrB,kBAAkB;gBACpBL;aAAAA,eAAAA,IAAIW,OAAO,cAAXX,mCAAAA,aAAa2B,SAAS,CAACC,MAAM,CAAC/B;YAC9B,uCAAuC;YACvCgC,WAAW,IAAMP,SAASZ;QAC5B,OAAO;YACLY;QACF;IACF,GACA;QAACZ;QAA2BY;QAAOtB;QAAKK;KAAiB;IAG3DyB,IAAAA,gBAAS,EAAC;QACR,eAAeC;gBACE/B,cASOA;YATtB,IAAIC,UAAU,GAACD,eAAAA,IAAIW,OAAO,cAAXX,mCAAAA,aAAamB,IAAI,GAAE;gBAChC,MAAMX,eAAeR;gBAErBmB;gBACA,iDAAiD;gBACjD,8BAA8B;gBAC9BU,WAAW;wBACT7B;qBAAAA,eAAAA,IAAIW,OAAO,cAAXX,mCAAAA,aAAa2B,SAAS,CAACK,GAAG,CAACnC;gBAC7B,GAAG;YACL,OAAO,IAAI,CAACI,YAAUD,gBAAAA,IAAIW,OAAO,cAAXX,oCAAAA,cAAamB,IAAI,GAAE;gBACvCI;YACF;QACF;QAEAQ;IACF,GAAG;QAACR;QAAatB;QAAQkB;QAAMnB;QAAKQ;KAAe;IAEnD,OAAO;QACLW;QACAG,OAAOC;IACT;AACF"}
|
|
@@ -51,27 +51,23 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
51
51
|
}
|
|
52
52
|
return newObj;
|
|
53
53
|
}
|
|
54
|
-
const useDialogPolyfill = (
|
|
54
|
+
const useDialogPolyfill = ()=>{
|
|
55
55
|
const hasDialogSupport = (0, _utils.supportsDialog)();
|
|
56
|
-
(0, _react.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// Checking showModal presence through hasOwnProperty is falsy natively, truthy with polyfill 🤷🏼♂️
|
|
66
|
-
console.error("Failed to load dialog-polyfill", error);
|
|
67
|
-
}
|
|
56
|
+
const hasAlreadyLoaded = (0, _react.useRef)(false);
|
|
57
|
+
const polyfillDialog = async (ref)=>{
|
|
58
|
+
if (!hasAlreadyLoaded.current && !hasDialogSupport && typeof window !== "undefined" && ref.current !== null) {
|
|
59
|
+
const { default: dialogPolyfill } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("dialog-polyfill")));
|
|
60
|
+
hasAlreadyLoaded.current = true;
|
|
61
|
+
try {
|
|
62
|
+
dialogPolyfill.registerDialog(ref.current);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error("Failed to load dialog-polyfill", error);
|
|
68
65
|
}
|
|
69
66
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
]);
|
|
67
|
+
};
|
|
68
|
+
return {
|
|
69
|
+
polyfillDialog
|
|
70
|
+
};
|
|
75
71
|
};
|
|
76
72
|
|
|
77
73
|
//# sourceMappingURL=useDialogPolyfill.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/hooks/useDialogPolyfill/useDialogPolyfill.ts"],"sourcesContent":["import { MutableRefObject,
|
|
1
|
+
{"version":3,"sources":["../../../../src/hooks/useDialogPolyfill/useDialogPolyfill.ts"],"sourcesContent":["import { MutableRefObject, useRef } from \"react\";\nimport { supportsDialog } from \"../../utils\";\n\n// Add polyfill for HTML Dialog in old browsers\nexport const useDialogPolyfill = () => {\n const hasDialogSupport = supportsDialog();\n const hasAlreadyLoaded = useRef(false);\n\n const polyfillDialog = async (\n ref: MutableRefObject<HTMLDialogElement | null>,\n ) => {\n if (\n !hasAlreadyLoaded.current &&\n !hasDialogSupport &&\n typeof window !== \"undefined\" &&\n ref.current !== null\n ) {\n const { default: dialogPolyfill } = await import(\"dialog-polyfill\");\n hasAlreadyLoaded.current = true;\n\n try {\n dialogPolyfill.registerDialog(ref.current);\n } catch (error) {\n console.error(\"Failed to load dialog-polyfill\", error);\n }\n }\n };\n\n return {\n polyfillDialog,\n };\n};\n"],"names":["useDialogPolyfill","hasDialogSupport","supportsDialog","hasAlreadyLoaded","useRef","polyfillDialog","ref","current","window","default","dialogPolyfill","registerDialog","error","console"],"mappings":";;;;+BAIaA;;;eAAAA;;;uBAJ4B;uBACV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGxB,MAAMA,oBAAoB;IAC/B,MAAMC,mBAAmBC,IAAAA,qBAAc;IACvC,MAAMC,mBAAmBC,IAAAA,aAAM,EAAC;IAEhC,MAAMC,iBAAiB,OACrBC;QAEA,IACE,CAACH,iBAAiBI,OAAO,IACzB,CAACN,oBACD,OAAOO,WAAW,eAClBF,IAAIC,OAAO,KAAK,MAChB;YACA,MAAM,EAAEE,SAASC,cAAc,EAAE,GAAG,MAAM,mEAAA,QAAO;YACjDP,iBAAiBI,OAAO,GAAG;YAE3B,IAAI;gBACFG,eAAeC,cAAc,CAACL,IAAIC,OAAO;YAC3C,EAAE,OAAOK,OAAO;gBACdC,QAAQD,KAAK,CAAC,kCAAkCA;YAClD;QACF;IACF;IAEA,OAAO;QACLP;IACF;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import classNames from "classnames/dedupe";
|
|
4
|
-
import {
|
|
4
|
+
import { circleInfo, circleTick, warning, error } from "@simplybusiness/icons";
|
|
5
5
|
import { Icon } from "../Icon";
|
|
6
6
|
const Alert = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
7
7
|
const { elementType: Element = "div", variant = "info", show = true, header, children, ...otherProps } = props;
|
|
@@ -14,8 +14,8 @@ const Alert = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
14
14
|
"--has-header": header
|
|
15
15
|
}, otherProps.className);
|
|
16
16
|
const icon = {
|
|
17
|
-
info,
|
|
18
|
-
success,
|
|
17
|
+
info: circleInfo,
|
|
18
|
+
success: circleTick,
|
|
19
19
|
warning,
|
|
20
20
|
error
|
|
21
21
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import { Ref, forwardRef, RefAttributes, ReactNode } from \"react\";\nimport classNames from \"classnames/dedupe\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import { Ref, forwardRef, RefAttributes, ReactNode } from \"react\";\nimport classNames from \"classnames/dedupe\";\nimport { circleInfo, circleTick, warning, error } from \"@simplybusiness/icons\";\nimport { DOMProps } from \"../../types/dom\";\nimport { ForwardedRefComponent } from \"../../types/components\";\nimport { Icon } from \"../Icon\";\n\nexport type AlertElementType = HTMLDivElement;\n\nexport interface AlertProps extends DOMProps, RefAttributes<AlertElementType> {\n children?: ReactNode;\n /** Custom class name for setting specific CSS */\n className?: string;\n elementType?: string | React.ElementType;\n variant?: \"info\" | \"success\" | \"warning\" | \"error\";\n show?: boolean;\n header?: string;\n}\n\nexport type AlertRef = Ref<AlertElementType>;\n\nconst Alert: ForwardedRefComponent<AlertProps, AlertElementType> = forwardRef(\n (props: AlertProps, ref: AlertRef) => {\n const {\n elementType: Element = \"div\",\n variant = \"info\",\n show = true,\n header,\n children,\n ...otherProps\n } = props;\n\n if (!show) return null;\n\n const classes = classNames(\n \"mobius\",\n \"mobius/Alert\",\n {\n \"--info\": variant === \"info\",\n \"--success\": variant === \"success\",\n \"--warning\": variant === \"warning\",\n \"--error\": variant === \"error\",\n \"--has-header\": header,\n },\n otherProps.className,\n );\n const icon = {\n info: circleInfo,\n success: circleTick,\n warning,\n error,\n };\n\n const headerClasses = classNames(\"mobius\", \"mobius/AlertHeader\");\n const iconClasses = classNames(\"mobius\", \"mobius/AlertIcon\");\n const contentClasses = classNames(\"mobius\", \"mobius/AlertContent\");\n\n return (\n <Element ref={ref} role=\"alert\" {...otherProps} className={classes}>\n <span className={iconClasses}>\n <Icon icon={icon[variant]} />\n </span>\n <div>\n {header && <p className={headerClasses}>{header}</p>}\n <div className={contentClasses}>{children}</div>\n </div>\n </Element>\n );\n },\n);\n\nAlert.displayName = \"Alert\";\nexport { Alert };\n"],"names":["forwardRef","classNames","circleInfo","circleTick","warning","error","Icon","Alert","props","ref","elementType","Element","variant","show","header","children","otherProps","classes","className","icon","info","success","headerClasses","iconClasses","contentClasses","role","span","div","p","displayName"],"mappings":";AAAA,SAAcA,UAAU,QAAkC,QAAQ;AAClE,OAAOC,gBAAgB,oBAAoB;AAC3C,SAASC,UAAU,EAAEC,UAAU,EAAEC,OAAO,EAAEC,KAAK,QAAQ,wBAAwB;AAG/E,SAASC,IAAI,QAAQ,UAAU;AAgB/B,MAAMC,sBAA6DP,WACjE,CAACQ,OAAmBC;IAClB,MAAM,EACJC,aAAaC,UAAU,KAAK,EAC5BC,UAAU,MAAM,EAChBC,OAAO,IAAI,EACXC,MAAM,EACNC,QAAQ,EACR,GAAGC,YACJ,GAAGR;IAEJ,IAAI,CAACK,MAAM,OAAO;IAElB,MAAMI,UAAUhB,WACd,UACA,gBACA;QACE,UAAUW,YAAY;QACtB,aAAaA,YAAY;QACzB,aAAaA,YAAY;QACzB,WAAWA,YAAY;QACvB,gBAAgBE;IAClB,GACAE,WAAWE,SAAS;IAEtB,MAAMC,OAAO;QACXC,MAAMlB;QACNmB,SAASlB;QACTC;QACAC;IACF;IAEA,MAAMiB,gBAAgBrB,WAAW,UAAU;IAC3C,MAAMsB,cAActB,WAAW,UAAU;IACzC,MAAMuB,iBAAiBvB,WAAW,UAAU;IAE5C,qBACE,MAACU;QAAQF,KAAKA;QAAKgB,MAAK;QAAS,GAAGT,UAAU;QAAEE,WAAWD;;0BACzD,KAACS;gBAAKR,WAAWK;0BACf,cAAA,KAACjB;oBAAKa,MAAMA,IAAI,CAACP,QAAQ;;;0BAE3B,MAACe;;oBACEb,wBAAU,KAACc;wBAAEV,WAAWI;kCAAgBR;;kCACzC,KAACa;wBAAIT,WAAWM;kCAAiBT;;;;;;AAIzC;AAGFR,MAAMsB,WAAW,GAAG;AACpB,SAAStB,KAAK,GAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Popover/Popover.tsx"],"sourcesContent":["import {\n FloatingArrow,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useDismiss,\n useFloating,\n useInteractions,\n} from \"@floating-ui/react\";\nimport { cross } from \"@simplybusiness/icons\";\nimport classNames from \"classnames\";\nimport {\n ReactElement,\n ReactNode,\n Ref,\n RefAttributes,\n cloneElement,\n useRef,\n useState,\n} from \"react\";\nimport { useWindowEvent } from \"../../hooks\";\nimport { DOMProps } from \"../../types\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\n\nexport type PopoverElementType = HTMLDivElement;\n\nexport interface PopoverProps\n extends DOMProps,\n RefAttributes<PopoverElementType> {\n children?: ReactNode;\n trigger: ReactElement;\n /** Callback that fires each time the accordion is opened */\n onOpen?: () => void;\n /** Callback that fires each time the accordion is closed */\n onClose?: () => void;\n /** Custom class name for setting specific CSS */\n className?: string;\n}\n\nexport type PopoverRef = Ref<PopoverElementType>;\n\nconst OFFSET_FROM_CONTENT_DEFAULT = 10;\n\nexport const Popover = (props: PopoverProps) => {\n const { trigger, children, onOpen, onClose, className } = props;\n const arrowRef = useRef(null);\n const [isOpen, setIsOpen] = useState(false);\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: setIsOpen,\n whileElementsMounted: autoUpdate,\n middleware: [\n arrow({\n element: arrowRef,\n }),\n offset(OFFSET_FROM_CONTENT_DEFAULT),\n shift(),\n flip(),\n ],\n });\n const dismiss = useDismiss(context, {\n bubbles: true,\n outsidePress: (event: MouseEvent) => {\n // Prevent 'onClose' from firing when clicking the toggle to close\n const toggle = refs.reference.current as HTMLElement;\n const isToggleClick = !toggle?.contains(event.target as HTMLElement);\n if (isToggleClick) {\n onClose?.();\n }\n return true;\n },\n });\n const { getReferenceProps, getFloatingProps } = useInteractions([dismiss]);\n\n const containerClasses = classNames(\n \"mobius\",\n \"mobius/PopoverContainer\",\n className,\n );\n\n const toggleVisibility = () => {\n if (isOpen) {\n setIsOpen(false);\n onClose?.();\n return;\n }\n\n setIsOpen(true);\n onOpen?.();\n };\n\n const triggerComponent = cloneElement(trigger, {\n ref: refs.setReference,\n className: classNames(trigger.props.className, \"mobius/PopoverToggle\"),\n onClick: toggleVisibility,\n ...getReferenceProps(),\n });\n\n useWindowEvent(\"keydown\", e => {\n if (e.key === \"Escape\") {\n onClose?.();\n e.preventDefault();\n e.stopPropagation();\n }\n });\n\n return (\n <>\n {triggerComponent}\n {isOpen && (\n <div\n className={containerClasses}\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n <div className=\"mobius/Popover\">\n <header className=\"mobius/PopoverHeader\">\n <Button\n type=\"button\"\n className=\"mobius/PopoverCloseButton\"\n onClick={toggleVisibility}\n aria-label=\"Close\"\n variant=\"ghost\"\n >\n <Icon\n icon={cross}\n size=\"md\"\n className=\"mobius/PopoverCloseIcon\"\n />\n </Button>\n </header>\n <div className=\"mobius/PopoverBody\">{children}</div>\n </div>\n <FloatingArrow
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Popover/Popover.tsx"],"sourcesContent":["import {\n FloatingArrow,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useDismiss,\n useFloating,\n useInteractions,\n} from \"@floating-ui/react\";\nimport { cross } from \"@simplybusiness/icons\";\nimport classNames from \"classnames\";\nimport {\n ReactElement,\n ReactNode,\n Ref,\n RefAttributes,\n cloneElement,\n useRef,\n useState,\n} from \"react\";\nimport { useWindowEvent } from \"../../hooks\";\nimport { DOMProps } from \"../../types\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\n\nexport type PopoverElementType = HTMLDivElement;\n\nexport interface PopoverProps\n extends DOMProps,\n RefAttributes<PopoverElementType> {\n children?: ReactNode;\n trigger: ReactElement;\n /** Callback that fires each time the accordion is opened */\n onOpen?: () => void;\n /** Callback that fires each time the accordion is closed */\n onClose?: () => void;\n /** Custom class name for setting specific CSS */\n className?: string;\n}\n\nexport type PopoverRef = Ref<PopoverElementType>;\n\nconst OFFSET_FROM_CONTENT_DEFAULT = 10;\n\nexport const Popover = (props: PopoverProps) => {\n const { trigger, children, onOpen, onClose, className } = props;\n const arrowRef = useRef(null);\n const [isOpen, setIsOpen] = useState(false);\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: setIsOpen,\n whileElementsMounted: autoUpdate,\n middleware: [\n arrow({\n element: arrowRef,\n }),\n offset(OFFSET_FROM_CONTENT_DEFAULT),\n shift(),\n flip(),\n ],\n });\n const dismiss = useDismiss(context, {\n bubbles: true,\n outsidePress: (event: MouseEvent) => {\n // Prevent 'onClose' from firing when clicking the toggle to close\n const toggle = refs.reference.current as HTMLElement;\n const isToggleClick = !toggle?.contains(event.target as HTMLElement);\n if (isToggleClick) {\n onClose?.();\n }\n return true;\n },\n });\n const { getReferenceProps, getFloatingProps } = useInteractions([dismiss]);\n\n const containerClasses = classNames(\n \"mobius\",\n \"mobius/PopoverContainer\",\n className,\n );\n\n const toggleVisibility = () => {\n if (isOpen) {\n setIsOpen(false);\n onClose?.();\n return;\n }\n\n setIsOpen(true);\n onOpen?.();\n };\n\n const triggerComponent = cloneElement(trigger, {\n ref: refs.setReference,\n className: classNames(trigger.props.className, \"mobius/PopoverToggle\"),\n onClick: toggleVisibility,\n ...getReferenceProps(),\n });\n\n useWindowEvent(\"keydown\", e => {\n if (e.key === \"Escape\") {\n onClose?.();\n e.preventDefault();\n e.stopPropagation();\n }\n });\n\n return (\n <>\n {triggerComponent}\n {isOpen && (\n <div\n className={containerClasses}\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n <div className=\"mobius/Popover\">\n <header className=\"mobius/PopoverHeader\">\n <Button\n type=\"button\"\n className=\"mobius/PopoverCloseButton\"\n onClick={toggleVisibility}\n aria-label=\"Close\"\n variant=\"ghost\"\n >\n <Icon\n icon={cross}\n size=\"md\"\n className=\"mobius/PopoverCloseIcon\"\n />\n </Button>\n </header>\n <div className=\"mobius/PopoverBody\">{children}</div>\n </div>\n <FloatingArrow\n ref={arrowRef}\n context={context}\n width={20}\n className=\"mobius/PopoverArrowIcon\"\n />\n </div>\n )}\n </>\n );\n};\n"],"names":["FloatingArrow","arrow","autoUpdate","flip","offset","shift","useDismiss","useFloating","useInteractions","cross","classNames","cloneElement","useRef","useState","useWindowEvent","Button","Icon","OFFSET_FROM_CONTENT_DEFAULT","Popover","props","trigger","children","onOpen","onClose","className","arrowRef","isOpen","setIsOpen","refs","floatingStyles","context","open","onOpenChange","whileElementsMounted","middleware","element","dismiss","bubbles","outsidePress","event","toggle","reference","current","isToggleClick","contains","target","getReferenceProps","getFloatingProps","containerClasses","toggleVisibility","triggerComponent","ref","setReference","onClick","e","key","preventDefault","stopPropagation","div","setFloating","style","header","type","aria-label","variant","icon","size","width"],"mappings":";AAAA,SACEA,aAAa,EACbC,KAAK,EACLC,UAAU,EACVC,IAAI,EACJC,MAAM,EACNC,KAAK,EACLC,UAAU,EACVC,WAAW,EACXC,eAAe,QACV,qBAAqB;AAC5B,SAASC,KAAK,QAAQ,wBAAwB;AAC9C,OAAOC,gBAAgB,aAAa;AACpC,SAKEC,YAAY,EACZC,MAAM,EACNC,QAAQ,QACH,QAAQ;AACf,SAASC,cAAc,QAAQ,cAAc;AAE7C,SAASC,MAAM,QAAQ,YAAY;AACnC,SAASC,IAAI,QAAQ,UAAU;AAmB/B,MAAMC,8BAA8B;AAEpC,OAAO,MAAMC,UAAU,CAACC;IACtB,MAAM,EAAEC,OAAO,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAEC,SAAS,EAAE,GAAGL;IAC1D,MAAMM,WAAWb,OAAO;IACxB,MAAM,CAACc,QAAQC,UAAU,GAAGd,SAAS;IACrC,MAAM,EAAEe,IAAI,EAAEC,cAAc,EAAEC,OAAO,EAAE,GAAGvB,YAAY;QACpDwB,MAAML;QACNM,cAAcL;QACdM,sBAAsB/B;QACtBgC,YAAY;YACVjC,MAAM;gBACJkC,SAASV;YACX;YACArB,OAAOa;YACPZ;YACAF;SACD;IACH;IACA,MAAMiC,UAAU9B,WAAWwB,SAAS;QAClCO,SAAS;QACTC,cAAc,CAACC;YACb,kEAAkE;YAClE,MAAMC,SAASZ,KAAKa,SAAS,CAACC,OAAO;YACrC,MAAMC,gBAAgB,EAACH,mBAAAA,6BAAAA,OAAQI,QAAQ,CAACL,MAAMM,MAAM;YACpD,IAAIF,eAAe;gBACjBpB,oBAAAA,8BAAAA;YACF;YACA,OAAO;QACT;IACF;IACA,MAAM,EAAEuB,iBAAiB,EAAEC,gBAAgB,EAAE,GAAGvC,gBAAgB;QAAC4B;KAAQ;IAEzE,MAAMY,mBAAmBtC,WACvB,UACA,2BACAc;IAGF,MAAMyB,mBAAmB;QACvB,IAAIvB,QAAQ;YACVC,UAAU;YACVJ,oBAAAA,8BAAAA;YACA;QACF;QAEAI,UAAU;QACVL,mBAAAA,6BAAAA;IACF;IAEA,MAAM4B,iCAAmBvC,aAAaS,SAAS;QAC7C+B,KAAKvB,KAAKwB,YAAY;QACtB5B,WAAWd,WAAWU,QAAQD,KAAK,CAACK,SAAS,EAAE;QAC/C6B,SAASJ;QACT,GAAGH,mBAAmB;IACxB;IAEAhC,eAAe,WAAWwC,CAAAA;QACxB,IAAIA,EAAEC,GAAG,KAAK,UAAU;YACtBhC,oBAAAA,8BAAAA;YACA+B,EAAEE,cAAc;YAChBF,EAAEG,eAAe;QACnB;IACF;IAEA,qBACE;;YACGP;YACAxB,wBACC,MAACgC;gBACClC,WAAWwB;gBACXG,KAAKvB,KAAK+B,WAAW;gBACrBC,OAAO/B;gBACN,GAAGkB,kBAAkB;;kCAEtB,MAACW;wBAAIlC,WAAU;;0CACb,KAACqC;gCAAOrC,WAAU;0CAChB,cAAA,KAACT;oCACC+C,MAAK;oCACLtC,WAAU;oCACV6B,SAASJ;oCACTc,cAAW;oCACXC,SAAQ;8CAER,cAAA,KAAChD;wCACCiD,MAAMxD;wCACNyD,MAAK;wCACL1C,WAAU;;;;0CAIhB,KAACkC;gCAAIlC,WAAU;0CAAsBH;;;;kCAEvC,KAACrB;wBACCmD,KAAK1B;wBACLK,SAASA;wBACTqC,OAAO;wBACP3C,WAAU;;;;;;AAMtB,EAAE"}
|
package/dist/esm/hooks/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./useBodyScrollLock";
|
|
|
2
2
|
export * from "./useBreakpoint";
|
|
3
3
|
export * from "./useButton";
|
|
4
4
|
export * from "./useDialog";
|
|
5
|
+
export * from "./useDialogPolyfill";
|
|
5
6
|
export * from "./useLabel";
|
|
6
7
|
export * from "./useOnClickOutside";
|
|
7
8
|
export * from "./useTextField";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/index.tsx"],"sourcesContent":["export * from \"./useBodyScrollLock\";\nexport * from \"./useBreakpoint\";\nexport * from \"./useButton\";\nexport * from \"./useDialog\";\nexport * from \"./useLabel\";\nexport * from \"./useOnClickOutside\";\nexport * from \"./useTextField\";\nexport * from \"./useWindowEvent\";\n"],"names":[],"mappings":"AAAA,cAAc,sBAAsB;AACpC,cAAc,kBAAkB;AAChC,cAAc,cAAc;AAC5B,cAAc,cAAc;AAC5B,cAAc,aAAa;AAC3B,cAAc,sBAAsB;AACpC,cAAc,iBAAiB;AAC/B,cAAc,mBAAmB"}
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/index.tsx"],"sourcesContent":["export * from \"./useBodyScrollLock\";\nexport * from \"./useBreakpoint\";\nexport * from \"./useButton\";\nexport * from \"./useDialog\";\nexport * from \"./useDialogPolyfill\";\nexport * from \"./useLabel\";\nexport * from \"./useOnClickOutside\";\nexport * from \"./useTextField\";\nexport * from \"./useWindowEvent\";\n"],"names":[],"mappings":"AAAA,cAAc,sBAAsB;AACpC,cAAc,kBAAkB;AAChC,cAAc,cAAc;AAC5B,cAAc,cAAc;AAC5B,cAAc,sBAAsB;AACpC,cAAc,aAAa;AAC3B,cAAc,sBAAsB;AACpC,cAAc,iBAAiB;AAC/B,cAAc,mBAAmB"}
|
|
@@ -7,9 +7,9 @@ const FALLBACK_TRANSITION_DURATION = 0;
|
|
|
7
7
|
export const useDialog = (props)=>{
|
|
8
8
|
const { ref, isOpen, transition, onOpen, onClose } = props;
|
|
9
9
|
const shouldTransition = supportsDialog() && transition.isEnabled;
|
|
10
|
+
const { polyfillDialog } = useDialogPolyfill();
|
|
10
11
|
// Read CSS variable value as number
|
|
11
12
|
const TRANSITION_DURATION_IN_MS = ref.current && Number(getComputedStyle(ref.current).getPropertyValue(transition.CSSVariable).replace("ms", "")) || FALLBACK_TRANSITION_DURATION;
|
|
12
|
-
useDialogPolyfill(ref);
|
|
13
13
|
useBodyScrollLock({
|
|
14
14
|
enabled: isOpen
|
|
15
15
|
});
|
|
@@ -57,6 +57,7 @@ export const useDialog = (props)=>{
|
|
|
57
57
|
async function toggleDialog() {
|
|
58
58
|
var _ref_current, _ref_current1;
|
|
59
59
|
if (isOpen && !((_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.open)) {
|
|
60
|
+
await polyfillDialog(ref);
|
|
60
61
|
open();
|
|
61
62
|
// Fix opening transition in Safari being skipped
|
|
62
63
|
// by wrapping with setTimeout
|
|
@@ -73,7 +74,8 @@ export const useDialog = (props)=>{
|
|
|
73
74
|
handleClose,
|
|
74
75
|
isOpen,
|
|
75
76
|
open,
|
|
76
|
-
ref
|
|
77
|
+
ref,
|
|
78
|
+
polyfillDialog
|
|
77
79
|
]);
|
|
78
80
|
return {
|
|
79
81
|
open,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/hooks/useDialog/useDialog.ts"],"sourcesContent":["import {\n MutableRefObject,\n SyntheticEvent,\n useCallback,\n useEffect,\n} from \"react\";\nimport { useDialogPolyfill } from \"../useDialogPolyfill\";\nimport { useBodyScrollLock } from \"../useBodyScrollLock\";\nimport { supportsDialog } from \"../../utils\";\n\nexport type TransitionProps = {\n isEnabled: boolean;\n CSSVariable: string;\n};\n\nexport type useDialogProps = {\n ref: MutableRefObject<HTMLDialogElement | null>;\n transition: TransitionProps;\n isOpen: boolean;\n onOpen?: () => void;\n onClose?: () => void;\n};\n\nconst TRANSITION_CLASS_NAME = \"--transition\";\nconst FALLBACK_TRANSITION_DURATION = 0;\n\nexport const useDialog = (props: useDialogProps) => {\n const { ref, isOpen, transition, onOpen, onClose } = props;\n const shouldTransition = supportsDialog() && transition.isEnabled;\n\n // Read CSS variable value as number\n const TRANSITION_DURATION_IN_MS =\n (ref.current &&\n Number(\n getComputedStyle(ref.current)\n .getPropertyValue(transition.CSSVariable)\n .replace(\"ms\", \"\"),\n )) ||\n FALLBACK_TRANSITION_DURATION;\n\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/hooks/useDialog/useDialog.ts"],"sourcesContent":["import {\n MutableRefObject,\n SyntheticEvent,\n useCallback,\n useEffect,\n} from \"react\";\nimport { useDialogPolyfill } from \"../useDialogPolyfill\";\nimport { useBodyScrollLock } from \"../useBodyScrollLock\";\nimport { supportsDialog } from \"../../utils\";\n\nexport type TransitionProps = {\n isEnabled: boolean;\n CSSVariable: string;\n};\n\nexport type useDialogProps = {\n ref: MutableRefObject<HTMLDialogElement | null>;\n transition: TransitionProps;\n isOpen: boolean;\n onOpen?: () => void;\n onClose?: () => void;\n};\n\nconst TRANSITION_CLASS_NAME = \"--transition\";\nconst FALLBACK_TRANSITION_DURATION = 0;\n\nexport const useDialog = (props: useDialogProps) => {\n const { ref, isOpen, transition, onOpen, onClose } = props;\n const shouldTransition = supportsDialog() && transition.isEnabled;\n const { polyfillDialog } = useDialogPolyfill();\n\n // Read CSS variable value as number\n const TRANSITION_DURATION_IN_MS =\n (ref.current &&\n Number(\n getComputedStyle(ref.current)\n .getPropertyValue(transition.CSSVariable)\n .replace(\"ms\", \"\"),\n )) ||\n FALLBACK_TRANSITION_DURATION;\n\n useBodyScrollLock({ enabled: isOpen });\n\n const open = useCallback(() => {\n ref.current?.showModal();\n onOpen?.();\n }, [onOpen, ref]);\n\n const close = useCallback(() => {\n ref.current?.close();\n onClose?.();\n }, [onClose, ref]);\n\n // Add close handler, to enable closing transitions\n const handleClose = useCallback(\n (event?: SyntheticEvent<HTMLElement, Event>) => {\n if (event) {\n // Prevent default event coming from onCancel,\n // which is triggered by pressing ESC key\n event.preventDefault();\n // Ensure that nested `<dialog>` elements\n // don't close the parent\n event.stopPropagation();\n }\n\n if (shouldTransition) {\n ref.current?.classList.remove(TRANSITION_CLASS_NAME);\n // Delay close to allow exit transition\n setTimeout(() => close(), TRANSITION_DURATION_IN_MS);\n } else {\n close();\n }\n },\n [TRANSITION_DURATION_IN_MS, close, ref, shouldTransition],\n );\n\n useEffect(() => {\n async function toggleDialog() {\n if (isOpen && !ref.current?.open) {\n await polyfillDialog(ref);\n\n open();\n // Fix opening transition in Safari being skipped\n // by wrapping with setTimeout\n setTimeout(() => {\n ref.current?.classList.add(TRANSITION_CLASS_NAME);\n }, 0);\n } else if (!isOpen && ref.current?.open) {\n handleClose();\n }\n }\n\n toggleDialog();\n }, [handleClose, isOpen, open, ref, polyfillDialog]);\n\n return {\n open,\n close: handleClose,\n };\n};\n"],"names":["useCallback","useEffect","useDialogPolyfill","useBodyScrollLock","supportsDialog","TRANSITION_CLASS_NAME","FALLBACK_TRANSITION_DURATION","useDialog","props","ref","isOpen","transition","onOpen","onClose","shouldTransition","isEnabled","polyfillDialog","TRANSITION_DURATION_IN_MS","current","Number","getComputedStyle","getPropertyValue","CSSVariable","replace","enabled","open","showModal","close","handleClose","event","preventDefault","stopPropagation","classList","remove","setTimeout","toggleDialog","add"],"mappings":"AAAA,SAGEA,WAAW,EACXC,SAAS,QACJ,QAAQ;AACf,SAASC,iBAAiB,QAAQ,uBAAuB;AACzD,SAASC,iBAAiB,QAAQ,uBAAuB;AACzD,SAASC,cAAc,QAAQ,cAAc;AAe7C,MAAMC,wBAAwB;AAC9B,MAAMC,+BAA+B;AAErC,OAAO,MAAMC,YAAY,CAACC;IACxB,MAAM,EAAEC,GAAG,EAAEC,MAAM,EAAEC,UAAU,EAAEC,MAAM,EAAEC,OAAO,EAAE,GAAGL;IACrD,MAAMM,mBAAmBV,oBAAoBO,WAAWI,SAAS;IACjE,MAAM,EAAEC,cAAc,EAAE,GAAGd;IAE3B,oCAAoC;IACpC,MAAMe,4BACJ,AAACR,IAAIS,OAAO,IACVC,OACEC,iBAAiBX,IAAIS,OAAO,EACzBG,gBAAgB,CAACV,WAAWW,WAAW,EACvCC,OAAO,CAAC,MAAM,QAErBjB;IAEFH,kBAAkB;QAAEqB,SAASd;IAAO;IAEpC,MAAMe,OAAOzB,YAAY;YACvBS;SAAAA,eAAAA,IAAIS,OAAO,cAAXT,mCAAAA,aAAaiB,SAAS;QACtBd,mBAAAA,6BAAAA;IACF,GAAG;QAACA;QAAQH;KAAI;IAEhB,MAAMkB,QAAQ3B,YAAY;YACxBS;SAAAA,eAAAA,IAAIS,OAAO,cAAXT,mCAAAA,aAAakB,KAAK;QAClBd,oBAAAA,8BAAAA;IACF,GAAG;QAACA;QAASJ;KAAI;IAEjB,mDAAmD;IACnD,MAAMmB,cAAc5B,YAClB,CAAC6B;QACC,IAAIA,OAAO;YACT,8CAA8C;YAC9C,yCAAyC;YACzCA,MAAMC,cAAc;YACpB,yCAAyC;YACzC,yBAAyB;YACzBD,MAAME,eAAe;QACvB;QAEA,IAAIjB,kBAAkB;gBACpBL;aAAAA,eAAAA,IAAIS,OAAO,cAAXT,mCAAAA,aAAauB,SAAS,CAACC,MAAM,CAAC5B;YAC9B,uCAAuC;YACvC6B,WAAW,IAAMP,SAASV;QAC5B,OAAO;YACLU;QACF;IACF,GACA;QAACV;QAA2BU;QAAOlB;QAAKK;KAAiB;IAG3Db,UAAU;QACR,eAAekC;gBACE1B,cASOA;YATtB,IAAIC,UAAU,GAACD,eAAAA,IAAIS,OAAO,cAAXT,mCAAAA,aAAagB,IAAI,GAAE;gBAChC,MAAMT,eAAeP;gBAErBgB;gBACA,iDAAiD;gBACjD,8BAA8B;gBAC9BS,WAAW;wBACTzB;qBAAAA,eAAAA,IAAIS,OAAO,cAAXT,mCAAAA,aAAauB,SAAS,CAACI,GAAG,CAAC/B;gBAC7B,GAAG;YACL,OAAO,IAAI,CAACK,YAAUD,gBAAAA,IAAIS,OAAO,cAAXT,oCAAAA,cAAagB,IAAI,GAAE;gBACvCG;YACF;QACF;QAEAO;IACF,GAAG;QAACP;QAAalB;QAAQe;QAAMhB;QAAKO;KAAe;IAEnD,OAAO;QACLS;QACAE,OAAOC;IACT;AACF,EAAE"}
|
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useRef } from "react";
|
|
2
2
|
import { supportsDialog } from "../../utils";
|
|
3
3
|
// Add polyfill for HTML Dialog in old browsers
|
|
4
|
-
export const useDialogPolyfill = (
|
|
4
|
+
export const useDialogPolyfill = ()=>{
|
|
5
5
|
const hasDialogSupport = supportsDialog();
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// Checking showModal presence through hasOwnProperty is falsy natively, truthy with polyfill 🤷🏼♂️
|
|
16
|
-
console.error("Failed to load dialog-polyfill", error);
|
|
17
|
-
}
|
|
6
|
+
const hasAlreadyLoaded = useRef(false);
|
|
7
|
+
const polyfillDialog = async (ref)=>{
|
|
8
|
+
if (!hasAlreadyLoaded.current && !hasDialogSupport && typeof window !== "undefined" && ref.current !== null) {
|
|
9
|
+
const { default: dialogPolyfill } = await import("dialog-polyfill");
|
|
10
|
+
hasAlreadyLoaded.current = true;
|
|
11
|
+
try {
|
|
12
|
+
dialogPolyfill.registerDialog(ref.current);
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.error("Failed to load dialog-polyfill", error);
|
|
18
15
|
}
|
|
19
16
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
]);
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
polyfillDialog
|
|
20
|
+
};
|
|
25
21
|
};
|
|
26
22
|
|
|
27
23
|
//# sourceMappingURL=useDialogPolyfill.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/hooks/useDialogPolyfill/useDialogPolyfill.ts"],"sourcesContent":["import { MutableRefObject,
|
|
1
|
+
{"version":3,"sources":["../../../../src/hooks/useDialogPolyfill/useDialogPolyfill.ts"],"sourcesContent":["import { MutableRefObject, useRef } from \"react\";\nimport { supportsDialog } from \"../../utils\";\n\n// Add polyfill for HTML Dialog in old browsers\nexport const useDialogPolyfill = () => {\n const hasDialogSupport = supportsDialog();\n const hasAlreadyLoaded = useRef(false);\n\n const polyfillDialog = async (\n ref: MutableRefObject<HTMLDialogElement | null>,\n ) => {\n if (\n !hasAlreadyLoaded.current &&\n !hasDialogSupport &&\n typeof window !== \"undefined\" &&\n ref.current !== null\n ) {\n const { default: dialogPolyfill } = await import(\"dialog-polyfill\");\n hasAlreadyLoaded.current = true;\n\n try {\n dialogPolyfill.registerDialog(ref.current);\n } catch (error) {\n console.error(\"Failed to load dialog-polyfill\", error);\n }\n }\n };\n\n return {\n polyfillDialog,\n };\n};\n"],"names":["useRef","supportsDialog","useDialogPolyfill","hasDialogSupport","hasAlreadyLoaded","polyfillDialog","ref","current","window","default","dialogPolyfill","registerDialog","error","console"],"mappings":"AAAA,SAA2BA,MAAM,QAAQ,QAAQ;AACjD,SAASC,cAAc,QAAQ,cAAc;AAE7C,+CAA+C;AAC/C,OAAO,MAAMC,oBAAoB;IAC/B,MAAMC,mBAAmBF;IACzB,MAAMG,mBAAmBJ,OAAO;IAEhC,MAAMK,iBAAiB,OACrBC;QAEA,IACE,CAACF,iBAAiBG,OAAO,IACzB,CAACJ,oBACD,OAAOK,WAAW,eAClBF,IAAIC,OAAO,KAAK,MAChB;YACA,MAAM,EAAEE,SAASC,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC;YACjDN,iBAAiBG,OAAO,GAAG;YAE3B,IAAI;gBACFG,eAAeC,cAAc,CAACL,IAAIC,OAAO;YAC3C,EAAE,OAAOK,OAAO;gBACdC,QAAQD,KAAK,CAAC,kCAAkCA;YAClD;QACF;IACF;IAEA,OAAO;QACLP;IACF;AACF,EAAE"}
|
|
@@ -2,6 +2,7 @@ export * from "./useBodyScrollLock";
|
|
|
2
2
|
export * from "./useBreakpoint";
|
|
3
3
|
export * from "./useButton";
|
|
4
4
|
export * from "./useDialog";
|
|
5
|
+
export * from "./useDialogPolyfill";
|
|
5
6
|
export * from "./useLabel";
|
|
6
7
|
export * from "./useOnClickOutside";
|
|
7
8
|
export * from "./useTextField";
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { MutableRefObject } from "react";
|
|
2
|
-
export declare const useDialogPolyfill: (
|
|
2
|
+
export declare const useDialogPolyfill: () => {
|
|
3
|
+
polyfillDialog: (ref: MutableRefObject<HTMLDialogElement | null>) => Promise<void>;
|
|
4
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplybusiness/mobius",
|
|
3
3
|
"license": "UNLICENSED",
|
|
4
|
-
"version": "4.6.
|
|
4
|
+
"version": "4.6.3",
|
|
5
5
|
"description": "Core library of Mobius react components",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"@floating-ui/react": "^0.26.8",
|
|
85
|
-
"@simplybusiness/icons": "^4.3.
|
|
85
|
+
"@simplybusiness/icons": "^4.3.1",
|
|
86
86
|
"classnames": "^2.5.1",
|
|
87
87
|
"dialog-polyfill": "^0.5.6",
|
|
88
88
|
"lodash.debounce": "^4.0.8",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Ref, forwardRef, RefAttributes, ReactNode } from "react";
|
|
2
2
|
import classNames from "classnames/dedupe";
|
|
3
|
-
import {
|
|
3
|
+
import { circleInfo, circleTick, warning, error } from "@simplybusiness/icons";
|
|
4
4
|
import { DOMProps } from "../../types/dom";
|
|
5
5
|
import { ForwardedRefComponent } from "../../types/components";
|
|
6
6
|
import { Icon } from "../Icon";
|
|
@@ -45,8 +45,8 @@ const Alert: ForwardedRefComponent<AlertProps, AlertElementType> = forwardRef(
|
|
|
45
45
|
otherProps.className,
|
|
46
46
|
);
|
|
47
47
|
const icon = {
|
|
48
|
-
info,
|
|
49
|
-
success,
|
|
48
|
+
info: circleInfo,
|
|
49
|
+
success: circleTick,
|
|
50
50
|
warning,
|
|
51
51
|
error,
|
|
52
52
|
};
|
|
@@ -42,9 +42,13 @@ import { Button } from "@simplybusiness/mobius";
|
|
|
42
42
|
|
|
43
43
|
<Canvas of={ButtonStories.Large} />
|
|
44
44
|
|
|
45
|
-
## Link
|
|
45
|
+
## As Link Element
|
|
46
46
|
|
|
47
|
-
<Canvas of={ButtonStories.
|
|
47
|
+
<Canvas of={ButtonStories.AsLinkElement} />
|
|
48
|
+
|
|
49
|
+
## With Link Styles
|
|
50
|
+
|
|
51
|
+
<Canvas of={ButtonStories.WithLinkStyles} />
|
|
48
52
|
|
|
49
53
|
## Loading
|
|
50
54
|
|
|
@@ -25,13 +25,15 @@ describe("Drawer", () => {
|
|
|
25
25
|
expect(container).toBeTruthy();
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
it("should render with default class names", () => {
|
|
28
|
+
it("should render with default class names", async () => {
|
|
29
29
|
render(
|
|
30
30
|
<Drawer isOpen direction="right">
|
|
31
31
|
<Drawer.Header />
|
|
32
32
|
</Drawer>,
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
36
|
+
|
|
35
37
|
const dialog = screen.getByRole("dialog");
|
|
36
38
|
const closeButton = screen.getByLabelText("Close");
|
|
37
39
|
|
|
@@ -39,13 +41,15 @@ describe("Drawer", () => {
|
|
|
39
41
|
expect(closeButton).toHaveClass(DRAWER_CLOSE_CLASS_NAME);
|
|
40
42
|
});
|
|
41
43
|
|
|
42
|
-
it("should render with custom class name", () => {
|
|
44
|
+
it("should render with custom class name", async () => {
|
|
43
45
|
render(
|
|
44
46
|
<Drawer direction="right" className={DRAWER_TEST_CLASS_NAME} isOpen>
|
|
45
47
|
<Drawer.Header />
|
|
46
48
|
</Drawer>,
|
|
47
49
|
);
|
|
48
50
|
|
|
51
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
52
|
+
|
|
49
53
|
const dialog = screen.getByRole("dialog");
|
|
50
54
|
const closeButton = screen.getByLabelText("Close");
|
|
51
55
|
|
|
@@ -55,17 +59,23 @@ describe("Drawer", () => {
|
|
|
55
59
|
});
|
|
56
60
|
|
|
57
61
|
describe("given the direction prop is set", () => {
|
|
58
|
-
it("should render with appropriate class name (right)", () => {
|
|
62
|
+
it("should render with appropriate class name (right)", async () => {
|
|
59
63
|
render(<Drawer isOpen direction="right" />);
|
|
60
64
|
|
|
65
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
66
|
+
|
|
61
67
|
const dialog = screen.getByRole("dialog");
|
|
68
|
+
|
|
62
69
|
expect(dialog).toHaveClass("--right");
|
|
63
70
|
});
|
|
64
71
|
|
|
65
|
-
it("should render with appropriate class name (bottom)", () => {
|
|
72
|
+
it("should render with appropriate class name (bottom)", async () => {
|
|
66
73
|
render(<Drawer isOpen direction="bottom" />);
|
|
67
74
|
|
|
75
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
76
|
+
|
|
68
77
|
const dialog = screen.getByRole("dialog");
|
|
78
|
+
|
|
69
79
|
expect(dialog).toHaveClass("--bottom");
|
|
70
80
|
});
|
|
71
81
|
});
|
|
@@ -105,6 +115,8 @@ describe("Drawer", () => {
|
|
|
105
115
|
|
|
106
116
|
render(<App />);
|
|
107
117
|
|
|
118
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
119
|
+
|
|
108
120
|
const dialog = screen.getByRole("dialog");
|
|
109
121
|
const drawerContent = screen.getByText("Sample content");
|
|
110
122
|
|
|
@@ -25,13 +25,15 @@ describe("Modal", () => {
|
|
|
25
25
|
expect(container).toBeTruthy();
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
it("should render with default class names", () => {
|
|
28
|
+
it("should render with default class names", async () => {
|
|
29
29
|
render(
|
|
30
30
|
<Modal isOpen>
|
|
31
31
|
<Modal.Header />
|
|
32
32
|
</Modal>,
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
36
|
+
|
|
35
37
|
const dialog = screen.getByRole("dialog");
|
|
36
38
|
const closeButton = screen.getByLabelText("Close");
|
|
37
39
|
|
|
@@ -39,13 +41,15 @@ describe("Modal", () => {
|
|
|
39
41
|
expect(closeButton).toHaveClass(MODAL_CLOSE_CLASS_NAME);
|
|
40
42
|
});
|
|
41
43
|
|
|
42
|
-
it("should render with custom class name", () => {
|
|
44
|
+
it("should render with custom class name", async () => {
|
|
43
45
|
render(
|
|
44
46
|
<Modal className={MODAL_TEST_CLASS_NAME} isOpen>
|
|
45
47
|
<Modal.Header />
|
|
46
48
|
</Modal>,
|
|
47
49
|
);
|
|
48
50
|
|
|
51
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
52
|
+
|
|
49
53
|
const dialog = screen.getByRole("dialog");
|
|
50
54
|
const closeButton = screen.getByLabelText("Close");
|
|
51
55
|
|
|
@@ -55,18 +59,22 @@ describe("Modal", () => {
|
|
|
55
59
|
});
|
|
56
60
|
|
|
57
61
|
describe("given the animation prop is set to slideUp", () => {
|
|
58
|
-
it("should render with appropriate class name", () => {
|
|
62
|
+
it("should render with appropriate class name", async () => {
|
|
59
63
|
render(<Modal isOpen animation="slideUp" />);
|
|
60
64
|
|
|
65
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
66
|
+
|
|
61
67
|
const dialog = screen.getByRole("dialog");
|
|
62
68
|
expect(dialog).toHaveClass("--slide-up");
|
|
63
69
|
});
|
|
64
70
|
});
|
|
65
71
|
|
|
66
72
|
describe("given the animation prop is set to fade", () => {
|
|
67
|
-
it("should render with appropriate class name", () => {
|
|
73
|
+
it("should render with appropriate class name", async () => {
|
|
68
74
|
render(<Modal isOpen animation="fade" />);
|
|
69
75
|
|
|
76
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
77
|
+
|
|
70
78
|
const dialog = screen.getByRole("dialog");
|
|
71
79
|
expect(dialog).toHaveClass("--fade");
|
|
72
80
|
});
|
|
@@ -87,6 +95,8 @@ describe("Modal", () => {
|
|
|
87
95
|
|
|
88
96
|
render(<App />);
|
|
89
97
|
|
|
98
|
+
await waitFor(() => screen.getByRole("dialog"));
|
|
99
|
+
|
|
90
100
|
const dialog = screen.getByRole("dialog");
|
|
91
101
|
const drawerContent = screen.getByText("Sample content");
|
|
92
102
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import {
|
|
3
|
-
import { Button, Flex, Popover, PopoverProps } from "..";
|
|
2
|
+
import { circleQuestion } from "@simplybusiness/icons";
|
|
3
|
+
import { Button, Flex, Popover, PopoverProps, Icon } from "..";
|
|
4
4
|
import { excludeControls } from "../../utils";
|
|
5
5
|
|
|
6
6
|
type StoryType = StoryObj<typeof Popover>;
|
|
@@ -21,44 +21,6 @@ const meta: Meta<typeof Popover> = {
|
|
|
21
21
|
],
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
type QuestionIconProps = {};
|
|
25
|
-
|
|
26
|
-
const QuestionIcon = forwardRef(
|
|
27
|
-
(props: QuestionIconProps, ref: Ref<SVGSVGElement>) => (
|
|
28
|
-
<svg
|
|
29
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
30
|
-
viewBox="0 0 16 16"
|
|
31
|
-
fill="none"
|
|
32
|
-
stroke="currentColor"
|
|
33
|
-
width="16px"
|
|
34
|
-
height="16px"
|
|
35
|
-
ref={ref}
|
|
36
|
-
{...props}
|
|
37
|
-
>
|
|
38
|
-
<g clipPath="url(#clip0_1641_88567)">
|
|
39
|
-
<path
|
|
40
|
-
d="M6.25 6.25002C6.25017 5.36011 6.91818 4.61203 7.80241 4.51155C8.68663 4.41107 9.50546 4.99019 9.7053 5.85737C9.90515 6.72456 9.42235 7.60364 8.58333 7.90027C8.23357 8.02393 7.99981 8.35471 8 8.72569V9.31253"
|
|
41
|
-
stroke="currentColor"
|
|
42
|
-
strokeLinecap="round"
|
|
43
|
-
strokeLinejoin="round"
|
|
44
|
-
/>
|
|
45
|
-
<path
|
|
46
|
-
d="M8 11.0625C7.87919 11.0625 7.78125 11.1604 7.78125 11.2812C7.78125 11.4021 7.87919 11.5 8 11.5C8.12081 11.5 8.21875 11.4021 8.21875 11.2812C8.21875 11.1604 8.12081 11.0625 8 11.0625V11.0625"
|
|
47
|
-
stroke="currentColor"
|
|
48
|
-
strokeLinecap="round"
|
|
49
|
-
strokeLinejoin="round"
|
|
50
|
-
/>
|
|
51
|
-
<circle cx="8" cy="8" r="6.5625" stroke="currentColor" />
|
|
52
|
-
</g>
|
|
53
|
-
<defs>
|
|
54
|
-
<clipPath id="clip0_1641_88567">
|
|
55
|
-
<rect width="16" height="16" fill="white" />
|
|
56
|
-
</clipPath>
|
|
57
|
-
</defs>
|
|
58
|
-
</svg>
|
|
59
|
-
),
|
|
60
|
-
);
|
|
61
|
-
|
|
62
24
|
export const Normal: StoryType = {
|
|
63
25
|
render: (args: PopoverProps) => <Popover {...args} />,
|
|
64
26
|
args: {
|
|
@@ -75,7 +37,7 @@ export const CustomTrigger: StoryType = {
|
|
|
75
37
|
<Button variant="ghost">
|
|
76
38
|
<Flex>
|
|
77
39
|
<span>Occurrence Limit</span>
|
|
78
|
-
<
|
|
40
|
+
<Icon icon={circleQuestion} />
|
|
79
41
|
</Flex>
|
|
80
42
|
</Button>
|
|
81
43
|
}
|
|
@@ -135,7 +135,12 @@ export const Popover = (props: PopoverProps) => {
|
|
|
135
135
|
</header>
|
|
136
136
|
<div className="mobius/PopoverBody">{children}</div>
|
|
137
137
|
</div>
|
|
138
|
-
<FloatingArrow
|
|
138
|
+
<FloatingArrow
|
|
139
|
+
ref={arrowRef}
|
|
140
|
+
context={context}
|
|
141
|
+
width={20}
|
|
142
|
+
className="mobius/PopoverArrowIcon"
|
|
143
|
+
/>
|
|
139
144
|
</div>
|
|
140
145
|
)}
|
|
141
146
|
</>
|
package/src/hooks/index.tsx
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./useBodyScrollLock";
|
|
|
2
2
|
export * from "./useBreakpoint";
|
|
3
3
|
export * from "./useButton";
|
|
4
4
|
export * from "./useDialog";
|
|
5
|
+
export * from "./useDialogPolyfill";
|
|
5
6
|
export * from "./useLabel";
|
|
6
7
|
export * from "./useOnClickOutside";
|
|
7
8
|
export * from "./useTextField";
|
|
@@ -27,6 +27,7 @@ const FALLBACK_TRANSITION_DURATION = 0;
|
|
|
27
27
|
export const useDialog = (props: useDialogProps) => {
|
|
28
28
|
const { ref, isOpen, transition, onOpen, onClose } = props;
|
|
29
29
|
const shouldTransition = supportsDialog() && transition.isEnabled;
|
|
30
|
+
const { polyfillDialog } = useDialogPolyfill();
|
|
30
31
|
|
|
31
32
|
// Read CSS variable value as number
|
|
32
33
|
const TRANSITION_DURATION_IN_MS =
|
|
@@ -38,7 +39,6 @@ export const useDialog = (props: useDialogProps) => {
|
|
|
38
39
|
)) ||
|
|
39
40
|
FALLBACK_TRANSITION_DURATION;
|
|
40
41
|
|
|
41
|
-
useDialogPolyfill(ref);
|
|
42
42
|
useBodyScrollLock({ enabled: isOpen });
|
|
43
43
|
|
|
44
44
|
const open = useCallback(() => {
|
|
@@ -77,6 +77,8 @@ export const useDialog = (props: useDialogProps) => {
|
|
|
77
77
|
useEffect(() => {
|
|
78
78
|
async function toggleDialog() {
|
|
79
79
|
if (isOpen && !ref.current?.open) {
|
|
80
|
+
await polyfillDialog(ref);
|
|
81
|
+
|
|
80
82
|
open();
|
|
81
83
|
// Fix opening transition in Safari being skipped
|
|
82
84
|
// by wrapping with setTimeout
|
|
@@ -89,7 +91,7 @@ export const useDialog = (props: useDialogProps) => {
|
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
toggleDialog();
|
|
92
|
-
}, [handleClose, isOpen, open, ref]);
|
|
94
|
+
}, [handleClose, isOpen, open, ref, polyfillDialog]);
|
|
93
95
|
|
|
94
96
|
return {
|
|
95
97
|
open,
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import { MutableRefObject,
|
|
1
|
+
import { MutableRefObject, useRef } from "react";
|
|
2
2
|
import { supportsDialog } from "../../utils";
|
|
3
3
|
|
|
4
4
|
// Add polyfill for HTML Dialog in old browsers
|
|
5
|
-
export const useDialogPolyfill = (
|
|
6
|
-
ref: MutableRefObject<HTMLDialogElement | null>,
|
|
7
|
-
) => {
|
|
5
|
+
export const useDialogPolyfill = () => {
|
|
8
6
|
const hasDialogSupport = supportsDialog();
|
|
7
|
+
const hasAlreadyLoaded = useRef(false);
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
const polyfillDialog = async (
|
|
10
|
+
ref: MutableRefObject<HTMLDialogElement | null>,
|
|
11
|
+
) => {
|
|
12
|
+
if (
|
|
13
|
+
!hasAlreadyLoaded.current &&
|
|
14
|
+
!hasDialogSupport &&
|
|
15
|
+
typeof window !== "undefined" &&
|
|
16
|
+
ref.current !== null
|
|
17
|
+
) {
|
|
18
|
+
const { default: dialogPolyfill } = await import("dialog-polyfill");
|
|
19
|
+
hasAlreadyLoaded.current = true;
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// TypeError: null is not an object (evaluating 'element.showModal')
|
|
24
|
-
// Checking showModal presence through hasOwnProperty is falsy natively, truthy with polyfill 🤷🏼♂️
|
|
25
|
-
console.error("Failed to load dialog-polyfill", error);
|
|
26
|
-
}
|
|
21
|
+
try {
|
|
22
|
+
dialogPolyfill.registerDialog(ref.current);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error("Failed to load dialog-polyfill", error);
|
|
27
25
|
}
|
|
28
26
|
}
|
|
27
|
+
};
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
return {
|
|
30
|
+
polyfillDialog,
|
|
31
|
+
};
|
|
32
32
|
};
|