@ably/ui 17.4.2 → 17.4.3

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 (339) hide show
  1. package/AGENTS.md +573 -0
  2. package/README.md +120 -68
  3. package/core/Accordion/types.js.map +1 -1
  4. package/core/Accordion/utils.js +1 -1
  5. package/core/Accordion/utils.js.map +1 -1
  6. package/core/Accordion.js +1 -1
  7. package/core/Accordion.js.map +1 -1
  8. package/core/Badge.js +1 -1
  9. package/core/Badge.js.map +1 -1
  10. package/core/Code/Code.test.js +2 -0
  11. package/core/Code/Code.test.js.map +1 -0
  12. package/core/Code.js +1 -1
  13. package/core/Code.js.map +1 -1
  14. package/core/CodeSnippet/ApiKeySelector.js +1 -1
  15. package/core/CodeSnippet/ApiKeySelector.js.map +1 -1
  16. package/core/CodeSnippet/CodeSnippet.test.js +2 -0
  17. package/core/CodeSnippet/CodeSnippet.test.js.map +1 -0
  18. package/core/CodeSnippet/CopyButton.js +1 -1
  19. package/core/CodeSnippet/CopyButton.js.map +1 -1
  20. package/core/CodeSnippet/LanguageSelector.js +1 -1
  21. package/core/CodeSnippet/LanguageSelector.js.map +1 -1
  22. package/core/CodeSnippet/PlainCodeView.js +1 -1
  23. package/core/CodeSnippet/PlainCodeView.js.map +1 -1
  24. package/core/CodeSnippet/TooltipButton.js +1 -1
  25. package/core/CodeSnippet/TooltipButton.js.map +1 -1
  26. package/core/CodeSnippet/languages.js +1 -1
  27. package/core/CodeSnippet/languages.js.map +1 -1
  28. package/core/CodeSnippet/languages.test.js +2 -0
  29. package/core/CodeSnippet/languages.test.js.map +1 -0
  30. package/core/CodeSnippet.js +1 -1
  31. package/core/CodeSnippet.js.map +1 -1
  32. package/core/ConnectStateWrapper.js.map +1 -1
  33. package/core/ContentTile.js +2 -0
  34. package/core/ContentTile.js.map +1 -0
  35. package/core/DropdownMenu.js +1 -1
  36. package/core/DropdownMenu.js.map +1 -1
  37. package/core/Expander.js +1 -1
  38. package/core/Expander.js.map +1 -1
  39. package/core/FeaturedLink.js +1 -1
  40. package/core/FeaturedLink.js.map +1 -1
  41. package/core/Flash.js +1 -1
  42. package/core/Flash.js.map +1 -1
  43. package/core/Flyout.js +1 -1
  44. package/core/Flyout.js.map +1 -1
  45. package/core/Footer/data.js +1 -1
  46. package/core/Footer/data.js.map +1 -1
  47. package/core/Footer.js +1 -1
  48. package/core/Footer.js.map +1 -1
  49. package/core/Header/HeaderLinks.js +1 -1
  50. package/core/Header/HeaderLinks.js.map +1 -1
  51. package/core/Header/types.js +2 -0
  52. package/core/Header/types.js.map +1 -0
  53. package/core/Header.js +1 -1
  54. package/core/Header.js.map +1 -1
  55. package/core/Icon/components/icon-display-cloud-servers-mono.js +2 -0
  56. package/core/Icon/components/icon-display-cloud-servers-mono.js.map +1 -0
  57. package/core/Icon/components/icon-display-data-integrity.js +2 -0
  58. package/core/Icon/components/icon-display-data-integrity.js.map +1 -0
  59. package/core/Icon/components/icon-display-database-connector.js +2 -0
  60. package/core/Icon/components/icon-display-database-connector.js.map +1 -0
  61. package/core/Icon/components/icon-display-ephemeral-messages-dark-col.js +2 -0
  62. package/core/Icon/components/icon-display-ephemeral-messages-dark-col.js.map +1 -0
  63. package/core/Icon/components/icon-display-ephemeral-messages.js +2 -0
  64. package/core/Icon/components/icon-display-ephemeral-messages.js.map +1 -0
  65. package/core/Icon/components/icon-display-live-updates.js +2 -0
  66. package/core/Icon/components/icon-display-live-updates.js.map +1 -0
  67. package/core/Icon/components/icon-display-message-annotations-dark-col.js +2 -0
  68. package/core/Icon/components/icon-display-message-annotations-dark-col.js.map +1 -0
  69. package/core/Icon/components/icon-display-message-annotations.js +2 -0
  70. package/core/Icon/components/icon-display-message-annotations.js.map +1 -0
  71. package/core/Icon/components/icon-display-multi-user-spaces.js +2 -0
  72. package/core/Icon/components/icon-display-multi-user-spaces.js.map +1 -0
  73. package/core/Icon/components/icon-display-sdks.js +2 -0
  74. package/core/Icon/components/icon-display-sdks.js.map +1 -0
  75. package/core/Icon/components/icon-display-something-else-mono.js +2 -0
  76. package/core/Icon/components/icon-display-something-else-mono.js.map +1 -0
  77. package/core/Icon/components/icon-display-something-else.js +2 -0
  78. package/core/Icon/components/icon-display-something-else.js.map +1 -0
  79. package/core/Icon/components/icon-display-ui-mono.js +2 -0
  80. package/core/Icon/components/icon-display-ui-mono.js.map +1 -0
  81. package/core/Icon/components/icon-display-ui.js +2 -0
  82. package/core/Icon/components/icon-display-ui.js.map +1 -0
  83. package/core/Icon/components/icon-gui-checklist-checked.js +1 -1
  84. package/core/Icon/components/icon-gui-checklist-checked.js.map +1 -1
  85. package/core/Icon/components/icon-gui-code-doc.js +1 -1
  86. package/core/Icon/components/icon-gui-code-doc.js.map +1 -1
  87. package/core/Icon/components/icon-gui-cursor.js +1 -1
  88. package/core/Icon/components/icon-gui-cursor.js.map +1 -1
  89. package/core/Icon/components/icon-gui-expand.js +1 -1
  90. package/core/Icon/components/icon-gui-expand.js.map +1 -1
  91. package/core/Icon/components/icon-gui-filter-flow-step-0.js +1 -1
  92. package/core/Icon/components/icon-gui-filter-flow-step-0.js.map +1 -1
  93. package/core/Icon/components/icon-gui-flower-growth.js +1 -1
  94. package/core/Icon/components/icon-gui-flower-growth.js.map +1 -1
  95. package/core/Icon/components/icon-gui-glasses.js +1 -1
  96. package/core/Icon/components/icon-gui-glasses.js.map +1 -1
  97. package/core/Icon/components/icon-gui-heartbeat-outline.js +2 -0
  98. package/core/Icon/components/icon-gui-heartbeat-outline.js.map +1 -0
  99. package/core/Icon/components/icon-gui-heartbeat-solid.js +2 -0
  100. package/core/Icon/components/icon-gui-heartbeat-solid.js.map +1 -0
  101. package/core/Icon/components/icon-gui-mouse.js +1 -1
  102. package/core/Icon/components/icon-gui-mouse.js.map +1 -1
  103. package/core/Icon/components/icon-gui-pitfall.js +1 -1
  104. package/core/Icon/components/icon-gui-pitfall.js.map +1 -1
  105. package/core/Icon/components/icon-gui-prod-ai-transport-outline.js +2 -0
  106. package/core/Icon/components/icon-gui-prod-ai-transport-outline.js.map +1 -0
  107. package/core/Icon/components/icon-gui-prod-ai-transport-solid.js +2 -0
  108. package/core/Icon/components/icon-gui-prod-ai-transport-solid.js.map +1 -0
  109. package/core/Icon/components/icon-gui-quote-marks-fill.js +1 -1
  110. package/core/Icon/components/icon-gui-quote-marks-fill.js.map +1 -1
  111. package/core/Icon/components/icon-product-ai-transport-mono.js +2 -0
  112. package/core/Icon/components/icon-product-ai-transport-mono.js.map +1 -0
  113. package/core/Icon/components/icon-product-ai-transport.js +2 -0
  114. package/core/Icon/components/icon-product-ai-transport.js.map +1 -0
  115. package/core/Icon/components/icon-product-chat-mono.js +1 -1
  116. package/core/Icon/components/icon-product-chat-mono.js.map +1 -1
  117. package/core/Icon/components/icon-product-liveobjects-mono.js +1 -1
  118. package/core/Icon/components/icon-product-liveobjects-mono.js.map +1 -1
  119. package/core/Icon/components/icon-product-livesync-mono.js +1 -1
  120. package/core/Icon/components/icon-product-livesync-mono.js.map +1 -1
  121. package/core/Icon/components/icon-product-pubsub-mono.js +1 -1
  122. package/core/Icon/components/icon-product-pubsub-mono.js.map +1 -1
  123. package/core/Icon/components/icon-product-spaces-mono.js +1 -1
  124. package/core/Icon/components/icon-product-spaces-mono.js.map +1 -1
  125. package/core/Icon/components/icon-tech-claude-mono.js +2 -0
  126. package/core/Icon/components/icon-tech-claude-mono.js.map +1 -0
  127. package/core/Icon/components/icon-tech-claude.js +2 -0
  128. package/core/Icon/components/icon-tech-claude.js.map +1 -0
  129. package/core/Icon/components/icon-tech-jetpack.js +2 -0
  130. package/core/Icon/components/icon-tech-jetpack.js.map +1 -0
  131. package/core/Icon/components/icon-tech-terraform-outline.js +2 -0
  132. package/core/Icon/components/icon-tech-terraform-outline.js.map +1 -0
  133. package/core/Icon/components/index.js +1 -1
  134. package/core/Icon/components/index.js.map +1 -1
  135. package/core/Icon/computed-icons/display-icons.js +1 -1
  136. package/core/Icon/computed-icons/display-icons.js.map +1 -1
  137. package/core/Icon/computed-icons/gui-icons.js +1 -1
  138. package/core/Icon/computed-icons/gui-icons.js.map +1 -1
  139. package/core/Icon/computed-icons/product-icons.js +1 -1
  140. package/core/Icon/computed-icons/product-icons.js.map +1 -1
  141. package/core/Icon/computed-icons/tech-icons.js +1 -1
  142. package/core/Icon/computed-icons/tech-icons.js.map +1 -1
  143. package/core/Icon.js +1 -1
  144. package/core/Icon.js.map +1 -1
  145. package/core/LinkButton.js +1 -1
  146. package/core/LinkButton.js.map +1 -1
  147. package/core/Logo.js +1 -1
  148. package/core/Logo.js.map +1 -1
  149. package/core/Meganav/MeganavBlog.js +2 -0
  150. package/core/Meganav/MeganavBlog.js.map +1 -0
  151. package/core/Meganav/MeganavCustomerStories.js +2 -0
  152. package/core/Meganav/MeganavCustomerStories.js.map +1 -0
  153. package/core/Meganav/MeganavMobile.js +1 -1
  154. package/core/Meganav/MeganavMobile.js.map +1 -1
  155. package/core/Meganav/MeganavPanel.js +1 -1
  156. package/core/Meganav/MeganavPanel.js.map +1 -1
  157. package/core/Meganav/MeganavPanelItemLinks.js +2 -0
  158. package/core/Meganav/MeganavPanelItemLinks.js.map +1 -0
  159. package/core/Meganav/MeganavTile.js +2 -0
  160. package/core/Meganav/MeganavTile.js.map +1 -0
  161. package/core/Meganav/PanelTitle.js +2 -0
  162. package/core/Meganav/PanelTitle.js.map +1 -0
  163. package/core/Meganav/data.js +1 -1
  164. package/core/Meganav/data.js.map +1 -1
  165. package/core/Meganav/images/cust-logo-doxy-dark.png +0 -0
  166. package/core/Meganav/images/cust-logo-doxy-light.png +0 -0
  167. package/core/Meganav/utils/getMenuItemsForHeader.js +2 -0
  168. package/core/Meganav/utils/getMenuItemsForHeader.js.map +1 -0
  169. package/core/Meganav.js +1 -1
  170. package/core/Meganav.js.map +1 -1
  171. package/core/Notice/component.css +9 -3
  172. package/core/Notice/component.js +1 -1
  173. package/core/Notice/component.js.map +1 -1
  174. package/core/Notice.js +1 -1
  175. package/core/Notice.js.map +1 -1
  176. package/core/Pricing/PricingCards.js +1 -1
  177. package/core/Pricing/PricingCards.js.map +1 -1
  178. package/core/Pricing/data.js +1 -1
  179. package/core/Pricing/data.js.map +1 -1
  180. package/core/Pricing/types.js.map +1 -1
  181. package/core/ProductTile/ProductDescription.js +1 -1
  182. package/core/ProductTile/ProductDescription.js.map +1 -1
  183. package/core/ProductTile/ProductIcon.js +1 -1
  184. package/core/ProductTile/ProductIcon.js.map +1 -1
  185. package/core/ProductTile/ProductLabel.js +1 -1
  186. package/core/ProductTile/ProductLabel.js.map +1 -1
  187. package/core/ProductTile/data.js +1 -1
  188. package/core/ProductTile/data.js.map +1 -1
  189. package/core/ProductTile.js +1 -1
  190. package/core/ProductTile.js.map +1 -1
  191. package/core/SegmentedControl.js +1 -1
  192. package/core/SegmentedControl.js.map +1 -1
  193. package/core/Slider/component.js +1 -1
  194. package/core/Slider/component.js.map +1 -1
  195. package/core/Slider.js +1 -1
  196. package/core/Slider.js.map +1 -1
  197. package/core/TabMenu.js +1 -1
  198. package/core/TabMenu.js.map +1 -1
  199. package/core/Table/data.js +1 -1
  200. package/core/Table/data.js.map +1 -1
  201. package/core/Toggle.js +1 -1
  202. package/core/Toggle.js.map +1 -1
  203. package/core/Tooltip.js +1 -1
  204. package/core/Tooltip.js.map +1 -1
  205. package/core/fonts/NEXT-Book-Light-Italic.eot +0 -0
  206. package/core/fonts/NEXT-Book-Light-Italic.otf +0 -0
  207. package/core/fonts/NEXT-Book-Light-Italic.woff +0 -0
  208. package/core/fonts/NEXT-Book-Light-Italic.woff2 +0 -0
  209. package/core/fonts/NEXT-Book-Light.eot +0 -0
  210. package/core/fonts/NEXT-Book-Light.otf +0 -0
  211. package/core/fonts/NEXT-Book-Light.woff +0 -0
  212. package/core/fonts/NEXT-Book-Light.woff2 +0 -0
  213. package/core/fonts/NEXT-Book-Medium-Italic.eot +0 -0
  214. package/core/fonts/NEXT-Book-Medium-Italic.otf +0 -0
  215. package/core/fonts/NEXT-Book-Medium-Italic.woff +0 -0
  216. package/core/fonts/NEXT-Book-Medium-Italic.woff2 +0 -0
  217. package/core/fonts/NEXT-Book-Medium.eot +0 -0
  218. package/core/fonts/NEXT-Book-Medium.otf +0 -0
  219. package/core/fonts/NEXT-Book-Medium.woff +0 -0
  220. package/core/fonts/NEXT-Book-Medium.woff2 +0 -0
  221. package/core/hooks/use-content-height.js +2 -0
  222. package/core/hooks/use-content-height.js.map +1 -0
  223. package/core/hooks/use-themed-scrollpoints.js +2 -0
  224. package/core/hooks/use-themed-scrollpoints.js.map +1 -0
  225. package/core/hooks/use-themed-scrollpoints.test.js +2 -0
  226. package/core/hooks/use-themed-scrollpoints.test.js.map +1 -0
  227. package/core/icons/display/icon-display-cloud-servers-mono.svg +3 -0
  228. package/core/icons/display/icon-display-data-integrity.svg +9 -0
  229. package/core/icons/display/icon-display-database-connector.svg +13 -0
  230. package/core/icons/display/icon-display-ephemeral-messages-dark-col.svg +6 -0
  231. package/core/icons/display/icon-display-ephemeral-messages.svg +6 -0
  232. package/core/icons/display/icon-display-live-updates.svg +8 -0
  233. package/core/icons/display/icon-display-message-annotations-dark-col.svg +11 -0
  234. package/core/icons/display/icon-display-message-annotations.svg +11 -0
  235. package/core/icons/display/icon-display-multi-user-spaces.svg +13 -0
  236. package/core/icons/display/icon-display-sdks.svg +11 -0
  237. package/core/icons/display/icon-display-something-else-mono.svg +4 -0
  238. package/core/icons/display/icon-display-something-else.svg +4 -0
  239. package/core/icons/display/icon-display-ui-mono.svg +22 -0
  240. package/core/icons/display/icon-display-ui.svg +22 -0
  241. package/core/icons/gui/icon-gui-checklist-checked.svg +1 -1
  242. package/core/icons/gui/icon-gui-code-doc.svg +1 -1
  243. package/core/icons/gui/icon-gui-cursor.svg +1 -1
  244. package/core/icons/gui/icon-gui-expand.svg +1 -1
  245. package/core/icons/gui/icon-gui-filter-flow-step-0.svg +3 -3
  246. package/core/icons/gui/icon-gui-flower-growth.svg +1 -1
  247. package/core/icons/gui/icon-gui-glasses.svg +1 -1
  248. package/core/icons/gui/icon-gui-heartbeat-outline.svg +4 -0
  249. package/core/icons/gui/icon-gui-heartbeat-solid.svg +4 -0
  250. package/core/icons/gui/icon-gui-mouse.svg +1 -1
  251. package/core/icons/gui/icon-gui-pitfall.svg +1 -1
  252. package/core/icons/gui/icon-gui-prod-ai-transport-outline.svg +5 -0
  253. package/core/icons/gui/icon-gui-prod-ai-transport-solid.svg +5 -0
  254. package/core/icons/gui/icon-gui-quote-marks-fill.svg +2 -2
  255. package/core/icons/product/icon-product-ai-transport-mono.svg +5 -0
  256. package/core/icons/product/icon-product-ai-transport.svg +12 -0
  257. package/core/icons/product/icon-product-chat-mono.svg +1 -1
  258. package/core/icons/product/icon-product-liveobjects-mono.svg +1 -4
  259. package/core/icons/product/icon-product-livesync-mono.svg +4 -4
  260. package/core/icons/product/icon-product-pubsub-mono.svg +1 -1
  261. package/core/icons/product/icon-product-spaces-mono.svg +1 -1
  262. package/core/icons/tech/icon-tech-claude-mono.svg +5 -0
  263. package/core/icons/tech/icon-tech-claude.svg +3 -0
  264. package/core/icons/tech/icon-tech-jetpack.svg +1 -0
  265. package/core/icons/tech/icon-tech-terraform-outline.svg +5 -0
  266. package/core/images/badges/g2-best-meets-requirements-spring-2025.svg +26 -0
  267. package/core/images/badges/g2-best-results-spring-2025.svg +26 -0
  268. package/core/images/badges/g2-best-support-spring-2025.svg +26 -0
  269. package/core/images/badges/g2-easiest-to-use-spring-2025.svg +26 -0
  270. package/core/images/badges/g2-users-most-likely-to-recommend-spring-2025.svg +26 -0
  271. package/core/images/cust-logo-mentimeter-mono-pos.svg +0 -0
  272. package/core/insights/command-queue.js +1 -1
  273. package/core/insights/command-queue.js.map +1 -1
  274. package/core/insights/datalayer.js +1 -1
  275. package/core/insights/datalayer.js.map +1 -1
  276. package/core/insights/index.js +1 -1
  277. package/core/insights/index.js.map +1 -1
  278. package/core/insights/index.test.js +1 -1
  279. package/core/insights/index.test.js.map +1 -1
  280. package/core/insights/mixpanel.js +1 -1
  281. package/core/insights/mixpanel.js.map +1 -1
  282. package/core/insights/mixpanel.test.js +2 -0
  283. package/core/insights/mixpanel.test.js.map +1 -0
  284. package/core/insights/posthog.js +1 -1
  285. package/core/insights/posthog.js.map +1 -1
  286. package/core/insights/posthog.test.js +2 -0
  287. package/core/insights/posthog.test.js.map +1 -0
  288. package/core/insights/service.js +1 -1
  289. package/core/insights/service.js.map +1 -1
  290. package/core/insights/types.js.map +1 -1
  291. package/core/react-renderer.js.map +1 -1
  292. package/core/sprites-display.svg +1 -1
  293. package/core/sprites-gui.svg +1 -1
  294. package/core/sprites-product.svg +1 -1
  295. package/core/sprites-tech.svg +1 -1
  296. package/core/styles/buttons.css +6 -6
  297. package/core/styles/colors/types.js +1 -1
  298. package/core/styles/colors/types.js.map +1 -1
  299. package/core/styles/forms.css +5 -5
  300. package/core/styles/legacy-buttons.css +8 -8
  301. package/core/styles/properties.css +4 -4
  302. package/core/styles/text.css +2 -2
  303. package/core/styles.components.css +4 -4
  304. package/core/utils/syntax-highlighter.css +31 -0
  305. package/core/utils/syntax-highlighter.js +1 -1
  306. package/core/utils/syntax-highlighter.js.map +1 -1
  307. package/core/utils/syntax-highlighter.test.js +2 -0
  308. package/core/utils/syntax-highlighter.test.js.map +1 -0
  309. package/index.d.ts +1201 -118
  310. package/package.json +66 -59
  311. package/tailwind.config.js +2 -2
  312. package/core/CookieMessage/component.css +0 -15
  313. package/core/CookieMessage.js +0 -2
  314. package/core/CookieMessage.js.map +0 -1
  315. package/core/Icon/components/icon-display-asset-tracking-col.js +0 -2
  316. package/core/Icon/components/icon-display-asset-tracking-col.js.map +0 -1
  317. package/core/Icon/components/icon-gui-prod-asset-tracking-outline.js +0 -2
  318. package/core/Icon/components/icon-gui-prod-asset-tracking-outline.js.map +0 -1
  319. package/core/Icon/components/icon-gui-prod-asset-tracking-solid.js +0 -2
  320. package/core/Icon/components/icon-gui-prod-asset-tracking-solid.js.map +0 -1
  321. package/core/Icon/components/icon-product-asset-tracking-mono.js +0 -2
  322. package/core/Icon/components/icon-product-asset-tracking-mono.js.map +0 -1
  323. package/core/Icon/components/icon-product-asset-tracking.js +0 -2
  324. package/core/Icon/components/icon-product-asset-tracking.js.map +0 -1
  325. package/core/Meganav/MeganavProductTile.js +0 -2
  326. package/core/Meganav/MeganavProductTile.js.map +0 -1
  327. package/core/Meganav/images/fan-engagement-nav-image.png +0 -0
  328. package/core/Meganav/images/founders-nav-image.png +0 -0
  329. package/core/icons/display/icon-display-asset-tracking-col.svg +0 -18
  330. package/core/icons/gui/icon-gui-prod-asset-tracking-outline.svg +0 -3
  331. package/core/icons/gui/icon-gui-prod-asset-tracking-solid.svg +0 -3
  332. package/core/icons/product/icon-product-asset-tracking-mono.svg +0 -3
  333. package/core/icons/product/icon-product-asset-tracking.svg +0 -12
  334. package/core/images/g2-best-meets-requirements-2025.svg +0 -10
  335. package/core/images/g2-best-support-2025.svg +0 -10
  336. package/core/images/g2-high-performer-2025.svg +0 -9
  337. package/core/images/g2-users-most-likely-to-recommend-2025.svg +0 -10
  338. package/core/utils/useCopyToClipboard.js +0 -2
  339. package/core/utils/useCopyToClipboard.js.map +0 -1
