@khanacademy/wonder-blocks-floating 0.0.0-PR2835-20251028140715 → 0.0.0-PR2842-20251029173610

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 CHANGED
@@ -1,7 +1,8 @@
1
1
  # @khanacademy/wonder-blocks-floating
2
2
 
3
- ## 0.0.0-PR2835-20251028140715
3
+ ## 0.0.0-PR2842-20251029173610
4
4
 
5
5
  ### Minor Changes
6
6
 
7
- - e488896: Adds wonder-blocks-floating package
7
+ - 7cc5c0d: Adds wonder-blocks-floating package
8
+ - 669e99a: Adds Floating component with basic props (including middlewares)
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+ import { FloatingContext } from "@floating-ui/react";
3
+ export declare const Arrow: React.ForwardRefExoticComponent<{
4
+ context: FloatingContext;
5
+ } & React.RefAttributes<SVGSVGElement>>;
@@ -1,2 +1,75 @@
1
1
  import * as React from "react";
2
- export default function Floating(): React.JSX.Element;
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 Floating(){return jsx("div",{children:"Floating"})}
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:472,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 Floating(){return jsxRuntime.jsx("div",{children:"Floating"})}
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:472,minBlockSize:ARROW_SIZE_INLINE,boxShadow:wonderBlocksTokens.boxShadow.mid,justifyContent:"center"}});
9
38
 
10
39
  exports.Floating = Floating;
@@ -0,0 +1,2 @@
1
+ export declare const ARROW_SIZE_INLINE = 20;
2
+ export declare const ARROW_SIZE_BLOCK = 10;
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-PR2835-20251028140715",
6
+ "version": "0.0.0-PR2842-20251029173610",
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.0.0"
23
+ "@khanacademy/wonder-blocks-tokens": "14.1.0"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "aphrodite": "^1.2.5",