@ably/ui 17.9.0-dev.7b4c6aac → 17.9.1-dev.f8cf1684
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/Code.js +1 -1
- package/core/Code.js.map +1 -1
- package/core/CodeSnippet/ApiKeySelector.js +1 -1
- package/core/CodeSnippet/ApiKeySelector.js.map +1 -1
- package/core/CodeSnippet/CopyButton.js +1 -1
- package/core/CodeSnippet/CopyButton.js.map +1 -1
- package/core/CodeSnippet/LanguageSelector.js +1 -1
- package/core/CodeSnippet/LanguageSelector.js.map +1 -1
- package/core/CodeSnippet/PlainCodeView.js +1 -1
- package/core/CodeSnippet/PlainCodeView.js.map +1 -1
- package/core/CodeSnippet/TooltipButton.js +1 -1
- package/core/CodeSnippet/TooltipButton.js.map +1 -1
- package/core/CodeSnippet.js +1 -1
- package/core/CodeSnippet.js.map +1 -1
- package/core/CookieMessage.js +1 -1
- package/core/CookieMessage.js.map +1 -1
- package/core/DropdownMenu.js +1 -1
- package/core/DropdownMenu.js.map +1 -1
- package/core/Expander.js +1 -1
- package/core/Expander.js.map +1 -1
- package/core/Flash.js +1 -1
- package/core/Flash.js.map +1 -1
- package/core/Header/HeaderLinks.js +1 -1
- package/core/Header/HeaderLinks.js.map +1 -1
- package/core/Header.js +1 -1
- package/core/Header.js.map +1 -1
- package/core/Meganav.js +1 -1
- package/core/Meganav.js.map +1 -1
- package/core/Pricing/PricingCards.js +1 -1
- package/core/Pricing/PricingCards.js.map +1 -1
- package/core/Slider.js +1 -1
- package/core/Slider.js.map +1 -1
- package/core/TabMenu.js +1 -1
- package/core/TabMenu.js.map +1 -1
- package/index.d.ts +12 -39
- package/package.json +2 -3
- package/core/utils/useCopyToClipboard.js +0 -2
- package/core/utils/useCopyToClipboard.js.map +0 -1
package/core/Slider.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{useCallback,useEffect,useState}from"react";import useEmblaCarousel from"embla-carousel-react";import Autoplay from"embla-carousel-autoplay";import Icon from"./Icon";const SlideIndicator=({numSlides,activeIndex,interval,intervalIndicator,isInline})=>{return React.createElement("ul",{className
|
|
1
|
+
import React,{useCallback,useEffect,useState}from"react";import useEmblaCarousel from"embla-carousel-react";import Autoplay from"embla-carousel-autoplay";import Icon from"./Icon";import cn from"./utils/cn";const SlideIndicator=({numSlides,activeIndex,interval,intervalIndicator,isInline})=>{return React.createElement("ul",{className:cn("flex gap-1 left-1/2",isInline?"bottom-0":"absolute bottom-0 transform -translate-x-1/2")},Array.from({length:numSlides},(_,i)=>intervalIndicator?React.createElement("li",{key:i,className:"relative w-10 h-1 mx-px rounded-full bg-neutral-500"},i===activeIndex&&React.createElement("span",{className:"absolute inset-0 rounded-full bg-active-orange",style:{animation:`fillAnimation ${interval}ms linear`}})):React.createElement("li",{key:i},React.createElement("span",{className:cn("ui-slider-marker",i===activeIndex?"text-active-orange":"text-cool-black"),"data-id":"slider-marker"},"⬤"))))};const Slider=({children,options})=>{const[activeIndex,setActiveIndex]=useState(0);const interval=options?.interval??1e4;const isInline=options?.controlPosition==="inline";const[emblaRef,emblaApi]=useEmblaCarousel({loop:true,duration:30},[Autoplay({delay:interval,stopOnInteraction:false})]);const scrollPrev=useCallback(()=>{if(emblaApi)emblaApi.scrollPrev()},[emblaApi]);const scrollNext=useCallback(()=>{if(emblaApi)emblaApi.scrollNext()},[emblaApi]);const onSelect=useCallback(emblaApi=>{setActiveIndex(emblaApi.selectedScrollSnap())},[]);useEffect(()=>{if(!emblaApi)return;onSelect(emblaApi);emblaApi.on("select",onSelect).on("reInit",onSelect);return()=>{emblaApi.off("select",onSelect).off("reInit",onSelect)}},[emblaApi,onSelect]);return React.createElement("div",{className:"relative"},React.createElement("div",{className:"overflow-hidden w-full py-10",ref:emblaRef},React.createElement("div",{className:"flex"},children.map((child,index)=>React.createElement("div",{key:index,className:"w-full flex-shrink-0 flex justify-center sm:px-[3.75rem]"},child)))),React.createElement("div",{className:cn("flex items-center pointer-events-none",isInline?"ui-standard-container justify-center gap-6 -mt-4":"sm:flex sm:absolute inset-0 justify-between")},React.createElement("button",{className:cn(isInline?"w-8 h-8":"hidden sm:flex w-12 h-12","pointer-events-auto rounded border border-mid-grey hover:border-active-orange flex justify-center items-center ui-icon-cta ui-icon-cta-left"),onClick:scrollPrev},React.createElement("div",{className:"ui-icon-cta-holder flex w-12"},React.createElement("div",{className:"w-full h-full flex-shrink-0 flex items-center justify-center"},React.createElement(Icon,{name:"icon-gui-arrow-long-left-outline",size:"1.5rem"})),React.createElement("div",{className:"w-full h-full flex-shrink-0 flex items-center justify-center"},React.createElement(Icon,{name:"icon-gui-arrow-long-left-outline",size:"1.5rem"})))),React.createElement(SlideIndicator,{numSlides:children.length,activeIndex:activeIndex,interval:interval,intervalIndicator:options?.intervalIndicator,isInline:isInline}),React.createElement("button",{className:cn(isInline?"w-8 h-8":"hidden sm:flex w-12 h-12","pointer-events-auto rounded border border-mid-grey hover:border-active-orange justify-center items-center ui-icon-cta ui-icon-cta-right"),onClick:scrollNext},React.createElement("div",{className:cn("ui-icon-cta-holder flex w-12",isInline?"-ml-3.5":"")},React.createElement("div",{className:"w-full h-full flex-shrink-0 flex items-center justify-center"},React.createElement(Icon,{name:"icon-gui-arrow-long-right-outline",size:"1.5rem"})),React.createElement("div",{className:"w-full h-full flex-shrink-0 flex items-center justify-center"},React.createElement(Icon,{name:"icon-gui-arrow-long-right-outline",size:"1.5rem"}))))))};export default Slider;
|
|
2
2
|
//# sourceMappingURL=Slider.js.map
|
package/core/Slider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/Slider.tsx"],"sourcesContent":["import React, { ReactNode, useCallback, useEffect, useState } from \"react\";\nimport useEmblaCarousel from \"embla-carousel-react\";\nimport Autoplay from \"embla-carousel-autoplay\";\nimport type { EmblaCarouselType } from \"embla-carousel\";\nimport Icon from \"./Icon\";\n\ninterface SliderProps {\n children: ReactNode[];\n options?: {\n interval?: number;\n controlPosition?: \"inline\" | \"floating\";\n intervalIndicator?: boolean;\n };\n}\n\ninterface SliderIndicatorProps {\n numSlides: number;\n activeIndex: number;\n interval: number;\n intervalIndicator?: boolean;\n isInline?: boolean;\n}\n\nconst SlideIndicator = ({\n numSlides,\n activeIndex,\n interval,\n intervalIndicator,\n isInline,\n}: SliderIndicatorProps) => {\n return (\n <ul\n className={
|
|
1
|
+
{"version":3,"sources":["../../src/core/Slider.tsx"],"sourcesContent":["import React, { ReactNode, useCallback, useEffect, useState } from \"react\";\nimport useEmblaCarousel from \"embla-carousel-react\";\nimport Autoplay from \"embla-carousel-autoplay\";\nimport type { EmblaCarouselType } from \"embla-carousel\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn\";\n\ninterface SliderProps {\n children: ReactNode[];\n options?: {\n interval?: number;\n controlPosition?: \"inline\" | \"floating\";\n intervalIndicator?: boolean;\n };\n}\n\ninterface SliderIndicatorProps {\n numSlides: number;\n activeIndex: number;\n interval: number;\n intervalIndicator?: boolean;\n isInline?: boolean;\n}\n\nconst SlideIndicator = ({\n numSlides,\n activeIndex,\n interval,\n intervalIndicator,\n isInline,\n}: SliderIndicatorProps) => {\n return (\n <ul\n className={cn(\n \"flex gap-1 left-1/2\",\n isInline ? \"bottom-0\" : \"absolute bottom-0 transform -translate-x-1/2\",\n )}\n >\n {Array.from({ length: numSlides }, (_, i) =>\n intervalIndicator ? (\n <li\n key={i}\n className=\"relative w-10 h-1 mx-px rounded-full bg-neutral-500\"\n >\n {i === activeIndex && (\n <span\n className=\"absolute inset-0 rounded-full bg-active-orange\"\n style={{\n animation: `fillAnimation ${interval}ms linear`,\n }}\n ></span>\n )}\n </li>\n ) : (\n <li key={i}>\n <span\n className={cn(\n \"ui-slider-marker\",\n i === activeIndex ? \"text-active-orange\" : \"text-cool-black\",\n )}\n data-id=\"slider-marker\"\n >\n ⬤\n </span>\n </li>\n ),\n )}\n </ul>\n );\n};\n\nconst Slider = ({ children, options }: SliderProps) => {\n const [activeIndex, setActiveIndex] = useState(0);\n const interval = options?.interval ?? 10000;\n const isInline = options?.controlPosition === \"inline\";\n\n const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true, duration: 30 }, [\n Autoplay({ delay: interval, stopOnInteraction: false }),\n ]);\n\n const scrollPrev = useCallback(() => {\n if (emblaApi) emblaApi.scrollPrev();\n }, [emblaApi]);\n\n const scrollNext = useCallback(() => {\n if (emblaApi) emblaApi.scrollNext();\n }, [emblaApi]);\n\n const onSelect = useCallback((emblaApi: EmblaCarouselType) => {\n setActiveIndex(emblaApi.selectedScrollSnap());\n }, []);\n\n useEffect(() => {\n if (!emblaApi) return;\n\n onSelect(emblaApi);\n emblaApi.on(\"select\", onSelect).on(\"reInit\", onSelect);\n\n return () => {\n emblaApi.off(\"select\", onSelect).off(\"reInit\", onSelect);\n };\n }, [emblaApi, onSelect]);\n\n return (\n <div className=\"relative\">\n <div className=\"overflow-hidden w-full py-10\" ref={emblaRef}>\n <div className=\"flex\">\n {children.map((child, index) => (\n <div\n key={index}\n className=\"w-full flex-shrink-0 flex justify-center sm:px-[3.75rem]\"\n >\n {child}\n </div>\n ))}\n </div>\n </div>\n\n <div\n className={cn(\n \"flex items-center pointer-events-none\",\n isInline\n ? \"ui-standard-container justify-center gap-6 -mt-4\"\n : \"sm:flex sm:absolute inset-0 justify-between\",\n )}\n >\n <button\n className={cn(\n isInline ? \"w-8 h-8\" : \"hidden sm:flex w-12 h-12\",\n \"pointer-events-auto rounded border border-mid-grey hover:border-active-orange flex justify-center items-center ui-icon-cta ui-icon-cta-left\",\n )}\n onClick={scrollPrev}\n >\n <div className=\"ui-icon-cta-holder flex w-12\">\n <div className=\"w-full h-full flex-shrink-0 flex items-center justify-center\">\n <Icon name=\"icon-gui-arrow-long-left-outline\" size=\"1.5rem\" />\n </div>\n <div className=\"w-full h-full flex-shrink-0 flex items-center justify-center\">\n <Icon name=\"icon-gui-arrow-long-left-outline\" size=\"1.5rem\" />\n </div>\n </div>\n </button>\n\n <SlideIndicator\n numSlides={children.length}\n activeIndex={activeIndex}\n interval={interval}\n intervalIndicator={options?.intervalIndicator}\n isInline={isInline}\n />\n\n <button\n className={cn(\n isInline ? \"w-8 h-8\" : \"hidden sm:flex w-12 h-12\",\n \"pointer-events-auto rounded border border-mid-grey hover:border-active-orange justify-center items-center ui-icon-cta ui-icon-cta-right\",\n )}\n onClick={scrollNext}\n >\n <div\n className={cn(\n \"ui-icon-cta-holder flex w-12\",\n isInline ? \"-ml-3.5\" : \"\",\n )}\n >\n <div className=\"w-full h-full flex-shrink-0 flex items-center justify-center\">\n <Icon name=\"icon-gui-arrow-long-right-outline\" size=\"1.5rem\" />\n </div>\n <div className=\"w-full h-full flex-shrink-0 flex items-center justify-center\">\n <Icon name=\"icon-gui-arrow-long-right-outline\" size=\"1.5rem\" />\n </div>\n </div>\n </button>\n </div>\n </div>\n );\n};\n\nexport default Slider;\n"],"names":["React","useCallback","useEffect","useState","useEmblaCarousel","Autoplay","Icon","cn","SlideIndicator","numSlides","activeIndex","interval","intervalIndicator","isInline","ul","className","Array","from","length","_","i","li","key","span","style","animation","data-id","Slider","children","options","setActiveIndex","controlPosition","emblaRef","emblaApi","loop","duration","delay","stopOnInteraction","scrollPrev","scrollNext","onSelect","selectedScrollSnap","on","off","div","ref","map","child","index","button","onClick","name","size"],"mappings":"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"}
|
package/core/TabMenu.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{useEffect}from"react";import*as Tabs from"@radix-ui/react-tabs";import{throttle}from"es-toolkit/compat";import cn from"./utils/cn";const DEFAULT_TAILWIND_ANIMATION_DURATION=150;const TabMenu=({tabs=[],contents=[],tabOnClick,tabClassName,rootClassName,contentClassName,options})=>{const{defaultTabIndex=0,underline=true,animated:animatedOption=true,flexibleTabWidth=false,flexibleTabHeight=false}=options??{};const listRef=React.useRef(null);const[animated,setAnimated]=React.useState(false);const[highlight,setHighlight]=React.useState({offset:0,width:0});useEffect(()=>{if(animatedOption&&highlight.width>0){setTimeout(()=>{setAnimated(true)},DEFAULT_TAILWIND_ANIMATION_DURATION)}},[animatedOption,highlight.width]);useEffect(()=>{const handleResize=throttle(()=>{const activeTabElement=listRef.current?.querySelector(`[data-state="active"]`);if(activeTabElement){updateHighlightDimensions(activeTabElement)}},100);handleResize();window.addEventListener("resize",handleResize);return()=>{window.removeEventListener("resize",handleResize)}},[]);const
|
|
1
|
+
import React,{useEffect}from"react";import*as Tabs from"@radix-ui/react-tabs";import{throttle}from"es-toolkit/compat";import cn from"./utils/cn";const DEFAULT_TAILWIND_ANIMATION_DURATION=150;const TabMenu=({tabs=[],contents=[],tabOnClick,tabClassName,rootClassName,contentClassName,options})=>{const{defaultTabIndex=0,underline=true,animated:animatedOption=true,flexibleTabWidth=false,flexibleTabHeight=false}=options??{};const listRef=React.useRef(null);const[animated,setAnimated]=React.useState(false);const[highlight,setHighlight]=React.useState({offset:0,width:0});useEffect(()=>{if(animatedOption&&highlight.width>0){setTimeout(()=>{setAnimated(true)},DEFAULT_TAILWIND_ANIMATION_DURATION)}},[animatedOption,highlight.width]);const updateHighlightDimensions=element=>{const{left:parentLeft}=listRef.current?.getBoundingClientRect()??{};const{left,width}=element.getBoundingClientRect()??{};setHighlight({offset:(left??0)-(parentLeft??0),width:width??0})};useEffect(()=>{const handleResize=throttle(()=>{const activeTabElement=listRef.current?.querySelector(`[data-state="active"]`);if(activeTabElement){updateHighlightDimensions(activeTabElement)}},100);handleResize();window.addEventListener("resize",handleResize);return()=>{window.removeEventListener("resize",handleResize)}},[]);const handleTabClick=(event,index)=>{tabOnClick?.(index);updateHighlightDimensions(event.currentTarget)};const tabTriggerContent=tab=>{if(!tab){return null}if(React.isValidElement(tab)||typeof tab==="string"){return tab}if(typeof tab==="object"&&"label"in tab){return tab.label}return null};return React.createElement(Tabs.Root,{defaultValue:`tab-${defaultTabIndex}`,className:cn({"h-full":flexibleTabHeight},rootClassName)},React.createElement(Tabs.List,{ref:listRef,className:cn("relative",{"flex border-b border-neutral-300 dark:border-neutral-1000":underline},{"h-full":flexibleTabHeight})},tabs.map((tab,index)=>tab&&React.createElement(Tabs.Trigger,{key:`tab-${index}`,className:cn("lg:px-6 md:px-5 px-4 py-4 ui-text-label1 font-bold data-[state=active]:text-neutral-1300 text-neutral-1000 dark:data-[state=active]:text-neutral-000 dark:text-neutral-300 focus:outline-none focus-visible:outline-gui-focus transition-colors hover:text-neutral-1300 dark:hover:text-neutral-000 active:text-neutral-900 dark:active:text-neutral-400 disabled:text-gui-unavailable dark:disabled:text-gui-unavailable-dark disabled:cursor-not-allowed",{"flex-1":flexibleTabWidth},{"h-full":flexibleTabHeight},tabClassName),value:`tab-${index}`,onClick:event=>handleTabClick(event,index),disabled:typeof tab==="object"&&"disabled"in tab?tab.disabled:false},tabTriggerContent(tab))),React.createElement("div",{className:cn("absolute bottom-0 bg-neutral-1300 dark:bg-neutral-000 h-[0.1875rem] w-6",{"transition-[transform,width]":animated}),style:{transform:`translateX(${highlight.offset}px)`,width:`${highlight.width}px`}})),contents.map((content,index)=>React.createElement(Tabs.Content,{key:`tab-${index}`,value:`tab-${index}`,className:contentClassName},content)))};export default TabMenu;
|
|
2
2
|
//# sourceMappingURL=TabMenu.js.map
|
package/core/TabMenu.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/TabMenu.tsx"],"sourcesContent":["import React, { ReactNode, useEffect } from \"react\";\nimport * as Tabs from \"@radix-ui/react-tabs\";\nimport { throttle } from \"es-toolkit/compat\";\nimport cn from \"./utils/cn\";\n\ntype TabTriggerContent =\n | string\n | { label: string; disabled?: boolean }\n | ReactNode;\n\n/**\n * Props for the TabMenu component.\n */\n\nexport type TabMenuProps = {\n /**\n * An array of tabs, which can be either a string or an object with a label and an optional disabled state.\n */\n tabs: TabTriggerContent[];\n\n /**\n * An optional array of React nodes representing the content for each tab.\n */\n contents?: ReactNode[];\n\n /**\n * An optional callback function that is called when a tab is clicked, receiving the index of the clicked tab.\n */\n tabOnClick?: (index: number) => void;\n\n /**\n * An optional class name to apply to each tab.\n */\n tabClassName?: string;\n\n /**\n * An optional class name to apply to the Tabs.Root element.\n */\n rootClassName?: string;\n\n /**\n * An optional class name to apply to the Tabs.Content element.\n */\n contentClassName?: string;\n\n /**\n * Optional configuration options for the TabMenu.\n */\n options?: {\n /**\n * The index of the tab that should be selected by default.\n */\n defaultTabIndex?: number;\n\n /**\n * Whether to show an underline below the selected tab.\n */\n underline?: boolean;\n\n /**\n * Whether to animate the transition between tabs.\n */\n animated?: boolean;\n\n /**\n * Whether the tab width should be flexible.\n */\n flexibleTabWidth?: boolean;\n\n /**\n * Whether the tab height should be flexible.\n */\n flexibleTabHeight?: boolean;\n };\n};\n\nconst DEFAULT_TAILWIND_ANIMATION_DURATION = 150;\n\nconst TabMenu: React.FC<TabMenuProps> = ({\n tabs = [],\n contents = [],\n tabOnClick,\n tabClassName,\n rootClassName,\n contentClassName,\n options,\n}) => {\n const {\n defaultTabIndex = 0,\n underline = true,\n animated: animatedOption = true,\n flexibleTabWidth = false,\n flexibleTabHeight = false,\n } = options ?? {};\n\n const listRef = React.useRef<HTMLDivElement>(null);\n const [animated, setAnimated] = React.useState(false);\n const [highlight, setHighlight] = React.useState({ offset: 0, width: 0 });\n\n useEffect(() => {\n if (animatedOption && highlight.width > 0) {\n setTimeout(() => {\n setAnimated(true);\n }, DEFAULT_TAILWIND_ANIMATION_DURATION);\n }\n }, [animatedOption, highlight.width]);\n\n useEffect(() => {\n const handleResize = throttle(() => {\n const activeTabElement =\n listRef.current?.querySelector<HTMLButtonElement>(\n `[data-state=\"active\"]`,\n );\n\n if (activeTabElement) {\n updateHighlightDimensions(activeTabElement);\n }\n }, 100);\n\n handleResize();\n\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n\n const
|
|
1
|
+
{"version":3,"sources":["../../src/core/TabMenu.tsx"],"sourcesContent":["import React, { ReactNode, useEffect } from \"react\";\nimport * as Tabs from \"@radix-ui/react-tabs\";\nimport { throttle } from \"es-toolkit/compat\";\nimport cn from \"./utils/cn\";\n\ntype TabTriggerContent =\n | string\n | { label: string; disabled?: boolean }\n | ReactNode;\n\n/**\n * Props for the TabMenu component.\n */\n\nexport type TabMenuProps = {\n /**\n * An array of tabs, which can be either a string or an object with a label and an optional disabled state.\n */\n tabs: TabTriggerContent[];\n\n /**\n * An optional array of React nodes representing the content for each tab.\n */\n contents?: ReactNode[];\n\n /**\n * An optional callback function that is called when a tab is clicked, receiving the index of the clicked tab.\n */\n tabOnClick?: (index: number) => void;\n\n /**\n * An optional class name to apply to each tab.\n */\n tabClassName?: string;\n\n /**\n * An optional class name to apply to the Tabs.Root element.\n */\n rootClassName?: string;\n\n /**\n * An optional class name to apply to the Tabs.Content element.\n */\n contentClassName?: string;\n\n /**\n * Optional configuration options for the TabMenu.\n */\n options?: {\n /**\n * The index of the tab that should be selected by default.\n */\n defaultTabIndex?: number;\n\n /**\n * Whether to show an underline below the selected tab.\n */\n underline?: boolean;\n\n /**\n * Whether to animate the transition between tabs.\n */\n animated?: boolean;\n\n /**\n * Whether the tab width should be flexible.\n */\n flexibleTabWidth?: boolean;\n\n /**\n * Whether the tab height should be flexible.\n */\n flexibleTabHeight?: boolean;\n };\n};\n\nconst DEFAULT_TAILWIND_ANIMATION_DURATION = 150;\n\nconst TabMenu: React.FC<TabMenuProps> = ({\n tabs = [],\n contents = [],\n tabOnClick,\n tabClassName,\n rootClassName,\n contentClassName,\n options,\n}) => {\n const {\n defaultTabIndex = 0,\n underline = true,\n animated: animatedOption = true,\n flexibleTabWidth = false,\n flexibleTabHeight = false,\n } = options ?? {};\n\n const listRef = React.useRef<HTMLDivElement>(null);\n const [animated, setAnimated] = React.useState(false);\n const [highlight, setHighlight] = React.useState({ offset: 0, width: 0 });\n\n useEffect(() => {\n if (animatedOption && highlight.width > 0) {\n setTimeout(() => {\n setAnimated(true);\n }, DEFAULT_TAILWIND_ANIMATION_DURATION);\n }\n }, [animatedOption, highlight.width]);\n\n const updateHighlightDimensions = (element: HTMLButtonElement) => {\n const { left: parentLeft } = listRef.current?.getBoundingClientRect() ?? {};\n const { left, width } = element.getBoundingClientRect() ?? {};\n\n setHighlight({\n offset: (left ?? 0) - (parentLeft ?? 0),\n width: width ?? 0,\n });\n };\n\n useEffect(() => {\n const handleResize = throttle(() => {\n const activeTabElement =\n listRef.current?.querySelector<HTMLButtonElement>(\n `[data-state=\"active\"]`,\n );\n\n if (activeTabElement) {\n updateHighlightDimensions(activeTabElement);\n }\n }, 100);\n\n handleResize();\n\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n\n const handleTabClick = (\n event: React.MouseEvent<HTMLButtonElement>,\n index: number,\n ) => {\n tabOnClick?.(index);\n updateHighlightDimensions(event.currentTarget as HTMLButtonElement);\n };\n\n const tabTriggerContent = (tab: TabTriggerContent) => {\n if (!tab) {\n return null;\n }\n\n if (React.isValidElement(tab) || typeof tab === \"string\") {\n return tab;\n }\n\n if (typeof tab === \"object\" && \"label\" in tab) {\n return tab.label;\n }\n\n return null;\n };\n\n return (\n <Tabs.Root\n defaultValue={`tab-${defaultTabIndex}`}\n className={cn({ \"h-full\": flexibleTabHeight }, rootClassName)}\n >\n <Tabs.List\n ref={listRef}\n className={cn(\n \"relative\",\n {\n \"flex border-b border-neutral-300 dark:border-neutral-1000\":\n underline,\n },\n { \"h-full\": flexibleTabHeight },\n )}\n >\n {tabs.map(\n (tab, index) =>\n tab && (\n <Tabs.Trigger\n key={`tab-${index}`}\n className={cn(\n \"lg:px-6 md:px-5 px-4 py-4 ui-text-label1 font-bold data-[state=active]:text-neutral-1300 text-neutral-1000 dark:data-[state=active]:text-neutral-000 dark:text-neutral-300 focus:outline-none focus-visible:outline-gui-focus transition-colors hover:text-neutral-1300 dark:hover:text-neutral-000 active:text-neutral-900 dark:active:text-neutral-400 disabled:text-gui-unavailable dark:disabled:text-gui-unavailable-dark disabled:cursor-not-allowed\",\n { \"flex-1\": flexibleTabWidth },\n { \"h-full\": flexibleTabHeight },\n tabClassName,\n )}\n value={`tab-${index}`}\n onClick={(event) => handleTabClick(event, index)}\n disabled={\n typeof tab === \"object\" && \"disabled\" in tab\n ? tab.disabled\n : false\n }\n >\n {tabTriggerContent(tab)}\n </Tabs.Trigger>\n ),\n )}\n <div\n className={cn(\n \"absolute bottom-0 bg-neutral-1300 dark:bg-neutral-000 h-[0.1875rem] w-6\",\n { \"transition-[transform,width]\": animated },\n )}\n style={{\n transform: `translateX(${highlight.offset}px)`,\n width: `${highlight.width}px`,\n }}\n ></div>\n </Tabs.List>\n {contents.map((content, index) => (\n <Tabs.Content\n key={`tab-${index}`}\n value={`tab-${index}`}\n className={contentClassName}\n >\n {content}\n </Tabs.Content>\n ))}\n </Tabs.Root>\n );\n};\n\nexport default TabMenu;\n"],"names":["React","useEffect","Tabs","throttle","cn","DEFAULT_TAILWIND_ANIMATION_DURATION","TabMenu","tabs","contents","tabOnClick","tabClassName","rootClassName","contentClassName","options","defaultTabIndex","underline","animated","animatedOption","flexibleTabWidth","flexibleTabHeight","listRef","useRef","setAnimated","useState","highlight","setHighlight","offset","width","setTimeout","updateHighlightDimensions","element","left","parentLeft","current","getBoundingClientRect","handleResize","activeTabElement","querySelector","window","addEventListener","removeEventListener","handleTabClick","event","index","currentTarget","tabTriggerContent","tab","isValidElement","label","Root","defaultValue","className","List","ref","map","Trigger","key","value","onClick","disabled","div","style","transform","content","Content"],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -321,37 +321,28 @@ type ApiKeySelectorProps = {
|
|
|
321
321
|
selectedApiKey: string;
|
|
322
322
|
onApiKeyChange: (apiKey: string) => void;
|
|
323
323
|
};
|
|
324
|
-
const ApiKeySelector: {
|
|
325
|
-
({ apiKeys, selectedApiKey, onApiKeyChange, }: ApiKeySelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
326
|
-
displayName: string;
|
|
327
|
-
};
|
|
324
|
+
const ApiKeySelector: ({ apiKeys, selectedApiKey, onApiKeyChange, }: ApiKeySelectorProps) => import("react/jsx-runtime").JSX.Element;
|
|
328
325
|
export default ApiKeySelector;
|
|
329
326
|
//# sourceMappingURL=ApiKeySelector.d.ts.map
|
|
330
327
|
}
|
|
331
328
|
|
|
332
329
|
declare module '@ably/ui/core/CodeSnippet/CopyButton' {
|
|
333
|
-
import React from "react";
|
|
334
330
|
type CopyButtonProps = {
|
|
335
331
|
onCopy: () => void;
|
|
336
|
-
isCopied: boolean;
|
|
337
332
|
tooltip?: string;
|
|
338
333
|
};
|
|
339
|
-
|
|
340
|
-
* A reusable copy button component with tooltip and copied indicator
|
|
341
|
-
*/
|
|
342
|
-
const CopyButton: React.MemoExoticComponent<({ onCopy, isCopied, tooltip }: CopyButtonProps) => import("react/jsx-runtime").JSX.Element>;
|
|
334
|
+
const CopyButton: ({ onCopy, tooltip }: CopyButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
343
335
|
export default CopyButton;
|
|
344
336
|
//# sourceMappingURL=CopyButton.d.ts.map
|
|
345
337
|
}
|
|
346
338
|
|
|
347
339
|
declare module '@ably/ui/core/CodeSnippet/LanguageSelector' {
|
|
348
|
-
import React from "react";
|
|
349
340
|
type LanguageSelectorProps = {
|
|
350
341
|
languages: string[];
|
|
351
342
|
activeLanguage: string;
|
|
352
343
|
onLanguageChange: (language: string) => void;
|
|
353
344
|
};
|
|
354
|
-
const LanguageSelector:
|
|
345
|
+
const LanguageSelector: ({ languages, activeLanguage, onLanguageChange, }: LanguageSelectorProps) => import("react/jsx-runtime").JSX.Element;
|
|
355
346
|
export default LanguageSelector;
|
|
356
347
|
//# sourceMappingURL=LanguageSelector.d.ts.map
|
|
357
348
|
}
|
|
@@ -365,29 +356,29 @@ type PlainCodeViewProps = {
|
|
|
365
356
|
icon: IconName | null;
|
|
366
357
|
className?: string;
|
|
367
358
|
};
|
|
368
|
-
const
|
|
369
|
-
export default
|
|
359
|
+
const PlainCodeView: React.FC<PlainCodeViewProps>;
|
|
360
|
+
export default PlainCodeView;
|
|
370
361
|
//# sourceMappingURL=PlainCodeView.d.ts.map
|
|
371
362
|
}
|
|
372
363
|
|
|
373
364
|
declare module '@ably/ui/core/CodeSnippet/TooltipButton' {
|
|
374
365
|
import React from "react";
|
|
366
|
+
import { SegmentedControlSize } from ".@ably/ui/core/SegmentedControl";
|
|
375
367
|
import { IconName } from ".@ably/ui/core/Icon/types";
|
|
368
|
+
import type { TooltipProps } from "@radix-ui/react-tooltip";
|
|
376
369
|
type TooltipButtonProps = {
|
|
377
|
-
tooltip: string;
|
|
370
|
+
tooltip: string | React.ReactNode;
|
|
378
371
|
active?: boolean;
|
|
379
372
|
onClick: () => void;
|
|
380
373
|
icon?: IconName;
|
|
381
374
|
className?: string;
|
|
382
375
|
children?: React.ReactNode;
|
|
383
376
|
variant?: "segmented" | "icon-button";
|
|
384
|
-
size?:
|
|
377
|
+
size?: SegmentedControlSize;
|
|
385
378
|
alwaysShowLabel?: boolean;
|
|
379
|
+
tooltipRootProps?: TooltipProps;
|
|
386
380
|
};
|
|
387
|
-
|
|
388
|
-
* A unified tooltip button component that can render either a segmented control or an icon button
|
|
389
|
-
*/
|
|
390
|
-
const TooltipButton: React.MemoExoticComponent<({ tooltip, active, onClick, icon, className, children, variant, size, alwaysShowLabel, }: TooltipButtonProps) => import("react/jsx-runtime").JSX.Element>;
|
|
381
|
+
const TooltipButton: ({ tooltip, active, onClick, icon, className, children, variant, size, alwaysShowLabel, tooltipRootProps, }: TooltipButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
391
382
|
export default TooltipButton;
|
|
392
383
|
//# sourceMappingURL=TooltipButton.d.ts.map
|
|
393
384
|
}
|
|
@@ -601,7 +592,7 @@ type LinkProps = {
|
|
|
601
592
|
const DropdownMenu: {
|
|
602
593
|
({ children }: DropdownMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
603
594
|
Trigger: ({ children, triggerClassNames, description, }: TriggerProps) => import("react/jsx-runtime").JSX.Element;
|
|
604
|
-
Content: ({ children, anchorPosition, contentClassNames, }: ContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
595
|
+
Content: ({ children, anchorPosition, contentClassNames, }: ContentProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
605
596
|
Link: ({ url, title, subtitle, iconName, children }: LinkProps) => import("react/jsx-runtime").JSX.Element;
|
|
606
597
|
};
|
|
607
598
|
export default DropdownMenu;
|
|
@@ -6244,24 +6235,6 @@ export function registerDefaultLanguages(register: any): void;
|
|
|
6244
6235
|
//# sourceMappingURL=syntax-highlighter.d.ts.map
|
|
6245
6236
|
}
|
|
6246
6237
|
|
|
6247
|
-
declare module '@ably/ui/core/utils/useCopyToClipboard' {
|
|
6248
|
-
interface CopyToClipboardState {
|
|
6249
|
-
isCopied: boolean;
|
|
6250
|
-
error: Error | null;
|
|
6251
|
-
}
|
|
6252
|
-
interface CopyToClipboardReturn extends CopyToClipboardState {
|
|
6253
|
-
copy: (text: string) => Promise<boolean>;
|
|
6254
|
-
}
|
|
6255
|
-
/**
|
|
6256
|
-
* A hook that provides copy-to-clipboard functionality with state management
|
|
6257
|
-
* @param copiedTimeout - How long to show the copied state in ms before resetting
|
|
6258
|
-
* @returns Object with isCopied state, any error, and copy function
|
|
6259
|
-
*/
|
|
6260
|
-
function useCopyToClipboard(copiedTimeout?: number): CopyToClipboardReturn;
|
|
6261
|
-
export default useCopyToClipboard;
|
|
6262
|
-
//# sourceMappingURL=useCopyToClipboard.d.ts.map
|
|
6263
|
-
}
|
|
6264
|
-
|
|
6265
6238
|
declare module '@ably/ui/reset/scripts' {
|
|
6266
6239
|
export {};
|
|
6267
6240
|
//# sourceMappingURL=scripts.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ably/ui",
|
|
3
|
-
"version": "17.9.
|
|
3
|
+
"version": "17.9.1-dev.f8cf1684",
|
|
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",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"eslint-config-prettier": "^10.1.8",
|
|
45
45
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
46
46
|
"eslint-plugin-react": "^7.35.0",
|
|
47
|
-
"eslint-plugin-react-hooks": "^
|
|
47
|
+
"eslint-plugin-react-hooks": "^7.0.0",
|
|
48
48
|
"eslint-plugin-react-perf": "^3.3.3",
|
|
49
49
|
"eslint-plugin-storybook": "^9.1.4",
|
|
50
50
|
"heroicons": "^2.2.0",
|
|
@@ -68,7 +68,6 @@
|
|
|
68
68
|
"@heroicons/react": "^2.2.0",
|
|
69
69
|
"@radix-ui/react-accordion": "^1.2.1",
|
|
70
70
|
"@radix-ui/react-collapsible": "^1.1.12",
|
|
71
|
-
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
72
71
|
"@radix-ui/react-navigation-menu": "^1.2.4",
|
|
73
72
|
"@radix-ui/react-select": "^2.2.2",
|
|
74
73
|
"@radix-ui/react-switch": "^1.1.1",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{useState,useCallback}from"react";function useCopyToClipboard(copiedTimeout=2e3){const[state,setState]=useState({isCopied:false,error:null});const copy=useCallback(async text=>{try{await navigator.clipboard.writeText(text);setState({isCopied:true,error:null});setTimeout(()=>{setState(prev=>({...prev,isCopied:false}))},copiedTimeout);return true}catch(error){setState({isCopied:false,error:error instanceof Error?error:new Error(String(error))});return false}},[copiedTimeout]);return{...state,copy}}export default useCopyToClipboard;
|
|
2
|
-
//# sourceMappingURL=useCopyToClipboard.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/utils/useCopyToClipboard.ts"],"sourcesContent":["import { useState, useCallback } from \"react\";\n\ninterface CopyToClipboardState {\n isCopied: boolean;\n error: Error | null;\n}\n\ninterface CopyToClipboardReturn extends CopyToClipboardState {\n copy: (text: string) => Promise<boolean>;\n}\n\n/**\n * A hook that provides copy-to-clipboard functionality with state management\n * @param copiedTimeout - How long to show the copied state in ms before resetting\n * @returns Object with isCopied state, any error, and copy function\n */\nfunction useCopyToClipboard(copiedTimeout = 2000): CopyToClipboardReturn {\n const [state, setState] = useState<CopyToClipboardState>({\n isCopied: false,\n error: null,\n });\n\n const copy = useCallback(\n async (text: string): Promise<boolean> => {\n try {\n await navigator.clipboard.writeText(text);\n setState({ isCopied: true, error: null });\n\n // Reset the copied state after timeout\n setTimeout(() => {\n setState((prev) => ({ ...prev, isCopied: false }));\n }, copiedTimeout);\n\n return true;\n } catch (error) {\n setState({\n isCopied: false,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n return false;\n }\n },\n [copiedTimeout],\n );\n\n return { ...state, copy };\n}\n\nexport default useCopyToClipboard;\n"],"names":["useState","useCallback","useCopyToClipboard","copiedTimeout","state","setState","isCopied","error","copy","text","navigator","clipboard","writeText","setTimeout","prev","Error","String"],"mappings":"AAAA,OAASA,QAAQ,CAAEC,WAAW,KAAQ,OAAQ,CAgB9C,SAASC,mBAAmBC,cAAgB,GAAI,EAC9C,KAAM,CAACC,MAAOC,SAAS,CAAGL,SAA+B,CACvDM,SAAU,MACVC,MAAO,IACT,GAEA,MAAMC,KAAOP,YACX,MAAOQ,OACL,GAAI,CACF,MAAMC,UAAUC,SAAS,CAACC,SAAS,CAACH,MACpCJ,SAAS,CAAEC,SAAU,KAAMC,MAAO,IAAK,GAGvCM,WAAW,KACTR,SAAS,AAACS,MAAU,CAAA,CAAE,GAAGA,IAAI,CAAER,SAAU,KAAM,CAAA,EACjD,EAAGH,eAEH,OAAO,IACT,CAAE,MAAOI,MAAO,CACdF,SAAS,CACPC,SAAU,MACVC,MAAOA,iBAAiBQ,MAAQR,MAAQ,IAAIQ,MAAMC,OAAOT,OAC3D,GACA,OAAO,KACT,CACF,EACA,CAACJ,cAAc,EAGjB,MAAO,CAAE,GAAGC,KAAK,CAAEI,IAAK,CAC1B,CAEA,eAAeN,kBAAmB"}
|