@ably/ui 18.4.1 → 19.0.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.
Files changed (48) hide show
  1. package/AGENTS.md +2 -2
  2. package/README.md +4 -3
  3. package/core/Code.js.map +1 -1
  4. package/core/DropdownMenu.js +1 -1
  5. package/core/DropdownMenu.js.map +1 -1
  6. package/core/Flash.js.map +1 -1
  7. package/core/Loader.js.map +1 -1
  8. package/core/Meganav/MeganavBlog.js +1 -1
  9. package/core/Meganav/MeganavBlog.js.map +1 -1
  10. package/core/Meganav/MeganavCustomerStories.js +1 -1
  11. package/core/Meganav/MeganavCustomerStories.js.map +1 -1
  12. package/core/Meganav/MeganavPanelItemLinks.js +1 -1
  13. package/core/Meganav/MeganavPanelItemLinks.js.map +1 -1
  14. package/core/Meganav/PanelTitle.js +1 -1
  15. package/core/Meganav/PanelTitle.js.map +1 -1
  16. package/core/Meganav/data.js +1 -1
  17. package/core/Meganav/data.js.map +1 -1
  18. package/core/Meganav/images/cust-logo-fin-dark.svg +5 -0
  19. package/core/Meganav/images/cust-logo-fin-light.svg +5 -0
  20. package/core/Notice.js.map +1 -1
  21. package/core/Pricing/data.js +1 -1
  22. package/core/Pricing/data.js.map +1 -1
  23. package/core/Pricing/data.test.js +2 -0
  24. package/core/Pricing/data.test.js.map +1 -0
  25. package/core/SessionData.js.map +1 -1
  26. package/core/hooks/use-themed-scrollpoints.js.map +1 -1
  27. package/core/insights/bot-detection.js +2 -0
  28. package/core/insights/bot-detection.js.map +1 -0
  29. package/core/insights/bot-detection.test.js +2 -0
  30. package/core/insights/bot-detection.test.js.map +1 -0
  31. package/core/insights/command-queue.js +1 -1
  32. package/core/insights/command-queue.js.map +1 -1
  33. package/core/insights/index.test.js +1 -1
  34. package/core/insights/index.test.js.map +1 -1
  35. package/core/insights/mixpanel.js +1 -1
  36. package/core/insights/mixpanel.js.map +1 -1
  37. package/core/insights/mixpanel.test.js +1 -1
  38. package/core/insights/mixpanel.test.js.map +1 -1
  39. package/core/insights/service.js +1 -1
  40. package/core/insights/service.js.map +1 -1
  41. package/core/styles/colors/utils.js +1 -1
  42. package/core/styles/colors/utils.js.map +1 -1
  43. package/index.d.ts +5 -0
  44. package/package.json +29 -31
  45. package/core/images/cust-logo-split-col-pos.png +0 -0
  46. package/core/images/cust-logo-split-col-pos@2x.png +0 -0
  47. package/core/images/cust-logo-split-mono-pos.svg +0 -9
  48. package/core/images/cust-photo-split-pato-echague.jpg +0 -0
package/AGENTS.md CHANGED
@@ -7,7 +7,7 @@
7
7
  - `pnpm build` - Build the library (prebuild, icons, swc, tsc, cleanup)
8
8
  - `pnpm test` - Run all tests with Vitest
9
9
  - `pnpm test -- src/core/insights/index.test.ts` - Run a single test file
10
- - `pnpm lint` - Run ESLint on all files
10
+ - `pnpm lint` - Run oxlint on all files, then ESLint for the storybook and comment rules
11
11
  - `pnpm format:check` - Check formatting with Prettier
12
12
  - `pnpm format:write` - Auto-format all files with Prettier
13
13
  - `pnpm storybook` - Start Storybook dev server on port 3200
@@ -46,7 +46,7 @@
46
46
 
47
47
  ### Chrome DevTools MCP (Optional)
48
48
 
49
- See the [root AGENTS.md](../../AGENTS.md) for the tool decision table. Use Chrome DevTools MCP for performance profiling and visual verification. Storybook URL: `http://localhost:3200` (port varies by worktree index).
49
+ See [docs/BROWSER-TOOLS.md](../../docs/BROWSER-TOOLS.md) for which browser tool to reach for. Use Chrome DevTools MCP for performance profiling and visual verification. Storybook URL: `http://localhost:3200` (port varies by worktree index).
50
50
 
51
51
  ## Styling Guide
52
52
 
package/README.md CHANGED
@@ -216,7 +216,7 @@ The easiest way to get started is to use the development script:
216
216
 
217
217
  This script will:
218
218
 
219
- - Check that all required tools (Node.js, pnpm) are installed at the correct versions via mise or asdf
219
+ - Check that all required tools (Node.js, pnpm) are installed at the correct versions via mise
220
220
  - Install all project dependencies
221
221
  - Start Storybook automatically
222
222
 
