tempest-react-sdk 0.73.0 → 0.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/README.md +6 -4
  2. package/dist/br/BrazilMap.module.cjs.map +1 -1
  3. package/dist/br/BrazilMap.module.js.map +1 -1
  4. package/dist/br/MapMarkers.cjs +1 -1
  5. package/dist/br/MapMarkers.cjs.map +1 -1
  6. package/dist/br/MapMarkers.js +19 -22
  7. package/dist/br/MapMarkers.js.map +1 -1
  8. package/dist/br/MunicipalitySearch.cjs +1 -1
  9. package/dist/br/MunicipalitySearch.cjs.map +1 -1
  10. package/dist/br/MunicipalitySearch.js +66 -48
  11. package/dist/br/MunicipalitySearch.js.map +1 -1
  12. package/dist/br/MunicipalitySearch.module.cjs +1 -1
  13. package/dist/br/MunicipalitySearch.module.cjs.map +1 -1
  14. package/dist/br/MunicipalitySearch.module.js +4 -3
  15. package/dist/br/MunicipalitySearch.module.js.map +1 -1
  16. package/dist/br.d.ts +12 -0
  17. package/dist/components/AIChat/AIChat.module.cjs.map +1 -1
  18. package/dist/components/AIChat/AIChat.module.js.map +1 -1
  19. package/dist/components/AIChat/AIChatTurn.cjs +1 -1
  20. package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
  21. package/dist/components/AIChat/AIChatTurn.js +1 -1
  22. package/dist/components/AIChat/AIChatTurn.js.map +1 -1
  23. package/dist/components/AppBar/AppBar.cjs +1 -1
  24. package/dist/components/AppBar/AppBar.cjs.map +1 -1
  25. package/dist/components/AppBar/AppBar.js +1 -0
  26. package/dist/components/AppBar/AppBar.js.map +1 -1
  27. package/dist/components/AppBar/AppBar.module.cjs +1 -1
  28. package/dist/components/AppBar/AppBar.module.cjs.map +1 -1
  29. package/dist/components/AppBar/AppBar.module.js +12 -11
  30. package/dist/components/AppBar/AppBar.module.js.map +1 -1
  31. package/dist/components/AppShell/AppShell.module.cjs.map +1 -1
  32. package/dist/components/AppShell/AppShell.module.js.map +1 -1
  33. package/dist/components/Button/Button.cjs +1 -1
  34. package/dist/components/Button/Button.cjs.map +1 -1
  35. package/dist/components/Button/Button.js +41 -36
  36. package/dist/components/Button/Button.js.map +1 -1
  37. package/dist/components/Button/Button.module.cjs.map +1 -1
  38. package/dist/components/Button/Button.module.js.map +1 -1
  39. package/dist/components/Button/ButtonContent.cjs +2 -0
  40. package/dist/components/Button/ButtonContent.cjs.map +1 -0
  41. package/dist/components/Button/ButtonContent.js +34 -0
  42. package/dist/components/Button/ButtonContent.js.map +1 -0
  43. package/dist/components/Button/ButtonSlot.cjs +2 -0
  44. package/dist/components/Button/ButtonSlot.cjs.map +1 -0
  45. package/dist/components/Button/ButtonSlot.js +36 -0
  46. package/dist/components/Button/ButtonSlot.js.map +1 -0
  47. package/dist/components/Button/button-class.cjs +2 -0
  48. package/dist/components/Button/button-class.cjs.map +1 -0
  49. package/dist/components/Button/button-class.js +13 -0
  50. package/dist/components/Button/button-class.js.map +1 -0
  51. package/dist/components/Button/link-rel.cjs +2 -0
  52. package/dist/components/Button/link-rel.cjs.map +1 -0
  53. package/dist/components/Button/link-rel.js +11 -0
  54. package/dist/components/Button/link-rel.js.map +1 -0
  55. package/dist/components/Button/slot.cjs +2 -0
  56. package/dist/components/Button/slot.cjs.map +1 -0
  57. package/dist/components/Button/slot.js +41 -0
  58. package/dist/components/Button/slot.js.map +1 -0
  59. package/dist/components/Carousel/Carousel.module.cjs.map +1 -1
  60. package/dist/components/Carousel/Carousel.module.js.map +1 -1
  61. package/dist/components/Chat/Chat.module.cjs.map +1 -1
  62. package/dist/components/Chat/Chat.module.js.map +1 -1
  63. package/dist/components/Collapsible/Collapsible.cjs +1 -1
  64. package/dist/components/Collapsible/Collapsible.cjs.map +1 -1
  65. package/dist/components/Collapsible/Collapsible.js +1 -1
  66. package/dist/components/Collapsible/Collapsible.js.map +1 -1
  67. package/dist/components/Combobox/Combobox.cjs +1 -1
  68. package/dist/components/Combobox/Combobox.cjs.map +1 -1
  69. package/dist/components/Combobox/Combobox.js +18 -23
  70. package/dist/components/Combobox/Combobox.js.map +1 -1
  71. package/dist/components/Combobox/use-listbox-dismiss.cjs +2 -0
  72. package/dist/components/Combobox/use-listbox-dismiss.cjs.map +1 -0
  73. package/dist/components/Combobox/use-listbox-dismiss.js +34 -0
  74. package/dist/components/Combobox/use-listbox-dismiss.js.map +1 -0
  75. package/dist/components/Dropzone/Dropzone.module.cjs.map +1 -1
  76. package/dist/components/Dropzone/Dropzone.module.js.map +1 -1
  77. package/dist/components/FilterBar/FilterBar.module.cjs.map +1 -1
  78. package/dist/components/FilterBar/FilterBar.module.js.map +1 -1
  79. package/dist/components/FloatingActionButton/FloatingActionButton.module.cjs.map +1 -1
  80. package/dist/components/FloatingActionButton/FloatingActionButton.module.js.map +1 -1
  81. package/dist/components/Form/Form.cjs.map +1 -1
  82. package/dist/components/Form/Form.js.map +1 -1
  83. package/dist/components/ImageCropper/ImageCropper.module.cjs.map +1 -1
  84. package/dist/components/ImageCropper/ImageCropper.module.js.map +1 -1
  85. package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
  86. package/dist/components/InstallButton/InstallButton.js.map +1 -1
  87. package/dist/components/ListTile/ListTile.module.cjs.map +1 -1
  88. package/dist/components/ListTile/ListTile.module.js.map +1 -1
  89. package/dist/components/Markdown/Markdown.module.cjs.map +1 -1
  90. package/dist/components/Markdown/Markdown.module.js.map +1 -1
  91. package/dist/components/Menubar/Menubar.module.cjs.map +1 -1
  92. package/dist/components/Menubar/Menubar.module.js.map +1 -1
  93. package/dist/components/Modal/Modal.cjs +1 -1
  94. package/dist/components/Modal/Modal.cjs.map +1 -1
  95. package/dist/components/Modal/Modal.js +1 -1
  96. package/dist/components/Modal/Modal.js.map +1 -1
  97. package/dist/components/Modal/Modal.module.cjs +1 -1
  98. package/dist/components/Modal/Modal.module.cjs.map +1 -1
  99. package/dist/components/Modal/Modal.module.js +1 -1
  100. package/dist/components/Modal/Modal.module.js.map +1 -1
  101. package/dist/components/MultiSelect/MultiSelect.cjs +1 -1
  102. package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
  103. package/dist/components/MultiSelect/MultiSelect.js +55 -54
  104. package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
  105. package/dist/components/Navbar/Navbar.cjs +1 -1
  106. package/dist/components/Navbar/Navbar.cjs.map +1 -1
  107. package/dist/components/Navbar/Navbar.js +1 -0
  108. package/dist/components/Navbar/Navbar.js.map +1 -1
  109. package/dist/components/Navbar/Navbar.module.cjs +1 -1
  110. package/dist/components/Navbar/Navbar.module.cjs.map +1 -1
  111. package/dist/components/Navbar/Navbar.module.js +9 -8
  112. package/dist/components/Navbar/Navbar.module.js.map +1 -1
  113. package/dist/components/NavigationMenu/NavigationMenu.module.cjs.map +1 -1
  114. package/dist/components/NavigationMenu/NavigationMenu.module.js.map +1 -1
  115. package/dist/components/NavigationRail/NavigationRail.module.cjs.map +1 -1
  116. package/dist/components/NavigationRail/NavigationRail.module.js.map +1 -1
  117. package/dist/components/NotificationCenter/NotificationCenter.module.cjs.map +1 -1
  118. package/dist/components/NotificationCenter/NotificationCenter.module.js.map +1 -1
  119. package/dist/components/Page/Page.cjs +1 -1
  120. package/dist/components/Page/Page.cjs.map +1 -1
  121. package/dist/components/Page/Page.js +23 -39
  122. package/dist/components/Page/Page.js.map +1 -1
  123. package/dist/components/Page/Page.module.cjs +1 -1
  124. package/dist/components/Page/Page.module.cjs.map +1 -1
  125. package/dist/components/Page/Page.module.js +5 -11
  126. package/dist/components/Page/Page.module.js.map +1 -1
  127. package/dist/components/PasswordInput/PasswordInput.module.cjs.map +1 -1
  128. package/dist/components/PasswordInput/PasswordInput.module.js.map +1 -1
  129. package/dist/components/PinInput/PinInput.module.cjs.map +1 -1
  130. package/dist/components/PinInput/PinInput.module.js.map +1 -1
  131. package/dist/components/Reveal/Reveal.cjs +2 -0
  132. package/dist/components/Reveal/Reveal.cjs.map +1 -0
  133. package/dist/components/Reveal/Reveal.js +56 -0
  134. package/dist/components/Reveal/Reveal.js.map +1 -0
  135. package/dist/components/Reveal/Reveal.module.cjs +3 -0
  136. package/dist/components/Reveal/Reveal.module.cjs.map +1 -0
  137. package/dist/components/Reveal/Reveal.module.js +7 -0
  138. package/dist/components/Reveal/Reveal.module.js.map +1 -0
  139. package/dist/components/Reveal/reveal-threshold.cjs +2 -0
  140. package/dist/components/Reveal/reveal-threshold.cjs.map +1 -0
  141. package/dist/components/Reveal/reveal-threshold.js +13 -0
  142. package/dist/components/Reveal/reveal-threshold.js.map +1 -0
  143. package/dist/components/SectionHeader/SectionHeader.cjs +2 -0
  144. package/dist/components/SectionHeader/SectionHeader.cjs.map +1 -0
  145. package/dist/components/SectionHeader/SectionHeader.js +66 -0
  146. package/dist/components/SectionHeader/SectionHeader.js.map +1 -0
  147. package/dist/components/SectionHeader/SectionHeader.module.cjs +3 -0
  148. package/dist/components/SectionHeader/SectionHeader.module.cjs.map +1 -0
  149. package/dist/components/SectionHeader/SectionHeader.module.js +15 -0
  150. package/dist/components/SectionHeader/SectionHeader.module.js.map +1 -0
  151. package/dist/components/Timeline/Timeline.cjs +1 -1
  152. package/dist/components/Timeline/Timeline.cjs.map +1 -1
  153. package/dist/components/Timeline/Timeline.js +22 -15
  154. package/dist/components/Timeline/Timeline.js.map +1 -1
  155. package/dist/components/Timeline/Timeline.module.cjs +1 -1
  156. package/dist/components/Timeline/Timeline.module.cjs.map +1 -1
  157. package/dist/components/Timeline/Timeline.module.js +1 -1
  158. package/dist/components/Timeline/Timeline.module.js.map +1 -1
  159. package/dist/components/Tour/Tour.module.cjs.map +1 -1
  160. package/dist/components/Tour/Tour.module.js.map +1 -1
  161. package/dist/components/Transfer/Transfer.module.cjs.map +1 -1
  162. package/dist/components/Transfer/Transfer.module.js.map +1 -1
  163. package/dist/components/VirtualTable/VirtualTable.module.cjs.map +1 -1
  164. package/dist/components/VirtualTable/VirtualTable.module.js.map +1 -1
  165. package/dist/geo/TrajectoryMap.module.cjs.map +1 -1
  166. package/dist/geo/TrajectoryMap.module.js.map +1 -1
  167. package/dist/icons/IconPicker.module.cjs.map +1 -1
  168. package/dist/icons/IconPicker.module.js.map +1 -1
  169. package/dist/styles/Reveal.css +2 -0
  170. package/dist/styles/SectionHeader.css +2 -0
  171. package/dist/styles/actions.css +26 -24
  172. package/dist/styles/base.css +3 -1
  173. package/dist/styles/br.css +3 -3
  174. package/dist/styles/chat.css +5 -5
  175. package/dist/styles/component/AIChat.css +3 -3
  176. package/dist/styles/component/AppBar.css +1 -0
  177. package/dist/styles/component/AppShell.css +1 -1
  178. package/dist/styles/component/BrazilMap.css +2 -2
  179. package/dist/styles/component/Button.css +25 -23
  180. package/dist/styles/component/Carousel.css +3 -3
  181. package/dist/styles/component/Chat.css +2 -2
  182. package/dist/styles/component/Dropzone.css +2 -1
  183. package/dist/styles/component/FilterBar.css +2 -2
  184. package/dist/styles/component/FloatingActionButton.css +1 -1
  185. package/dist/styles/component/IconPicker.css +1 -1
  186. package/dist/styles/component/ImageCropper.css +2 -2
  187. package/dist/styles/component/ListTile.css +1 -1
  188. package/dist/styles/component/Markdown.css +1 -1
  189. package/dist/styles/component/Menubar.css +1 -1
  190. package/dist/styles/component/Modal.css +2 -2
  191. package/dist/styles/component/MunicipalitySearch.css +1 -1
  192. package/dist/styles/component/Navbar.css +1 -0
  193. package/dist/styles/component/NavigationMenu.css +1 -1
  194. package/dist/styles/component/NavigationRail.css +1 -1
  195. package/dist/styles/component/NotificationCenter.css +3 -3
  196. package/dist/styles/component/Page.css +0 -6
  197. package/dist/styles/component/PasswordInput.css +1 -1
  198. package/dist/styles/component/PinInput.css +1 -1
  199. package/dist/styles/component/Reveal.css +9 -0
  200. package/dist/styles/component/SectionHeader.css +9 -0
  201. package/dist/styles/component/Timeline.css +5 -5
  202. package/dist/styles/component/Tour.css +2 -2
  203. package/dist/styles/component/TrajectoryMap.css +1 -1
  204. package/dist/styles/component/Transfer.css +2 -2
  205. package/dist/styles/component/VirtualTable.css +2 -2
  206. package/dist/styles/core.css +3 -1
  207. package/dist/styles/data.css +15 -15
  208. package/dist/styles/feedback.css +3 -3
  209. package/dist/styles/forms.css +6 -5
  210. package/dist/styles/geo.css +1 -1
  211. package/dist/styles/icons.css +1 -1
  212. package/dist/styles/inverse.css +372 -0
  213. package/dist/styles/layout.css +9 -7
  214. package/dist/styles/manifest.json +14 -1
  215. package/dist/styles/navigation.css +8 -6
  216. package/dist/styles/overlay.css +2 -2
  217. package/dist/styles/utility.css +8 -0
  218. package/dist/styles.css +1 -1
  219. package/dist/tempest-react-sdk.cjs +1 -1
  220. package/dist/tempest-react-sdk.d.ts +473 -11
  221. package/dist/tempest-react-sdk.js +350 -346
  222. package/dist/theme/create-theme.cjs +3 -3
  223. package/dist/theme/create-theme.cjs.map +1 -1
  224. package/dist/theme/create-theme.js +72 -55
  225. package/dist/theme/create-theme.js.map +1 -1
  226. package/dist/theme/inverse-render.cjs +3 -0
  227. package/dist/theme/inverse-render.cjs.map +1 -0
  228. package/dist/theme/inverse-render.js +10 -0
  229. package/dist/theme/inverse-render.js.map +1 -0
  230. package/dist/theme/inverse-restore.cjs +5 -0
  231. package/dist/theme/inverse-restore.cjs.map +1 -0
  232. package/dist/theme/inverse-restore.js +30 -0
  233. package/dist/theme/inverse-restore.js.map +1 -0
  234. package/dist/theme/inverse-surface.cjs +2 -0
  235. package/dist/theme/inverse-surface.cjs.map +1 -0
  236. package/dist/theme/inverse-surface.js +255 -0
  237. package/dist/theme/inverse-surface.js.map +1 -0
  238. package/dist/theme/status-tokens.cjs +2 -0
  239. package/dist/theme/status-tokens.cjs.map +1 -0
  240. package/dist/theme/status-tokens.js +15 -0
  241. package/dist/theme/status-tokens.js.map +1 -0
  242. package/dist/vite/create-vite-config.cjs +1 -1
  243. package/dist/vite/create-vite-config.cjs.map +1 -1
  244. package/dist/vite/create-vite-config.js +6 -4
  245. package/dist/vite/create-vite-config.js.map +1 -1
  246. package/package.json +1 -1
