@ably/ui 17.5.8-dev.cb861d36 → 17.6.0

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/README.md CHANGED
@@ -102,31 +102,18 @@ import Meganav from "@ably/ui/core/Meganav";
102
102
 
103
103
  ### Icons
104
104
 
105
- We have access to two sets of icons via the `Icon` component, custom local assets hosted in the repo itself, and the third-party Heroicons library.
105
+ Icons are available in two formats to support different application types:
106
106
 
107
- #### Local Custom Icons
107
+ 1. **React Component Imports** (recommended for React apps)
108
+ 2. **SVG Spritesheets** (fallback for non-React apps)
108
109
 
109
- Putting SVG files inside a `src/core/icons` folder will:
110
-
111
- 1. Add them to a per-group sprites file (e.g., `core/sprites-gui.svg`) for backward compatibility
112
- 2. Generate React components that can be imported dynamically
113
-
114
- The sprites file can be loaded with the `loadSprites` helper available in the `core` module or included in the page directly.
110
+ We provide access to both custom local assets hosted in the repo and the third-party [Heroicons](https://heroicons.com/) library.
115
111
 
116
- #### Heroicons Integration
112
+ #### For React Applications (Recommended)
117
113
 
118
- The system automatically falls back to [Heroicons](https://heroicons.com/) when a local icon isn't found, using this naming convention:
114
+ **Using the Icon React Component**
119
115
 
120
- - `icon-gui-{heroicon-name}-{variant}`
121
-
122
- Where `variant` can be:
123
-
124
- - `outline` → 24px outline icons
125
- - `solid` → 24px solid icons
126
- - `mini` → 20px solid icons
127
- - `micro` → 16px solid icons
128
-
129
- #### Usage with the Icon React Component
116
+ The `Icon` component is the preferred method for React applications, providing automatic fallback and consistent sizing:
130
117
 
131
118
  ```tsx
132
119
  // Local custom icon
@@ -139,7 +126,17 @@ Where `variant` can be:
139
126
  <Icon name="icon-gui-chevron-down" variant="solid" size="1.5rem" />
140
127
  ```
141
128
 
142
- #### Usage without a component (sprites method)
129
+ **How the React Component Works**
130
+
131
+ 1. **First**: Attempts to load a local React component generated from your custom SVGs
132
+ 2. **Fallback**: If no local component exists, dynamically imports the corresponding heroicon
133
+ 3. **Graceful degradation**: If neither exists, returns null (no icon displayed)
134
+
135
+ #### For Non-React Applications
136
+
137
+ **Using SVG Spritesheets**
138
+
139
+ For applications that don't use React, icons are available as SVG sprites that can be referenced directly:
143
140
 
144
141
  ```html
145
142
  <!-- The width and height are required for correct sizing. The actual color class might depend on the svg and whether it uses strokes, fills etc. Note as well xlink:href, which is xlinkHref in react. -->
@@ -148,7 +145,7 @@ Where `variant` can be:
148
145
  </svg>
149
146
  ```
150
147
 
151
- Usage without a component, in React, with hover states. Note the [group](https://tailwindcss.com/docs/hover-focus-and-other-states#group-hover) class:
148
+ Even in React applications, you can use the sprite method for advanced use cases like hover states with the [group](https://tailwindcss.com/docs/hover-focus-and-other-states#group-hover) class:
152
149
 
153
150
  ```tsx
154
151
  <a
@@ -162,11 +159,29 @@ Usage without a component, in React, with hover states. Note the [group](https:/
162
159
  </a>
163
160
  ```
164
161
 
165
- #### How the Fallback System Works
162
+ The sprites file can be loaded with the `loadSprites` helper available in the `core` module or included in the page directly.
166
163
 
167
- 1. **First**: Attempts to load a local React component generated from your custom SVGs
168
- 2. **Fallback**: If no local component exists, dynamically imports the corresponding heroicon
169
- 3. **Graceful degradation**: If neither exists, returns null (no icon displayed)
164
+ #### Icon Sources
165
+
166
+ **Local Custom Icons**
167
+
168
+ Putting SVG files inside a `src/core/icons` folder will:
169
+
170
+ 1. Generate React components that can be imported dynamically
171
+ 2. Add them to a per-group sprites file (e.g., `core/sprites-gui.svg`) for non-React usage
172
+
173
+ **Heroicons Integration**
174
+
175
+ The system automatically falls back to [Heroicons](https://heroicons.com/) when a local icon isn't found, using this naming convention:
176
+
177
+ - `icon-gui-{heroicon-name}-{variant}`
178
+
179
+ Where `variant` can be:
180
+
181
+ - `outline` → 24px outline icons
182
+ - `solid` → 24px solid icons
183
+ - `mini` → 20px solid icons
184
+ - `micro` → 16px solid icons
170
185
 
171
186
  This hybrid approach allows you to use custom brand icons while having access to the entire heroicons library as a fallback.
172
187
 
@@ -1,2 +1,2 @@
1
- import React,{Fragment,useEffect,useRef,useState}from"react";import throttle from"lodash.throttle";import Icon from"../Icon";import FeaturedLink from"../FeaturedLink";import LinkButton from"../LinkButton";import Tooltip from"../Tooltip";import cn from"../utils/cn";const PricingCards=({data,delimiter})=>{const descriptionsRef=useRef([]);const[descriptionHeight,setDescriptionHeight]=useState(0);const determineMaxDescriptionHeight=throttle(()=>{if(descriptionsRef.current.length){setDescriptionHeight(Math.max(...descriptionsRef.current.map(description=>description?.getBoundingClientRect().height??0)))}},100);useEffect(()=>{determineMaxDescriptionHeight();window.addEventListener("resize",determineMaxDescriptionHeight);return()=>{window.removeEventListener("resize",determineMaxDescriptionHeight);determineMaxDescriptionHeight.cancel()}},[]);const delimiterColumn=index=>delimiter&&index%2===1?React.createElement("div",{className:cn("flex items-center justify-center w-full @[920px]:w-5",{"m-2":delimiter!=="blank"})},delimiter!=="blank"?React.createElement(Icon,{name:delimiter,size:"20px",additionalCSS:"text-neutral-800 dark: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"};const borderClasses=color=>{const classes={neutral:{border:"border-neutral-200 dark:border-neutral-1100",bg:"bg-neutral-200 dark:bg-neutral-1100"},blue:{border:"border-blue-400 dark:border-blue-600",bg:"bg-blue-400 dark:bg-blue-600"},orange:{border:"border-orange-600 dark:border-orange-600",bg:"bg-orange-600 dark:bg-orange-600"}};if(color&&classes[color]){return classes[color]}};return React.createElement("div",{className:"@container flex justify-center","data-testid":delimiter?"delimited-pricing-card-group":"pricing-card-group"},React.createElement("div",{className:cn("gap-2",delimiter?gridRules.delimited:gridRules.nonDelimited)},data.map(({title,description,price,cta,sections,border},index)=>React.createElement(Fragment,{key:title.content},delimiterColumn(index),React.createElement("div",{className:cn("relative border flex-1 px-6 py-6 flex flex-col gap-6 rounded-2xl group min-w-[17rem] backdrop-blur h-[32rem]",borderClasses(border?.color)?.border??"border-neutral-200 dark:border-neutral-1100",border?.style,{"@[520px]:flex-row @[920px]:flex-col":delimiter}),"data-testid":delimiter?"delimited-pricing-card":"pricing-card"},border?React.createElement("div",{className:cn("flex items-center absolute z-10 -top-3 self-center font-semibold uppercase text-neutral-000 font-sans h-6 text-[11px] px-2.5 py-0.5 rounded-2xl select-none tracking-widest",borderClasses(border?.color)?.border,borderClasses(border?.color)?.bg)},border.text):null,React.createElement("div",{className:cn("absolute z-0 top-0 left-0 w-full h-full rounded-2xl bg-neutral-100 dark:bg-neutral-1200",{"group-hover:bg-neutral-100 dark:group-hover:bg-neutral-1200 group-hover:opacity-100":!delimiter})}),React.createElement("div",{className:cn(`relative z-10 flex flex-col gap-4`,{"@[520px]:flex-1 @[920px]:flex-none":delimiter})},React.createElement("div",null,React.createElement("div",{className:"flex items-center mb-1"},React.createElement("p",{className:cn(title.className,title.color)},title.content),title.tooltip?React.createElement(Tooltip,{interactive:typeof title.tooltip!=="string",iconSize:"1.25rem"},title.tooltip):null),React.createElement("p",{className:cn("ui-text-h1 text-h1-xl h-5 block opacity-100 visible group-hover:opacity-0 group-hover:invisible group-active:opacity-0 group-active:invisible","transition-all duration-300 ease-in-out group-hover:-mt-8 group-active:-mt-8 touch-manipulation",description.className,description.color),style:{height:descriptionHeight}},React.createElement("span",{ref:el=>descriptionsRef.current[index]=el},description.content))),React.createElement("div",{className:cn("flex items-end gap-2",{"@[520px]:flex-col @[520px]:items-start @[920px]:flex-row @[920px]:items-end":delimiter})},React.createElement("p",{className:"ui-text-h1 text-h1-xl font-medium tracking-tight leading-none text-neutral-1300 dark:text-neutral-000"},price.amount),React.createElement("div",{className:"ui-text-p3 text-neutral-1300 dark:text-neutral-000"},price.content)),cta?React.createElement("div",{className:"group"},React.createElement(LinkButton,{className:cn("w-full",cta.className),variant:cta.url==="/contact"?"priority":"primary",href:cta.url,onClick:cta.onClick,disabled:cta.disabled,rightIcon:"icon-gui-arrow-right-outline",iconColor:cta.iconColor},cta.text)):delimiter?null:React.createElement("div",{className:"flex items-center justify-center h-12 w-full"},React.createElement("hr",{className:"border-neutral-500 dark:border-neutral-800 w-16"}))),React.createElement("div",{className:"flex flex-col gap-4 relative z-10"},sections.map(({title,items,listItemColors,cta})=>React.createElement("div",{key:title,className:"flex flex-col gap-2"},React.createElement("p",{className:"text-neutral-700 dark:text-neutral-600 font-mono uppercase text-overline2 font-medium tracking-[0.12em] h-4"},title),React.createElement("div",{className:cn({"flex flex-col":!delimiter})},items.map((item,index)=>Array.isArray(item)?React.createElement("div",{key:item[0],className:cn("flex justify-between gap-4 px-2 -mx-2",index===0?"py-2":"py-1",index>0&&index%2===0?"bg-blue-100 dark:bg-blue-900 rounded-md":"")},item.map((subItem,subIndex)=>React.createElement("span",{key:subItem,className:cn("ui-text-p3",index===0?"font-bold":"font-medium","text-neutral-1000 dark:text-neutral-300 leading-[1.4rem]",subIndex%2===1?"text-right":"")},subItem))):React.createElement("div",{key:item,className:"flex items-start"},listItemColors?React.createElement(Icon,{name:"icon-gui-check-circled-fill",color:listItemColors.background,secondaryColor:listItemColors.foreground,size:"16px",additionalCSS:"mt-1"}):null,React.createElement("div",{className:cn(`flex-1 font-medium text-neutral-1000 dark:text-neutral-300 ui-text-p3`)},item)))),cta?React.createElement("div",{className:"relative items-center opacity-0 invisible h-10 group-hover:opacity-100 group-hover:visible group-active:opacity-100 group-active:visible transition-all duration-300 ease-in-out group-hover:delay-200 group-active:delay-300 touch-manipulation"},React.createElement(FeaturedLink,{url:cta.url,additionalCSS:"absolute font-medium ui-text-p3 dark:text-neutral-500 dark:hover:text-neutral-000 cursor-pointer",onClick:cta.onClick,iconColor:listItemColors?.foreground},cta.text)):null)))),delimiterColumn(index)))))};export default PricingCards;
1
+ import React,{Fragment,useEffect,useRef,useState}from"react";import throttle from"lodash.throttle";import Icon from"../Icon";import LinkButton from"../LinkButton";import Tooltip from"../Tooltip";import cn from"../utils/cn";const PricingCards=({data,delimiter})=>{const descriptionsRef=useRef([]);const[descriptionHeight,setDescriptionHeight]=useState(0);const determineMaxDescriptionHeight=throttle(()=>{if(descriptionsRef.current.length){setDescriptionHeight(Math.max(...descriptionsRef.current.map(description=>description?.getBoundingClientRect().height??0)))}},100);useEffect(()=>{determineMaxDescriptionHeight();window.addEventListener("resize",determineMaxDescriptionHeight);return()=>{window.removeEventListener("resize",determineMaxDescriptionHeight);determineMaxDescriptionHeight.cancel()}},[]);const delimiterColumn=index=>delimiter&&index%2===1?React.createElement("div",{className:cn("flex items-center justify-center w-full @[920px]:w-5",{"m-2":delimiter!=="blank"})},delimiter!=="blank"?React.createElement(Icon,{name:delimiter,size:"20px",additionalCSS:"text-neutral-800 dark: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"};const borderClasses=color=>{const classes={neutral:{border:"border-neutral-600 dark:border-neutral-700",bg:"bg-neutral-600 dark:bg-neutral-700"},blue:{border:"border-blue-400 dark:border-blue-600",bg:"bg-blue-400 dark:bg-blue-600"},orange:{border:"border-orange-600 dark:border-orange-600",bg:"bg-orange-600 dark:bg-orange-600"}};if(color&&classes[color]){return classes[color]}};return React.createElement("div",{className:"@container flex justify-center","data-testid":delimiter?"delimited-pricing-card-group":"pricing-card-group"},React.createElement("div",{className:cn("gap-2",delimiter?gridRules.delimited:gridRules.nonDelimited)},data.map(({title,description,price,cta,sections,border,bottomCta},index)=>React.createElement(Fragment,{key:title.content},delimiterColumn(index),React.createElement("div",{className:cn("relative border flex-1 px-6 pt-6 pb-4 flex flex-col gap-6 rounded-2xl group min-w-[17rem] backdrop-blur bg-neutral-100 dark:bg-neutral-1200",borderClasses(border?.color)?.border??"border-neutral-200 dark:border-neutral-1100",border?.style,{"@[520px]:flex-row @[920px]:flex-col":delimiter}),"data-testid":delimiter?"delimited-pricing-card":"pricing-card"},border?React.createElement("div",{className:cn("flex items-center absolute z-10 -top-3 self-center font-semibold uppercase text-neutral-000 font-sans h-6 text-[11px] px-2.5 py-0.5 rounded-2xl select-none tracking-widest",borderClasses(border?.color)?.border,borderClasses(border?.color)?.bg)},border.text):null,React.createElement("div",{className:cn(`relative z-10 flex flex-col gap-4`,{"@[520px]:flex-1 @[920px]:flex-none":delimiter})},React.createElement("div",null,React.createElement("div",{className:"flex items-center mb-1"},React.createElement("p",{className:cn(title.className,title.color)},title.content),title.tooltip?React.createElement(Tooltip,{interactive:typeof title.tooltip!=="string",iconSize:"1.25rem"},title.tooltip):null),React.createElement("p",{className:cn("ui-text-h1 text-h1-xl h-5 block",description.className,description.color),style:{height:descriptionHeight}},React.createElement("span",{ref:el=>descriptionsRef.current[index]=el},description.content))),React.createElement("div",{className:cn("flex items-end gap-2",{"@[520px]:flex-col @[520px]:items-start @[920px]:flex-row @[920px]:items-end":delimiter})},React.createElement("p",{className:"ui-text-h1 text-h1-xl font-medium tracking-tight leading-none text-neutral-1300 dark:text-neutral-000"},price.amount),React.createElement("div",{className:"ui-text-p3 text-neutral-1300 dark:text-neutral-000"},price.content)),cta?React.createElement("div",{className:"group"},React.createElement(LinkButton,{className:cn("w-full",cta.className),variant:cta.url==="/contact"?"priority":"primary",href:cta.url,onClick:cta.onClick,disabled:cta.disabled,rightIcon:"icon-gui-arrow-right-outline",iconColor:cta.iconColor},cta.text)):delimiter?null:React.createElement("div",{className:"flex items-center justify-center h-12 w-full"},React.createElement("hr",{className:"border-neutral-500 dark:border-neutral-800 w-16"}))),React.createElement("div",{className:"flex flex-col gap-4 relative z-10 flex-grow"},sections.map(({title,items,listItemColors})=>React.createElement("div",{key:title,className:"flex flex-col gap-3"},React.createElement("p",{className:"text-neutral-700 dark:text-neutral-600 font-mono uppercase text-overline2 font-medium tracking-[0.12em] h-4"},title),React.createElement("div",{className:cn({"flex flex-col":!delimiter})},items.map((item,index)=>Array.isArray(item)?React.createElement("div",{key:item[0],className:cn("flex justify-between gap-4 px-2 -mx-2",index===0?"py-2":"py-1",index>0&&index%2===0?"bg-blue-100 dark:bg-blue-900 rounded-md":"")},item.map((subItem,subIndex)=>React.createElement("span",{key:subItem,className:cn("ui-text-p3",index===0?"font-bold":"font-medium","text-neutral-1000 dark:text-neutral-300 leading-[1.4rem]",subIndex%2===1?"text-right":"")},subItem))):React.createElement("div",{key:item,className:"flex items-start gap-2"},listItemColors?React.createElement(Icon,{name:"icon-gui-check-circled-fill",color:listItemColors.background,secondaryColor:listItemColors.foreground,size:"16px",additionalCSS:"mt-1"}):null,React.createElement("div",{className:cn(`flex-1 font-medium text-neutral-1000 dark:text-neutral-300 ui-text-p3`)},item))))))),bottomCta&&React.createElement("div",null,React.createElement("div",{className:"border-t border-neutral-200 dark:border-neutral-1100 -mx-6"}),React.createElement("a",{href:bottomCta.url,className:cn("text-[13px] font-sans font-semibold group/bottom-cta cursor-pointer pt-4 flex items-center","text-neutral-700 dark:text-neutral-600 hover:text-neutral-1300 dark:hover:text-neutral-000 focus:outline-none focus-visible:outline-gui-focus")},bottomCta.text,React.createElement(Icon,{name:"icon-gui-arrow-down-outline",size:"12px",color:bottomCta.iconColor,additionalCSS:cn("align-middle ml-2 relative transition-[bottom] bottom-0 group-hover/bottom-cta:-bottom-0.5")})))),delimiterColumn(index)))))};export default PricingCards;
2
2
  //# sourceMappingURL=PricingCards.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Pricing/PricingCards.tsx"],"sourcesContent":["import React, { Fragment, useEffect, useRef, useState } from \"react\";\nimport throttle from \"lodash.throttle\";\nimport type { PricingDataFeature } from \"./types\";\nimport Icon from \"../Icon\";\nimport FeaturedLink from \"../FeaturedLink\";\nimport LinkButton from \"../LinkButton\";\nimport { IconName } from \"../Icon/types\";\nimport Tooltip from \"../Tooltip\";\nimport cn from \"../utils/cn\";\n\nexport type PricingCardsProps = {\n data: PricingDataFeature[];\n delimiter?: IconName | \"blank\";\n};\n\nconst PricingCards = ({ data, delimiter }: PricingCardsProps) => {\n const descriptionsRef = useRef<(HTMLSpanElement | null)[]>([]);\n const [descriptionHeight, setDescriptionHeight] = useState<number>(0);\n\n const determineMaxDescriptionHeight = throttle(() => {\n if (descriptionsRef.current.length) {\n setDescriptionHeight(\n Math.max(\n ...descriptionsRef.current.map(\n (description) => description?.getBoundingClientRect().height ?? 0,\n ),\n ),\n );\n }\n }, 100);\n\n useEffect(() => {\n determineMaxDescriptionHeight();\n\n window.addEventListener(\"resize\", determineMaxDescriptionHeight);\n\n return () => {\n window.removeEventListener(\"resize\", determineMaxDescriptionHeight);\n determineMaxDescriptionHeight.cancel();\n };\n }, []);\n\n const delimiterColumn = (index: number) =>\n delimiter && index % 2 === 1 ? (\n <div\n className={cn(\"flex items-center justify-center w-full @[920px]:w-5\", {\n \"m-2\": delimiter !== \"blank\",\n })}\n >\n {delimiter !== \"blank\" ? (\n <Icon\n name={delimiter}\n size=\"20px\"\n additionalCSS={\"text-neutral-800 dark:text-neutral-500\"}\n />\n ) : null}\n </div>\n ) : null;\n\n const gridRules = {\n nonDelimited: \"grid @[552px]:grid-cols-2 @[1104px]:grid-cols-4\",\n delimited: \"flex flex-col items-center @[920px]:flex-row\",\n };\n\n const borderClasses = (color?: \"neutral\" | \"blue\" | \"orange\") => {\n const classes: Record<\n string,\n {\n border: string;\n bg: string;\n }\n > = {\n neutral: {\n border: \"border-neutral-200 dark:border-neutral-1100\",\n bg: \"bg-neutral-200 dark:bg-neutral-1100\",\n },\n blue: {\n border: \"border-blue-400 dark:border-blue-600\",\n bg: \"bg-blue-400 dark:bg-blue-600\",\n },\n orange: {\n border: \"border-orange-600 dark:border-orange-600\",\n bg: \"bg-orange-600 dark:bg-orange-600\",\n },\n };\n\n if (color && classes[color]) {\n return classes[color];\n }\n };\n\n return (\n <div\n className=\"@container flex justify-center\"\n data-testid={\n delimiter ? \"delimited-pricing-card-group\" : \"pricing-card-group\"\n }\n >\n <div\n className={cn(\n \"gap-2\",\n delimiter ? gridRules.delimited : gridRules.nonDelimited,\n )}\n >\n {data.map(\n ({ title, description, price, cta, sections, border }, index) => (\n <Fragment key={title.content}>\n {delimiterColumn(index)}\n <div\n className={cn(\n \"relative border flex-1 px-6 py-6 flex flex-col gap-6 rounded-2xl group min-w-[17rem] backdrop-blur h-[32rem]\",\n borderClasses(border?.color)?.border ??\n \"border-neutral-200 dark:border-neutral-1100\",\n border?.style,\n { \"@[520px]:flex-row @[920px]:flex-col\": delimiter },\n )}\n data-testid={\n delimiter ? \"delimited-pricing-card\" : \"pricing-card\"\n }\n >\n {border ? (\n <div\n className={cn(\n \"flex items-center absolute z-10 -top-3 self-center font-semibold uppercase text-neutral-000 font-sans h-6 text-[11px] px-2.5 py-0.5 rounded-2xl select-none tracking-widest\",\n borderClasses(border?.color)?.border,\n borderClasses(border?.color)?.bg,\n )}\n >\n {border.text}\n </div>\n ) : null}\n <div\n className={cn(\n \"absolute z-0 top-0 left-0 w-full h-full rounded-2xl bg-neutral-100 dark:bg-neutral-1200\",\n {\n \"group-hover:bg-neutral-100 dark:group-hover:bg-neutral-1200 group-hover:opacity-100\":\n !delimiter,\n },\n )}\n ></div>\n <div\n className={cn(`relative z-10 flex flex-col gap-4`, {\n \"@[520px]:flex-1 @[920px]:flex-none\": delimiter,\n })}\n >\n <div>\n <div className=\"flex items-center mb-1\">\n <p className={cn(title.className, title.color)}>\n {title.content}\n </p>\n {title.tooltip ? (\n <Tooltip\n interactive={typeof title.tooltip !== \"string\"}\n iconSize=\"1.25rem\"\n >\n {title.tooltip}\n </Tooltip>\n ) : null}\n </div>\n <p\n className={cn(\n \"ui-text-h1 text-h1-xl h-5 block opacity-100 visible group-hover:opacity-0 group-hover:invisible group-active:opacity-0 group-active:invisible\",\n \"transition-all duration-300 ease-in-out group-hover:-mt-8 group-active:-mt-8 touch-manipulation\",\n description.className,\n description.color,\n )}\n style={{ height: descriptionHeight }}\n >\n <span ref={(el) => (descriptionsRef.current[index] = el)}>\n {description.content}\n </span>\n </p>\n </div>\n <div\n className={cn(\"flex items-end gap-2\", {\n \"@[520px]:flex-col @[520px]:items-start @[920px]:flex-row @[920px]:items-end\":\n delimiter,\n })}\n >\n <p className=\"ui-text-h1 text-h1-xl font-medium tracking-tight leading-none text-neutral-1300 dark:text-neutral-000\">\n {price.amount}\n </p>\n <div className=\"ui-text-p3 text-neutral-1300 dark:text-neutral-000\">\n {price.content}\n </div>\n </div>\n {cta ? (\n <div className=\"group\">\n <LinkButton\n className={cn(\"w-full\", cta.className)}\n variant={\n cta.url === \"/contact\" ? \"priority\" : \"primary\"\n }\n href={cta.url}\n onClick={cta.onClick}\n disabled={cta.disabled}\n rightIcon=\"icon-gui-arrow-right-outline\"\n iconColor={cta.iconColor}\n >\n {cta.text}\n </LinkButton>\n </div>\n ) : delimiter ? null : (\n <div className=\"flex items-center justify-center h-12 w-full\">\n <hr className=\"border-neutral-500 dark:border-neutral-800 w-16\" />\n </div>\n )}\n </div>\n <div className=\"flex flex-col gap-4 relative z-10\">\n {sections.map(({ title, items, listItemColors, cta }) => (\n <div key={title} className=\"flex flex-col gap-2\">\n <p className=\"text-neutral-700 dark:text-neutral-600 font-mono uppercase text-overline2 font-medium tracking-[0.12em] h-4\">\n {title}\n </p>\n <div className={cn({ \"flex flex-col\": !delimiter })}>\n {items.map((item, index) =>\n Array.isArray(item) ? (\n <div\n key={item[0]}\n className={cn(\n \"flex justify-between gap-4 px-2 -mx-2\",\n index === 0 ? \"py-2\" : \"py-1\",\n index > 0 && index % 2 === 0\n ? \"bg-blue-100 dark:bg-blue-900 rounded-md\"\n : \"\",\n )}\n >\n {item.map((subItem, subIndex) => (\n <span\n key={subItem}\n className={cn(\n \"ui-text-p3\",\n index === 0 ? \"font-bold\" : \"font-medium\",\n \"text-neutral-1000 dark:text-neutral-300 leading-[1.4rem]\",\n subIndex % 2 === 1 ? \"text-right\" : \"\",\n )}\n >\n {subItem}\n </span>\n ))}\n </div>\n ) : (\n <div key={item} className=\"flex items-start\">\n {listItemColors ? (\n <Icon\n name=\"icon-gui-check-circled-fill\"\n color={listItemColors.background}\n secondaryColor={listItemColors.foreground}\n size=\"16px\"\n additionalCSS=\"mt-1\"\n />\n ) : null}\n <div\n className={cn(\n `flex-1 font-medium text-neutral-1000 dark:text-neutral-300 ui-text-p3`,\n )}\n >\n {item}\n </div>\n </div>\n ),\n )}\n </div>\n {cta ? (\n <div\n className=\"relative items-center opacity-0 invisible h-10\n group-hover:opacity-100 group-hover:visible group-active:opacity-100 group-active:visible\n transition-all duration-300 ease-in-out \n group-hover:delay-200 group-active:delay-300 touch-manipulation\"\n >\n <FeaturedLink\n url={cta.url}\n additionalCSS=\"absolute font-medium ui-text-p3 dark:text-neutral-500 dark:hover:text-neutral-000 cursor-pointer\"\n onClick={cta.onClick}\n iconColor={listItemColors?.foreground}\n >\n {cta.text}\n </FeaturedLink>\n </div>\n ) : null}\n </div>\n ))}\n </div>\n </div>\n {delimiterColumn(index)}\n </Fragment>\n ),\n )}\n </div>\n </div>\n );\n};\n\nexport default PricingCards;\n"],"names":["React","Fragment","useEffect","useRef","useState","throttle","Icon","FeaturedLink","LinkButton","Tooltip","cn","PricingCards","data","delimiter","descriptionsRef","descriptionHeight","setDescriptionHeight","determineMaxDescriptionHeight","current","length","Math","max","map","description","getBoundingClientRect","height","window","addEventListener","removeEventListener","cancel","delimiterColumn","index","div","className","name","size","additionalCSS","gridRules","nonDelimited","delimited","borderClasses","color","classes","neutral","border","bg","blue","orange","data-testid","title","price","cta","sections","key","content","style","text","p","tooltip","interactive","iconSize","span","ref","el","amount","variant","url","href","onClick","disabled","rightIcon","iconColor","hr","items","listItemColors","item","Array","isArray","subItem","subIndex","background","secondaryColor","foreground"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/core/Pricing/PricingCards.tsx"],"sourcesContent":["import React, { Fragment, useEffect, useRef, useState } from \"react\";\nimport throttle from \"lodash.throttle\";\nimport type { PricingDataFeature } from \"./types\";\nimport Icon from \"../Icon\";\nimport LinkButton from \"../LinkButton\";\nimport { IconName } from \"../Icon/types\";\nimport Tooltip from \"../Tooltip\";\nimport cn from \"../utils/cn\";\n\nexport type PricingCardsProps = {\n data: PricingDataFeature[];\n delimiter?: IconName | \"blank\";\n};\n\nconst PricingCards = ({ data, delimiter }: PricingCardsProps) => {\n const descriptionsRef = useRef<(HTMLSpanElement | null)[]>([]);\n const [descriptionHeight, setDescriptionHeight] = useState<number>(0);\n\n const determineMaxDescriptionHeight = throttle(() => {\n if (descriptionsRef.current.length) {\n setDescriptionHeight(\n Math.max(\n ...descriptionsRef.current.map(\n (description) => description?.getBoundingClientRect().height ?? 0,\n ),\n ),\n );\n }\n }, 100);\n\n useEffect(() => {\n determineMaxDescriptionHeight();\n\n window.addEventListener(\"resize\", determineMaxDescriptionHeight);\n\n return () => {\n window.removeEventListener(\"resize\", determineMaxDescriptionHeight);\n determineMaxDescriptionHeight.cancel();\n };\n }, []);\n\n const delimiterColumn = (index: number) =>\n delimiter && index % 2 === 1 ? (\n <div\n className={cn(\"flex items-center justify-center w-full @[920px]:w-5\", {\n \"m-2\": delimiter !== \"blank\",\n })}\n >\n {delimiter !== \"blank\" ? (\n <Icon\n name={delimiter}\n size=\"20px\"\n additionalCSS={\"text-neutral-800 dark:text-neutral-500\"}\n />\n ) : null}\n </div>\n ) : null;\n\n const gridRules = {\n nonDelimited: \"grid @[552px]:grid-cols-2 @[1104px]:grid-cols-4\",\n delimited: \"flex flex-col items-center @[920px]:flex-row\",\n };\n\n const borderClasses = (color?: \"neutral\" | \"blue\" | \"orange\") => {\n const classes: Record<\n string,\n {\n border: string;\n bg: string;\n }\n > = {\n neutral: {\n border: \"border-neutral-600 dark:border-neutral-700\",\n bg: \"bg-neutral-600 dark:bg-neutral-700\",\n },\n blue: {\n border: \"border-blue-400 dark:border-blue-600\",\n bg: \"bg-blue-400 dark:bg-blue-600\",\n },\n orange: {\n border: \"border-orange-600 dark:border-orange-600\",\n bg: \"bg-orange-600 dark:bg-orange-600\",\n },\n };\n\n if (color && classes[color]) {\n return classes[color];\n }\n };\n\n return (\n <div\n className=\"@container flex justify-center\"\n data-testid={\n delimiter ? \"delimited-pricing-card-group\" : \"pricing-card-group\"\n }\n >\n <div\n className={cn(\n \"gap-2\",\n delimiter ? gridRules.delimited : gridRules.nonDelimited,\n )}\n >\n {data.map(\n (\n { title, description, price, cta, sections, border, bottomCta },\n index,\n ) => (\n <Fragment key={title.content}>\n {delimiterColumn(index)}\n <div\n className={cn(\n \"relative border flex-1 px-6 pt-6 pb-4 flex flex-col gap-6 rounded-2xl group min-w-[17rem] backdrop-blur bg-neutral-100 dark:bg-neutral-1200\",\n borderClasses(border?.color)?.border ??\n \"border-neutral-200 dark:border-neutral-1100\",\n border?.style,\n { \"@[520px]:flex-row @[920px]:flex-col\": delimiter },\n )}\n data-testid={\n delimiter ? \"delimited-pricing-card\" : \"pricing-card\"\n }\n >\n {border ? (\n <div\n className={cn(\n \"flex items-center absolute z-10 -top-3 self-center font-semibold uppercase text-neutral-000 font-sans h-6 text-[11px] px-2.5 py-0.5 rounded-2xl select-none tracking-widest\",\n borderClasses(border?.color)?.border,\n borderClasses(border?.color)?.bg,\n )}\n >\n {border.text}\n </div>\n ) : null}\n <div\n className={cn(`relative z-10 flex flex-col gap-4`, {\n \"@[520px]:flex-1 @[920px]:flex-none\": delimiter,\n })}\n >\n <div>\n <div className=\"flex items-center mb-1\">\n <p className={cn(title.className, title.color)}>\n {title.content}\n </p>\n {title.tooltip ? (\n <Tooltip\n interactive={typeof title.tooltip !== \"string\"}\n iconSize=\"1.25rem\"\n >\n {title.tooltip}\n </Tooltip>\n ) : null}\n </div>\n <p\n className={cn(\n \"ui-text-h1 text-h1-xl h-5 block\",\n description.className,\n description.color,\n )}\n style={{ height: descriptionHeight }}\n >\n <span ref={(el) => (descriptionsRef.current[index] = el)}>\n {description.content}\n </span>\n </p>\n </div>\n <div\n className={cn(\"flex items-end gap-2\", {\n \"@[520px]:flex-col @[520px]:items-start @[920px]:flex-row @[920px]:items-end\":\n delimiter,\n })}\n >\n <p className=\"ui-text-h1 text-h1-xl font-medium tracking-tight leading-none text-neutral-1300 dark:text-neutral-000\">\n {price.amount}\n </p>\n <div className=\"ui-text-p3 text-neutral-1300 dark:text-neutral-000\">\n {price.content}\n </div>\n </div>\n {cta ? (\n <div className=\"group\">\n <LinkButton\n className={cn(\"w-full\", cta.className)}\n variant={\n cta.url === \"/contact\" ? \"priority\" : \"primary\"\n }\n href={cta.url}\n onClick={cta.onClick}\n disabled={cta.disabled}\n rightIcon=\"icon-gui-arrow-right-outline\"\n iconColor={cta.iconColor}\n >\n {cta.text}\n </LinkButton>\n </div>\n ) : delimiter ? null : (\n <div className=\"flex items-center justify-center h-12 w-full\">\n <hr className=\"border-neutral-500 dark:border-neutral-800 w-16\" />\n </div>\n )}\n </div>\n <div className=\"flex flex-col gap-4 relative z-10 flex-grow\">\n {sections.map(({ title, items, listItemColors }) => (\n <div key={title} className=\"flex flex-col gap-3\">\n <p className=\"text-neutral-700 dark:text-neutral-600 font-mono uppercase text-overline2 font-medium tracking-[0.12em] h-4\">\n {title}\n </p>\n <div className={cn({ \"flex flex-col\": !delimiter })}>\n {items.map((item, index) =>\n Array.isArray(item) ? (\n <div\n key={item[0]}\n className={cn(\n \"flex justify-between gap-4 px-2 -mx-2\",\n index === 0 ? \"py-2\" : \"py-1\",\n index > 0 && index % 2 === 0\n ? \"bg-blue-100 dark:bg-blue-900 rounded-md\"\n : \"\",\n )}\n >\n {item.map((subItem, subIndex) => (\n <span\n key={subItem}\n className={cn(\n \"ui-text-p3\",\n index === 0 ? \"font-bold\" : \"font-medium\",\n \"text-neutral-1000 dark:text-neutral-300 leading-[1.4rem]\",\n subIndex % 2 === 1 ? \"text-right\" : \"\",\n )}\n >\n {subItem}\n </span>\n ))}\n </div>\n ) : (\n <div key={item} className=\"flex items-start gap-2\">\n {listItemColors ? (\n <Icon\n name=\"icon-gui-check-circled-fill\"\n color={listItemColors.background}\n secondaryColor={listItemColors.foreground}\n size=\"16px\"\n additionalCSS=\"mt-1\"\n />\n ) : null}\n <div\n className={cn(\n `flex-1 font-medium text-neutral-1000 dark:text-neutral-300 ui-text-p3`,\n )}\n >\n {item}\n </div>\n </div>\n ),\n )}\n </div>\n </div>\n ))}\n </div>\n\n {bottomCta && (\n <div>\n <div className=\"border-t border-neutral-200 dark:border-neutral-1100 -mx-6\"></div>\n <a\n href={bottomCta.url}\n className={cn(\n \"text-[13px] font-sans font-semibold group/bottom-cta cursor-pointer pt-4 flex items-center\",\n \"text-neutral-700 dark:text-neutral-600 hover:text-neutral-1300 dark:hover:text-neutral-000 focus:outline-none focus-visible:outline-gui-focus\",\n )}\n >\n {bottomCta.text}\n <Icon\n name=\"icon-gui-arrow-down-outline\"\n size=\"12px\"\n color={bottomCta.iconColor}\n additionalCSS={cn(\n \"align-middle ml-2 relative transition-[bottom] bottom-0 group-hover/bottom-cta:-bottom-0.5\",\n )}\n />\n </a>\n </div>\n )}\n </div>\n {delimiterColumn(index)}\n </Fragment>\n ),\n )}\n </div>\n </div>\n );\n};\n\nexport default PricingCards;\n"],"names":["React","Fragment","useEffect","useRef","useState","throttle","Icon","LinkButton","Tooltip","cn","PricingCards","data","delimiter","descriptionsRef","descriptionHeight","setDescriptionHeight","determineMaxDescriptionHeight","current","length","Math","max","map","description","getBoundingClientRect","height","window","addEventListener","removeEventListener","cancel","delimiterColumn","index","div","className","name","size","additionalCSS","gridRules","nonDelimited","delimited","borderClasses","color","classes","neutral","border","bg","blue","orange","data-testid","title","price","cta","sections","bottomCta","key","content","style","text","p","tooltip","interactive","iconSize","span","ref","el","amount","variant","url","href","onClick","disabled","rightIcon","iconColor","hr","items","listItemColors","item","Array","isArray","subItem","subIndex","background","secondaryColor","foreground","a"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import React from"react";import Tooltip from"../Tooltip";export const planData=[{title:{content:"Free",className:"ui-text-h4 tracking-[-0.002rem]",color:"text-neutral-1300 dark:text-neutral-000"},description:{content:"Build a proof of concept.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$0"},cta:{text:"Start for free",url:"/sign-up",iconColor:"text-neutral-600 dark:text-neutral-700"},sections:[{title:"Capacity",items:["200 concurrent connections","500 messages / second","6M messages / month"]},{title:"Includes",items:["Build with any Ably product","Community & email support (best effort)","No commitment"],listItemColors:{foreground:"text-neutral-700 dark:text-neutral-600",background:"text-neutral-100 dark:text-neutral-1200"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Standard",className:"ui-text-h4 tracking-[-0.002rem]",color:"text-neutral-1300 dark:text-neutral-000"},description:{content:"Roll-out into production.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$29",content:React.createElement(React.Fragment,null,React.createElement("p",{className:"ui-text-p3 font-medium",style:{color:"currentColor"}},"/ month"),React.createElement("div",{className:"flex -mt-1"},React.createElement("p",{className:"ui-text-p3 font-bold text-gui-blue-default-dark leading-[1.4rem]"},"+ usage"),React.createElement(Tooltip,{interactive:true,iconSize:"1.25rem"},"Usage is billed on top of your plan. You'll be charged monthly based on how many messages, channel minutes, and connection minutes you use. See rates above.")))},cta:{text:"Get started",url:"/users/paid_sign_up?package=standard",iconColor:"text-neutral-600 dark:text-neutral-700"},sections:[{title:"Capacity",items:["10k concurrent channels","10k concurrent connections","2.5k messages / second"]},{title:"Includes",items:["Build with any Ably product","1 day email support SLA","Uptime SLO"],listItemColors:{foreground:"text-neutral-700 dark:text-neutral-600",background:"text-neutral-100 dark:text-neutral-1200"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Pro",className:"ui-text-h4 tracking-[-0.002rem]",color:"text-neutral-1300 dark:text-neutral-000"},description:{content:"Scale business critical workloads.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$399",content:React.createElement(React.Fragment,null,React.createElement("p",{className:"ui-text-p3 font-medium",style:{color:"currentColor"}},"/ month"),React.createElement("div",{className:"flex -mt-1"},React.createElement("p",{className:"ui-text-p3 font-bold text-gui-blue-default-dark leading-[1.4rem]"},"+ usage"),React.createElement(Tooltip,{interactive:true,iconSize:"1.25rem"},"Usage is billed on top of your plan. You'll be charged monthly based on how many messages, channel minutes, and connection minutes you use. See rates above.")))},cta:{text:"Get started",url:"/users/paid_sign_up?package=pro",iconColor:"text-neutral-600 dark:text-neutral-700"},sections:[{title:"Capacity",items:["50k concurrent channels","50k concurrent connections","10k messages / second"]},{title:"Includes",items:["Build with any Ably product","4 hour email support SLA","Datadog (lite)","Uptime SLO"],listItemColors:{foreground:"text-neutral-700 dark:text-neutral-600",background:"text-neutral-100 dark:text-neutral-1200"},cta:{text:"See all features",url:"#pricing-table"}}]},{title:{content:"Enterprise",className:"ui-text-h4 tracking-[-0.002rem]",color:"text-orange-600"},description:{content:"Serious workloads without limits.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"Custom"},cta:{text:"Contact us",url:"/contact"},sections:[{title:"Capacity",items:["Unlimited concurrent channels","Unlimited connections","Unlimited messages / second"]},{title:"Includes",items:["Build with any Ably product","24/7 mission critical support","99.999% uptime SLAs","Committed use discounts","Datadog","CNAME, SSO, & more"],listItemColors:{foreground:"text-orange-700 dark:text-orange-500",background:"text-neutral-100 dark:text-neutral-1200"},cta:{text:"See all features",url:"#pricing-table"}}]}];export const consumptionData=[{title:{content:"Messages",className:"ui-text-h3",color:"text-neutral-1300 dark: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-700 dark:text-neutral-600"},price:{amount:"$2.50",content:"/ 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"]]}],subtext:"As low as $0.50/M with volume discount"},{title:{content:"Channels",className:"ui-text-h3",color:"text-neutral-1300 dark:text-neutral-000",tooltip:React.createElement("p",null,"We charge you for the amount of time a channel is active in our network by the minute. For example, if ten channels are in use for 45 minutes, you will be charged a total of 450 channel minutes.")},description:{content:"Channels are used to route messages from publishers to subscribers. Channels are billed by the minute when actively being used by a connected client.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$1.00",content:"/ 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"]]}],subtext:"As low as $0.20/M with volume discount"},{title:{content:"Connections",className:"ui-text-h3",color:"text-neutral-1300 dark:text-neutral-000",tooltip:React.createElement("p",null,"We charge you for the amount of time devices are connected to our network by the minute. For example, if ten devices are each connected for 45 minutes, you will be charged a total of 450 connection minutes.")},description:{content:"Clients establish and maintain a connection to the Ably service, typically over WebSockets.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$1.00",content:"/ 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"]]}],subtext:"As low as $0.20/M with volume discount"}];
1
+ import React from"react";import Tooltip from"../Tooltip";export const planData=[{title:{content:"Free",className:"ui-text-h4 tracking-[-0.002rem]",color:"text-neutral-1300 dark:text-neutral-000"},description:{content:"Build a proof of concept.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$0"},cta:{text:"Start for free",url:"/sign-up",iconColor:"text-neutral-600 dark:text-neutral-700"},sections:[{title:"Capacity",items:["200 concurrent connections","500 messages / second","6M messages / month"]},{title:"Includes",items:["Build with any Ably product","Community & email support (best effort)","No commitment"],listItemColors:{foreground:"text-neutral-700 dark:text-neutral-600",background:"text-neutral-100 dark:text-neutral-1200"}}],bottomCta:{text:"See all features",url:"#pricing-table"}},{title:{content:"Standard",className:"ui-text-h4 tracking-[-0.002rem]",color:"text-neutral-1300 dark:text-neutral-000"},description:{content:"Roll-out into production.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$29",content:React.createElement(React.Fragment,null,React.createElement("p",{className:"ui-text-p3 font-medium",style:{color:"currentColor"}},"/ month"),React.createElement("div",{className:"flex -mt-1"},React.createElement("p",{className:"ui-text-p3 font-bold text-gui-blue-default-dark leading-[1.4rem]"},"+ usage"),React.createElement(Tooltip,{interactive:true,iconSize:"1.25rem"},"Usage is billed on top of your plan. You'll be charged monthly based on how many messages, channel minutes, and connection minutes you use. See rates above.")))},cta:{text:"Get started",url:"/users/paid_sign_up?package=standard",iconColor:"text-neutral-600 dark:text-neutral-700"},sections:[{title:"Capacity",items:["10k concurrent channels","10k concurrent connections","2.5k messages / second"]},{title:"Includes",items:["Build with any Ably product","1 day email support SLA","Uptime SLO"],listItemColors:{foreground:"text-neutral-700 dark:text-neutral-600",background:"text-neutral-100 dark:text-neutral-1200"}}],bottomCta:{text:"See all features",url:"#pricing-table"}},{title:{content:"Pro",className:"ui-text-h4 tracking-[-0.002rem]",color:"text-neutral-1300 dark:text-neutral-000"},description:{content:"Scale business critical workloads.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$399",content:React.createElement(React.Fragment,null,React.createElement("p",{className:"ui-text-p3 font-medium",style:{color:"currentColor"}},"/ month"),React.createElement("div",{className:"flex -mt-1"},React.createElement("p",{className:"ui-text-p3 font-bold text-gui-blue-default-dark leading-[1.4rem]"},"+ usage"),React.createElement(Tooltip,{interactive:true,iconSize:"1.25rem"},"Usage is billed on top of your plan. You'll be charged monthly based on how many messages, channel minutes, and connection minutes you use. See rates above.")))},cta:{text:"Get started",url:"/users/paid_sign_up?package=pro",iconColor:"text-neutral-600 dark:text-neutral-700"},sections:[{title:"Capacity",items:["50k concurrent channels","50k concurrent connections","10k messages / second"]},{title:"Includes",items:["Build with any Ably product","4 hour email support SLA","Datadog (lite)","Uptime SLO"],listItemColors:{foreground:"text-neutral-700 dark:text-neutral-600",background:"text-neutral-100 dark:text-neutral-1200"}}],bottomCta:{text:"See all features",url:"#pricing-table"}},{title:{content:"Enterprise",className:"ui-text-h4 tracking-[-0.002rem]",color:"text-orange-600"},description:{content:"Serious workloads without limits.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"Custom"},cta:{text:"Contact us",url:"/contact"},sections:[{title:"Capacity",items:["Unlimited concurrent channels","Unlimited connections","Unlimited messages / second"]},{title:"Includes",items:["Build with any Ably product","24/7 mission critical support","99.999% uptime SLAs","Committed use discounts","Datadog","CNAME, SSO, & more"],listItemColors:{foreground:"text-orange-700 dark:text-orange-500",background:"text-neutral-100 dark:text-neutral-1200"}}],bottomCta:{text:"See all features",url:"#pricing-table"}}];export const consumptionData=[{title:{content:"Messages",className:"ui-text-h3",color:"text-neutral-1300 dark: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-700 dark:text-neutral-600"},price:{amount:"$2.50",content:"/ 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"]]}],subtext:"As low as $0.50/M with volume discount"},{title:{content:"Channels",className:"ui-text-h3",color:"text-neutral-1300 dark:text-neutral-000",tooltip:React.createElement("p",null,"We charge you for the amount of time a channel is active in our network by the minute. For example, if ten channels are in use for 45 minutes, you will be charged a total of 450 channel minutes.")},description:{content:"Channels are used to route messages from publishers to subscribers. Channels are billed by the minute when actively being used by a connected client.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$1.00",content:"/ 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"]]}],subtext:"As low as $0.20/M with volume discount"},{title:{content:"Connections",className:"ui-text-h3",color:"text-neutral-1300 dark:text-neutral-000",tooltip:React.createElement("p",null,"We charge you for the amount of time devices are connected to our network by the minute. For example, if ten devices are each connected for 45 minutes, you will be charged a total of 450 connection minutes.")},description:{content:"Clients establish and maintain a connection to the Ably service, typically over WebSockets.",className:"ui-text-p3",color:"text-neutral-700 dark:text-neutral-600"},price:{amount:"$1.00",content:"/ 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"]]}],subtext:"As low as $0.20/M with volume discount"}];
2
2
  //# sourceMappingURL=data.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Pricing/data.tsx"],"sourcesContent":["import React from \"react\";\nimport { PricingDataFeature } from \"./types\";\nimport Tooltip from \"../Tooltip\";\n\nexport const planData: PricingDataFeature[] = [\n {\n title: {\n content: \"Free\",\n className: \"ui-text-h4 tracking-[-0.002rem]\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n },\n description: {\n content: \"Build a proof of concept.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"$0\" },\n cta: {\n text: \"Start for free\",\n url: \"/sign-up\",\n iconColor: \"text-neutral-600 dark:text-neutral-700\",\n },\n sections: [\n {\n title: \"Capacity\",\n items: [\n \"200 concurrent connections\",\n \"500 messages / second\",\n \"6M messages / month\",\n ],\n },\n {\n title: \"Includes\",\n items: [\n \"Build with any Ably product\",\n \"Community & email support (best effort)\",\n \"No commitment\",\n ],\n listItemColors: {\n foreground: \"text-neutral-700 dark:text-neutral-600\",\n background: \"text-neutral-100 dark:text-neutral-1200\",\n },\n cta: {\n text: \"See all features\",\n url: \"#pricing-table\",\n },\n },\n ],\n },\n {\n title: {\n content: \"Standard\",\n className: \"ui-text-h4 tracking-[-0.002rem]\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n },\n description: {\n content: \"Roll-out into production.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: {\n amount: \"$29\",\n content: (\n <>\n <p\n className=\"ui-text-p3 font-medium\"\n style={{ color: \"currentColor\" }}\n >\n / month\n </p>\n <div className=\"flex -mt-1\">\n <p className=\"ui-text-p3 font-bold text-gui-blue-default-dark leading-[1.4rem]\">\n + usage\n </p>\n <Tooltip interactive={true} iconSize=\"1.25rem\">\n Usage is billed on top of your plan. You&apos;ll be charged\n monthly based on how many messages, channel minutes, and\n connection minutes you use. See rates above.\n </Tooltip>\n </div>\n </>\n ),\n },\n cta: {\n text: \"Get started\",\n url: \"/users/paid_sign_up?package=standard\",\n iconColor: \"text-neutral-600 dark:text-neutral-700\",\n },\n sections: [\n {\n title: \"Capacity\",\n items: [\n \"10k concurrent channels\",\n \"10k concurrent connections\",\n \"2.5k messages / second\",\n ],\n },\n {\n title: \"Includes\",\n items: [\n \"Build with any Ably product\",\n \"1 day email support SLA\",\n \"Uptime SLO\",\n ],\n listItemColors: {\n foreground: \"text-neutral-700 dark:text-neutral-600\",\n background: \"text-neutral-100 dark:text-neutral-1200\",\n },\n cta: {\n text: \"See all features\",\n url: \"#pricing-table\",\n },\n },\n ],\n },\n {\n title: {\n content: \"Pro\",\n className: \"ui-text-h4 tracking-[-0.002rem]\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n },\n description: {\n content: \"Scale business critical workloads.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: {\n amount: \"$399\",\n content: (\n <>\n <p\n className=\"ui-text-p3 font-medium\"\n style={{ color: \"currentColor\" }}\n >\n / month\n </p>\n <div className=\"flex -mt-1\">\n <p className=\"ui-text-p3 font-bold text-gui-blue-default-dark leading-[1.4rem]\">\n + usage\n </p>\n <Tooltip interactive={true} iconSize=\"1.25rem\">\n Usage is billed on top of your plan. You&apos;ll be charged\n monthly based on how many messages, channel minutes, and\n connection minutes you use. See rates above.\n </Tooltip>\n </div>\n </>\n ),\n },\n cta: {\n text: \"Get started\",\n url: \"/users/paid_sign_up?package=pro\",\n iconColor: \"text-neutral-600 dark:text-neutral-700\",\n },\n sections: [\n {\n title: \"Capacity\",\n items: [\n \"50k concurrent channels\",\n \"50k concurrent connections\",\n \"10k messages / second\",\n ],\n },\n {\n title: \"Includes\",\n items: [\n \"Build with any Ably product\",\n \"4 hour email support SLA\",\n \"Datadog (lite)\",\n \"Uptime SLO\",\n ],\n listItemColors: {\n foreground: \"text-neutral-700 dark:text-neutral-600\",\n background: \"text-neutral-100 dark:text-neutral-1200\",\n },\n cta: {\n text: \"See all features\",\n url: \"#pricing-table\",\n },\n },\n ],\n },\n\n {\n title: {\n content: \"Enterprise\",\n className: \"ui-text-h4 tracking-[-0.002rem]\",\n color: \"text-orange-600\",\n },\n description: {\n content: \"Serious workloads without limits.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"Custom\" },\n cta: {\n text: \"Contact us\",\n url: \"/contact\",\n },\n sections: [\n {\n title: \"Capacity\",\n items: [\n \"Unlimited concurrent channels\",\n \"Unlimited connections\",\n \"Unlimited messages / second\",\n ],\n },\n {\n title: \"Includes\",\n items: [\n \"Build with any Ably product\",\n \"24/7 mission critical support\",\n \"99.999% uptime SLAs\",\n \"Committed use discounts\",\n \"Datadog\",\n \"CNAME, SSO, & more\",\n ],\n listItemColors: {\n foreground: \"text-orange-700 dark:text-orange-500\",\n background: \"text-neutral-100 dark:text-neutral-1200\",\n },\n cta: {\n text: \"See all features\",\n url: \"#pricing-table\",\n },\n },\n ],\n },\n];\n\nexport const consumptionData: PricingDataFeature[] = [\n {\n title: {\n content: \"Messages\",\n className: \"ui-text-h3\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n },\n description: {\n content:\n \"Messages contain the data that a client is communicating, such as the contents of a chat message.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"$2.50\", content: \"/ million\" },\n sections: [\n {\n title: \"Volume discounts\",\n items: [\n [\"Consumption\", \"$ / million msgs\"],\n [\"First 50 million msgs\", \"$2.50\"],\n [\"Next 450 million msgs\", \"$2.25\"],\n [\"Next 4.5 billion msgs\", \"$1.95\"],\n [\"Next 15 billion msgs\", \"$1.65\"],\n [\"Next 30 billion msgs\", \"$1.40\"],\n [\"Over 50 billion msgs\", \"$1.25\"],\n ],\n },\n ],\n subtext: \"As low as $0.50/M with volume discount\",\n },\n {\n title: {\n content: \"Channels\",\n className: \"ui-text-h3\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n tooltip: (\n <p>\n We charge you for the amount of time a channel is active in our\n network by the minute. For example, if ten channels are in use for 45\n minutes, you will be charged a total of 450 channel minutes.\n </p>\n ),\n },\n description: {\n content:\n \"Channels are used to route messages from publishers to subscribers. Channels are billed by the minute when actively being used by a connected client.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"$1.00\", content: \"/ million mins\" },\n sections: [\n {\n title: \"Volume discounts\",\n items: [\n [\"Consumption\", \"$ / million mins\"],\n [\"First 10 million mins\", \"$1.00\"],\n [\"Next 90 million mins\", \"$0.95\"],\n [\"Next 900 million mins\", \"$0.85\"],\n [\"Next 4 billion mins\", \"$0.75\"],\n [\"Next 10 billion mins\", \"$0.65\"],\n [\"Over 15 billion mins\", \"$0.60\"],\n ],\n },\n ],\n subtext: \"As low as $0.20/M with volume discount\",\n },\n {\n title: {\n content: \"Connections\",\n className: \"ui-text-h3\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n tooltip: (\n <p>\n We charge you for the amount of time devices are connected to our\n network by the minute. For example, if ten devices are each connected\n for 45 minutes, you will be charged a total of 450 connection minutes.\n </p>\n ),\n },\n description: {\n content:\n \"Clients establish and maintain a connection to the Ably service, typically over WebSockets.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"$1.00\", content: \"/ million mins\" },\n sections: [\n {\n title: \"Volume discounts\",\n items: [\n [\"Consumption\", \"$ / million mins\"],\n [\"First 10 million mins\", \"$1.00\"],\n [\"Next 90 million mins\", \"$0.95\"],\n [\"Next 900 million mins\", \"$0.85\"],\n [\"Next 4 billion mins\", \"$0.75\"],\n [\"Next 10 billion mins\", \"$0.65\"],\n [\"Over 15 billion mins\", \"$0.60\"],\n ],\n },\n ],\n subtext: \"As low as $0.20/M with volume discount\",\n },\n];\n"],"names":["React","Tooltip","planData","title","content","className","color","description","price","amount","cta","text","url","iconColor","sections","items","listItemColors","foreground","background","p","style","div","interactive","iconSize","consumptionData","subtext","tooltip"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAE1B,QAAOC,YAAa,YAAa,AAEjC,QAAO,MAAMC,SAAiC,CAC5C,CACEC,MAAO,CACLC,QAAS,OACTC,UAAW,kCACXC,MAAO,yCACT,EACAC,YAAa,CACXH,QAAS,4BACTC,UAAW,aACXC,MAAO,wCACT,EACAE,MAAO,CAAEC,OAAQ,IAAK,EACtBC,IAAK,CACHC,KAAM,iBACNC,IAAK,WACLC,UAAW,wCACb,EACAC,SAAU,CACR,CACEX,MAAO,WACPY,MAAO,CACL,6BACA,wBACA,sBACD,AACH,EACA,CACEZ,MAAO,WACPY,MAAO,CACL,8BACA,0CACA,gBACD,CACDC,eAAgB,CACdC,WAAY,yCACZC,WAAY,yCACd,EACAR,IAAK,CACHC,KAAM,mBACNC,IAAK,gBACP,CACF,EACD,AACH,EACA,CACET,MAAO,CACLC,QAAS,WACTC,UAAW,kCACXC,MAAO,yCACT,EACAC,YAAa,CACXH,QAAS,4BACTC,UAAW,aACXC,MAAO,wCACT,EACAE,MAAO,CACLC,OAAQ,MACRL,QACE,wCACE,oBAACe,KACCd,UAAU,yBACVe,MAAO,CAAEd,MAAO,cAAe,GAChC,WAGD,oBAACe,OAAIhB,UAAU,cACb,oBAACc,KAAEd,UAAU,oEAAmE,WAGhF,oBAACJ,SAAQqB,YAAa,KAAMC,SAAS,WAAU,iKAQvD,EACAb,IAAK,CACHC,KAAM,cACNC,IAAK,uCACLC,UAAW,wCACb,EACAC,SAAU,CACR,CACEX,MAAO,WACPY,MAAO,CACL,0BACA,6BACA,yBACD,AACH,EACA,CACEZ,MAAO,WACPY,MAAO,CACL,8BACA,0BACA,aACD,CACDC,eAAgB,CACdC,WAAY,yCACZC,WAAY,yCACd,EACAR,IAAK,CACHC,KAAM,mBACNC,IAAK,gBACP,CACF,EACD,AACH,EACA,CACET,MAAO,CACLC,QAAS,MACTC,UAAW,kCACXC,MAAO,yCACT,EACAC,YAAa,CACXH,QAAS,qCACTC,UAAW,aACXC,MAAO,wCACT,EACAE,MAAO,CACLC,OAAQ,OACRL,QACE,wCACE,oBAACe,KACCd,UAAU,yBACVe,MA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"}
1
+ {"version":3,"sources":["../../../src/core/Pricing/data.tsx"],"sourcesContent":["import React from \"react\";\nimport { PricingDataFeature } from \"./types\";\nimport Tooltip from \"../Tooltip\";\n\nexport const planData: PricingDataFeature[] = [\n {\n title: {\n content: \"Free\",\n className: \"ui-text-h4 tracking-[-0.002rem]\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n },\n description: {\n content: \"Build a proof of concept.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"$0\" },\n cta: {\n text: \"Start for free\",\n url: \"/sign-up\",\n iconColor: \"text-neutral-600 dark:text-neutral-700\",\n },\n sections: [\n {\n title: \"Capacity\",\n items: [\n \"200 concurrent connections\",\n \"500 messages / second\",\n \"6M messages / month\",\n ],\n },\n {\n title: \"Includes\",\n items: [\n \"Build with any Ably product\",\n \"Community & email support (best effort)\",\n \"No commitment\",\n ],\n listItemColors: {\n foreground: \"text-neutral-700 dark:text-neutral-600\",\n background: \"text-neutral-100 dark:text-neutral-1200\",\n },\n },\n ],\n bottomCta: {\n text: \"See all features\",\n url: \"#pricing-table\",\n },\n },\n {\n title: {\n content: \"Standard\",\n className: \"ui-text-h4 tracking-[-0.002rem]\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n },\n description: {\n content: \"Roll-out into production.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: {\n amount: \"$29\",\n content: (\n <>\n <p\n className=\"ui-text-p3 font-medium\"\n style={{ color: \"currentColor\" }}\n >\n / month\n </p>\n <div className=\"flex -mt-1\">\n <p className=\"ui-text-p3 font-bold text-gui-blue-default-dark leading-[1.4rem]\">\n + usage\n </p>\n <Tooltip interactive={true} iconSize=\"1.25rem\">\n Usage is billed on top of your plan. You&apos;ll be charged\n monthly based on how many messages, channel minutes, and\n connection minutes you use. See rates above.\n </Tooltip>\n </div>\n </>\n ),\n },\n cta: {\n text: \"Get started\",\n url: \"/users/paid_sign_up?package=standard\",\n iconColor: \"text-neutral-600 dark:text-neutral-700\",\n },\n sections: [\n {\n title: \"Capacity\",\n items: [\n \"10k concurrent channels\",\n \"10k concurrent connections\",\n \"2.5k messages / second\",\n ],\n },\n {\n title: \"Includes\",\n items: [\n \"Build with any Ably product\",\n \"1 day email support SLA\",\n \"Uptime SLO\",\n ],\n listItemColors: {\n foreground: \"text-neutral-700 dark:text-neutral-600\",\n background: \"text-neutral-100 dark:text-neutral-1200\",\n },\n },\n ],\n bottomCta: {\n text: \"See all features\",\n url: \"#pricing-table\",\n },\n },\n {\n title: {\n content: \"Pro\",\n className: \"ui-text-h4 tracking-[-0.002rem]\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n },\n description: {\n content: \"Scale business critical workloads.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: {\n amount: \"$399\",\n content: (\n <>\n <p\n className=\"ui-text-p3 font-medium\"\n style={{ color: \"currentColor\" }}\n >\n / month\n </p>\n <div className=\"flex -mt-1\">\n <p className=\"ui-text-p3 font-bold text-gui-blue-default-dark leading-[1.4rem]\">\n + usage\n </p>\n <Tooltip interactive={true} iconSize=\"1.25rem\">\n Usage is billed on top of your plan. You&apos;ll be charged\n monthly based on how many messages, channel minutes, and\n connection minutes you use. See rates above.\n </Tooltip>\n </div>\n </>\n ),\n },\n cta: {\n text: \"Get started\",\n url: \"/users/paid_sign_up?package=pro\",\n iconColor: \"text-neutral-600 dark:text-neutral-700\",\n },\n sections: [\n {\n title: \"Capacity\",\n items: [\n \"50k concurrent channels\",\n \"50k concurrent connections\",\n \"10k messages / second\",\n ],\n },\n {\n title: \"Includes\",\n items: [\n \"Build with any Ably product\",\n \"4 hour email support SLA\",\n \"Datadog (lite)\",\n \"Uptime SLO\",\n ],\n listItemColors: {\n foreground: \"text-neutral-700 dark:text-neutral-600\",\n background: \"text-neutral-100 dark:text-neutral-1200\",\n },\n },\n ],\n bottomCta: {\n text: \"See all features\",\n url: \"#pricing-table\",\n },\n },\n\n {\n title: {\n content: \"Enterprise\",\n className: \"ui-text-h4 tracking-[-0.002rem]\",\n color: \"text-orange-600\",\n },\n description: {\n content: \"Serious workloads without limits.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"Custom\" },\n cta: {\n text: \"Contact us\",\n url: \"/contact\",\n },\n sections: [\n {\n title: \"Capacity\",\n items: [\n \"Unlimited concurrent channels\",\n \"Unlimited connections\",\n \"Unlimited messages / second\",\n ],\n },\n {\n title: \"Includes\",\n items: [\n \"Build with any Ably product\",\n \"24/7 mission critical support\",\n \"99.999% uptime SLAs\",\n \"Committed use discounts\",\n \"Datadog\",\n \"CNAME, SSO, & more\",\n ],\n listItemColors: {\n foreground: \"text-orange-700 dark:text-orange-500\",\n background: \"text-neutral-100 dark:text-neutral-1200\",\n },\n },\n ],\n bottomCta: {\n text: \"See all features\",\n url: \"#pricing-table\",\n },\n },\n];\n\nexport const consumptionData: PricingDataFeature[] = [\n {\n title: {\n content: \"Messages\",\n className: \"ui-text-h3\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n },\n description: {\n content:\n \"Messages contain the data that a client is communicating, such as the contents of a chat message.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"$2.50\", content: \"/ million\" },\n sections: [\n {\n title: \"Volume discounts\",\n items: [\n [\"Consumption\", \"$ / million msgs\"],\n [\"First 50 million msgs\", \"$2.50\"],\n [\"Next 450 million msgs\", \"$2.25\"],\n [\"Next 4.5 billion msgs\", \"$1.95\"],\n [\"Next 15 billion msgs\", \"$1.65\"],\n [\"Next 30 billion msgs\", \"$1.40\"],\n [\"Over 50 billion msgs\", \"$1.25\"],\n ],\n },\n ],\n subtext: \"As low as $0.50/M with volume discount\",\n },\n {\n title: {\n content: \"Channels\",\n className: \"ui-text-h3\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n tooltip: (\n <p>\n We charge you for the amount of time a channel is active in our\n network by the minute. For example, if ten channels are in use for 45\n minutes, you will be charged a total of 450 channel minutes.\n </p>\n ),\n },\n description: {\n content:\n \"Channels are used to route messages from publishers to subscribers. Channels are billed by the minute when actively being used by a connected client.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"$1.00\", content: \"/ million mins\" },\n sections: [\n {\n title: \"Volume discounts\",\n items: [\n [\"Consumption\", \"$ / million mins\"],\n [\"First 10 million mins\", \"$1.00\"],\n [\"Next 90 million mins\", \"$0.95\"],\n [\"Next 900 million mins\", \"$0.85\"],\n [\"Next 4 billion mins\", \"$0.75\"],\n [\"Next 10 billion mins\", \"$0.65\"],\n [\"Over 15 billion mins\", \"$0.60\"],\n ],\n },\n ],\n subtext: \"As low as $0.20/M with volume discount\",\n },\n {\n title: {\n content: \"Connections\",\n className: \"ui-text-h3\",\n color: \"text-neutral-1300 dark:text-neutral-000\",\n tooltip: (\n <p>\n We charge you for the amount of time devices are connected to our\n network by the minute. For example, if ten devices are each connected\n for 45 minutes, you will be charged a total of 450 connection minutes.\n </p>\n ),\n },\n description: {\n content:\n \"Clients establish and maintain a connection to the Ably service, typically over WebSockets.\",\n className: \"ui-text-p3\",\n color: \"text-neutral-700 dark:text-neutral-600\",\n },\n price: { amount: \"$1.00\", content: \"/ million mins\" },\n sections: [\n {\n title: \"Volume discounts\",\n items: [\n [\"Consumption\", \"$ / million mins\"],\n [\"First 10 million mins\", \"$1.00\"],\n [\"Next 90 million mins\", \"$0.95\"],\n [\"Next 900 million mins\", \"$0.85\"],\n [\"Next 4 billion mins\", \"$0.75\"],\n [\"Next 10 billion mins\", \"$0.65\"],\n [\"Over 15 billion mins\", \"$0.60\"],\n ],\n },\n ],\n subtext: \"As low as $0.20/M with volume discount\",\n },\n];\n"],"names":["React","Tooltip","planData","title","content","className","color","description","price","amount","cta","text","url","iconColor","sections","items","listItemColors","foreground","background","bottomCta","p","style","div","interactive","iconSize","consumptionData","subtext","tooltip"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAE1B,QAAOC,YAAa,YAAa,AAEjC,QAAO,MAAMC,SAAiC,CAC5C,CACEC,MAAO,CACLC,QAAS,OACTC,UAAW,kCACXC,MAAO,yCACT,EACAC,YAAa,CACXH,QAAS,4BACTC,UAAW,aACXC,MAAO,wCACT,EACAE,MAAO,CAAEC,OAAQ,IAAK,EACtBC,IAAK,CACHC,KAAM,iBACNC,IAAK,WACLC,UAAW,wCACb,EACAC,SAAU,CACR,CACEX,MAAO,WACPY,MAAO,CACL,6BACA,wBACA,sBACD,AACH,EACA,CACEZ,MAAO,WACPY,MAAO,CACL,8BACA,0CACA,gBACD,CACDC,eAAgB,CACdC,WAAY,yCACZC,WAAY,yCACd,CACF,EACD,CACDC,UAAW,CACTR,KAAM,mBACNC,IAAK,gBACP,CACF,EACA,CACET,MAAO,CACLC,QAAS,WACTC,UAAW,kCACXC,MAAO,yCACT,EACAC,YAAa,CACXH,QAAS,4BACTC,UAAW,aACXC,MAAO,wCACT,EACAE,MAAO,CACLC,OAAQ,MACRL,QACE,wCACE,oBAACgB,KACCf,UAAU,yBACVgB,MAAO,CAAEf,MAAO,cAAe,GAChC,WAGD,oBAACgB,OAAIjB,UAAU,cACb,oBAACe,KAAEf,UAAU,oEAAmE,WAGhF,oBAACJ,SAAQsB,YAAa,KAAMC,SAAS,WAAU,iKAQvD,EACAd,IAAK,CACHC,KAAM,cACNC,IAAK,uCACLC,UAAW,wCACb,EACAC,SAAU,CACR,CACEX,MAAO,WACPY,MAAO,CACL,0BACA,6BACA,yBACD,AACH,EACA,CACEZ,MAAO,WACPY,MAAO,CACL,8BACA,0BACA,aACD,CACDC,eAAgB,CACdC,WAAY,yCACZC,WAAY,yCACd,CACF,EACD,CACDC,UAAW,CACTR,KAAM,mBACNC,IAAK,gBACP,CACF,EACA,CACET,MAAO,CACLC,QAAS,MACTC,UAAW,kCACXC,MAAO,yCACT,EACAC,YAAa,CACXH,QAAS,qCACTC,UAAW,aACXC,MAAO,wCACT,EACAE,MAAO,CACLC,OAAQ,OACRL,QACE,wCACE,oBAACgB,KACCf,UAAU,yBACV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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Pricing/types.ts"],"sourcesContent":["import { ReactNode } from \"react\";\nimport { ColorClass, ColorThemeSet } from \"../styles/colors/types\";\n\ntype PricingDataHeader = {\n content: string;\n className?: string;\n color?: ColorClass | ColorThemeSet;\n tooltip?: string | ReactNode;\n};\n\ntype PricingDataFeatureCta = {\n text: string;\n url: string;\n className?: string;\n disabled?: boolean;\n onClick?: () => void;\n iconColor?: ColorClass | ColorThemeSet;\n};\n\nexport type PricingDataFeatureSection = {\n title: string;\n items: string[] | string[][];\n listItemColors?: { foreground: ColorThemeSet; background: ColorThemeSet };\n cta?: PricingDataFeatureCta;\n};\n\nexport type PricingDataFeatureBorder = {\n text: string;\n style: \"border-solid\" | \"border-dashed\" | \"border-dotted\";\n color: \"neutral\" | \"blue\" | \"orange\";\n};\n\nexport type PricingDataFeature = {\n title: PricingDataHeader;\n description: PricingDataHeader;\n price: { amount: string; content?: ReactNode };\n cta?: PricingDataFeatureCta;\n sections: PricingDataFeatureSection[];\n border?: PricingDataFeatureBorder;\n subtext?: string;\n};\n"],"names":[],"mappings":"AAgCA,QAQE"}
1
+ {"version":3,"sources":["../../../src/core/Pricing/types.ts"],"sourcesContent":["import { ReactNode } from \"react\";\nimport { ColorClass, ColorThemeSet } from \"../styles/colors/types\";\n\ntype PricingDataHeader = {\n content: string;\n className?: string;\n color?: ColorClass | ColorThemeSet;\n tooltip?: string | ReactNode;\n};\n\ntype PricingDataFeatureCta = {\n text: string;\n url: string;\n className?: string;\n disabled?: boolean;\n onClick?: () => void;\n iconColor?: ColorClass | ColorThemeSet;\n};\n\nexport type PricingDataFeatureSection = {\n title: string;\n items: string[] | string[][];\n listItemColors?: { foreground: ColorThemeSet; background: ColorThemeSet };\n};\n\nexport type PricingDataFeatureBorder = {\n text: string;\n style: \"border-solid\" | \"border-dashed\" | \"border-dotted\";\n color: \"neutral\" | \"blue\" | \"orange\";\n};\n\nexport type PricingDataFeature = {\n title: PricingDataHeader;\n description: PricingDataHeader;\n price: { amount: string; content?: ReactNode };\n cta?: PricingDataFeatureCta;\n sections: PricingDataFeatureSection[];\n border?: PricingDataFeatureBorder;\n subtext?: string;\n bottomCta?: PricingDataFeatureCta;\n};\n"],"names":[],"mappings":"AA+BA,QASE"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Tooltip.tsx"],"sourcesContent":["import React, {\n ButtonHTMLAttributes,\n HTMLAttributes,\n PropsWithChildren,\n ReactNode,\n useRef,\n useState,\n MouseEvent,\n RefObject,\n useEffect,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn\";\nimport { IconSize } from \"./Icon/types\";\n\ntype TooltipProps = {\n triggerElement?: ReactNode;\n triggerProps?: ButtonHTMLAttributes<HTMLButtonElement>;\n tooltipProps?: HTMLAttributes<HTMLDivElement>;\n interactive?: boolean;\n iconSize?: IconSize;\n} & HTMLAttributes<HTMLDivElement>;\n\nconst Tooltip = ({\n children,\n triggerElement,\n triggerProps,\n tooltipProps,\n interactive = false,\n iconSize = \"1rem\",\n ...rest\n}: PropsWithChildren<TooltipProps>) => {\n const [open, setOpen] = useState(false);\n const [fadeOut, setFadeOut] = useState(false);\n const [position, setPosition] = useState({ x: 0, y: 0, orientation: \"top\" });\n const offset = 8;\n const reference = useRef<HTMLButtonElement>(null);\n const floating = useRef<HTMLDivElement>(null);\n const fadeOutTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n useEffect(() => {\n if (open) {\n const floatingRect = floating.current?.getBoundingClientRect();\n const referenceRect = reference.current?.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n let orientation = \"top\";\n\n if (floatingRect && referenceRect) {\n let x =\n referenceRect.left +\n referenceRect.width / 2 -\n floatingRect.width / 2 +\n window.scrollX;\n let y =\n referenceRect.top - floatingRect.height - offset + window.scrollY;\n\n // Adjust if tooltip goes off the right edge\n if (x + floatingRect.width > viewportWidth + window.scrollX) {\n x = viewportWidth + window.scrollX - floatingRect.width - offset;\n orientation = \"left\";\n }\n\n // Adjust if tooltip goes off the left edge\n if (x < window.scrollX) {\n x = window.scrollX + offset;\n orientation = \"right\";\n }\n\n // Adjust if tooltip goes off the top edge\n if (y < window.scrollY) {\n y = referenceRect.bottom + offset + window.scrollY;\n orientation = \"bottom\";\n }\n\n // Adjust if tooltip goes off the bottom edge\n if (y + floatingRect.height > viewportHeight + window.scrollY) {\n y = referenceRect.top - floatingRect.height - offset + window.scrollY;\n }\n\n setPosition({ x, y, orientation });\n }\n } else {\n setPosition({ x: 0, y: 0, orientation: \"top\" });\n }\n\n return () => {\n if (fadeOutTimeoutRef.current !== null) {\n clearTimeout(fadeOutTimeoutRef.current);\n }\n };\n }, [open]);\n\n const initiateFadeOut = () => {\n setFadeOut(true);\n fadeOutTimeoutRef.current = setTimeout(() => {\n setOpen(false);\n setFadeOut(false);\n }, 250);\n };\n\n const cursorTowardsTooltip = (\n event: MouseEvent,\n ref: RefObject<HTMLButtonElement>,\n ) => {\n if (!ref.current) {\n return false;\n }\n\n const { clientX, clientY } = event;\n const { x, y, width, height } = ref.current.getBoundingClientRect();\n const { orientation } = position;\n\n switch (orientation) {\n case \"top\":\n return clientX >= x && clientX <= x + width && clientY < y;\n case \"left\":\n return clientY >= y && clientY <= y + height && clientX < x;\n case \"right\":\n return clientY >= y && clientY <= y + height && clientX > x + width;\n case \"bottom\":\n return clientX >= x && clientX <= x + width && clientY > y + height;\n default:\n return false;\n }\n };\n\n const fadeOutIfNotWithinTrigger = (event: MouseEvent) => {\n if (!reference.current) return;\n\n const { clientX, clientY } = event;\n const { x, y, width, height } = reference.current.getBoundingClientRect();\n const withinBounds =\n clientX >= x &&\n clientX <= x + width &&\n clientY >= y &&\n clientY <= y + height;\n\n if (!withinBounds) {\n initiateFadeOut();\n }\n };\n\n return (\n <div {...rest} className={cn(\"inline-flex ml-2\", rest?.className)}>\n <button\n onMouseEnter={() => setOpen(true)}\n onMouseLeave={(event) => {\n if (!interactive || !cursorTowardsTooltip(event, reference)) {\n initiateFadeOut();\n }\n }}\n type=\"button\"\n ref={reference}\n aria-describedby=\"tooltip\"\n {...triggerProps}\n className={cn(\n \"p-0 relative focus:outline-none h-[1rem]\",\n triggerProps?.className,\n )}\n >\n {triggerElement ?? (\n <Icon\n name=\"icon-gui-information-circle-outline\"\n color=\"text-neutral-700 dark:text-neutral-600 hover:text-neutral-1000 dark:hover:text-neutral-300\"\n size={iconSize as IconSize}\n />\n )}\n </button>\n\n {open\n ? createPortal(\n <div\n role=\"tooltip\"\n ref={floating}\n onMouseLeave={(event) =>\n setTimeout(() => fadeOutIfNotWithinTrigger(event), 250)\n }\n style={{\n top: position.y,\n left: position.x,\n zIndex: 1000,\n boxShadow: \"4px 4px 15px rgba(0, 0, 0, 0.2)\",\n }}\n {...tooltipProps}\n className={cn(\n \"bg-neutral-300 dark:bg-neutral-1000 text-neutral-1100 dark:text-neutral-200 ui-text-p3 font-medium p-4\",\n { \"pointer-events-none\": !interactive },\n \"rounded-lg absolute\",\n tooltipProps?.className,\n { \"animate-[tooltipExit_0.25s_ease-in-out]\": fadeOut },\n { \"animate-[tooltipEntry_0.25s_ease-in-out]\": !fadeOut },\n )}\n >\n <div className=\"max-w-60 w-auto\">{children}</div>\n </div>,\n document.body,\n )\n : null}\n </div>\n );\n};\n\nexport default Tooltip;\n"],"names":["React","useRef","useState","useEffect","createPortal","Icon","cn","Tooltip","children","triggerElement","triggerProps","tooltipProps","interactive","iconSize","rest","open","setOpen","fadeOut","setFadeOut","position","setPosition","x","y","orientation","offset","reference","floating","fadeOutTimeoutRef","floatingRect","current","getBoundingClientRect","referenceRect","viewportWidth","window","innerWidth","viewportHeight","innerHeight","left","width","scrollX","top","height","scrollY","bottom","clearTimeout","initiateFadeOut","setTimeout","cursorTowardsTooltip","event","ref","clientX","clientY","fadeOutIfNotWithinTrigger","withinBounds","div","className","button","onMouseEnter","onMouseLeave","type","aria-describedby","name","color","size","role","style","zIndex","boxShadow","document","body"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/Tooltip.tsx"],"sourcesContent":["import React, {\n ButtonHTMLAttributes,\n HTMLAttributes,\n PropsWithChildren,\n ReactNode,\n useRef,\n useState,\n MouseEvent,\n RefObject,\n useEffect,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn\";\nimport { IconSize } from \"./Icon/types\";\n\ntype TooltipProps = {\n triggerElement?: ReactNode;\n triggerProps?: ButtonHTMLAttributes<HTMLButtonElement>;\n tooltipProps?: HTMLAttributes<HTMLDivElement>;\n interactive?: boolean;\n iconSize?: IconSize;\n} & HTMLAttributes<HTMLDivElement>;\n\nconst Tooltip = ({\n children,\n triggerElement,\n triggerProps,\n tooltipProps,\n interactive = false,\n iconSize = \"1rem\",\n ...rest\n}: PropsWithChildren<TooltipProps>) => {\n const [open, setOpen] = useState(false);\n const [fadeOut, setFadeOut] = useState(false);\n const [position, setPosition] = useState({ x: 0, y: 0, orientation: \"top\" });\n const offset = 8;\n const reference = useRef<HTMLButtonElement>(null);\n const floating = useRef<HTMLDivElement>(null);\n const fadeOutTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n useEffect(() => {\n if (open) {\n const floatingRect = floating.current?.getBoundingClientRect();\n const referenceRect = reference.current?.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n let orientation = \"top\";\n\n if (floatingRect && referenceRect) {\n let x =\n referenceRect.left +\n referenceRect.width / 2 -\n floatingRect.width / 2 +\n window.scrollX;\n let y =\n referenceRect.top - floatingRect.height - offset + window.scrollY;\n\n // Adjust if tooltip goes off the right edge\n if (x + floatingRect.width > viewportWidth + window.scrollX) {\n x = viewportWidth + window.scrollX - floatingRect.width - offset;\n orientation = \"left\";\n }\n\n // Adjust if tooltip goes off the left edge\n if (x < window.scrollX) {\n x = window.scrollX + offset;\n orientation = \"right\";\n }\n\n // Adjust if tooltip goes off the top edge\n if (y < window.scrollY) {\n y = referenceRect.bottom + offset + window.scrollY;\n orientation = \"bottom\";\n }\n\n // Adjust if tooltip goes off the bottom edge\n if (y + floatingRect.height > viewportHeight + window.scrollY) {\n y = referenceRect.top - floatingRect.height - offset + window.scrollY;\n }\n\n setPosition({ x, y, orientation });\n }\n } else {\n setPosition({ x: 0, y: 0, orientation: \"top\" });\n }\n\n return () => {\n if (fadeOutTimeoutRef.current !== null) {\n clearTimeout(fadeOutTimeoutRef.current);\n }\n };\n }, [open]);\n\n const initiateFadeOut = () => {\n setFadeOut(true);\n fadeOutTimeoutRef.current = setTimeout(() => {\n setOpen(false);\n setFadeOut(false);\n }, 250);\n };\n\n const cursorTowardsTooltip = (\n event: MouseEvent,\n ref: RefObject<HTMLButtonElement>,\n ) => {\n if (!ref.current) {\n return false;\n }\n\n const { clientX, clientY } = event;\n const { x, y, width, height } = ref.current.getBoundingClientRect();\n const { orientation } = position;\n\n switch (orientation) {\n case \"top\":\n return clientX >= x && clientX <= x + width && clientY < y;\n case \"left\":\n return clientY >= y && clientY <= y + height && clientX < x;\n case \"right\":\n return clientY >= y && clientY <= y + height && clientX > x + width;\n case \"bottom\":\n return clientX >= x && clientX <= x + width && clientY > y + height;\n default:\n return false;\n }\n };\n\n const fadeOutIfNotWithinTrigger = (event: MouseEvent) => {\n if (!reference.current) return;\n\n const { clientX, clientY } = event;\n const { x, y, width, height } = reference.current.getBoundingClientRect();\n const withinBounds =\n clientX >= x &&\n clientX <= x + width &&\n clientY >= y &&\n clientY <= y + height;\n\n if (!withinBounds) {\n initiateFadeOut();\n }\n };\n\n return (\n <div {...rest} className={cn(\"inline-flex ml-2\", rest?.className)}>\n <button\n onMouseEnter={() => setOpen(true)}\n onMouseLeave={(event) => {\n if (!interactive || !cursorTowardsTooltip(event, reference)) {\n initiateFadeOut();\n }\n }}\n type=\"button\"\n ref={reference}\n aria-describedby=\"tooltip\"\n {...triggerProps}\n className={cn(\n \"p-0 relative focus:outline-none h-[1rem]\",\n triggerProps?.className,\n )}\n >\n {triggerElement ?? (\n <Icon\n name=\"icon-gui-information-circle-outline\"\n color=\"text-neutral-700 dark:text-neutral-600 hover:text-neutral-1000 dark:hover:text-neutral-300\"\n size={iconSize}\n />\n )}\n </button>\n\n {open\n ? createPortal(\n <div\n role=\"tooltip\"\n ref={floating}\n onMouseLeave={(event) =>\n setTimeout(() => fadeOutIfNotWithinTrigger(event), 250)\n }\n style={{\n top: position.y,\n left: position.x,\n zIndex: 1000,\n boxShadow: \"4px 4px 15px rgba(0, 0, 0, 0.2)\",\n }}\n {...tooltipProps}\n className={cn(\n \"bg-neutral-300 dark:bg-neutral-1000 text-neutral-1100 dark:text-neutral-200 ui-text-p3 font-medium p-4\",\n { \"pointer-events-none\": !interactive },\n \"rounded-lg absolute\",\n tooltipProps?.className,\n { \"animate-[tooltipExit_0.25s_ease-in-out]\": fadeOut },\n { \"animate-[tooltipEntry_0.25s_ease-in-out]\": !fadeOut },\n )}\n >\n <div className=\"max-w-60 w-auto\">{children}</div>\n </div>,\n document.body,\n )\n : null}\n </div>\n );\n};\n\nexport default Tooltip;\n"],"names":["React","useRef","useState","useEffect","createPortal","Icon","cn","Tooltip","children","triggerElement","triggerProps","tooltipProps","interactive","iconSize","rest","open","setOpen","fadeOut","setFadeOut","position","setPosition","x","y","orientation","offset","reference","floating","fadeOutTimeoutRef","floatingRect","current","getBoundingClientRect","referenceRect","viewportWidth","window","innerWidth","viewportHeight","innerHeight","left","width","scrollX","top","height","scrollY","bottom","clearTimeout","initiateFadeOut","setTimeout","cursorTowardsTooltip","event","ref","clientX","clientY","fadeOutIfNotWithinTrigger","withinBounds","div","className","button","onMouseEnter","onMouseLeave","type","aria-describedby","name","color","size","role","style","zIndex","boxShadow","document","body"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/remote-session-data.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\n// Fetches current users session data\n// Assumes an authenticated session, so will only work when used on ably.com/ably.io\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst NOT_FOUND_ERROR_CODE = \"not-found\";\n\nconst fetchSessionData = async (store, sessionUrl) => {\n const sessionLoaded = (payload = {}) =>\n store.dispatch({ type: \"session/loaded\", payload });\n\n try {\n if (!sessionUrl) {\n console.log(\n `Skipping fetching session, invalid sessionUrl: \"${sessionUrl}\"`,\n );\n sessionLoaded();\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(sessionUrl, options);\n const jsonResponse = isJsonResponse(res.headers.get(\"content-type\"));\n\n if (!jsonResponse) {\n throw new Error(\"Session endpoint is not serving json\");\n }\n\n const payload = await res.json();\n\n if (payload.error === NOT_FOUND_ERROR_CODE) {\n sessionLoaded();\n } else {\n sessionLoaded(payload);\n }\n } catch (e) {\n sessionLoaded();\n console.warn(\"Could not fetch session data due to error:\", e);\n }\n};\n\nconst initialState = { data: null };\n\nconst REDUCER_KEY = \"session\";\n\nconst reducerSessionData = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"session/loaded\":\n return { ...state, data: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectSessionData = (store) => store.getState()[REDUCER_KEY]?.data;\n\nexport { fetchSessionData, reducerSessionData, selectSessionData };\n"],"names":["isJsonResponse","NOT_FOUND_ERROR_CODE","fetchSessionData","store","sessionUrl","sessionLoaded","payload","dispatch","type","console","log","options","headers","accept","cache","credentials","res","fetch","jsonResponse","get","Error","json","error","e","warn","initialState","data","REDUCER_KEY","reducerSessionData","state","action","selectSessionData","getState"],"mappings":"AAKA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,qBAAuB,YAE7B,MAAMC,iBAAmB,MAAOC,MAAOC,cACrC,MAAMC,cAAgB,CAACC,QAAU,CAAC,CAAC,GACjCH,MAAMI,QAAQ,CAAC,CAAEC,KAAM,iBAAkBF,OAAQ,GAEnD,GAAI,CACF,GAAI,CAACF,WAAY,CACfK,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEN,WAAW,CAAC,CAAC,EAElEC,gBACA,MACF,CAEA,MAAMM,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,GA0BgB,MA1BuB,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMb,WAAYO,SACpC,MAAMO,aAAelB,eAAegB,IAAIJ,OAAO,CAACO,GAAG,CAAC,iBAEpD,GAAI,CAACD,aAAc,CACjB,MAAM,IAAIE,MAAM,uCAClB,CAEA,MAAMd,QAAU,MAAMU,IAAIK,IAAI,GAE9B,GAAIf,QAAQgB,KAAK,GAAKrB,qBAAsB,CAC1CI,eACF,KAAO,CACLA,cAAcC,QAChB,CACF,CAAE,MAAOiB,EAAG,CACVlB,gBACAI,QAAQe,IAAI,CAAC,6CAA8CD,EAC7D,CACF,EAEA,MAAME,aAAe,CAAEC,KAAM,IAAK,EAElC,MAAMC,YAAc,UAEpB,MAAMC,mBAAqB,CACzB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOtB,IAAI,EACjB,IAAK,iBACH,MAAO,CAAE,GAAGqB,KAAK,CAAEH,KAAMI,OAAOxB,OAAO,AAAC,CAC1C,SACE,OAAOuB,KACX,CACF,CACF,EAEA,MAAME,kBAAoB,AAAC5B,OAAUA,MAAM6B,QAAQ,EAAE,CAACL,YAAY,EAAED,IAEpE,QAASxB,gBAAgB,CAAE0B,kBAAkB,CAAEG,iBAAiB,CAAG"}
1
+ {"version":3,"sources":["../../src/core/remote-session-data.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\n// Fetches current users session data\n// Assumes an authenticated session, so will only work when used on ably.com/ably.io\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst NOT_FOUND_ERROR_CODE = \"not-found\";\n\nconst fetchSessionData = async (store, sessionUrl) => {\n const sessionLoaded = (payload = {}) =>\n store.dispatch({ type: \"session/loaded\", payload });\n\n try {\n if (!sessionUrl) {\n console.log(\n `Skipping fetching session, invalid sessionUrl: \"${sessionUrl}\"`,\n );\n sessionLoaded();\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(sessionUrl, options);\n const jsonResponse = isJsonResponse(res.headers.get(\"content-type\"));\n\n if (!jsonResponse) {\n throw new Error(\"Session endpoint is not serving json\");\n }\n\n const payload = await res.json();\n\n if (payload.error === NOT_FOUND_ERROR_CODE) {\n sessionLoaded();\n } else {\n sessionLoaded(payload);\n }\n } catch (e) {\n sessionLoaded();\n console.warn(\"Could not fetch session data due to error:\", e);\n }\n};\n\nconst initialState = { data: null };\n\nconst REDUCER_KEY = \"session\";\n\nconst reducerSessionData = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"session/loaded\":\n return { ...state, data: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectSessionData = (store) => store.getState()[REDUCER_KEY]?.data;\n\nexport { fetchSessionData, reducerSessionData, selectSessionData };\n"],"names":["isJsonResponse","NOT_FOUND_ERROR_CODE","fetchSessionData","store","sessionUrl","sessionLoaded","payload","dispatch","type","console","log","options","headers","accept","cache","credentials","res","fetch","jsonResponse","get","Error","json","error","e","warn","initialState","data","REDUCER_KEY","reducerSessionData","state","action","selectSessionData","getState"],"mappings":"AAKA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,qBAAuB,YAE7B,MAAMC,iBAAmB,MAAOC,MAAOC,cACrC,MAAMC,cAAgB,CAACC,QAAU,CAAC,CAAC,GACjCH,MAAMI,QAAQ,CAAC,CAAEC,KAAM,iBAAkBF,OAAQ,GAEnD,GAAI,CACF,GAAI,CAACF,WAAY,CACfK,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEN,WAAW,CAAC,CAAC,EAElEC,gBACA,MACF,CAEA,MAAMM,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,GAyC4B,MAzCW,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMb,WAAYO,SACpC,MAAMO,aAAelB,eAAegB,IAAIJ,OAAO,CAACO,GAAG,CAAC,iBAEpD,GAAI,CAACD,aAAc,CACjB,MAAM,IAAIE,MAAM,uCAClB,CAEA,MAAMd,QAAU,MAAMU,IAAIK,IAAI,GAE9B,GAAIf,QAAQgB,KAAK,GAAKrB,qBAAsB,CAC1CI,eACF,KAAO,CACLA,cAAcC,QAChB,CACF,CAAE,MAAOiB,EAAG,CACVlB,gBACAI,QAAQe,IAAI,CAAC,6CAA8CD,EAC7D,CACF,EAEA,MAAME,aAAe,CAAEC,KAAM,IAAK,EAElC,MAAMC,YAAc,UAEpB,MAAMC,mBAAqB,CACzB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOtB,IAAI,EACjB,IAAK,iBACH,MAAO,CAAE,GAAGqB,KAAK,CAAEH,KAAMI,OAAOxB,OAAO,AAAC,CAC1C,SACE,OAAOuB,KACX,CACF,CACF,EAEA,MAAME,kBAAoB,AAAC5B,OAAUA,MAAM6B,QAAQ,EAAE,CAACL,YAAY,EAAED,IAEpE,QAASxB,gBAAgB,CAAE0B,kBAAkB,CAAEG,iBAAiB,CAAG"}
package/index.d.ts CHANGED
@@ -5415,7 +5415,6 @@ export type PricingDataFeatureSection = {
5415
5415
  foreground: ColorThemeSet;
5416
5416
  background: ColorThemeSet;
5417
5417
  };
5418
- cta?: PricingDataFeatureCta;
5419
5418
  };
5420
5419
  export type PricingDataFeatureBorder = {
5421
5420
  text: string;
@@ -5433,6 +5432,7 @@ export type PricingDataFeature = {
5433
5432
  sections: PricingDataFeatureSection[];
5434
5433
  border?: PricingDataFeatureBorder;
5435
5434
  subtext?: string;
5435
+ bottomCta?: PricingDataFeatureCta;
5436
5436
  };
5437
5437
  export {};
5438
5438
  //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ably/ui",
3
- "version": "17.5.8-dev.cb861d36",
3
+ "version": "17.6.0",
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",