@ably/ui 14.6.3 → 14.6.4-dev.b24b149

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/core/.DS_Store ADDED
Binary file
Binary file
package/core/Accordion.js CHANGED
@@ -1 +1 @@
1
- import React,{useState,useRef,useEffect}from"react";import Icon from"./Icon";const themeClasses={dark:{bg:"bg-neutral-1200",hoverBg:"hover:bg-neutral-1100",text:"text-white",toggleIconColor:"text-orange-600",selectableBg:"bg-neutral-300",selectableText:"text-neutral-1300"},light:{bg:"bg-neutral-200",hoverBg:"hover:bg-neutral-300",text:"text-neutral-1300",toggleIconColor:"text-neutral-1000",selectableBg:"bg-neutral-1200",selectableText:"text-white"},transparent:{bg:"bg-transparent",hoverBg:"hover:bg-transparent",text:"text-neutral-1000",toggleIconColor:"text-dark-grey",border:"border-neutral-500 border-b last:border-none"},darkTransparent:{bg:"bg-transparent",hoverBg:"hover:bg-transparent",text:"text-neutral-000",toggleIconColor:"text-orange-600",border:"border-neutral-900 border-b last:border-none"}};const isNonTransparentTheme=theme=>!["transparent","darkTransparent"].includes(theme);const AccordionRow=({name,children,onClick,open,rowIcon,options,toggleIcons,theme})=>{const rowRef=useRef(null);const[contentHeight,setContentHeight]=useState(0);useEffect(()=>{const resizeObserver=new ResizeObserver(()=>{if(rowRef.current){setContentHeight(rowRef.current.scrollHeight+16)}});if(rowRef.current){resizeObserver.observe(rowRef.current)}return()=>{if(rowRef.current){resizeObserver.unobserve(rowRef.current)}}},[]);const{selectable,sticky}=options||{};const{text,bg,hoverBg,toggleIconColor,selectableBg,selectableText,border}=themeClasses[theme];const bgClasses=selectable&&open&&selectableBg||`${bg} ${hoverBg}`;const textClass=selectable&&open&&selectableText||text;return /*#__PURE__*/React.createElement("div",{className:`${border??""}`},/*#__PURE__*/React.createElement("button",{type:"button",onClick:onClick,className:`flex w-full ${sticky?"sticky top-0":""} focus:outline-none py-16 rounded-lg ui-text-p1 font-bold text-left items-center gap-12 ${isNonTransparentTheme(theme)?"px-16":""} transition-colors ${bgClasses} ${textClass}`},rowIcon?/*#__PURE__*/React.createElement(Icon,{name:rowIcon,color:textClass,size:"32"}):null,/*#__PURE__*/React.createElement("span",null,name),!selectable?/*#__PURE__*/React.createElement("span",{className:"flex-1 justify-end flex items-center"},/*#__PURE__*/React.createElement(Icon,{name:open?toggleIcons.open.name:toggleIcons.closed.name,color:toggleIconColor,size:"16"})," "):null),/*#__PURE__*/React.createElement("div",{className:`ui-text-p2 transition-[max-height] duration-500 overflow-y-hidden ${isNonTransparentTheme(theme)?"pt-16":""}`,style:{maxHeight:open?contentHeight:0},ref:rowRef},/*#__PURE__*/React.createElement("div",{className:"pb-16"},children)))};const Accordion=({data,theme="transparent",id="id-accordion",className="",icons={closed:{name:"icon-gui-plus"},open:{name:"icon-gui-minus"}},options})=>{const{defaultOpenIndexes,autoClose}=options||{};const[openIndexes,setOpenIndexes]=useState(defaultOpenIndexes??[]);const handleSetIndex=index=>{const currentIndexIsOpen=openIndexes.includes(index);if(autoClose){setOpenIndexes(currentIndexIsOpen?[]:[index])}else{setOpenIndexes(currentIndexIsOpen?openIndexes.filter(i=>i!==index):[...openIndexes,index])}};return /*#__PURE__*/React.createElement("div",{className:className,id:id},data.map((item,currentIndex)=>{return /*#__PURE__*/React.createElement(AccordionRow,{key:item.name,name:item.name,rowIcon:item.icon,open:openIndexes.includes(currentIndex),onClick:()=>handleSetIndex(currentIndex),toggleIcons:icons,theme:theme,options:options},item.content)}))};export default Accordion;
1
+ import React,{useState,useRef,useEffect}from"react";import Icon from"./Icon";const themeClasses={dark:{bg:"bg-neutral-1200",hoverBg:"hover:bg-neutral-1100",text:"text-white",toggleIconColor:"text-orange-600",selectableBg:"bg-neutral-300",selectableText:"text-neutral-1300"},light:{bg:"bg-neutral-200",hoverBg:"hover:bg-neutral-300",text:"text-neutral-1300",toggleIconColor:"text-neutral-1000",selectableBg:"bg-neutral-1200",selectableText:"text-white"},transparent:{bg:"bg-transparent",hoverBg:"hover:bg-transparent",text:"text-neutral-1000",toggleIconColor:"text-dark-grey",border:"border-neutral-500 border-b last:border-none"},darkTransparent:{bg:"bg-transparent",hoverBg:"hover:bg-transparent",text:"text-neutral-000",toggleIconColor:"text-orange-600",border:"border-neutral-900 border-b last:border-none"}};const isNonTransparentTheme=theme=>!["transparent","darkTransparent"].includes(theme);const AccordionRow=({name,children,onClick,open,rowIcon,options,toggleIcons,theme})=>{const rowRef=useRef(null);const[contentHeight,setContentHeight]=useState(0);useEffect(()=>{const resizeObserver=new ResizeObserver(()=>{if(rowRef.current){setContentHeight(rowRef.current.scrollHeight+16)}});if(rowRef.current){resizeObserver.observe(rowRef.current)}return()=>{if(rowRef.current){resizeObserver.unobserve(rowRef.current)}}},[]);const{selectable,sticky}=options||{};const{text,bg,hoverBg,toggleIconColor,selectableBg,selectableText,border}=themeClasses[theme];const bgClasses=selectable&&open&&selectableBg||`${bg} ${hoverBg}`;const textClass=selectable&&open&&selectableText||text;return /*#__PURE__*/React.createElement("div",{className:`${border??""}`},/*#__PURE__*/React.createElement("button",{type:"button",onClick:onClick,className:`flex w-full ${sticky?"sticky top-0":""} focus:outline-none py-16 rounded-lg ui-text-p1 font-bold text-left items-center gap-12 ${isNonTransparentTheme(theme)?"px-16 mb-16":""} transition-colors ${bgClasses} ${textClass}`},rowIcon?/*#__PURE__*/React.createElement(Icon,{name:rowIcon,color:textClass,size:"32"}):null,/*#__PURE__*/React.createElement("span",null,name),!selectable?/*#__PURE__*/React.createElement("span",{className:"flex-1 justify-end flex items-center"},/*#__PURE__*/React.createElement(Icon,{name:open?toggleIcons.open.name:toggleIcons.closed.name,color:toggleIconColor,size:"16"})," "):null),/*#__PURE__*/React.createElement("div",{className:`ui-text-p2 transition-[max-height] duration-500 overflow-y-hidden`,style:{maxHeight:open?contentHeight:0},ref:rowRef},/*#__PURE__*/React.createElement("div",{className:"pb-16"},children)))};const Accordion=({data,theme="transparent",id="id-accordion",className="",icons={closed:{name:"icon-gui-plus"},open:{name:"icon-gui-minus"}},options})=>{const{defaultOpenIndexes,autoClose}=options||{};const[openIndexes,setOpenIndexes]=useState(defaultOpenIndexes??[]);const handleSetIndex=index=>{const currentIndexIsOpen=openIndexes.includes(index);if(autoClose){setOpenIndexes(currentIndexIsOpen?[]:[index])}else{setOpenIndexes(currentIndexIsOpen?openIndexes.filter(i=>i!==index):[...openIndexes,index])}};return /*#__PURE__*/React.createElement("div",{className:className,id:id},data.map((item,currentIndex)=>{return /*#__PURE__*/React.createElement(AccordionRow,{key:item.name,name:item.name,rowIcon:item.icon,open:openIndexes.includes(currentIndex),onClick:()=>handleSetIndex(currentIndex),toggleIcons:icons,theme:theme,options:options},item.content)}))};export default Accordion;
Binary file
Binary file
Binary file
Binary file
Binary file
package/core/Expander.js CHANGED
@@ -1 +1 @@
1
- import React,{useEffect,useRef,useState}from"react";import throttle from"lodash.throttle";const Expander=({heightThreshold=200,className,fadeClassName,controlsClassName,controlsOpenedLabel,controlsClosedLabel,children})=>{const innerRef=useRef(null);const[showControls,setShowControls]=useState(false);const[contentHeight,setContentHeight]=useState(heightThreshold);const[height,setHeight]=useState(heightThreshold);const[expanded,setExpanded]=useState(false);useEffect(()=>{if(innerRef.current){setContentHeight(innerRef.current.clientHeight)}if(contentHeight<heightThreshold){setHeight("auto")}else if(expanded){setHeight(contentHeight)}else{setHeight(heightThreshold)}setShowControls(contentHeight>=heightThreshold)},[contentHeight,heightThreshold,expanded]);useEffect(()=>{const onResize=throttle(()=>{if(innerRef.current){setContentHeight(innerRef.current.clientHeight)}},250);window.addEventListener("resize",onResize);return()=>{window.removeEventListener("resize",onResize)}},[]);return /*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{style:{height},"data-testid":"expander-container",className:`overflow-hidden transition-all relative ${className??""}`},showControls&&!expanded&&/*#__PURE__*/React.createElement("div",{className:`h-64 w-full bg-gradient-to-t from-white to-transparent absolute bottom-0 left-0 right-0 ${fadeClassName??""}`}),/*#__PURE__*/React.createElement("div",{ref:innerRef},children)),showControls&&/*#__PURE__*/React.createElement("div",{onClick:()=>setExpanded(!expanded),onKeyDown:e=>e.key==="Enter"&&setExpanded(!expanded),tabIndex:0,"data-testid":"expander-controls",className:`mt-16 cursor-pointer font-bold text-gui-blue-default-light hover:text-gui-blue-hover-light ${controlsClassName??""}`},expanded?controlsOpenedLabel??"View less -":controlsClosedLabel??"View all +"))};export default Expander;
1
+ import React,{useEffect,useRef,useState}from"react";import throttle from"lodash.throttle";const Expander=({heightThreshold=200,className,fadeClassName,controlsClassName,controlsOpenedLabel,controlsClosedLabel,children})=>{const innerRef=useRef(null);const[showControls,setShowControls]=useState(false);const[contentHeight,setContentHeight]=useState(heightThreshold);const[height,setHeight]=useState(heightThreshold);const[expanded,setExpanded]=useState(false);useEffect(()=>{if(innerRef.current){setContentHeight(innerRef.current.clientHeight)}if(contentHeight<heightThreshold){setHeight("auto")}else if(expanded){setHeight(contentHeight)}else{setHeight(heightThreshold)}setShowControls(contentHeight>=heightThreshold)},[contentHeight,heightThreshold,expanded]);useEffect(()=>{const onResize=throttle(()=>{if(innerRef.current){setContentHeight(innerRef.current.clientHeight)}},250);window.addEventListener("resize",onResize);return()=>{window.removeEventListener("resize",onResize)}},[]);return /*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{style:{height},"data-testid":"expander-container",className:`overflow-hidden transition-all relative ${className??""}`},showControls&&!expanded&&/*#__PURE__*/React.createElement("div",{className:`h-64 w-full bg-gradient-to-t from-white to-transparent absolute bottom-0 left-0 right-0 ${fadeClassName??""}`}),/*#__PURE__*/React.createElement("div",{ref:innerRef},children)),showControls&&/*#__PURE__*/React.createElement("div",{onClick:()=>setExpanded(!expanded),onKeyDown:e=>e.key==="Enter"&&setExpanded(!expanded),tabIndex:0,"data-testid":"expander-controls",className:`${heightThreshold===0&&!expanded?"":"mt-16"} cursor-pointer font-bold text-gui-blue-default-light hover:text-gui-blue-hover-light ${controlsClassName??""}`},expanded?controlsOpenedLabel??"View less -":controlsClosedLabel??"View all +"))};export default Expander;
Binary file
@@ -1 +1 @@
1
- import React from"react";import Icon from"./Icon";const buildTargetAndRel=(url,newWindow)=>{const props={};if(newWindow){props.target="_blank";if(url.startsWith("/")&&!url.startsWith("//")){props.rel="noopener"}else{props.rel="noopenner noreferrer"}}return props};const FeaturedLink=({url,textSize="text-p2",iconColor,flush=false,reverse=false,additionalCSS="",newWindow=false,onClick=undefined,children,disabled=false})=>{const targetAndRel=buildTargetAndRel(url,newWindow);return /*#__PURE__*/React.createElement("a",{...onClick?{}:{href:url},className:`font-sans font-bold block ${disabled?"text-gui-unavailable pointer-events-none":"text-gui-default hover:text-gui-hover focus:text-gui-focus focus:outline-gui-focus"} group ui-${textSize} ${flush?"":"py-8"} ${additionalCSS}`,style:{"--featured-link-icon-size":`var(${textSize.replace("text","--fs")})`},...targetAndRel,onClick:onClick},reverse?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement(Icon,{name:"icon-gui-link-arrow",size:`calc(var(--featured-link-icon-size) * 1.25)`,color:iconColor,additionalCSS:`align-middle mr-8 relative -top-1 -right-4 transition-[right] ${disabled?"":"group-hover:right-0"} transform rotate-180`}),children):/*#__PURE__*/React.createElement(React.Fragment,null,children,/*#__PURE__*/React.createElement(Icon,{name:"icon-gui-link-arrow",size:`calc(var(--featured-link-icon-size) * 1.25)`,color:iconColor,additionalCSS:`align-middle ml-8 relative -top-1 -left-4 transition-[left] ${disabled?"":"group-hover:left-0"}`})))};export default FeaturedLink;
1
+ import React from"react";import Icon from"./Icon";const buildTargetAndRel=(url,newWindow)=>{const props={};if(newWindow){props.target="_blank";if(url.startsWith("/")&&!url.startsWith("//")){props.rel="noopener"}else{props.rel="noopenner noreferrer"}}return props};const FeaturedLink=({url,textSize="text-p2",iconColor,flush=false,reverse=false,additionalCSS="",newWindow=false,onClick=undefined,children,disabled=false})=>{const targetAndRel=buildTargetAndRel(url,newWindow);return /*#__PURE__*/React.createElement("a",{...onClick?{}:{href:url},className:`font-sans font-bold block ${disabled?"text-gui-unavailable pointer-events-none":"text-gui-default hover:text-gui-hover focus:text-gui-focus focus:outline-gui-focus"} group/featured-link ui-${textSize} ${flush?"":"py-8"} ${additionalCSS}`,style:{"--featured-link-icon-size":`var(${textSize.replace("text","--fs")})`},...targetAndRel,onClick:onClick},reverse?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement(Icon,{name:"icon-gui-link-arrow",size:`calc(var(--featured-link-icon-size) * 1.25)`,color:iconColor,additionalCSS:`align-middle mr-8 relative -top-1 -right-4 transition-[right] ${disabled?"":"group-hover/featured-link:right-0"} transform rotate-180`}),children):/*#__PURE__*/React.createElement(React.Fragment,null,children,/*#__PURE__*/React.createElement(Icon,{name:"icon-gui-link-arrow",size:`calc(var(--featured-link-icon-size) * 1.25)`,color:iconColor,additionalCSS:`align-middle ml-8 relative -top-1 -left-4 transition-[left] ${disabled?"":"group-hover/featured-link:left-0"}`})))};export default FeaturedLink;
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1 +1 @@
1
- import React,{Fragment}from"react";import{determineThemeColor}from"../styles/colors/utils";import Icon from"../Icon";import FeaturedLink from"../FeaturedLink";const PricingCards=({data,theme="dark",delimiter})=>{const t=color=>determineThemeColor("dark",theme,color);const delimiterColumn=index=>delimiter&&index%2===1?/*#__PURE__*/React.createElement("div",{className:`flex items-center justify-center w-full @[920px]:w-20 ${delimiter!=="blank"?"m-8":""}`},delimiter!=="blank"?/*#__PURE__*/React.createElement(Icon,{name:delimiter,size:"20",additionalCSS:t("text-neutral-500")}):null):null;const gridRules={nonDelimited:"grid @[552px]:grid-cols-2 @[1104px]:grid-cols-4",delimited:"flex flex-col items-center @[920px]:flex-row"};return /*#__PURE__*/React.createElement("div",{className:"@container flex justify-center"},/*#__PURE__*/React.createElement("div",{className:`${delimiter?gridRules.delimited:gridRules.nonDelimited} gap-8`},data.map(({title,description,price,cta,sections},index)=>/*#__PURE__*/React.createElement(Fragment,{key:title.content},delimiterColumn(index),/*#__PURE__*/React.createElement("div",{className:`relative border ${t("border-neutral-1100")} flex-1 px-24 py-32 flex flex-col gap-24 rounded-2xl group ${delimiter?"@[520px]:flex-row @[920px]:flex-col":""} min-w-[272px] overflow-hidden backdrop-blur`},/*#__PURE__*/React.createElement("div",{className:`absolute z-0 -top-32 -left-32 w-[calc(100%+64px)] h-[calc(100%+64px)] rounded-2xl ${t("bg-neutral-1300")} ${cta?`${t("group-hover:bg-neutral-1200")} group-hover:opacity-100`:""} transition-[colors,opacity] opacity-25`}),/*#__PURE__*/React.createElement("div",{className:`relative z-10 flex flex-col gap-24 ${delimiter?"@[520px]:flex-1 @[920px]:flex-none":""}`},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("p",{className:`mb-12 ${title.className??""} ${t(title.color??"text-neutral-000")}`},title.content),/*#__PURE__*/React.createElement("p",{className:`ui-text-p1 ${description.className??""} ${t(description.color??"text-neutral-000")}`},description.content)),/*#__PURE__*/React.createElement("div",{className:`flex items-end gap-8 ${delimiter?"@[520px]:flex-col @[520px]:items-start @[920px]:flex-row @[920px]:items-end":""}`},/*#__PURE__*/React.createElement("p",{className:`ui-text-title font-medium tracking-tight leading-none ${t("text-neutral-000")}`},price.amount),/*#__PURE__*/React.createElement("div",{className:t("text-neutral-000")},price.content)),cta?/*#__PURE__*/React.createElement("div",{className:"group"},/*#__PURE__*/React.createElement(FeaturedLink,{additionalCSS:`text-center ui-btn ${t("bg-neutral-000")} ${t("text-neutral-1300")} hover:text-neutral-000 px-24 !py-12 ${cta.className??""} cursor-pointer`,url:cta.url,onClick:cta.onClick,disabled:cta.disabled},cta.text)):null),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col gap-24 relative z-10"},sections.map(({title,items,listItemColors,cta})=>/*#__PURE__*/React.createElement("div",{key:title,className:"flex flex-col gap-12"},/*#__PURE__*/React.createElement("p",{className:`${t("text-neutral-500")} font-mono uppercase text-overline2 tracking-[0.16em]`},title),/*#__PURE__*/React.createElement("div",{className:delimiter?"":"flex flex-col gap-4"},items.map((item,index)=>Array.isArray(item)?/*#__PURE__*/React.createElement("div",{key:item[0],className:`flex justify-between gap-16 px-8 -mx-8 ${index===0?"py-8":"py-4"} ${index>0&&index%2===0?`${t("bg-blue-900")} rounded-md`:""}`},item.map((subItem,subIndex)=>/*#__PURE__*/React.createElement("span",{key:subItem,className:`ui-text-p3 ${index===0?"font-bold":"font-medium"} ${t("text-neutral-300")} ${subIndex%2===1?"text-right":""}`},subItem))):/*#__PURE__*/React.createElement("div",{key:item,className:"flex gap-8 items-start"},listItemColors?/*#__PURE__*/React.createElement(Icon,{name:"icon-gui-check-circled-fill",color:t(listItemColors.background),secondaryColor:t(listItemColors.foreground),size:"16",additionalCSS:"mt-2"}):null,/*#__PURE__*/React.createElement("div",{className:`flex-1 ${listItemColors?"ui-text-p3":"ui-text-p2"} font-medium ${t("text-neutral-300")}`},item)))),cta?/*#__PURE__*/React.createElement("div",{className:"flex items-center h-40"},/*#__PURE__*/React.createElement("div",{className:`hidden sm:block sm:group-hover:hidden leading-6 font-extralight text-p3 ${t("text-neutral-800")}`},"•••"),/*#__PURE__*/React.createElement(FeaturedLink,{url:cta.url,additionalCSS:`sm:hidden group-hover:block font-medium ui-text-p3 ${t("text-neutral-500")} hover:${t("text-neutral-000")} transition-colors cursor-pointer`,onClick:cta.onClick},cta.text)):null)))),delimiterColumn(index)))))};export default PricingCards;
1
+ import React,{Fragment}from"react";import{determineThemeColor}from"../styles/colors/utils";import Icon from"../Icon";import FeaturedLink from"../FeaturedLink";const PricingCards=({data,theme="dark",delimiter})=>{const t=color=>determineThemeColor("dark",theme,color);const delimiterColumn=index=>delimiter&&index%2===1?/*#__PURE__*/React.createElement("div",{className:`flex items-center justify-center w-full @[920px]:w-20 ${delimiter!=="blank"?"m-8":""}`},delimiter!=="blank"?/*#__PURE__*/React.createElement(Icon,{name:delimiter,size:"20",additionalCSS:t("text-neutral-500")}):null):null;const gridRules={nonDelimited:"grid @[552px]:grid-cols-2 @[1104px]:grid-cols-4",delimited:"flex flex-col items-center @[920px]:flex-row"};return /*#__PURE__*/React.createElement("div",{className:"@container flex justify-center"},/*#__PURE__*/React.createElement("div",{className:`${delimiter?gridRules.delimited:gridRules.nonDelimited} gap-8`},data.map(({title,description,price,cta,sections},index)=>/*#__PURE__*/React.createElement(Fragment,{key:title.content},delimiterColumn(index),/*#__PURE__*/React.createElement("div",{className:`relative border ${t("border-neutral-1100")} flex-1 px-24 py-32 flex flex-col gap-24 rounded-2xl group ${delimiter?"@[520px]:flex-row @[920px]:flex-col":""} min-w-[272px] overflow-hidden backdrop-blur`},/*#__PURE__*/React.createElement("div",{className:`absolute z-0 -top-32 -left-32 w-[calc(100%+64px)] h-[calc(100%+64px)] rounded-2xl ${t("bg-neutral-1300")} ${cta?`${t("group-hover:bg-neutral-1200")} group-hover:opacity-100`:""} transition-[colors,opacity] opacity-25`}),/*#__PURE__*/React.createElement("div",{className:`relative z-10 flex flex-col gap-24 ${delimiter?"@[520px]:flex-1 @[920px]:flex-none":""}`},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("p",{className:`mb-12 ${title.className??""} ${t(title.color??"text-neutral-000")}`},title.content),/*#__PURE__*/React.createElement("p",{className:`ui-text-p1 ${description.className??""} ${t(description.color??"text-neutral-000")}`},description.content)),/*#__PURE__*/React.createElement("div",{className:`flex items-end gap-8 ${delimiter?"@[520px]:flex-col @[520px]:items-start @[920px]:flex-row @[920px]:items-end":""}`},/*#__PURE__*/React.createElement("p",{className:`ui-text-title font-medium tracking-tight leading-none ${t("text-neutral-000")}`},price.amount),/*#__PURE__*/React.createElement("div",{className:`ui-text-p3 ${t("text-neutral-000")}`},price.content)),cta?/*#__PURE__*/React.createElement("div",{className:"group"},/*#__PURE__*/React.createElement(FeaturedLink,{additionalCSS:`text-center ui-btn ${t("bg-neutral-000")} ${t("text-neutral-1300")} hover:text-neutral-000 px-24 !py-12 ${cta.className??""} cursor-pointer`,url:cta.url,onClick:cta.onClick,disabled:cta.disabled},cta.text)):null),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col gap-24 relative z-10"},sections.map(({title,items,listItemColors,cta})=>/*#__PURE__*/React.createElement("div",{key:title,className:"flex flex-col gap-12"},/*#__PURE__*/React.createElement("p",{className:`${t("text-neutral-500")} font-mono uppercase text-overline2 tracking-[0.16em]`},title),/*#__PURE__*/React.createElement("div",{className:delimiter?"":"flex flex-col gap-4"},items.map((item,index)=>Array.isArray(item)?/*#__PURE__*/React.createElement("div",{key:item[0],className:`flex justify-between gap-16 px-8 -mx-8 ${index===0?"py-8":"py-4"} ${index>0&&index%2===0?`${t("bg-blue-900")} rounded-md`:""}`},item.map((subItem,subIndex)=>/*#__PURE__*/React.createElement("span",{key:subItem,className:`ui-text-p3 ${index===0?"font-bold":"font-medium"} ${t("text-neutral-300")} ${subIndex%2===1?"text-right":""}`},subItem))):/*#__PURE__*/React.createElement("div",{key:item,className:"flex gap-8 items-start"},listItemColors?/*#__PURE__*/React.createElement(Icon,{name:"icon-gui-check-circled-fill",color:t(listItemColors.background),secondaryColor:t(listItemColors.foreground),size:"16",additionalCSS:"mt-2"}):null,/*#__PURE__*/React.createElement("div",{className:`flex-1 ${listItemColors?"ui-text-p3":"ui-text-p2"} font-medium ${t("text-neutral-300")}`},item)))),cta?/*#__PURE__*/React.createElement("div",{className:"relative flex items-center h-40"},/*#__PURE__*/React.createElement(FeaturedLink,{url:cta.url,additionalCSS:`absolute sm:-translate-x-96 sm:opacity-0 sm:group-hover:translate-x-0 duration-300 delay-0 sm:group-hover:delay-100 sm:group-hover:opacity-100 transition-[transform,opacity] font-medium ui-text-p3 ${t("text-neutral-500")} hover:${t("text-neutral-000")} cursor-pointer`,onClick:cta.onClick,iconColor:t(listItemColors?.foreground??"text-white")},cta.text),/*#__PURE__*/React.createElement("div",{className:`absolute sm:translate-x-0 sm:opacity-100 sm:group-hover:translate-x-96 sm:group-hover:opacity-0 duration-200 delay-100 sm:group-hover:delay-0 transition-[transform,opacity] leading-6 tracking-widen-0.15 font-light text-p3 ${t("text-neutral-800")}`},"•••")):null)))),delimiterColumn(index)))))};export default PricingCards;
@@ -1 +1 @@
1
- import React from"react";export const planData=[{title:{content:"Free",className:"font-mono text-p3 uppercase font-extrabold tracking-[0.16em]",color:"text-neutral-700"},description:{content:"Build a proof of concept.",className:"ui-text-p1",color:"text-neutral-500"},price:{amount:"$0"},cta:{text:"Start for free",url:"/sign-up"},sections:[{title:"Capacity",items:["200 concurrent channels","200 concurrent connections"]},{title:"Includes",items:["Community & email support (best effort)","No commitment"],listItemColors:{foreground:"text-neutral-600",background:"text-neutral-1000"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Standard",className:"font-mono text-p3 uppercase font-extrabold tracking-[0.16em]",color:"text-neutral-000"},description:{content:"Roll-out into production.",className:"ui-text-p1",color:"text-neutral-500"},price:{amount:"$29",content:/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("p",{className:"ui-text-p3 font-medium",style:{color:"currentColor"}},"/month"),/*#__PURE__*/React.createElement("p",{className:"ui-text-p2 font-bold text-gui-blue-default-dark -mt-6"},"+ consumption"))},cta:{text:"Get started",url:"/users/paid_sign_up?package=standard"},sections:[{title:"Capacity",items:["10k concurrent channels","10k concurrent connections","2.5k messages/second"]},{title:"Includes",items:["1 day email support SLA","Uptime SLO"],listItemColors:{foreground:"text-blue-400",background:"text-blue-800"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Pro",className:"font-mono text-p3 uppercase font-extrabold tracking-[0.16em]",color:"text-neutral-000"},description:{content:"Scale business critical workloads.",className:"ui-text-p1",color:"text-neutral-500"},price:{amount:"$399",content:/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("p",{className:"ui-text-p3 font-medium",style:{color:"currentColor"}},"/month"),/*#__PURE__*/React.createElement("p",{className:"ui-text-p2 font-bold text-gui-blue-default-dark -mt-6"},"+ consumption"))},cta:{text:"Get started",url:"/users/paid_sign_up?package=pro"},sections:[{title:"Capacity",items:["50k concurrent channels","50k concurrent connections","10k messages/second"]},{title:"Includes",items:["4 hour email support SLA","Datadog (lite)","Uptime SLO"],listItemColors:{foreground:"text-blue-400",background:"text-blue-800"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Enterprise",className:"font-mono text-p3 uppercase font-extrabold tracking-[0.16em]",color:"text-orange-600"},description:{content:"Serious workloads without limits.",className:"ui-text-p1",color:"text-neutral-500"},price:{amount:"Custom"},cta:{text:"Contact us",url:"#pricing-enterprise",className:"ui-btn-alt text-white"},sections:[{title:"Capacity",items:["Unlimited concurrent channels","Unlimited concurrent connections","Unlimited messages/second"]},{title:"Includes",items:["24/7 mission critical support","99.999% uptime SLAs","Committed use discounts","Datadog","CNAME, SSO, & more"],listItemColors:{foreground:"text-orange-600",background:"text-orange-1000"},cta:{text:"See all features",url:"#pricing-table"}}]}];export const consumptionData=[{title:{content:"Messages",className:"ui-text-h3",color:"text-neutral-000"},description:{content:"Messages contain the data that a client is communicating, such as the contents of a chat message.",className:"ui-text-p3",color:"text-neutral-600"},price:{amount:"$2.50",content:"per million"},sections:[{title:"Volume discounts",items:[["Consumption","$/million msgs"],["First 50 million msgs","$2.50"],["Next 450 million msgs","$2.25"],["Next 4.5 billion msgs","$1.95"],["Next 15 billion msgs","$1.65"],["Next 30 billion msgs","$1.40"],["Over 50 billion msgs","$1.25"]]}]},{title:{content:"Channels",className:"ui-text-h3",color:"text-neutral-000"},description:{content:"Clients publish and receive messages on channels (also know as topics). We only charge for active channels.",className:"ui-text-p3",color:"text-neutral-600"},price:{amount:"$1.00",content:"per million mins"},sections:[{title:"Volume discounts",items:[["Consumption","$/million msgs"],["First 10 million msgs","$1.00"],["Next 90 million msgs","$0.95"],["Next 900 million msgs","$0.85"],["Next 4 billion msgs","$0.75"],["Next 10 billion msgs","$0.65"],["Over 15 billion msgs","$0.60"]]}]},{title:{content:"Connections",className:"ui-text-h3",color:"text-neutral-000"},description:{content:"Clients establish and maintain a connection to the Ably service, typically over WebSockets. We only charge for active connections.",className:"ui-text-p3",color:"text-neutral-600"},price:{amount:"$1.00",content:"per million mins"},sections:[{title:"Volume discounts",items:[["Consumption","$/million msgs"],["First 10 million msgs","$1.00"],["Next 90 million msgs","$0.95"],["Next 900 million msgs","$0.85"],["Next 4 billion msgs","$0.75"],["Next 10 billion msgs","$0.65"],["Over 15 billion msgs","$0.60"]]}]}];
1
+ import React from"react";export const planData=[{title:{content:"Free",className:"font-mono text-p3 uppercase font-extrabold tracking-[0.16em]",color:"text-neutral-700"},description:{content:"Build a proof of concept.",className:"ui-text-p1",color:"text-neutral-500"},price:{amount:"$0"},cta:{text:"Start for free",url:"/sign-up"},sections:[{title:"Limits",items:["200 concurrent channels","200 concurrent connections","500 messages/second","6M messages/month"]},{title:"Includes",items:["Community & email support (best effort)","No commitment"],listItemColors:{foreground:"text-neutral-600",background:"text-neutral-1000"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Standard",className:"font-mono text-p3 uppercase font-extrabold tracking-[0.16em]",color:"text-neutral-000"},description:{content:"Roll-out into production.",className:"ui-text-p1",color:"text-neutral-500"},price:{amount:"$29",content:/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("p",{className:"ui-text-p3 font-medium",style:{color:"currentColor"}},"/month"),/*#__PURE__*/React.createElement("p",{className:"ui-text-p2 font-bold text-gui-blue-default-dark -mt-6"},"+ consumption"))},cta:{text:"Get started",url:"/users/paid_sign_up?package=standard"},sections:[{title:"Limits",items:["10k concurrent channels","10k concurrent connections","2.5k messages/second"]},{title:"Includes",items:["1 day email support SLA","Uptime SLO"],listItemColors:{foreground:"text-blue-400",background:"text-blue-800"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Pro",className:"font-mono text-p3 uppercase font-extrabold tracking-[0.16em]",color:"text-neutral-000"},description:{content:"Scale business critical workloads.",className:"ui-text-p1",color:"text-neutral-500"},price:{amount:"$399",content:/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("p",{className:"ui-text-p3 font-medium",style:{color:"currentColor"}},"/month"),/*#__PURE__*/React.createElement("p",{className:"ui-text-p2 font-bold text-gui-blue-default-dark -mt-6"},"+ consumption"))},cta:{text:"Get started",url:"/users/paid_sign_up?package=pro"},sections:[{title:"Limits",items:["50k concurrent channels","50k concurrent connections","10k messages/second"]},{title:"Includes",items:["2 hour support SLA","Datadog (lite)","Uptime SLO"],listItemColors:{foreground:"text-blue-400",background:"text-blue-800"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Enterprise",className:"font-mono text-p3 uppercase font-extrabold tracking-[0.16em]",color:"text-orange-600"},description:{content:"Serious workloads without limits.",className:"ui-text-p1",color:"text-neutral-500"},price:{amount:"Custom"},cta:{text:"Contact us",url:"/contact",className:"ui-btn-alt text-white"},sections:[{title:"Limits",items:["Unlimited concurrent channels","Unlimited concurrent connections","Unlimited messages/second"]},{title:"Includes",items:["24/7 mission critical support","99.999% uptime SLAs","Committed use discounts","Datadog","CNAME, SSO, & more"],listItemColors:{foreground:"text-orange-600",background:"text-orange-1000"},cta:{text:"See all features",url:"#pricing-table"}}]}];export const consumptionData=[{title:{content:"Messages",className:"ui-text-h3",color:"text-neutral-000"},description:{content:"Messages contain the data that a client is communicating, such as the contents of a chat message.",className:"ui-text-p3",color:"text-neutral-600"},price:{amount:"$2.50",content:"per million"},sections:[{title:"Volume discounts",items:[["Consumption","$/million msgs"],["First 50 million msgs","$2.50"],["Next 450 million msgs","$2.25"],["Next 4.5 billion msgs","$1.95"],["Next 15 billion msgs","$1.65"],["Next 30 billion msgs","$1.40"],["Over 50 billion msgs","$1.25"]]}]},{title:{content:"Channels",className:"ui-text-h3",color:"text-neutral-000"},description:{content:"Clients publish and receive messages on channels (also know as topics). We only charge for active channels.",className:"ui-text-p3",color:"text-neutral-600"},price:{amount:"$1.00",content:"per million mins"},sections:[{title:"Volume discounts",items:[["Consumption","$/million mins"],["First 10 million mins","$1.00"],["Next 90 million mins","$0.95"],["Next 900 million mins","$0.85"],["Next 4 billion mins","$0.75"],["Next 10 billion mins","$0.65"],["Over 15 billion mins","$0.60"]]}]},{title:{content:"Connections",className:"ui-text-h3",color:"text-neutral-000"},description:{content:"Clients establish and maintain a connection to the Ably service, typically over WebSockets.",className:"ui-text-p3",color:"text-neutral-600"},price:{amount:"$1.00",content:"per million mins"},sections:[{title:"Volume discounts",items:[["Consumption","$/million mins"],["First 10 million mins","$1.00"],["Next 90 million mins","$0.95"],["Next 900 million mins","$0.85"],["Next 4 billion mins","$0.75"],["Next 10 billion mins","$0.65"],["Over 15 billion mins","$0.60"]]}]}];
Binary file
Binary file
Binary file
package/core/Tooltip.js CHANGED
@@ -1 +1 @@
1
- import React,{useLayoutEffect,useRef,useState}from"react";import{createPortal}from"react-dom";import Icon from"./Icon";import{determineThemeColor}from"./styles/colors/utils";const Tooltip=({children,triggerElement,triggerProps,tooltipProps,theme="dark",...rest})=>{const[open,setOpen]=useState(false);const[fadeOut,setFadeOut]=useState(false);const[position,setPosition]=useState({x:0,y:0});const offset=8;const reference=useRef(null);const floating=useRef(null);const t=color=>determineThemeColor("light",theme,color);useLayoutEffect(()=>{if(open){const floatingRect=floating.current?.getBoundingClientRect();const referenceRect=reference.current?.getBoundingClientRect();const viewportWidth=window.innerWidth;const viewportHeight=window.innerHeight;if(floatingRect&&referenceRect){let x=referenceRect.left+referenceRect.width/2-floatingRect.width/2+window.scrollX;let y=referenceRect.top-floatingRect.height-offset+window.scrollY;if(x+floatingRect.width>viewportWidth+window.scrollX){x=viewportWidth+window.scrollX-floatingRect.width-offset}if(x<window.scrollX){x=window.scrollX+offset}if(y<window.scrollY){y=referenceRect.bottom+offset+window.scrollY}if(y+floatingRect.height>viewportHeight+window.scrollY){y=referenceRect.top-floatingRect.height-offset+window.scrollY}setPosition({x,y})}}else{setPosition({x:0,y:0})}},[open]);return /*#__PURE__*/React.createElement("div",{...rest,className:`relative inline-block align-top h-16 ${rest?.className??""}`},/*#__PURE__*/React.createElement("button",{onMouseEnter:()=>setOpen(true),onMouseLeave:()=>{setFadeOut(true);setTimeout(()=>{setOpen(false);setFadeOut(false)},250)},type:"button",ref:reference,"aria-describedby":"tooltip",...triggerProps,className:`ml-8 p-0 relative top-1 focus:outline-none ${triggerProps?.className??""}`},triggerElement??/*#__PURE__*/React.createElement(Icon,{name:"icon-gui-info",color:`${t("text-neutral-800")}`,size:"1rem"})),open?/*#__PURE__*/createPortal(/*#__PURE__*/React.createElement("div",{role:"tooltip",ref:floating,style:{top:position.y,left:position.x,zIndex:1e3,boxShadow:"4px 4px 15px rgba(0, 0, 0, 0.2)"},...tooltipProps,className:`${t("bg-neutral-1000")} ${t("text-neutral-200")} ui-text-p3 font-medium p-16 rounded-lg pointer-events-none absolute ${tooltipProps?.className??""} ${fadeOut?"animate-[tooltipExit_0.25s_ease-in-out]":"animate-[tooltipEntry_0.25s_ease-in-out]"}`},/*#__PURE__*/React.createElement("div",{className:"max-w-[240px] w-auto"},children)),document.body):null)};export default Tooltip;
1
+ import React,{useRef,useState,useEffect}from"react";import{createPortal}from"react-dom";import Icon from"./Icon";import{determineThemeColor}from"./styles/colors/utils";const Tooltip=({children,triggerElement,triggerProps,tooltipProps,theme="dark",interactive=false,...rest})=>{const[open,setOpen]=useState(false);const[fadeOut,setFadeOut]=useState(false);const[position,setPosition]=useState({x:0,y:0});const offset=8;const reference=useRef(null);const floating=useRef(null);const fadeOutTimeoutRef=useRef(null);const t=color=>determineThemeColor("light",theme,color);useEffect(()=>{if(open){const floatingRect=floating.current?.getBoundingClientRect();const referenceRect=reference.current?.getBoundingClientRect();const viewportWidth=window.innerWidth;const viewportHeight=window.innerHeight;if(floatingRect&&referenceRect){let x=referenceRect.left+referenceRect.width/2-floatingRect.width/2+window.scrollX;let y=referenceRect.top-floatingRect.height-offset+window.scrollY;if(x+floatingRect.width>viewportWidth+window.scrollX){x=viewportWidth+window.scrollX-floatingRect.width-offset}if(x<window.scrollX){x=window.scrollX+offset}if(y<window.scrollY){y=referenceRect.bottom+offset+window.scrollY}if(y+floatingRect.height>viewportHeight+window.scrollY){y=referenceRect.top-floatingRect.height-offset+window.scrollY}setPosition({x,y})}}else{setPosition({x:0,y:0})}return()=>{if(fadeOutTimeoutRef.current!==null){clearTimeout(fadeOutTimeoutRef.current)}}},[open]);const initiateFadeOut=()=>{setFadeOut(true);fadeOutTimeoutRef.current=setTimeout(()=>{setOpen(false);setFadeOut(false)},250)};const cursorHeadsNorth=(event,ref)=>{if(ref.current){const{clientX,clientY}=event;const{x,y,width}=ref.current.getBoundingClientRect();return clientX>=x&&clientX<=x+width&&clientY<y}return false};return /*#__PURE__*/React.createElement("div",{...rest,className:`relative inline-block align-top h-16 ${rest?.className??""}`},/*#__PURE__*/React.createElement("button",{onMouseEnter:()=>setOpen(true),onMouseLeave:event=>{if(!interactive||!cursorHeadsNorth(event,reference)){initiateFadeOut()}},type:"button",ref:reference,"aria-describedby":"tooltip",...triggerProps,className:`ml-8 p-0 relative top-1 focus:outline-none ${triggerProps?.className??""}`},triggerElement??/*#__PURE__*/React.createElement(Icon,{name:"icon-gui-info",color:`${t("text-neutral-800")}`,size:"1rem"})),open?/*#__PURE__*/createPortal(/*#__PURE__*/React.createElement("div",{role:"tooltip",ref:floating,onMouseLeave:initiateFadeOut,style:{top:position.y,left:position.x,zIndex:1e3,boxShadow:"4px 4px 15px rgba(0, 0, 0, 0.2)"},...tooltipProps,className:`${t("bg-neutral-1000")} ${t("text-neutral-200")} ui-text-p3 font-medium p-16 ${interactive?"":"pointer-events-none"} rounded-lg absolute ${tooltipProps?.className??""} ${fadeOut?"animate-[tooltipExit_0.25s_ease-in-out]":"animate-[tooltipEntry_0.25s_ease-in-out]"}`},/*#__PURE__*/React.createElement("div",{className:"max-w-[240px] w-auto"},children)),document.body):null)};export default Tooltip;
Binary file
package/index.d.ts CHANGED
@@ -873,8 +873,9 @@ type TooltipProps = {
873
873
  triggerProps?: ButtonHTMLAttributes<HTMLButtonElement>;
874
874
  tooltipProps?: HTMLAttributes<HTMLDivElement>;
875
875
  theme?: Theme;
876
+ interactive?: boolean;
876
877
  } & HTMLAttributes<HTMLDivElement>;
877
- const Tooltip: ({ children, triggerElement, triggerProps, tooltipProps, theme, ...rest }: PropsWithChildren<TooltipProps>) => import("react/jsx-runtime").JSX.Element;
878
+ const Tooltip: ({ children, triggerElement, triggerProps, tooltipProps, theme, interactive, ...rest }: PropsWithChildren<TooltipProps>) => import("react/jsx-runtime").JSX.Element;
878
879
  export default Tooltip;
879
880
  //# sourceMappingURL=Tooltip.d.ts.map
880
881
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ably/ui",
3
- "version": "14.6.3",
3
+ "version": "14.6.4-dev.b24b149",
4
4
  "description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -39,7 +39,7 @@
39
39
  "eslint": "^8.57.0",
40
40
  "eslint-config-prettier": "^9.1.0",
41
41
  "eslint-plugin-react": "^7.34.3",
42
- "eslint-plugin-storybook": "^0.8.0",
42
+ "eslint-plugin-storybook": "^0.9.0",
43
43
  "http-server": "14.1.1",
44
44
  "msw": "2.4.2",
45
45
  "msw-storybook-addon": "^2.0.2",