@@ -1,21 +1,22 @@
1
1
  import "../../styles/component/AppBar.css";
2
2
  //#region src/components/AppBar/AppBar.module.css
3
- var e = "tempest_bar_SHqWS", t = "tempest_centered_S0CCw", n = "tempest_surface_fusKb", r = "tempest_primary_QcCyN", i = "tempest_transparent_uGrsu", a = "tempest_bordered_5M9FZ", o = "tempest_sticky_DStUO", s = "tempest_safeArea_Vo3Bi", c = "tempest_leading_mXv-d", l = "tempest_actions_x7tMx", u = "tempest_title_qaMMQ", d = "tempest_brand_xKt54", f = "tempest_iconBtn_S-BTg", p = {
3
+ var e = "tempest_bar_SHqWS", t = "tempest_centered_S0CCw", n = "tempest_surface_fusKb", r = "tempest_primary_QcCyN", i = "tempest_inverse_Icool", a = "tempest_transparent_uGrsu", o = "tempest_bordered_5M9FZ", s = "tempest_sticky_DStUO", c = "tempest_safeArea_Vo3Bi", l = "tempest_leading_mXv-d", u = "tempest_actions_x7tMx", d = "tempest_title_qaMMQ", f = "tempest_brand_xKt54", p = "tempest_iconBtn_S-BTg", m = {
4
4
  bar: e,
5
5
  centered: t,
6
6
  surface: n,
7
7
  primary: r,
8
- transparent: i,
9
- bordered: a,
10
- sticky: o,
11
- safeArea: s,
12
- leading: c,
13
- actions: l,
14
- title: u,
15
- brand: d,
16
- iconBtn: f
8
+ inverse: i,
9
+ transparent: a,
10
+ bordered: o,
11
+ sticky: s,
12
+ safeArea: c,
13
+ leading: l,
14
+ actions: u,
15
+ title: d,
16
+ brand: f,
17
+ iconBtn: p
17
18
  };
18
19
  //#endregion
19
- export { l as actions, e as bar, a as bordered, d as brand, t as centered, p as default, f as iconBtn, c as leading, r as primary, s as safeArea, o as sticky, n as surface, u as title, i as transparent };
20
+ export { u as actions, e as bar, o as bordered, f as brand, t as centered, m as default, p as iconBtn, i as inverse, l as leading, r as primary, c as safeArea, s as sticky, n as surface, d as title, a as transparent };
20
21
 
21
22
  //# sourceMappingURL=AppBar.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppBar.module.js","names":[],"sources":["../../../src/components/AppBar/AppBar.module.css"],"sourcesContent":[".bar {\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: center;\n gap: var(--tempest-space-2);\n width: 100%;\n min-height: 56px;\n padding: var(--tempest-space-3) var(--tempest-space-4);\n font-family: var(--tempest-font-sans);\n}\n\n/* Symmetric side columns so the title is truly centered. */\n.bar.centered {\n grid-template-columns: 1fr auto 1fr;\n}\n\n.bar.surface {\n background: var(--tempest-surface);\n color: var(--tempest-text);\n}\n\n.bar.primary {\n background: var(--tempest-primary);\n color: var(--tempest-primary-foreground);\n}\n\n.bar.transparent {\n background: transparent;\n color: inherit;\n}\n\n.bar.bordered {\n border-bottom: 1px solid var(--tempest-border);\n}\n\n.bar.sticky {\n position: sticky;\n top: 0;\n z-index: 30;\n}\n\n.bar.safeArea {\n padding-top: max(var(--tempest-space-3), env(safe-area-inset-top, 0px));\n}\n\n.leading {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n min-width: 0;\n}\n\n.actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--tempest-space-1);\n min-width: 0;\n}\n\n.title {\n margin: 0;\n min-width: 0;\n font-size: var(--tempest-text-xl);\n font-weight: var(--tempest-weight-bold);\n line-height: 1.2;\n text-align: left;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.bar.centered .title {\n text-align: center;\n}\n\n.brand {\n font-size: var(--tempest-text-lg);\n font-weight: var(--tempest-weight-bold);\n color: inherit;\n white-space: nowrap;\n}\n\n.iconBtn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 36px;\n height: 36px;\n padding: 0;\n border: none;\n border-radius: var(--tempest-radius-full);\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n\n.iconBtn:hover {\n background: var(--tempest-surface-2);\n}\n\n.iconBtn:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n"],"mappings":";"}
1
+ {"version":3,"file":"AppBar.module.js","names":[],"sources":["../../../src/components/AppBar/AppBar.module.css"],"sourcesContent":[".bar {\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: center;\n gap: var(--tempest-space-2);\n width: 100%;\n min-height: 56px;\n padding: var(--tempest-space-3) var(--tempest-space-4);\n font-family: var(--tempest-font-sans);\n}\n\n/* Symmetric side columns so the title is truly centered. */\n.bar.centered {\n grid-template-columns: 1fr auto 1fr;\n}\n\n.bar.surface {\n background: var(--tempest-surface);\n color: var(--tempest-text);\n}\n\n.bar.primary {\n background: var(--tempest-primary);\n color: var(--tempest-primary-foreground);\n}\n\n.bar.inverse {\n background: var(--tempest-bg);\n color: var(--tempest-text);\n}\n\n.bar.transparent {\n background: transparent;\n color: inherit;\n}\n\n.bar.bordered {\n border-bottom: 1px solid var(--tempest-border);\n}\n\n.bar.sticky {\n position: sticky;\n top: 0;\n z-index: 30;\n}\n\n.bar.safeArea {\n padding-top: max(var(--tempest-space-3), env(safe-area-inset-top, 0px));\n}\n\n.leading {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n min-width: 0;\n}\n\n.actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--tempest-space-1);\n min-width: 0;\n}\n\n.title {\n margin: 0;\n min-width: 0;\n font-size: var(--tempest-text-xl);\n font-weight: var(--tempest-weight-bold);\n line-height: 1.2;\n text-align: left;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.bar.centered .title {\n text-align: center;\n}\n\n.brand {\n font-size: var(--tempest-text-lg);\n font-weight: var(--tempest-weight-bold);\n color: inherit;\n white-space: nowrap;\n}\n\n.iconBtn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 36px;\n height: 36px;\n padding: 0;\n border: none;\n border-radius: var(--tempest-radius-full);\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n\n.iconBtn:hover {\n background: var(--tempest-surface-2);\n}\n\n.iconBtn:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n"],"mappings":";"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppShell.module.cjs","names":[],"sources":["../../../src/components/AppShell/AppShell.module.css"],"sourcesContent":[".shell {\n display: flex;\n flex-direction: column;\n min-height: 100dvh;\n width: 100%;\n background: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n}\n\n.navbar {\n flex: 0 0 auto;\n}\n\n.row {\n flex: 1 1 auto;\n display: flex;\n min-height: 0;\n width: 100%;\n}\n\n.sidebar {\n flex: 0 0 auto;\n}\n\n.main {\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n}\n\n.footer {\n flex: 0 0 auto;\n}\n\n.bottomNav {\n position: sticky;\n bottom: 0;\n z-index: 30;\n flex: 0 0 auto;\n}\n"],"mappings":";"}
1
+ {"version":3,"file":"AppShell.module.cjs","names":[],"sources":["../../../src/components/AppShell/AppShell.module.css"],"sourcesContent":[".shell {\n display: flex;\n flex-direction: column;\n min-height: 100dvh;\n width: 100%;\n background: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n}\n\n/*\n * The wrapper steps out of the box tree so the bar inside it is laid out by the\n * shell directly.\n *\n * A sticky element cannot leave its containing block, and as a plain block this\n * wrapper was exactly as tall as the bar: `Navbar` is sticky by default and\n * scrolled away with the page anyway — measured in Chromium and Firefox at\n * 1440x900, `top: -1261px` at `scrollY` 1261 (#406). With `display: contents`\n * the containing block is the shell, which grows with the content, and the bar\n * stays at `top: 0`. Making the wrapper sticky instead would pin the bar even\n * when the app passed `sticky={false}`; this way the bar's own prop decides.\n */\n.navbar {\n display: contents;\n}\n\n.row {\n flex: 1 1 auto;\n display: flex;\n min-height: 0;\n width: 100%;\n}\n\n.sidebar {\n flex: 0 0 auto;\n}\n\n.main {\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n}\n\n.footer {\n flex: 0 0 auto;\n}\n\n.bottomNav {\n position: sticky;\n bottom: 0;\n z-index: 30;\n flex: 0 0 auto;\n}\n"],"mappings":";"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppShell.module.js","names":[],"sources":["../../../src/components/AppShell/AppShell.module.css"],"sourcesContent":[".shell {\n display: flex;\n flex-direction: column;\n min-height: 100dvh;\n width: 100%;\n background: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n}\n\n.navbar {\n flex: 0 0 auto;\n}\n\n.row {\n flex: 1 1 auto;\n display: flex;\n min-height: 0;\n width: 100%;\n}\n\n.sidebar {\n flex: 0 0 auto;\n}\n\n.main {\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n}\n\n.footer {\n flex: 0 0 auto;\n}\n\n.bottomNav {\n position: sticky;\n bottom: 0;\n z-index: 30;\n flex: 0 0 auto;\n}\n"],"mappings":";"}
1
+ {"version":3,"file":"AppShell.module.js","names":[],"sources":["../../../src/components/AppShell/AppShell.module.css"],"sourcesContent":[".shell {\n display: flex;\n flex-direction: column;\n min-height: 100dvh;\n width: 100%;\n background: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n}\n\n/*\n * The wrapper steps out of the box tree so the bar inside it is laid out by the\n * shell directly.\n *\n * A sticky element cannot leave its containing block, and as a plain block this\n * wrapper was exactly as tall as the bar: `Navbar` is sticky by default and\n * scrolled away with the page anyway — measured in Chromium and Firefox at\n * 1440x900, `top: -1261px` at `scrollY` 1261 (#406). With `display: contents`\n * the containing block is the shell, which grows with the content, and the bar\n * stays at `top: 0`. Making the wrapper sticky instead would pin the bar even\n * when the app passed `sticky={false}`; this way the bar's own prop decides.\n */\n.navbar {\n display: contents;\n}\n\n.row {\n flex: 1 1 auto;\n display: flex;\n min-height: 0;\n width: 100%;\n}\n\n.sidebar {\n flex: 0 0 auto;\n}\n\n.main {\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n}\n\n.footer {\n flex: 0 0 auto;\n}\n\n.bottomNav {\n position: sticky;\n bottom: 0;\n z-index: 30;\n flex: 0 0 auto;\n}\n"],"mappings":";"}
@@ -1,2 +1,2 @@
1
- const e=require("../../utils/cn.cjs"),t=require("./Button.module.cjs");let n=require("react/jsx-runtime");function r({variant:r=`primary`,size:a=`md`,loading:o=!1,fullWidth:s=!1,iconOnly:c=!1,pill:l=!1,leftIcon:u,rightIcon:d,disabled:f,className:p,children:m,...h}){return(0,n.jsxs)(`button`,{className:e.cn(t.default.button,t.default[r],t.default[a],c&&t.default.iconOnly,l&&t.default.pill,o&&t.default.loading,s&&t.default.fullWidth,p),disabled:f||o,...h,children:[o&&(0,n.jsx)(`span`,{className:t.default.spinner,"aria-hidden":!0,children:(0,n.jsx)(i,{})}),(0,n.jsxs)(`span`,{className:e.cn(t.default.content,o&&t.default.hiddenText),children:[u,m,d]})]})}function i(){return(0,n.jsx)(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,n.jsx)(`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`})})}exports.Button=r;
1
+ const e=require("./button-class.cjs"),t=require("./ButtonContent.cjs"),n=require("./link-rel.cjs");let r=require("react"),i=require("react/jsx-runtime");var a=(0,r.forwardRef)(function(r,a){let{variant:o,size:s,loading:c=!1,disabled:l=!1,fullWidth:u,iconOnly:d,pill:f,leftIcon:p,rightIcon:m,className:h,children:g,href:_,target:v,rel:y,...b}=r,x=l||c,S=e.buttonClassName({variant:o,size:s,loading:c,fullWidth:u,iconOnly:d,pill:f},h),C=(0,i.jsx)(t.ButtonContent,{loading:c,leftIcon:p,rightIcon:m,children:g});return _===void 0?(0,i.jsx)(`button`,{...b,ref:a,className:S,disabled:x,"aria-busy":c||void 0,children:C}):(0,i.jsx)(`a`,{...b,ref:a,className:S,href:x?void 0:_,target:v,rel:n.resolveLinkRel(v,y),role:x?`link`:b.role,"aria-disabled":x||void 0,"aria-busy":c||void 0,tabIndex:x?-1:b.tabIndex,onClick:x?e.preventActivation:b.onClick,onAuxClick:x?e.preventActivation:b.onAuxClick,children:C})});exports.Button=a;
2
2
  //# sourceMappingURL=Button.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Button.cjs","names":[],"sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — this is the design system's button: variant, size,\n * loading, fullWidth, iconOnly, pill, leftIcon and rightIcon are the whole\n * vocabulary every screen composes from. Eight orthogonal knobs on the most-used\n * component is the API working — the count rule is looking for two components fused\n * together, and there is only one here.\n */\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Button.module.css\";\n\nexport type ButtonVariant =\n \"primary\" | \"secondary\" | \"danger\" | \"success\" | \"ghost\" | \"soft\" | \"outline\" | \"link\";\nexport type ButtonSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n loading?: boolean;\n fullWidth?: boolean;\n /** Removes horizontal padding and forces a square footprint (use with `aria-label`). */\n iconOnly?: boolean;\n /** Pill-shaped border radius. */\n pill?: boolean;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n}\n\n/**\n * Primary action button with variants, sizes and a loading state that\n * preserves layout via an absolutely-positioned spinner.\n *\n * Variants: `primary` (solid), `secondary` (neutral), `danger`, `success`,\n * `ghost` (transparent), `soft` (tinted), `outline` (bordered), `link`.\n *\n * Sizes are density-aware — they read from `--tempest-control-height-*`\n * tokens which respond to the `data-tempest-density` attribute.\n */\nexport function Button({\n variant = \"primary\",\n size = \"md\",\n loading = false,\n fullWidth = false,\n iconOnly = false,\n pill = false,\n leftIcon,\n rightIcon,\n disabled,\n className,\n children,\n ...props\n}: ButtonProps) {\n return (\n <button\n className={cn(\n styles.button,\n styles[variant],\n styles[size],\n iconOnly && styles.iconOnly,\n pill && styles.pill,\n loading && styles.loading,\n fullWidth && styles.fullWidth,\n className,\n )}\n disabled={disabled || loading}\n {...props}\n >\n {loading && (\n <span className={styles.spinner} aria-hidden>\n <SpinnerIcon />\n </span>\n )}\n <span className={cn(styles.content, loading && styles.hiddenText)}>\n {leftIcon}\n {children}\n {rightIcon}\n </span>\n </button>\n );\n}\n\nfunction SpinnerIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M21 12a9 9 0 1 1-6.219-8.56\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n"],"mappings":"0GAsCA,SAAgB,EAAO,CACnB,UAAU,UACV,OAAO,KACP,UAAU,GACV,YAAY,GACZ,WAAW,GACX,OAAO,GACP,WACA,YACA,WACA,YACA,WACA,GAAG,GACS,CACZ,OACI,EAAA,EAAA,KAAA,CAAC,SAAD,CACI,UAAW,EAAA,GACP,EAAA,QAAO,OACP,EAAA,QAAO,GACP,EAAA,QAAO,GACP,GAAY,EAAA,QAAO,SACnB,GAAQ,EAAA,QAAO,KACf,GAAW,EAAA,QAAO,QAClB,GAAa,EAAA,QAAO,UACpB,CACJ,EACA,SAAU,GAAY,EACtB,GAAI,EAZR,SAAA,CAcK,IACG,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,QAAS,cAAA,GAC7B,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,CAAA,CACZ,CAAA,GAEV,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,GAAW,EAAA,QAAO,UAAU,EAAhE,SAAA,CACK,EACA,EACA,CACC,CACF,CAAA,CAAA,GAEhB,CAEA,SAAS,GAAc,CACnB,OACI,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,MAAM,6BAEN,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,EAAE,8BACF,OAAO,eACP,YAAY,IACZ,cAAc,OACjB,CAAA,CACA,CAAA,CAEb"}