@@ -261,10 +261,11 @@ You will need to authenticate with [npmjs](https://docs.npmjs.com/creating-and-v
261
261
  After the above, you should have:
262
262
 
263
263
  - NPM_TOKEN set in your environment
264
- - `.npmrc` file to read NPM_TOKEN from your environment like this:
264
+ - your user-level `~/.npmrc` (not this package's `.npmrc`) reading it:
265
265
  ```
266
266
  //registry.npmjs.org/:_authToken=${NPM_TOKEN}
267
267
  ```
268
+ pnpm ignores environment-variable credentials in a committed project `.npmrc`.
268
269
 
269
270
  To deploy a review app with your in-progress code, you can use the `pre-release` script:
270
271
 
@@ -324,7 +325,7 @@ If using positioning any other than static, be mindful of creating stacking cont
324
325
 
325
326
  ### Formatting & linting files
326
327
 
327
- By default, [Prettier](https://prettier.io/) & [ESLint](https://eslint.org/) will handle most of the frontend files. You can use them through your editor (which should pick up the relevant config files) or on the command line (see `scripts` in package.json).
328
+ By default, [Prettier](https://prettier.io/) & [oxlint](https://oxc.rs/docs/guide/usage/linter) (plus a small ESLint for the storybook and comment rules) will handle most of the frontend files. You can use them through your editor (which should pick up the relevant config files) or on the command line (see `scripts` in package.json).
328
329
 
329
330
  ### Adding a new component
330
331
 
package/core/Code.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Code.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n highlightSnippet,\n LINE_HIGHLIGHT_CLASSES,\n registerDefaultLanguages,\n splitHtmlLines,\n} from \"./utils/syntax-highlighter\";\nimport languagesRegistry from \"./utils/syntax-highlighter-registry\";\nimport cn from \"./utils/cn\";\n\nregisterDefaultLanguages(languagesRegistry);\n\nexport type LineHighlightType = \"addition\" | \"removal\" | \"highlight\";\n\ntype CodeProps = {\n language: string;\n snippet: string;\n textSize?: string;\n padding?: string;\n additionalCSS?: string;\n showLines?: boolean;\n lineCSS?: string;\n wrap?: boolean;\n lineHighlights?: Record<number, LineHighlightType>;\n};\n\nconst Code = ({\n language,\n snippet,\n textSize = \"ui-text-code\",\n padding = \"p-8\",\n additionalCSS = \"\",\n showLines,\n lineCSS,\n wrap = false,\n lineHighlights,\n}: CodeProps) => {\n // Trim the snippet and remove trailing empty lines\n const trimmedSnippet = snippet.trimEnd();\n const HTMLraw = highlightSnippet(language, trimmedSnippet) ?? \"\";\n const className = `language-${language} ${textSize}`;\n\n // Calculate line count after removing trailing empty lines\n const lines = trimmedSnippet.split(/\\r\\n|\\r|\\n/);\n const lineCount = lines.length;\n\n const hasHighlights =\n lineHighlights && Object.keys(lineHighlights).length > 0;\n\n // Per-line rendering when highlights are present\n if (hasHighlights) {\n const htmlLines = splitHtmlLines(HTMLraw);\n\n return (\n <div\n className={cn(\"hljs overflow-y-auto\", padding, additionalCSS)}\n data-id=\"code\"\n >\n <pre\n lang={language}\n className={cn(\n \"h-full flex-1 text-p4 leading-normal\",\n wrap ? \"whitespace-pre-wrap break-words\" : \"overflow-x-auto\",\n )}\n >\n <code className={className}>\n {htmlLines.map((lineHtml, i) => {\n const lineNum = i + 1;\n const highlightType = lineHighlights[lineNum];\n const highlightClass = highlightType\n ? LINE_HIGHLIGHT_CLASSES[highlightType]\n : undefined;\n\n return (\n <span\n key={i}\n className={cn(\"flex min-w-full pl-2\", highlightClass)}\n >\n {showLines && (\n <span\n className={cn(\n \"mr-4 font-mono text-right text-neutral-800 select-none shrink-0 inline-block leading-normal\",\n lineCSS,\n )}\n style={{ minWidth: `${String(lineCount).length}ch` }}\n >\n {lineNum}\n </span>\n )}\n <span\n className=\"flex-1 !leading-normal\"\n // lineHtml comes from highlightSnippet() which HTML-escapes\n // its input before emitting tokens. The fallback is the\n // literal \"&nbsp;\" entity. No caller-controlled HTML reaches\n // this sink.\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: lineHtml || \"&nbsp;\",\n }}\n />\n </span>\n );\n })}\n </code>\n </pre>\n </div>\n );\n }\n\n // Default: single-block rendering (no highlights)\n return (\n <div\n className={cn(\"hljs overflow-y-auto flex\", padding, additionalCSS)}\n data-id=\"code\"\n >\n {showLines ? (\n <div className=\"text-p4 leading-normal pt-px\">\n {[...Array(lineCount)].map((_, i) => (\n <p\n className={cn(\n \"mr-4 font-mono text-right text-neutral-800\",\n lineCSS,\n )}\n key={i}\n >\n {i + 1}\n </p>\n ))}\n </div>\n ) : null}\n <pre\n lang={language}\n className={cn(\n \"h-full flex-1 text-p4 leading-normal\",\n wrap ? \"whitespace-pre-wrap break-words\" : \"overflow-x-auto\",\n )}\n >\n <code\n className={className}\n // HTMLraw is produced by highlightSnippet(); same trust analysis as\n // the lineHtml site above — the highlighter escapes input before\n // emitting tokens.\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: HTMLraw }}\n />\n </pre>\n </div>\n );\n};\n\nexport default Code;\n"],"names":["React","highlightSnippet","LINE_HIGHLIGHT_CLASSES","registerDefaultLanguages","splitHtmlLines","languagesRegistry","cn","Code","language","snippet","textSize","padding","additionalCSS","showLines","lineCSS","wrap","lineHighlights","trimmedSnippet","trimEnd","HTMLraw","className","lines","split","lineCount","length","hasHighlights","Object","keys","htmlLines","div","data-id","pre","lang","code","map","lineHtml","i","lineNum","highlightType","highlightClass","undefined","span","key","style","minWidth","String","dangerouslySetInnerHTML","__html","Array","_","p"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QACEC,gBAAgB,CAChBC,sBAAsB,CACtBC,wBAAwB,CACxBC,cAAc,KACT,4BAA6B,AACpC,QAAOC,sBAAuB,qCAAsC,AACpE,QAAOC,OAAQ,YAAa,CAE5BH,yBAAyBE,mBAgBzB,MAAME,KAAO,CAAC,CACZC,QAAQ,CACRC,OAAO,CACPC,SAAW,cAAc,CACzBC,QAAU,KAAK,CACfC,cAAgB,EAAE,CAClBC,SAAS,CACTC,OAAO,CACPC,KAAO,KAAK,CACZC,cAAc,CACJ,IAEV,MAAMC,eAAiBR,QAAQS,OAAO,GACtC,MAAMC,QAAUlB,iBAAiBO,SAAUS,iBAAmB,GAC9D,MAAMG,UAAY,CAAC,SAAS,EAAEZ,SAAS,CAAC,EAAEE,SAAS,CAAC,CAGpD,MAAMW,MAAQJ,eAAeK,KAAK,CAAC,cACnC,MAAMC,UAAYF,MAAMG,MAAM,CAE9B,MAAMC,cACJT,gBAAkBU,OAAOC,IAAI,CAACX,gBAAgBQ,MAAM,CAAG,EAGzD,GAAIC,cAAe,CACjB,MAAMG,UAAYxB,eAAee,SAEjC,OACE,oBAACU,OACCT,UAAWd,GAAG,uBAAwBK,QAASC,eAC/CkB,UAAQ,QAER,oBAACC,OACCC,KAAMxB,SACNY,UAAWd,GACT,uCACAS,KAAO,kCAAoC,oBAG7C,oBAACkB,QAAKb,UAAWA,WACdQ,UAAUM,GAAG,CAAC,CAACC,SAAUC,KACxB,MAAMC,QAAUD,EAAI,EACpB,MAAME,cAAgBtB,cAAc,CAACqB,QAAQ,CAC7C,MAAME,eAAiBD,cACnBpC,sBAAsB,CAACoC,cAAc,CACrCE,UAEJ,OACE,oBAACC,QACCC,IAAKN,EACLhB,UAAWd,GAAG,uBAAwBiC,iBAErC1B,WACC,oBAAC4B,QACCrB,UAAWd,GACT,8FACAQ,SAEF6B,MAAO,CAAEC,SAAU,CAAC,EAAEC,OAAOtB,WAAWC,MAAM,CAAC,EAAE,CAAC,AAAC,GAElDa,SAGL,oBAACI,QACCrB,UAAU,yBAMV0B,wBAAyB,CACvBC,OAAQZ,UAAY,QACtB,IAIR,KAKV,CAGA,OACE,oBAACN,OACCT,UAAWd,GAAG,4BAA6BK,QAASC,eACpDkB,UAAQ,QAEPjB,UACC,oBAACgB,OAAIT,UAAU,gCACZ,IAAI4B,MAAMzB,WAAW,CAACW,GAAG,CAAC,CAACe,EAAGb,IAC7B,oBAACc,KACC9B,UAAWd,GACT,6CACAQ,SAEF4B,IAAKN,GAEJA,EAAI,KAIT,KACJ,oBAACL,OACCC,KAAMxB,SACNY,UAAWd,GACT,uCACAS,KAAO,kCAAoC,oBAG7C,oBAACkB,QACCb,UAAWA,UAKX0B,wBAAyB,CAAEC,OAAQ5B,OAAQ,KAKrD,CAEA,gBAAeZ,IAAK"}
1
+ {"version":3,"sources":["../../src/core/Code.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n highlightSnippet,\n LINE_HIGHLIGHT_CLASSES,\n registerDefaultLanguages,\n splitHtmlLines,\n} from \"./utils/syntax-highlighter\";\nimport languagesRegistry from \"./utils/syntax-highlighter-registry\";\nimport cn from \"./utils/cn\";\n\nregisterDefaultLanguages(languagesRegistry);\n\nexport type LineHighlightType = \"addition\" | \"removal\" | \"highlight\";\n\ntype CodeProps = {\n language: string;\n snippet: string;\n textSize?: string;\n padding?: string;\n additionalCSS?: string;\n showLines?: boolean;\n lineCSS?: string;\n wrap?: boolean;\n lineHighlights?: Record<number, LineHighlightType>;\n};\n\nconst Code = ({\n language,\n snippet,\n textSize = \"ui-text-code\",\n padding = \"p-8\",\n additionalCSS = \"\",\n showLines,\n lineCSS,\n wrap = false,\n lineHighlights,\n}: CodeProps) => {\n // Trim the snippet and remove trailing empty lines\n const trimmedSnippet = snippet.trimEnd();\n const HTMLraw = highlightSnippet(language, trimmedSnippet) ?? \"\";\n const className = `language-${language} ${textSize}`;\n\n // Calculate line count after removing trailing empty lines\n const lines = trimmedSnippet.split(/\\r\\n|\\r|\\n/);\n const lineCount = lines.length;\n\n const hasHighlights =\n lineHighlights && Object.keys(lineHighlights).length > 0;\n\n // Per-line rendering when highlights are present\n if (hasHighlights) {\n const htmlLines = splitHtmlLines(HTMLraw);\n\n return (\n <div\n className={cn(\"hljs overflow-y-auto\", padding, additionalCSS)}\n data-id=\"code\"\n >\n <pre\n lang={language}\n className={cn(\n \"h-full flex-1 text-p4 leading-normal\",\n wrap ? \"whitespace-pre-wrap break-words\" : \"overflow-x-auto\",\n )}\n >\n <code className={className}>\n {htmlLines.map((lineHtml, i) => {\n const lineNum = i + 1;\n const highlightType = lineHighlights[lineNum];\n const highlightClass = highlightType\n ? LINE_HIGHLIGHT_CLASSES[highlightType]\n : undefined;\n\n return (\n <span\n key={i}\n className={cn(\"flex min-w-full pl-2\", highlightClass)}\n >\n {showLines && (\n <span\n className={cn(\n \"mr-4 font-mono text-right text-neutral-800 select-none shrink-0 inline-block leading-normal\",\n lineCSS,\n )}\n style={{ minWidth: `${String(lineCount).length}ch` }}\n >\n {lineNum}\n </span>\n )}\n <span\n className=\"flex-1 !leading-normal\"\n // lineHtml comes from highlightSnippet() which HTML-escapes\n // its input before emitting tokens. The fallback is the\n // literal \"&nbsp;\" entity. No caller-controlled HTML reaches\n // this sink.\n // oxlint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: lineHtml || \"&nbsp;\",\n }}\n />\n </span>\n );\n })}\n </code>\n </pre>\n </div>\n );\n }\n\n // Default: single-block rendering (no highlights)\n return (\n <div\n className={cn(\"hljs overflow-y-auto flex\", padding, additionalCSS)}\n data-id=\"code\"\n >\n {showLines ? (\n <div className=\"text-p4 leading-normal pt-px\">\n {[...Array(lineCount)].map((_, i) => (\n <p\n className={cn(\n \"mr-4 font-mono text-right text-neutral-800\",\n lineCSS,\n )}\n key={i}\n >\n {i + 1}\n </p>\n ))}\n </div>\n ) : null}\n <pre\n lang={language}\n className={cn(\n \"h-full flex-1 text-p4 leading-normal\",\n wrap ? \"whitespace-pre-wrap break-words\" : \"overflow-x-auto\",\n )}\n >\n <code\n className={className}\n // HTMLraw is produced by highlightSnippet(); same trust analysis as\n // the lineHtml site above — the highlighter escapes input before\n // emitting tokens.\n // oxlint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: HTMLraw }}\n />\n </pre>\n </div>\n );\n};\n\nexport default Code;\n"],"names":["React","highlightSnippet","LINE_HIGHLIGHT_CLASSES","registerDefaultLanguages","splitHtmlLines","languagesRegistry","cn","Code","language","snippet","textSize","padding","additionalCSS","showLines","lineCSS","wrap","lineHighlights","trimmedSnippet","trimEnd","HTMLraw","className","lines","split","lineCount","length","hasHighlights","Object","keys","htmlLines","div","data-id","pre","lang","code","map","lineHtml","i","lineNum","highlightType","highlightClass","undefined","span","key","style","minWidth","String","dangerouslySetInnerHTML","__html","Array","_","p"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QACEC,gBAAgB,CAChBC,sBAAsB,CACtBC,wBAAwB,CACxBC,cAAc,KACT,4BAA6B,AACpC,QAAOC,sBAAuB,qCAAsC,AACpE,QAAOC,OAAQ,YAAa,CAE5BH,yBAAyBE,mBAgBzB,MAAME,KAAO,CAAC,CACZC,QAAQ,CACRC,OAAO,CACPC,SAAW,cAAc,CACzBC,QAAU,KAAK,CACfC,cAAgB,EAAE,CAClBC,SAAS,CACTC,OAAO,CACPC,KAAO,KAAK,CACZC,cAAc,CACJ,IAEV,MAAMC,eAAiBR,QAAQS,OAAO,GACtC,MAAMC,QAAUlB,iBAAiBO,SAAUS,iBAAmB,GAC9D,MAAMG,UAAY,CAAC,SAAS,EAAEZ,SAAS,CAAC,EAAEE,SAAS,CAAC,CAGpD,MAAMW,MAAQJ,eAAeK,KAAK,CAAC,cACnC,MAAMC,UAAYF,MAAMG,MAAM,CAE9B,MAAMC,cACJT,gBAAkBU,OAAOC,IAAI,CAACX,gBAAgBQ,MAAM,CAAG,EAGzD,GAAIC,cAAe,CACjB,MAAMG,UAAYxB,eAAee,SAEjC,OACE,oBAACU,OACCT,UAAWd,GAAG,uBAAwBK,QAASC,eAC/CkB,UAAQ,QAER,oBAACC,OACCC,KAAMxB,SACNY,UAAWd,GACT,uCACAS,KAAO,kCAAoC,oBAG7C,oBAACkB,QAAKb,UAAWA,WACdQ,UAAUM,GAAG,CAAC,CAACC,SAAUC,KACxB,MAAMC,QAAUD,EAAI,EACpB,MAAME,cAAgBtB,cAAc,CAACqB,QAAQ,CAC7C,MAAME,eAAiBD,cACnBpC,sBAAsB,CAACoC,cAAc,CACrCE,UAEJ,OACE,oBAACC,QACCC,IAAKN,EACLhB,UAAWd,GAAG,uBAAwBiC,iBAErC1B,WACC,oBAAC4B,QACCrB,UAAWd,GACT,8FACAQ,SAEF6B,MAAO,CAAEC,SAAU,CAAC,EAAEC,OAAOtB,WAAWC,MAAM,CAAC,EAAE,CAAC,AAAC,GAElDa,SAGL,oBAACI,QACCrB,UAAU,yBAMV0B,wBAAyB,CACvBC,OAAQZ,UAAY,QACtB,IAIR,KAKV,CAGA,OACE,oBAACN,OACCT,UAAWd,GAAG,4BAA6BK,QAASC,eACpDkB,UAAQ,QAEPjB,UACC,oBAACgB,OAAIT,UAAU,gCACZ,IAAI4B,MAAMzB,WAAW,CAACW,GAAG,CAAC,CAACe,EAAGb,IAC7B,oBAACc,KACC9B,UAAWd,GACT,6CACAQ,SAEF4B,IAAKN,GAEJA,EAAI,KAIT,KACJ,oBAACL,OACCC,KAAMxB,SACNY,UAAWd,GACT,uCACAS,KAAO,kCAAoC,oBAG7C,oBAACkB,QACCb,UAAWA,UAKX0B,wBAAyB,CAAEC,OAAQ5B,OAAQ,KAKrD,CAEA,gBAAeZ,IAAK"}
@@ -1,2 +1,2 @@
1
- import React,{createContext,useContext,useState,useEffect,useRef}from"react";import Icon from"./Icon";import cn from"./utils/cn";const DropdownMenuContext=createContext({isOpen:false,setOpen:()=>{}});const DropdownMenu=({children})=>{const[isOpen,setOpen]=useState(false);const ref=useRef(null);useEffect(()=>{const clickHandler=e=>{if(ref.current?.contains(e.target))return;setOpen(false)};document.addEventListener("click",clickHandler);return()=>document.removeEventListener("click",clickHandler)},[]);return React.createElement(DropdownMenuContext.Provider,{value:{isOpen,setOpen}},React.createElement("div",{id:"dropdown-menu",className:"relative",ref:ref},children))};const Trigger=({children,triggerClassNames="",description})=>{const{isOpen,setOpen}=useContext(DropdownMenuContext);return React.createElement("button",{id:"menu-trigger","aria-label":description,onClick:()=>setOpen(!isOpen),className:cn("flex items-center ui-text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 focus:outline-none",triggerClassNames)},children,React.createElement(Icon,{name:isOpen?"icon-gui-chevron-up-mini":"icon-gui-chevron-down-mini",size:"1.25rem",additionalCSS:"text-neutral-1300 dark:text-neutral-000"}))};const Content=({children,anchorPosition="right",contentClassNames})=>{const{isOpen}=useContext(DropdownMenuContext);if(!isOpen){return null}return React.createElement("div",{id:"menu-content",role:"menu",className:cn("flex flex-col absolute z-10 border border-neutral-400 dark:border-neutral-900 bg-neutral-000 dark:bg-neutral-1300 rounded-lg ui-shadow-md-soft",anchorPosition==="right"?"right-0":"left-0",contentClassNames)},children)};const Link=({url,title,subtitle,iconName,children})=>{return React.createElement("a",{href:url,className:"menu-link group block p-2 rounded-lg hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100 text-neutral-1000 dark:text-neutral-300 hover:text-neutral-1300 hover:dark:text-neutral-000"},React.createElement("p",{className:"mb-1"},title,iconName?React.createElement(Icon,{name:iconName,size:"1rem",additionalCSS:"align-middle ml-2 relative -top-px -left-1 text-neutral-1300 dark:text-neutral-000"}):null),subtitle?React.createElement("p",{className:"ui-text-p3 mb-4"},subtitle):null,children)};DropdownMenu.Trigger=Trigger;DropdownMenu.Content=Content;DropdownMenu.Link=Link;export default DropdownMenu;
1
+ import React,{createContext,useContext,useState,useEffect,useRef}from"react";import Icon from"./Icon";import cn from"./utils/cn";const DropdownMenuContext=createContext({isOpen:false,setOpen:()=>{}});const DropdownMenu=({children})=>{const[isOpen,setOpen]=useState(false);const ref=useRef(null);useEffect(()=>{const clickHandler=e=>{if(ref.current?.contains(e.target))return;setOpen(false)};document.addEventListener("click",clickHandler);return()=>document.removeEventListener("click",clickHandler)},[]);return React.createElement(DropdownMenuContext.Provider,{value:{isOpen,setOpen}},React.createElement("div",{id:"dropdown-menu",className:"relative",ref:ref},children))};const Trigger=({children,triggerClassNames="",description})=>{const{isOpen,setOpen}=useContext(DropdownMenuContext);return React.createElement("button",{id:"menu-trigger","aria-label":description,onClick:()=>setOpen(!isOpen),className:cn("flex items-center ui-text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 focus:outline-none",triggerClassNames)},children,React.createElement(Icon,{name:isOpen?"icon-gui-chevron-up-mini":"icon-gui-chevron-down-mini",size:"1.25rem",additionalCSS:"text-neutral-1300 dark:text-neutral-000"}))};const Content=({children,anchorPosition="right",contentClassNames})=>{const{isOpen}=useContext(DropdownMenuContext);if(!isOpen){return null}return React.createElement("div",{id:"menu-content",role:"menu",className:cn("flex flex-col absolute z-10 border border-neutral-400 dark:border-neutral-900 bg-neutral-000 dark:bg-neutral-1300 rounded-lg ui-shadow-md-soft",anchorPosition==="right"?"right-0":"left-0",contentClassNames)},children)};const Link=({url,title,subtitle,iconName,children})=>{return React.createElement("a",{href:url,className:"menu-link group block p-2 rounded-lg\n hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100 text-neutral-1000 dark:text-neutral-300 hover:text-neutral-1300 hover:dark:text-neutral-000"},React.createElement("p",{className:"mb-1"},title,iconName?React.createElement(Icon,{name:iconName,size:"1rem",additionalCSS:"align-middle ml-2 relative -top-px -left-1 text-neutral-1300 dark:text-neutral-000"}):null),subtitle?React.createElement("p",{className:"ui-text-p3 mb-4"},subtitle):null,children)};DropdownMenu.Trigger=Trigger;DropdownMenu.Content=Content;DropdownMenu.Link=Link;export default DropdownMenu;
2
2
  //# sourceMappingURL=DropdownMenu.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/DropdownMenu.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useState,\n useEffect,\n useRef,\n ReactNode,\n Dispatch,\n} from \"react\";\nimport Icon from \"./Icon\";\nimport { IconName } from \"./Icon/types\";\nimport cn from \"./utils/cn\";\n\nconst DropdownMenuContext = createContext<{\n isOpen: boolean;\n setOpen: Dispatch<React.SetStateAction<boolean>>;\n}>({\n isOpen: false,\n setOpen: () => {},\n});\n\ntype DropdownMenuProps = {\n /**\n * The content to be displayed within the dropdown menu.\n */\n children: ReactNode;\n};\n\ntype TriggerProps = {\n /**\n * The content to be displayed within the trigger element.\n */\n children: ReactNode;\n /**\n * Additional class names to apply to the trigger element.\n */\n triggerClassNames?: string;\n /**\n * A description for the trigger element, used for accessibility purposes.\n */\n description?: string;\n};\n\ntype ContentProps = {\n /**\n * The content to be displayed within the dropdown menu.\n */\n children: ReactNode;\n /**\n * The position of the dropdown menu relative to the trigger element.\n * Defaults to \"right\".\n */\n anchorPosition?: string;\n /**\n * Additional class names to apply to the content container.\n */\n contentClassNames?: string;\n};\n\ntype LinkProps = {\n url: string;\n title: string;\n subtitle?: string;\n iconName?: IconName;\n children?: ReactNode;\n};\n\nconst DropdownMenu = ({ children }: DropdownMenuProps) => {\n const [isOpen, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const clickHandler = (e: MouseEvent) => {\n if (ref.current?.contains(e.target as Node)) return;\n setOpen(false);\n };\n document.addEventListener(\"click\", clickHandler);\n return () => document.removeEventListener(\"click\", clickHandler);\n }, []);\n\n return (\n <DropdownMenuContext.Provider value={{ isOpen, setOpen }}>\n <div id=\"dropdown-menu\" className=\"relative\" ref={ref}>\n {children}\n </div>\n </DropdownMenuContext.Provider>\n );\n};\n\nconst Trigger = ({\n children,\n triggerClassNames = \"\",\n description,\n}: TriggerProps) => {\n const { isOpen, setOpen } = useContext(DropdownMenuContext);\n\n return (\n <button\n id=\"menu-trigger\"\n aria-label={description}\n onClick={() => setOpen(!isOpen)}\n className={cn(\n \"flex items-center ui-text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 focus:outline-none\",\n triggerClassNames,\n )}\n >\n {children}\n <Icon\n name={\n isOpen ? \"icon-gui-chevron-up-mini\" : \"icon-gui-chevron-down-mini\"\n }\n size=\"1.25rem\"\n additionalCSS=\"text-neutral-1300 dark:text-neutral-000\"\n />\n </button>\n );\n};\n\nconst Content = ({\n children,\n anchorPosition = \"right\",\n contentClassNames,\n}: ContentProps) => {\n const { isOpen } = useContext(DropdownMenuContext);\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <div\n id=\"menu-content\"\n role=\"menu\"\n className={cn(\n \"flex flex-col absolute z-10 border border-neutral-400 dark:border-neutral-900 bg-neutral-000 dark:bg-neutral-1300 rounded-lg ui-shadow-md-soft\",\n anchorPosition === \"right\" ? \"right-0\" : \"left-0\",\n contentClassNames,\n )}\n >\n {children}\n </div>\n );\n};\n\nconst Link = ({ url, title, subtitle, iconName, children }: LinkProps) => {\n return (\n <a\n href={url}\n className=\"menu-link group block p-2 rounded-lg\n hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100 text-neutral-1000 dark:text-neutral-300 hover:text-neutral-1300 hover:dark:text-neutral-000\"\n >\n <p className=\"mb-1\">\n {title}\n {iconName ? (\n <Icon\n name={iconName}\n size=\"1rem\"\n additionalCSS=\"align-middle ml-2 relative -top-px -left-1 text-neutral-1300 dark:text-neutral-000\"\n />\n ) : null}\n </p>\n {subtitle ? <p className=\"ui-text-p3 mb-4\">{subtitle}</p> : null}\n {children}\n </a>\n );\n};\n\nDropdownMenu.Trigger = Trigger;\nDropdownMenu.Content = Content;\nDropdownMenu.Link = Link;\n\nexport default DropdownMenu;\n"],"names":["React","createContext","useContext","useState","useEffect","useRef","Icon","cn","DropdownMenuContext","isOpen","setOpen","DropdownMenu","children","ref","clickHandler","e","current","contains","target","document","addEventListener","removeEventListener","Provider","value","div","id","className","Trigger","triggerClassNames","description","button","aria-label","onClick","name","size","additionalCSS","Content","anchorPosition","contentClassNames","role","Link","url","title","subtitle","iconName","a","href","p"],"mappings":"AAAA,OAAOA,OACLC,aAAa,CACbC,UAAU,CACVC,QAAQ,CACRC,SAAS,CACTC,MAAM,KAGD,OAAQ,AACf,QAAOC,SAAU,QAAS,AAE1B,QAAOC,OAAQ,YAAa,CAE5B,MAAMC,oBAAsBP,cAGzB,CACDQ,OAAQ,MACRC,QAAS,KAAO,CAClB,GAgDA,MAAMC,aAAe,CAAC,CAAEC,QAAQ,CAAqB,IACnD,KAAM,CAACH,OAAQC,QAAQ,CAAGP,SAAS,OACnC,MAAMU,IAAMR,OAAuB,MAEnCD,UAAU,KACR,MAAMU,aAAe,AAACC,IACpB,GAAIF,IAAIG,OAAO,EAAEC,SAASF,EAAEG,MAAM,EAAW,OAC7CR,QAAQ,MACV,EACAS,SAASC,gBAAgB,CAAC,QAASN,cACnC,MAAO,IAAMK,SAASE,mBAAmB,CAAC,QAASP,aACrD,EAAG,EAAE,EAEL,OACE,oBAACN,oBAAoBc,QAAQ,EAACC,MAAO,CAAEd,OAAQC,OAAQ,GACrD,oBAACc,OAAIC,GAAG,gBAAgBC,UAAU,WAAWb,IAAKA,KAC/CD,UAIT,EAEA,MAAMe,QAAU,CAAC,CACff,QAAQ,CACRgB,kBAAoB,EAAE,CACtBC,WAAW,CACE,IACb,KAAM,CAAEpB,MAAM,CAAEC,OAAO,CAAE,CAAGR,WAAWM,qBAEvC,OACE,oBAACsB,UACCL,GAAG,eACHM,aAAYF,YACZG,QAAS,IAAMtB,QAAQ,CAACD,QACxBiB,UAAWnB,GACT,4GACAqB,oBAGDhB,SACD,oBAACN,MACC2B,KACExB,OAAS,2BAA6B,6BAExCyB,KAAK,UACLC,cAAc,4CAItB,EAEA,MAAMC,QAAU,CAAC,CACfxB,QAAQ,CACRyB,eAAiB,OAAO,CACxBC,iBAAiB,CACJ,IACb,KAAM,CAAE7B,MAAM,CAAE,CAAGP,WAAWM,qBAE9B,GAAI,CAACC,OAAQ,CACX,OAAO,IACT,CAEA,OACE,oBAACe,OACCC,GAAG,eACHc,KAAK,OACLb,UAAWnB,GACT,iJACA8B,iBAAmB,QAAU,UAAY,SACzCC,oBAGD1B,SAGP,EAEA,MAAM4B,KAAO,CAAC,CAAEC,GAAG,CAAEC,KAAK,CAAEC,QAAQ,CAAEC,QAAQ,CAAEhC,QAAQ,CAAa,IACnE,OACE,oBAACiC,KACCC,KAAML,IACNf,UAAU,sOAGV,oBAACqB,KAAErB,UAAU,QACVgB,MACAE,SACC,oBAACtC,MACC2B,KAAMW,SACNV,KAAK,OACLC,cAAc,uFAEd,MAELQ,SAAW,oBAACI,KAAErB,UAAU,mBAAmBiB,UAAgB,KAC3D/B,SAGP,CAEAD,CAAAA,aAAagB,OAAO,CAAGA,OACvBhB,CAAAA,aAAayB,OAAO,CAAGA,OACvBzB,CAAAA,aAAa6B,IAAI,CAAGA,IAEpB,gBAAe7B,YAAa"}
1
+ {"version":3,"sources":["../../src/core/DropdownMenu.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useState,\n useEffect,\n useRef,\n ReactNode,\n Dispatch,\n} from \"react\";\nimport Icon from \"./Icon\";\nimport { IconName } from \"./Icon/types\";\nimport cn from \"./utils/cn\";\n\nconst DropdownMenuContext = createContext<{\n isOpen: boolean;\n setOpen: Dispatch<React.SetStateAction<boolean>>;\n}>({\n isOpen: false,\n setOpen: () => {},\n});\n\ntype DropdownMenuProps = {\n /**\n * The content to be displayed within the dropdown menu.\n */\n children: ReactNode;\n};\n\ntype TriggerProps = {\n /**\n * The content to be displayed within the trigger element.\n */\n children: ReactNode;\n /**\n * Additional class names to apply to the trigger element.\n */\n triggerClassNames?: string;\n /**\n * A description for the trigger element, used for accessibility purposes.\n */\n description?: string;\n};\n\ntype ContentProps = {\n /**\n * The content to be displayed within the dropdown menu.\n */\n children: ReactNode;\n /**\n * The position of the dropdown menu relative to the trigger element.\n * Defaults to \"right\".\n */\n anchorPosition?: string;\n /**\n * Additional class names to apply to the content container.\n */\n contentClassNames?: string;\n};\n\ntype LinkProps = {\n url: string;\n title: string;\n subtitle?: string;\n iconName?: IconName;\n children?: ReactNode;\n};\n\nconst DropdownMenu = ({ children }: DropdownMenuProps) => {\n const [isOpen, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const clickHandler = (e: MouseEvent) => {\n if (ref.current?.contains(e.target as Node)) return;\n setOpen(false);\n };\n document.addEventListener(\"click\", clickHandler);\n return () => document.removeEventListener(\"click\", clickHandler);\n }, []);\n\n return (\n <DropdownMenuContext.Provider value={{ isOpen, setOpen }}>\n <div id=\"dropdown-menu\" className=\"relative\" ref={ref}>\n {children}\n </div>\n </DropdownMenuContext.Provider>\n );\n};\n\nconst Trigger = ({\n children,\n triggerClassNames = \"\",\n description,\n}: TriggerProps) => {\n const { isOpen, setOpen } = useContext(DropdownMenuContext);\n\n return (\n <button\n id=\"menu-trigger\"\n aria-label={description}\n onClick={() => setOpen(!isOpen)}\n className={cn(\n \"flex items-center ui-text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 focus:outline-none\",\n triggerClassNames,\n )}\n >\n {children}\n <Icon\n name={\n isOpen ? \"icon-gui-chevron-up-mini\" : \"icon-gui-chevron-down-mini\"\n }\n size=\"1.25rem\"\n additionalCSS=\"text-neutral-1300 dark:text-neutral-000\"\n />\n </button>\n );\n};\n\nconst Content = ({\n children,\n anchorPosition = \"right\",\n contentClassNames,\n}: ContentProps) => {\n const { isOpen } = useContext(DropdownMenuContext);\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <div\n id=\"menu-content\"\n role=\"menu\"\n className={cn(\n \"flex flex-col absolute z-10 border border-neutral-400 dark:border-neutral-900 bg-neutral-000 dark:bg-neutral-1300 rounded-lg ui-shadow-md-soft\",\n anchorPosition === \"right\" ? \"right-0\" : \"left-0\",\n contentClassNames,\n )}\n >\n {children}\n </div>\n );\n};\n\nconst Link = ({ url, title, subtitle, iconName, children }: LinkProps) => {\n return (\n <a\n href={url}\n className=\"menu-link group block p-2 rounded-lg\n hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100 text-neutral-1000 dark:text-neutral-300 hover:text-neutral-1300 hover:dark:text-neutral-000\"\n >\n <p className=\"mb-1\">\n {title}\n {iconName ? (\n <Icon\n name={iconName}\n size=\"1rem\"\n additionalCSS=\"align-middle ml-2 relative -top-px -left-1 text-neutral-1300 dark:text-neutral-000\"\n />\n ) : null}\n </p>\n {subtitle ? <p className=\"ui-text-p3 mb-4\">{subtitle}</p> : null}\n {children}\n </a>\n );\n};\n\nDropdownMenu.Trigger = Trigger;\nDropdownMenu.Content = Content;\nDropdownMenu.Link = Link;\n\nexport default DropdownMenu;\n"],"names":["React","createContext","useContext","useState","useEffect","useRef","Icon","cn","DropdownMenuContext","isOpen","setOpen","DropdownMenu","children","ref","clickHandler","e","current","contains","target","document","addEventListener","removeEventListener","Provider","value","div","id","className","Trigger","triggerClassNames","description","button","aria-label","onClick","name","size","additionalCSS","Content","anchorPosition","contentClassNames","role","Link","url","title","subtitle","iconName","a","href","p"],"mappings":"AAAA,OAAOA,OACLC,aAAa,CACbC,UAAU,CACVC,QAAQ,CACRC,SAAS,CACTC,MAAM,KAGD,OAAQ,AACf,QAAOC,SAAU,QAAS,AAE1B,QAAOC,OAAQ,YAAa,CAE5B,MAAMC,oBAAsBP,cAGzB,CACDQ,OAAQ,MACRC,QAAS,KAAO,CAClB,GAgDA,MAAMC,aAAe,CAAC,CAAEC,QAAQ,CAAqB,IACnD,KAAM,CAACH,OAAQC,QAAQ,CAAGP,SAAS,OACnC,MAAMU,IAAMR,OAAuB,MAEnCD,UAAU,KACR,MAAMU,aAAe,AAACC,IACpB,GAAIF,IAAIG,OAAO,EAAEC,SAASF,EAAEG,MAAM,EAAW,OAC7CR,QAAQ,MACV,EACAS,SAASC,gBAAgB,CAAC,QAASN,cACnC,MAAO,IAAMK,SAASE,mBAAmB,CAAC,QAASP,aACrD,EAAG,EAAE,EAEL,OACE,oBAACN,oBAAoBc,QAAQ,EAACC,MAAO,CAAEd,OAAQC,OAAQ,GACrD,oBAACc,OAAIC,GAAG,gBAAgBC,UAAU,WAAWb,IAAKA,KAC/CD,UAIT,EAEA,MAAMe,QAAU,CAAC,CACff,QAAQ,CACRgB,kBAAoB,EAAE,CACtBC,WAAW,CACE,IACb,KAAM,CAAEpB,MAAM,CAAEC,OAAO,CAAE,CAAGR,WAAWM,qBAEvC,OACE,oBAACsB,UACCL,GAAG,eACHM,aAAYF,YACZG,QAAS,IAAMtB,QAAQ,CAACD,QACxBiB,UAAWnB,GACT,4GACAqB,oBAGDhB,SACD,oBAACN,MACC2B,KACExB,OAAS,2BAA6B,6BAExCyB,KAAK,UACLC,cAAc,4CAItB,EAEA,MAAMC,QAAU,CAAC,CACfxB,QAAQ,CACRyB,eAAiB,OAAO,CACxBC,iBAAiB,CACJ,IACb,KAAM,CAAE7B,MAAM,CAAE,CAAGP,WAAWM,qBAE9B,GAAI,CAACC,OAAQ,CACX,OAAO,IACT,CAEA,OACE,oBAACe,OACCC,GAAG,eACHc,KAAK,OACLb,UAAWnB,GACT,iJACA8B,iBAAmB,QAAU,UAAY,SACzCC,oBAGD1B,SAGP,EAEA,MAAM4B,KAAO,CAAC,CAAEC,GAAG,CAAEC,KAAK,CAAEC,QAAQ,CAAEC,QAAQ,CAAEhC,QAAQ,CAAa,IACnE,OACE,oBAACiC,KACCC,KAAML,IACNf,UAAU,6OAGV,oBAACqB,KAAErB,UAAU,QACVgB,MACAE,SACC,oBAACtC,MACC2B,KAAMW,SACNV,KAAK,OACLC,cAAc,uFAEd,MAELQ,SAAW,oBAACI,KAAErB,UAAU,mBAAmBiB,UAAgB,KAC3D/B,SAGP,CAEAD,CAAAA,aAAagB,OAAO,CAAGA,OACvBhB,CAAAA,aAAayB,OAAO,CAAGA,OACvBzB,CAAAA,aAAa6B,IAAI,CAAGA,IAEpB,gBAAe7B,YAAa"}
package/core/Flash.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Flash.tsx"],"sourcesContent":["import React, {\n useEffect,\n useState,\n useRef,\n createContext,\n useContext,\n useCallback,\n useMemo,\n PropsWithChildren,\n} from \"react\";\nimport DOMPurify from \"dompurify\";\nimport Icon from \"./Icon\";\nimport { ColorClass } from \"./styles/colors/types\";\nimport { IconName } from \"./Icon/types\";\n\ntype FlashPropsType = \"error\" | \"success\" | \"notice\" | \"info\" | \"alert\";\n\ntype FlashProps = {\n id: string;\n removed: boolean;\n type: FlashPropsType;\n content: string;\n removeFlash: (id: string) => void;\n};\n\ntype BackendFlashesProps = {\n flashes: string[][];\n};\n\nconst FLASH_DATA_ID = \"ui-flashes\";\n\ntype FlashContextType = {\n flashes: FlashProps[];\n addFlashes: (flashes: Pick<FlashProps, \"type\" | \"content\">[]) => void;\n removeFlash: (id: string) => void;\n};\n\nconst FlashContext = createContext<FlashContextType | undefined>(undefined);\n\ntype FlashProviderProps = PropsWithChildren;\n\n/**\n * FlashProvider - Context provider for managing flash messages throughout the application.\n *\n * Maintains a global list of flash messages and provides methods to add/remove them.\n * Automatically deduplicates messages with the same type and content to prevent duplicates.\n * Use this at the app root level and access via useFlashContext() in child components.\n */\nconst FlashProvider = ({ children }: FlashProviderProps) => {\n const [flashes, setFlashes] = useState<FlashProps[]>([]);\n\n const removeFlash = useCallback((flashId: string) => {\n setFlashes((prev) => prev.filter((item) => item.id !== flashId));\n }, []);\n\n const addFlashes = useCallback(\n (newFlashes: Pick<FlashProps, \"type\" | \"content\">[]) => {\n setFlashes((prev) => {\n const withIds = newFlashes\n .filter(\n (flash) =>\n !prev.some(\n (existing) =>\n existing.content === flash.content &&\n existing.type === flash.type,\n ),\n )\n .map((flash) => ({\n ...flash,\n id: Math.random().toString(36).slice(2),\n removed: false,\n removeFlash,\n }));\n\n return [...prev, ...withIds];\n });\n },\n [removeFlash],\n );\n\n const contextValue = useMemo(\n () => ({ flashes, addFlashes, removeFlash }),\n [flashes, addFlashes, removeFlash],\n );\n\n return (\n <FlashContext.Provider value={contextValue}>\n {children}\n </FlashContext.Provider>\n );\n};\n\nconst useFlashContext = () => {\n const context = useContext(FlashContext);\n if (context === undefined) {\n throw new Error(\"useFlashContext must be used within FlashProvider\");\n }\n return context;\n};\n\nconst FLASH_BG_COLOR = {\n error: \"bg-gui-error\",\n success: \"bg-zingy-green\",\n notice: \"bg-electric-cyan\",\n info: \"bg-electric-cyan\",\n alert: \"bg-active-orange\",\n};\n\nconst FLASH_TEXT_COLOR = {\n error: \"text-white\",\n success: \"text-cool-black\",\n notice: \"text-cool-black\",\n info: \"text-cool-black\",\n alert: \"text-white\",\n};\n\nconst AUTO_HIDE = [\"success\", \"info\", \"notice\"];\nconst AUTO_HIDE_TIME = 8000;\n\nconst useAutoHide = (type: string, closeFlash: () => void) => {\n const timeoutId = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (AUTO_HIDE.includes(type)) {\n timeoutId.current = setTimeout(() => {\n closeFlash();\n }, AUTO_HIDE_TIME);\n }\n\n return () => {\n if (timeoutId.current) {\n clearTimeout(timeoutId.current);\n }\n };\n }, [type, closeFlash]);\n};\n\n/**\n * Flash - Individual flash message component with animations and auto-dismiss.\n *\n * Displays a colored notification banner with an icon, message content, and close button.\n * Success/info/notice messages auto-hide after 8 seconds. Error/alert messages require\n * manual dismissal. Uses CSS animations for smooth entry/exit and height transitions\n * on close. Content is sanitized with DOMPurify to allow safe HTML links from backend.\n */\nconst Flash = ({ id, type, content, removeFlash }: FlashProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [closed, setClosed] = useState(false);\n const [flashHeight, setFlashHeight] = useState(0);\n\n const closeFlash = () => {\n if (ref.current) {\n setFlashHeight(ref.current.getBoundingClientRect().height);\n }\n\n setClosed(true);\n\n setTimeout(() => {\n if (id) {\n removeFlash(id);\n }\n }, 100);\n };\n\n useAutoHide(type, closeFlash);\n\n const animateEntry = !closed;\n\n let style;\n\n if (flashHeight && !closed) {\n style = { height: `${flashHeight}px` };\n } else if (closed) {\n style = { height: 0, marginTop: 0, zIndex: -1 };\n } else {\n style = {};\n }\n\n const safeContent = DOMPurify.sanitize(content, {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\"],\n ALLOWED_URI_REGEXP: /^\\/[^/]/,\n });\n\n const withIcons: Record<FlashPropsType, IconName | \"\"> = {\n notice: \"icon-gui-ably-badge\",\n success: \"icon-gui-check-outline\",\n error: \"icon-gui-exclamation-triangle-outline\",\n alert: \"icon-gui-exclamation-triangle-outline\",\n info: \"\",\n };\n\n const iconColor: Record<FlashPropsType, ColorClass | \"\"> = {\n notice: \"text-cool-black\",\n success: \"text-cool-black\",\n error: \"text-white\",\n alert: \"text-white\",\n info: \"\",\n };\n\n return (\n <div\n className={`ui-flash-message ui-grid-px ${\n animateEntry ? \"ui-flash-message-enter\" : \"\"\n }`}\n style={style}\n ref={ref}\n data-id=\"ui-flash\"\n data-testid=\"ui-flash\"\n >\n <div\n className={`${FLASH_BG_COLOR[type]} p-8 flex align-center rounded shadow-container-subtle`}\n >\n {withIcons[type] && iconColor[type] && (\n <Icon\n name={withIcons[type]}\n color={iconColor[type]}\n size=\"1.5rem\"\n additionalCSS=\"mr-4 self-baseline\"\n />\n )}\n <p\n className={`ui-text-p1 mr-4 ${FLASH_TEXT_COLOR[type]}`}\n // Sanitised inline-markup allowlist (a + relative href) applied above\n // via DOMPurify. Slice 3a replaces the local config with the shared\n // sanitizeInlineMarkup helper.\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: safeContent }}\n />\n <button\n type=\"button\"\n className=\"p-0 ml-auto self-start focus:outline-none focus-base\"\n onClick={closeFlash}\n >\n {iconColor[type] && (\n <Icon\n name=\"icon-gui-x-mark-outline\"\n color={iconColor[type]}\n size=\"1.5rem\"\n additionalCSS=\"transition-colors\"\n />\n )}\n </button>\n </div>\n </div>\n );\n};\n\n/**\n * Flashes - Container component that renders all active flash messages.\n *\n * Reads from FlashContext and displays each flash message in order.\n * Use this component where you want flash messages to appear in your layout\n * (typically near the top of the page). Filters out removed messages.\n */\nconst Flashes = () => {\n const { flashes } = useFlashContext();\n\n return (\n <div className=\"ui-flash\" data-id={FLASH_DATA_ID}>\n {flashes\n .filter((item) => !item.removed)\n .map((flash) => (\n <Flash key={flash.id} {...flash} />\n ))}\n </div>\n );\n};\n\n/**\n * BackendFlashes - Integration component for server-side flash messages (default export).\n *\n * Receives flash messages from backend as an array of [type, content] tuples and adds\n * them to the FlashContext on mount. Primary use case is hydrating flash messages from\n * Rails or other backend frameworks. Renders the Flashes component to display messages.\n * Must be used within FlashProvider.\n */\nconst BackendFlashes = ({ flashes }: BackendFlashesProps) => {\n const context = useContext(FlashContext);\n const addFlashes = context?.addFlashes;\n\n useEffect(() => {\n if (!addFlashes) {\n console.warn(\"BackendFlashes must be used within FlashProvider\");\n return;\n }\n\n const transformedFlashes = flashes.map((flash) => {\n const [type, content] = flash;\n return { type: type as FlashPropsType, content };\n });\n\n if (transformedFlashes.length > 0) {\n addFlashes(transformedFlashes);\n }\n }, [flashes, addFlashes]);\n\n if (!context) return null;\n\n return <Flashes />;\n};\n\nexport { FLASH_DATA_ID, Flashes, FlashProvider, useFlashContext };\nexport default BackendFlashes;\n"],"names":["React","useEffect","useState","useRef","createContext","useContext","useCallback","useMemo","DOMPurify","Icon","FLASH_DATA_ID","FlashContext","undefined","FlashProvider","children","flashes","setFlashes","removeFlash","flashId","prev","filter","item","id","addFlashes","newFlashes","withIds","flash","some","existing","content","type","map","Math","random","toString","slice","removed","contextValue","Provider","value","useFlashContext","context","Error","FLASH_BG_COLOR","error","success","notice","info","alert","FLASH_TEXT_COLOR","AUTO_HIDE","AUTO_HIDE_TIME","useAutoHide","closeFlash","timeoutId","includes","current","setTimeout","clearTimeout","Flash","ref","closed","setClosed","flashHeight","setFlashHeight","getBoundingClientRect","height","animateEntry","style","marginTop","zIndex","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","ALLOWED_URI_REGEXP","withIcons","iconColor","div","className","data-id","data-testid","name","color","size","additionalCSS","p","dangerouslySetInnerHTML","__html","button","onClick","Flashes","key","BackendFlashes","console","warn","transformedFlashes","length"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/Flash.tsx"],"sourcesContent":["import React, {\n useEffect,\n useState,\n useRef,\n createContext,\n useContext,\n useCallback,\n useMemo,\n PropsWithChildren,\n} from \"react\";\nimport DOMPurify from \"dompurify\";\nimport Icon from \"./Icon\";\nimport { ColorClass } from \"./styles/colors/types\";\nimport { IconName } from \"./Icon/types\";\n\ntype FlashPropsType = \"error\" | \"success\" | \"notice\" | \"info\" | \"alert\";\n\ntype FlashProps = {\n id: string;\n removed: boolean;\n type: FlashPropsType;\n content: string;\n removeFlash: (id: string) => void;\n};\n\ntype BackendFlashesProps = {\n flashes: string[][];\n};\n\nconst FLASH_DATA_ID = \"ui-flashes\";\n\ntype FlashContextType = {\n flashes: FlashProps[];\n addFlashes: (flashes: Pick<FlashProps, \"type\" | \"content\">[]) => void;\n removeFlash: (id: string) => void;\n};\n\nconst FlashContext = createContext<FlashContextType | undefined>(undefined);\n\ntype FlashProviderProps = PropsWithChildren;\n\n/**\n * FlashProvider - Context provider for managing flash messages throughout the application.\n *\n * Maintains a global list of flash messages and provides methods to add/remove them.\n * Automatically deduplicates messages with the same type and content to prevent duplicates.\n * Use this at the app root level and access via useFlashContext() in child components.\n */\nconst FlashProvider = ({ children }: FlashProviderProps) => {\n const [flashes, setFlashes] = useState<FlashProps[]>([]);\n\n const removeFlash = useCallback((flashId: string) => {\n setFlashes((prev) => prev.filter((item) => item.id !== flashId));\n }, []);\n\n const addFlashes = useCallback(\n (newFlashes: Pick<FlashProps, \"type\" | \"content\">[]) => {\n setFlashes((prev) => {\n const withIds = newFlashes\n .filter(\n (flash) =>\n !prev.some(\n (existing) =>\n existing.content === flash.content &&\n existing.type === flash.type,\n ),\n )\n .map((flash) => ({\n ...flash,\n id: Math.random().toString(36).slice(2),\n removed: false,\n removeFlash,\n }));\n\n return [...prev, ...withIds];\n });\n },\n [removeFlash],\n );\n\n const contextValue = useMemo(\n () => ({ flashes, addFlashes, removeFlash }),\n [flashes, addFlashes, removeFlash],\n );\n\n return (\n <FlashContext.Provider value={contextValue}>\n {children}\n </FlashContext.Provider>\n );\n};\n\nconst useFlashContext = () => {\n const context = useContext(FlashContext);\n if (context === undefined) {\n throw new Error(\"useFlashContext must be used within FlashProvider\");\n }\n return context;\n};\n\nconst FLASH_BG_COLOR = {\n error: \"bg-gui-error\",\n success: \"bg-zingy-green\",\n notice: \"bg-electric-cyan\",\n info: \"bg-electric-cyan\",\n alert: \"bg-active-orange\",\n};\n\nconst FLASH_TEXT_COLOR = {\n error: \"text-white\",\n success: \"text-cool-black\",\n notice: \"text-cool-black\",\n info: \"text-cool-black\",\n alert: \"text-white\",\n};\n\nconst AUTO_HIDE = [\"success\", \"info\", \"notice\"];\nconst AUTO_HIDE_TIME = 8000;\n\nconst useAutoHide = (type: string, closeFlash: () => void) => {\n const timeoutId = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (AUTO_HIDE.includes(type)) {\n timeoutId.current = setTimeout(() => {\n closeFlash();\n }, AUTO_HIDE_TIME);\n }\n\n return () => {\n if (timeoutId.current) {\n clearTimeout(timeoutId.current);\n }\n };\n }, [type, closeFlash]);\n};\n\n/**\n * Flash - Individual flash message component with animations and auto-dismiss.\n *\n * Displays a colored notification banner with an icon, message content, and close button.\n * Success/info/notice messages auto-hide after 8 seconds. Error/alert messages require\n * manual dismissal. Uses CSS animations for smooth entry/exit and height transitions\n * on close. Content is sanitized with DOMPurify to allow safe HTML links from backend.\n */\nconst Flash = ({ id, type, content, removeFlash }: FlashProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [closed, setClosed] = useState(false);\n const [flashHeight, setFlashHeight] = useState(0);\n\n const closeFlash = () => {\n if (ref.current) {\n setFlashHeight(ref.current.getBoundingClientRect().height);\n }\n\n setClosed(true);\n\n setTimeout(() => {\n if (id) {\n removeFlash(id);\n }\n }, 100);\n };\n\n useAutoHide(type, closeFlash);\n\n const animateEntry = !closed;\n\n let style;\n\n if (flashHeight && !closed) {\n style = { height: `${flashHeight}px` };\n } else if (closed) {\n style = { height: 0, marginTop: 0, zIndex: -1 };\n } else {\n style = {};\n }\n\n const safeContent = DOMPurify.sanitize(content, {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\"],\n ALLOWED_URI_REGEXP: /^\\/[^/]/,\n });\n\n const withIcons: Record<FlashPropsType, IconName | \"\"> = {\n notice: \"icon-gui-ably-badge\",\n success: \"icon-gui-check-outline\",\n error: \"icon-gui-exclamation-triangle-outline\",\n alert: \"icon-gui-exclamation-triangle-outline\",\n info: \"\",\n };\n\n const iconColor: Record<FlashPropsType, ColorClass | \"\"> = {\n notice: \"text-cool-black\",\n success: \"text-cool-black\",\n error: \"text-white\",\n alert: \"text-white\",\n info: \"\",\n };\n\n return (\n <div\n className={`ui-flash-message ui-grid-px ${\n animateEntry ? \"ui-flash-message-enter\" : \"\"\n }`}\n style={style}\n ref={ref}\n data-id=\"ui-flash\"\n data-testid=\"ui-flash\"\n >\n <div\n className={`${FLASH_BG_COLOR[type]} p-8 flex align-center rounded shadow-container-subtle`}\n >\n {withIcons[type] && iconColor[type] && (\n <Icon\n name={withIcons[type]}\n color={iconColor[type]}\n size=\"1.5rem\"\n additionalCSS=\"mr-4 self-baseline\"\n />\n )}\n <p\n className={`ui-text-p1 mr-4 ${FLASH_TEXT_COLOR[type]}`}\n // Sanitised inline-markup allowlist (a + relative href) applied above\n // via DOMPurify. Slice 3a replaces the local config with the shared\n // sanitizeInlineMarkup helper.\n // oxlint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: safeContent }}\n />\n <button\n type=\"button\"\n className=\"p-0 ml-auto self-start focus:outline-none focus-base\"\n onClick={closeFlash}\n >\n {iconColor[type] && (\n <Icon\n name=\"icon-gui-x-mark-outline\"\n color={iconColor[type]}\n size=\"1.5rem\"\n additionalCSS=\"transition-colors\"\n />\n )}\n </button>\n </div>\n </div>\n );\n};\n\n/**\n * Flashes - Container component that renders all active flash messages.\n *\n * Reads from FlashContext and displays each flash message in order.\n * Use this component where you want flash messages to appear in your layout\n * (typically near the top of the page). Filters out removed messages.\n */\nconst Flashes = () => {\n const { flashes } = useFlashContext();\n\n return (\n <div className=\"ui-flash\" data-id={FLASH_DATA_ID}>\n {flashes\n .filter((item) => !item.removed)\n .map((flash) => (\n <Flash key={flash.id} {...flash} />\n ))}\n </div>\n );\n};\n\n/**\n * BackendFlashes - Integration component for server-side flash messages (default export).\n *\n * Receives flash messages from backend as an array of [type, content] tuples and adds\n * them to the FlashContext on mount. Primary use case is hydrating flash messages from\n * Rails or other backend frameworks. Renders the Flashes component to display messages.\n * Must be used within FlashProvider.\n */\nconst BackendFlashes = ({ flashes }: BackendFlashesProps) => {\n const context = useContext(FlashContext);\n const addFlashes = context?.addFlashes;\n\n useEffect(() => {\n if (!addFlashes) {\n console.warn(\"BackendFlashes must be used within FlashProvider\");\n return;\n }\n\n const transformedFlashes = flashes.map((flash) => {\n const [type, content] = flash;\n return { type: type as FlashPropsType, content };\n });\n\n if (transformedFlashes.length > 0) {\n addFlashes(transformedFlashes);\n }\n }, [flashes, addFlashes]);\n\n if (!context) return null;\n\n return <Flashes />;\n};\n\nexport { FLASH_DATA_ID, Flashes, FlashProvider, useFlashContext };\nexport default BackendFlashes;\n"],"names":["React","useEffect","useState","useRef","createContext","useContext","useCallback","useMemo","DOMPurify","Icon","FLASH_DATA_ID","FlashContext","undefined","FlashProvider","children","flashes","setFlashes","removeFlash","flashId","prev","filter","item","id","addFlashes","newFlashes","withIds","flash","some","existing","content","type","map","Math","random","toString","slice","removed","contextValue","Provider","value","useFlashContext","context","Error","FLASH_BG_COLOR","error","success","notice","info","alert","FLASH_TEXT_COLOR","AUTO_HIDE","AUTO_HIDE_TIME","useAutoHide","closeFlash","timeoutId","includes","current","setTimeout","clearTimeout","Flash","ref","closed","setClosed","flashHeight","setFlashHeight","getBoundingClientRect","height","animateEntry","style","marginTop","zIndex","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","ALLOWED_URI_REGEXP","withIcons","iconColor","div","className","data-id","data-testid","name","color","size","additionalCSS","p","dangerouslySetInnerHTML","__html","button","onClick","Flashes","key","BackendFlashes","console","warn","transformedFlashes","length"],"mappings":"AAAA,OAAOA,OACLC,SAAS,CACTC,QAAQ,CACRC,MAAM,CACNC,aAAa,CACbC,UAAU,CACVC,WAAW,CACXC,OAAO,KAEF,OAAQ,AACf,QAAOC,cAAe,WAAY,AAClC,QAAOC,SAAU,QAAS,CAkB1B,MAAMC,cAAgB,aAQtB,MAAMC,aAAeP,cAA4CQ,WAWjE,MAAMC,cAAgB,CAAC,CAAEC,QAAQ,CAAsB,IACrD,KAAM,CAACC,QAASC,WAAW,CAAGd,SAAuB,EAAE,EAEvD,MAAMe,YAAcX,YAAY,AAACY,UAC/BF,WAAW,AAACG,MAASA,KAAKC,MAAM,CAAC,AAACC,MAASA,KAAKC,EAAE,GAAKJ,SACzD,EAAG,EAAE,EAEL,MAAMK,WAAajB,YACjB,AAACkB,aACCR,WAAW,AAACG,OACV,MAAMM,QAAUD,WACbJ,MAAM,CACL,AAACM,OACC,CAACP,KAAKQ,IAAI,CACR,AAACC,UACCA,SAASC,OAAO,GAAKH,MAAMG,OAAO,EAClCD,SAASE,IAAI,GAAKJ,MAAMI,IAAI,GAGnCC,GAAG,CAAC,AAACL,OAAW,CAAA,CACf,GAAGA,KAAK,CACRJ,GAAIU,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,KAAK,CAAC,GACrCC,QAAS,MACTnB,WACF,CAAA,GAEF,MAAO,IAAIE,QAASM,QAAQ,AAC9B,EACF,EACA,CAACR,YAAY,EAGf,MAAMoB,aAAe9B,QACnB,IAAO,CAAA,CAAEQ,QAASQ,WAAYN,WAAY,CAAA,EAC1C,CAACF,QAASQ,WAAYN,YAAY,EAGpC,OACE,oBAACN,aAAa2B,QAAQ,EAACC,MAAOF,cAC3BvB,SAGP,EAEA,MAAM0B,gBAAkB,KACtB,MAAMC,QAAUpC,WAAWM,cAC3B,GAAI8B,UAAY7B,UAAW,CACzB,MAAM,IAAI8B,MAAM,oDAClB,CACA,OAAOD,OACT,EAEA,MAAME,eAAiB,CACrBC,MAAO,eACPC,QAAS,iBACTC,OAAQ,mBACRC,KAAM,mBACNC,MAAO,kBACT,EAEA,MAAMC,iBAAmB,CACvBL,MAAO,aACPC,QAAS,kBACTC,OAAQ,kBACRC,KAAM,kBACNC,MAAO,YACT,EAEA,MAAME,UAAY,CAAC,UAAW,OAAQ,SAAS,CAC/C,MAAMC,eAAiB,IAEvB,MAAMC,YAAc,CAACtB,KAAcuB,cACjC,MAAMC,UAAYnD,OAA6C,MAE/DF,UAAU,KACR,GAAIiD,UAAUK,QAAQ,CAACzB,MAAO,CAC5BwB,UAAUE,OAAO,CAAGC,WAAW,KAC7BJ,YACF,EAAGF,eACL,CAEA,MAAO,KACL,GAAIG,UAAUE,OAAO,CAAE,CACrBE,aAAaJ,UAAUE,OAAO,CAChC,CACF,CACF,EAAG,CAAC1B,KAAMuB,WAAW,CACvB,EAUA,MAAMM,MAAQ,CAAC,CAAErC,EAAE,CAAEQ,IAAI,CAAED,OAAO,CAAEZ,WAAW,CAAc,IAC3D,MAAM2C,IAAMzD,OAAuB,MACnC,KAAM,CAAC0D,OAAQC,UAAU,CAAG5D,SAAS,OACrC,KAAM,CAAC6D,YAAaC,eAAe,CAAG9D,SAAS,GAE/C,MAAMmD,WAAa,KACjB,GAAIO,IAAIJ,OAAO,CAAE,CACfQ,eAAeJ,IAAIJ,OAAO,CAACS,qBAAqB,GAAGC,MAAM,CAC3D,CAEAJ,UAAU,MAEVL,WAAW,KACT,GAAInC,GAAI,CACNL,YAAYK,GACd,CACF,EAAG,IACL,EAEA8B,YAAYtB,KAAMuB,YAElB,MAAMc,aAAe,CAACN,OAEtB,IAAIO,MAEJ,GAAIL,aAAe,CAACF,OAAQ,CAC1BO,MAAQ,CAAEF,OAAQ,CAAC,EAAEH,YAAY,EAAE,CAAC,AAAC,CACvC,MAAO,GAAIF,OAAQ,CACjBO,MAAQ,CAAEF,OAAQ,EAAGG,UAAW,EAAGC,OAAQ,CAAC,CAAE,CAChD,KAAO,CACLF,MAAQ,CAAC,CACX,CAEA,MAAMG,YAAc/D,UAAUgE,QAAQ,CAAC3C,QAAS,CAC9C4C,aAAc,CAAC,IAAI,CACnBC,aAAc,CAAC,OAAQ,cAAc,CACrCC,mBAAoB,SACtB,GAEA,MAAMC,UAAmD,CACvD9B,OAAQ,sBACRD,QAAS,yBACTD,MAAO,wCACPI,MAAO,wCACPD,KAAM,EACR,EAEA,MAAM8B,UAAqD,CACzD/B,OAAQ,kBACRD,QAAS,kBACTD,MAAO,aACPI,MAAO,aACPD,KAAM,EACR,EAEA,OACE,oBAAC+B,OACCC,UAAW,CAAC,4BAA4B,EACtCZ,aAAe,yBAA2B,GAC3C,CAAC,CACFC,MAAOA,MACPR,IAAKA,IACLoB,UAAQ,WACRC,cAAY,YAEZ,oBAACH,OACCC,UAAW,CAAC,EAAEpC,cAAc,CAACb,KAAK,CAAC,sDAAsD,CAAC,EAEzF8C,SAAS,CAAC9C,KAAK,EAAI+C,SAAS,CAAC/C,KAAK,EACjC,oBAACrB,MACCyE,KAAMN,SAAS,CAAC9C,KAAK,CACrBqD,MAAON,SAAS,CAAC/C,KAAK,CACtBsD,KAAK,SACLC,cAAc,uBAGlB,oBAACC,KACCP,UAAW,CAAC,gBAAgB,EAAE9B,gBAAgB,CAACnB,KAAK,CAAC,CAAC,CAKtDyD,wBAAyB,CAAEC,OAAQjB,WAAY,IAEjD,oBAACkB,UACC3D,KAAK,SACLiD,UAAU,uDACVW,QAASrC,YAERwB,SAAS,CAAC/C,KAAK,EACd,oBAACrB,MACCyE,KAAK,0BACLC,MAAON,SAAS,CAAC/C,KAAK,CACtBsD,KAAK,SACLC,cAAc,wBAO5B,EASA,MAAMM,QAAU,KACd,KAAM,CAAE5E,OAAO,CAAE,CAAGyB,kBAEpB,OACE,oBAACsC,OAAIC,UAAU,WAAWC,UAAStE,eAChCK,QACEK,MAAM,CAAC,AAACC,MAAS,CAACA,KAAKe,OAAO,EAC9BL,GAAG,CAAC,AAACL,OACJ,oBAACiC,OAAMiC,IAAKlE,MAAMJ,EAAE,CAAG,GAAGI,KAAK,IAIzC,EAUA,MAAMmE,eAAiB,CAAC,CAAE9E,OAAO,CAAuB,IACtD,MAAM0B,QAAUpC,WAAWM,cAC3B,MAAMY,WAAakB,SAASlB,WAE5BtB,UAAU,KACR,GAAI,CAACsB,WAAY,CACfuE,QAAQC,IAAI,CAAC,oDACb,MACF,CAEA,MAAMC,mBAAqBjF,QAAQgB,GAAG,CAAC,AAACL,QACtC,KAAM,CAACI,KAAMD,QAAQ,CAAGH,MACxB,MAAO,CAAEI,KAAMA,KAAwBD,OAAQ,CACjD,GAEA,GAAImE,mBAAmBC,MAAM,CAAG,EAAG,CACjC1E,WAAWyE,mBACb,CACF,EAAG,CAACjF,QAASQ,WAAW,EAExB,GAAI,CAACkB,QAAS,OAAO,KAErB,OAAO,oBAACkD,aACV,CAEA,QAASjF,aAAa,CAAEiF,OAAO,CAAE9E,aAAa,CAAE2B,eAAe,CAAG,AAClE,gBAAeqD,cAAe"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Loader.tsx"],"sourcesContent":["import React from \"react\";\n\ntype LoaderProps = {\n size?: string;\n ringColor?: string;\n additionalCSS?: string;\n};\n\nconst Loader = ({\n ringColor = \"text-dark-grey\",\n size = \"1.5rem\",\n additionalCSS = \"\",\n}: LoaderProps) => (\n <svg\n className={`${ringColor} ${additionalCSS}`}\n style={{ width: size, height: size }}\n height=\"24\"\n viewBox=\"0 0 24 24\"\n width=\"24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <style\n // Hardcoded CSS keyframes — no caller-supplied input. Required because\n // styled-components / CSS-in-JS would force a build step on consumers.\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: `\n @keyframes chunk-animation {\n to {\n transform: rotate(360deg);\n }\n }\n\n .chunk {\n transform: rotate(0deg);\n transform-origin: center;\n animation: chunk-animation 0.6s cubic-bezier(.44,.15,.66,.98) forwards infinite;\n }\n `,\n }}\n ></style>\n <path\n fill=\"currentColor\"\n d=\"m12 1.99976c-1.9778 0-3.91121.58649-5.5557 1.6853s-2.92621 2.6606-3.68309 4.48786c-.75688 1.82728-.95491 3.83788-.56906 5.77778.38585 1.9398 1.33826 3.7216 2.73679 5.1201 1.39852 1.3985 3.18035 2.351 5.12016 2.7368 1.9398.3859 3.9505.1878 5.7777-.569 1.8273-.7569 3.3891-2.0387 4.4879-3.6831 1.0988-1.6445 1.6853-3.5779 1.6853-5.5557 0-1.3133-.2587-2.61362-.7612-3.82688-.5025-1.21325-1.2391-2.31565-2.1677-3.24423-.9286-.92859-2.031-1.66518-3.2443-2.16773-1.2132-.50255-2.5136-.7612-3.8268-.7612zm0 18.00004c-1.5822 0-3.12896-.4692-4.44456-1.3483-1.31559-.879-2.34097-2.1285-2.94647-3.5903s-.76393-3.0703-.45525-4.6222c.30868-1.55181 1.07061-2.97728 2.18943-4.0961s2.54428-1.88074 4.09615-2.18943c1.5518-.30868 3.1604-.15025 4.6222.45525s2.7112 1.63088 3.5903 2.94647c.879 1.3156 1.3482 2.86231 1.3482 4.44461 0 2.1217-.8428 4.1565-2.3431 5.6568s-3.5352 2.3432-5.6569 2.3432z\"\n opacity=\".5\"\n />\n <path\n className=\"chunk\"\n d=\"m20 11.9998h2c0-1.3133-.2587-2.61362-.7612-3.82688-.5026-1.21325-1.2391-2.31565-2.1677-3.24423-.9286-.92859-2.031-1.66518-3.2443-2.16773-1.2132-.50255-2.5136-.7612-3.8268-.7612v2c2.1217 0 4.1566.84285 5.6569 2.34314 1.5002 1.50029 2.3431 3.53512 2.3431 5.6569z\"\n fill=\"#ff5416\"\n />\n </svg>\n);\n\nexport default Loader;\n"],"names":["React","Loader","ringColor","size","additionalCSS","svg","className","style","width","height","viewBox","xmlns","dangerouslySetInnerHTML","__html","path","fill","d","opacity"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,CAQ1B,MAAMC,OAAS,CAAC,CACdC,UAAY,gBAAgB,CAC5BC,KAAO,QAAQ,CACfC,cAAgB,EAAE,CACN,GACZ,oBAACC,OACCC,UAAW,CAAC,EAAEJ,UAAU,CAAC,EAAEE,cAAc,CAAC,CAC1CG,MAAO,CAAEC,MAAOL,KAAMM,OAAQN,IAAK,EACnCM,OAAO,KACPC,QAAQ,YACRF,MAAM,KACNG,MAAM,8BAEN,oBAACJ,SAICK,wBAAyB,CACvBC,OAAQ;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,CAAC,AACC,IAEF,oBAACC,QACCC,KAAK,eACLC,EAAE,+2BACFC,QAAQ,OAEV,oBAACH,QACCR,UAAU,QACVU,EAAE,uQACFD,KAAK,YAKX,gBAAed,MAAO"}
1
+ {"version":3,"sources":["../../src/core/Loader.tsx"],"sourcesContent":["import React from \"react\";\n\ntype LoaderProps = {\n size?: string;\n ringColor?: string;\n additionalCSS?: string;\n};\n\nconst Loader = ({\n ringColor = \"text-dark-grey\",\n size = \"1.5rem\",\n additionalCSS = \"\",\n}: LoaderProps) => (\n <svg\n className={`${ringColor} ${additionalCSS}`}\n style={{ width: size, height: size }}\n height=\"24\"\n viewBox=\"0 0 24 24\"\n width=\"24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <style\n // Hardcoded CSS keyframes — no caller-supplied input. Required because\n // styled-components / CSS-in-JS would force a build step on consumers.\n // oxlint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: `\n @keyframes chunk-animation {\n to {\n transform: rotate(360deg);\n }\n }\n\n .chunk {\n transform: rotate(0deg);\n transform-origin: center;\n animation: chunk-animation 0.6s cubic-bezier(.44,.15,.66,.98) forwards infinite;\n }\n `,\n }}\n ></style>\n <path\n fill=\"currentColor\"\n d=\"m12 1.99976c-1.9778 0-3.91121.58649-5.5557 1.6853s-2.92621 2.6606-3.68309 4.48786c-.75688 1.82728-.95491 3.83788-.56906 5.77778.38585 1.9398 1.33826 3.7216 2.73679 5.1201 1.39852 1.3985 3.18035 2.351 5.12016 2.7368 1.9398.3859 3.9505.1878 5.7777-.569 1.8273-.7569 3.3891-2.0387 4.4879-3.6831 1.0988-1.6445 1.6853-3.5779 1.6853-5.5557 0-1.3133-.2587-2.61362-.7612-3.82688-.5025-1.21325-1.2391-2.31565-2.1677-3.24423-.9286-.92859-2.031-1.66518-3.2443-2.16773-1.2132-.50255-2.5136-.7612-3.8268-.7612zm0 18.00004c-1.5822 0-3.12896-.4692-4.44456-1.3483-1.31559-.879-2.34097-2.1285-2.94647-3.5903s-.76393-3.0703-.45525-4.6222c.30868-1.55181 1.07061-2.97728 2.18943-4.0961s2.54428-1.88074 4.09615-2.18943c1.5518-.30868 3.1604-.15025 4.6222.45525s2.7112 1.63088 3.5903 2.94647c.879 1.3156 1.3482 2.86231 1.3482 4.44461 0 2.1217-.8428 4.1565-2.3431 5.6568s-3.5352 2.3432-5.6569 2.3432z\"\n opacity=\".5\"\n />\n <path\n className=\"chunk\"\n d=\"m20 11.9998h2c0-1.3133-.2587-2.61362-.7612-3.82688-.5026-1.21325-1.2391-2.31565-2.1677-3.24423-.9286-.92859-2.031-1.66518-3.2443-2.16773-1.2132-.50255-2.5136-.7612-3.8268-.7612v2c2.1217 0 4.1566.84285 5.6569 2.34314 1.5002 1.50029 2.3431 3.53512 2.3431 5.6569z\"\n fill=\"#ff5416\"\n />\n </svg>\n);\n\nexport default Loader;\n"],"names":["React","Loader","ringColor","size","additionalCSS","svg","className","style","width","height","viewBox","xmlns","dangerouslySetInnerHTML","__html","path","fill","d","opacity"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,CAQ1B,MAAMC,OAAS,CAAC,CACdC,UAAY,gBAAgB,CAC5BC,KAAO,QAAQ,CACfC,cAAgB,EAAE,CACN,GACZ,oBAACC,OACCC,UAAW,CAAC,EAAEJ,UAAU,CAAC,EAAEE,cAAc,CAAC,CAC1CG,MAAO,CAAEC,MAAOL,KAAMM,OAAQN,IAAK,EACnCM,OAAO,KACPC,QAAQ,YACRF,MAAM,KACNG,MAAM,8BAEN,oBAACJ,SAICK,wBAAyB,CACvBC,OAAQ;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,CAAC,AACC,IAEF,oBAACC,QACCC,KAAK,eACLC,EAAE,+2BACFC,QAAQ,OAEV,oBAACH,QACCR,UAAU,QACVU,EAAE,uQACFD,KAAK,YAKX,gBAAed,MAAO"}
@@ -1,2 +1,2 @@
1
- import React from"react";import{PanelTitle}from"./PanelTitle";import Badge from"../Badge";import MeganavPanelItemLinks from"./MeganavPanelItemLinks";const getCategoryColor=category=>{const upperCategory=category.toUpperCase();if(["NEW RELEASE","ABLY ENGINEERING","ABLY NEWS","NEW FEATURE","REALTIME EXPERIENCES"].includes(upperCategory))return"orange";if(["CHAT","SPACES"].includes(upperCategory))return"blue";if(["LIVEOBJECTS","LIVESYNC"].includes(upperCategory))return"green";if(upperCategory==="PUBSUB")return"pink";if(upperCategory==="AI TRANSPORT")return"violet";return"neutral"};const MeganavBlog=({title,link,icon,posts})=>{return React.createElement(React.Fragment,null,React.createElement("div",{className:"mt-3 hidden md:block"},React.createElement(PanelTitle,{title:title,link:link}),posts.map(post=>React.createElement("a",{href:post.link,className:"flex flex-col gap-1 p-3 transition-colors group/blog-post rounded-lg hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100 focus-base",key:post.link},React.createElement("span",{className:"flex flex-wrap gap-2"},post.categories.map(category=>React.createElement(Badge,{color:getCategoryColor(category),key:category,size:"xs",className:"group-hover/blog-post:bg-neutral-000 dark:group-hover/blog-post:bg-neutral-1300"},category.toUpperCase()))),React.createElement("span",{className:"ui-text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 group-hover/blog-post:text-neutral-1300 dark:group-hover/blog-post:text-neutral-000"},post.title),React.createElement("span",{className:"text-[11px] font-medium leading-[1.4] text-neutral-700 dark:text-neutral-600"},post.pubDate)))),React.createElement("div",{className:"block md:hidden"},React.createElement(MeganavPanelItemLinks,{listItems:[{label:title,link:link,icon:icon}]})))};export default MeganavBlog;
1
+ import React from"react";import{PanelTitle}from"./PanelTitle";import Badge from"../Badge";import MeganavPanelItemLinks from"./MeganavPanelItemLinks";const getCategoryColor=category=>{const upperCategory=category.toUpperCase();if(["NEW RELEASE","ABLY ENGINEERING","ABLY NEWS","NEW FEATURE","REALTIME EXPERIENCES"].includes(upperCategory))return"orange";if(["CHAT","SPACES"].includes(upperCategory))return"blue";if(["LIVEOBJECTS","LIVESYNC"].includes(upperCategory))return"green";if(upperCategory==="PUBSUB")return"pink";if(upperCategory==="AI TRANSPORT")return"violet";return"neutral"};const MeganavBlog=({title,link,icon,posts})=>{return React.createElement(React.Fragment,null,React.createElement("div",{className:"mt-3 hidden md:block"},React.createElement(PanelTitle,{title:title,link:link}),posts.map(post=>React.createElement("a",{href:post.link,className:"flex flex-col gap-1 p-3 \n transition-colors group/blog-post rounded-lg\n hover:bg-neutral-100 dark:hover:bg-neutral-1200 \n active:bg-neutral-200 dark:active:bg-neutral-1100 focus-base",key:post.link},React.createElement("span",{className:"flex flex-wrap gap-2"},post.categories.map(category=>React.createElement(Badge,{color:getCategoryColor(category),key:category,size:"xs",className:"group-hover/blog-post:bg-neutral-000 dark:group-hover/blog-post:bg-neutral-1300"},category.toUpperCase()))),React.createElement("span",{className:"ui-text-label3 font-semibold text-neutral-1000 dark:text-neutral-300\n group-hover/blog-post:text-neutral-1300 dark:group-hover/blog-post:text-neutral-000"},post.title),React.createElement("span",{className:"text-[11px] font-medium leading-[1.4] text-neutral-700 dark:text-neutral-600"},post.pubDate)))),React.createElement("div",{className:"block md:hidden"},React.createElement(MeganavPanelItemLinks,{listItems:[{label:title,link:link,icon:icon}]})))};export default MeganavBlog;
2
2
  //# sourceMappingURL=MeganavBlog.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Meganav/MeganavBlog.tsx"],"sourcesContent":["import React from \"react\";\nimport { PanelTitle } from \"./PanelTitle\";\nimport Badge from \"../Badge\";\n\nimport { ColorClassColorGroups } from \"../styles/colors/types\";\nimport MeganavPanelItemLinks from \"./MeganavPanelItemLinks\";\nimport { IconName } from \"../Icon/types\";\n\nexport type BlogPost = {\n title: string;\n link: string;\n categories: string[];\n pubDate: string;\n};\n\nexport type MeganavBlogProps = {\n title: string;\n link: string;\n icon?: IconName;\n posts: BlogPost[];\n};\n\nconst getCategoryColor = (category: string): ColorClassColorGroups => {\n const upperCategory = category.toUpperCase();\n if (\n [\n \"NEW RELEASE\",\n \"ABLY ENGINEERING\",\n \"ABLY NEWS\",\n \"NEW FEATURE\",\n \"REALTIME EXPERIENCES\",\n ].includes(upperCategory)\n )\n return \"orange\";\n if ([\"CHAT\", \"SPACES\"].includes(upperCategory)) return \"blue\";\n if ([\"LIVEOBJECTS\", \"LIVESYNC\"].includes(upperCategory)) return \"green\";\n if (upperCategory === \"PUBSUB\") return \"pink\";\n if (upperCategory === \"AI TRANSPORT\") return \"violet\";\n return \"neutral\";\n};\n\nconst MeganavBlog = ({ title, link, icon, posts }: MeganavBlogProps) => {\n return (\n <>\n <div className=\"mt-3 hidden md:block\">\n <PanelTitle title={title} link={link} />\n {posts.map((post) => (\n <a\n href={post.link}\n className=\"flex flex-col gap-1 p-3 \n transition-colors group/blog-post rounded-lg\n hover:bg-neutral-100 dark:hover:bg-neutral-1200 \n active:bg-neutral-200 dark:active:bg-neutral-1100 focus-base\"\n key={post.link}\n >\n <span className=\"flex flex-wrap gap-2\">\n {post.categories.map((category: string) => (\n <Badge\n color={getCategoryColor(category)}\n key={category}\n size=\"xs\"\n className=\"group-hover/blog-post:bg-neutral-000 dark:group-hover/blog-post:bg-neutral-1300\"\n >\n {category.toUpperCase()}\n </Badge>\n ))}\n </span>\n <span\n className=\"ui-text-label3 font-semibold text-neutral-1000 dark:text-neutral-300\n group-hover/blog-post:text-neutral-1300 dark:group-hover/blog-post:text-neutral-000\"\n >\n {post.title}\n </span>\n\n <span className=\"text-[11px] font-medium leading-[1.4] text-neutral-700 dark:text-neutral-600\">\n {post.pubDate}\n </span>\n </a>\n ))}\n </div>\n <div className=\"block md:hidden\">\n <MeganavPanelItemLinks\n listItems={[\n {\n label: title,\n link: link,\n icon: icon,\n },\n ]}\n />\n </div>\n </>\n );\n};\n\nexport default MeganavBlog;\n"],"names":["React","PanelTitle","Badge","MeganavPanelItemLinks","getCategoryColor","category","upperCategory","toUpperCase","includes","MeganavBlog","title","link","icon","posts","div","className","map","post","a","href","key","span","categories","color","size","pubDate","listItems","label"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAASC,UAAU,KAAQ,cAAe,AAC1C,QAAOC,UAAW,UAAW,AAG7B,QAAOC,0BAA2B,yBAA0B,CAiB5D,MAAMC,iBAAmB,AAACC,WACxB,MAAMC,cAAgBD,SAASE,WAAW,GAC1C,GACE,CACE,cACA,mBACA,YACA,cACA,uBACD,CAACC,QAAQ,CAACF,eAEX,MAAO,SACT,GAAI,CAAC,OAAQ,SAAS,CAACE,QAAQ,CAACF,eAAgB,MAAO,OACvD,GAAI,CAAC,cAAe,WAAW,CAACE,QAAQ,CAACF,eAAgB,MAAO,QAChE,GAAIA,gBAAkB,SAAU,MAAO,OACvC,GAAIA,gBAAkB,eAAgB,MAAO,SAC7C,MAAO,SACT,EAEA,MAAMG,YAAc,CAAC,CAAEC,KAAK,CAAEC,IAAI,CAAEC,IAAI,CAAEC,KAAK,CAAoB,IACjE,OACE,wCACE,oBAACC,OAAIC,UAAU,wBACb,oBAACd,YAAWS,MAAOA,MAAOC,KAAMA,OAC/BE,MAAMG,GAAG,CAAC,AAACC,MACV,oBAACC,KACCC,KAAMF,KAAKN,IAAI,CACfI,UAAU,uLAIVK,IAAKH,KAAKN,IAAI,EAEd,oBAACU,QAAKN,UAAU,wBACbE,KAAKK,UAAU,CAACN,GAAG,CAAC,AAACX,UACpB,oBAACH,OACCqB,MAAOnB,iBAAiBC,UACxBe,IAAKf,SACLmB,KAAK,KACLT,UAAU,mFAETV,SAASE,WAAW,MAI3B,oBAACc,QACCN,UAAU,4JAGTE,KAAKP,KAAK,EAGb,oBAACW,QAAKN,UAAU,gFACbE,KAAKQ,OAAO,KAKrB,oBAACX,OAAIC,UAAU,mBACb,oBAACZ,uBACCuB,UAAW,CACT,CACEC,MAAOjB,MACPC,KAAMA,KACNC,KAAMA,IACR,EACD,IAKX,CAEA,gBAAeH,WAAY"}
1
+ {"version":3,"sources":["../../../src/core/Meganav/MeganavBlog.tsx"],"sourcesContent":["import React from \"react\";\nimport { PanelTitle } from \"./PanelTitle\";\nimport Badge from \"../Badge\";\n\nimport { ColorClassColorGroups } from \"../styles/colors/types\";\nimport MeganavPanelItemLinks from \"./MeganavPanelItemLinks\";\nimport { IconName } from \"../Icon/types\";\n\nexport type BlogPost = {\n title: string;\n link: string;\n categories: string[];\n pubDate: string;\n};\n\nexport type MeganavBlogProps = {\n title: string;\n link: string;\n icon?: IconName;\n posts: BlogPost[];\n};\n\nconst getCategoryColor = (category: string): ColorClassColorGroups => {\n const upperCategory = category.toUpperCase();\n if (\n [\n \"NEW RELEASE\",\n \"ABLY ENGINEERING\",\n \"ABLY NEWS\",\n \"NEW FEATURE\",\n \"REALTIME EXPERIENCES\",\n ].includes(upperCategory)\n )\n return \"orange\";\n if ([\"CHAT\", \"SPACES\"].includes(upperCategory)) return \"blue\";\n if ([\"LIVEOBJECTS\", \"LIVESYNC\"].includes(upperCategory)) return \"green\";\n if (upperCategory === \"PUBSUB\") return \"pink\";\n if (upperCategory === \"AI TRANSPORT\") return \"violet\";\n return \"neutral\";\n};\n\nconst MeganavBlog = ({ title, link, icon, posts }: MeganavBlogProps) => {\n return (\n <>\n <div className=\"mt-3 hidden md:block\">\n <PanelTitle title={title} link={link} />\n {posts.map((post) => (\n <a\n href={post.link}\n className=\"flex flex-col gap-1 p-3 \n transition-colors group/blog-post rounded-lg\n hover:bg-neutral-100 dark:hover:bg-neutral-1200 \n active:bg-neutral-200 dark:active:bg-neutral-1100 focus-base\"\n key={post.link}\n >\n <span className=\"flex flex-wrap gap-2\">\n {post.categories.map((category: string) => (\n <Badge\n color={getCategoryColor(category)}\n key={category}\n size=\"xs\"\n className=\"group-hover/blog-post:bg-neutral-000 dark:group-hover/blog-post:bg-neutral-1300\"\n >\n {category.toUpperCase()}\n </Badge>\n ))}\n </span>\n <span\n className=\"ui-text-label3 font-semibold text-neutral-1000 dark:text-neutral-300\n group-hover/blog-post:text-neutral-1300 dark:group-hover/blog-post:text-neutral-000\"\n >\n {post.title}\n </span>\n\n <span className=\"text-[11px] font-medium leading-[1.4] text-neutral-700 dark:text-neutral-600\">\n {post.pubDate}\n </span>\n </a>\n ))}\n </div>\n <div className=\"block md:hidden\">\n <MeganavPanelItemLinks\n listItems={[\n {\n label: title,\n link: link,\n icon: icon,\n },\n ]}\n />\n </div>\n </>\n );\n};\n\nexport default MeganavBlog;\n"],"names":["React","PanelTitle","Badge","MeganavPanelItemLinks","getCategoryColor","category","upperCategory","toUpperCase","includes","MeganavBlog","title","link","icon","posts","div","className","map","post","a","href","key","span","categories","color","size","pubDate","listItems","label"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAASC,UAAU,KAAQ,cAAe,AAC1C,QAAOC,UAAW,UAAW,AAG7B,QAAOC,0BAA2B,yBAA0B,CAiB5D,MAAMC,iBAAmB,AAACC,WACxB,MAAMC,cAAgBD,SAASE,WAAW,GAC1C,GACE,CACE,cACA,mBACA,YACA,cACA,uBACD,CAACC,QAAQ,CAACF,eAEX,MAAO,SACT,GAAI,CAAC,OAAQ,SAAS,CAACE,QAAQ,CAACF,eAAgB,MAAO,OACvD,GAAI,CAAC,cAAe,WAAW,CAACE,QAAQ,CAACF,eAAgB,MAAO,QAChE,GAAIA,gBAAkB,SAAU,MAAO,OACvC,GAAIA,gBAAkB,eAAgB,MAAO,SAC7C,MAAO,SACT,EAEA,MAAMG,YAAc,CAAC,CAAEC,KAAK,CAAEC,IAAI,CAAEC,IAAI,CAAEC,KAAK,CAAoB,IACjE,OACE,wCACE,oBAACC,OAAIC,UAAU,wBACb,oBAACd,YAAWS,MAAOA,MAAOC,KAAMA,OAC/BE,MAAMG,GAAG,CAAC,AAACC,MACV,oBAACC,KACCC,KAAMF,KAAKN,IAAI,CACfI,UAAU,gNAIVK,IAAKH,KAAKN,IAAI,EAEd,oBAACU,QAAKN,UAAU,wBACbE,KAAKK,UAAU,CAACN,GAAG,CAAC,AAACX,UACpB,oBAACH,OACCqB,MAAOnB,iBAAiBC,UACxBe,IAAKf,SACLmB,KAAK,KACLT,UAAU,mFAETV,SAASE,WAAW,MAI3B,oBAACc,QACCN,UAAU,uKAGTE,KAAKP,KAAK,EAGb,oBAACW,QAAKN,UAAU,gFACbE,KAAKQ,OAAO,KAKrB,oBAACX,OAAIC,UAAU,mBACb,oBAACZ,uBACCuB,UAAW,CACT,CACEC,MAAOjB,MACPC,KAAMA,KACNC,KAAMA,IACR,EACD,IAKX,CAEA,gBAAeH,WAAY"}
@@ -1,2 +1,2 @@
1
- import React from"react";import{PanelTitle}from"./PanelTitle";import MeganavPanelItemLinks from"./MeganavPanelItemLinks";const MeganavCustomerStories=({customerStoriesHighlight,title,link,icon})=>{const{companyName,companyDesc,companyLink,companyLogo,companyLogoDark}=customerStoriesHighlight;return React.createElement(React.Fragment,null,React.createElement("div",{className:"mt-3 hidden md:block"},React.createElement(PanelTitle,{title:title,link:link}),React.createElement("a",{href:companyLink,className:"flex flex-col gap-y-2.5 p-3 pointer-events-auto rounded-lg transition-colors group/customer-story-highlight hover:bg-neutral-100 dark:hover:bg-neutral-1200 focus-base active:bg-neutral-200 dark:active:bg-neutral-1100"},React.createElement("figure",{className:"rounded bg-neutral-100 dark:bg-neutral-1200 group-hover/customer-story-highlight:bg-neutral-000 dark:group-hover/customer-story-highlight:bg-neutral-1300 flex justify-center items-center gap-4 h-[120px]"},React.createElement("img",{src:companyLogo,alt:companyName,className:"max-h-[90px] max-w-[180px] dark:hidden"}),companyLogoDark&&React.createElement("img",{src:companyLogoDark,alt:companyName,className:"max-h-[90px] max-w-[180px] hidden dark:block"})),React.createElement("span",{className:"flex flex-col gap-2"},React.createElement("span",{className:"ui-text-p4 text-neutral-1000 dark:text-neutral-300"},React.createElement("strong",{className:"font-semibold text-neutral-1300 dark:text-neutral-000"},companyName)," ",companyDesc)))),React.createElement("div",{className:"block md:hidden"},React.createElement(MeganavPanelItemLinks,{listItems:[{label:title,link:link,icon:icon}]})))};export default MeganavCustomerStories;
1
+ import React from"react";import{PanelTitle}from"./PanelTitle";import MeganavPanelItemLinks from"./MeganavPanelItemLinks";const MeganavCustomerStories=({customerStoriesHighlight,title,link,icon})=>{const{companyName,companyDesc,companyLink,companyLogo,companyLogoDark}=customerStoriesHighlight;return React.createElement(React.Fragment,null,React.createElement("div",{className:"mt-3 hidden md:block"},React.createElement(PanelTitle,{title:title,link:link}),React.createElement("a",{href:companyLink,className:"flex flex-col gap-y-2.5 p-3 pointer-events-auto rounded-lg\n transition-colors group/customer-story-highlight \n hover:bg-neutral-100 dark:hover:bg-neutral-1200 focus-base\n active:bg-neutral-200 dark:active:bg-neutral-1100"},React.createElement("figure",{className:"rounded bg-neutral-100 dark:bg-neutral-1200 \n group-hover/customer-story-highlight:bg-neutral-000 \n dark:group-hover/customer-story-highlight:bg-neutral-1300\n flex justify-center items-center gap-4 h-[120px]"},React.createElement("img",{src:companyLogo,alt:companyName,className:"max-h-[90px] max-w-[180px] dark:hidden"}),companyLogoDark&&React.createElement("img",{src:companyLogoDark,alt:companyName,className:"max-h-[90px] max-w-[180px] hidden dark:block"})),React.createElement("span",{className:"flex flex-col gap-2"},React.createElement("span",{className:"ui-text-p4 text-neutral-1000 dark:text-neutral-300"},React.createElement("strong",{className:"font-semibold text-neutral-1300 dark:text-neutral-000"},companyName)," ",companyDesc)))),React.createElement("div",{className:"block md:hidden"},React.createElement(MeganavPanelItemLinks,{listItems:[{label:title,link:link,icon:icon}]})))};export default MeganavCustomerStories;
2
2
  //# sourceMappingURL=MeganavCustomerStories.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Meganav/MeganavCustomerStories.tsx"],"sourcesContent":["import React from \"react\";\nimport { PanelTitle } from \"./PanelTitle\";\nimport MeganavPanelItemLinks from \"./MeganavPanelItemLinks\";\nimport { IconName } from \"../Icon/types\";\n\nexport type CustomerStoryHighlight = {\n companyName: string;\n companyDesc: string;\n companyLink: string;\n companyLogo: string;\n companyLogoDark?: string;\n};\n\nconst MeganavCustomerStories = ({\n customerStoriesHighlight,\n title,\n link,\n icon,\n}: {\n customerStoriesHighlight: CustomerStoryHighlight;\n title: string;\n link: string;\n icon?: IconName;\n}) => {\n const {\n companyName,\n companyDesc,\n companyLink,\n companyLogo,\n companyLogoDark,\n } = customerStoriesHighlight;\n return (\n <>\n <div className=\"mt-3 hidden md:block\">\n <PanelTitle title={title} link={link} />\n <a\n href={companyLink}\n className=\"flex flex-col gap-y-2.5 p-3 pointer-events-auto rounded-lg\n transition-colors group/customer-story-highlight \n hover:bg-neutral-100 dark:hover:bg-neutral-1200 focus-base\n active:bg-neutral-200 dark:active:bg-neutral-1100\"\n >\n <figure\n className=\"rounded bg-neutral-100 dark:bg-neutral-1200 \n group-hover/customer-story-highlight:bg-neutral-000 \n dark:group-hover/customer-story-highlight:bg-neutral-1300\n flex justify-center items-center gap-4 h-[120px]\"\n >\n <img\n src={companyLogo}\n alt={companyName}\n className=\"max-h-[90px] max-w-[180px] dark:hidden\"\n />\n {companyLogoDark && (\n <img\n src={companyLogoDark}\n alt={companyName}\n className=\"max-h-[90px] max-w-[180px] hidden dark:block\"\n />\n )}\n </figure>\n <span className=\"flex flex-col gap-2\">\n <span className=\"ui-text-p4 text-neutral-1000 dark:text-neutral-300\">\n <strong className=\"font-semibold text-neutral-1300 dark:text-neutral-000\">\n {companyName}\n </strong>{\" \"}\n {companyDesc}\n </span>\n </span>\n </a>\n </div>\n <div className=\"block md:hidden\">\n <MeganavPanelItemLinks\n listItems={[\n {\n label: title,\n link: link,\n icon: icon,\n },\n ]}\n />\n </div>\n </>\n );\n};\n\nexport default MeganavCustomerStories;\n"],"names":["React","PanelTitle","MeganavPanelItemLinks","MeganavCustomerStories","customerStoriesHighlight","title","link","icon","companyName","companyDesc","companyLink","companyLogo","companyLogoDark","div","className","a","href","figure","img","src","alt","span","strong","listItems","label"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAASC,UAAU,KAAQ,cAAe,AAC1C,QAAOC,0BAA2B,yBAA0B,CAW5D,MAAMC,uBAAyB,CAAC,CAC9BC,wBAAwB,CACxBC,KAAK,CACLC,IAAI,CACJC,IAAI,CAML,IACC,KAAM,CACJC,WAAW,CACXC,WAAW,CACXC,WAAW,CACXC,WAAW,CACXC,eAAe,CAChB,CAAGR,yBACJ,OACE,wCACE,oBAACS,OAAIC,UAAU,wBACb,oBAACb,YAAWI,MAAOA,MAAOC,KAAMA,OAChC,oBAACS,KACCC,KAAMN,YACNI,UAAU,6NAKV,oBAACG,UACCH,UAAU,gNAKV,oBAACI,OACCC,IAAKR,YACLS,IAAKZ,YACLM,UAAU,2CAEXF,iBACC,oBAACM,OACCC,IAAKP,gBACLQ,IAAKZ,YACLM,UAAU,kDAIhB,oBAACO,QAAKP,UAAU,uBACd,oBAACO,QAAKP,UAAU,sDACd,oBAACQ,UAAOR,UAAU,yDACfN,aACO,IACTC,gBAKT,oBAACI,OAAIC,UAAU,mBACb,oBAACZ,uBACCqB,UAAW,CACT,CACEC,MAAOnB,MACPC,KAAMA,KACNC,KAAMA,IACR,EACD,IAKX,CAEA,gBAAeJ,sBAAuB"}
1
+ {"version":3,"sources":["../../../src/core/Meganav/MeganavCustomerStories.tsx"],"sourcesContent":["import React from \"react\";\nimport { PanelTitle } from \"./PanelTitle\";\nimport MeganavPanelItemLinks from \"./MeganavPanelItemLinks\";\nimport { IconName } from \"../Icon/types\";\n\nexport type CustomerStoryHighlight = {\n companyName: string;\n companyDesc: string;\n companyLink: string;\n companyLogo: string;\n companyLogoDark?: string;\n};\n\nconst MeganavCustomerStories = ({\n customerStoriesHighlight,\n title,\n link,\n icon,\n}: {\n customerStoriesHighlight: CustomerStoryHighlight;\n title: string;\n link: string;\n icon?: IconName;\n}) => {\n const {\n companyName,\n companyDesc,\n companyLink,\n companyLogo,\n companyLogoDark,\n } = customerStoriesHighlight;\n return (\n <>\n <div className=\"mt-3 hidden md:block\">\n <PanelTitle title={title} link={link} />\n <a\n href={companyLink}\n className=\"flex flex-col gap-y-2.5 p-3 pointer-events-auto rounded-lg\n transition-colors group/customer-story-highlight \n hover:bg-neutral-100 dark:hover:bg-neutral-1200 focus-base\n active:bg-neutral-200 dark:active:bg-neutral-1100\"\n >\n <figure\n className=\"rounded bg-neutral-100 dark:bg-neutral-1200 \n group-hover/customer-story-highlight:bg-neutral-000 \n dark:group-hover/customer-story-highlight:bg-neutral-1300\n flex justify-center items-center gap-4 h-[120px]\"\n >\n <img\n src={companyLogo}\n alt={companyName}\n className=\"max-h-[90px] max-w-[180px] dark:hidden\"\n />\n {companyLogoDark && (\n <img\n src={companyLogoDark}\n alt={companyName}\n className=\"max-h-[90px] max-w-[180px] hidden dark:block\"\n />\n )}\n </figure>\n <span className=\"flex flex-col gap-2\">\n <span className=\"ui-text-p4 text-neutral-1000 dark:text-neutral-300\">\n <strong className=\"font-semibold text-neutral-1300 dark:text-neutral-000\">\n {companyName}\n </strong>{\" \"}\n {companyDesc}\n </span>\n </span>\n </a>\n </div>\n <div className=\"block md:hidden\">\n <MeganavPanelItemLinks\n listItems={[\n {\n label: title,\n link: link,\n icon: icon,\n },\n ]}\n />\n </div>\n </>\n );\n};\n\nexport default MeganavCustomerStories;\n"],"names":["React","PanelTitle","MeganavPanelItemLinks","MeganavCustomerStories","customerStoriesHighlight","title","link","icon","companyName","companyDesc","companyLink","companyLogo","companyLogoDark","div","className","a","href","figure","img","src","alt","span","strong","listItems","label"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAASC,UAAU,KAAQ,cAAe,AAC1C,QAAOC,0BAA2B,yBAA0B,CAW5D,MAAMC,uBAAyB,CAAC,CAC9BC,wBAAwB,CACxBC,KAAK,CACLC,IAAI,CACJC,IAAI,CAML,IACC,KAAM,CACJC,WAAW,CACXC,WAAW,CACXC,WAAW,CACXC,WAAW,CACXC,eAAe,CAChB,CAAGR,yBACJ,OACE,wCACE,oBAACS,OAAIC,UAAU,wBACb,oBAACb,YAAWI,MAAOA,MAAOC,KAAMA,OAChC,oBAACS,KACCC,KAAMN,YACNI,UAAU,oPAKV,oBAACG,UACCH,UAAU,qPAKV,oBAACI,OACCC,IAAKR,YACLS,IAAKZ,YACLM,UAAU,2CAEXF,iBACC,oBAACM,OACCC,IAAKP,gBACLQ,IAAKZ,YACLM,UAAU,kDAIhB,oBAACO,QAAKP,UAAU,uBACd,oBAACO,QAAKP,UAAU,sDACd,oBAACQ,UAAOR,UAAU,yDACfN,aACO,IACTC,gBAKT,oBAACI,OAAIC,UAAU,mBACb,oBAACZ,uBACCqB,UAAW,CACT,CACEC,MAAOnB,MACPC,KAAMA,KACNC,KAAMA,IACR,EACD,IAKX,CAEA,gBAAeJ,sBAAuB"}
@@ -1,2 +1,2 @@
1
- import React from"react";import Icon from"../Icon";import cn from"../utils/cn";import Badge from"../Badge";import{PanelTitle}from"./PanelTitle";const MeganavPanelItemLinks=({label,listItems,link,displayTitleInMobile=true})=>{return React.createElement("ul",{className:cn(!displayTitleInMobile&&"-mt-3 md:mt-0")},(link?.label||label)&&React.createElement(PanelTitle,{title:link?.label||label||"",link:link?.link??"",displayTitleInMobile:displayTitleInMobile}),listItems&&listItems.map(listItem=>React.createElement("li",{className:cn("list-none py-2.5 md:py-2 px-3 my-0 flex gap-x-2.5 rounded-lg group hover:cursor-pointer","hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100",listItem.isMobile?"md:hidden":"md:flex"),key:listItem.label},listItem.icon&&React.createElement(Icon,{name:listItem.icon,size:"1.25rem",additionalCSS:"text-neutral-1000 dark:text-neutral-300"}),React.createElement("a",{className:"pointer-events-auto font-sans text-label2 md:text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 group-hover:text-neutral-1300 dark:group-hover:text-neutral-000 focus-base",href:listItem.link},listItem.label),listItem.badge&&React.createElement(Badge,{size:"xs"},listItem.badge))))};export default MeganavPanelItemLinks;
1
+ import React from"react";import Icon from"../Icon";import cn from"../utils/cn";import Badge from"../Badge";import{PanelTitle}from"./PanelTitle";const MeganavPanelItemLinks=({label,listItems,link,displayTitleInMobile=true})=>{return React.createElement("ul",{className:cn(!displayTitleInMobile&&"-mt-3 md:mt-0")},(link?.label||label)&&React.createElement(PanelTitle,{title:link?.label||label||"",link:link?.link??"",displayTitleInMobile:displayTitleInMobile}),listItems&&listItems.map(listItem=>React.createElement("li",{className:cn("list-none py-2.5 md:py-2 px-3 my-0 flex gap-x-2.5 rounded-lg group hover:cursor-pointer","hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100",listItem.isMobile?"md:hidden":"md:flex"),key:listItem.label},listItem.icon&&React.createElement(Icon,{name:listItem.icon,size:"1.25rem",additionalCSS:"text-neutral-1000 dark:text-neutral-300"}),React.createElement("a",{className:"pointer-events-auto font-sans text-label2 md:text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 \n group-hover:text-neutral-1300 dark:group-hover:text-neutral-000 focus-base",href:listItem.link},listItem.label),listItem.badge&&React.createElement(Badge,{size:"xs"},listItem.badge))))};export default MeganavPanelItemLinks;
2
2
  //# sourceMappingURL=MeganavPanelItemLinks.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Meganav/MeganavPanelItemLinks.tsx"],"sourcesContent":["import React from \"react\";\nimport Icon from \"../Icon\";\nimport cn from \"../utils/cn\";\nimport Badge from \"../Badge\";\nimport { PanelTitle } from \"./PanelTitle\";\nimport { IconName } from \"../Icon/types\";\nimport { FlyoutPanelList } from \"./data\";\n\nexport type MeganavPanelItemLink = {\n label?: string;\n listItems: FlyoutPanelList[];\n icon?: IconName;\n link?: {\n label: string;\n link: string;\n };\n displayTitleInMobile?: boolean;\n};\n\nconst MeganavPanelItemLinks = ({\n label,\n listItems,\n link,\n displayTitleInMobile = true,\n}: MeganavPanelItemLink) => {\n return (\n <ul className={cn(!displayTitleInMobile && \"-mt-3 md:mt-0\")}>\n {(link?.label || label) && (\n <PanelTitle\n title={link?.label || label || \"\"}\n link={link?.link ?? \"\"}\n displayTitleInMobile={displayTitleInMobile}\n />\n )}\n\n {listItems &&\n listItems.map((listItem) => (\n <li\n className={cn(\n \"list-none py-2.5 md:py-2 px-3 my-0 flex gap-x-2.5 rounded-lg group hover:cursor-pointer\",\n \"hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100\",\n listItem.isMobile ? \"md:hidden\" : \"md:flex\",\n )}\n key={listItem.label}\n >\n {listItem.icon && (\n <Icon\n name={listItem.icon}\n size=\"1.25rem\"\n additionalCSS=\"text-neutral-1000 dark:text-neutral-300\"\n />\n )}\n <a\n className=\"pointer-events-auto font-sans text-label2 md:text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 \n group-hover:text-neutral-1300 dark:group-hover:text-neutral-000 focus-base\"\n href={listItem.link}\n >\n {listItem.label}\n </a>\n {listItem.badge && <Badge size=\"xs\">{listItem.badge}</Badge>}\n </li>\n ))}\n </ul>\n );\n};\n\nexport default MeganavPanelItemLinks;\n"],"names":["React","Icon","cn","Badge","PanelTitle","MeganavPanelItemLinks","label","listItems","link","displayTitleInMobile","ul","className","title","map","listItem","li","isMobile","key","icon","name","size","additionalCSS","a","href","badge"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAAOC,SAAU,SAAU,AAC3B,QAAOC,OAAQ,aAAc,AAC7B,QAAOC,UAAW,UAAW,AAC7B,QAASC,UAAU,KAAQ,cAAe,CAe1C,MAAMC,sBAAwB,CAAC,CAC7BC,KAAK,CACLC,SAAS,CACTC,IAAI,CACJC,qBAAuB,IAAI,CACN,IACrB,OACE,oBAACC,MAAGC,UAAWT,GAAG,CAACO,sBAAwB,kBACxC,AAACD,CAAAA,MAAMF,OAASA,KAAI,GACnB,oBAACF,YACCQ,MAAOJ,MAAMF,OAASA,OAAS,GAC/BE,KAAMA,MAAMA,MAAQ,GACpBC,qBAAsBA,uBAIzBF,WACCA,UAAUM,GAAG,CAAC,AAACC,UACb,oBAACC,MACCJ,UAAWT,GACT,0FACA,oGACAY,SAASE,QAAQ,CAAG,YAAc,WAEpCC,IAAKH,SAASR,KAAK,EAElBQ,SAASI,IAAI,EACZ,oBAACjB,MACCkB,KAAML,SAASI,IAAI,CACnBE,KAAK,UACLC,cAAc,4CAGlB,oBAACC,KACCX,UAAU,6LAEVY,KAAMT,SAASN,IAAI,EAElBM,SAASR,KAAK,EAEhBQ,SAASU,KAAK,EAAI,oBAACrB,OAAMiB,KAAK,MAAMN,SAASU,KAAK,IAK/D,CAEA,gBAAenB,qBAAsB"}
1
+ {"version":3,"sources":["../../../src/core/Meganav/MeganavPanelItemLinks.tsx"],"sourcesContent":["import React from \"react\";\nimport Icon from \"../Icon\";\nimport cn from \"../utils/cn\";\nimport Badge from \"../Badge\";\nimport { PanelTitle } from \"./PanelTitle\";\nimport { IconName } from \"../Icon/types\";\nimport { FlyoutPanelList } from \"./data\";\n\nexport type MeganavPanelItemLink = {\n label?: string;\n listItems: FlyoutPanelList[];\n icon?: IconName;\n link?: {\n label: string;\n link: string;\n };\n displayTitleInMobile?: boolean;\n};\n\nconst MeganavPanelItemLinks = ({\n label,\n listItems,\n link,\n displayTitleInMobile = true,\n}: MeganavPanelItemLink) => {\n return (\n <ul className={cn(!displayTitleInMobile && \"-mt-3 md:mt-0\")}>\n {(link?.label || label) && (\n <PanelTitle\n title={link?.label || label || \"\"}\n link={link?.link ?? \"\"}\n displayTitleInMobile={displayTitleInMobile}\n />\n )}\n\n {listItems &&\n listItems.map((listItem) => (\n <li\n className={cn(\n \"list-none py-2.5 md:py-2 px-3 my-0 flex gap-x-2.5 rounded-lg group hover:cursor-pointer\",\n \"hover:bg-neutral-100 dark:hover:bg-neutral-1200 active:bg-neutral-200 dark:active:bg-neutral-1100\",\n listItem.isMobile ? \"md:hidden\" : \"md:flex\",\n )}\n key={listItem.label}\n >\n {listItem.icon && (\n <Icon\n name={listItem.icon}\n size=\"1.25rem\"\n additionalCSS=\"text-neutral-1000 dark:text-neutral-300\"\n />\n )}\n <a\n className=\"pointer-events-auto font-sans text-label2 md:text-label3 font-semibold text-neutral-1000 dark:text-neutral-300 \n group-hover:text-neutral-1300 dark:group-hover:text-neutral-000 focus-base\"\n href={listItem.link}\n >\n {listItem.label}\n </a>\n {listItem.badge && <Badge size=\"xs\">{listItem.badge}</Badge>}\n </li>\n ))}\n </ul>\n );\n};\n\nexport default MeganavPanelItemLinks;\n"],"names":["React","Icon","cn","Badge","PanelTitle","MeganavPanelItemLinks","label","listItems","link","displayTitleInMobile","ul","className","title","map","listItem","li","isMobile","key","icon","name","size","additionalCSS","a","href","badge"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAAOC,SAAU,SAAU,AAC3B,QAAOC,OAAQ,aAAc,AAC7B,QAAOC,UAAW,UAAW,AAC7B,QAASC,UAAU,KAAQ,cAAe,CAe1C,MAAMC,sBAAwB,CAAC,CAC7BC,KAAK,CACLC,SAAS,CACTC,IAAI,CACJC,qBAAuB,IAAI,CACN,IACrB,OACE,oBAACC,MAAGC,UAAWT,GAAG,CAACO,sBAAwB,kBACxC,AAACD,CAAAA,MAAMF,OAASA,KAAI,GACnB,oBAACF,YACCQ,MAAOJ,MAAMF,OAASA,OAAS,GAC/BE,KAAMA,MAAMA,MAAQ,GACpBC,qBAAsBA,uBAIzBF,WACCA,UAAUM,GAAG,CAAC,AAACC,UACb,oBAACC,MACCJ,UAAWT,GACT,0FACA,oGACAY,SAASE,QAAQ,CAAG,YAAc,WAEpCC,IAAKH,SAASR,KAAK,EAElBQ,SAASI,IAAI,EACZ,oBAACjB,MACCkB,KAAML,SAASI,IAAI,CACnBE,KAAK,UACLC,cAAc,4CAGlB,oBAACC,KACCX,UAAU,4MAEVY,KAAMT,SAASN,IAAI,EAElBM,SAASR,KAAK,EAEhBQ,SAASU,KAAK,EAAI,oBAACrB,OAAMiB,KAAK,MAAMN,SAASU,KAAK,IAK/D,CAEA,gBAAenB,qBAAsB"}
@@ -1,2 +1,2 @@
1
- import React from"react";import FeaturedLink from"../FeaturedLink";import cn from"../utils/cn";export const PanelTitle=({title,link,displayTitleInMobile=true})=>{return React.createElement("div",{className:cn("mb-3 px-3",displayTitleInMobile?"block":"hidden md:block")},link?React.createElement(FeaturedLink,{url:link,textSize:"text-overline2",additionalCSS:"ui-text-overline2 mb-0 py-0 font-medium font-mono text-neutral-700 dark:text-neutral-600 hover:text-neutral-1300 dark:hover:text-neutral-000 active:text-neutral-1100 dark:active:text-neutral-200 focus-base"},title):React.createElement("p",{className:"ui-text-overline2 text-neutral-700 dark:text-neutral-600 font-medium font-mono"},title))};
1
+ import React from"react";import FeaturedLink from"../FeaturedLink";import cn from"../utils/cn";export const PanelTitle=({title,link,displayTitleInMobile=true})=>{return React.createElement("div",{className:cn("mb-3 px-3",displayTitleInMobile?"block":"hidden md:block")},link?React.createElement(FeaturedLink,{url:link,textSize:"text-overline2",additionalCSS:"ui-text-overline2 mb-0 py-0 font-medium font-mono\n text-neutral-700 dark:text-neutral-600 hover:text-neutral-1300 dark:hover:text-neutral-000\n active:text-neutral-1100 dark:active:text-neutral-200 focus-base"},title):React.createElement("p",{className:"ui-text-overline2 text-neutral-700 dark:text-neutral-600 font-medium font-mono"},title))};
2
2
  //# sourceMappingURL=PanelTitle.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Meganav/PanelTitle.tsx"],"sourcesContent":["import React from \"react\";\nimport FeaturedLink from \"../FeaturedLink\";\nimport cn from \"../utils/cn\";\n\nexport const PanelTitle = ({\n title,\n link,\n displayTitleInMobile = true,\n}: {\n title: string;\n link?: string;\n displayTitleInMobile?: boolean;\n}) => {\n return (\n <div\n className={cn(\n \"mb-3 px-3\",\n displayTitleInMobile ? \"block\" : \"hidden md:block\",\n )}\n >\n {link ? (\n <FeaturedLink\n url={link}\n textSize=\"text-overline2\"\n additionalCSS=\"ui-text-overline2 mb-0 py-0 font-medium font-mono\n text-neutral-700 dark:text-neutral-600 hover:text-neutral-1300 dark:hover:text-neutral-000\n active:text-neutral-1100 dark:active:text-neutral-200 focus-base\"\n >\n {title}\n </FeaturedLink>\n ) : (\n <p className=\"ui-text-overline2 text-neutral-700 dark:text-neutral-600 font-medium font-mono\">\n {title}\n </p>\n )}\n </div>\n );\n};\n"],"names":["React","FeaturedLink","cn","PanelTitle","title","link","displayTitleInMobile","div","className","url","textSize","additionalCSS","p"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAAOC,iBAAkB,iBAAkB,AAC3C,QAAOC,OAAQ,aAAc,AAE7B,QAAO,MAAMC,WAAa,CAAC,CACzBC,KAAK,CACLC,IAAI,CACJC,qBAAuB,IAAI,CAK5B,IACC,OACE,oBAACC,OACCC,UAAWN,GACT,YACAI,qBAAuB,QAAU,oBAGlCD,KACC,oBAACJ,cACCQ,IAAKJ,KACLK,SAAS,iBACTC,cAAc,iNAIbP,OAGH,oBAACQ,KAAEJ,UAAU,kFACVJ,OAKX,CAAE"}
1
+ {"version":3,"sources":["../../../src/core/Meganav/PanelTitle.tsx"],"sourcesContent":["import React from \"react\";\nimport FeaturedLink from \"../FeaturedLink\";\nimport cn from \"../utils/cn\";\n\nexport const PanelTitle = ({\n title,\n link,\n displayTitleInMobile = true,\n}: {\n title: string;\n link?: string;\n displayTitleInMobile?: boolean;\n}) => {\n return (\n <div\n className={cn(\n \"mb-3 px-3\",\n displayTitleInMobile ? \"block\" : \"hidden md:block\",\n )}\n >\n {link ? (\n <FeaturedLink\n url={link}\n textSize=\"text-overline2\"\n additionalCSS=\"ui-text-overline2 mb-0 py-0 font-medium font-mono\n text-neutral-700 dark:text-neutral-600 hover:text-neutral-1300 dark:hover:text-neutral-000\n active:text-neutral-1100 dark:active:text-neutral-200 focus-base\"\n >\n {title}\n </FeaturedLink>\n ) : (\n <p className=\"ui-text-overline2 text-neutral-700 dark:text-neutral-600 font-medium font-mono\">\n {title}\n </p>\n )}\n </div>\n );\n};\n"],"names":["React","FeaturedLink","cn","PanelTitle","title","link","displayTitleInMobile","div","className","url","textSize","additionalCSS","p"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAAOC,iBAAkB,iBAAkB,AAC3C,QAAOC,OAAQ,aAAc,AAE7B,QAAO,MAAMC,WAAa,CAAC,CACzBC,KAAK,CACLC,IAAI,CACJC,qBAAuB,IAAI,CAK5B,IACC,OACE,oBAACC,OACCC,UAAWN,GACT,YACAI,qBAAuB,QAAU,oBAGlCD,KACC,oBAACJ,cACCQ,IAAKJ,KACLK,SAAS,iBACTC,cAAc,uOAIbP,OAGH,oBAACQ,KAAEJ,UAAU,kFACVJ,OAKX,CAAE"}
@@ -1,2 +1,2 @@
1
- import React from"react";import G2BestMeetsRequirementsSpring2025 from"../images/badges/g2-best-meets-requirements-spring-2025.svg";import G2BestResultsSpring2025 from"../images/badges/g2-best-results-spring-2025.svg";import G2BestSupportSpring2025 from"../images/badges/g2-best-support-spring-2025.svg";import{products}from"../ProductTile/data";import DialpadLogo from"../Meganav/images/cust-logo-dialpad-light.png";import DialpadLogoDark from"../Meganav/images/cust-logo-dialpad-dark.png";export const productsMenu=[{label:"Architecture",icon:"icon-gui-squares-2-x-2-outline",link:"/platform"},{label:"Integrations",icon:"icon-gui-puzzle-piece-outline",link:"/docs/platform/integrations"},{label:"SDKs",icon:"icon-gui-cube-transparent-outline",link:"/docs/sdks"},{label:"Security & Compliance",icon:"icon-gui-shield-check-outline",link:"/security-and-compliance"}];export const compareMenu=[{label:"Ably vs Pusher",link:"/compare/ably-vs-pusher"},{label:"Ably vs PubNub",link:"/compare/ably-vs-pubnub"},{label:"Ably vs Socket.io",link:"/compare/ably-vs-socketio"}];export const solutionsMenu=[{label:"Fan Engagement",icon:"icon-gui-hand-thumb-up-outline",link:"/fan-engagement",description:"Enhance every moment with live, interactive fan experiences."},{label:"FinTech",icon:"icon-gui-currency-dollar-outline",link:"/fin-tech",description:"Speed, reliability, and confidence in every user interaction."},{label:"EdTech",icon:"icon-gui-academic-cap-outline",link:"/ed-tech",description:"Power collaborative, interactive learning environments."},{label:"CXTech",icon:"icon-gui-face-smile-outline",link:"/cx-tech",description:"Deliver fast support, strong relationships, and high retention."},{label:"HealthTech",icon:"icon-gui-heartbeat-outline",link:"/health-tech",description:"Reliable tools with full data privacy and compliance."}];export const customerStoriesHighlight={companyLogo:DialpadLogo,companyLogoDark:DialpadLogoDark,companyLink:"/case-studies/dialpad",companyName:"Dialpad",companyDesc:"are sending 60B+ messages per month across 20+ critical use cases with zero downtime since migrating to Ably."};export const companyMenu=[{label:"Our story",icon:"icon-gui-ably-badge",link:"/about"},{label:"Careers",icon:"icon-gui-briefcase-outline",link:"/careers",badge:"WE'RE HIRING"}];export const ablyAwards=[{image:G2BestSupportSpring2025,desc:"G2 Best Support Spring 2025"},{image:G2BestMeetsRequirementsSpring2025,desc:"G2 Best Meets Requirements Spring 2025"},{image:G2BestResultsSpring2025,desc:"G2 Best Results Spring 2025"}];export const menuItemLinks=[{name:"Pricing",link:"/pricing",isHiddenMobile:true},{name:"Docs",link:"/docs",isHiddenMobile:true}];export const defaultBlogPosts=[{title:"Ably AI Transport: keep your agents connected and stateful across devices",link:"/blog/ably-ai-transport",categories:["New Release","AI Transport","New Feature","RealTime Experiences","Engineering","Ably News"],pubDate:"Dec 9, 2025"},{title:"Live chat at unlimited scale: What it takes to support stadium-sized audiences",link:"/blog/live-chat-at-unlimited-scale",categories:["Chat"],pubDate:"Nov 18, 2025"}];export const productsForNav={...products,pubsub:{...products.pubsub,link:"/pubsub"},liveSync:{...products.liveSync,link:"/livesync"},chat:{...products.chat,link:"/chat"},spaces:{...products.spaces,link:"/spaces"},aiTransport:{...products.aiTransport,link:"/ai-transport"},liveObjects:{...products.liveObjects,link:"/liveobjects"}};
1
+ import React from"react";import G2BestMeetsRequirementsSpring2025 from"../images/badges/g2-best-meets-requirements-spring-2025.svg";import G2BestResultsSpring2025 from"../images/badges/g2-best-results-spring-2025.svg";import G2BestSupportSpring2025 from"../images/badges/g2-best-support-spring-2025.svg";import{products}from"../ProductTile/data";import FinLogoLight from"../Meganav/images/cust-logo-fin-light.svg";import FinLogoDark from"../Meganav/images/cust-logo-fin-dark.svg";export const productsMenu=[{label:"Architecture",icon:"icon-gui-squares-2-x-2-outline",link:"/platform"},{label:"Integrations",icon:"icon-gui-puzzle-piece-outline",link:"/docs/platform/integrations"},{label:"SDKs",icon:"icon-gui-cube-transparent-outline",link:"/docs/sdks"},{label:"Security & Compliance",icon:"icon-gui-shield-check-outline",link:"/security-and-compliance"}];export const compareMenu=[{label:"Ably vs Pusher",link:"/compare/ably-vs-pusher"},{label:"Ably vs PubNub",link:"/compare/ably-vs-pubnub"},{label:"Ably vs Socket.io",link:"/compare/ably-vs-socketio"}];export const solutionsMenu=[{label:"Fan Engagement",icon:"icon-gui-hand-thumb-up-outline",link:"/fan-engagement",description:"Enhance every moment with live, interactive fan experiences."},{label:"FinTech",icon:"icon-gui-currency-dollar-outline",link:"/fin-tech",description:"Speed, reliability, and confidence in every user interaction."},{label:"EdTech",icon:"icon-gui-academic-cap-outline",link:"/ed-tech",description:"Power collaborative, interactive learning environments."},{label:"CXTech",icon:"icon-gui-face-smile-outline",link:"/cx-tech",description:"Deliver fast support, strong relationships, and high retention."},{label:"HealthTech",icon:"icon-gui-heartbeat-outline",link:"/health-tech",description:"Reliable tools with full data privacy and compliance."}];export const customerStoriesHighlight={companyLogo:FinLogoLight,companyLogoDark:FinLogoDark,companyLink:"/case-studies/fin-intercom",companyName:"Fin",companyDesc:"drove 80% more efficiency in realtime delivery for AI chat by replacing its in-house realtime platform with Ably."};export const companyMenu=[{label:"Our story",icon:"icon-gui-ably-badge",link:"/about"},{label:"Careers",icon:"icon-gui-briefcase-outline",link:"/careers",badge:"WE'RE HIRING"}];export const ablyAwards=[{image:G2BestSupportSpring2025,desc:"G2 Best Support Spring 2025"},{image:G2BestMeetsRequirementsSpring2025,desc:"G2 Best Meets Requirements Spring 2025"},{image:G2BestResultsSpring2025,desc:"G2 Best Results Spring 2025"}];export const menuItemLinks=[{name:"Pricing",link:"/pricing",isHiddenMobile:true},{name:"Docs",link:"/docs",isHiddenMobile:true}];export const defaultBlogPosts=[{title:"Ably AI Transport: keep your agents connected and stateful across devices",link:"/blog/ably-ai-transport",categories:["New Release","AI Transport","New Feature","RealTime Experiences","Engineering","Ably News"],pubDate:"Dec 9, 2025"},{title:"Live chat at unlimited scale: What it takes to support stadium-sized audiences",link:"/blog/live-chat-at-unlimited-scale",categories:["Chat"],pubDate:"Nov 18, 2025"}];export const productsForNav={...products,pubsub:{...products.pubsub,link:"/pubsub"},liveSync:{...products.liveSync,link:"/livesync"},chat:{...products.chat,link:"/chat"},spaces:{...products.spaces,link:"/spaces"},aiTransport:{...products.aiTransport,link:"/ai-transport"},liveObjects:{...products.liveObjects,link:"/liveobjects"}};
2
2
  //# sourceMappingURL=data.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Meganav/data.tsx"],"sourcesContent":["import React from \"react\";\nimport { IconName } from \"../Icon/types\";\nimport { CustomerStoryHighlight } from \"./MeganavCustomerStories\";\nimport { BlogPost } from \"./MeganavBlog\";\nimport G2BestMeetsRequirementsSpring2025 from \"../images/badges/g2-best-meets-requirements-spring-2025.svg\";\nimport G2BestResultsSpring2025 from \"../images/badges/g2-best-results-spring-2025.svg\";\nimport G2BestSupportSpring2025 from \"../images/badges/g2-best-support-spring-2025.svg\";\nimport { products } from \"../ProductTile/data\";\nimport DialpadLogo from \"../Meganav/images/cust-logo-dialpad-light.png\";\nimport DialpadLogoDark from \"../Meganav/images/cust-logo-dialpad-dark.png\";\n\nexport type FlyoutPanelList = {\n label: string;\n icon?: IconName;\n link: string;\n isMobile?: boolean;\n description?: string;\n badge?: string;\n};\n\nexport type MenuItem = {\n name: string;\n link?: string;\n isHiddenMobile?: boolean;\n content?: React.ReactNode;\n panelClassName?: string;\n};\n\nexport const productsMenu: FlyoutPanelList[] = [\n {\n label: \"Architecture\",\n icon: \"icon-gui-squares-2-x-2-outline\",\n link: \"/platform\",\n },\n {\n label: \"Integrations\",\n icon: \"icon-gui-puzzle-piece-outline\",\n link: \"/docs/platform/integrations\",\n },\n {\n label: \"SDKs\",\n icon: \"icon-gui-cube-transparent-outline\",\n link: \"/docs/sdks\",\n },\n {\n label: \"Security & Compliance\",\n icon: \"icon-gui-shield-check-outline\",\n link: \"/security-and-compliance\",\n },\n];\n\nexport const compareMenu: FlyoutPanelList[] = [\n {\n label: \"Ably vs Pusher\",\n link: \"/compare/ably-vs-pusher\",\n },\n {\n label: \"Ably vs PubNub\",\n link: \"/compare/ably-vs-pubnub\",\n },\n {\n label: \"Ably vs Socket.io\",\n link: \"/compare/ably-vs-socketio\",\n },\n];\n\nexport const solutionsMenu: FlyoutPanelList[] = [\n {\n label: \"Fan Engagement\",\n icon: \"icon-gui-hand-thumb-up-outline\",\n link: \"/fan-engagement\",\n description: \"Enhance every moment with live, interactive fan experiences.\",\n },\n {\n label: \"FinTech\",\n icon: \"icon-gui-currency-dollar-outline\",\n link: \"/fin-tech\",\n description:\n \"Speed, reliability, and confidence in every user interaction.\",\n },\n {\n label: \"EdTech\",\n icon: \"icon-gui-academic-cap-outline\",\n link: \"/ed-tech\",\n description: \"Power collaborative, interactive learning environments.\",\n },\n {\n label: \"CXTech\",\n icon: \"icon-gui-face-smile-outline\",\n link: \"/cx-tech\",\n description:\n \"Deliver fast support, strong relationships, and high retention.\",\n },\n\n {\n label: \"HealthTech\",\n icon: \"icon-gui-heartbeat-outline\",\n link: \"/health-tech\",\n description: \"Reliable tools with full data privacy and compliance.\",\n },\n];\n\nexport const customerStoriesHighlight: CustomerStoryHighlight = {\n companyLogo: DialpadLogo,\n companyLogoDark: DialpadLogoDark,\n companyLink: \"/case-studies/dialpad\",\n companyName: \"Dialpad\",\n companyDesc:\n \"are sending 60B+ messages per month across 20+ critical use cases with zero downtime since migrating to Ably.\",\n};\n\nexport const companyMenu: FlyoutPanelList[] = [\n {\n label: \"Our story\",\n icon: \"icon-gui-ably-badge\",\n link: \"/about\",\n },\n {\n label: \"Careers\",\n icon: \"icon-gui-briefcase-outline\",\n link: \"/careers\",\n badge: \"WE'RE HIRING\",\n },\n];\n\nexport const ablyAwards = [\n {\n image: G2BestSupportSpring2025,\n desc: \"G2 Best Support Spring 2025\",\n },\n {\n image: G2BestMeetsRequirementsSpring2025,\n desc: \"G2 Best Meets Requirements Spring 2025\",\n },\n {\n image: G2BestResultsSpring2025,\n desc: \"G2 Best Results Spring 2025\",\n },\n];\n\nexport const menuItemLinks = [\n { name: \"Pricing\", link: \"/pricing\", isHiddenMobile: true },\n { name: \"Docs\", link: \"/docs\", isHiddenMobile: true },\n];\n\nexport const defaultBlogPosts: BlogPost[] = [\n {\n title:\n \"Ably AI Transport: keep your agents connected and stateful across devices\",\n link: \"/blog/ably-ai-transport\",\n categories: [\n \"New Release\",\n \"AI Transport\",\n \"New Feature\",\n \"RealTime Experiences\",\n \"Engineering\",\n \"Ably News\",\n ],\n pubDate: \"Dec 9, 2025\",\n },\n {\n title:\n \"Live chat at unlimited scale: What it takes to support stadium-sized audiences\",\n link: \"/blog/live-chat-at-unlimited-scale\",\n categories: [\"Chat\"],\n pubDate: \"Nov 18, 2025\",\n },\n];\n\nexport const productsForNav = {\n ...products,\n pubsub: { ...products.pubsub, link: \"/pubsub\" },\n liveSync: { ...products.liveSync, link: \"/livesync\" },\n chat: { ...products.chat, link: \"/chat\" },\n spaces: { ...products.spaces, link: \"/spaces\" },\n aiTransport: {\n ...products.aiTransport,\n link: \"/ai-transport\",\n },\n liveObjects: { ...products.liveObjects, link: \"/liveobjects\" },\n};\n"],"names":["React","G2BestMeetsRequirementsSpring2025","G2BestResultsSpring2025","G2BestSupportSpring2025","products","DialpadLogo","DialpadLogoDark","productsMenu","label","icon","link","compareMenu","solutionsMenu","description","customerStoriesHighlight","companyLogo","companyLogoDark","companyLink","companyName","companyDesc","companyMenu","badge","ablyAwards","image","desc","menuItemLinks","name","isHiddenMobile","defaultBlogPosts","title","categories","pubDate","productsForNav","pubsub","liveSync","chat","spaces","aiTransport","liveObjects"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAI1B,QAAOC,sCAAuC,6DAA8D,AAC5G,QAAOC,4BAA6B,kDAAmD,AACvF,QAAOC,4BAA6B,kDAAmD,AACvF,QAASC,QAAQ,KAAQ,qBAAsB,AAC/C,QAAOC,gBAAiB,+CAAgD,AACxE,QAAOC,oBAAqB,8CAA+C,AAmB3E,QAAO,MAAMC,aAAkC,CAC7C,CACEC,MAAO,eACPC,KAAM,iCACNC,KAAM,WACR,EACA,CACEF,MAAO,eACPC,KAAM,gCACNC,KAAM,6BACR,EACA,CACEF,MAAO,OACPC,KAAM,oCACNC,KAAM,YACR,EACA,CACEF,MAAO,wBACPC,KAAM,gCACNC,KAAM,0BACR,EACD,AAAC,AAEF,QAAO,MAAMC,YAAiC,CAC5C,CACEH,MAAO,iBACPE,KAAM,yBACR,EACA,CACEF,MAAO,iBACPE,KAAM,yBACR,EACA,CACEF,MAAO,oBACPE,KAAM,2BACR,EACD,AAAC,AAEF,QAAO,MAAME,cAAmC,CAC9C,CACEJ,MAAO,iBACPC,KAAM,iCACNC,KAAM,kBACNG,YAAa,8DACf,EACA,CACEL,MAAO,UACPC,KAAM,mCACNC,KAAM,YACNG,YACE,+DACJ,EACA,CACEL,MAAO,SACPC,KAAM,gCACNC,KAAM,WACNG,YAAa,yDACf,EACA,CACEL,MAAO,SACPC,KAAM,8BACNC,KAAM,WACNG,YACE,iEACJ,EAEA,CACEL,MAAO,aACPC,KAAM,6BACNC,KAAM,eACNG,YAAa,uDACf,EACD,AAAC,AAEF,QAAO,MAAMC,yBAAmD,CAC9DC,YAAaV,YACbW,gBAAiBV,gBACjBW,YAAa,wBACbC,YAAa,UACbC,YACE,+GACJ,CAAE,AAEF,QAAO,MAAMC,YAAiC,CAC5C,CACEZ,MAAO,YACPC,KAAM,sBACNC,KAAM,QACR,EACA,CACEF,MAAO,UACPC,KAAM,6BACNC,KAAM,WACNW,MAAO,cACT,EACD,AAAC,AAEF,QAAO,MAAMC,WAAa,CACxB,CACEC,MAAOpB,wBACPqB,KAAM,6BACR,EACA,CACED,MAAOtB,kCACPuB,KAAM,wCACR,EACA,CACED,MAAOrB,wBACPsB,KAAM,6BACR,EACD,AAAC,AAEF,QAAO,MAAMC,cAAgB,CAC3B,CAAEC,KAAM,UAAWhB,KAAM,WAAYiB,eAAgB,IAAK,EAC1D,CAAED,KAAM,OAAQhB,KAAM,QAASiB,eAAgB,IAAK,EACrD,AAAC,AAEF,QAAO,MAAMC,iBAA+B,CAC1C,CACEC,MACE,4EACFnB,KAAM,0BACNoB,WAAY,CACV,cACA,eACA,cACA,uBACA,cACA,YACD,CACDC,QAAS,aACX,EACA,CACEF,MACE,iFACFnB,KAAM,qCACNoB,WAAY,CAAC,OAAO,CACpBC,QAAS,cACX,EACD,AAAC,AAEF,QAAO,MAAMC,eAAiB,CAC5B,GAAG5B,QAAQ,CACX6B,OAAQ,CAAE,GAAG7B,SAAS6B,MAAM,CAAEvB,KAAM,SAAU,EAC9CwB,SAAU,CAAE,GAAG9B,SAAS8B,QAAQ,CAAExB,KAAM,WAAY,EACpDyB,KAAM,CAAE,GAAG/B,SAAS+B,IAAI,CAAEzB,KAAM,OAAQ,EACxC0B,OAAQ,CAAE,GAAGhC,SAASgC,MAAM,CAAE1B,KAAM,SAAU,EAC9C2B,YAAa,CACX,GAAGjC,SAASiC,WAAW,CACvB3B,KAAM,eACR,EACA4B,YAAa,CAAE,GAAGlC,SAASkC,WAAW,CAAE5B,KAAM,cAAe,CAC/D,CAAE"}
1
+ {"version":3,"sources":["../../../src/core/Meganav/data.tsx"],"sourcesContent":["import React from \"react\";\nimport { IconName } from \"../Icon/types\";\nimport { CustomerStoryHighlight } from \"./MeganavCustomerStories\";\nimport { BlogPost } from \"./MeganavBlog\";\nimport G2BestMeetsRequirementsSpring2025 from \"../images/badges/g2-best-meets-requirements-spring-2025.svg\";\nimport G2BestResultsSpring2025 from \"../images/badges/g2-best-results-spring-2025.svg\";\nimport G2BestSupportSpring2025 from \"../images/badges/g2-best-support-spring-2025.svg\";\nimport { products } from \"../ProductTile/data\";\nimport FinLogoLight from \"../Meganav/images/cust-logo-fin-light.svg\";\nimport FinLogoDark from \"../Meganav/images/cust-logo-fin-dark.svg\";\n\nexport type FlyoutPanelList = {\n label: string;\n icon?: IconName;\n link: string;\n isMobile?: boolean;\n description?: string;\n badge?: string;\n};\n\nexport type MenuItem = {\n name: string;\n link?: string;\n isHiddenMobile?: boolean;\n content?: React.ReactNode;\n panelClassName?: string;\n};\n\nexport const productsMenu: FlyoutPanelList[] = [\n {\n label: \"Architecture\",\n icon: \"icon-gui-squares-2-x-2-outline\",\n link: \"/platform\",\n },\n {\n label: \"Integrations\",\n icon: \"icon-gui-puzzle-piece-outline\",\n link: \"/docs/platform/integrations\",\n },\n {\n label: \"SDKs\",\n icon: \"icon-gui-cube-transparent-outline\",\n link: \"/docs/sdks\",\n },\n {\n label: \"Security & Compliance\",\n icon: \"icon-gui-shield-check-outline\",\n link: \"/security-and-compliance\",\n },\n];\n\nexport const compareMenu: FlyoutPanelList[] = [\n {\n label: \"Ably vs Pusher\",\n link: \"/compare/ably-vs-pusher\",\n },\n {\n label: \"Ably vs PubNub\",\n link: \"/compare/ably-vs-pubnub\",\n },\n {\n label: \"Ably vs Socket.io\",\n link: \"/compare/ably-vs-socketio\",\n },\n];\n\nexport const solutionsMenu: FlyoutPanelList[] = [\n {\n label: \"Fan Engagement\",\n icon: \"icon-gui-hand-thumb-up-outline\",\n link: \"/fan-engagement\",\n description: \"Enhance every moment with live, interactive fan experiences.\",\n },\n {\n label: \"FinTech\",\n icon: \"icon-gui-currency-dollar-outline\",\n link: \"/fin-tech\",\n description:\n \"Speed, reliability, and confidence in every user interaction.\",\n },\n {\n label: \"EdTech\",\n icon: \"icon-gui-academic-cap-outline\",\n link: \"/ed-tech\",\n description: \"Power collaborative, interactive learning environments.\",\n },\n {\n label: \"CXTech\",\n icon: \"icon-gui-face-smile-outline\",\n link: \"/cx-tech\",\n description:\n \"Deliver fast support, strong relationships, and high retention.\",\n },\n\n {\n label: \"HealthTech\",\n icon: \"icon-gui-heartbeat-outline\",\n link: \"/health-tech\",\n description: \"Reliable tools with full data privacy and compliance.\",\n },\n];\n\nexport const customerStoriesHighlight: CustomerStoryHighlight = {\n companyLogo: FinLogoLight,\n companyLogoDark: FinLogoDark,\n companyLink: \"/case-studies/fin-intercom\",\n companyName: \"Fin\",\n companyDesc:\n \"drove 80% more efficiency in realtime delivery for AI chat by replacing its in-house realtime platform with Ably.\",\n};\n\nexport const companyMenu: FlyoutPanelList[] = [\n {\n label: \"Our story\",\n icon: \"icon-gui-ably-badge\",\n link: \"/about\",\n },\n {\n label: \"Careers\",\n icon: \"icon-gui-briefcase-outline\",\n link: \"/careers\",\n badge: \"WE'RE HIRING\",\n },\n];\n\nexport const ablyAwards = [\n {\n image: G2BestSupportSpring2025,\n desc: \"G2 Best Support Spring 2025\",\n },\n {\n image: G2BestMeetsRequirementsSpring2025,\n desc: \"G2 Best Meets Requirements Spring 2025\",\n },\n {\n image: G2BestResultsSpring2025,\n desc: \"G2 Best Results Spring 2025\",\n },\n];\n\nexport const menuItemLinks = [\n { name: \"Pricing\", link: \"/pricing\", isHiddenMobile: true },\n { name: \"Docs\", link: \"/docs\", isHiddenMobile: true },\n];\n\nexport const defaultBlogPosts: BlogPost[] = [\n {\n title:\n \"Ably AI Transport: keep your agents connected and stateful across devices\",\n link: \"/blog/ably-ai-transport\",\n categories: [\n \"New Release\",\n \"AI Transport\",\n \"New Feature\",\n \"RealTime Experiences\",\n \"Engineering\",\n \"Ably News\",\n ],\n pubDate: \"Dec 9, 2025\",\n },\n {\n title:\n \"Live chat at unlimited scale: What it takes to support stadium-sized audiences\",\n link: \"/blog/live-chat-at-unlimited-scale\",\n categories: [\"Chat\"],\n pubDate: \"Nov 18, 2025\",\n },\n];\n\nexport const productsForNav = {\n ...products,\n pubsub: { ...products.pubsub, link: \"/pubsub\" },\n liveSync: { ...products.liveSync, link: \"/livesync\" },\n chat: { ...products.chat, link: \"/chat\" },\n spaces: { ...products.spaces, link: \"/spaces\" },\n aiTransport: {\n ...products.aiTransport,\n link: \"/ai-transport\",\n },\n liveObjects: { ...products.liveObjects, link: \"/liveobjects\" },\n};\n"],"names":["React","G2BestMeetsRequirementsSpring2025","G2BestResultsSpring2025","G2BestSupportSpring2025","products","FinLogoLight","FinLogoDark","productsMenu","label","icon","link","compareMenu","solutionsMenu","description","customerStoriesHighlight","companyLogo","companyLogoDark","companyLink","companyName","companyDesc","companyMenu","badge","ablyAwards","image","desc","menuItemLinks","name","isHiddenMobile","defaultBlogPosts","title","categories","pubDate","productsForNav","pubsub","liveSync","chat","spaces","aiTransport","liveObjects"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAI1B,QAAOC,sCAAuC,6DAA8D,AAC5G,QAAOC,4BAA6B,kDAAmD,AACvF,QAAOC,4BAA6B,kDAAmD,AACvF,QAASC,QAAQ,KAAQ,qBAAsB,AAC/C,QAAOC,iBAAkB,2CAA4C,AACrE,QAAOC,gBAAiB,0CAA2C,AAmBnE,QAAO,MAAMC,aAAkC,CAC7C,CACEC,MAAO,eACPC,KAAM,iCACNC,KAAM,WACR,EACA,CACEF,MAAO,eACPC,KAAM,gCACNC,KAAM,6BACR,EACA,CACEF,MAAO,OACPC,KAAM,oCACNC,KAAM,YACR,EACA,CACEF,MAAO,wBACPC,KAAM,gCACNC,KAAM,0BACR,EACD,AAAC,AAEF,QAAO,MAAMC,YAAiC,CAC5C,CACEH,MAAO,iBACPE,KAAM,yBACR,EACA,CACEF,MAAO,iBACPE,KAAM,yBACR,EACA,CACEF,MAAO,oBACPE,KAAM,2BACR,EACD,AAAC,AAEF,QAAO,MAAME,cAAmC,CAC9C,CACEJ,MAAO,iBACPC,KAAM,iCACNC,KAAM,kBACNG,YAAa,8DACf,EACA,CACEL,MAAO,UACPC,KAAM,mCACNC,KAAM,YACNG,YACE,+DACJ,EACA,CACEL,MAAO,SACPC,KAAM,gCACNC,KAAM,WACNG,YAAa,yDACf,EACA,CACEL,MAAO,SACPC,KAAM,8BACNC,KAAM,WACNG,YACE,iEACJ,EAEA,CACEL,MAAO,aACPC,KAAM,6BACNC,KAAM,eACNG,YAAa,uDACf,EACD,AAAC,AAEF,QAAO,MAAMC,yBAAmD,CAC9DC,YAAaV,aACbW,gBAAiBV,YACjBW,YAAa,6BACbC,YAAa,MACbC,YACE,mHACJ,CAAE,AAEF,QAAO,MAAMC,YAAiC,CAC5C,CACEZ,MAAO,YACPC,KAAM,sBACNC,KAAM,QACR,EACA,CACEF,MAAO,UACPC,KAAM,6BACNC,KAAM,WACNW,MAAO,cACT,EACD,AAAC,AAEF,QAAO,MAAMC,WAAa,CACxB,CACEC,MAAOpB,wBACPqB,KAAM,6BACR,EACA,CACED,MAAOtB,kCACPuB,KAAM,wCACR,EACA,CACED,MAAOrB,wBACPsB,KAAM,6BACR,EACD,AAAC,AAEF,QAAO,MAAMC,cAAgB,CAC3B,CAAEC,KAAM,UAAWhB,KAAM,WAAYiB,eAAgB,IAAK,EAC1D,CAAED,KAAM,OAAQhB,KAAM,QAASiB,eAAgB,IAAK,EACrD,AAAC,AAEF,QAAO,MAAMC,iBAA+B,CAC1C,CACEC,MACE,4EACFnB,KAAM,0BACNoB,WAAY,CACV,cACA,eACA,cACA,uBACA,cACA,YACD,CACDC,QAAS,aACX,EACA,CACEF,MACE,iFACFnB,KAAM,qCACNoB,WAAY,CAAC,OAAO,CACpBC,QAAS,cACX,EACD,AAAC,AAEF,QAAO,MAAMC,eAAiB,CAC5B,GAAG5B,QAAQ,CACX6B,OAAQ,CAAE,GAAG7B,SAAS6B,MAAM,CAAEvB,KAAM,SAAU,EAC9CwB,SAAU,CAAE,GAAG9B,SAAS8B,QAAQ,CAAExB,KAAM,WAAY,EACpDyB,KAAM,CAAE,GAAG/B,SAAS+B,IAAI,CAAEzB,KAAM,OAAQ,EACxC0B,OAAQ,CAAE,GAAGhC,SAASgC,MAAM,CAAE1B,KAAM,SAAU,EAC9C2B,YAAa,CACX,GAAGjC,SAASiC,WAAW,CACvB3B,KAAM,eACR,EACA4B,YAAa,CAAE,GAAGlC,SAASkC,WAAW,CAAE5B,KAAM,cAAe,CAC/D,CAAE"}
@@ -0,0 +1,5 @@
1
+ <svg width="244" height="122" viewBox="0 0 244 122" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M153.262 81.5712H146.407V50.7141H153.262V81.5712ZM153.262 47.286H146.407V40.4287H153.262V47.286ZM124.127 81.5712H117.271V40.4287H142.979V47.286H124.126V57.5718H142.979V64.4291H124.126V81.5717L124.127 81.5712Z" fill="white"/>
3
+ <path d="M163.545 54.5714V50.7142H156.69V81.5713L163.545 81.5665V65.5711C163.545 59.2495 166.902 55.9994 171.686 55.9994C176.47 55.9994 178.434 59.8922 178.399 65.6066V81.5708H185.254V64.2851C185.29 54.1778 180.006 50.1809 173.361 50.1089C169.643 50.1089 165.676 51.4284 163.545 54.5709V54.5714Z" fill="white"/>
4
+ <path d="M100.324 67.6661C104.042 67.6661 107.05 64.6196 106.987 60.8866C106.926 57.231 103.868 54.3337 100.213 54.3337H97.6566C95.7453 54.3337 93.9922 53.6617 92.6169 52.5428C92.4835 52.4348 92.4835 52.2323 92.6169 52.1243C93.9922 51.0059 95.7453 50.3339 97.6566 50.3339H100.205C103.924 50.3339 107.014 47.3392 106.987 43.6197C106.961 39.8997 104.013 37.0264 100.37 37.001C96.6518 36.9741 93.6578 40.0662 93.6578 43.7848V46.334C93.6578 48.2459 92.9859 49.9993 91.8678 51.375C91.7598 51.5084 91.5573 51.5084 91.4494 51.375C90.3312 49.9988 89.6594 48.2459 89.6594 46.334V43.6677C89.6594 39.9477 86.6136 36.9381 82.8815 37.001C79.2268 37.0624 76.3302 40.121 76.3302 43.7766V46.334C76.3302 48.2459 75.6584 49.9993 74.5402 51.375C74.4323 51.5084 74.2297 51.5084 74.1218 51.375C73.0036 49.9988 72.3318 48.2459 72.3318 46.334V43.6677C72.3313 39.8997 69.2059 36.8608 65.4071 37.0062C61.9534 37.1368 59.1384 39.953 59.0065 43.4075C58.8625 47.2072 61.8987 50.3339 65.6658 50.3339H68.3315C70.2429 50.3339 71.9959 51.0059 73.3712 52.1243C73.5046 52.2323 73.5046 52.4348 73.3712 52.5428C71.9959 53.6617 70.2429 54.3337 68.3315 54.3337H65.7752C62.1199 54.3337 59.0621 57.2305 59.0012 60.8866C58.9397 64.5423 61.9457 67.6661 65.6643 67.6661H68.3301C70.2414 67.6661 71.9945 68.3381 73.3698 69.4565C73.5032 69.5645 73.5032 69.7671 73.3698 69.8751C71.994 70.9939 70.2414 71.6659 68.3301 71.6659H65.6643C61.8973 71.6659 58.8596 74.7926 59.005 78.5923C59.1355 82.0468 61.9505 84.863 65.4057 84.9935C69.2044 85.1375 72.3304 82.1006 72.3304 78.3326V75.6662C72.3304 73.7544 73.0022 72.001 74.1203 70.6253C74.2283 70.4923 74.4308 70.4923 74.5388 70.6253C75.6569 72.0014 76.3287 73.7544 76.3287 75.6662V78.2232C76.3287 81.8788 79.2253 84.9374 82.8801 84.9988C86.6136 85.0617 89.658 82.0536 89.658 78.3341V75.6677C89.658 73.7558 90.3298 72.0024 91.4479 70.6267C91.5559 70.4933 91.7584 70.4933 91.8664 70.6267C92.9845 72.0024 93.6563 73.7558 93.6563 75.6677V78.3341C93.6563 82.102 96.7823 85.1404 100.581 84.995C104.035 84.8644 106.85 82.0483 106.98 78.5923C107.124 74.7926 104.088 71.6659 100.321 71.6659H97.6552C95.7438 71.6659 93.9908 70.9939 92.6155 69.8751C92.4821 69.7671 92.4821 69.5645 92.6155 69.4565C93.9908 68.3381 95.7438 67.6661 97.6552 67.6661H100.324ZM80.3314 50.3339H85.6629C87.5743 50.3339 89.3273 51.0059 90.7027 52.1243C90.8361 52.2323 90.8361 52.4348 90.7027 52.5428C89.3273 53.6617 87.5743 54.3337 85.6629 54.3337H80.3314C78.4201 54.3337 76.6671 53.6617 75.2917 52.5428C75.1583 52.4348 75.1583 52.2323 75.2917 52.1243C76.6671 51.0059 78.4201 50.3339 80.3314 50.3339ZM72.3342 60.9999V58.3335C72.3342 56.4217 73.006 54.6682 74.1242 53.2926C74.2321 53.1591 74.4347 53.1591 74.5426 53.2926C75.6612 54.6687 76.3326 56.4217 76.3326 58.3335V63.6653C76.3326 65.5772 75.6608 67.3306 74.5426 68.7063C74.4347 68.8392 74.2321 68.8392 74.1242 68.7063C73.006 67.3301 72.3342 65.5772 72.3342 63.6653V60.9989V61.0004V60.9999ZM85.6634 71.6659H80.3319C78.4206 71.6659 76.6675 70.9939 75.2922 69.8751C75.1588 69.7671 75.1588 69.5645 75.2922 69.4565C76.6675 68.3381 78.4206 67.6661 80.3319 67.6661H85.6634C87.5748 67.6661 89.3278 68.3381 90.7031 69.4565C90.8365 69.5645 90.8365 69.7671 90.7031 69.8751C89.3278 70.9939 87.5748 71.6659 85.6634 71.6659ZM93.6606 60.9999V63.6663C93.6606 65.5781 92.9888 67.3315 91.8707 68.7072C91.7627 68.8407 91.5602 68.8407 91.4522 68.7072C90.3341 67.3315 89.6623 65.5781 89.6623 63.6663V58.333C89.6623 56.4212 90.3341 54.6678 91.4522 53.2921C91.5602 53.1587 91.7627 53.1587 91.8707 53.2921C92.9888 54.6682 93.6606 56.4212 93.6606 58.333V60.9994V60.9999Z" fill="white"/>
5
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="244" height="122" viewBox="0 0 244 122" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M153.262 81.5712H146.407V50.7141H153.262V81.5712ZM153.262 47.286H146.407V40.4287H153.262V47.286ZM124.127 81.5712H117.271V40.4287H142.979V47.286H124.126V57.5718H142.979V64.4291H124.126V81.5717L124.127 81.5712Z" fill="#03020D"/>
3
+ <path d="M163.545 54.5714V50.7142H156.69V81.5713L163.545 81.5665V65.5711C163.545 59.2495 166.902 55.9994 171.686 55.9994C176.471 55.9994 178.434 59.8922 178.399 65.6066V81.5708H185.254V64.2851C185.29 54.1778 180.006 50.1809 173.361 50.1089C169.643 50.1089 165.676 51.4284 163.545 54.5709V54.5714Z" fill="#03020D"/>
4
+ <path d="M100.324 67.6661C104.042 67.6661 107.05 64.6196 106.987 60.8866C106.926 57.231 103.868 54.3337 100.213 54.3337H97.6566C95.7453 54.3337 93.9922 53.6617 92.6169 52.5428C92.4835 52.4348 92.4835 52.2323 92.6169 52.1243C93.9922 51.0059 95.7453 50.3339 97.6566 50.3339H100.205C103.924 50.3339 107.014 47.3392 106.987 43.6197C106.961 39.8997 104.013 37.0264 100.37 37.001C96.6518 36.9741 93.6578 40.0662 93.6578 43.7848V46.334C93.6578 48.2459 92.9859 49.9993 91.8678 51.375C91.7598 51.5084 91.5573 51.5084 91.4494 51.375C90.3312 49.9988 89.6594 48.2459 89.6594 46.334V43.6677C89.6594 39.9477 86.6136 36.9381 82.8815 37.001C79.2268 37.0624 76.3302 40.121 76.3302 43.7766V46.334C76.3302 48.2459 75.6584 49.9993 74.5402 51.375C74.4323 51.5084 74.2297 51.5084 74.1218 51.375C73.0036 49.9988 72.3318 48.2459 72.3318 46.334V43.6677C72.3313 39.8997 69.2059 36.8608 65.4071 37.0062C61.9534 37.1368 59.1384 39.953 59.0065 43.4075C58.8625 47.2072 61.8987 50.3339 65.6658 50.3339H68.3315C70.2429 50.3339 71.9959 51.0059 73.3712 52.1243C73.5046 52.2323 73.5046 52.4348 73.3712 52.5428C71.9959 53.6617 70.2429 54.3337 68.3315 54.3337H65.7752C62.1199 54.3337 59.0621 57.2305 59.0012 60.8866C58.9397 64.5423 61.9457 67.6661 65.6643 67.6661H68.3301C70.2414 67.6661 71.9945 68.3381 73.3698 69.4565C73.5032 69.5645 73.5032 69.7671 73.3698 69.8751C71.994 70.9939 70.2414 71.6659 68.3301 71.6659H65.6643C61.8973 71.6659 58.8596 74.7926 59.005 78.5923C59.1355 82.0468 61.9505 84.863 65.4057 84.9935C69.2044 85.1375 72.3304 82.1006 72.3304 78.3326V75.6662C72.3304 73.7544 73.0022 72.001 74.1203 70.6253C74.2283 70.4923 74.4308 70.4923 74.5388 70.6253C75.6569 72.0014 76.3287 73.7544 76.3287 75.6662V78.2232C76.3287 81.8788 79.2253 84.9374 82.8801 84.9988C86.6136 85.0617 89.658 82.0536 89.658 78.3341V75.6677C89.658 73.7558 90.3298 72.0024 91.4479 70.6267C91.5559 70.4933 91.7584 70.4933 91.8664 70.6267C92.9845 72.0024 93.6563 73.7558 93.6563 75.6677V78.3341C93.6563 82.102 96.7823 85.1404 100.581 84.995C104.035 84.8644 106.85 82.0483 106.98 78.5923C107.124 74.7926 104.088 71.6659 100.321 71.6659H97.6552C95.7438 71.6659 93.9908 70.9939 92.6155 69.8751C92.4821 69.7671 92.4821 69.5645 92.6155 69.4565C93.9908 68.3381 95.7438 67.6661 97.6552 67.6661H100.324ZM80.3314 50.3339H85.6629C87.5743 50.3339 89.3273 51.0059 90.7027 52.1243C90.8361 52.2323 90.8361 52.4348 90.7027 52.5428C89.3273 53.6617 87.5743 54.3337 85.6629 54.3337H80.3314C78.4201 54.3337 76.6671 53.6617 75.2917 52.5428C75.1583 52.4348 75.1583 52.2323 75.2917 52.1243C76.6671 51.0059 78.4201 50.3339 80.3314 50.3339ZM72.3342 60.9999V58.3335C72.3342 56.4217 73.006 54.6682 74.1242 53.2926C74.2321 53.1591 74.4347 53.1591 74.5426 53.2926C75.6612 54.6687 76.3326 56.4217 76.3326 58.3335V63.6653C76.3326 65.5772 75.6608 67.3306 74.5426 68.7063C74.4347 68.8392 74.2321 68.8392 74.1242 68.7063C73.006 67.3301 72.3342 65.5772 72.3342 63.6653V60.9989V61.0004V60.9999ZM85.6634 71.6659H80.3319C78.4206 71.6659 76.6675 70.9939 75.2922 69.8751C75.1588 69.7671 75.1588 69.5645 75.2922 69.4565C76.6675 68.3381 78.4206 67.6661 80.3319 67.6661H85.6634C87.5748 67.6661 89.3278 68.3381 90.7031 69.4565C90.8365 69.5645 90.8365 69.7671 90.7031 69.8751C89.3278 70.9939 87.5748 71.6659 85.6634 71.6659ZM93.6606 60.9999V63.6663C93.6606 65.5781 92.9888 67.3315 91.8707 68.7072C91.7627 68.8407 91.5602 68.8407 91.4522 68.7072C90.3341 67.3315 89.6623 65.5781 89.6623 63.6663V58.333C89.6623 56.4212 90.3341 54.6678 91.4522 53.2921C91.5602 53.1587 91.7627 53.1587 91.8707 53.2921C92.9888 54.6682 93.6606 56.4212 93.6606 58.333V60.9994V60.9999Z" fill="#03020D"/>
5
+ </svg>
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Notice.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport DOMPurify from \"dompurify\";\n\nimport { ColorClass, ColorThemeSet } from \"./styles/colors/types\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn.js\";\nimport NoticeScripts from \"./Notice/component.js\";\nimport useRailsUjsLinks from \"./hooks/use-rails-ujs-hooks\";\n\n// TODO(jamiehenson):\n// This type is a bit messed up currently due to the NoticeScripts import being interpreted as NoticeProps.\n// Plan is to TS-ify the JS assets too, so this can be rectified then. The NoticeScripts-oriented props are\n// the ones after the line break.\nexport type NoticeProps = {\n buttonLink?: string;\n buttonLabel?: string;\n bodyText?: string;\n title?: string;\n closeBtn?: boolean;\n config?: {\n options: {\n collapse: boolean;\n };\n noticeId: string | number;\n cookieId: string;\n };\n bgColor?: string;\n textColor?: ColorClass | ColorThemeSet;\n onClose?: () => void;\n\n bannerContainer?: Element | null;\n cookieId?: string;\n noticeId?: string;\n options?: { collapse: boolean };\n};\n\nconst defaultTextColor = \"text-neutral-1300 dark:text-neutral-000\";\n\nconst contentWrapperClasses = \"w-full pr-2 ui-text-p4 self-center\";\n\nconst Notice = ({\n buttonLink,\n buttonLabel,\n bodyText,\n title,\n config,\n closeBtn,\n bgColor = \"bg-orange-100 dark:bg-orange-1100\",\n textColor = defaultTextColor,\n onClose,\n}: NoticeProps) => {\n const contentRef = useRef<HTMLSpanElement>(null);\n const [isClosing, setIsClosing] = useState(false);\n useRailsUjsLinks(contentRef);\n\n useEffect(() => {\n const cleanup = NoticeScripts({\n bannerContainer: document.querySelector('[data-id=\"ui-notice\"]'),\n cookieId: config?.cookieId,\n noticeId: config?.noticeId,\n options: {\n collapse: config?.options?.collapse || false,\n },\n });\n\n return cleanup;\n }, [config?.cookieId, config?.noticeId, config?.options?.collapse]);\n\n const safeContent = DOMPurify.sanitize(bodyText ?? \"\", {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\"],\n ALLOWED_URI_REGEXP: /^\\/[^/]/,\n });\n\n const isSafeButtonLink =\n typeof buttonLink === \"string\" &&\n (/^\\/(?!\\/)/.test(buttonLink) || /^https?:\\/\\//.test(buttonLink));\n\n // have to add the style classes here as src/core/Notice/component.css is not being properly imported or distributed when ably-ui is used as a package.\n return (\n <div\n className={cn(\n \"ui-announcement relative z-[60]\",\n isClosing\n ? \"ui-announcement-hidden max-h-0 -translate-y-full opacity-0 overflow-hidden\"\n : \"ui-announcement-visible\",\n bgColor,\n textColor,\n )}\n data-id=\"ui-notice\"\n >\n <div className=\"ui-grid-px py-4 max-w-screen-xl mx-auto flex items-start\">\n <div className={cn(contentWrapperClasses, textColor)}>\n <strong className=\"font-bold whitespace-nowrap pr-1\">{title}</strong>\n <span\n ref={contentRef}\n className=\"pr-1\"\n // Sanitised inline-markup allowlist (a + relative href) applied above\n // via DOMPurify. Slice 3a replaces the local config with the shared\n // sanitizeInlineMarkup helper.\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: safeContent,\n }}\n ></span>\n {buttonLabel &&\n (isSafeButtonLink ? (\n <a\n href={buttonLink}\n className=\"focus-base transition-colors cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark\"\n >\n {buttonLabel}\n </a>\n ) : (\n <span className=\"focus-base transition-colors cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark\">\n {buttonLabel}\n </span>\n ))}\n </div>\n\n {closeBtn && (\n <button\n type=\"button\"\n className=\"ml-auto h-5 w-5 border-none bg-none self-baseline outline-none focus:outline-none focus:ring-0 focus:border-transparent\"\n onClick={() => {\n setIsClosing(true);\n setTimeout(() => {\n document.dispatchEvent(new CustomEvent(\"notice-closed\"));\n onClose?.();\n }, 300);\n }}\n >\n <Icon\n name=\"icon-gui-x-mark-outline\"\n size=\"1.25rem\"\n color={textColor}\n />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default Notice;\n"],"names":["React","useEffect","useRef","useState","DOMPurify","Icon","cn","NoticeScripts","useRailsUjsLinks","defaultTextColor","contentWrapperClasses","Notice","buttonLink","buttonLabel","bodyText","title","config","closeBtn","bgColor","textColor","onClose","contentRef","isClosing","setIsClosing","cleanup","bannerContainer","document","querySelector","cookieId","noticeId","options","collapse","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","ALLOWED_URI_REGEXP","isSafeButtonLink","test","div","className","data-id","strong","span","ref","dangerouslySetInnerHTML","__html","a","href","button","type","onClick","setTimeout","dispatchEvent","CustomEvent","name","size","color"],"mappings":"AAAA,OAAOA,OAASC,SAAS,CAAEC,MAAM,CAAEC,QAAQ,KAAQ,OAAQ,AAC3D,QAAOC,cAAe,WAAY,AAGlC,QAAOC,SAAU,QAAS,AAC1B,QAAOC,OAAQ,eAAgB,AAC/B,QAAOC,kBAAmB,uBAAwB,AAClD,QAAOC,qBAAsB,6BAA8B,CA6B3D,MAAMC,iBAAmB,0CAEzB,MAAMC,sBAAwB,qCAE9B,MAAMC,OAAS,CAAC,CACdC,UAAU,CACVC,WAAW,CACXC,QAAQ,CACRC,KAAK,CACLC,MAAM,CACNC,QAAQ,CACRC,QAAU,mCAAmC,CAC7CC,UAAYV,gBAAgB,CAC5BW,OAAO,CACK,IACZ,MAAMC,WAAanB,OAAwB,MAC3C,KAAM,CAACoB,UAAWC,aAAa,CAAGpB,SAAS,OAC3CK,iBAAiBa,YAEjBpB,UAAU,KACR,MAAMuB,QAAUjB,cAAc,CAC5BkB,gBAAiBC,SAASC,aAAa,CAAC,yBACxCC,SAAUZ,QAAQY,SAClBC,SAAUb,QAAQa,SAClBC,QAAS,CACPC,SAAUf,QAAQc,SAASC,UAAY,KACzC,CACF,GAEA,OAAOP,OACT,EAAG,CAACR,QAAQY,SAAUZ,QAAQa,SAAUb,QAAQc,SAASC,SAAS,EAElE,MAAMC,YAAc5B,UAAU6B,QAAQ,CAACnB,UAAY,GAAI,CACrDoB,aAAc,CAAC,IAAI,CACnBC,aAAc,CAAC,OAAQ,cAAc,CACrCC,mBAAoB,SACtB,GAEA,MAAMC,iBACJ,OAAOzB,aAAe,UACrB,CAAA,YAAY0B,IAAI,CAAC1B,aAAe,eAAe0B,IAAI,CAAC1B,WAAU,EAGjE,OACE,oBAAC2B,OACCC,UAAWlC,GACT,kCACAgB,UACI,6EACA,0BACJJ,QACAC,WAEFsB,UAAQ,aAER,oBAACF,OAAIC,UAAU,4DACb,oBAACD,OAAIC,UAAWlC,GAAGI,sBAAuBS,YACxC,oBAACuB,UAAOF,UAAU,oCAAoCzB,OACtD,oBAAC4B,QACCC,IAAKvB,WACLmB,UAAU,OAKVK,wBAAyB,CACvBC,OAAQd,WACV,IAEDnB,aACEwB,CAAAA,iBACC,oBAACU,KACCC,KAAMpC,WACN4B,UAAU,6HAET3B,aAGH,oBAAC8B,QAAKH,UAAU,6HACb3B,YAEL,GAGHI,UACC,oBAACgC,UACCC,KAAK,SACLV,UAAU,0HACVW,QAAS,KACP5B,aAAa,MACb6B,WAAW,KACT1B,SAAS2B,aAAa,CAAC,IAAIC,YAAY,kBACvClC,WACF,EAAG,IACL,GAEA,oBAACf,MACCkD,KAAK,0BACLC,KAAK,UACLC,MAAOtC,cAOrB,CAEA,gBAAeR,MAAO"}
1
+ {"version":3,"sources":["../../src/core/Notice.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport DOMPurify from \"dompurify\";\n\nimport { ColorClass, ColorThemeSet } from \"./styles/colors/types\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn.js\";\nimport NoticeScripts from \"./Notice/component.js\";\nimport useRailsUjsLinks from \"./hooks/use-rails-ujs-hooks\";\n\n// TODO(jamiehenson):\n// This type is a bit messed up currently due to the NoticeScripts import being interpreted as NoticeProps.\n// Plan is to TS-ify the JS assets too, so this can be rectified then. The NoticeScripts-oriented props are\n// the ones after the line break.\nexport type NoticeProps = {\n buttonLink?: string;\n buttonLabel?: string;\n bodyText?: string;\n title?: string;\n closeBtn?: boolean;\n config?: {\n options: {\n collapse: boolean;\n };\n noticeId: string | number;\n cookieId: string;\n };\n bgColor?: string;\n textColor?: ColorClass | ColorThemeSet;\n onClose?: () => void;\n\n bannerContainer?: Element | null;\n cookieId?: string;\n noticeId?: string;\n options?: { collapse: boolean };\n};\n\nconst defaultTextColor = \"text-neutral-1300 dark:text-neutral-000\";\n\nconst contentWrapperClasses = \"w-full pr-2 ui-text-p4 self-center\";\n\nconst Notice = ({\n buttonLink,\n buttonLabel,\n bodyText,\n title,\n config,\n closeBtn,\n bgColor = \"bg-orange-100 dark:bg-orange-1100\",\n textColor = defaultTextColor,\n onClose,\n}: NoticeProps) => {\n const contentRef = useRef<HTMLSpanElement>(null);\n const [isClosing, setIsClosing] = useState(false);\n useRailsUjsLinks(contentRef);\n\n useEffect(() => {\n const cleanup = NoticeScripts({\n bannerContainer: document.querySelector('[data-id=\"ui-notice\"]'),\n cookieId: config?.cookieId,\n noticeId: config?.noticeId,\n options: {\n collapse: config?.options?.collapse || false,\n },\n });\n\n return cleanup;\n }, [config?.cookieId, config?.noticeId, config?.options?.collapse]);\n\n const safeContent = DOMPurify.sanitize(bodyText ?? \"\", {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\"],\n ALLOWED_URI_REGEXP: /^\\/[^/]/,\n });\n\n const isSafeButtonLink =\n typeof buttonLink === \"string\" &&\n (/^\\/(?!\\/)/.test(buttonLink) || /^https?:\\/\\//.test(buttonLink));\n\n // have to add the style classes here as src/core/Notice/component.css is not being properly imported or distributed when ably-ui is used as a package.\n return (\n <div\n className={cn(\n \"ui-announcement relative z-[60]\",\n isClosing\n ? \"ui-announcement-hidden max-h-0 -translate-y-full opacity-0 overflow-hidden\"\n : \"ui-announcement-visible\",\n bgColor,\n textColor,\n )}\n data-id=\"ui-notice\"\n >\n <div className=\"ui-grid-px py-4 max-w-screen-xl mx-auto flex items-start\">\n <div className={cn(contentWrapperClasses, textColor)}>\n <strong className=\"font-bold whitespace-nowrap pr-1\">{title}</strong>\n <span\n ref={contentRef}\n className=\"pr-1\"\n // Sanitised inline-markup allowlist (a + relative href) applied above\n // via DOMPurify. Slice 3a replaces the local config with the shared\n // sanitizeInlineMarkup helper.\n // oxlint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: safeContent,\n }}\n ></span>\n {buttonLabel &&\n (isSafeButtonLink ? (\n <a\n href={buttonLink}\n className=\"focus-base transition-colors cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark\"\n >\n {buttonLabel}\n </a>\n ) : (\n <span className=\"focus-base transition-colors cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark\">\n {buttonLabel}\n </span>\n ))}\n </div>\n\n {closeBtn && (\n <button\n type=\"button\"\n className=\"ml-auto h-5 w-5 border-none bg-none self-baseline outline-none focus:outline-none focus:ring-0 focus:border-transparent\"\n onClick={() => {\n setIsClosing(true);\n setTimeout(() => {\n document.dispatchEvent(new CustomEvent(\"notice-closed\"));\n onClose?.();\n }, 300);\n }}\n >\n <Icon\n name=\"icon-gui-x-mark-outline\"\n size=\"1.25rem\"\n color={textColor}\n />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default Notice;\n"],"names":["React","useEffect","useRef","useState","DOMPurify","Icon","cn","NoticeScripts","useRailsUjsLinks","defaultTextColor","contentWrapperClasses","Notice","buttonLink","buttonLabel","bodyText","title","config","closeBtn","bgColor","textColor","onClose","contentRef","isClosing","setIsClosing","cleanup","bannerContainer","document","querySelector","cookieId","noticeId","options","collapse","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","ALLOWED_URI_REGEXP","isSafeButtonLink","test","div","className","data-id","strong","span","ref","dangerouslySetInnerHTML","__html","a","href","button","type","onClick","setTimeout","dispatchEvent","CustomEvent","name","size","color"],"mappings":"AAAA,OAAOA,OAASC,SAAS,CAAEC,MAAM,CAAEC,QAAQ,KAAQ,OAAQ,AAC3D,QAAOC,cAAe,WAAY,AAGlC,QAAOC,SAAU,QAAS,AAC1B,QAAOC,OAAQ,eAAgB,AAC/B,QAAOC,kBAAmB,uBAAwB,AAClD,QAAOC,qBAAsB,6BAA8B,CA6B3D,MAAMC,iBAAmB,0CAEzB,MAAMC,sBAAwB,qCAE9B,MAAMC,OAAS,CAAC,CACdC,UAAU,CACVC,WAAW,CACXC,QAAQ,CACRC,KAAK,CACLC,MAAM,CACNC,QAAQ,CACRC,QAAU,mCAAmC,CAC7CC,UAAYV,gBAAgB,CAC5BW,OAAO,CACK,IACZ,MAAMC,WAAanB,OAAwB,MAC3C,KAAM,CAACoB,UAAWC,aAAa,CAAGpB,SAAS,OAC3CK,iBAAiBa,YAEjBpB,UAAU,KACR,MAAMuB,QAAUjB,cAAc,CAC5BkB,gBAAiBC,SAASC,aAAa,CAAC,yBACxCC,SAAUZ,QAAQY,SAClBC,SAAUb,QAAQa,SAClBC,QAAS,CACPC,SAAUf,QAAQc,SAASC,UAAY,KACzC,CACF,GAEA,OAAOP,OACT,EAAG,CAACR,QAAQY,SAAUZ,QAAQa,SAAUb,QAAQc,SAASC,SAAS,EAElE,MAAMC,YAAc5B,UAAU6B,QAAQ,CAACnB,UAAY,GAAI,CACrDoB,aAAc,CAAC,IAAI,CACnBC,aAAc,CAAC,OAAQ,cAAc,CACrCC,mBAAoB,SACtB,GAEA,MAAMC,iBACJ,OAAOzB,aAAe,UACrB,CAAA,YAAY0B,IAAI,CAAC1B,aAAe,eAAe0B,IAAI,CAAC1B,WAAU,EAGjE,OACE,oBAAC2B,OACCC,UAAWlC,GACT,kCACAgB,UACI,6EACA,0BACJJ,QACAC,WAEFsB,UAAQ,aAER,oBAACF,OAAIC,UAAU,4DACb,oBAACD,OAAIC,UAAWlC,GAAGI,sBAAuBS,YACxC,oBAACuB,UAAOF,UAAU,oCAAoCzB,OACtD,oBAAC4B,QACCC,IAAKvB,WACLmB,UAAU,OAKVK,wBAAyB,CACvBC,OAAQd,WACV,IAEDnB,aACEwB,CAAAA,iBACC,oBAACU,KACCC,KAAMpC,WACN4B,UAAU,6HAET3B,aAGH,oBAAC8B,QAAKH,UAAU,6HACb3B,YAEL,GAGHI,UACC,oBAACgC,UACCC,KAAK,SACLV,UAAU,0HACVW,QAAS,KACP5B,aAAa,MACb6B,WAAW,KACT1B,SAAS2B,aAAa,CAAC,IAAIC,YAAY,kBACvClC,WACF,EAAG,IACL,GAEA,oBAACf,MACCkD,KAAK,0BACLC,KAAK,UACLC,MAAOtC,cAOrB,CAEA,gBAAeR,MAAO"}
@@ -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"}}],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",isPriority:true},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"}];
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:"/sign-up?next=package",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:"/sign-up?next=package",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",isPriority:true},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