@khanacademy/wonder-blocks-floating 0.0.0-PR2844-20251112222914 → 0.0.0-PR2846-20251113184845
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 +3 -2
- package/dist/components/floating.d.ts +17 -1
- package/dist/components/focus-manager.d.ts +12 -0
- package/dist/es/index.js +4 -2
- package/dist/index.js +3 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-floating
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-PR2846-20251113184845
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
7
|
- 7cc5c0d: Adds wonder-blocks-floating package
|
|
8
|
+
- 0bf70fc: Adds focus management support
|
|
8
9
|
- b286374: Adds Floating component with basic props (including middlewares)
|
|
9
|
-
-
|
|
10
|
+
- fad599f: Adds `portal` prop to Floating component. Includes `maybeGetPortalMountedModalHostElement` util to portal floating elements inside modals.
|
|
@@ -78,6 +78,22 @@ type FloatingProps = {
|
|
|
78
78
|
* @default true
|
|
79
79
|
*/
|
|
80
80
|
portal?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Whether to use the FocusManager component to manage the focus of the
|
|
83
|
+
* floating element.
|
|
84
|
+
* @default false
|
|
85
|
+
*/
|
|
86
|
+
useFocusManager?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The element that will receive focus when the floating element is opened.
|
|
89
|
+
*/
|
|
90
|
+
initialFocusRef?: React.RefObject<HTMLElement>;
|
|
91
|
+
/**
|
|
92
|
+
* When enabled, user can hide the floating element by pressing the `esc`
|
|
93
|
+
* key or clicking/tapping outside of it.
|
|
94
|
+
* @default false
|
|
95
|
+
*/
|
|
96
|
+
dismissEnabled?: boolean;
|
|
81
97
|
};
|
|
82
98
|
/**
|
|
83
99
|
* A component that uses the Floating UI library to position a floating element
|
|
@@ -96,5 +112,5 @@ type FloatingProps = {
|
|
|
96
112
|
* </Floating>
|
|
97
113
|
* ```
|
|
98
114
|
*/
|
|
99
|
-
export default function Floating({ content, children, placement, open, onOpenChange, portal, strategy, testId, hide: hideProp, offset: offsetProp, flip: flipProp, shift: shiftProp, showArrow, }: FloatingProps): React.JSX.Element;
|
|
115
|
+
export default function Floating({ content, children, placement, open, onOpenChange, portal, strategy, testId, useFocusManager, initialFocusRef, dismissEnabled, hide: hideProp, offset: offsetProp, flip: flipProp, shift: shiftProp, showArrow, }: FloatingProps): React.JSX.Element;
|
|
100
116
|
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { FloatingRootContext } from "@floating-ui/react";
|
|
3
|
+
/**
|
|
4
|
+
* Renders the floating element with the focus manager if enabled.
|
|
5
|
+
*/
|
|
6
|
+
export declare function FocusManager({ context, dismissEnabled, useFocusManager, initialFocusRef, children, }: {
|
|
7
|
+
context: FloatingRootContext;
|
|
8
|
+
dismissEnabled: boolean;
|
|
9
|
+
useFocusManager: boolean;
|
|
10
|
+
initialFocusRef: React.RefObject<HTMLElement> | undefined;
|
|
11
|
+
children: React.JSX.Element;
|
|
12
|
+
}): React.JSX.Element;
|
package/dist/es/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { useMemo } from 'react';
|
|
4
|
-
import { FloatingArrow, FloatingPortal, useFloating, autoUpdate, offset, flip, shift, arrow, hide } from '@floating-ui/react';
|
|
4
|
+
import { FloatingArrow, FloatingPortal, FloatingFocusManager, useFloating, autoUpdate, offset, flip, shift, arrow, hide, useDismiss, useInteractions } from '@floating-ui/react';
|
|
5
5
|
import { StyleSheet, css } from 'aphrodite';
|
|
6
6
|
import { semanticColor, border, boxShadow } from '@khanacademy/wonder-blocks-tokens';
|
|
7
7
|
|
|
@@ -15,6 +15,8 @@ function maybeGetNextAncestorModalLauncherPortal(element){let candidateElement=e
|
|
|
15
15
|
|
|
16
16
|
function Portal({portal,children,reference}){if(portal){const modalHost=maybeGetPortalMountedModalHostElement(reference)||document.body;return jsx(FloatingPortal,{root:modalHost,children:children})}return children}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
function FocusManager({context,dismissEnabled,useFocusManager,initialFocusRef,children}){if(!useFocusManager){return children}return jsx(FloatingFocusManager,{context:context,modal:false,initialFocus:initialFocusRef,closeOnFocusOut:false,visuallyHiddenDismiss:dismissEnabled,children:children})}
|
|
19
|
+
|
|
20
|
+
const StyledDiv=addStyle("div");const SHIFT_PADDING=12;function Floating({content,children,placement="top",open=false,onOpenChange,portal=true,strategy="absolute",testId,useFocusManager=false,initialFocusRef,dismissEnabled=false,hide:hideProp=true,offset:offsetProp=20,flip:flipProp=true,shift:shiftProp=true,showArrow=true}){const arrowRef=React.useRef(null);const prevOpenRef=React.useRef(open??false);const{elements,refs,floatingStyles,context,middlewareData}=useFloating({open,onOpenChange,placement,strategy,whileElementsMounted:autoUpdate,middleware:[offset({mainAxis:offsetProp}),flipProp?flip():undefined,shiftProp?shift({padding:SHIFT_PADDING,crossAxis:true}):undefined,showArrow?arrow({element:arrowRef}):undefined,hideProp?hide():undefined]});const dismiss=useDismiss(context,{enabled:dismissEnabled});const{getReferenceProps,getFloatingProps}=useInteractions([dismiss]);React.useEffect(()=>{if(prevOpenRef.current!==open){onOpenChange?.(open);prevOpenRef.current=open;}},[onOpenChange,open]);const trigger=React.useMemo(()=>{return React.cloneElement(children,{ref:refs.setReference,...getReferenceProps()})},[children,refs.setReference,getReferenceProps]);return jsxs(Fragment,{children:[trigger,open&&elements.reference&&jsx(Portal,{portal:portal,reference:elements.reference,children:jsx(FocusManager,{useFocusManager:useFocusManager,context:context,dismissEnabled:dismissEnabled,initialFocusRef:initialFocusRef,children:jsxs(StyledDiv,{"data-testid":testId,"data-placement":placement,ref:refs.setFloating,style:[styles.floating,floatingStyles,{visibility:middlewareData.hide?.referenceHidden?"hidden":"visible"}],...getFloatingProps(),children:[content,showArrow&&jsx(Arrow,{ref:arrowRef,context:context})]})})})]})}const styles=StyleSheet.create({floating:{background:semanticColor.core.background.base.default,border:`solid ${border.width.thin} ${semanticColor.core.border.neutral.subtle}`,borderRadius:border.radius.radius_040,maxInlineSize:472,minBlockSize:ARROW_SIZE_INLINE,boxShadow:boxShadow.mid,justifyContent:"center"}});
|
|
19
21
|
|
|
20
22
|
export { Floating };
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,8 @@ function maybeGetNextAncestorModalLauncherPortal(element){let candidateElement=e
|
|
|
38
38
|
|
|
39
39
|
function Portal({portal,children,reference}){if(portal){const modalHost=maybeGetPortalMountedModalHostElement(reference)||document.body;return jsxRuntime.jsx(react.FloatingPortal,{root:modalHost,children:children})}return children}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
function FocusManager({context,dismissEnabled,useFocusManager,initialFocusRef,children}){if(!useFocusManager){return children}return jsxRuntime.jsx(react.FloatingFocusManager,{context:context,modal:false,initialFocus:initialFocusRef,closeOnFocusOut:false,visuallyHiddenDismiss:dismissEnabled,children:children})}
|
|
42
|
+
|
|
43
|
+
const StyledDiv=addStyle("div");const SHIFT_PADDING=12;function Floating({content,children,placement="top",open=false,onOpenChange,portal=true,strategy="absolute",testId,useFocusManager=false,initialFocusRef,dismissEnabled=false,hide:hideProp=true,offset:offsetProp=20,flip:flipProp=true,shift:shiftProp=true,showArrow=true}){const arrowRef=React__namespace.useRef(null);const prevOpenRef=React__namespace.useRef(open??false);const{elements,refs,floatingStyles,context,middlewareData}=react.useFloating({open,onOpenChange,placement,strategy,whileElementsMounted:react.autoUpdate,middleware:[react.offset({mainAxis:offsetProp}),flipProp?react.flip():undefined,shiftProp?react.shift({padding:SHIFT_PADDING,crossAxis:true}):undefined,showArrow?react.arrow({element:arrowRef}):undefined,hideProp?react.hide():undefined]});const dismiss=react.useDismiss(context,{enabled:dismissEnabled});const{getReferenceProps,getFloatingProps}=react.useInteractions([dismiss]);React__namespace.useEffect(()=>{if(prevOpenRef.current!==open){onOpenChange?.(open);prevOpenRef.current=open;}},[onOpenChange,open]);const trigger=React__namespace.useMemo(()=>{return React__namespace.cloneElement(children,{ref:refs.setReference,...getReferenceProps()})},[children,refs.setReference,getReferenceProps]);return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[trigger,open&&elements.reference&&jsxRuntime.jsx(Portal,{portal:portal,reference:elements.reference,children:jsxRuntime.jsx(FocusManager,{useFocusManager:useFocusManager,context:context,dismissEnabled:dismissEnabled,initialFocusRef:initialFocusRef,children:jsxRuntime.jsxs(StyledDiv,{"data-testid":testId,"data-placement":placement,ref:refs.setFloating,style:[styles.floating,floatingStyles,{visibility:middlewareData.hide?.referenceHidden?"hidden":"visible"}],...getFloatingProps(),children:[content,showArrow&&jsxRuntime.jsx(Arrow,{ref:arrowRef,context:context})]})})})]})}const styles=aphrodite.StyleSheet.create({floating:{background:wonderBlocksTokens.semanticColor.core.background.base.default,border:`solid ${wonderBlocksTokens.border.width.thin} ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,borderRadius:wonderBlocksTokens.border.radius.radius_040,maxInlineSize:472,minBlockSize:ARROW_SIZE_INLINE,boxShadow:wonderBlocksTokens.boxShadow.mid,justifyContent:"center"}});
|
|
42
44
|
|
|
43
45
|
exports.Floating = Floating;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "A package that provides support for floating UI components in our UIs, including portal and focus management support.",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.0.0-
|
|
6
|
+
"version": "0.0.0-PR2846-20251113184845",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"types": "dist/index.d.ts",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@floating-ui/react": "^0.27.16",
|
|
23
|
-
"@khanacademy/wonder-blocks-tokens": "14.1.
|
|
23
|
+
"@khanacademy/wonder-blocks-tokens": "14.1.2"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"aphrodite": "^1.2.5",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@khanacademy/wb-dev-build-settings": "3.2.0",
|
|
31
|
-
"@khanacademy/wonder-blocks-modal": "8.5.
|
|
31
|
+
"@khanacademy/wonder-blocks-modal": "8.5.5"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"test": "echo \"Error: no test specified\" && exit 1"
|