1
+ {"version":3,"file":"Button.cjs","names":[],"sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — this is the design system's button: variant, size,\n * loading, fullWidth, iconOnly, pill, leftIcon and rightIcon are the whole\n * vocabulary every screen composes from, and href only picks which element carries\n * it. Nine orthogonal knobs on the most-used component is the API working — the\n * count rule is looking for two components fused together, and there is only one\n * here.\n */\nimport { forwardRef } from \"react\";\nimport type {\n AnchorHTMLAttributes,\n ButtonHTMLAttributes,\n ForwardedRef,\n HTMLAttributes,\n ReactElement,\n ReactNode,\n Ref,\n RefAttributes,\n} from \"react\";\nimport { buttonClassName, preventActivation } from \"./button-class\";\nimport { ButtonContent } from \"./ButtonContent\";\nimport { resolveLinkRel } from \"./link-rel\";\nimport type { ButtonBaseProps } from \"./types\";\n\nexport type { ButtonBaseProps, ButtonSize, ButtonVariant } from \"./types\";\n\n/** `Button` rendering a native `<button>` — the default, when `href` is not set. */\nexport interface ButtonAsButtonProps\n extends ButtonBaseProps, ButtonHTMLAttributes<HTMLButtonElement> {\n href?: undefined;\n}\n\n/**\n * `Button` rendering an `<a href>` — a call to action that navigates.\n *\n * `type` is a `<button>` attribute and is rejected here; `target` and `rel` are\n * forwarded, and `target=\"_blank\"` always gets `noopener noreferrer` added.\n */\nexport interface ButtonAsLinkProps\n extends ButtonBaseProps, Omit<AnchorHTMLAttributes<HTMLAnchorElement>, \"href\" | \"type\"> {\n /** Destination. Its presence is what makes the button an `<a>`. */\n href: string;\n type?: never;\n}\n\nexport type ButtonProps = ButtonAsButtonProps | ButtonAsLinkProps;\n\n/**\n * Each mode's props with the ref type of the element it renders, so a `ref` to an\n * `HTMLButtonElement` on a link is a type error.\n */\ntype ButtonPropsWithRef =\n | (ButtonAsButtonProps & RefAttributes<HTMLButtonElement>)\n | (ButtonAsLinkProps & RefAttributes<HTMLAnchorElement>);\n\n/** `Button`'s call signature: one props union, each member with its own ref type. */\ntype ButtonComponent = ((props: ButtonPropsWithRef) => ReactElement) & { displayName?: string };\n\n/** The flattened view the render function works on after the call site was type-checked. */\ntype ButtonRenderProps = ButtonBaseProps &\n HTMLAttributes<HTMLElement> & {\n href?: string;\n target?: string;\n rel?: string;\n };\n\n/**\n * Primary action button with variants, sizes and a loading state that\n * preserves layout via an absolutely-positioned spinner.\n *\n * Variants: `primary` (solid), `secondary` (neutral), `danger`, `success`,\n * `ghost` (transparent), `soft` (tinted), `outline` (bordered), `link`.\n *\n * Sizes are density-aware — they read from `--tempest-control-height-*`\n * tokens which respond to the `data-tempest-density` attribute.\n *\n * With `href` it renders an `<a>` with the same look: a call to action that\n * navigates keeps the middle click, Ctrl+click, \"open in new tab\" and the URL\n * preview, which a `<button>` calling `location.assign` loses. `target=\"_blank\"`\n * gets `noopener noreferrer`. An `<a>` has no `disabled`, so a disabled or loading\n * link gets `aria-disabled=\"true\"`, `role=\"link\"`, `tabIndex={-1}`, no `href`, and\n * its click and middle-click cancelled.\n *\n * To style another element — a react-router `Link` — use {@link ButtonSlot}. It is\n * a separate component, not an `asChild` prop, so an app that never uses it does\n * not ship the prop merge and ref composition it needs.\n *\n * The ref is typed per mode: `HTMLButtonElement`, or `HTMLAnchorElement` with\n * `href`. `forwardRef` takes one ref type for all props, so its result is re-typed\n * to the per-mode union — the runtime is plain `forwardRef`.\n *\n * @example\n * <Button onClick={save}>Salvar</Button>\n *\n * @example\n * <Button href=\"https://wa.me/5586999999999\" target=\"_blank\" rightIcon={<ExternalLink />}>\n * Fale conosco\n * </Button>\n */\nexport const Button = forwardRef<HTMLElement, ButtonProps>(function Button(\n props: ButtonProps,\n ref: ForwardedRef<HTMLElement>,\n): ReactElement {\n const {\n variant,\n size,\n loading = false,\n disabled = false,\n fullWidth,\n iconOnly,\n pill,\n leftIcon,\n rightIcon,\n className,\n children,\n href,\n target,\n rel,\n ...rest\n } = props as ButtonRenderProps;\n const inactive = disabled || loading;\n const classes = buttonClassName(\n { variant, size, loading, fullWidth, iconOnly, pill },\n className,\n );\n const content: ReactNode = (\n <ButtonContent loading={loading} leftIcon={leftIcon} rightIcon={rightIcon}>\n {children}\n </ButtonContent>\n );\n\n if (href !== undefined) {\n return (\n <a\n {...rest}\n ref={ref as Ref<HTMLAnchorElement>}\n className={classes}\n href={inactive ? undefined : href}\n target={target}\n rel={resolveLinkRel(target, rel)}\n role={inactive ? \"link\" : rest.role}\n aria-disabled={inactive || undefined}\n aria-busy={loading || undefined}\n tabIndex={inactive ? -1 : rest.tabIndex}\n onClick={inactive ? preventActivation : rest.onClick}\n onAuxClick={inactive ? preventActivation : rest.onAuxClick}\n >\n {content}\n </a>\n );\n }\n\n return (\n <button\n {...(rest as ButtonHTMLAttributes<HTMLButtonElement>)}\n ref={ref as Ref<HTMLButtonElement>}\n className={classes}\n disabled={inactive}\n aria-busy={loading || undefined}\n >\n {content}\n </button>\n );\n}) as unknown as ButtonComponent;\n"],"mappings":"yJAmGA,IAAa,GAAA,EAAS,EAAA,WAAA,CAAqC,SACvD,EACA,EACY,CACZ,GAAM,CACF,UACA,OACA,UAAU,GACV,WAAW,GACX,YACA,WACA,OACA,WACA,YACA,YACA,WACA,OACA,SACA,MACA,GAAG,GACH,EACE,EAAW,GAAY,EACvB,EAAU,EAAA,gBACZ,CAAE,UAAS,OAAM,UAAS,YAAW,WAAU,MAAK,EACpD,CACJ,EACM,GACF,EAAA,EAAA,IAAA,CAAC,EAAA,cAAD,CAAwB,UAAmB,WAAqB,YAC3D,UACU,CAAA,EAwBnB,OArBI,IAAS,IAAA,IAsBT,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,GAAK,EACA,MACL,UAAW,EACX,SAAU,EACV,YAAW,GAAW,IAAA,GAErB,SAAA,CACG,CAAA,GA5BJ,EAAA,EAAA,IAAA,CAAC,IAAD,CACI,GAAI,EACC,MACL,UAAW,EACX,KAAM,EAAW,IAAA,GAAY,EACrB,SACR,IAAK,EAAA,eAAe,EAAQ,CAAG,EAC/B,KAAM,EAAW,OAAS,EAAK,KAC/B,gBAAe,GAAY,IAAA,GAC3B,YAAW,GAAW,IAAA,GACtB,SAAU,EAAW,GAAK,EAAK,SAC/B,QAAS,EAAW,EAAA,kBAAoB,EAAK,QAC7C,WAAY,EAAW,EAAA,kBAAoB,EAAK,WAE/C,SAAA,CACF,CAAA,CAef,CAAC"}
@@ -1,42 +1,47 @@
1
- import { cn as e } from "../../utils/cn.js";
2
- import t from "./Button.module.js";
3
- import { jsx as n, jsxs as r } from "react/jsx-runtime";
1
+ import { buttonClassName as e, preventActivation as t } from "./button-class.js";
2
+ import { ButtonContent as n } from "./ButtonContent.js";
3
+ import { resolveLinkRel as r } from "./link-rel.js";
4
+ import { forwardRef as i } from "react";
5
+ import { jsx as a } from "react/jsx-runtime";
4
6
  //#region src/components/Button/Button.tsx
