@khanacademy/wonder-blocks-floating 0.0.0-PR2835-20251027145156 → 0.0.0-PR2842-20251029142342
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-arrow.d.ts +5 -0
- package/dist/components/floating.d.ts +74 -1
- package/dist/es/index.js +13 -3
- package/dist/index.js +31 -2
- package/dist/util/constants.d.ts +2 -0
- package/package.json +14 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-floating
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-PR2842-20251029142342
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- 7cc5c0d: Adds wonder-blocks-floating package
|
|
8
|
+
- 669e99a: Adds Floating component with basic props (including middlewares)
|
|
@@ -1,2 +1,75 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
|
|
2
|
+
import { Placement } from "@floating-ui/react";
|
|
3
|
+
type FloatingProps = {
|
|
4
|
+
/**
|
|
5
|
+
* The reference (or anchored) element that is used to calculate the
|
|
6
|
+
* position of the floating element.
|
|
7
|
+
*/
|
|
8
|
+
children: React.ReactElement;
|
|
9
|
+
/**
|
|
10
|
+
* The content to display in the floating element.
|
|
11
|
+
*/
|
|
12
|
+
content: React.ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* The padding to apply between the floating element and its boundary.
|
|
15
|
+
* @default 8
|
|
16
|
+
*/
|
|
17
|
+
boundaryPadding?: number;
|
|
18
|
+
/**
|
|
19
|
+
* The placement of the floating element relative to the reference element.
|
|
20
|
+
* @default "top"
|
|
21
|
+
* @see https://floating-ui.com/docs/useFloating#placement
|
|
22
|
+
*/
|
|
23
|
+
placement?: Placement;
|
|
24
|
+
/**
|
|
25
|
+
* The strategy to use for positioning the floating element.
|
|
26
|
+
* @default "absolute"
|
|
27
|
+
* @see https://floating-ui.com/docs/useFloating#strategy
|
|
28
|
+
*/
|
|
29
|
+
strategy?: "fixed" | "absolute";
|
|
30
|
+
/**
|
|
31
|
+
* Whether the floating element is open.
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
open: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Callback for when the floating element is opened or closed.
|
|
37
|
+
*/
|
|
38
|
+
onOpenChange?: (open: boolean) => void;
|
|
39
|
+
/**
|
|
40
|
+
* The test ID to use for the floating element.
|
|
41
|
+
*/
|
|
42
|
+
testId?: string;
|
|
43
|
+
/**
|
|
44
|
+
* The flip strategy to use.
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
flip?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Whether to hide the floating element when the reference element is hidden.
|
|
50
|
+
* @default true
|
|
51
|
+
*/
|
|
52
|
+
hide?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* The offset of the floating element from the reference element.
|
|
55
|
+
* @default 20
|
|
56
|
+
*/
|
|
57
|
+
offset?: number;
|
|
58
|
+
/**
|
|
59
|
+
* The shift strategy to use.
|
|
60
|
+
* @default true
|
|
61
|
+
*/
|
|
62
|
+
shift?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Whether to show the arrow on the floating element.
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
showArrow?: boolean;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* A component that uses the Floating UI library to position a floating element
|
|
71
|
+
* relative to a reference element. The floating element appears on hover or
|
|
72
|
+
* focus.
|
|
73
|
+
*/
|
|
74
|
+
export default function Floating({ content, children, boundaryPadding, placement, open, onOpenChange, strategy, testId, hide: hideProp, offset: offsetProp, flip: flipProp, shift: shiftProp, showArrow, }: FloatingProps): React.JSX.Element;
|
|
75
|
+
export {};
|
package/dist/es/index.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import 'react';
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { FloatingArrow, useFloating, autoUpdate, offset, flip, shift, arrow, hide } from '@floating-ui/react';
|
|
5
|
+
import { StyleSheet, css } from 'aphrodite';
|
|
6
|
+
import { semanticColor, border, boxShadow } from '@khanacademy/wonder-blocks-tokens';
|
|
3
7
|
|
|
4
|
-
function
|
|
8
|
+
function flatten(list){const result=[];if(!list){return result}else if(Array.isArray(list)){for(const item of list){result.push(...flatten(item));}}else {result.push(list);}return result}function processStyleList(style){const stylesheetStyles=[];const inlineStyles=[];if(!style){return {style:{},className:""}}const shouldInlineStyles=typeof global!=="undefined"&&global.SNAPSHOT_INLINE_APHRODITE;flatten(style).forEach(child=>{const _definition=child._definition;if(_definition!=null){if(shouldInlineStyles){const def={};for(const[key,value]of Object.entries(_definition)){def[key.replace(/-[a-z]/g,match=>match[1].toUpperCase())]=value;}inlineStyles.push(def);}else {stylesheetStyles.push(child);}}else {inlineStyles.push(child);}});const inlineStylesObject=Object.assign({},...inlineStyles);if(inlineStyles.length>0&&!shouldInlineStyles){const inlineStylesStyleSheet=StyleSheet.create({inlineStyles:inlineStylesObject});stylesheetStyles.push(inlineStylesStyleSheet.inlineStyles);}return {style:shouldInlineStyles?inlineStylesObject:{},className:css(...stylesheetStyles)}}const isHeaderRegex=/^h[1-6]$/;const styles$1=StyleSheet.create({text:{WebkitFontSmoothing:"antialiased",MozOsxFontSmoothing:"grayscale"},header:{marginTop:0,marginBottom:0}});React.forwardRef(function Text({children,style,tag:Tag="span",testId,...otherProps},ref){const isHeader=isHeaderRegex.test(Tag);const styleAttributes=processStyleList([styles$1.text,isHeader&&styles$1.header,style]);const classNames=otherProps.className?[otherProps.className,styleAttributes.className].join(" "):styleAttributes.className;return jsx(Tag,{...otherProps,style:styleAttributes.style,className:classNames,"data-testid":testId,ref:ref,children:children})});function addStyle(Component,defaultStyle){return React.forwardRef((props,ref)=>{const{className,style,...otherProps}=props;const reset=typeof Component==="string"?overrides[Component]:null;const{className:aphroditeClassName,style:inlineStyles}=processStyleList([reset,defaultStyle,style]);return jsx(Component,{...otherProps,ref:ref,className:[aphroditeClassName,className].filter(Boolean).join(" "),style:inlineStyles})})}const overrides=StyleSheet.create({button:{margin:0,"::-moz-focus-inner":{border:0}}});const styles$2=StyleSheet.create({default:{alignItems:"stretch",borderWidth:0,borderStyle:"solid",boxSizing:"border-box",display:"flex",flexDirection:"column",margin:0,padding:0,position:"relative",zIndex:0,minHeight:0,minWidth:0}});React.forwardRef(function View(props,ref){const{testId,tag="div",...restProps}=props;const commonProps={...restProps,"data-testid":testId};const StyledTag=useMemo(()=>addStyle(tag,styles$2.default),[tag]);return jsx(StyledTag,{...commonProps,ref:ref})});(function(RenderState){RenderState["Initial"]="initial";RenderState["Standard"]="standard";return RenderState})({});(function(RenderStateInternal){RenderStateInternal["Root"]="root";RenderStateInternal["Initial"]="initial";RenderStateInternal["Standard"]="standard";return RenderStateInternal})({});const RenderStateContext=React.createContext("root");RenderStateContext.displayName="RenderStateContext";
|
|
9
|
+
|
|
10
|
+
const ARROW_SIZE_INLINE=20;const ARROW_SIZE_BLOCK=10;
|
|
11
|
+
|
|
12
|
+
const Arrow=React.forwardRef(function Arrow({context},ref){const style=context.placement.endsWith("top")?{filter:`drop-shadow(0 4px 2px ${semanticColor.core.shadow.transparent.mid})`}:undefined;return jsx(FloatingArrow,{ref:ref,context:context,fill:semanticColor.core.background.base.default,stroke:semanticColor.core.border.neutral.subtle,strokeWidth:1,width:ARROW_SIZE_INLINE,height:ARROW_SIZE_BLOCK,style:style})});
|
|
13
|
+
|
|
14
|
+
const StyledDiv=addStyle("div");function Floating({content,children,boundaryPadding=8,placement="top",open=false,onOpenChange,strategy="absolute",testId,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{refs,floatingStyles,context,middlewareData}=useFloating({open,onOpenChange,placement,strategy,whileElementsMounted:autoUpdate,middleware:[offset({mainAxis:offsetProp}),flipProp?flip():undefined,shiftProp?shift({padding:boundaryPadding,crossAxis:true}):undefined,showArrow?arrow({element:arrowRef}):undefined,hideProp?hide():undefined]});React.useEffect(()=>{if(prevOpenRef.current!==open){onOpenChange?.(open);prevOpenRef.current=open;}},[onOpenChange,open]);const trigger=React.useMemo(()=>{return React.cloneElement(children,{ref:refs.setReference})},[children,refs.setReference]);return jsxs(Fragment,{children:[trigger,open&&jsxs(StyledDiv,{"data-testid":testId,"data-placement":placement,ref:refs.setFloating,style:[styles.floating,floatingStyles,{visibility:middlewareData.hide?.referenceHidden?"hidden":"visible"}],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:288,minBlockSize:ARROW_SIZE_INLINE,boxShadow:boxShadow.mid,justifyContent:"center"}});
|
|
5
15
|
|
|
6
16
|
export { Floating };
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,37 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
-
require('react');
|
|
6
|
+
var React = require('react');
|
|
7
|
+
var react = require('@floating-ui/react');
|
|
8
|
+
var aphrodite = require('aphrodite');
|
|
9
|
+
var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
|
|
7
10
|
|
|
8
|
-
function
|
|
11
|
+
function _interopNamespace(e) {
|
|
12
|
+
if (e && e.__esModule) return e;
|
|
13
|
+
var n = Object.create(null);
|
|
14
|
+
if (e) {
|
|
15
|
+
Object.keys(e).forEach(function (k) {
|
|
16
|
+
if (k !== 'default') {
|
|
17
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
18
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () { return e[k]; }
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
n["default"] = e;
|
|
26
|
+
return Object.freeze(n);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
30
|
+
|
|
31
|
+
function flatten(list){const result=[];if(!list){return result}else if(Array.isArray(list)){for(const item of list){result.push(...flatten(item));}}else {result.push(list);}return result}function processStyleList(style){const stylesheetStyles=[];const inlineStyles=[];if(!style){return {style:{},className:""}}const shouldInlineStyles=typeof global!=="undefined"&&global.SNAPSHOT_INLINE_APHRODITE;flatten(style).forEach(child=>{const _definition=child._definition;if(_definition!=null){if(shouldInlineStyles){const def={};for(const[key,value]of Object.entries(_definition)){def[key.replace(/-[a-z]/g,match=>match[1].toUpperCase())]=value;}inlineStyles.push(def);}else {stylesheetStyles.push(child);}}else {inlineStyles.push(child);}});const inlineStylesObject=Object.assign({},...inlineStyles);if(inlineStyles.length>0&&!shouldInlineStyles){const inlineStylesStyleSheet=aphrodite.StyleSheet.create({inlineStyles:inlineStylesObject});stylesheetStyles.push(inlineStylesStyleSheet.inlineStyles);}return {style:shouldInlineStyles?inlineStylesObject:{},className:aphrodite.css(...stylesheetStyles)}}const isHeaderRegex=/^h[1-6]$/;const styles$1=aphrodite.StyleSheet.create({text:{WebkitFontSmoothing:"antialiased",MozOsxFontSmoothing:"grayscale"},header:{marginTop:0,marginBottom:0}});React__namespace.forwardRef(function Text({children,style,tag:Tag="span",testId,...otherProps},ref){const isHeader=isHeaderRegex.test(Tag);const styleAttributes=processStyleList([styles$1.text,isHeader&&styles$1.header,style]);const classNames=otherProps.className?[otherProps.className,styleAttributes.className].join(" "):styleAttributes.className;return jsxRuntime.jsx(Tag,{...otherProps,style:styleAttributes.style,className:classNames,"data-testid":testId,ref:ref,children:children})});function addStyle(Component,defaultStyle){return React__namespace.forwardRef((props,ref)=>{const{className,style,...otherProps}=props;const reset=typeof Component==="string"?overrides[Component]:null;const{className:aphroditeClassName,style:inlineStyles}=processStyleList([reset,defaultStyle,style]);return jsxRuntime.jsx(Component,{...otherProps,ref:ref,className:[aphroditeClassName,className].filter(Boolean).join(" "),style:inlineStyles})})}const overrides=aphrodite.StyleSheet.create({button:{margin:0,"::-moz-focus-inner":{border:0}}});const styles$2=aphrodite.StyleSheet.create({default:{alignItems:"stretch",borderWidth:0,borderStyle:"solid",boxSizing:"border-box",display:"flex",flexDirection:"column",margin:0,padding:0,position:"relative",zIndex:0,minHeight:0,minWidth:0}});React__namespace.forwardRef(function View(props,ref){const{testId,tag="div",...restProps}=props;const commonProps={...restProps,"data-testid":testId};const StyledTag=React.useMemo(()=>addStyle(tag,styles$2.default),[tag]);return jsxRuntime.jsx(StyledTag,{...commonProps,ref:ref})});(function(RenderState){RenderState["Initial"]="initial";RenderState["Standard"]="standard";return RenderState})({});(function(RenderStateInternal){RenderStateInternal["Root"]="root";RenderStateInternal["Initial"]="initial";RenderStateInternal["Standard"]="standard";return RenderStateInternal})({});const RenderStateContext=React__namespace.createContext("root");RenderStateContext.displayName="RenderStateContext";
|
|
32
|
+
|
|
33
|
+
const ARROW_SIZE_INLINE=20;const ARROW_SIZE_BLOCK=10;
|
|
34
|
+
|
|
35
|
+
const Arrow=React__namespace.forwardRef(function Arrow({context},ref){const style=context.placement.endsWith("top")?{filter:`drop-shadow(0 4px 2px ${wonderBlocksTokens.semanticColor.core.shadow.transparent.mid})`}:undefined;return jsxRuntime.jsx(react.FloatingArrow,{ref:ref,context:context,fill:wonderBlocksTokens.semanticColor.core.background.base.default,stroke:wonderBlocksTokens.semanticColor.core.border.neutral.subtle,strokeWidth:1,width:ARROW_SIZE_INLINE,height:ARROW_SIZE_BLOCK,style:style})});
|
|
36
|
+
|
|
37
|
+
const StyledDiv=addStyle("div");function Floating({content,children,boundaryPadding=8,placement="top",open=false,onOpenChange,strategy="absolute",testId,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{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:boundaryPadding,crossAxis:true}):undefined,showArrow?react.arrow({element:arrowRef}):undefined,hideProp?react.hide():undefined]});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})},[children,refs.setReference]);return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[trigger,open&&jsxRuntime.jsxs(StyledDiv,{"data-testid":testId,"data-placement":placement,ref:refs.setFloating,style:[styles.floating,floatingStyles,{visibility:middlewareData.hide?.referenceHidden?"hidden":"visible"}],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:288,minBlockSize:ARROW_SIZE_INLINE,boxShadow:wonderBlocksTokens.boxShadow.mid,justifyContent:"center"}});
|
|
9
38
|
|
|
10
39
|
exports.Floating = Floating;
|
package/package.json
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-floating",
|
|
3
|
-
"version": "0.0.0-PR2835-20251027145156",
|
|
4
3
|
"description": "A package that provides support for floating UI components in our UIs, including portal and focus management support.",
|
|
5
|
-
"
|
|
6
|
-
"module": "dist/es/index.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"author": "",
|
|
4
|
+
"author": "Khan Academy",
|
|
9
5
|
"license": "MIT",
|
|
6
|
+
"version": "0.0.0-PR2842-20251029142342",
|
|
10
7
|
"publishConfig": {
|
|
11
8
|
"access": "public"
|
|
12
9
|
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/Khan/wonder-blocks.git",
|
|
13
|
+
"directory": "packages/wonder-blocks-floating"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/Khan/wonder-blocks/issues"
|
|
17
|
+
},
|
|
18
|
+
"main": "dist/index.js",
|
|
19
|
+
"module": "dist/es/index.js",
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
13
21
|
"dependencies": {
|
|
14
22
|
"@floating-ui/react": "^0.27.16",
|
|
15
|
-
"@khanacademy/wonder-blocks-tokens": "14.
|
|
23
|
+
"@khanacademy/wonder-blocks-tokens": "14.1.0"
|
|
16
24
|
},
|
|
17
25
|
"peerDependencies": {
|
|
18
26
|
"aphrodite": "^1.2.5",
|