package/README.md CHANGED
@@ -2,20 +2,6 @@
2
2
 
3
3
  `ably-ui` is the of home of the Ably design system library ([https://ably-ui.herokuapp.com/](https://ably-ui.herokuapp.com/)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.
4
4
 
5
- ## Getting started
6
-
7
- `ably-ui` is a library built in mind with supporting a variety of websites/apps based on core web technologies. That's why where possible we build based on those but publish in a way that is easy to consume for frameworks we use across our properties.
8
-
9
- As an example, the `Logo` component has two templates, for a [React](https://reactjs.org/) component and [view-component](https://viewcomponent.org/) but uses the same CSS classes and same JavaScript hooks (`data-id`).
10
-
11
- In some cases, this is impractical. Some components will be more specialized and take advantage of a given framework, and we will have no need to make it available in multiple frameworks (for example, something that is only used within signed in, SPA like areas).
12
-
13
- ### Guiding principles
14
-
15
- 1. Provide easy access to common patterns and assets, from brand colours to navigation.
16
- 2. Use the web platform as much as possible without relying on frameworks.
17
- 3. Be flexible in how the library can be integrated.
18
-
19
5
  ### Library structure
20
6
 
21
7
  The library is built out of modules, assets, and JavaScript components. A module is a container for all of those.
@@ -24,8 +10,6 @@ For example, the `core` module provides the most general elements one can build
24
10
 
25
11
  Components do not require assets directly — instead, it's up to the consumer to load the assets and pass them to the components. This ensures flexibility in terms of URLs.
26
12
 
27
- Each module, apart from components, exposes a `scripts.js` and `styles.css`. `scripts.js` contains helper functions. `styles.css` contains CSS that does not belong to any module in particular.
28
-
29
13
  ### Installation
30
14
 
31
15
  ### NPM
@@ -33,11 +17,7 @@ Each module, apart from components, exposes a `scripts.js` and `styles.css`. `sc
33
17
  This type of installation gives you access to module/components assets as well as React components.
34
18
 
35
19
  ```bash
36
- npm install @ably/ui
37
-
38
- # or
39
-
40
- yarn add @ably/ui # Preferred
20
+ pnpm add @ably/ui # Preferred
41
21
  ```
42
22
 
43
23
  To attach the imported JavaScript from the `Core` module to the `window` object:
@@ -122,31 +102,18 @@ import Meganav from "@ably/ui/core/Meganav";
122
102
 
123
103
  ### Icons
124
104
 
125
- We have access to two sets of icons via the `Icon` component, custom local assets hosted in the repo itself, and the third-party Heroicons library.
105
+ Icons are available in two formats to support different application types:
126
106
 
127
- #### Local Custom Icons
107
+ 1. **React Component Imports** (recommended for React apps)
108
+ 2. **SVG Spritesheets** (fallback for non-React apps)
128
109
 
129
- Putting SVG files inside a `src/core/icons` folder will:
110
+ We provide access to both custom local assets hosted in the repo and the third-party [Heroicons](https://heroicons.com/) library.
130
111
 
131
- 1. Add them to a per-group sprites file (e.g., `core/sprites-gui.svg`) for backward compatibility
132
- 2. Generate React components that can be imported dynamically
112
+ #### For React Applications (Recommended)
133
113
 
134
- The sprites file can be loaded with the `loadSprites` helper available in the `core` module or included in the page directly.
135
-
136
- #### Heroicons Integration
114
+ **Using the Icon React Component**
137
115
 
138
- The system automatically falls back to [Heroicons](https://heroicons.com/) when a local icon isn't found, using this naming convention:
139
-
140
- - `icon-gui-{heroicon-name}-{variant}`
141
-
142
- Where `variant` can be:
143
-
144
- - `outline` → 24px outline icons
145
- - `solid` → 24px solid icons
146
- - `mini` → 20px solid icons
147
- - `micro` → 16px solid icons
148
-
149
- #### Usage with the Icon React Component
116
+ The `Icon` component is the preferred method for React applications, providing automatic fallback and consistent sizing:
150
117
 
151
118
  ```tsx
152
119
  // Local custom icon
@@ -159,7 +126,17 @@ Where `variant` can be:
159
126
  <Icon name="icon-gui-chevron-down" variant="solid" size="1.5rem" />
160
127
  ```
161
128
 
162
- #### Usage without a component (sprites method)
129
+ **How the React Component Works**
130
+
131
+ 1. **First**: Attempts to load a local React component generated from your custom SVGs
132
+ 2. **Fallback**: If no local component exists, dynamically imports the corresponding heroicon
133
+ 3. **Graceful degradation**: If neither exists, returns null (no icon displayed)
134
+
135
+ #### For Non-React Applications
136
+
137
+ **Using SVG Spritesheets**
138
+
139
+ For applications that don't use React, icons are available as SVG sprites that can be referenced directly:
163
140
 
164
141
  ```html
165
142
  <!-- The width and height are required for correct sizing. The actual color class might depend on the svg and whether it uses strokes, fills etc. Note as well xlink:href, which is xlinkHref in react. -->
@@ -168,7 +145,7 @@ Where `variant` can be:
168
145
  </svg>
169
146
  ```
170
147
 
171
- Usage without a component, in React, with hover states. Note the [group](https://tailwindcss.com/docs/hover-focus-and-other-states#group-hover) class:
148
+ Even in React applications, you can use the sprite method for advanced use cases like hover states with the [group](https://tailwindcss.com/docs/hover-focus-and-other-states#group-hover) class:
172
149
 
173
150
  ```tsx
174
151
  <a
@@ -182,11 +159,29 @@ Usage without a component, in React, with hover states. Note the [group](https:/
182
159
  </a>
183
160
  ```
184
161
 
185
- #### How the Fallback System Works
162
+ The sprites file can be loaded with the `loadSprites` helper available in the `core` module or included in the page directly.
186
163
 
187
- 1. **First**: Attempts to load a local React component generated from your custom SVGs
188
- 2. **Fallback**: If no local component exists, dynamically imports the corresponding heroicon
189
- 3. **Graceful degradation**: If neither exists, returns null (no icon displayed)
164
+ #### Icon Sources
165
+
166
+ **Local Custom Icons**
167
+
168
+ Putting SVG files inside a `src/core/icons` folder will:
169
+
170
+ 1. Generate React components that can be imported dynamically
171
+ 2. Add them to a per-group sprites file (e.g., `core/sprites-gui.svg`) for non-React usage
172
+
173
+ **Heroicons Integration**
174
+
175
+ The system automatically falls back to [Heroicons](https://heroicons.com/) when a local icon isn't found, using this naming convention:
176
+
177
+ - `icon-gui-{heroicon-name}-{variant}`
178
+
179
+ Where `variant` can be:
180
+
181
+ - `outline` → 24px outline icons
182
+ - `solid` → 24px solid icons
183
+ - `mini` → 20px solid icons
184
+ - `micro` → 16px solid icons
190
185
 
191
186
  This hybrid approach allows you to use custom brand icons while having access to the entire heroicons library as a fallback.
192
187
 
@@ -211,11 +206,29 @@ An important part of ably-ui is ensuring the produced UI is accessible to as wid
211
206
 
212
207
  To visualise the assets in `ably-ui`, there is a Storybook instance, which serves as both a showcase and a development environment.
213
208
 
214
- Firstly, ensure you have all of the required project dependencies by running `yarn` in the project root.
209
+ ### Quick Start
210
+
211
+ The easiest way to get started is to use the development script:
212
+
213
+ ```bash
214
+ ./bin/dev
215
+ ```
216
+
217
+ This script will:
215
218
 
216
- Then, to run Storybook, run `yarn storybook` in the project root - it should open automatically in your browser.
219
+ - Check that all required tools (Node.js, pnpm) are installed at the correct versions via asdf
220
+ - Install all project dependencies
221
+ - Start Storybook automatically
217
222
 
218
- To build Storybook as if it was a statically built site (i.e. what it looks like when deployed), run `yarn build-storybook` from the project root, go to the generated directory with `cd preview`, and then run `npx http-server` (accepting the prompt to install that package if you haven't done already). The built site will be available at the listed local URL.
223
+ ### Manual Setup
224
+
225
+ If you prefer to run commands manually:
226
+
227
+ Firstly, ensure you have all of the required project dependencies by running `pnpm install` in the project root.
228
+
229
+ Then, to run Storybook, run `pnpm storybook` in the project root - it should open automatically in your browser.
230
+
231
+ To build Storybook as if it was a statically built site (i.e. what it looks like when deployed), run `pnpm build-storybook` from the project root, go to the generated directory with `cd preview`, and then run `npx http-server` (accepting the prompt to install that package if you haven't done already). The built site will be available at the listed local URL.
219
232
 
220
233
  ### SWC compile flags
221
234
 
@@ -236,7 +249,7 @@ if (__DEBUG_MODE__) {
236
249
  The flag can be added to the list in `swc.config.ts`, and enabled with an environment variable:
237
250
 
238
251
  ```
239
- $ DEBUG_MODE=true yarn build
252
+ $ DEBUG_MODE=true pnpm build
240
253
  ```
241
254
 
242
255
  ### Publishing pre-release packages for review apps
@@ -256,22 +269,25 @@ After the above, you should have:
256
269
  To deploy a review app with your in-progress code, you can use the `pre-release` script:
257
270
 
258
271
  ```bash
259
- # in root
260
- scripts/pre-release.sh
272
+ # in packages/ui directory
273
+ ./scripts/pre-release.sh
261
274
  ```
262
275
 
263
- This script is a combination of two scripts:
276
+ This script automates the following steps:
264
277
 
265
278
  1. Pre-Release:
266
279
 
267
- - update your local dependencies for ably-ui and run a production build
268
- - release an NPM package with the version built from your current SemVer but adding a pre-release tag based on a short SHA of your HEAD commit
280
+ - Updates local dependencies for ably-ui and runs a production build
281
+ - Releases an NPM package with the version built from your current SemVer but adding a pre-release tag based on a short SHA of your HEAD commit
282
+ - Waits for the package to be available on the NPM registry (handles propagation delay)
283
+ - Automatically updates both `apps/website` and `apps/voltaire` with the new dev version
269
284
 
270
285
  2. Update Pre-Release Version:
271
286
 
272
- - commit all the above and push to origin
287
+ - Commits all changes (UI package.json, app package.json files, and lockfiles) in a single atomic commit
288
+ - Pushes the commit and tag to origin
273
289
 
274
- This will trigger a build of the review app.
290
+ This will trigger a build of the review app with the pre-release version installed in both consuming apps.
275
291
 
276
292
  ### Components
277
293
 
@@ -282,8 +298,8 @@ All components live in `src` and follow a directory and filename convention:
282
298
  - module directory (TitleCase)
283
299
  - module asset files: `scripts.js` for JavaScript and `styles.css` for CSS
284
300
  - component directory (TitleCase)
285
- - `component.js` - supporting/legacy JS script
286
- - `component.css` - additional CSS
301
+ - `component.js` - supporting JS script (legacy)
302
+ - `component.css` - additional CSS (legacy)
287
303
  - `[ComponentName].stories.tsx` - if React, a Storybook presentation file
288
304
  - if React, `[ComponentName].tsx` at a sibling level to the component directory
289
305
 
@@ -326,13 +342,13 @@ We use [Semantic Versioning 2.0.0](https://semver.org/) to version different lib
326
342
 
327
343
  Packages are published to the [GitHub private registry](https://github.com/features/packages).
328
344
 
329
- Publishing is done by tagging a release in GitHub. This triggers a GitHub action that pushes to the private NPM registry as well as publishing new artefacts in the CDN, with the version taken from the tag of the GitHub release.
345
+ Publishing is done by tagging a release in GitHub. This triggers a GitHub action that pushes to the NPM registry as well as deploying Storybook to the [ably/ably-ui](https://github.com/ably/ably-ui) repository, with the version taken from the tag of the GitHub release.
330
346
 
331
- This will trigger GitHub actions in supported apps (currently [Voltaire](http://github.com/ably/voltaire) & [Website](http://github.com/ably/website)) to create a PR with an ably-ui version update.
347
+ After publishing, you can manually trigger the `update-ably-ui` workflow to create a single draft PR that updates both [Voltaire](http://github.com/ably/voltaire) and [Website](http://github.com/ably/website) with the new ably-ui version.
332
348
 
333
349
  **To trigger a release:**
334
350
 
335
- - Make sure you have run pre-release script `./pre-release.sh` (This updates the npm package version for ably-ui in `package.json`).
351
+ - Make sure you have run the pre-release script `./scripts/pre-release.sh` (This updates the npm package version for ably-ui in `package.json` and updates both consuming apps).
336
352
  - Merge your PR into `main` after it has been approved.
337
353
  - On the Github [Ably-UI](http://github.com/ably/ably-ui) repo, [create a new release](https://github.com/ably/ably-ui/releases/new) tag.
338
354
  - Create a new tag with the new version number for the release.
@@ -341,14 +357,50 @@ This will trigger GitHub actions in supported apps (currently [Voltaire](http://
341
357
  - Click on the Autogenerate release notes button.
342
358
  - Publish Release.
343
359
  - Check the Github `Actions` tab in the repo to make sure the release is green.
344
- - Upon successful release, a compiled version of the Storybook site will be deployed to Github Pages.
360
+ - Upon successful release, a compiled version of the Storybook site will be deployed to the [ably/ably-ui](https://github.com/ably/ably-ui) repository's gh-pages branch.
361
+ - Manually trigger the `update-ably-ui` workflow from the Actions tab to create a draft PR updating both apps.
362
+
363
+ This will publish the package to NPM and deploy a new Storybook site to [https://ably.github.io/ably-ui/](https://ably.github.io/ably-ui/). To update the consuming apps, manually trigger the workflow, which will create a single draft PR for both Voltaire and Website that requires review before merging.
364
+
365
+ ### Tagging Convention (Monorepo)
366
+
367
+ In the monorepo, ably-ui uses **component-prefixed tags** to enable independent releases:
368
+
369
+ **Release tags:** `ui-<version>` (e.g., `ui-17.13.2`)
370
+ - Used for production NPM releases
371
+ - Created via GitHub Releases
372
+ - Do NOT include `v` prefix
373
+
374
+ **Pre-release tags:** `ui-v<version>-dev.<sha>` (e.g., `ui-v17.13.2-dev.a1b2c3d`)
375
+ - Created automatically by `./scripts/pre-release.sh`
376
+ - Published to NPM with `dev` tag
377
+ - Includes `v` prefix and commit SHA
345
378
 
346
- This will release the packages and update library and create & push the commit & tag, and also create corresponding PRs in Voltaire & Website. It will also deploy a new Storybook site to [https://ably.github.io/ably-ui/](https://ably.github.io/ably-ui/).
379
+ See the [root docs/TAGGING.md](../../docs/TAGGING.md) for complete details on the monorepo tagging convention.
380
+
381
+ ### Review Apps
382
+
383
+ Review apps allow you to create temporary deployments of Storybook for sharing UI changes with stakeholders without requiring local development setup.
384
+
385
+ To create a review app:
386
+
387
+ 1. Create a pull request with your changes
388
+ 2. Add the `review-app` label to your PR
389
+ 3. A Heroku review app will be automatically created and deployed
390
+ 4. The deployment will appear in the deployments section of your PR (basic auth is enabled - ask fellow contributors for credentials if needed)
391
+
392
+ Review apps are automatically cleaned up when the PR is closed or the label is removed. Only repository contributors can create review apps.
347
393
 
348
394
  ### Running tests
349
395
 
350
- `ably-ui` uses Storybook's `test-runner`, which on push automatically turns all stories into executable tests, underpinned by Jest and Playright. This means that we don't have to explicitly write tests for stories, though we have the ability to write [https://storybook.js.org/docs/writing-stories/play-function](play functions), which allow us to test more detailed interactions. More information on the capabilities of `test-runner` can be found [https://storybook.js.org/docs/writing-tests/test-runner](here).
396
+ `ably-ui` uses [vitest](https://vitest.dev/) with the [Storybook addon for vitest](https://storybook.js.org/docs/writing-tests/integrations/vitest-addon) to automatically turn all stories into executable tests. This means that we don't have to explicitly write tests for stories, though we have the ability to write [play functions](https://storybook.js.org/docs/writing-stories/play-function), which allow us to test more detailed interactions.
351
397
 
352
- Snapshots are also assessed via `test-runner`. To generate new snapshots, run `yarn test:update-snapshots`.
398
+ The tests run in a browser environment using Playwright, providing comprehensive visual regression testing and interaction testing capabilities.
399
+
400
+ You can run the tests locally using:
401
+
402
+ ```bash
403
+ pnpm test
404
+ ```
353
405
 
354
- You can run the tests by either running a dev instance of Storybook locally and then running `yarn test`, or by pushing a branch to GitHub.
406
+ This will run all story tests using vitest in a headless browser environment.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Accordion/types.ts"],"sourcesContent":["import { ReactNode } from \"react\";\nimport { IconName, IconSize } from \"../Icon/types\";\nimport { ColorThemeSet } from \"../styles/colors/types\";\n\n/**\n * Represents the data structure for an Accordion component.\n */\nexport type AccordionData = {\n /**\n * The name of the accordion item.\n */\n name: string;\n\n /**\n * The optional icon name to be displayed alongside the accordion item.\n */\n icon?: IconName | AccordionIcon;\n\n /**\n * The content to be displayed when the accordion item is expanded.\n */\n content: ReactNode;\n\n /**\n * Optional click handler function that is called when the accordion item is clicked.\n * @param index - The index of the clicked accordion item.\n */\n onClick?: (index: number) => void;\n\n /**\n * Indicates whether the accordion item is interactive.\n * When false, the item cannot be expanded or collapsed by user interaction.\n * @default true\n */\n interactive?: boolean;\n};\n\nexport type AccordionIcon = {\n name: IconName;\n css?: string;\n};\n\nexport type AccordionIcons = {\n closed: AccordionIcon;\n open: AccordionIcon;\n};\n\nexport const accordionThemes = [\"default\", \"transparent\", \"static\"] as const;\n\nexport type AccordionTheme = (typeof accordionThemes)[number];\n\n/**\n * Represents the theme colors for an accordion component.\n */\nexport type AccordionThemeColors = {\n /**\n * Background color class for the accordion.\n */\n bg: ColorThemeSet;\n\n /**\n * Background color when the accordion item is hovered.\n */\n hoverBg: ColorThemeSet;\n\n /**\n * Text color class for the accordion.\n */\n text: ColorThemeSet;\n\n /**\n * Color class for the toggle icon of the accordion.\n */\n toggleIconColor: ColorThemeSet;\n\n /**\n * Optional background color class for selectable accordion items.\n */\n selectableBg?: ColorThemeSet;\n\n /**\n * Optional text color class for selectable accordion items.\n */\n selectableText?: ColorThemeSet;\n\n /**\n * Optional border color for the accordion.\n */\n border?: string;\n};\n\n/**\n * Options for configuring the Accordion component.\n */\nexport type AccordionOptions = {\n /**\n * If true, only one accordion item can be open at a time.\n * @default false\n */\n autoClose?: boolean;\n\n /**\n * If true, accordion items can be selected.\n * @default false\n */\n selectable?: boolean;\n\n /**\n * If true, the accordion header will stick to the top when scrolling.\n * @default false\n */\n sticky?: boolean;\n\n /**\n * An array of indexes indicating which accordion items should be open by default.\n * @default []\n */\n defaultOpenIndexes?: number[];\n\n /**\n * If true, all accordion items will be fully open.\n * @default false\n */\n fullyOpen?: boolean;\n\n /**\n * Custom CSS class to apply to the accordion header.\n * @default \"\"\n */\n headerCSS?: string;\n\n /**\n * If true, borders between accordion items will be hidden.\n * @default false\n */\n hideBorders?: boolean;\n\n /**\n * Size of the row icon.\n * @default \"32px\"\n */\n rowIconSize?: IconSize;\n\n /**\n * Size of the accordion icon.\n * @default \"16px\"\n */\n iconSize?: IconSize;\n\n /**\n * Custom CSS classes to apply to the selected accordion header.\n * @default \"\"\n */\n selectedHeaderCSS?: string;\n\n /**\n * Custom CSS classes to apply to the accordion content.\n * @default \"\"\n */\n contentCSS?: string;\n};\n"],"names":["accordionThemes"],"mappings":"AA+CA,OAAO,MAAMA,gBAAkB,CAAC,UAAW,cAAe,SAAS,AAAU"}
1
+ {"version":3,"sources":["../../../src/core/Accordion/types.ts"],"sourcesContent":["import { ReactNode } from \"react\";\nimport { IconName, IconSize } from \"../Icon/types\";\nimport { ColorThemeSet } from \"../styles/colors/types\";\n\n/**\n * Represents the data structure for an Accordion component.\n */\nexport type AccordionData = {\n /**\n * The name of the accordion item.\n */\n name: string;\n\n /**\n * Custom heading content. If provided, this will be used instead of `name`.\n * Can be a ReactNode or a function that receives the index and isOpen state\n * and returns ReactNode.\n */\n heading?: ReactNode | ((index: number, isOpen: boolean) => ReactNode);\n\n /**\n * The optional icon name to be displayed alongside the accordion item.\n */\n icon?: IconName | AccordionIcon;\n\n /**\n * The content to be displayed when the accordion item is expanded.\n */\n content: ReactNode;\n\n /**\n * Optional click handler function that is called when the accordion item is clicked.\n * @param index - The index of the clicked accordion item.\n */\n onClick?: (index: number) => void;\n\n /**\n * Indicates whether the accordion item is interactive.\n * When false, the item cannot be expanded or collapsed by user interaction.\n * @default true\n */\n interactive?: boolean;\n};\n\nexport type AccordionIcon = {\n name: IconName;\n css?: string;\n};\n\nexport type AccordionIcons = {\n closed: AccordionIcon;\n open: AccordionIcon;\n};\n\nexport const accordionThemes = [\"default\", \"transparent\", \"static\"] as const;\n\nexport type AccordionTheme = (typeof accordionThemes)[number];\n\n/**\n * Represents the theme colors for an accordion component.\n */\nexport type AccordionThemeColors = {\n /**\n * Background color class for the accordion.\n */\n bg: ColorThemeSet;\n\n /**\n * Background color when the accordion item is hovered.\n */\n hoverBg: ColorThemeSet;\n\n /**\n * Text color class for the accordion.\n */\n text: ColorThemeSet;\n\n /**\n * Color class for the toggle icon of the accordion.\n */\n toggleIconColor: ColorThemeSet;\n\n /**\n * Optional background color class for selectable accordion items.\n */\n selectableBg?: ColorThemeSet;\n\n /**\n * Optional text color class for selectable accordion items.\n */\n selectableText?: ColorThemeSet;\n\n /**\n * Optional border color for the accordion.\n */\n border?: string;\n};\n\n/**\n * Options for configuring the Accordion component.\n */\nexport type AccordionOptions = {\n /**\n * If true, only one accordion item can be open at a time.\n * @default false\n */\n autoClose?: boolean;\n\n /**\n * If true, accordion items can be selected.\n * @default false\n */\n selectable?: boolean;\n\n /**\n * If true, the accordion header will stick to the top when scrolling.\n * @default false\n */\n sticky?: boolean;\n\n /**\n * An array of indexes indicating which accordion items should be open by default.\n * @default []\n */\n defaultOpenIndexes?: number[];\n\n /**\n * If true, all accordion items will be fully open.\n * @default false\n */\n fullyOpen?: boolean;\n\n /**\n * Custom CSS class to apply to the accordion header.\n * @default \"\"\n */\n headerCSS?: string;\n\n /**\n * If true, borders between accordion items will be hidden.\n * @default false\n */\n hideBorders?: boolean;\n\n /**\n * Size of the row icon.\n * @default \"32px\"\n */\n rowIconSize?: IconSize;\n\n /**\n * Size of the accordion icon.\n * @default \"16px\"\n */\n iconSize?: IconSize;\n\n /**\n * Custom CSS classes to apply to the selected accordion header.\n * @default \"\"\n */\n selectedHeaderCSS?: string;\n\n /**\n * Custom CSS classes to apply to the accordion content.\n * @default \"\"\n */\n contentCSS?: string;\n\n /**\n * Custom CSS classes to apply to the accordion item wrapper when it is open/active.\n * @default \"\"\n */\n selectedItemCSS?: string;\n};\n"],"names":["accordionThemes"],"mappings":"AAsDA,OAAO,MAAMA,gBAAkB,CAAC,UAAW,cAAe,SAAS,AAAU"}
@@ -1,2 +1,2 @@
1
- export const themeClasses={default:{bg:"bg-neutral-200 dark:bg-neutral-1100",hoverBg:"hover:bg-neutral-300 dark:hover:bg-neutral-1100",text:"text-neutral-1300 dark:text-white",toggleIconColor:"text-neutral-1000 dark:text-orange-600",selectableBg:"bg-neutral-1200 dark:bg-neutral-300",selectableText:"text-neutral-000 dark:text-neutral-1300"},transparent:{bg:"bg-transparent dark:bg-transparent",hoverBg:"hover:bg-transparent dark:hover:bg-transparent",text:"text-neutral-1000 dark:text-neutral-000",toggleIconColor:"text-dark-grey dark:text-orange-600",border:"border-neutral-500 border-b last:border-none dark:border-neutral-900"},static:{bg:"bg-neutral-200 dark:bg-neutral-1200",hoverBg:"hover:bg-neutral-200 dark:hover:bg-neutral-1200",text:"text-neutral-1300 dark:text-white",toggleIconColor:"text-neutral-200 dark:text-neutral-1200",selectableBg:"bg-neutral-1200 dark:bg-neutral-1200",selectableText:"text-white dark:text-neutral-1300"}};export const isNonTransparentTheme=theme=>theme!=="transparent";export const isStaticTheme=theme=>theme==="static";
1
+ export const themeClasses={default:{bg:"bg-neutral-200 dark:bg-neutral-1100",hoverBg:"hover:bg-neutral-300 dark:hover:bg-neutral-1100",text:"text-neutral-1300 dark:text-white",toggleIconColor:"text-neutral-1000 dark:text-orange-600",selectableBg:"bg-neutral-1200 dark:bg-neutral-300",selectableText:"text-neutral-000 dark:text-neutral-1300"},transparent:{bg:"bg-transparent dark:bg-transparent",hoverBg:"hover:bg-transparent dark:hover:bg-transparent",text:"text-neutral-1000 dark:text-neutral-000",toggleIconColor:"text-neutral-700 dark:text-neutral-600",border:"border-neutral-500 border-b last:border-none dark:border-neutral-1000"},static:{bg:"bg-neutral-200 dark:bg-neutral-1200",hoverBg:"hover:bg-neutral-200 dark:hover:bg-neutral-1200",text:"text-neutral-1300 dark:text-white",toggleIconColor:"text-neutral-200 dark:text-neutral-1200",selectableBg:"bg-neutral-1200 dark:bg-neutral-1200",selectableText:"text-white dark:text-neutral-1300"}};export const isNonTransparentTheme=theme=>theme!=="transparent";export const isStaticTheme=theme=>theme==="static";
2
2
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Accordion/utils.ts"],"sourcesContent":["import { AccordionTheme, AccordionThemeColors } from \"./types\";\n\nexport const themeClasses: Record<AccordionTheme, AccordionThemeColors> = {\n default: {\n bg: \"bg-neutral-200 dark:bg-neutral-1100\",\n hoverBg: \"hover:bg-neutral-300 dark:hover:bg-neutral-1100\",\n text: \"text-neutral-1300 dark:text-white\",\n toggleIconColor: \"text-neutral-1000 dark:text-orange-600\",\n selectableBg: \"bg-neutral-1200 dark:bg-neutral-300\",\n selectableText: \"text-neutral-000 dark:text-neutral-1300\",\n },\n transparent: {\n bg: \"bg-transparent dark:bg-transparent\",\n hoverBg: \"hover:bg-transparent dark:hover:bg-transparent\",\n text: \"text-neutral-1000 dark:text-neutral-000\",\n toggleIconColor: \"text-dark-grey dark:text-orange-600\",\n border:\n \"border-neutral-500 border-b last:border-none dark:border-neutral-900\",\n },\n static: {\n bg: \"bg-neutral-200 dark:bg-neutral-1200\",\n hoverBg: \"hover:bg-neutral-200 dark:hover:bg-neutral-1200\",\n text: \"text-neutral-1300 dark:text-white\",\n toggleIconColor: \"text-neutral-200 dark:text-neutral-1200\",\n selectableBg: \"bg-neutral-1200 dark:bg-neutral-1200\",\n selectableText: \"text-white dark:text-neutral-1300\",\n },\n};\n\nexport const isNonTransparentTheme = (theme: AccordionTheme) =>\n theme !== \"transparent\";\n\nexport const isStaticTheme = (theme: AccordionTheme) => theme === \"static\";\n"],"names":["themeClasses","default","bg","hoverBg","text","toggleIconColor","selectableBg","selectableText","transparent","border","static","isNonTransparentTheme","theme","isStaticTheme"],"mappings":"AAEA,OAAO,MAAMA,aAA6D,CACxEC,QAAS,CACPC,GAAI,sCACJC,QAAS,kDACTC,KAAM,oCACNC,gBAAiB,yCACjBC,aAAc,sCACdC,eAAgB,yCAClB,EACAC,YAAa,CACXN,GAAI,qCACJC,QAAS,iDACTC,KAAM,0CACNC,gBAAiB,sCACjBI,OACE,sEACJ,EACAC,OAAQ,CACNR,GAAI,sCACJC,QAAS,kDACTC,KAAM,oCACNC,gBAAiB,0CACjBC,aAAc,uCACdC,eAAgB,mCAClB,CACF,CAAE,AAEF,QAAO,MAAMI,sBAAwB,AAACC,OACpCA,QAAU,aAAc,AAE1B,QAAO,MAAMC,cAAgB,AAACD,OAA0BA,QAAU,QAAS"}
1
+ {"version":3,"sources":["../../../src/core/Accordion/utils.ts"],"sourcesContent":["import { AccordionTheme, AccordionThemeColors } from \"./types\";\n\nexport const themeClasses: Record<AccordionTheme, AccordionThemeColors> = {\n default: {\n bg: \"bg-neutral-200 dark:bg-neutral-1100\",\n hoverBg: \"hover:bg-neutral-300 dark:hover:bg-neutral-1100\",\n text: \"text-neutral-1300 dark:text-white\",\n toggleIconColor: \"text-neutral-1000 dark:text-orange-600\",\n selectableBg: \"bg-neutral-1200 dark:bg-neutral-300\",\n selectableText: \"text-neutral-000 dark:text-neutral-1300\",\n },\n transparent: {\n bg: \"bg-transparent dark:bg-transparent\",\n hoverBg: \"hover:bg-transparent dark:hover:bg-transparent\",\n text: \"text-neutral-1000 dark:text-neutral-000\",\n toggleIconColor: \"text-neutral-700 dark:text-neutral-600\",\n border:\n \"border-neutral-500 border-b last:border-none dark:border-neutral-1000\",\n },\n static: {\n bg: \"bg-neutral-200 dark:bg-neutral-1200\",\n hoverBg: \"hover:bg-neutral-200 dark:hover:bg-neutral-1200\",\n text: \"text-neutral-1300 dark:text-white\",\n toggleIconColor: \"text-neutral-200 dark:text-neutral-1200\",\n selectableBg: \"bg-neutral-1200 dark:bg-neutral-1200\",\n selectableText: \"text-white dark:text-neutral-1300\",\n },\n};\n\nexport const isNonTransparentTheme = (theme: AccordionTheme) =>\n theme !== \"transparent\";\n\nexport const isStaticTheme = (theme: AccordionTheme) => theme === \"static\";\n"],"names":["themeClasses","default","bg","hoverBg","text","toggleIconColor","selectableBg","selectableText","transparent","border","static","isNonTransparentTheme","theme","isStaticTheme"],"mappings":"AAEA,OAAO,MAAMA,aAA6D,CACxEC,QAAS,CACPC,GAAI,sCACJC,QAAS,kDACTC,KAAM,oCACNC,gBAAiB,yCACjBC,aAAc,sCACdC,eAAgB,yCAClB,EACAC,YAAa,CACXN,GAAI,qCACJC,QAAS,iDACTC,KAAM,0CACNC,gBAAiB,yCACjBI,OACE,uEACJ,EACAC,OAAQ,CACNR,GAAI,sCACJC,QAAS,kDACTC,KAAM,oCACNC,gBAAiB,0CACjBC,aAAc,uCACdC,eAAgB,mCAClB,CACF,CAAE,AAEF,QAAO,MAAMI,sBAAwB,AAACC,OACpCA,QAAU,aAAc,AAE1B,QAAO,MAAMC,cAAgB,AAACD,OAA0BA,QAAU,QAAS"}
package/core/Accordion.js CHANGED
@@ -1,2 +1,2 @@
1
- import React,{useMemo,useState,forwardRef,useEffect}from"react";import{AccordionContent,AccordionItem,AccordionTrigger,Accordion as RadixAccordion}from"@radix-ui/react-accordion";import Icon from"./Icon";import{themeClasses,isNonTransparentTheme,isStaticTheme}from"./Accordion/utils";import cn from"./utils/cn";const AccordionRow=({name,children,rowIcon,options,toggleIcons,theme,index,onClick,openRowValues,rowInteractive=true})=>{const{selectable,sticky}=options||{};const rowKey=`accordion-item-${index}`;const isOpen=openRowValues.includes(rowKey);const{text,bg,hoverBg,selectableBg,selectableText,border,toggleIconColor}=themeClasses[theme];const textClass=selectable&&isOpen&&selectableText||text;return React.createElement(AccordionItem,{value:rowKey,className:cn({[`${border}`]:border&&!options?.hideBorders})},React.createElement(AccordionTrigger,{onClick:onClick,className:cn({"flex w-full group/accordion-trigger py-4 ui-text-p1 font-bold text-left items-center gap-3 transition-colors focus:outline-none":true,"px-4 mb-4 rounded-lg":isNonTransparentTheme(theme),"px-0 rounded-none":!isNonTransparentTheme(theme),"pointer-events-none focus-visible:outline-none":isStaticTheme(theme),"focus-base":!isStaticTheme(theme),"sticky top-0":sticky,[`${bg} ${hoverBg} ${text}`]:!(selectable&&isOpen),[`${selectableBg} ${selectableText}`]:selectable&&isOpen,[options?.headerCSS??""]:options?.headerCSS,[options?.selectedHeaderCSS??""]:options?.selectedHeaderCSS&&isOpen})},rowIcon?React.createElement(Icon,{name:typeof rowIcon==="object"?rowIcon.name:rowIcon,color:textClass,additionalCSS:typeof rowIcon==="object"&&rowIcon.css?rowIcon.css:"",size:options?.rowIconSize??"32px"}):null,React.createElement("span",null,name),!selectable&&!isStaticTheme(theme)&&rowInteractive?React.createElement("span",{className:"flex-1 justify-end flex items-center"},React.createElement(Icon,{name:isOpen?toggleIcons.open.name:toggleIcons.closed.name,color:toggleIconColor,size:options?.iconSize??"16px"})):null),rowInteractive&&React.createElement(AccordionContent,{className:cn({"ui-text-p2 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down":true,[options?.contentCSS??""]:options?.contentCSS})},React.createElement("div",{className:"pb-4"},children)))};const Accordion=forwardRef(({data,theme="transparent",icons={closed:{name:"icon-gui-plus-outline"},open:{name:"icon-gui-minus-outline"}},options,...props},ref)=>{const openIndexes=useMemo(()=>{const indexValues=data.map((_,i)=>`accordion-item-${i}`);return options?.fullyOpen?indexValues:indexValues.filter((_,index)=>options?.defaultOpenIndexes?.includes(index))},[options?.defaultOpenIndexes,options?.fullyOpen,data.length]);const[openRowValues,setOpenRowValues]=useState(openIndexes);useEffect(()=>{setOpenRowValues(openIndexes)},[openIndexes]);const innerAccordion=data.map((item,index)=>React.createElement(AccordionRow,{key:item.name,name:item.name,rowIcon:item.icon,toggleIcons:icons,theme:theme,options:options,index:index,onClick:()=>{item.onClick?.(index)},openRowValues:openRowValues,rowInteractive:item.interactive},item.content));return React.createElement("div",{ref:ref,...props},options?.autoClose?React.createElement(RadixAccordion,{type:"single",collapsible:true,value:openRowValues[0],onValueChange:values=>setOpenRowValues([values])},innerAccordion):React.createElement(RadixAccordion,{type:"multiple",value:openRowValues,onValueChange:values=>setOpenRowValues(values)},innerAccordion))});Accordion.displayName="Accordion";export default Accordion;
1
+ import React,{useMemo,useState,forwardRef,useEffect}from"react";import{AccordionContent,AccordionItem,AccordionTrigger,Accordion as RadixAccordion}from"@radix-ui/react-accordion";import Icon from"./Icon";import{themeClasses,isNonTransparentTheme,isStaticTheme}from"./Accordion/utils";import cn from"./utils/cn";const AccordionRow=({name,heading,children,rowIcon,options,toggleIcons,theme,index,onClick,openRowValues,rowInteractive=true})=>{const{selectable,sticky}=options||{};const rowKey=`accordion-item-${index}`;const isOpen=openRowValues.includes(rowKey);const{text,bg,hoverBg,selectableBg,selectableText,border,toggleIconColor}=themeClasses[theme];const textClass=selectable&&isOpen&&selectableText||text;const renderHeading=()=>{if(heading){if(typeof heading==="function"){return heading(index,isOpen)}return heading}return React.createElement("span",null,name)};return React.createElement(AccordionItem,{value:rowKey,className:cn({[`${border}`]:border&&!options?.hideBorders,[`${options?.selectedItemCSS}`]:options?.selectedItemCSS&&isOpen})},React.createElement(AccordionTrigger,{onClick:onClick,className:cn({"flex w-full group/accordion-trigger py-4 ui-text-p1 font-bold text-left items-center gap-3 transition-colors focus:outline-none":true,"px-4 mb-4 rounded-lg":isNonTransparentTheme(theme),"px-0 rounded-none":!isNonTransparentTheme(theme),"pointer-events-none focus-visible:outline-none":isStaticTheme(theme),"focus-base":!isStaticTheme(theme),"sticky top-0":sticky,[`${bg} ${hoverBg} ${text}`]:!(selectable&&isOpen),[`${selectableBg} ${selectableText}`]:selectable&&isOpen,[options?.headerCSS??""]:options?.headerCSS,[options?.selectedHeaderCSS??""]:options?.selectedHeaderCSS&&isOpen})},rowIcon?React.createElement(Icon,{name:typeof rowIcon==="object"?rowIcon.name:rowIcon,color:textClass,additionalCSS:typeof rowIcon==="object"&&rowIcon.css?rowIcon.css:"",size:options?.rowIconSize??"32px"}):null,renderHeading(),!selectable&&!isStaticTheme(theme)&&rowInteractive?React.createElement("span",{className:"flex-1 justify-end flex items-center"},React.createElement(Icon,{name:isOpen?toggleIcons.open.name:toggleIcons.closed.name,color:toggleIconColor,additionalCSS:isOpen?typeof toggleIcons.open==="object"&&toggleIcons.open.css||"":typeof toggleIcons.closed==="object"&&toggleIcons.closed.css||"",size:options?.iconSize??"16px"})):null),rowInteractive&&React.createElement(AccordionContent,{className:cn({"ui-text-p2 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down":true,[options?.contentCSS??""]:options?.contentCSS})},React.createElement("div",{className:"pb-4"},children)))};const Accordion=forwardRef(({data,theme="transparent",icons={closed:{name:"icon-gui-plus-outline"},open:{name:"icon-gui-minus-outline"}},options,...props},ref)=>{const openIndexes=useMemo(()=>{const indexValues=data.map((_,i)=>`accordion-item-${i}`);return options?.fullyOpen?indexValues:indexValues.filter((_,index)=>options?.defaultOpenIndexes?.includes(index))},[data,options?.fullyOpen,options?.defaultOpenIndexes]);const[openRowValues,setOpenRowValues]=useState(openIndexes);useEffect(()=>{setOpenRowValues(openIndexes)},[openIndexes]);const innerAccordion=data.map((item,index)=>React.createElement(AccordionRow,{key:item.name,name:item.name,heading:item.heading,rowIcon:item.icon,toggleIcons:icons,theme:theme,options:options,index:index,onClick:()=>{item.onClick?.(index)},openRowValues:openRowValues,rowInteractive:item.interactive},item.content));return React.createElement("div",{ref:ref,...props},options?.autoClose?React.createElement(RadixAccordion,{type:"single",collapsible:true,value:openRowValues[0],onValueChange:values=>setOpenRowValues([values])},innerAccordion):React.createElement(RadixAccordion,{type:"multiple",value:openRowValues,onValueChange:values=>setOpenRowValues(values)},innerAccordion))});Accordion.displayName="Accordion";export default Accordion;
2
2
  //# sourceMappingURL=Accordion.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Accordion.tsx"],"sourcesContent":["import React, {\n ReactNode,\n useMemo,\n useState,\n forwardRef,\n useEffect,\n} from \"react\";\nimport {\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n Accordion as RadixAccordion,\n} from \"@radix-ui/react-accordion\";\n\nimport Icon from \"./Icon\";\nimport type { IconName } from \"./Icon/types\";\nimport type {\n AccordionData,\n AccordionIcon,\n AccordionIcons,\n AccordionOptions,\n AccordionTheme,\n} from \"./Accordion/types\";\nimport {\n themeClasses,\n isNonTransparentTheme,\n isStaticTheme,\n} from \"./Accordion/utils\";\nimport cn from \"./utils/cn\";\n\ntype AccordionRowProps = {\n children: ReactNode;\n name: string;\n rowIcon?: IconName | AccordionIcon;\n theme: AccordionTheme;\n toggleIcons: AccordionIcons;\n options?: AccordionOptions;\n index: number;\n onClick: () => void;\n openRowValues: string[];\n rowInteractive?: boolean;\n};\n\nexport type AccordionProps = {\n /**\n * The data for the accordion items.\n */\n data: AccordionData[];\n\n /**\n * Icons for the accordion toggle.\n */\n icons?: AccordionIcons;\n\n /**\n * Theme for the accordion.\n */\n theme?: AccordionTheme;\n\n /**\n * Options for the accordion behavior.\n */\n options?: AccordionOptions;\n} & React.HTMLAttributes<HTMLDivElement>;\n\nconst AccordionRow = ({\n name,\n children,\n rowIcon,\n options,\n toggleIcons,\n theme,\n index,\n onClick,\n openRowValues,\n rowInteractive = true,\n}: AccordionRowProps) => {\n const { selectable, sticky } = options || {};\n const rowKey = `accordion-item-${index}`;\n const isOpen = openRowValues.includes(rowKey);\n\n const {\n text,\n bg,\n hoverBg,\n selectableBg,\n selectableText,\n border,\n toggleIconColor,\n } = themeClasses[theme];\n\n const textClass = (selectable && isOpen && selectableText) || text;\n\n return (\n <AccordionItem\n value={rowKey}\n className={cn({\n [`${border}`]: border && !options?.hideBorders,\n })}\n >\n <AccordionTrigger\n onClick={onClick}\n className={cn({\n \"flex w-full group/accordion-trigger py-4 ui-text-p1 font-bold text-left items-center gap-3 transition-colors focus:outline-none\":\n true,\n \"px-4 mb-4 rounded-lg\": isNonTransparentTheme(theme),\n \"px-0 rounded-none\": !isNonTransparentTheme(theme),\n \"pointer-events-none focus-visible:outline-none\":\n isStaticTheme(theme),\n \"focus-base\": !isStaticTheme(theme),\n \"sticky top-0\": sticky,\n [`${bg} ${hoverBg} ${text}`]: !(selectable && isOpen),\n [`${selectableBg} ${selectableText}`]: selectable && isOpen,\n [options?.headerCSS ?? \"\"]: options?.headerCSS,\n [options?.selectedHeaderCSS ?? \"\"]:\n options?.selectedHeaderCSS && isOpen,\n })}\n >\n {rowIcon ? (\n <Icon\n name={typeof rowIcon === \"object\" ? rowIcon.name : rowIcon}\n color={textClass}\n additionalCSS={\n typeof rowIcon === \"object\" && rowIcon.css ? rowIcon.css : \"\"\n }\n size={options?.rowIconSize ?? \"32px\"}\n />\n ) : null}\n <span>{name}</span>\n {!selectable && !isStaticTheme(theme) && rowInteractive ? (\n <span className=\"flex-1 justify-end flex items-center\">\n <Icon\n name={isOpen ? toggleIcons.open.name : toggleIcons.closed.name}\n color={toggleIconColor}\n size={options?.iconSize ?? \"16px\"}\n />\n </span>\n ) : null}\n </AccordionTrigger>\n {rowInteractive && (\n <AccordionContent\n className={cn({\n \"ui-text-p2 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\":\n true,\n [options?.contentCSS ?? \"\"]: options?.contentCSS,\n })}\n >\n <div className=\"pb-4\">{children}</div>\n </AccordionContent>\n )}\n </AccordionItem>\n );\n};\n\nconst Accordion = forwardRef<HTMLDivElement, AccordionProps>(\n (\n {\n data,\n theme = \"transparent\",\n icons = {\n closed: { name: \"icon-gui-plus-outline\" },\n open: { name: \"icon-gui-minus-outline\" },\n },\n options,\n ...props\n },\n ref,\n ) => {\n const openIndexes = useMemo(() => {\n const indexValues = data.map((_, i) => `accordion-item-${i}`);\n return options?.fullyOpen\n ? indexValues\n : indexValues.filter((_, index) =>\n options?.defaultOpenIndexes?.includes(index),\n );\n }, [options?.defaultOpenIndexes, options?.fullyOpen, data.length]);\n\n const [openRowValues, setOpenRowValues] = useState<string[]>(openIndexes);\n\n useEffect(() => {\n setOpenRowValues(openIndexes);\n }, [openIndexes]);\n\n const innerAccordion = data.map((item, index) => (\n <AccordionRow\n key={item.name}\n name={item.name}\n rowIcon={item.icon}\n toggleIcons={icons}\n theme={theme}\n options={options}\n index={index}\n onClick={() => {\n item.onClick?.(index);\n }}\n openRowValues={openRowValues}\n rowInteractive={item.interactive}\n >\n {item.content}\n </AccordionRow>\n ));\n\n return (\n <div ref={ref} {...props}>\n {options?.autoClose ? (\n <RadixAccordion\n type=\"single\"\n collapsible\n value={openRowValues[0]}\n onValueChange={(values) => setOpenRowValues([values])}\n >\n {innerAccordion}\n </RadixAccordion>\n ) : (\n <RadixAccordion\n type=\"multiple\"\n value={openRowValues}\n onValueChange={(values) => setOpenRowValues(values)}\n >\n {innerAccordion}\n </RadixAccordion>\n )}\n </div>\n );\n },\n);\n\nAccordion.displayName = \"Accordion\";\n\nexport default Accordion;\n"],"names":["React","useMemo","useState","forwardRef","useEffect","AccordionContent","AccordionItem","AccordionTrigger","Accordion","RadixAccordion","Icon","themeClasses","isNonTransparentTheme","isStaticTheme","cn","AccordionRow","name","children","rowIcon","options","toggleIcons","theme","index","onClick","openRowValues","rowInteractive","selectable","sticky","rowKey","isOpen","includes","text","bg","hoverBg","selectableBg","selectableText","border","toggleIconColor","textClass","value","className","hideBorders","headerCSS","selectedHeaderCSS","color","additionalCSS","css","size","rowIconSize","span","open","closed","iconSize","contentCSS","div","data","icons","props","ref","openIndexes","indexValues","map","_","i","fullyOpen","filter","defaultOpenIndexes","length","setOpenRowValues","innerAccordion","item","key","icon","interactive","content","autoClose","type","collapsible","onValueChange","values","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/Accordion.tsx"],"sourcesContent":["import React, {\n ReactNode,\n useMemo,\n useState,\n forwardRef,\n useEffect,\n} from \"react\";\nimport {\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n Accordion as RadixAccordion,\n} from \"@radix-ui/react-accordion\";\n\nimport Icon from \"./Icon\";\nimport type { IconName } from \"./Icon/types\";\nimport type {\n AccordionData,\n AccordionIcon,\n AccordionIcons,\n AccordionOptions,\n AccordionTheme,\n} from \"./Accordion/types\";\nimport {\n themeClasses,\n isNonTransparentTheme,\n isStaticTheme,\n} from \"./Accordion/utils\";\nimport cn from \"./utils/cn\";\n\ntype AccordionRowProps = {\n children: ReactNode;\n name: string;\n heading?: ReactNode | ((index: number, isOpen: boolean) => ReactNode);\n rowIcon?: IconName | AccordionIcon;\n theme: AccordionTheme;\n toggleIcons: AccordionIcons;\n options?: AccordionOptions;\n index: number;\n onClick: () => void;\n openRowValues: string[];\n rowInteractive?: boolean;\n};\n\nexport type AccordionProps = {\n /**\n * The data for the accordion items.\n */\n data: AccordionData[];\n\n /**\n * Icons for the accordion toggle.\n */\n icons?: AccordionIcons;\n\n /**\n * Theme for the accordion.\n */\n theme?: AccordionTheme;\n\n /**\n * Options for the accordion behavior.\n */\n options?: AccordionOptions;\n} & React.HTMLAttributes<HTMLDivElement>;\n\nconst AccordionRow = ({\n name,\n heading,\n children,\n rowIcon,\n options,\n toggleIcons,\n theme,\n index,\n onClick,\n openRowValues,\n rowInteractive = true,\n}: AccordionRowProps) => {\n const { selectable, sticky } = options || {};\n const rowKey = `accordion-item-${index}`;\n const isOpen = openRowValues.includes(rowKey);\n\n const {\n text,\n bg,\n hoverBg,\n selectableBg,\n selectableText,\n border,\n toggleIconColor,\n } = themeClasses[theme];\n\n const textClass = (selectable && isOpen && selectableText) || text;\n\n // Render custom heading or fallback to name\n const renderHeading = () => {\n if (heading) {\n if (typeof heading === \"function\") {\n return heading(index, isOpen);\n }\n return heading;\n }\n return <span>{name}</span>;\n };\n\n return (\n <AccordionItem\n value={rowKey}\n className={cn({\n [`${border}`]: border && !options?.hideBorders,\n [`${options?.selectedItemCSS}`]: options?.selectedItemCSS && isOpen,\n })}\n >\n <AccordionTrigger\n onClick={onClick}\n className={cn({\n \"flex w-full group/accordion-trigger py-4 ui-text-p1 font-bold text-left items-center gap-3 transition-colors focus:outline-none\": true,\n \"px-4 mb-4 rounded-lg\": isNonTransparentTheme(theme),\n \"px-0 rounded-none\": !isNonTransparentTheme(theme),\n \"pointer-events-none focus-visible:outline-none\":\n isStaticTheme(theme),\n \"focus-base\": !isStaticTheme(theme),\n \"sticky top-0\": sticky,\n [`${bg} ${hoverBg} ${text}`]: !(selectable && isOpen),\n [`${selectableBg} ${selectableText}`]: selectable && isOpen,\n [options?.headerCSS ?? \"\"]: options?.headerCSS,\n [options?.selectedHeaderCSS ?? \"\"]:\n options?.selectedHeaderCSS && isOpen,\n })}\n >\n {rowIcon ? (\n <Icon\n name={typeof rowIcon === \"object\" ? rowIcon.name : rowIcon}\n color={textClass}\n additionalCSS={\n typeof rowIcon === \"object\" && rowIcon.css ? rowIcon.css : \"\"\n }\n size={options?.rowIconSize ?? \"32px\"}\n />\n ) : null}\n {renderHeading()}\n {!selectable && !isStaticTheme(theme) && rowInteractive ? (\n <span className=\"flex-1 justify-end flex items-center\">\n <Icon\n name={isOpen ? toggleIcons.open.name : toggleIcons.closed.name}\n color={toggleIconColor}\n additionalCSS={\n isOpen\n ? (typeof toggleIcons.open === \"object\" &&\n toggleIcons.open.css) ||\n \"\"\n : (typeof toggleIcons.closed === \"object\" &&\n toggleIcons.closed.css) ||\n \"\"\n }\n size={options?.iconSize ?? \"16px\"}\n />\n </span>\n ) : null}\n </AccordionTrigger>\n {rowInteractive && (\n <AccordionContent\n className={cn({\n \"ui-text-p2 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\": true,\n [options?.contentCSS ?? \"\"]: options?.contentCSS,\n })}\n >\n <div className=\"pb-4\">{children}</div>\n </AccordionContent>\n )}\n </AccordionItem>\n );\n};\n\nconst Accordion = forwardRef<HTMLDivElement, AccordionProps>(\n (\n {\n data,\n theme = \"transparent\",\n icons = {\n closed: { name: \"icon-gui-plus-outline\" },\n open: { name: \"icon-gui-minus-outline\" },\n },\n options,\n ...props\n },\n ref,\n ) => {\n const openIndexes = useMemo(() => {\n const indexValues = data.map((_, i) => `accordion-item-${i}`);\n return options?.fullyOpen\n ? indexValues\n : indexValues.filter((_, index) =>\n options?.defaultOpenIndexes?.includes(index),\n );\n }, [data, options?.fullyOpen, options?.defaultOpenIndexes]);\n\n const [openRowValues, setOpenRowValues] = useState<string[]>(openIndexes);\n\n useEffect(() => {\n setOpenRowValues(openIndexes);\n }, [openIndexes]);\n\n const innerAccordion = data.map((item, index) => (\n <AccordionRow\n key={item.name}\n name={item.name}\n heading={item.heading}\n rowIcon={item.icon}\n toggleIcons={icons}\n theme={theme}\n options={options}\n index={index}\n onClick={() => {\n item.onClick?.(index);\n }}\n openRowValues={openRowValues}\n rowInteractive={item.interactive}\n >\n {item.content}\n </AccordionRow>\n ));\n\n return (\n <div ref={ref} {...props}>\n {options?.autoClose ? (\n <RadixAccordion\n type=\"single\"\n collapsible\n value={openRowValues[0]}\n onValueChange={(values) => setOpenRowValues([values])}\n >\n {innerAccordion}\n </RadixAccordion>\n ) : (\n <RadixAccordion\n type=\"multiple\"\n value={openRowValues}\n onValueChange={(values) => setOpenRowValues(values)}\n >\n {innerAccordion}\n </RadixAccordion>\n )}\n </div>\n );\n },\n);\n\nAccordion.displayName = \"Accordion\";\n\nexport default Accordion;\n"],"names":["React","useMemo","useState","forwardRef","useEffect","AccordionContent","AccordionItem","AccordionTrigger","Accordion","RadixAccordion","Icon","themeClasses","isNonTransparentTheme","isStaticTheme","cn","AccordionRow","name","heading","children","rowIcon","options","toggleIcons","theme","index","onClick","openRowValues","rowInteractive","selectable","sticky","rowKey","isOpen","includes","text","bg","hoverBg","selectableBg","selectableText","border","toggleIconColor","textClass","renderHeading","span","value","className","hideBorders","selectedItemCSS","headerCSS","selectedHeaderCSS","color","additionalCSS","css","size","rowIconSize","open","closed","iconSize","contentCSS","div","data","icons","props","ref","openIndexes","indexValues","map","_","i","fullyOpen","filter","defaultOpenIndexes","setOpenRowValues","innerAccordion","item","key","icon","interactive","content","autoClose","type","collapsible","onValueChange","values","displayName"],"mappings":"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"}
package/core/Badge.js CHANGED
@@ -1,2 +1,2 @@
1
- import React,{useMemo}from"react";import Icon from"./Icon";import cn from"./utils/cn";const Badge=({size="md",color="neutral",iconBefore,iconAfter,className,children,disabled=false,focusable=false,hoverable=false,iconSize="12px",ariaLabel})=>{const sizeClass=useMemo(()=>{switch(size){case"xs":return"px-2 py-0 text-[10px] leading-tight";case"sm":return"px-2 py-0.5 text-[10px] leading-tight";case"md":return"px-2.5 py-0.5 text-[11px] leading-normal";case"lg":return"px-3 py-[0.1875rem] text-[12px] leading-normal"}},[size]);const childClass=useMemo(()=>{switch(size){case"xs":case"sm":return"leading-[18px]";case"md":case"lg":return"leading-[20px]"}},[size]);const colorClass=useMemo(()=>{switch(color){case"neutral":return"text-neutral-900 dark:text-neutral-400";case"violet":return"text-violet-400";case"orange":return"text-orange-600";case"yellow":return"text-yellow-600";case"green":return"text-green-600";case"blue":return"text-blue-600";case"pink":return"text-pink-600";case"red":return"text-orange-700"}},[color]);return React.createElement("div",{className:cn("inline-flex bg-neutral-100 dark:bg-neutral-1200 rounded-2xl gap-1 items-center focus-base transition-colors select-none font-semibold",sizeClass,colorClass,{"focus-base":focusable},{"hover:bg-neutral-300 hover:dark:bg-neutral-1000 active:bg-neutral-300 dark:active:bg-neutral-1000":hoverable},{"cursor-not-allowed disabled:text-gui-unavailable dark:disabled:text-gui-unavailable-dark":disabled},className),tabIndex:focusable?0:undefined,"aria-label":focusable||hoverable?ariaLabel:undefined},iconBefore?React.createElement(Icon,{name:iconBefore,size:iconSize,color:colorClass}):null,React.createElement("span",{className:cn("whitespace-nowrap tracking-[0.04em]",childClass)},children),iconAfter?React.createElement(Icon,{name:iconAfter,size:iconSize,color:colorClass}):null)};export default Badge;
1
+ import React,{useMemo}from"react";import Icon from"./Icon";import cn from"./utils/cn";const defaultIconSizeByBadgeSize={lg:"16px",md:"15px",sm:"14px",xs:"13px"};const Badge=({size="md",color="neutral",iconBefore,iconAfter,className,childClassName,children,disabled=false,focusable=false,hoverable=false,iconSize,ariaLabel})=>{const sizeClass=useMemo(()=>{switch(size){case"xs":return"px-2 py-0 text-[10px] leading-tight";case"sm":return"px-2 py-0.5 text-[10px] leading-tight";case"md":return"px-2.5 py-0.5 text-[11px] leading-normal";case"lg":return"px-3 py-[0.1875rem] text-[12px] leading-normal"}},[size]);const childClass=useMemo(()=>{switch(size){case"xs":case"sm":return"leading-[18px]";case"md":case"lg":return"leading-[20px]"}},[size]);const colorClass=useMemo(()=>{switch(color){case"neutral":return"text-neutral-900 dark:text-neutral-400";case"violet":return"text-violet-400";case"orange":return"text-orange-600";case"yellow":return"text-yellow-600";case"green":return"text-green-600";case"blue":return"text-blue-600";case"pink":return"text-pink-600";case"red":return"text-orange-700"}},[color]);const computedIconSize=iconSize??defaultIconSizeByBadgeSize[size];return React.createElement("div",{className:cn("inline-flex bg-neutral-100 dark:bg-neutral-1200 rounded-2xl gap-1 items-center focus-base transition-colors select-none font-semibold",sizeClass,colorClass,{"focus-base":focusable},{"hover:bg-neutral-300 hover:dark:bg-neutral-1000 active:bg-neutral-300 dark:active:bg-neutral-1000":hoverable},{"cursor-not-allowed disabled:text-gui-disabled-light dark:disabled:text-gui-disabled-dark":disabled},className),tabIndex:focusable?0:undefined,role:focusable?"button":undefined,"aria-label":focusable||hoverable?ariaLabel:undefined},iconBefore?React.createElement(Icon,{name:iconBefore,size:computedIconSize,color:colorClass}):null,React.createElement("span",{className:cn("whitespace-nowrap tracking-[0.04em]",childClass,childClassName)},children),iconAfter?React.createElement(Icon,{name:iconAfter,size:computedIconSize,color:colorClass}):null)};export default Badge;
2
2
  //# sourceMappingURL=Badge.js.map
package/core/Badge.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Badge.tsx"],"sourcesContent":["import React, { PropsWithChildren, useMemo } from \"react\";\nimport { IconName, IconSize } from \"./Icon/types\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn\";\nimport { ColorClassColorGroups } from \"./styles/colors/types\";\n\n/**\n * Props for the Badge component.\n */\ninterface BadgeProps {\n /**\n * The size of the badge. Can be one of \"xs\", \"sm\", \"md\", or \"lg\".\n */\n size?: \"xs\" | \"sm\" | \"md\" | \"lg\";\n\n /**\n * The color of the badge. Can be a value from ColorClassColorGroups or \"red\".\n */\n color?: ColorClassColorGroups | \"red\";\n\n /**\n * The name of the icon to be displayed before the children in the badge.\n */\n iconBefore?: IconName;\n\n /**\n * The name of the icon to be displayed after the children in the badge.\n */\n iconAfter?: IconName;\n\n /**\n * Additional CSS class names to apply to the badge.\n */\n className?: string;\n\n /**\n * Whether the badge is disabled. Defaults to false.\n */\n disabled?: boolean;\n\n /**\n * Whether the badge is focusable. Defaults to false.\n */\n focusable?: boolean;\n\n /**\n * Whether the badge is hoverable. Defaults to false.\n */\n hoverable?: boolean;\n\n /**\n * The size of the icons in the badge. Defaults to 12px.\n */\n iconSize?: IconSize;\n\n /**\n * Accessible label for the badge when interactive\n */\n ariaLabel?: string;\n}\n\nconst Badge: React.FC<PropsWithChildren<BadgeProps>> = ({\n size = \"md\",\n color = \"neutral\",\n iconBefore,\n iconAfter,\n className,\n children,\n disabled = false,\n focusable = false,\n hoverable = false,\n iconSize = \"12px\",\n ariaLabel,\n}) => {\n const sizeClass = useMemo(() => {\n switch (size) {\n case \"xs\":\n return \"px-2 py-0 text-[10px] leading-tight\";\n case \"sm\":\n return \"px-2 py-0.5 text-[10px] leading-tight\";\n case \"md\":\n return \"px-2.5 py-0.5 text-[11px] leading-normal\";\n case \"lg\":\n return \"px-3 py-[0.1875rem] text-[12px] leading-normal\";\n }\n }, [size]);\n\n const childClass = useMemo(() => {\n switch (size) {\n case \"xs\":\n case \"sm\":\n return \"leading-[18px]\";\n case \"md\":\n case \"lg\":\n return \"leading-[20px]\";\n }\n }, [size]);\n\n const colorClass = useMemo(() => {\n switch (color) {\n case \"neutral\":\n return \"text-neutral-900 dark:text-neutral-400\";\n case \"violet\":\n return \"text-violet-400\";\n case \"orange\":\n return \"text-orange-600\";\n case \"yellow\":\n return \"text-yellow-600\";\n case \"green\":\n return \"text-green-600\";\n case \"blue\":\n return \"text-blue-600\";\n case \"pink\":\n return \"text-pink-600\";\n case \"red\":\n return \"text-orange-700\";\n }\n }, [color]);\n\n return (\n <div\n className={cn(\n \"inline-flex bg-neutral-100 dark:bg-neutral-1200 rounded-2xl gap-1 items-center focus-base transition-colors select-none font-semibold\",\n sizeClass,\n colorClass,\n { \"focus-base\": focusable },\n {\n \"hover:bg-neutral-300 hover:dark:bg-neutral-1000 active:bg-neutral-300 dark:active:bg-neutral-1000\":\n hoverable,\n },\n {\n \"cursor-not-allowed disabled:text-gui-unavailable dark:disabled:text-gui-unavailable-dark\":\n disabled,\n },\n className,\n )}\n tabIndex={focusable ? 0 : undefined}\n aria-label={focusable || hoverable ? ariaLabel : undefined}\n >\n {iconBefore ? (\n <Icon name={iconBefore} size={iconSize} color={colorClass} />\n ) : null}\n <span className={cn(\"whitespace-nowrap tracking-[0.04em]\", childClass)}>\n {children}\n </span>\n {iconAfter ? (\n <Icon name={iconAfter} size={iconSize} color={colorClass} />\n ) : null}\n </div>\n );\n};\n\nexport default Badge;\n"],"names":["React","useMemo","Icon","cn","Badge","size","color","iconBefore","iconAfter","className","children","disabled","focusable","hoverable","iconSize","ariaLabel","sizeClass","childClass","colorClass","div","tabIndex","undefined","aria-label","name","span"],"mappings":"AAAA,OAAOA,OAA4BC,OAAO,KAAQ,OAAQ,AAE1D,QAAOC,SAAU,QAAS,AAC1B,QAAOC,OAAQ,YAAa,CA0D5B,MAAMC,MAAiD,CAAC,CACtDC,KAAO,IAAI,CACXC,MAAQ,SAAS,CACjBC,UAAU,CACVC,SAAS,CACTC,SAAS,CACTC,QAAQ,CACRC,SAAW,KAAK,CAChBC,UAAY,KAAK,CACjBC,UAAY,KAAK,CACjBC,SAAW,MAAM,CACjBC,SAAS,CACV,IACC,MAAMC,UAAYf,QAAQ,KACxB,OAAQI,MACN,IAAK,KACH,MAAO,qCACT,KAAK,KACH,MAAO,uCACT,KAAK,KACH,MAAO,0CACT,KAAK,KACH,MAAO,gDACX,CACF,EAAG,CAACA,KAAK,EAET,MAAMY,WAAahB,QAAQ,KACzB,OAAQI,MACN,IAAK,KACL,IAAK,KACH,MAAO,gBACT,KAAK,KACL,IAAK,KACH,MAAO,gBACX,CACF,EAAG,CAACA,KAAK,EAET,MAAMa,WAAajB,QAAQ,KACzB,OAAQK,OACN,IAAK,UACH,MAAO,wCACT,KAAK,SACH,MAAO,iBACT,KAAK,SACH,MAAO,iBACT,KAAK,SACH,MAAO,iBACT,KAAK,QACH,MAAO,gBACT,KAAK,OACH,MAAO,eACT,KAAK,OACH,MAAO,eACT,KAAK,MACH,MAAO,iBACX,CACF,EAAG,CAACA,MAAM,EAEV,OACE,oBAACa,OACCV,UAAWN,GACT,wIACAa,UACAE,WACA,CAAE,aAAcN,SAAU,EAC1B,CACE,oGACEC,SACJ,EACA,CACE,2FACEF,QACJ,EACAF,WAEFW,SAAUR,UAAY,EAAIS,UAC1BC,aAAYV,WAAaC,UAAYE,UAAYM,WAEhDd,WACC,oBAACL,MAAKqB,KAAMhB,WAAYF,KAAMS,SAAUR,MAAOY,aAC7C,KACJ,oBAACM,QAAKf,UAAWN,GAAG,sCAAuCc,aACxDP,UAEFF,UACC,oBAACN,MAAKqB,KAAMf,UAAWH,KAAMS,SAAUR,MAAOY,aAC5C,KAGV,CAEA,gBAAed,KAAM"}
1
+ {"version":3,"sources":["../../src/core/Badge.tsx"],"sourcesContent":["import React, { PropsWithChildren, useMemo } from \"react\";\nimport { IconName, IconSize } from \"./Icon/types\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn\";\nimport { ColorClassColorGroups } from \"./styles/colors/types\";\n\n/**\n * Props for the Badge component.\n */\nexport interface BadgeProps {\n /**\n * The size of the badge. Can be one of \"xs\", \"sm\", \"md\", or \"lg\".\n */\n size?: \"xs\" | \"sm\" | \"md\" | \"lg\";\n\n /**\n * The color of the badge. Can be a value from ColorClassColorGroups or \"red\".\n */\n color?: ColorClassColorGroups | \"red\";\n\n /**\n * The name of the icon to be displayed before the children in the badge.\n */\n iconBefore?: IconName;\n\n /**\n * The name of the icon to be displayed after the children in the badge.\n */\n iconAfter?: IconName;\n\n /**\n * Additional CSS class names to apply to the badge.\n */\n className?: string;\n\n /**\n * Whether the badge is disabled. Defaults to false.\n */\n disabled?: boolean;\n\n /**\n * Whether the badge is focusable. Defaults to false.\n */\n focusable?: boolean;\n\n /**\n * Whether the badge is hoverable. Defaults to false.\n */\n hoverable?: boolean;\n\n /**\n * The size of the icons in the badge. If not provided, it will be derived from the badge size.\n */\n iconSize?: IconSize;\n\n /**\n * Accessible label for the badge when interactive\n */\n ariaLabel?: string;\n\n /**\n * Additional CSS class names to apply to the children of the badge.\n */\n childClassName?: string;\n}\n\nconst defaultIconSizeByBadgeSize: Record<\n NonNullable<BadgeProps[\"size\"]>,\n IconSize\n> = {\n lg: \"16px\",\n md: \"15px\",\n sm: \"14px\",\n xs: \"13px\",\n};\n\nconst Badge: React.FC<PropsWithChildren<BadgeProps>> = ({\n size = \"md\",\n color = \"neutral\",\n iconBefore,\n iconAfter,\n className,\n childClassName,\n children,\n disabled = false,\n focusable = false,\n hoverable = false,\n iconSize,\n ariaLabel,\n}) => {\n const sizeClass = useMemo(() => {\n switch (size) {\n case \"xs\":\n return \"px-2 py-0 text-[10px] leading-tight\";\n case \"sm\":\n return \"px-2 py-0.5 text-[10px] leading-tight\";\n case \"md\":\n return \"px-2.5 py-0.5 text-[11px] leading-normal\";\n case \"lg\":\n return \"px-3 py-[0.1875rem] text-[12px] leading-normal\";\n }\n }, [size]);\n\n const childClass = useMemo(() => {\n switch (size) {\n case \"xs\":\n case \"sm\":\n return \"leading-[18px]\";\n case \"md\":\n case \"lg\":\n return \"leading-[20px]\";\n }\n }, [size]);\n\n const colorClass = useMemo(() => {\n switch (color) {\n case \"neutral\":\n return \"text-neutral-900 dark:text-neutral-400\";\n case \"violet\":\n return \"text-violet-400\";\n case \"orange\":\n return \"text-orange-600\";\n case \"yellow\":\n return \"text-yellow-600\";\n case \"green\":\n return \"text-green-600\";\n case \"blue\":\n return \"text-blue-600\";\n case \"pink\":\n return \"text-pink-600\";\n case \"red\":\n return \"text-orange-700\";\n }\n }, [color]);\n\n const computedIconSize = iconSize ?? defaultIconSizeByBadgeSize[size];\n\n return (\n <div\n className={cn(\n \"inline-flex bg-neutral-100 dark:bg-neutral-1200 rounded-2xl gap-1 items-center focus-base transition-colors select-none font-semibold\",\n sizeClass,\n colorClass,\n { \"focus-base\": focusable },\n {\n \"hover:bg-neutral-300 hover:dark:bg-neutral-1000 active:bg-neutral-300 dark:active:bg-neutral-1000\":\n hoverable,\n },\n {\n \"cursor-not-allowed disabled:text-gui-disabled-light dark:disabled:text-gui-disabled-dark\":\n disabled,\n },\n className,\n )}\n tabIndex={focusable ? 0 : undefined}\n role={focusable ? \"button\" : undefined}\n aria-label={focusable || hoverable ? ariaLabel : undefined}\n >\n {iconBefore ? (\n <Icon name={iconBefore} size={computedIconSize} color={colorClass} />\n ) : null}\n\n <span\n className={cn(\n \"whitespace-nowrap tracking-[0.04em]\",\n childClass,\n childClassName,\n )}\n >\n {children}\n </span>\n\n {iconAfter ? (\n <Icon name={iconAfter} size={computedIconSize} color={colorClass} />\n ) : null}\n </div>\n );\n};\n\nexport default Badge;\n"],"names":["React","useMemo","Icon","cn","defaultIconSizeByBadgeSize","lg","md","sm","xs","Badge","size","color","iconBefore","iconAfter","className","childClassName","children","disabled","focusable","hoverable","iconSize","ariaLabel","sizeClass","childClass","colorClass","computedIconSize","div","tabIndex","undefined","role","aria-label","name","span"],"mappings":"AAAA,OAAOA,OAA4BC,OAAO,KAAQ,OAAQ,AAE1D,QAAOC,SAAU,QAAS,AAC1B,QAAOC,OAAQ,YAAa,CA+D5B,MAAMC,2BAGF,CACFC,GAAI,OACJC,GAAI,OACJC,GAAI,OACJC,GAAI,MACN,EAEA,MAAMC,MAAiD,CAAC,CACtDC,KAAO,IAAI,CACXC,MAAQ,SAAS,CACjBC,UAAU,CACVC,SAAS,CACTC,SAAS,CACTC,cAAc,CACdC,QAAQ,CACRC,SAAW,KAAK,CAChBC,UAAY,KAAK,CACjBC,UAAY,KAAK,CACjBC,QAAQ,CACRC,SAAS,CACV,IACC,MAAMC,UAAYrB,QAAQ,KACxB,OAAQS,MACN,IAAK,KACH,MAAO,qCACT,KAAK,KACH,MAAO,uCACT,KAAK,KACH,MAAO,0CACT,KAAK,KACH,MAAO,gDACX,CACF,EAAG,CAACA,KAAK,EAET,MAAMa,WAAatB,QAAQ,KACzB,OAAQS,MACN,IAAK,KACL,IAAK,KACH,MAAO,gBACT,KAAK,KACL,IAAK,KACH,MAAO,gBACX,CACF,EAAG,CAACA,KAAK,EAET,MAAMc,WAAavB,QAAQ,KACzB,OAAQU,OACN,IAAK,UACH,MAAO,wCACT,KAAK,SACH,MAAO,iBACT,KAAK,SACH,MAAO,iBACT,KAAK,SACH,MAAO,iBACT,KAAK,QACH,MAAO,gBACT,KAAK,OACH,MAAO,eACT,KAAK,OACH,MAAO,eACT,KAAK,MACH,MAAO,iBACX,CACF,EAAG,CAACA,MAAM,EAEV,MAAMc,iBAAmBL,UAAYhB,0BAA0B,CAACM,KAAK,CAErE,OACE,oBAACgB,OACCZ,UAAWX,GACT,wIACAmB,UACAE,WACA,CAAE,aAAcN,SAAU,EAC1B,CACE,oGACEC,SACJ,EACA,CACE,2FACEF,QACJ,EACAH,WAEFa,SAAUT,UAAY,EAAIU,UAC1BC,KAAMX,UAAY,SAAWU,UAC7BE,aAAYZ,WAAaC,UAAYE,UAAYO,WAEhDhB,WACC,oBAACV,MAAK6B,KAAMnB,WAAYF,KAAMe,iBAAkBd,MAAOa,aACrD,KAEJ,oBAACQ,QACClB,UAAWX,GACT,sCACAoB,WACAR,iBAGDC,UAGFH,UACC,oBAACX,MAAK6B,KAAMlB,UAAWH,KAAMe,iBAAkBd,MAAOa,aACpD,KAGV,CAEA,gBAAef,KAAM"}
@@ -0,0 +1,2 @@
1
+ import React from"react";import{describe,expect,it}from"vitest";import{render}from"@testing-library/react";import Code from"../Code";describe("Code",()=>{it("renders a single <code> element when no highlights are present",()=>{const{container}=render(React.createElement(Code,{language:"javascript",snippet:'var x = "hello";'}));const codeElements=container.querySelectorAll("pre > code");expect(codeElements.length).toBe(1)});it("wraps highlighted lines in a single <code> element",()=>{const{container}=render(React.createElement(Code,{language:"javascript",snippet:'var x = "hello";\nvar y = "world";',lineHighlights:{1:"addition"}}));const pre=container.querySelector("pre");const codeElements=pre?.querySelectorAll("code");expect(codeElements?.length).toBe(1);const lineSpans=codeElements?.[0].querySelectorAll(":scope > span");expect(lineSpans?.length).toBe(2)});it("applies highlight classes to the correct lines",()=>{const{container}=render(React.createElement(Code,{language:"javascript",snippet:"line1\nline2\nline3",lineHighlights:{1:"addition",3:"removal"}}));const lineWrappers=container.querySelectorAll("pre > code > span");expect(lineWrappers.length).toBe(3);expect(lineWrappers[0].classList.contains("code-line-addition")).toBe(true);expect(lineWrappers[1].classList.contains("code-line-addition")).toBe(false);expect(lineWrappers[2].classList.contains("code-line-removal")).toBe(true)})});
2
+ //# sourceMappingURL=Code.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/Code/Code.test.tsx"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\n\nimport React from \"react\";\nimport { describe, expect, it } from \"vitest\";\nimport { render } from \"@testing-library/react\";\n\nimport Code from \"../Code\";\n\ndescribe(\"Code\", () => {\n it(\"renders a single <code> element when no highlights are present\", () => {\n const { container } = render(\n <Code language=\"javascript\" snippet={'var x = \"hello\";'} />,\n );\n const codeElements = container.querySelectorAll(\"pre > code\");\n expect(codeElements.length).toBe(1);\n });\n\n it(\"wraps highlighted lines in a single <code> element\", () => {\n const { container } = render(\n <Code\n language=\"javascript\"\n snippet={'var x = \"hello\";\\nvar y = \"world\";'}\n lineHighlights={{ 1: \"addition\" }}\n />,\n );\n\n const pre = container.querySelector(\"pre\");\n const codeElements = pre?.querySelectorAll(\"code\");\n expect(codeElements?.length).toBe(1);\n\n // Line content spans should be inside the <code>\n const lineSpans = codeElements?.[0].querySelectorAll(\":scope > span\");\n expect(lineSpans?.length).toBe(2);\n });\n\n it(\"applies highlight classes to the correct lines\", () => {\n const { container } = render(\n <Code\n language=\"javascript\"\n snippet={\"line1\\nline2\\nline3\"}\n lineHighlights={{ 1: \"addition\", 3: \"removal\" }}\n />,\n );\n\n const lineWrappers = container.querySelectorAll(\"pre > code > span\");\n expect(lineWrappers.length).toBe(3);\n expect(lineWrappers[0].classList.contains(\"code-line-addition\")).toBe(true);\n expect(lineWrappers[1].classList.contains(\"code-line-addition\")).toBe(\n false,\n );\n expect(lineWrappers[2].classList.contains(\"code-line-removal\")).toBe(true);\n });\n});\n"],"names":["React","describe","expect","it","render","Code","container","language","snippet","codeElements","querySelectorAll","length","toBe","lineHighlights","pre","querySelector","lineSpans","lineWrappers","classList","contains"],"mappings":"AAIA,OAAOA,UAAW,OAAQ,AAC1B,QAASC,QAAQ,CAAEC,MAAM,CAAEC,EAAE,KAAQ,QAAS,AAC9C,QAASC,MAAM,KAAQ,wBAAyB,AAEhD,QAAOC,SAAU,SAAU,CAE3BJ,SAAS,OAAQ,KACfE,GAAG,iEAAkE,KACnE,KAAM,CAAEG,SAAS,CAAE,CAAGF,OACpB,oBAACC,MAAKE,SAAS,aAAaC,QAAS,sBAEvC,MAAMC,aAAeH,UAAUI,gBAAgB,CAAC,cAChDR,OAAOO,aAAaE,MAAM,EAAEC,IAAI,CAAC,EACnC,GAEAT,GAAG,qDAAsD,KACvD,KAAM,CAAEG,SAAS,CAAE,CAAGF,OACpB,oBAACC,MACCE,SAAS,aACTC,QAAS,qCACTK,eAAgB,CAAE,EAAG,UAAW,KAIpC,MAAMC,IAAMR,UAAUS,aAAa,CAAC,OACpC,MAAMN,aAAeK,KAAKJ,iBAAiB,QAC3CR,OAAOO,cAAcE,QAAQC,IAAI,CAAC,GAGlC,MAAMI,UAAYP,cAAc,CAAC,EAAE,CAACC,iBAAiB,iBACrDR,OAAOc,WAAWL,QAAQC,IAAI,CAAC,EACjC,GAEAT,GAAG,iDAAkD,KACnD,KAAM,CAAEG,SAAS,CAAE,CAAGF,OACpB,oBAACC,MACCE,SAAS,aACTC,QAAS,sBACTK,eAAgB,CAAE,EAAG,WAAY,EAAG,SAAU,KAIlD,MAAMI,aAAeX,UAAUI,gBAAgB,CAAC,qBAChDR,OAAOe,aAAaN,MAAM,EAAEC,IAAI,CAAC,GACjCV,OAAOe,YAAY,CAAC,EAAE,CAACC,SAAS,CAACC,QAAQ,CAAC,uBAAuBP,IAAI,CAAC,MACtEV,OAAOe,YAAY,CAAC,EAAE,CAACC,SAAS,CAACC,QAAQ,CAAC,uBAAuBP,IAAI,CACnE,OAEFV,OAAOe,YAAY,CAAC,EAAE,CAACC,SAAS,CAACC,QAAQ,CAAC,sBAAsBP,IAAI,CAAC,KACvE,EACF"}
package/core/Code.js CHANGED
@@ -1,2 +1,2 @@
1
- import React from"react";import{highlightSnippet,registerDefaultLanguages}from"./utils/syntax-highlighter";import languagesRegistry from"./utils/syntax-highlighter-registry";import cn from"./utils/cn";registerDefaultLanguages(languagesRegistry);const Code=({language,snippet,textSize="ui-text-code",padding="p-8",additionalCSS="",showLines,lineCSS})=>{const trimmedSnippet=snippet.trimEnd();const HTMLraw=highlightSnippet(language,trimmedSnippet)??"";const className=`language-${language} ${textSize}`;const lines=trimmedSnippet.split(/\r\n|\r|\n/);const lineCount=lines.length;return React.createElement("div",{className:cn("hljs overflow-y-auto flex",padding,additionalCSS),"data-id":"code"},showLines?React.createElement("div",{className:"text-code leading-6 pt-px"},[...Array(lineCount)].map((_,i)=>React.createElement("p",{className:cn("mr-4 font-mono text-right text-neutral-800",lineCSS),key:i},i+1))):null,React.createElement("pre",{lang:language,className:"overflow-x-auto h-full flex-1 leading-6"},React.createElement("code",{className:className,dangerouslySetInnerHTML:{__html:HTMLraw}})))};export default Code;
1
+ import React from"react";import{highlightSnippet,LINE_HIGHLIGHT_CLASSES,registerDefaultLanguages,splitHtmlLines}from"./utils/syntax-highlighter";import languagesRegistry from"./utils/syntax-highlighter-registry";import cn from"./utils/cn";registerDefaultLanguages(languagesRegistry);const Code=({language,snippet,textSize="ui-text-code",padding="p-8",additionalCSS="",showLines,lineCSS,wrap=false,lineHighlights})=>{const trimmedSnippet=snippet.trimEnd();const HTMLraw=highlightSnippet(language,trimmedSnippet)??"";const className=`language-${language} ${textSize}`;const lines=trimmedSnippet.split(/\r\n|\r|\n/);const lineCount=lines.length;const hasHighlights=lineHighlights&&Object.keys(lineHighlights).length>0;if(hasHighlights){const htmlLines=splitHtmlLines(HTMLraw);return React.createElement("div",{className:cn("hljs overflow-y-auto",padding,additionalCSS),"data-id":"code"},React.createElement("pre",{lang:language,className:cn("h-full flex-1 text-p4 leading-normal",wrap?"whitespace-pre-wrap break-words":"overflow-x-auto")},React.createElement("code",{className:className},htmlLines.map((lineHtml,i)=>{const lineNum=i+1;const highlightType=lineHighlights[lineNum];const highlightClass=highlightType?LINE_HIGHLIGHT_CLASSES[highlightType]:undefined;return React.createElement("span",{key:i,className:cn("flex min-w-full pl-2",highlightClass)},showLines&&React.createElement("span",{className:cn("mr-4 font-mono text-right text-neutral-800 select-none shrink-0 inline-block leading-normal",lineCSS),style:{minWidth:`${String(lineCount).length}ch`}},lineNum),React.createElement("span",{className:"flex-1 !leading-normal",dangerouslySetInnerHTML:{__html:lineHtml||"&nbsp;"}}))}))))}return React.createElement("div",{className:cn("hljs overflow-y-auto flex",padding,additionalCSS),"data-id":"code"},showLines?React.createElement("div",{className:"text-p4 leading-normal pt-px"},[...Array(lineCount)].map((_,i)=>React.createElement("p",{className:cn("mr-4 font-mono text-right text-neutral-800",lineCSS),key:i},i+1))):null,React.createElement("pre",{lang:language,className:cn("h-full flex-1 text-p4 leading-normal",wrap?"whitespace-pre-wrap break-words":"overflow-x-auto")},React.createElement("code",{className:className,dangerouslySetInnerHTML:{__html:HTMLraw}})))};export default Code;
2
2
  //# sourceMappingURL=Code.js.map
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 registerDefaultLanguages,\n} from \"./utils/syntax-highlighter\";\nimport languagesRegistry from \"./utils/syntax-highlighter-registry\";\nimport cn from \"./utils/cn\";\n\nregisterDefaultLanguages(languagesRegistry);\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};\n\nconst Code = ({\n language,\n snippet,\n textSize = \"ui-text-code\",\n padding = \"p-8\",\n additionalCSS = \"\",\n showLines,\n lineCSS,\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 return (\n <div\n className={cn(\"hljs overflow-y-auto flex\", padding, additionalCSS)}\n data-id=\"code\"\n >\n {showLines ? (\n <div className=\"text-code leading-6 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 lang={language} className=\"overflow-x-auto h-full flex-1 leading-6\">\n <code\n className={className}\n dangerouslySetInnerHTML={{ __html: HTMLraw }}\n />\n </pre>\n </div>\n );\n};\n\nexport default Code;\n"],"names":["React","highlightSnippet","registerDefaultLanguages","languagesRegistry","cn","Code","language","snippet","textSize","padding","additionalCSS","showLines","lineCSS","trimmedSnippet","trimEnd","HTMLraw","className","lines","split","lineCount","length","div","data-id","Array","map","_","i","p","key","pre","lang","code","dangerouslySetInnerHTML","__html"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QACEC,gBAAgB,CAChBC,wBAAwB,KACnB,4BAA6B,AACpC,QAAOC,sBAAuB,qCAAsC,AACpE,QAAOC,OAAQ,YAAa,CAE5BF,yBAAyBC,mBAYzB,MAAME,KAAO,CAAC,CACZC,QAAQ,CACRC,OAAO,CACPC,SAAW,cAAc,CACzBC,QAAU,KAAK,CACfC,cAAgB,EAAE,CAClBC,SAAS,CACTC,OAAO,CACG,IAEV,MAAMC,eAAiBN,QAAQO,OAAO,GACtC,MAAMC,QAAUd,iBAAiBK,SAAUO,iBAAmB,GAC9D,MAAMG,UAAY,CAAC,SAAS,EAAEV,SAAS,CAAC,EAAEE,SAAS,CAAC,CAGpD,MAAMS,MAAQJ,eAAeK,KAAK,CAAC,cACnC,MAAMC,UAAYF,MAAMG,MAAM,CAE9B,OACE,oBAACC,OACCL,UAAWZ,GAAG,4BAA6BK,QAASC,eACpDY,UAAQ,QAEPX,UACC,oBAACU,OAAIL,UAAU,6BACZ,IAAIO,MAAMJ,WAAW,CAACK,GAAG,CAAC,CAACC,EAAGC,IAC7B,oBAACC,KACCX,UAAWZ,GACT,6CACAQ,SAEFgB,IAAKF,GAEJA,EAAI,KAIT,KACJ,oBAACG,OAAIC,KAAMxB,SAAUU,UAAU,2CAC7B,oBAACe,QACCf,UAAWA,UACXgB,wBAAyB,CAAEC,OAAQlB,OAAQ,KAKrD,CAEA,gBAAeV,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 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 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,yBACV0B,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,UACX0B,wBAAyB,CAAEC,OAAQ5B,OAAQ,KAKrD,CAEA,gBAAeZ,IAAK"}
@@ -1,2 +1,2 @@
1
- import React,{useMemo}from"react";import*as Select from"@radix-ui/react-select";import Badge from"../Badge";import Icon from"../Icon";import Tooltip from"../Tooltip";const ApiKeySelector=({apiKeys,selectedApiKey,onApiKeyChange})=>{const isDemoMode=useMemo(()=>apiKeys?.length===1&&apiKeys[0].app==="demo",[apiKeys]);const renderDemoMode=useMemo(()=>React.createElement("div",{className:"flex items-center gap-2"},React.createElement(Badge,{className:"ml-1 bg-neutral-200 dark:bg-neutral-1100"},"DEMO ONLY"),React.createElement(Tooltip,{className:"ml-0",triggerElement:React.createElement(Icon,{name:"icon-gui-information-circle-outline",size:"16px",color:"text-neutral-700 dark:text-neutral-600"})},"This code example uses a temporary key that is rate limited and expires in 4 hrs. Sign in to Ably to use your API keys instead.")),[]);const renderApiKeyDropdown=useMemo(()=>{if(isDemoMode){return renderDemoMode}if(!apiKeys?.length){return null}return React.createElement(Select.Root,{value:selectedApiKey,onValueChange:onApiKeyChange},React.createElement(Select.Trigger,{className:"font-sans inline-flex items-center justify-between rounded px-3 py-2 ml-1 text-14 text-neutral-1300 dark:text-neutral-000 bg-neutral-200 dark:bg-neutral-1100 hover:bg-neutral-300 dark:hover:bg-neutral-1000 gap-2 focus-base border","aria-label":"API Key"},React.createElement(Select.Value,null),React.createElement(Select.Icon,{className:"size-4"},React.createElement(Icon,{name:"icon-gui-chevron-down-micro",size:"16px"}))),React.createElement(Select.Portal,null,React.createElement(Select.Content,{className:"overflow-hidden rounded-lg bg-neutral-000 dark:bg-neutral-1300 border border-neutral-200 dark:border-neutral-1000 shadow-md z-50"},React.createElement(Select.ScrollUpButton,{className:"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base"},React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px",additionalCSS:"rotate-180"})),React.createElement(Select.Viewport,{className:"rounded-lg font-sans"},apiKeys.map(apiKeyItem=>React.createElement(Select.Group,{key:apiKeyItem.app},apiKeys.length>1&&React.createElement(Select.Label,{className:"text-neutral-700 rounded-none dark:text-neutral-600 p-1 bg-neutral-200 dark:bg-neutral-1100"},apiKeyItem.app),apiKeyItem.keys.map(({name,key})=>React.createElement(Select.Item,{key:`${apiKeyItem.app}-${name}-${key}`,value:key,className:"relative flex items-center justify-between m-2 p-2 rounded-lg text-14 text-neutral-1300 dark:text-neutral-000 select-none hover:bg-neutral-100 dark:hover:bg-neutral-1200 data-[highlighted]:outline-none data-[highlighted]:bg-neutral-100 dark:data-[highlighted]:bg-neutral-1200 focus-base min-w-64"},React.createElement(Select.ItemText,null,key.length>10?`${key.substring(0,10)}...`:key,React.createElement("span",{className:"font-light"},name&&` - ${name}`)),React.createElement(Select.ItemIndicator,{className:"size-4"},React.createElement(Icon,{name:"icon-gui-check-micro",size:"16px"}))))))),React.createElement(Select.ScrollDownButton,{className:"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base"},React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px"})))))},[apiKeys,isDemoMode,selectedApiKey,onApiKeyChange,renderDemoMode]);return React.createElement("div",{className:"flex items-center border-t border-neutral-200 dark:border-neutral-1100 px-3 py-3"},React.createElement("span",{className:"ui-text-label4 text-neutral-700 dark:text-neutral-600 mr-1"},"API key:"),renderApiKeyDropdown)};ApiKeySelector.displayName="ApiKeySelector";export default ApiKeySelector;
1
+ import React,{useMemo}from"react";import*as Select from"@radix-ui/react-select";import Badge from"../Badge";import Icon from"../Icon";import Tooltip from"../Tooltip";const ApiKeySelector=({apiKeys,selectedApiKey,onApiKeyChange})=>{const isDemoMode=useMemo(()=>apiKeys?.length===1&&apiKeys[0].app==="demo",[apiKeys]);const renderDemoMode=useMemo(()=>React.createElement("div",{className:"flex items-center gap-2"},React.createElement(Badge,{className:"ml-1 bg-neutral-200 dark:bg-neutral-1100"},"DEMO ONLY"),React.createElement(Tooltip,{className:"ml-0",triggerProps:{className:"h-5"},contentProps:{className:"bg-neutral-1100 dark:bg-neutral-200 text-neutral-300 dark:text-neutral-1000"},triggerElement:React.createElement("div",{className:"group/code-snippet-tooltip-icon-hover flex items-center justify-center"},React.createElement(Icon,{name:"icon-gui-information-circle-outline",size:"20px",color:"text-neutral-700 dark:text-neutral-600",additionalCSS:"group-hover/code-snippet-tooltip-icon-hover:hidden"}),React.createElement(Icon,{name:"icon-gui-information-circle-solid",size:"20px",color:"text-neutral-1300 dark:text-neutral-000",additionalCSS:"group-hover/code-snippet-tooltip-icon-hover:flex hidden"}))},"This code example uses a temporary key that is rate limited and expires in 4 hrs. Sign in to Ably to use your API keys instead.")),[]);const renderApiKeyDropdown=useMemo(()=>{if(isDemoMode){return renderDemoMode}if(!apiKeys?.length){return null}return React.createElement(Select.Root,{value:selectedApiKey,onValueChange:onApiKeyChange},React.createElement(Select.Trigger,{className:"font-sans inline-flex items-center justify-between rounded px-3 py-2 ml-1 text-14 text-neutral-1300 dark:text-neutral-000 bg-neutral-200 dark:bg-neutral-1100 hover:bg-neutral-300 dark:hover:bg-neutral-1000 gap-2 focus-base border border-neutral-300 dark:border-neutral-1000 transition-colors","aria-label":"API Key"},React.createElement(Select.Value,null),React.createElement(Select.Icon,{className:"size-4"},React.createElement(Icon,{name:"icon-gui-chevron-down-micro",size:"16px"}))),React.createElement(Select.Portal,null,React.createElement(Select.Content,{className:"overflow-hidden rounded-lg bg-neutral-000 dark:bg-neutral-1300 border border-neutral-300 dark:border-neutral-1000 shadow-md z-50"},React.createElement(Select.ScrollUpButton,{className:"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base"},React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px",additionalCSS:"rotate-180"})),React.createElement(Select.Viewport,{className:"rounded-lg font-sans"},apiKeys.map(apiKeyItem=>React.createElement(Select.Group,{key:apiKeyItem.app},apiKeys.length>1&&React.createElement(Select.Label,{className:"text-neutral-700 rounded-none dark:text-neutral-600 p-1 bg-neutral-200 dark:bg-neutral-1100"},apiKeyItem.app),apiKeyItem.keys.map(({name,key})=>React.createElement(Select.Item,{key:`${apiKeyItem.app}-${name}-${key}`,value:key,className:"relative flex items-center justify-between m-2 p-2 rounded-lg text-14 text-neutral-1300 dark:text-neutral-000 select-none hover:bg-neutral-100 dark:hover:bg-neutral-1200 data-[highlighted]:outline-none data-[highlighted]:bg-neutral-100 dark:data-[highlighted]:bg-neutral-1200 focus-base min-w-64"},React.createElement(Select.ItemText,null,key.length>10?`${key.substring(0,10)}...`:key,React.createElement("span",{className:"font-light"},name&&` - ${name}`)),React.createElement(Select.ItemIndicator,{className:"size-4"},React.createElement(Icon,{name:"icon-gui-check-micro",size:"16px"}))))))),React.createElement(Select.ScrollDownButton,{className:"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base"},React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px"})))))},[apiKeys,isDemoMode,selectedApiKey,onApiKeyChange,renderDemoMode]);return React.createElement("div",{className:"flex items-center border-t border-neutral-300 dark:border-neutral-1000 px-3 py-3"},React.createElement("span",{className:"ui-text-label4 text-neutral-700 dark:text-neutral-600 mr-1"},"API key:"),renderApiKeyDropdown)};export default ApiKeySelector;
2
2
  //# sourceMappingURL=ApiKeySelector.js.map