5
- function i({ variant: i = "primary", size: o = "md", loading: s = !1, fullWidth: c = !1, iconOnly: l = !1, pill: u = !1, leftIcon: d, rightIcon: f, disabled: p, className: m, children: h, ...g }) {
6
- return /* @__PURE__ */ r("button", {
7
- className: e(t.button, t[i], t[o], l && t.iconOnly, u && t.pill, s && t.loading, c && t.fullWidth, m),
8
- disabled: p || s,
9
- ...g,
10
- children: [s && /* @__PURE__ */ n("span", {
11
- className: t.spinner,
12
- "aria-hidden": !0,
13
- children: /* @__PURE__ */ n(a, {})
14
- }), /* @__PURE__ */ r("span", {
15
- className: e(t.content, s && t.hiddenText),
16
- children: [
17
- d,
18
- h,
19
- f
20
- ]
21
- })]
7
+ var o = i(function(i, o) {
8
+ let { variant: s, size: c, loading: l = !1, disabled: u = !1, fullWidth: d, iconOnly: f, pill: p, leftIcon: m, rightIcon: h, className: g, children: _, href: v, target: y, rel: b, ...x } = i, S = u || l, C = e({
9
+ variant: s,
10
+ size: c,
11
+ loading: l,
12
+ fullWidth: d,
13
+ iconOnly: f,
14
+ pill: p
15
+ }, g), w = /* @__PURE__ */ a(n, {
16
+ loading: l,
17
+ leftIcon: m,
18
+ rightIcon: h,
19
+ children: _
22
20
  });
23
- }
24
- function a() {
25
- return /* @__PURE__ */ n("svg", {
26
- width: "16",
27
- height: "16",
28
- viewBox: "0 0 24 24",
29
- fill: "none",
30
- xmlns: "http://www.w3.org/2000/svg",
31
- children: /* @__PURE__ */ n("path", {
32
- d: "M21 12a9 9 0 1 1-6.219-8.56",
33
- stroke: "currentColor",
34
- strokeWidth: "2",
35
- strokeLinecap: "round"
36
- })
21
+ return v === void 0 ? /* @__PURE__ */ a("button", {
22
+ ...x,
23
+ ref: o,
24
+ className: C,
25
+ disabled: S,
26
+ "aria-busy": l || void 0,
27
+ children: w
28
+ }) : /* @__PURE__ */ a("a", {
29
+ ...x,
30
+ ref: o,
31
+ className: C,
32
+ href: S ? void 0 : v,
33
+ target: y,
34
+ rel: r(y, b),
35
+ role: S ? "link" : x.role,
36
+ "aria-disabled": S || void 0,
37
+ "aria-busy": l || void 0,
38
+ tabIndex: S ? -1 : x.tabIndex,
39
+ onClick: S ? t : x.onClick,
40
+ onAuxClick: S ? t : x.onAuxClick,
41
+ children: w
37
42
  });
38
- }
43
+ });
39
44
  //#endregion
40
- export { i as Button };
45
+ export { o as Button };
41
46
 
42
47
  //# sourceMappingURL=Button.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","names":[],"sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — this is the design system's button: variant, size,\n * loading, fullWidth, iconOnly, pill, leftIcon and rightIcon are the whole\n * vocabulary every screen composes from. Eight orthogonal knobs on the most-used\n * component is the API working — the count rule is looking for two components fused\n * together, and there is only one here.\n */\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Button.module.css\";\n\nexport type ButtonVariant =\n \"primary\" | \"secondary\" | \"danger\" | \"success\" | \"ghost\" | \"soft\" | \"outline\" | \"link\";\nexport type ButtonSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n loading?: boolean;\n fullWidth?: boolean;\n /** Removes horizontal padding and forces a square footprint (use with `aria-label`). */\n iconOnly?: boolean;\n /** Pill-shaped border radius. */\n pill?: boolean;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n}\n\n/**\n * Primary action button with variants, sizes and a loading state that\n * preserves layout via an absolutely-positioned spinner.\n *\n * Variants: `primary` (solid), `secondary` (neutral), `danger`, `success`,\n * `ghost` (transparent), `soft` (tinted), `outline` (bordered), `link`.\n *\n * Sizes are density-aware — they read from `--tempest-control-height-*`\n * tokens which respond to the `data-tempest-density` attribute.\n */\nexport function Button({\n variant = \"primary\",\n size = \"md\",\n loading = false,\n fullWidth = false,\n iconOnly = false,\n pill = false,\n leftIcon,\n rightIcon,\n disabled,\n className,\n children,\n ...props\n}: ButtonProps) {\n return (\n <button\n className={cn(\n styles.button,\n styles[variant],\n styles[size],\n iconOnly && styles.iconOnly,\n pill && styles.pill,\n loading && styles.loading,\n fullWidth && styles.fullWidth,\n className,\n )}\n disabled={disabled || loading}\n {...props}\n >\n {loading && (\n <span className={styles.spinner} aria-hidden>\n <SpinnerIcon />\n </span>\n )}\n <span className={cn(styles.content, loading && styles.hiddenText)}>\n {leftIcon}\n {children}\n {rightIcon}\n </span>\n </button>\n );\n}\n\nfunction SpinnerIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M21 12a9 9 0 1 1-6.219-8.56\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n"],"mappings":";;;;AAsCA,SAAgB,EAAO,EACnB,aAAU,WACV,UAAO,MACP,aAAU,IACV,eAAY,IACZ,cAAW,IACX,UAAO,IACP,aACA,cACA,aACA,cACA,aACA,GAAG,KACS;CACZ,OACI,kBAAC,UAAD;EACI,WAAW,EACP,EAAO,QACP,EAAO,IACP,EAAO,IACP,KAAY,EAAO,UACnB,KAAQ,EAAO,MACf,KAAW,EAAO,SAClB,KAAa,EAAO,WACpB,CACJ;EACA,UAAU,KAAY;EACtB,GAAI;EAZR,UAAA,CAcK,KACG,kBAAC,QAAD;GAAM,WAAW,EAAO;GAAS,eAAA;GAC7B,UAAA,kBAAC,GAAD,CAAc,CAAA;EACZ,CAAA,GAEV,kBAAC,QAAD;GAAM,WAAW,EAAG,EAAO,SAAS,KAAW,EAAO,UAAU;GAAhE,UAAA;IACK;IACA;IACA;GACC;EACF,CAAA,CAAA;;AAEhB;AAEA,SAAS,IAAc;CACnB,OACI,kBAAC,OAAD;EACI,OAAM;EACN,QAAO;EACP,SAAQ;EACR,MAAK;EACL,OAAM;EAEN,UAAA,kBAAC,QAAD;GACI,GAAE;GACF,QAAO;GACP,aAAY;GACZ,eAAc;EACjB,CAAA;CACA,CAAA;AAEb"}
1
+ {"version":3,"file":"Button.js","names":[],"sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — this is the design system's button: variant, size,\n * loading, fullWidth, iconOnly, pill, leftIcon and rightIcon are the whole\n * vocabulary every screen composes from, and href only picks which element carries\n * it. Nine orthogonal knobs on the most-used component is the API working — the\n * count rule is looking for two components fused together, and there is only one\n * here.\n */\nimport { forwardRef } from \"react\";\nimport type {\n AnchorHTMLAttributes,\n ButtonHTMLAttributes,\n ForwardedRef,\n HTMLAttributes,\n ReactElement,\n ReactNode,\n Ref,\n RefAttributes,\n} from \"react\";\nimport { buttonClassName, preventActivation } from \"./button-class\";\nimport { ButtonContent } from \"./ButtonContent\";\nimport { resolveLinkRel } from \"./link-rel\";\nimport type { ButtonBaseProps } from \"./types\";\n\nexport type { ButtonBaseProps, ButtonSize, ButtonVariant } from \"./types\";\n\n/** `Button` rendering a native `<button>` — the default, when `href` is not set. */\nexport interface ButtonAsButtonProps\n extends ButtonBaseProps, ButtonHTMLAttributes<HTMLButtonElement> {\n href?: undefined;\n}\n\n/**\n * `Button` rendering an `<a href>` — a call to action that navigates.\n *\n * `type` is a `<button>` attribute and is rejected here; `target` and `rel` are\n * forwarded, and `target=\"_blank\"` always gets `noopener noreferrer` added.\n */\nexport interface ButtonAsLinkProps\n extends ButtonBaseProps, Omit<AnchorHTMLAttributes<HTMLAnchorElement>, \"href\" | \"type\"> {\n /** Destination. Its presence is what makes the button an `<a>`. */\n href: string;\n type?: never;\n}\n\nexport type ButtonProps = ButtonAsButtonProps | ButtonAsLinkProps;\n\n/**\n * Each mode's props with the ref type of the element it renders, so a `ref` to an\n * `HTMLButtonElement` on a link is a type error.\n */\ntype ButtonPropsWithRef =\n | (ButtonAsButtonProps & RefAttributes<HTMLButtonElement>)\n | (ButtonAsLinkProps & RefAttributes<HTMLAnchorElement>);\n\n/** `Button`'s call signature: one props union, each member with its own ref type. */\ntype ButtonComponent = ((props: ButtonPropsWithRef) => ReactElement) & { displayName?: string };\n\n/** The flattened view the render function works on after the call site was type-checked. */\ntype ButtonRenderProps = ButtonBaseProps &\n HTMLAttributes<HTMLElement> & {\n href?: string;\n target?: string;\n rel?: string;\n };\n\n/**\n * Primary action button with variants, sizes and a loading state that\n * preserves layout via an absolutely-positioned spinner.\n *\n * Variants: `primary` (solid), `secondary` (neutral), `danger`, `success`,\n * `ghost` (transparent), `soft` (tinted), `outline` (bordered), `link`.\n *\n * Sizes are density-aware — they read from `--tempest-control-height-*`\n * tokens which respond to the `data-tempest-density` attribute.\n *\n * With `href` it renders an `<a>` with the same look: a call to action that\n * navigates keeps the middle click, Ctrl+click, \"open in new tab\" and the URL\n * preview, which a `<button>` calling `location.assign` loses. `target=\"_blank\"`\n * gets `noopener noreferrer`. An `<a>` has no `disabled`, so a disabled or loading\n * link gets `aria-disabled=\"true\"`, `role=\"link\"`, `tabIndex={-1}`, no `href`, and\n * its click and middle-click cancelled.\n *\n * To style another element — a react-router `Link` — use {@link ButtonSlot}. It is\n * a separate component, not an `asChild` prop, so an app that never uses it does\n * not ship the prop merge and ref composition it needs.\n *\n * The ref is typed per mode: `HTMLButtonElement`, or `HTMLAnchorElement` with\n * `href`. `forwardRef` takes one ref type for all props, so its result is re-typed\n * to the per-mode union — the runtime is plain `forwardRef`.\n *\n * @example\n * <Button onClick={save}>Salvar</Button>\n *\n * @example\n * <Button href=\"https://wa.me/5586999999999\" target=\"_blank\" rightIcon={<ExternalLink />}>\n * Fale conosco\n * </Button>\n */\nexport const Button = forwardRef<HTMLElement, ButtonProps>(function Button(\n props: ButtonProps,\n ref: ForwardedRef<HTMLElement>,\n): ReactElement {\n const {\n variant,\n size,\n loading = false,\n disabled = false,\n fullWidth,\n iconOnly,\n pill,\n leftIcon,\n rightIcon,\n className,\n children,\n href,\n target,\n rel,\n ...rest\n } = props as ButtonRenderProps;\n const inactive = disabled || loading;\n const classes = buttonClassName(\n { variant, size, loading, fullWidth, iconOnly, pill },\n className,\n );\n const content: ReactNode = (\n <ButtonContent loading={loading} leftIcon={leftIcon} rightIcon={rightIcon}>\n {children}\n </ButtonContent>\n );\n\n if (href !== undefined) {\n return (\n <a\n {...rest}\n ref={ref as Ref<HTMLAnchorElement>}\n className={classes}\n href={inactive ? undefined : href}\n target={target}\n rel={resolveLinkRel(target, rel)}\n role={inactive ? \"link\" : rest.role}\n aria-disabled={inactive || undefined}\n aria-busy={loading || undefined}\n tabIndex={inactive ? -1 : rest.tabIndex}\n onClick={inactive ? preventActivation : rest.onClick}\n onAuxClick={inactive ? preventActivation : rest.onAuxClick}\n >\n {content}\n </a>\n );\n }\n\n return (\n <button\n {...(rest as ButtonHTMLAttributes<HTMLButtonElement>)}\n ref={ref as Ref<HTMLButtonElement>}\n className={classes}\n disabled={inactive}\n aria-busy={loading || undefined}\n >\n {content}\n </button>\n );\n}) as unknown as ButtonComponent;\n"],"mappings":";;;;;;AAmGA,IAAa,IAAS,EAAqC,SACvD,GACA,GACY;CACZ,IAAM,EACF,YACA,SACA,aAAU,IACV,cAAW,IACX,cACA,aACA,SACA,aACA,cACA,cACA,aACA,SACA,WACA,QACA,GAAG,MACH,GACE,IAAW,KAAY,GACvB,IAAU,EACZ;EAAE;EAAS;EAAM;EAAS;EAAW;EAAU;CAAK,GACpD,CACJ,GACM,IACF,kBAAC,GAAD;EAAwB;EAAmB;EAAqB;EAC3D;CACU,CAAA;CAwBnB,OArBI,MAAS,KAAA,IAsBT,kBAAC,UAAD;EACI,GAAK;EACA;EACL,WAAW;EACX,UAAU;EACV,aAAW,KAAW,KAAA;EAErB,UAAA;CACG,CAAA,IA5BJ,kBAAC,KAAD;EACI,GAAI;EACC;EACL,WAAW;EACX,MAAM,IAAW,KAAA,IAAY;EACrB;EACR,KAAK,EAAe,GAAQ,CAAG;EAC/B,MAAM,IAAW,SAAS,EAAK;EAC/B,iBAAe,KAAY,KAAA;EAC3B,aAAW,KAAW,KAAA;EACtB,UAAU,IAAW,KAAK,EAAK;EAC/B,SAAS,IAAW,IAAoB,EAAK;EAC7C,YAAY,IAAW,IAAoB,EAAK;EAE/C,UAAA;CACF,CAAA;AAef,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Button.module.cjs","names":[],"sources":["../../../src/components/Button/Button.module.css"],"sourcesContent":[".button {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-control-gap, var(--tempest-space-2));\n border: 1px solid transparent;\n border-radius: var(--tempest-control-radius, var(--tempest-radius-md));\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-none);\n letter-spacing: var(--tempest-tracking-normal);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n transition: var(--tempest-transition-base);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.button:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .button:hover:not(:disabled) {\n box-shadow: var(--tempest-shadow-sm);\n }\n}\n\n.button:active:not(:disabled) {\n transform: translateY(1px);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.button:disabled {\n opacity: 0.55;\n box-shadow: none;\n}\n\n/* ============================================================\n * Variants — solid (default), soft, outline, ghost\n * Status colors: primary, secondary (neutral), danger, success\n * ============================================================ */\n\n/* primary — solid filled */\n.primary {\n background-color: var(--tempest-primary);\n color: var(--tempest-primary-foreground);\n}\n.primary:hover:not(:disabled) {\n background-color: var(--tempest-primary-hover);\n}\n.primary:active:not(:disabled) {\n background-color: var(--tempest-primary-active);\n}\n\n/* secondary — neutral surface */\n.secondary {\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n border-color: var(--tempest-border);\n}\n.secondary:hover:not(:disabled) {\n background-color: var(--tempest-surface-2);\n border-color: var(--tempest-border-strong);\n}\n\n/* danger — solid red */\n.danger {\n background-color: var(--tempest-danger-solid);\n color: var(--tempest-danger-on-solid);\n}\n.danger:hover:not(:disabled) {\n background-color: var(--tempest-danger-hover);\n}\n\n/* success — solid green */\n.success {\n background-color: var(--tempest-success-solid);\n color: var(--tempest-success-on-solid);\n}\n.success:hover:not(:disabled) {\n filter: brightness(0.92);\n}\n\n/* ghost — transparent, hover surface */\n.ghost {\n background-color: transparent;\n color: var(--tempest-text);\n box-shadow: none;\n}\n.ghost:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n box-shadow: none;\n}\n.ghost:active:not(:disabled) {\n background-color: var(--tempest-surface-2);\n box-shadow: none;\n}\n\n/* soft — tinted background, primary text */\n.soft {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n box-shadow: none;\n}\n.soft:hover:not(:disabled) {\n background-color: var(--tempest-primary-soft-hover);\n}\n\n/* outline — bordered, transparent fill */\n.outline {\n background-color: transparent;\n color: var(--tempest-primary);\n border-color: var(--tempest-primary);\n box-shadow: none;\n}\n/*\n * The text colour has to move with the background.\n *\n * `.outline` sets `color: var(--tempest-primary)` over a transparent background,\n * where it is fine. This rule tints the background to `--tempest-primary-soft` and,\n * without restating the colour, leaves the fill token sitting on the tint: **4.38:1 in\n * the light theme and 4.28:1 in dark**, both under the 4.5:1 floor for text — so the\n * label got harder to read at the exact moment the pointer was on it.\n *\n * `--tempest-primary-on-soft` is the token for this ground (6.18:1 / 8.72:1) and\n * `docs/styles.md` has documented the rule all along. A rule that changes only the\n * background of a coloured element is the shape of this bug; the other eight places in\n * the SDK that tint a background inherit `--tempest-text`, `--tempest-text-muted` or\n * `--tempest-primary-on-soft` and are fine.\n */\n.outline:hover:not(:disabled) {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n}\n\n/* link — text-only, underline on hover */\n.link {\n background-color: transparent;\n color: var(--tempest-primary);\n box-shadow: none;\n padding-left: 0;\n padding-right: 0;\n border-radius: var(--tempest-radius-sm);\n}\n.link:hover:not(:disabled) {\n color: var(--tempest-primary-hover);\n text-decoration: underline;\n background: none;\n box-shadow: none;\n}\n\n/* ============================================================\n * Sizes — token-driven, density-aware\n * ============================================================ */\n.xs {\n height: var(--tempest-control-height-xs);\n padding: 0 var(--tempest-control-padding-xs);\n font-size: var(--tempest-control-font-xs);\n}\n.sm {\n height: var(--tempest-control-height-sm);\n padding: 0 var(--tempest-control-padding-sm);\n font-size: var(--tempest-control-font-sm);\n}\n.md {\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n font-size: var(--tempest-control-font-md);\n}\n.lg {\n height: var(--tempest-control-height-lg);\n padding: 0 var(--tempest-control-padding-lg);\n font-size: var(--tempest-control-font-lg);\n}\n.xl {\n height: var(--tempest-control-height-xl);\n padding: 0 var(--tempest-control-padding-xl);\n font-size: var(--tempest-control-font-xl);\n}\n\n/* Square (icon-only) — width matches height */\n.iconOnly {\n position: relative;\n}\n.iconOnly.xs {\n width: var(--tempest-control-height-xs);\n padding: 0;\n}\n.iconOnly.sm {\n width: var(--tempest-control-height-sm);\n padding: 0;\n}\n.iconOnly.md {\n width: var(--tempest-control-height-md);\n padding: 0;\n}\n.iconOnly.lg {\n width: var(--tempest-control-height-lg);\n padding: 0;\n}\n.iconOnly.xl {\n width: var(--tempest-control-height-xl);\n padding: 0;\n}\n\n/* Touch hit-slop — extend tap target to a min 44×44 on coarse pointers\n * for the smallest icon-only sizes, without changing visual footprint. */\n@media (pointer: coarse) {\n .iconOnly.xs::after,\n .iconOnly.sm::after {\n content: \"\";\n position: absolute;\n inset: -8px;\n }\n}\n\n/* Pill shape */\n.pill {\n border-radius: var(--tempest-radius-full);\n}\n\n.fullWidth {\n width: 100%;\n}\n\n/*\n * Lay out leftIcon + label + rightIcon as one centered, gapped row. Without\n * this the three are inline inside a single span (no gap, icon baseline-\n * aligned instead of centered), which reads as off-center — most visible on\n * fullWidth buttons where the label has room to drift.\n */\n.content {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-control-gap, var(--tempest-space-2));\n min-width: 0;\n}\n\n.loading .hiddenText {\n visibility: hidden;\n}\n\n.spinner {\n position: absolute;\n animation: tempest-spin 0.8s linear infinite;\n}\n\n@keyframes tempest-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],"mappings":";"}
1
+ {"version":3,"file":"Button.module.cjs","names":[],"sources":["../../../src/components/Button/Button.module.css"],"sourcesContent":[".button {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-control-gap, var(--tempest-space-2));\n border: 1px solid transparent;\n border-radius: var(--tempest-control-radius, var(--tempest-radius-md));\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-none);\n letter-spacing: var(--tempest-tracking-normal);\n color: var(--_tempest-button-fg);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n transition: var(--tempest-transition-base);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.button:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .button:hover:not(:disabled, [aria-disabled=\"true\"]) {\n box-shadow: var(--tempest-shadow-sm);\n }\n}\n\n.button:active:not(:disabled, [aria-disabled=\"true\"]) {\n transform: translateY(1px);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.button:disabled,\n.button[aria-disabled=\"true\"] {\n opacity: 0.55;\n box-shadow: none;\n}\n\n.button[aria-disabled=\"true\"] {\n cursor: not-allowed;\n}\n\n/*\n * `<Button href>` and `<ButtonSlot>` around a link render an `<a>`, and an app's own link\n * rules reach it. `.button` is one class (0,1,0); `a:hover { color }` is (0,1,1) and\n * wins — the Vite React template ships exactly that rule, so in a fresh app a\n * primary link-button turned its label `#535bf2` on hover, over the primary fill.\n *\n * Each variant therefore sets its text colour as `--_tempest-button-fg` instead of\n * `color`, and this rule restates it on every link state at (0,2,1), above any\n * single-element link rule. The `link` variant's hover underline is (0,3,0) and\n * still applies.\n */\na.button:is(:link, :visited, :hover, :active, :focus, :not([href])) {\n color: var(--_tempest-button-fg);\n text-decoration: none;\n}\n\n/* ============================================================\n * Variants — solid (default), soft, outline, ghost\n * Status colors: primary, secondary (neutral), danger, success\n * ============================================================ */\n\n/* primary — solid filled */\n.primary {\n background-color: var(--tempest-primary);\n --_tempest-button-fg: var(--tempest-primary-foreground);\n}\n.primary:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-primary-hover);\n}\n.primary:active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-primary-active);\n}\n\n/* secondary — neutral surface */\n.secondary {\n background-color: var(--tempest-surface);\n --_tempest-button-fg: var(--tempest-text);\n border-color: var(--tempest-border);\n}\n.secondary:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-surface-2);\n border-color: var(--tempest-border-strong);\n}\n\n/* danger — solid red */\n.danger {\n background-color: var(--tempest-danger-solid);\n --_tempest-button-fg: var(--tempest-danger-on-solid);\n}\n.danger:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-danger-hover);\n}\n\n/* success — solid green */\n.success {\n background-color: var(--tempest-success-solid);\n --_tempest-button-fg: var(--tempest-success-on-solid);\n}\n.success:hover:not(:disabled, [aria-disabled=\"true\"]) {\n filter: brightness(0.92);\n}\n\n/* ghost — transparent, hover surface */\n.ghost {\n background-color: transparent;\n --_tempest-button-fg: var(--tempest-text);\n box-shadow: none;\n}\n.ghost:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-surface);\n box-shadow: none;\n}\n.ghost:active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-surface-2);\n box-shadow: none;\n}\n\n/* soft — tinted background, primary text */\n.soft {\n background-color: var(--tempest-primary-soft);\n --_tempest-button-fg: var(--tempest-primary-on-soft);\n box-shadow: none;\n}\n.soft:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-primary-soft-hover);\n}\n\n/* outline — bordered, transparent fill */\n.outline {\n background-color: transparent;\n --_tempest-button-fg: var(--tempest-primary);\n border-color: var(--tempest-primary);\n box-shadow: none;\n}\n/*\n * The text colour has to move with the background.\n *\n * `.outline` sets its text to `var(--tempest-primary)` over a transparent background,\n * where it is fine. This rule tints the background to `--tempest-primary-soft` and,\n * without restating the colour, leaves the fill token sitting on the tint: **4.38:1 in\n * the light theme and 4.28:1 in dark**, both under the 4.5:1 floor for text — so the\n * label got harder to read at the exact moment the pointer was on it.\n *\n * `--tempest-primary-on-soft` is the token for this ground (6.18:1 / 8.72:1) and\n * `docs/styles.md` has documented the rule all along. A rule that changes only the\n * background of a coloured element is the shape of this bug; the other eight places in\n * the SDK that tint a background inherit `--tempest-text`, `--tempest-text-muted` or\n * `--tempest-primary-on-soft` and are fine.\n */\n.outline:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-primary-soft);\n --_tempest-button-fg: var(--tempest-primary-on-soft);\n}\n\n/* link — text-only, underline on hover */\n.link {\n background-color: transparent;\n --_tempest-button-fg: var(--tempest-primary);\n box-shadow: none;\n padding-left: 0;\n padding-right: 0;\n border-radius: var(--tempest-radius-sm);\n}\n.link:hover:not(:disabled, [aria-disabled=\"true\"]) {\n --_tempest-button-fg: var(--tempest-primary-hover);\n text-decoration: underline;\n background: none;\n box-shadow: none;\n}\n\n/* ============================================================\n * Sizes — token-driven, density-aware\n * ============================================================ */\n.xs {\n height: var(--tempest-control-height-xs);\n padding: 0 var(--tempest-control-padding-xs);\n font-size: var(--tempest-control-font-xs);\n}\n.sm {\n height: var(--tempest-control-height-sm);\n padding: 0 var(--tempest-control-padding-sm);\n font-size: var(--tempest-control-font-sm);\n}\n.md {\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n font-size: var(--tempest-control-font-md);\n}\n.lg {\n height: var(--tempest-control-height-lg);\n padding: 0 var(--tempest-control-padding-lg);\n font-size: var(--tempest-control-font-lg);\n}\n.xl {\n height: var(--tempest-control-height-xl);\n padding: 0 var(--tempest-control-padding-xl);\n font-size: var(--tempest-control-font-xl);\n}\n\n/* Square (icon-only) — width matches height */\n.iconOnly {\n position: relative;\n}\n.iconOnly.xs {\n width: var(--tempest-control-height-xs);\n padding: 0;\n}\n.iconOnly.sm {\n width: var(--tempest-control-height-sm);\n padding: 0;\n}\n.iconOnly.md {\n width: var(--tempest-control-height-md);\n padding: 0;\n}\n.iconOnly.lg {\n width: var(--tempest-control-height-lg);\n padding: 0;\n}\n.iconOnly.xl {\n width: var(--tempest-control-height-xl);\n padding: 0;\n}\n\n/* Touch hit-slop — extend tap target to a min 44×44 on coarse pointers\n * for the smallest icon-only sizes, without changing visual footprint. */\n@media (pointer: coarse) {\n .iconOnly.xs::after,\n .iconOnly.sm::after {\n content: \"\";\n position: absolute;\n inset: -8px;\n }\n}\n\n/* Pill shape */\n.pill {\n border-radius: var(--tempest-radius-full);\n}\n\n.fullWidth {\n width: 100%;\n}\n\n/*\n * Lay out leftIcon + label + rightIcon as one centered, gapped row. Without\n * this the three are inline inside a single span (no gap, icon baseline-\n * aligned instead of centered), which reads as off-center — most visible on\n * fullWidth buttons where the label has room to drift.\n */\n.content {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-control-gap, var(--tempest-space-2));\n min-width: 0;\n}\n\n/*\n * Hide the label by paint only. `visibility: hidden` also drops it from the\n * accessibility tree, so a loading button lost its name (#416). `opacity: 0`\n * keeps the name and the width; `pointer-events: none` keeps the invisible\n * label out of hit-testing, as it was. Forced colors leaves `opacity` alone.\n */\n.loading .hiddenText {\n opacity: 0;\n pointer-events: none;\n}\n\n.spinner {\n position: absolute;\n animation: tempest-spin 0.8s linear infinite;\n}\n\n@keyframes tempest-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],"mappings":";"}
@@ -1 +1 @@
1
- {"version":3,"file":"Button.module.js","names":[],"sources":["../../../src/components/Button/Button.module.css"],"sourcesContent":[".button {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-control-gap, var(--tempest-space-2));\n border: 1px solid transparent;\n border-radius: var(--tempest-control-radius, var(--tempest-radius-md));\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-none);\n letter-spacing: var(--tempest-tracking-normal);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n transition: var(--tempest-transition-base);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.button:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .button:hover:not(:disabled) {\n box-shadow: var(--tempest-shadow-sm);\n }\n}\n\n.button:active:not(:disabled) {\n transform: translateY(1px);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.button:disabled {\n opacity: 0.55;\n box-shadow: none;\n}\n\n/* ============================================================\n * Variants — solid (default), soft, outline, ghost\n * Status colors: primary, secondary (neutral), danger, success\n * ============================================================ */\n\n/* primary — solid filled */\n.primary {\n background-color: var(--tempest-primary);\n color: var(--tempest-primary-foreground);\n}\n.primary:hover:not(:disabled) {\n background-color: var(--tempest-primary-hover);\n}\n.primary:active:not(:disabled) {\n background-color: var(--tempest-primary-active);\n}\n\n/* secondary — neutral surface */\n.secondary {\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n border-color: var(--tempest-border);\n}\n.secondary:hover:not(:disabled) {\n background-color: var(--tempest-surface-2);\n border-color: var(--tempest-border-strong);\n}\n\n/* danger — solid red */\n.danger {\n background-color: var(--tempest-danger-solid);\n color: var(--tempest-danger-on-solid);\n}\n.danger:hover:not(:disabled) {\n background-color: var(--tempest-danger-hover);\n}\n\n/* success — solid green */\n.success {\n background-color: var(--tempest-success-solid);\n color: var(--tempest-success-on-solid);\n}\n.success:hover:not(:disabled) {\n filter: brightness(0.92);\n}\n\n/* ghost — transparent, hover surface */\n.ghost {\n background-color: transparent;\n color: var(--tempest-text);\n box-shadow: none;\n}\n.ghost:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n box-shadow: none;\n}\n.ghost:active:not(:disabled) {\n background-color: var(--tempest-surface-2);\n box-shadow: none;\n}\n\n/* soft — tinted background, primary text */\n.soft {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n box-shadow: none;\n}\n.soft:hover:not(:disabled) {\n background-color: var(--tempest-primary-soft-hover);\n}\n\n/* outline — bordered, transparent fill */\n.outline {\n background-color: transparent;\n color: var(--tempest-primary);\n border-color: var(--tempest-primary);\n box-shadow: none;\n}\n/*\n * The text colour has to move with the background.\n *\n * `.outline` sets `color: var(--tempest-primary)` over a transparent background,\n * where it is fine. This rule tints the background to `--tempest-primary-soft` and,\n * without restating the colour, leaves the fill token sitting on the tint: **4.38:1 in\n * the light theme and 4.28:1 in dark**, both under the 4.5:1 floor for text — so the\n * label got harder to read at the exact moment the pointer was on it.\n *\n * `--tempest-primary-on-soft` is the token for this ground (6.18:1 / 8.72:1) and\n * `docs/styles.md` has documented the rule all along. A rule that changes only the\n * background of a coloured element is the shape of this bug; the other eight places in\n * the SDK that tint a background inherit `--tempest-text`, `--tempest-text-muted` or\n * `--tempest-primary-on-soft` and are fine.\n */\n.outline:hover:not(:disabled) {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n}\n\n/* link — text-only, underline on hover */\n.link {\n background-color: transparent;\n color: var(--tempest-primary);\n box-shadow: none;\n padding-left: 0;\n padding-right: 0;\n border-radius: var(--tempest-radius-sm);\n}\n.link:hover:not(:disabled) {\n color: var(--tempest-primary-hover);\n text-decoration: underline;\n background: none;\n box-shadow: none;\n}\n\n/* ============================================================\n * Sizes — token-driven, density-aware\n * ============================================================ */\n.xs {\n height: var(--tempest-control-height-xs);\n padding: 0 var(--tempest-control-padding-xs);\n font-size: var(--tempest-control-font-xs);\n}\n.sm {\n height: var(--tempest-control-height-sm);\n padding: 0 var(--tempest-control-padding-sm);\n font-size: var(--tempest-control-font-sm);\n}\n.md {\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n font-size: var(--tempest-control-font-md);\n}\n.lg {\n height: var(--tempest-control-height-lg);\n padding: 0 var(--tempest-control-padding-lg);\n font-size: var(--tempest-control-font-lg);\n}\n.xl {\n height: var(--tempest-control-height-xl);\n padding: 0 var(--tempest-control-padding-xl);\n font-size: var(--tempest-control-font-xl);\n}\n\n/* Square (icon-only) — width matches height */\n.iconOnly {\n position: relative;\n}\n.iconOnly.xs {\n width: var(--tempest-control-height-xs);\n padding: 0;\n}\n.iconOnly.sm {\n width: var(--tempest-control-height-sm);\n padding: 0;\n}\n.iconOnly.md {\n width: var(--tempest-control-height-md);\n padding: 0;\n}\n.iconOnly.lg {\n width: var(--tempest-control-height-lg);\n padding: 0;\n}\n.iconOnly.xl {\n width: var(--tempest-control-height-xl);\n padding: 0;\n}\n\n/* Touch hit-slop — extend tap target to a min 44×44 on coarse pointers\n * for the smallest icon-only sizes, without changing visual footprint. */\n@media (pointer: coarse) {\n .iconOnly.xs::after,\n .iconOnly.sm::after {\n content: \"\";\n position: absolute;\n inset: -8px;\n }\n}\n\n/* Pill shape */\n.pill {\n border-radius: var(--tempest-radius-full);\n}\n\n.fullWidth {\n width: 100%;\n}\n\n/*\n * Lay out leftIcon + label + rightIcon as one centered, gapped row. Without\n * this the three are inline inside a single span (no gap, icon baseline-\n * aligned instead of centered), which reads as off-center — most visible on\n * fullWidth buttons where the label has room to drift.\n */\n.content {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-control-gap, var(--tempest-space-2));\n min-width: 0;\n}\n\n.loading .hiddenText {\n visibility: hidden;\n}\n\n.spinner {\n position: absolute;\n animation: tempest-spin 0.8s linear infinite;\n}\n\n@keyframes tempest-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],"mappings":";"}
1
+ {"version":3,"file":"Button.module.js","names":[],"sources":["../../../src/components/Button/Button.module.css"],"sourcesContent":[".button {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-control-gap, var(--tempest-space-2));\n border: 1px solid transparent;\n border-radius: var(--tempest-control-radius, var(--tempest-radius-md));\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-none);\n letter-spacing: var(--tempest-tracking-normal);\n color: var(--_tempest-button-fg);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n transition: var(--tempest-transition-base);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.button:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .button:hover:not(:disabled, [aria-disabled=\"true\"]) {\n box-shadow: var(--tempest-shadow-sm);\n }\n}\n\n.button:active:not(:disabled, [aria-disabled=\"true\"]) {\n transform: translateY(1px);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.button:disabled,\n.button[aria-disabled=\"true\"] {\n opacity: 0.55;\n box-shadow: none;\n}\n\n.button[aria-disabled=\"true\"] {\n cursor: not-allowed;\n}\n\n/*\n * `<Button href>` and `<ButtonSlot>` around a link render an `<a>`, and an app's own link\n * rules reach it. `.button` is one class (0,1,0); `a:hover { color }` is (0,1,1) and\n * wins — the Vite React template ships exactly that rule, so in a fresh app a\n * primary link-button turned its label `#535bf2` on hover, over the primary fill.\n *\n * Each variant therefore sets its text colour as `--_tempest-button-fg` instead of\n * `color`, and this rule restates it on every link state at (0,2,1), above any\n * single-element link rule. The `link` variant's hover underline is (0,3,0) and\n * still applies.\n */\na.button:is(:link, :visited, :hover, :active, :focus, :not([href])) {\n color: var(--_tempest-button-fg);\n text-decoration: none;\n}\n\n/* ============================================================\n * Variants — solid (default), soft, outline, ghost\n * Status colors: primary, secondary (neutral), danger, success\n * ============================================================ */\n\n/* primary — solid filled */\n.primary {\n background-color: var(--tempest-primary);\n --_tempest-button-fg: var(--tempest-primary-foreground);\n}\n.primary:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-primary-hover);\n}\n.primary:active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-primary-active);\n}\n\n/* secondary — neutral surface */\n.secondary {\n background-color: var(--tempest-surface);\n --_tempest-button-fg: var(--tempest-text);\n border-color: var(--tempest-border);\n}\n.secondary:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-surface-2);\n border-color: var(--tempest-border-strong);\n}\n\n/* danger — solid red */\n.danger {\n background-color: var(--tempest-danger-solid);\n --_tempest-button-fg: var(--tempest-danger-on-solid);\n}\n.danger:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-danger-hover);\n}\n\n/* success — solid green */\n.success {\n background-color: var(--tempest-success-solid);\n --_tempest-button-fg: var(--tempest-success-on-solid);\n}\n.success:hover:not(:disabled, [aria-disabled=\"true\"]) {\n filter: brightness(0.92);\n}\n\n/* ghost — transparent, hover surface */\n.ghost {\n background-color: transparent;\n --_tempest-button-fg: var(--tempest-text);\n box-shadow: none;\n}\n.ghost:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-surface);\n box-shadow: none;\n}\n.ghost:active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-surface-2);\n box-shadow: none;\n}\n\n/* soft — tinted background, primary text */\n.soft {\n background-color: var(--tempest-primary-soft);\n --_tempest-button-fg: var(--tempest-primary-on-soft);\n box-shadow: none;\n}\n.soft:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-primary-soft-hover);\n}\n\n/* outline — bordered, transparent fill */\n.outline {\n background-color: transparent;\n --_tempest-button-fg: var(--tempest-primary);\n border-color: var(--tempest-primary);\n box-shadow: none;\n}\n/*\n * The text colour has to move with the background.\n *\n * `.outline` sets its text to `var(--tempest-primary)` over a transparent background,\n * where it is fine. This rule tints the background to `--tempest-primary-soft` and,\n * without restating the colour, leaves the fill token sitting on the tint: **4.38:1 in\n * the light theme and 4.28:1 in dark**, both under the 4.5:1 floor for text — so the\n * label got harder to read at the exact moment the pointer was on it.\n *\n * `--tempest-primary-on-soft` is the token for this ground (6.18:1 / 8.72:1) and\n * `docs/styles.md` has documented the rule all along. A rule that changes only the\n * background of a coloured element is the shape of this bug; the other eight places in\n * the SDK that tint a background inherit `--tempest-text`, `--tempest-text-muted` or\n * `--tempest-primary-on-soft` and are fine.\n */\n.outline:hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--tempest-primary-soft);\n --_tempest-button-fg: var(--tempest-primary-on-soft);\n}\n\n/* link — text-only, underline on hover */\n.link {\n background-color: transparent;\n --_tempest-button-fg: var(--tempest-primary);\n box-shadow: none;\n padding-left: 0;\n padding-right: 0;\n border-radius: var(--tempest-radius-sm);\n}\n.link:hover:not(:disabled, [aria-disabled=\"true\"]) {\n --_tempest-button-fg: var(--tempest-primary-hover);\n text-decoration: underline;\n background: none;\n box-shadow: none;\n}\n\n/* ============================================================\n * Sizes — token-driven, density-aware\n * ============================================================ */\n.xs {\n height: var(--tempest-control-height-xs);\n padding: 0 var(--tempest-control-padding-xs);\n font-size: var(--tempest-control-font-xs);\n}\n.sm {\n height: var(--tempest-control-height-sm);\n padding: 0 var(--tempest-control-padding-sm);\n font-size: var(--tempest-control-font-sm);\n}\n.md {\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n font-size: var(--tempest-control-font-md);\n}\n.lg {\n height: var(--tempest-control-height-lg);\n padding: 0 var(--tempest-control-padding-lg);\n font-size: var(--tempest-control-font-lg);\n}\n.xl {\n height: var(--tempest-control-height-xl);\n padding: 0 var(--tempest-control-padding-xl);\n font-size: var(--tempest-control-font-xl);\n}\n\n/* Square (icon-only) — width matches height */\n.iconOnly {\n position: relative;\n}\n.iconOnly.xs {\n width: var(--tempest-control-height-xs);\n padding: 0;\n}\n.iconOnly.sm {\n width: var(--tempest-control-height-sm);\n padding: 0;\n}\n.iconOnly.md {\n width: var(--tempest-control-height-md);\n padding: 0;\n}\n.iconOnly.lg {\n width: var(--tempest-control-height-lg);\n padding: 0;\n}\n.iconOnly.xl {\n width: var(--tempest-control-height-xl);\n padding: 0;\n}\n\n/* Touch hit-slop — extend tap target to a min 44×44 on coarse pointers\n * for the smallest icon-only sizes, without changing visual footprint. */\n@media (pointer: coarse) {\n .iconOnly.xs::after,\n .iconOnly.sm::after {\n content: \"\";\n position: absolute;\n inset: -8px;\n }\n}\n\n/* Pill shape */\n.pill {\n border-radius: var(--tempest-radius-full);\n}\n\n.fullWidth {\n width: 100%;\n}\n\n/*\n * Lay out leftIcon + label + rightIcon as one centered, gapped row. Without\n * this the three are inline inside a single span (no gap, icon baseline-\n * aligned instead of centered), which reads as off-center — most visible on\n * fullWidth buttons where the label has room to drift.\n */\n.content {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-control-gap, var(--tempest-space-2));\n min-width: 0;\n}\n\n/*\n * Hide the label by paint only. `visibility: hidden` also drops it from the\n * accessibility tree, so a loading button lost its name (#416). `opacity: 0`\n * keeps the name and the width; `pointer-events: none` keeps the invisible\n * label out of hit-testing, as it was. Forced colors leaves `opacity` alone.\n */\n.loading .hiddenText {\n opacity: 0;\n pointer-events: none;\n}\n\n.spinner {\n position: absolute;\n animation: tempest-spin 0.8s linear infinite;\n}\n\n@keyframes tempest-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],"mappings":";"}
@@ -0,0 +1,2 @@
1
+ const e=require("../../utils/cn.cjs"),t=require("./Button.module.cjs");let n=require("react/jsx-runtime");function r({loading:r,leftIcon:i,rightIcon:a,children:o}){return(0,n.jsxs)(n.Fragment,{children:[r&&(0,n.jsx)(`span`,{className:t.default.spinner,"aria-hidden":!0,children:(0,n.jsx)(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,n.jsx)(`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`})})}),(0,n.jsxs)(`span`,{className:e.cn(t.default.content,r&&t.default.hiddenText),children:[i,o,a]})]})}exports.ButtonContent=r;
2
+ //# sourceMappingURL=ButtonContent.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonContent.cjs","names":[],"sources":["../../../src/components/Button/ButtonContent.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Button.module.css\";\n\n/** Props of {@link ButtonContent}. */\nexport interface ButtonContentProps {\n loading: boolean;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n children?: ReactNode;\n}\n\n/**\n * The inside of every button-looking element: the absolutely-positioned spinner\n * plus the icon/label row, shared by `Button` and `ButtonSlot`.\n *\n * While loading, the row is hidden by paint only (`opacity: 0`), never with\n * `visibility: hidden` or `display: none`: those drop the label from the\n * accessibility tree and the button is announced with no name (#416). Painted\n * out, the label still sizes the button — its width does not move — and still\n * names it. The spinner is `aria-hidden`, so the name is the label alone and the\n * busy state comes from `aria-busy` on the host element.\n *\n * @param props - See {@link ButtonContentProps}.\n * @returns The content nodes.\n */\nexport function ButtonContent({ loading, leftIcon, rightIcon, children }: ButtonContentProps) {\n return (\n <>\n {loading && (\n <span className={styles.spinner} aria-hidden>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M21 12a9 9 0 1 1-6.219-8.56\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n </span>\n )}\n <span className={cn(styles.content, loading && styles.hiddenText)}>\n {leftIcon}\n {children}\n {rightIcon}\n </span>\n </>\n );\n}\n"],"mappings":"0GA0BA,SAAgB,EAAc,CAAE,UAAS,WAAU,YAAW,YAAgC,CAC1F,OACI,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CACK,IACG,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,QAAS,cAAA,GAC7B,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,MAAM,6BAEN,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,EAAE,8BACF,OAAO,eACP,YAAY,IACZ,cAAc,OACjB,CAAA,CACA,CAAA,CACH,CAAA,GAEV,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,GAAW,EAAA,QAAO,UAAU,EAAhE,SAAA,CACK,EACA,EACA,CACC,CACR,CAAA,CAAA,CAAA,CAAA,CAEV"}
@@ -0,0 +1,34 @@
1
+ import { cn as e } from "../../utils/cn.js";
2
+ import t from "./Button.module.js";
3
+ import { Fragment as n, jsx as r, jsxs as i } from "react/jsx-runtime";
4
+ //#region src/components/Button/ButtonContent.tsx
5
+ function a({ loading: a, leftIcon: o, rightIcon: s, children: c }) {
6
+ return /* @__PURE__ */ i(n, { children: [a && /* @__PURE__ */ r("span", {
7
+ className: t.spinner,
8
+ "aria-hidden": !0,
9
+ children: /* @__PURE__ */ r("svg", {
10
+ width: "16",
11
+ height: "16",
12
+ viewBox: "0 0 24 24",
13
+ fill: "none",
14
+ xmlns: "http://www.w3.org/2000/svg",
15
+ children: /* @__PURE__ */ r("path", {
16
+ d: "M21 12a9 9 0 1 1-6.219-8.56",
17
+ stroke: "currentColor",
18
+ strokeWidth: "2",
19
+ strokeLinecap: "round"
20
+ })
21
+ })
22
+ }), /* @__PURE__ */ i("span", {
23
+ className: e(t.content, a && t.hiddenText),
24
+ children: [
25
+ o,
26
+ c,
27
+ s
28
+ ]
29
+ })] });
30
+ }
31
+ //#endregion
32
+ export { a as ButtonContent };
33
+
34
+ //# sourceMappingURL=ButtonContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonContent.js","names":[],"sources":["../../../src/components/Button/ButtonContent.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Button.module.css\";\n\n/** Props of {@link ButtonContent}. */\nexport interface ButtonContentProps {\n loading: boolean;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n children?: ReactNode;\n}\n\n/**\n * The inside of every button-looking element: the absolutely-positioned spinner\n * plus the icon/label row, shared by `Button` and `ButtonSlot`.\n *\n * While loading, the row is hidden by paint only (`opacity: 0`), never with\n * `visibility: hidden` or `display: none`: those drop the label from the\n * accessibility tree and the button is announced with no name (#416). Painted\n * out, the label still sizes the button — its width does not move — and still\n * names it. The spinner is `aria-hidden`, so the name is the label alone and the\n * busy state comes from `aria-busy` on the host element.\n *\n * @param props - See {@link ButtonContentProps}.\n * @returns The content nodes.\n */\nexport function ButtonContent({ loading, leftIcon, rightIcon, children }: ButtonContentProps) {\n return (\n <>\n {loading && (\n <span className={styles.spinner} aria-hidden>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M21 12a9 9 0 1 1-6.219-8.56\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n </span>\n )}\n <span className={cn(styles.content, loading && styles.hiddenText)}>\n {leftIcon}\n {children}\n {rightIcon}\n </span>\n </>\n );\n}\n"],"mappings":";;;;AA0BA,SAAgB,EAAc,EAAE,YAAS,aAAU,cAAW,eAAgC;CAC1F,OACI,kBAAA,GAAA,EAAA,UAAA,CACK,KACG,kBAAC,QAAD;EAAM,WAAW,EAAO;EAAS,eAAA;EAC7B,UAAA,kBAAC,OAAD;GACI,OAAM;GACN,QAAO;GACP,SAAQ;GACR,MAAK;GACL,OAAM;GAEN,UAAA,kBAAC,QAAD;IACI,GAAE;IACF,QAAO;IACP,aAAY;IACZ,eAAc;GACjB,CAAA;EACA,CAAA;CACH,CAAA,GAEV,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAO,SAAS,KAAW,EAAO,UAAU;EAAhE,UAAA;GACK;GACA;GACA;EACC;CACR,CAAA,CAAA,EAAA,CAAA;AAEV"}
@@ -0,0 +1,2 @@
1
+ const e=require("./button-class.cjs"),t=require("./ButtonContent.cjs"),n=require("./link-rel.cjs"),r=require("./slot.cjs");let i=require("react"),a=require("react/jsx-runtime");var o=(0,i.forwardRef)(function({variant:o,size:s,loading:c=!1,disabled:l=!1,fullWidth:u,iconOnly:d,pill:f,leftIcon:p,rightIcon:m,className:h,children:g,..._},v){let y=(0,i.isValidElement)(g)?g.props:{},b={..._,className:e.buttonClassName({variant:o,size:s,loading:c,fullWidth:u,iconOnly:d,pill:f},h),"aria-busy":c||void 0};return y.target===`_blank`&&(b.rel=n.resolveLinkRel(`_blank`,typeof y.rel==`string`?y.rel:void 0)),(l||c)&&(b[`aria-disabled`]=!0,b.tabIndex=-1,b.onClick=e.preventActivation,b.onAuxClick=e.preventActivation,y.href!==void 0&&(b.href=void 0,b.role=`link`)),(0,a.jsx)(r.Slot,{child:g,slotProps:b,slotRef:v,content:(0,a.jsx)(t.ButtonContent,{loading:c,leftIcon:p,rightIcon:m,children:y.children})})});exports.ButtonSlot=o;
2
+ //# sourceMappingURL=ButtonSlot.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonSlot.cjs","names":[],"sources":["../../../src/components/Button/ButtonSlot.tsx"],"sourcesContent":["import { forwardRef, isValidElement } from \"react\";\nimport type { ForwardedRef, HTMLAttributes, ReactElement, ReactNode } from \"react\";\nimport { buttonClassName, preventActivation } from \"./button-class\";\nimport { ButtonContent } from \"./ButtonContent\";\nimport { resolveLinkRel } from \"./link-rel\";\nimport { Slot } from \"./slot\";\nimport type { SlotProps } from \"./slot\";\nimport type { ButtonBaseProps } from \"./types\";\n\n/** Props of {@link ButtonSlot}: the `Button` look, applied to the single child. */\nexport interface ButtonSlotProps\n extends ButtonBaseProps, Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** The one element that receives the classes, props and ref — e.g. a router `Link`. */\n children: ReactElement;\n}\n\n/**\n * Lends the `Button` look to its single child element instead of rendering one —\n * the `asChild`/Slot pattern. `<ButtonSlot><Link to=\"/x\">Go</Link></ButtonSlot>`\n * styles a react-router `Link`, so the route changes without a reload, and no\n * router is imported here.\n *\n * It is a component of its own rather than an `asChild` prop on `Button` because\n * of what it costs: the prop merge and ref composition are ~0.6 kB brotli, and a\n * prop is a runtime branch no bundler can drop, so every app using `Button` paid\n * for it. As a separate export it is tree-shaken away where unused.\n *\n * Merge rules: classes are joined (a function `className`, as `NavLink` takes,\n * stays a function); `ButtonSlot`'s props win over the child's, because they carry\n * the disabled semantics; handlers run `ButtonSlot`'s first and skip the child's\n * when the event was prevented; both refs receive the node. A child with\n * `target=\"_blank\"` gets `noopener noreferrer`.\n *\n * Disabled or loading: `aria-disabled=\"true\"`, `tabIndex={-1}`, click and\n * middle-click cancelled — a router `Link` then skips its navigation because the\n * event arrives prevented. A plain `<a href>` child also loses the `href` and gets\n * `role=\"link\"`; a `Link` computes its own `href`, which stays in the DOM.\n *\n * @example\n * <ButtonSlot variant=\"outline\">\n * <Link to=\"/planos\">Ver planos</Link>\n * </ButtonSlot>\n *\n * @throws {Error} When `children` is not a single React element.\n */\nexport const ButtonSlot = forwardRef<HTMLElement, ButtonSlotProps>(function ButtonSlot(\n {\n variant,\n size,\n loading = false,\n disabled = false,\n fullWidth,\n iconOnly,\n pill,\n leftIcon,\n rightIcon,\n className,\n children,\n ...rest\n }: ButtonSlotProps,\n ref: ForwardedRef<HTMLElement>,\n): ReactElement {\n const childProps = (isValidElement(children) ? children.props : {}) as {\n target?: unknown;\n rel?: unknown;\n href?: unknown;\n children?: ReactNode;\n };\n const slotProps: SlotProps = {\n ...rest,\n className: buttonClassName(\n { variant, size, loading, fullWidth, iconOnly, pill },\n className,\n ),\n \"aria-busy\": loading || undefined,\n };\n if (childProps.target === \"_blank\") {\n slotProps.rel = resolveLinkRel(\n \"_blank\",\n typeof childProps.rel === \"string\" ? childProps.rel : undefined,\n );\n }\n if (disabled || loading) {\n slotProps[\"aria-disabled\"] = true;\n slotProps.tabIndex = -1;\n slotProps.onClick = preventActivation;\n slotProps.onAuxClick = preventActivation;\n if (childProps.href !== undefined) {\n slotProps.href = undefined;\n slotProps.role = \"link\";\n }\n }\n return (\n <Slot\n child={children}\n slotProps={slotProps}\n slotRef={ref}\n content={\n <ButtonContent loading={loading} leftIcon={leftIcon} rightIcon={rightIcon}>\n {childProps.children}\n </ButtonContent>\n }\n />\n );\n});\n"],"mappings":"iLA6CA,IAAa,GAAA,EAAa,EAAA,WAAA,CAAyC,SAC/D,CACI,UACA,OACA,UAAU,GACV,WAAW,GACX,YACA,WACA,OACA,WACA,YACA,YACA,WACA,GAAG,GAEP,EACY,CACZ,IAAM,GAAA,EAAc,EAAA,eAAA,CAAe,CAAQ,EAAI,EAAS,MAAQ,CAAC,EAM3D,EAAuB,CACzB,GAAG,EACH,UAAW,EAAA,gBACP,CAAE,UAAS,OAAM,UAAS,YAAW,WAAU,MAAK,EACpD,CACJ,EACA,YAAa,GAAW,IAAA,EAC5B,EAiBA,OAhBI,EAAW,SAAW,WACtB,EAAU,IAAM,EAAA,eACZ,SACA,OAAO,EAAW,KAAQ,SAAW,EAAW,IAAM,IAAA,EAC1D,IAEA,GAAY,KACZ,EAAU,iBAAmB,GAC7B,EAAU,SAAW,GACrB,EAAU,QAAU,EAAA,kBACpB,EAAU,WAAa,EAAA,kBACnB,EAAW,OAAS,IAAA,KACpB,EAAU,KAAO,IAAA,GACjB,EAAU,KAAO,UAIrB,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CACI,MAAO,EACI,YACX,QAAS,EACT,SACI,EAAA,EAAA,IAAA,CAAC,EAAA,cAAD,CAAwB,UAAmB,WAAqB,YAC3D,SAAA,EAAW,QACD,CAAA,CAEtB,CAAA,CAET,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { buttonClassName as e, preventActivation as t } from "./button-class.js";
2
+ import { ButtonContent as n } from "./ButtonContent.js";
3
+ import { resolveLinkRel as r } from "./link-rel.js";
4
+ import { Slot as i } from "./slot.js";
5
+ import { forwardRef as a, isValidElement as o } from "react";
6
+ import { jsx as s } from "react/jsx-runtime";
7
+ //#region src/components/Button/ButtonSlot.tsx
8
+ var c = a(function({ variant: a, size: c, loading: l = !1, disabled: u = !1, fullWidth: d, iconOnly: f, pill: p, leftIcon: m, rightIcon: h, className: g, children: _, ...v }, y) {
9
+ let b = o(_) ? _.props : {}, x = {
10
+ ...v,
11
+ className: e({
12
+ variant: a,
13
+ size: c,
14
+ loading: l,
15
+ fullWidth: d,
16
+ iconOnly: f,
17
+ pill: p
18
+ }, g),
19
+ "aria-busy": l || void 0
20
+ };
21
+ return b.target === "_blank" && (x.rel = r("_blank", typeof b.rel == "string" ? b.rel : void 0)), (u || l) && (x["aria-disabled"] = !0, x.tabIndex = -1, x.onClick = t, x.onAuxClick = t, b.href !== void 0 && (x.href = void 0, x.role = "link")), /* @__PURE__ */ s(i, {
22
+ child: _,
23
+ slotProps: x,
24
+ slotRef: y,
25
+ content: /* @__PURE__ */ s(n, {
26
+ loading: l,
27
+ leftIcon: m,
28
+ rightIcon: h,
29
+ children: b.children
30
+ })
31
+ });
32
+ });
33
+ //#endregion
34
+ export { c as ButtonSlot };
35
+
36
+ //# sourceMappingURL=ButtonSlot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonSlot.js","names":[],"sources":["../../../src/components/Button/ButtonSlot.tsx"],"sourcesContent":["import { forwardRef, isValidElement } from \"react\";\nimport type { ForwardedRef, HTMLAttributes, ReactElement, ReactNode } from \"react\";\nimport { buttonClassName, preventActivation } from \"./button-class\";\nimport { ButtonContent } from \"./ButtonContent\";\nimport { resolveLinkRel } from \"./link-rel\";\nimport { Slot } from \"./slot\";\nimport type { SlotProps } from \"./slot\";\nimport type { ButtonBaseProps } from \"./types\";\n\n/** Props of {@link ButtonSlot}: the `Button` look, applied to the single child. */\nexport interface ButtonSlotProps\n extends ButtonBaseProps, Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** The one element that receives the classes, props and ref — e.g. a router `Link`. */\n children: ReactElement;\n}\n\n/**\n * Lends the `Button` look to its single child element instead of rendering one —\n * the `asChild`/Slot pattern. `<ButtonSlot><Link to=\"/x\">Go</Link></ButtonSlot>`\n * styles a react-router `Link`, so the route changes without a reload, and no\n * router is imported here.\n *\n * It is a component of its own rather than an `asChild` prop on `Button` because\n * of what it costs: the prop merge and ref composition are ~0.6 kB brotli, and a\n * prop is a runtime branch no bundler can drop, so every app using `Button` paid\n * for it. As a separate export it is tree-shaken away where unused.\n *\n * Merge rules: classes are joined (a function `className`, as `NavLink` takes,\n * stays a function); `ButtonSlot`'s props win over the child's, because they carry\n * the disabled semantics; handlers run `ButtonSlot`'s first and skip the child's\n * when the event was prevented; both refs receive the node. A child with\n * `target=\"_blank\"` gets `noopener noreferrer`.\n *\n * Disabled or loading: `aria-disabled=\"true\"`, `tabIndex={-1}`, click and\n * middle-click cancelled — a router `Link` then skips its navigation because the\n * event arrives prevented. A plain `<a href>` child also loses the `href` and gets\n * `role=\"link\"`; a `Link` computes its own `href`, which stays in the DOM.\n *\n * @example\n * <ButtonSlot variant=\"outline\">\n * <Link to=\"/planos\">Ver planos</Link>\n * </ButtonSlot>\n *\n * @throws {Error} When `children` is not a single React element.\n */\nexport const ButtonSlot = forwardRef<HTMLElement, ButtonSlotProps>(function ButtonSlot(\n {\n variant,\n size,\n loading = false,\n disabled = false,\n fullWidth,\n iconOnly,\n pill,\n leftIcon,\n rightIcon,\n className,\n children,\n ...rest\n }: ButtonSlotProps,\n ref: ForwardedRef<HTMLElement>,\n): ReactElement {\n const childProps = (isValidElement(children) ? children.props : {}) as {\n target?: unknown;\n rel?: unknown;\n href?: unknown;\n children?: ReactNode;\n };\n const slotProps: SlotProps = {\n ...rest,\n className: buttonClassName(\n { variant, size, loading, fullWidth, iconOnly, pill },\n className,\n ),\n \"aria-busy\": loading || undefined,\n };\n if (childProps.target === \"_blank\") {\n slotProps.rel = resolveLinkRel(\n \"_blank\",\n typeof childProps.rel === \"string\" ? childProps.rel : undefined,\n );\n }\n if (disabled || loading) {\n slotProps[\"aria-disabled\"] = true;\n slotProps.tabIndex = -1;\n slotProps.onClick = preventActivation;\n slotProps.onAuxClick = preventActivation;\n if (childProps.href !== undefined) {\n slotProps.href = undefined;\n slotProps.role = \"link\";\n }\n }\n return (\n <Slot\n child={children}\n slotProps={slotProps}\n slotRef={ref}\n content={\n <ButtonContent loading={loading} leftIcon={leftIcon} rightIcon={rightIcon}>\n {childProps.children}\n </ButtonContent>\n }\n />\n );\n});\n"],"mappings":";;;;;;;AA6CA,IAAa,IAAa,EAAyC,SAC/D,EACI,YACA,SACA,aAAU,IACV,cAAW,IACX,cACA,aACA,SACA,aACA,cACA,cACA,aACA,GAAG,KAEP,GACY;CACZ,IAAM,IAAc,EAAe,CAAQ,IAAI,EAAS,QAAQ,CAAC,GAM3D,IAAuB;EACzB,GAAG;EACH,WAAW,EACP;GAAE;GAAS;GAAM;GAAS;GAAW;GAAU;EAAK,GACpD,CACJ;EACA,aAAa,KAAW,KAAA;CAC5B;CAiBA,OAhBI,EAAW,WAAW,aACtB,EAAU,MAAM,EACZ,UACA,OAAO,EAAW,OAAQ,WAAW,EAAW,MAAM,KAAA,CAC1D,KAEA,KAAY,OACZ,EAAU,mBAAmB,IAC7B,EAAU,WAAW,IACrB,EAAU,UAAU,GACpB,EAAU,aAAa,GACnB,EAAW,SAAS,KAAA,MACpB,EAAU,OAAO,KAAA,GACjB,EAAU,OAAO,UAIrB,kBAAC,GAAD;EACI,OAAO;EACI;EACX,SAAS;EACT,SACI,kBAAC,GAAD;GAAwB;GAAmB;GAAqB;GAC3D,UAAA,EAAW;EACD,CAAA;CAEtB,CAAA;AAET,CAAC"}
@@ -0,0 +1,2 @@
1
+ const e=require("../../utils/cn.cjs"),t=require("./Button.module.cjs");function n({variant:n=`primary`,size:r=`md`,loading:i=!1,fullWidth:a=!1,iconOnly:o=!1,pill:s=!1},c){return e.cn(t.default.button,t.default[n],t.default[r],o&&t.default.iconOnly,s&&t.default.pill,i&&t.default.loading,a&&t.default.fullWidth,c)}function r(e){e.preventDefault()}exports.buttonClassName=n,exports.preventActivation=r;
2
+ //# sourceMappingURL=button-class.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-class.cjs","names":[],"sources":["../../../src/components/Button/button-class.ts"],"sourcesContent":["import type { MouseEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Button.module.css\";\nimport type { ButtonBaseProps } from \"./types\";\n\n/**\n * The class list of a button-looking element, shared by `Button` and `ButtonSlot`\n * so the two can never drift apart.\n *\n * @param props - The look props.\n * @param className - The consumer's own class, appended last.\n * @returns The joined class string.\n */\nexport function buttonClassName(\n {\n variant = \"primary\",\n size = \"md\",\n loading = false,\n fullWidth = false,\n iconOnly = false,\n pill = false,\n }: ButtonBaseProps,\n className: string | undefined,\n): string {\n return cn(\n styles.button,\n styles[variant],\n styles[size],\n iconOnly && styles.iconOnly,\n pill && styles.pill,\n loading && styles.loading,\n fullWidth && styles.fullWidth,\n className,\n );\n}\n\n/**\n * Click handler of a disabled link: cancels the navigation.\n *\n * @param event - The click or middle-click.\n */\nexport function preventActivation(event: MouseEvent<HTMLElement>): void {\n event.preventDefault();\n}\n"],"mappings":"uEAaA,SAAgB,EACZ,CACI,UAAU,UACV,OAAO,KACP,UAAU,GACV,YAAY,GACZ,WAAW,GACX,OAAO,IAEX,EACM,CACN,OAAO,EAAA,GACH,EAAA,QAAO,OACP,EAAA,QAAO,GACP,EAAA,QAAO,GACP,GAAY,EAAA,QAAO,SACnB,GAAQ,EAAA,QAAO,KACf,GAAW,EAAA,QAAO,QAClB,GAAa,EAAA,QAAO,UACpB,CACJ,CACJ,CAOA,SAAgB,EAAkB,EAAsC,CACpE,EAAM,eAAe,CACzB"}
@@ -0,0 +1,13 @@
1
+ import { cn as e } from "../../utils/cn.js";
2
+ import t from "./Button.module.js";
3
+ //#region src/components/Button/button-class.ts
4
+ function n({ variant: n = "primary", size: r = "md", loading: i = !1, fullWidth: a = !1, iconOnly: o = !1, pill: s = !1 }, c) {
5
+ return e(t.button, t[n], t[r], o && t.iconOnly, s && t.pill, i && t.loading, a && t.fullWidth, c);
6
+ }
7
+ function r(e) {
8
+ e.preventDefault();
9
+ }
10
+ //#endregion
11
+ export { n as buttonClassName, r as preventActivation };
12
+
13
+ //# sourceMappingURL=button-class.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-class.js","names":[],"sources":["../../../src/components/Button/button-class.ts"],"sourcesContent":["import type { MouseEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Button.module.css\";\nimport type { ButtonBaseProps } from \"./types\";\n\n/**\n * The class list of a button-looking element, shared by `Button` and `ButtonSlot`\n * so the two can never drift apart.\n *\n * @param props - The look props.\n * @param className - The consumer's own class, appended last.\n * @returns The joined class string.\n */\nexport function buttonClassName(\n {\n variant = \"primary\",\n size = \"md\",\n loading = false,\n fullWidth = false,\n iconOnly = false,\n pill = false,\n }: ButtonBaseProps,\n className: string | undefined,\n): string {\n return cn(\n styles.button,\n styles[variant],\n styles[size],\n iconOnly && styles.iconOnly,\n pill && styles.pill,\n loading && styles.loading,\n fullWidth && styles.fullWidth,\n className,\n );\n}\n\n/**\n * Click handler of a disabled link: cancels the navigation.\n *\n * @param event - The click or middle-click.\n */\nexport function preventActivation(event: MouseEvent<HTMLElement>): void {\n event.preventDefault();\n}\n"],"mappings":";;;AAaA,SAAgB,EACZ,EACI,aAAU,WACV,UAAO,MACP,aAAU,IACV,eAAY,IACZ,cAAW,IACX,UAAO,MAEX,GACM;CACN,OAAO,EACH,EAAO,QACP,EAAO,IACP,EAAO,IACP,KAAY,EAAO,UACnB,KAAQ,EAAO,MACf,KAAW,EAAO,SAClB,KAAa,EAAO,WACpB,CACJ;AACJ;AAOA,SAAgB,EAAkB,GAAsC;CACpE,EAAM,eAAe;AACzB"}
@@ -0,0 +1,2 @@
1
+ var e=[`noopener`,`noreferrer`];function t(t,n){if(t!==`_blank`)return n;let r=` ${(n??``).toLowerCase().replace(/\s+/g,` `)} `;return[n?.trim(),...e.filter(e=>!r.includes(` ${e} `))].filter(Boolean).join(` `)}exports.resolveLinkRel=t;
2
+ //# sourceMappingURL=link-rel.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-rel.cjs","names":[],"sources":["../../../src/components/Button/link-rel.ts"],"sourcesContent":["/** Link relationships that `target=\"_blank\"` must carry. */\nconst BLANK_TARGET_REL: readonly string[] = [\"noopener\", \"noreferrer\"];\n\n/**\n * The `rel` to render for a link, adding `noopener noreferrer` to a new-tab link.\n *\n * A page opened with `target=\"_blank\"` and no `noopener` gets `window.opener` and\n * can redirect the tab that opened it. It is a mechanical rule with one right\n * answer, so it lives here instead of in a warning on the docs page. The tokens\n * the consumer passed are kept, and none is added twice (case-insensitively).\n *\n * @param target - The link's `target`.\n * @param rel - The `rel` the consumer passed, if any.\n * @returns The `rel` to render, or `undefined` when there is none.\n */\nexport function resolveLinkRel(\n target: string | undefined,\n rel: string | undefined,\n): string | undefined {\n if (target !== \"_blank\") return rel;\n const present = ` ${(rel ?? \"\").toLowerCase().replace(/\\s+/g, \" \")} `;\n return [rel?.trim(), ...BLANK_TARGET_REL.filter((token) => !present.includes(` ${token} `))]\n .filter(Boolean)\n .join(\" \");\n}\n"],"mappings":"AACA,IAAM,EAAsC,CAAC,WAAY,YAAY,EAcrE,SAAgB,EACZ,EACA,EACkB,CAClB,GAAI,IAAW,SAAU,OAAO,EAChC,IAAM,EAAU,KAAK,GAAO,GAAA,CAAI,YAAY,CAAC,CAAC,QAAQ,OAAQ,GAAG,EAAE,GACnE,MAAO,CAAC,GAAK,KAAK,EAAG,GAAG,EAAiB,OAAQ,GAAU,CAAC,EAAQ,SAAS,IAAI,EAAM,EAAE,CAAC,CAAC,CAAC,CACvF,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,CACjB"}
@@ -0,0 +1,11 @@
1
+ //#region src/components/Button/link-rel.ts
2
+ var e = ["noopener", "noreferrer"];
3
+ function t(t, n) {
4
+ if (t !== "_blank") return n;
5
+ let r = ` ${(n ?? "").toLowerCase().replace(/\s+/g, " ")} `;
6
+ return [n?.trim(), ...e.filter((e) => !r.includes(` ${e} `))].filter(Boolean).join(" ");
7
+ }
8
+ //#endregion
9
+ export { t as resolveLinkRel };
10
+
11
+ //# sourceMappingURL=link-rel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-rel.js","names":[],"sources":["../../../src/components/Button/link-rel.ts"],"sourcesContent":["/** Link relationships that `target=\"_blank\"` must carry. */\nconst BLANK_TARGET_REL: readonly string[] = [\"noopener\", \"noreferrer\"];\n\n/**\n * The `rel` to render for a link, adding `noopener noreferrer` to a new-tab link.\n *\n * A page opened with `target=\"_blank\"` and no `noopener` gets `window.opener` and\n * can redirect the tab that opened it. It is a mechanical rule with one right\n * answer, so it lives here instead of in a warning on the docs page. The tokens\n * the consumer passed are kept, and none is added twice (case-insensitively).\n *\n * @param target - The link's `target`.\n * @param rel - The `rel` the consumer passed, if any.\n * @returns The `rel` to render, or `undefined` when there is none.\n */\nexport function resolveLinkRel(\n target: string | undefined,\n rel: string | undefined,\n): string | undefined {\n if (target !== \"_blank\") return rel;\n const present = ` ${(rel ?? \"\").toLowerCase().replace(/\\s+/g, \" \")} `;\n return [rel?.trim(), ...BLANK_TARGET_REL.filter((token) => !present.includes(` ${token} `))]\n .filter(Boolean)\n .join(\" \");\n}\n"],"mappings":";AACA,IAAM,IAAsC,CAAC,YAAY,YAAY;AAcrE,SAAgB,EACZ,GACA,GACkB;CAClB,IAAI,MAAW,UAAU,OAAO;CAChC,IAAM,IAAU,KAAK,KAAO,GAAA,CAAI,YAAY,CAAC,CAAC,QAAQ,QAAQ,GAAG,EAAE;CACnE,OAAO,CAAC,GAAK,KAAK,GAAG,GAAG,EAAiB,QAAQ,MAAU,CAAC,EAAQ,SAAS,IAAI,EAAM,EAAE,CAAC,CAAC,CAAC,CACvF,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;AACjB"}
@@ -0,0 +1,2 @@
1
+ const e=require("../../utils/cn.cjs");let t=require("react");var n=Number.parseInt(t.version,10);function r(...e){return t=>{for(let n of e)typeof n==`function`?n(t):n&&(n.current=t)}}function i(e){return n>=19?e.props.ref:e.ref}function a(t,n){return typeof n==`function`?(...r)=>e.cn(t,n(...r)):e.cn(t,n)}function o(e,t){let n={...t,...e};for(let r of Object.keys(e)){let i=e[r],a=t[r];/^on[A-Z]/.test(r)&&typeof i==`function`&&typeof a==`function`&&(n[r]=e=>{i(e),e.defaultPrevented||a(e)})}return n.className=a(e.className,t.className),e.style&&(n.style={...t.style,...e.style}),n}function s({child:e,slotProps:n,slotRef:a,content:s}){let c=(0,t.isValidElement)(e)?i(e):void 0,l=(0,t.useMemo)(()=>r(c,a),[c,a]);if(!(0,t.isValidElement)(e))throw Error(`ButtonSlot expects exactly one React element as its child.`);let u=o(n,e.props);return u.ref=l,(0,t.cloneElement)(e,u,s)}exports.Slot=s,exports.composeRefs=r,exports.getElementRef=i,exports.mergeSlotProps=o;
2
+ //# sourceMappingURL=slot.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slot.cjs","names":[],"sources":["../../../src/components/Button/slot.ts"],"sourcesContent":["import { cloneElement, isValidElement, useMemo, version } from \"react\";\nimport type { CSSProperties, ReactElement, ReactNode, Ref, RefCallback, RefObject } from \"react\";\nimport { cn } from \"@/utils/cn\";\n\n/** Props a slot hands to the element it renders through. */\nexport type SlotProps = Record<string, unknown> & {\n className?: string;\n style?: CSSProperties;\n};\n\n/**\n * Major version of the React running the page.\n *\n * React 19 moved an element's `ref` into `element.props.ref` and turned the old\n * `element.ref` into a getter that logs a deprecation warning; React 18 only has\n * `element.ref`. Reading the version once picks the right field without touching\n * the deprecated one.\n */\nconst REACT_MAJOR: number = Number.parseInt(version, 10);\n\n/**\n * Combine several refs into one callback ref, so a single DOM node reaches all of\n * them — the ref the consumer put on the child and the one forwarded to `Button`.\n *\n * @param refs - Callback refs, ref objects, `null` or `undefined`, in any mix.\n * @returns A callback ref that assigns the node to every ref it was given.\n */\nexport function composeRefs<T>(...refs: Array<Ref<T> | undefined>): RefCallback<T> {\n return (node: T | null): void => {\n for (const ref of refs) {\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as RefObject<T | null>).current = node;\n }\n };\n}\n\n/**\n * Read the `ref` a React element was created with, on React 18 and 19 alike.\n *\n * @param element - The element whose ref is wanted.\n * @returns The element's ref, or `undefined` when it has none.\n */\nexport function getElementRef(element: ReactElement): Ref<unknown> | undefined {\n if (REACT_MAJOR >= 19) return (element.props as { ref?: Ref<unknown> }).ref;\n return (element as unknown as { ref?: Ref<unknown> }).ref;\n}\n\n/**\n * Join the slot's class with the child's, which may be a function of state.\n *\n * react-router's `NavLink` takes `className` as `({ isActive }) => string`.\n * Stringifying that would drop the active class, so a function stays a function\n * and gets the slot's class prepended to whatever it returns.\n *\n * @param slotClass - The slot's class string.\n * @param childClass - The child's `className`: a string, a function or absent.\n * @returns A string, or a function of the same shape as the child's.\n */\nfunction mergeClassName(slotClass: string | undefined, childClass: unknown): unknown {\n if (typeof childClass === \"function\") {\n return (...args: unknown[]): string =>\n cn(slotClass, childClass(...args) as string | undefined);\n }\n return cn(slotClass, childClass as string | undefined);\n}\n\n/**\n * Merge the slot's props over the child's own props.\n *\n * The rules, and why each one is that way round:\n *\n * - **Plain props: the slot wins.** The slot is `ButtonSlot`, and the props it adds\n * carry its invariants — `aria-disabled`, `tabIndex={-1}` and the click blocker\n * of a disabled link. A child prop overriding them would make a disabled link\n * navigate, which is the bug the props exist to prevent.\n * - **`className` is joined**, slot first, so the child keeps its own classes.\n * A function `className` (react-router's `NavLink`) stays a function.\n * - **`style` is merged** when the slot sets one, slot keys over child keys, for\n * the same reason as the plain props. Without a slot `style` the child's stays\n * untouched, function or not.\n * - **Event handlers (`on[A-Z]…`) both run**: the slot's first, then the child's,\n * unless the slot's handler called `preventDefault()`. That is what lets a\n * disabled `ButtonSlot` stop a react-router `Link`: the `Link` runs the `onClick` it\n * was given and then skips its own navigation when the event is already\n * prevented.\n *\n * @param slotProps - Props the slot applies.\n * @param childProps - Props the child element was created with.\n * @returns The merged props for `cloneElement`.\n */\nexport function mergeSlotProps(\n slotProps: SlotProps,\n childProps: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...childProps, ...slotProps };\n\n for (const key of Object.keys(slotProps)) {\n const slotValue = slotProps[key];\n const childValue = childProps[key];\n if (\n /^on[A-Z]/.test(key) &&\n typeof slotValue === \"function\" &&\n typeof childValue === \"function\"\n ) {\n merged[key] = (event: { defaultPrevented?: boolean }): void => {\n slotValue(event);\n if (!event.defaultPrevented) childValue(event);\n };\n }\n }\n\n merged.className = mergeClassName(slotProps.className, childProps.className);\n if (slotProps.style) {\n merged.style = { ...(childProps.style as CSSProperties | undefined), ...slotProps.style };\n }\n return merged;\n}\n\n/** Props of {@link Slot}. */\nexport interface SlotComponentProps {\n /** The single element the consumer passed as `children`. */\n child: ReactNode;\n /** Props to merge over the child's own (see {@link mergeSlotProps}). */\n slotProps: SlotProps;\n /** Ref forwarded to the slot, composed with the child's own ref. */\n slotRef?: Ref<HTMLElement>;\n /** What to render inside the child, in place of its children. */\n content: ReactNode;\n}\n\n/**\n * Render `child` with the slot's props, ref and content — the `asChild` pattern behind `ButtonSlot`.\n *\n * Kept local to `Button` instead of taking `@radix-ui/react-slot`: the whole\n * mechanism is a prop merge and a ref composition, and a dependency for that\n * would put its version bounds on every consumer of the SDK.\n *\n * The composed ref is memoised on the two refs, so a re-render with the same refs\n * does not detach and re-attach them.\n *\n * @param props - See {@link SlotComponentProps}.\n * @returns The cloned element.\n * @throws {Error} When `child` is not a single React element.\n */\nexport function Slot({ child, slotProps, slotRef, content }: SlotComponentProps): ReactElement {\n const childRef = isValidElement(child)\n ? (getElementRef(child) as Ref<HTMLElement> | undefined)\n : undefined;\n const ref = useMemo(() => composeRefs(childRef, slotRef), [childRef, slotRef]);\n if (!isValidElement(child)) {\n throw new Error(\"ButtonSlot expects exactly one React element as its child.\");\n }\n const merged = mergeSlotProps(slotProps, child.props as Record<string, unknown>);\n merged.ref = ref;\n return cloneElement(child, merged, content);\n}\n"],"mappings":"6DAkBA,IAAM,EAAsB,OAAO,SAAS,EAAA,QAAS,EAAE,EASvD,SAAgB,EAAe,GAAG,EAAiD,CAC/E,MAAQ,IAAyB,CAC7B,IAAK,IAAM,KAAO,EACV,OAAO,GAAQ,WAAY,EAAI,CAAI,EAC9B,IAAK,EAA6B,QAAU,EAE7D,CACJ,CAQA,SAAgB,EAAc,EAAiD,CAE3E,OADI,GAAe,GAAY,EAAQ,MAAiC,IAChE,EAA8C,GAC1D,CAaA,SAAS,EAAe,EAA+B,EAA8B,CAKjF,OAJI,OAAO,GAAe,YACd,GAAG,IACP,EAAA,GAAG,EAAW,EAAW,GAAG,CAAI,CAAuB,EAExD,EAAA,GAAG,EAAW,CAAgC,CACzD,CA0BA,SAAgB,EACZ,EACA,EACuB,CACvB,IAAM,EAAkC,CAAE,GAAG,EAAY,GAAG,CAAU,EAEtE,IAAK,IAAM,KAAO,OAAO,KAAK,CAAS,EAAG,CACtC,IAAM,EAAY,EAAU,GACtB,EAAa,EAAW,GAE1B,WAAW,KAAK,CAAG,GACnB,OAAO,GAAc,YACrB,OAAO,GAAe,aAEtB,EAAO,GAAQ,GAAgD,CAC3D,EAAU,CAAK,EACV,EAAM,kBAAkB,EAAW,CAAK,CACjD,EAER,CAMA,MAJA,GAAO,UAAY,EAAe,EAAU,UAAW,EAAW,SAAS,EACvE,EAAU,QACV,EAAO,MAAQ,CAAE,GAAI,EAAW,MAAqC,GAAG,EAAU,KAAM,GAErF,CACX,CA4BA,SAAgB,EAAK,CAAE,QAAO,YAAW,UAAS,WAA6C,CAC3F,IAAM,GAAA,EAAW,EAAA,eAAA,CAAe,CAAK,EAC9B,EAAc,CAAK,EACpB,IAAA,GACA,GAAA,EAAM,EAAA,QAAA,KAAc,EAAY,EAAU,CAAO,EAAG,CAAC,EAAU,CAAO,CAAC,EAC7E,GAAI,EAAA,EAAC,EAAA,eAAA,CAAe,CAAK,EACrB,MAAU,MAAM,4DAA4D,EAEhF,IAAM,EAAS,EAAe,EAAW,EAAM,KAAgC,EAE/E,MADA,GAAO,IAAM,GACb,EAAO,EAAA,aAAA,CAAa,EAAO,EAAQ,CAAO,CAC9C"}