@signalflare-ai/ui 1.2.0 → 1.4.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 (318) hide show
  1. package/CHANGELOG.md +154 -1
  2. package/ai/component-registry.json +208 -550
  3. package/ai/component-registry.md +3042 -3115
  4. package/ai/schemas.ts +504 -96
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.d.ts.map +1 -1
  7. package/dist/{ai-actions-BdUZI3Gk.js → ai-actions-CBfz5XEf.js} +4 -4
  8. package/dist/{ai-actions-BdUZI3Gk.js.map → ai-actions-CBfz5XEf.js.map} +1 -1
  9. package/dist/{ai-agent-card-BR2NIYhi.js → ai-agent-card-CByAUe0q.js} +3 -3
  10. package/dist/ai-agent-card-CByAUe0q.js.map +1 -0
  11. package/dist/{ai-approval-Ba7mrKba.js → ai-approval-Ci8N70a7.js} +4 -3
  12. package/dist/{ai-approval-Ba7mrKba.js.map → ai-approval-Ci8N70a7.js.map} +1 -1
  13. package/dist/{ai-code-block-CZtoL73R.js → ai-code-block-P9TJHvaC.js} +37 -39
  14. package/dist/ai-code-block-P9TJHvaC.js.map +1 -0
  15. package/dist/{ai-conversation-Cc7WlaBg.js → ai-conversation-Qslfdi1t.js} +28 -42
  16. package/dist/ai-conversation-Qslfdi1t.js.map +1 -0
  17. package/dist/{ai-info-banner-C7EWPBj7.js → ai-info-banner-B_9vtGK3.js} +3 -3
  18. package/dist/{ai-info-banner-C7EWPBj7.js.map → ai-info-banner-B_9vtGK3.js.map} +1 -1
  19. package/dist/{ai-message-Bp7L68U_.js → ai-message-Ci3gwM7G.js} +6 -6
  20. package/dist/{ai-message-Bp7L68U_.js.map → ai-message-Ci3gwM7G.js.map} +1 -1
  21. package/dist/{ai-mission-header-TiCJfTNt.js → ai-mission-header-CaBc19-t.js} +2 -2
  22. package/dist/{ai-mission-header-TiCJfTNt.js.map → ai-mission-header-CaBc19-t.js.map} +1 -1
  23. package/dist/{ai-part-group-DNb9I446.js → ai-part-group-Dx1Mr92B.js} +5 -4
  24. package/dist/ai-part-group-Dx1Mr92B.js.map +1 -0
  25. package/dist/{ai-prompt-input-BVvov_KF.js → ai-prompt-input-Bm4XoSj2.js} +19 -17
  26. package/dist/ai-prompt-input-Bm4XoSj2.js.map +1 -0
  27. package/dist/{ai-question-GPPMk7YM.js → ai-question-OyJovxGe.js} +4 -3
  28. package/dist/{ai-question-GPPMk7YM.js.map → ai-question-OyJovxGe.js.map} +1 -1
  29. package/dist/{ai-reasoning-_feFjk56.js → ai-reasoning-BLfBXx3F.js} +9 -5
  30. package/dist/ai-reasoning-BLfBXx3F.js.map +1 -0
  31. package/dist/{ai-response-CvjV3WhV.js → ai-response-hbVCZJmo.js} +2 -2
  32. package/dist/{ai-response-CvjV3WhV.js.map → ai-response-hbVCZJmo.js.map} +1 -1
  33. package/dist/{ai-shimmer-j6lKIrjj.js → ai-shimmer-BamNMNK3.js} +2 -2
  34. package/dist/{ai-shimmer-j6lKIrjj.js.map → ai-shimmer-BamNMNK3.js.map} +1 -1
  35. package/dist/{ai-status-badge-CSU_QOdz.js → ai-status-badge-BZLczdkI.js} +2 -2
  36. package/dist/{ai-status-badge-CSU_QOdz.js.map → ai-status-badge-BZLczdkI.js.map} +1 -1
  37. package/dist/{ai-streaming-text-IWW1BhvZ.js → ai-streaming-text-DgYu64UH.js} +1 -1
  38. package/dist/{ai-streaming-text-IWW1BhvZ.js.map → ai-streaming-text-DgYu64UH.js.map} +1 -1
  39. package/dist/{ai-subagent-JA4iIMW3.js → ai-subagent-p97AI1h9.js} +3 -3
  40. package/dist/{ai-subagent-JA4iIMW3.js.map → ai-subagent-p97AI1h9.js.map} +1 -1
  41. package/dist/{ai-suggestion-BdO6MBuH.js → ai-suggestion-Bj6vF7CT.js} +3 -3
  42. package/dist/{ai-suggestion-BdO6MBuH.js.map → ai-suggestion-Bj6vF7CT.js.map} +1 -1
  43. package/dist/{ai-task-list-DYw4R1FA.js → ai-task-list-C_UQYpk9.js} +6 -4
  44. package/dist/{ai-task-list-DYw4R1FA.js.map → ai-task-list-C_UQYpk9.js.map} +1 -1
  45. package/dist/{ai-timeline-C42tOUT8.js → ai-timeline-CePL1LOU.js} +3 -3
  46. package/dist/ai-timeline-CePL1LOU.js.map +1 -0
  47. package/dist/{ai-tool-03jOTwUI.js → ai-tool-CfRcwmHT.js} +17 -11
  48. package/dist/ai-tool-CfRcwmHT.js.map +1 -0
  49. package/dist/{ai-usage-bar-BRf5LC_b.js → ai-usage-bar-45pVRCGA.js} +2 -2
  50. package/dist/{ai-usage-bar-BRf5LC_b.js.map → ai-usage-bar-45pVRCGA.js.map} +1 -1
  51. package/dist/{badge-BheXjMc8.js → badge-Beb-6uut.js} +5 -5
  52. package/dist/{badge-BheXjMc8.js.map → badge-Beb-6uut.js.map} +1 -1
  53. package/dist/{banner-CcsjunJg.js → banner-CCEksxPg.js} +3 -3
  54. package/dist/{banner-CcsjunJg.js.map → banner-CCEksxPg.js.map} +1 -1
  55. package/dist/{breadcrumbs-CouSyy3H.js → breadcrumbs-HiTmgaZ4.js} +5 -5
  56. package/dist/{breadcrumbs-CouSyy3H.js.map → breadcrumbs-HiTmgaZ4.js.map} +1 -1
  57. package/dist/{button-CO6-qPax.js → button-BHOgXJRU.js} +4 -4
  58. package/dist/{button-CO6-qPax.js.map → button-BHOgXJRU.js.map} +1 -1
  59. package/dist/catalog.js +1 -1
  60. package/dist/catalog.js.map +1 -1
  61. package/dist/{chart-Dg0qUeSc.js → chart-B9FfZdKs.js} +7 -7
  62. package/dist/chart-B9FfZdKs.js.map +1 -0
  63. package/dist/{checkbox-D7p4QKsC.js → checkbox-Cy_OCyay.js} +3 -3
  64. package/dist/{checkbox-D7p4QKsC.js.map → checkbox-Cy_OCyay.js.map} +1 -1
  65. package/dist/{clipboard-text-kLaMogs3.js → clipboard-text-CKSvNp9L.js} +6 -5
  66. package/dist/clipboard-text-CKSvNp9L.js.map +1 -0
  67. package/dist/{cn-YROP2_ox.js → cn-CmAOpn49.js} +2 -2
  68. package/dist/{cn-YROP2_ox.js.map → cn-CmAOpn49.js.map} +1 -1
  69. package/dist/{code-BN8InC0G.js → code-JsQz-0G_.js} +4 -4
  70. package/dist/{code-BN8InC0G.js.map → code-JsQz-0G_.js.map} +1 -1
  71. package/dist/{collapsible-D_ueZ0jz.js → collapsible-1kOZ-89L.js} +2 -2
  72. package/dist/{collapsible-D_ueZ0jz.js.map → collapsible-1kOZ-89L.js.map} +1 -1
  73. package/dist/{combobox-B7TOK0U2.js → combobox-CQwDmqgA.js} +4 -4
  74. package/dist/{combobox-B7TOK0U2.js.map → combobox-CQwDmqgA.js.map} +1 -1
  75. package/dist/command-line/cli.js +3 -3
  76. package/dist/{command-palette-CuNUyJca.js → command-palette-Bkuv3e6o.js} +20 -5
  77. package/dist/command-palette-Bkuv3e6o.js.map +1 -0
  78. package/dist/components/ai-actions.js +1 -1
  79. package/dist/components/ai-agent-card.js +1 -1
  80. package/dist/components/ai-approval.js +1 -1
  81. package/dist/components/ai-code-block.js +1 -1
  82. package/dist/components/ai-conversation.js +1 -1
  83. package/dist/components/ai-info-banner.js +1 -1
  84. package/dist/components/ai-message.js +1 -1
  85. package/dist/components/ai-mission-header.js +1 -1
  86. package/dist/components/ai-part-group.js +1 -1
  87. package/dist/components/ai-prompt-input.js +1 -1
  88. package/dist/components/ai-question.js +1 -1
  89. package/dist/components/ai-reasoning.js +1 -1
  90. package/dist/components/ai-response.js +1 -1
  91. package/dist/components/ai-shimmer.js +1 -1
  92. package/dist/components/ai-status-badge.js +1 -1
  93. package/dist/components/ai-streaming-text.js +1 -1
  94. package/dist/components/ai-subagent.js +1 -1
  95. package/dist/components/ai-suggestion.js +1 -1
  96. package/dist/components/ai-task-list.js +1 -1
  97. package/dist/components/ai-timeline.js +1 -1
  98. package/dist/components/ai-tool.js +1 -1
  99. package/dist/components/ai-usage-bar.js +1 -1
  100. package/dist/components/badge.js +1 -1
  101. package/dist/components/banner.js +1 -1
  102. package/dist/components/breadcrumbs.js +1 -1
  103. package/dist/components/button.js +1 -1
  104. package/dist/components/chart.js +2 -2
  105. package/dist/components/checkbox.js +1 -1
  106. package/dist/components/clipboard-text.js +1 -1
  107. package/dist/components/code.js +1 -1
  108. package/dist/components/collapsible.js +1 -1
  109. package/dist/components/combobox.js +1 -1
  110. package/dist/components/command-palette.js +1 -1
  111. package/dist/components/data-grid.js +1 -1
  112. package/dist/components/date-picker.js +1 -1
  113. package/dist/components/date-range-picker.js +1 -1
  114. package/dist/components/dialog.js +1 -1
  115. package/dist/components/dropdown.js +1 -1
  116. package/dist/components/empty.js +1 -1
  117. package/dist/components/field.js +1 -1
  118. package/dist/components/filters.js +1 -1
  119. package/dist/components/flow.js +1 -1
  120. package/dist/components/grid.js +1 -1
  121. package/dist/components/input.js +2 -2
  122. package/dist/components/label.js +1 -1
  123. package/dist/components/layer-card.js +1 -1
  124. package/dist/components/link.js +3 -3
  125. package/dist/components/link.js.map +1 -1
  126. package/dist/components/loader.js +2 -2
  127. package/dist/components/menubar.js +1 -1
  128. package/dist/components/meter.js +1 -1
  129. package/dist/components/pagination.js +1 -1
  130. package/dist/components/popover.js +1 -1
  131. package/dist/components/radio.js +1 -1
  132. package/dist/components/select.js +1 -1
  133. package/dist/components/sensitive-input.js +1 -1
  134. package/dist/components/sidebar.js +1 -1
  135. package/dist/components/signalflare-ai-logo.js +1 -1
  136. package/dist/components/sparkline.js +1 -1
  137. package/dist/components/stat-card.js +1 -1
  138. package/dist/components/surface.js +1 -1
  139. package/dist/components/switch.js +1 -1
  140. package/dist/components/table.js +1 -1
  141. package/dist/components/tabs.js +1 -1
  142. package/dist/components/text-roll.js +1 -1
  143. package/dist/components/text.js +1 -1
  144. package/dist/components/theme-toggle.js +1 -1
  145. package/dist/components/toast.js +1 -1
  146. package/dist/components/tooltip.js +1 -1
  147. package/dist/components/use-agent-harness.js +1 -1
  148. package/dist/data-grid-DrguJq_H.js +395 -0
  149. package/dist/data-grid-DrguJq_H.js.map +1 -0
  150. package/dist/{date-picker--ox89RBy.js → date-picker-O34AqG3f.js} +2 -2
  151. package/dist/{date-picker--ox89RBy.js.map → date-picker-O34AqG3f.js.map} +1 -1
  152. package/dist/{date-range-picker-DVa7QBqE.js → date-range-picker-YKYvum_r.js} +29 -39
  153. package/dist/{date-range-picker-DVa7QBqE.js.map → date-range-picker-YKYvum_r.js.map} +1 -1
  154. package/dist/{dialog-Bv1oSFOd.js → dialog-DYqu4aDO.js} +3 -3
  155. package/dist/{dialog-Bv1oSFOd.js.map → dialog-DYqu4aDO.js.map} +1 -1
  156. package/dist/{dist-B6iWiWwp.js → dist-6AtBsaJE.js} +153 -47
  157. package/dist/dist-6AtBsaJE.js.map +1 -0
  158. package/dist/{dropdown-B_nrGXjV.js → dropdown-XzbnRLYR.js} +15 -5
  159. package/dist/dropdown-XzbnRLYR.js.map +1 -0
  160. package/dist/{echart-CdOUaT-r.js → echart-DGBIVAv1.js} +23 -57
  161. package/dist/{echart-CdOUaT-r.js.map → echart-DGBIVAv1.js.map} +1 -1
  162. package/dist/{empty-DZnN0zKX.js → empty-C1tAkawe.js} +6 -6
  163. package/dist/{empty-DZnN0zKX.js.map → empty-C1tAkawe.js.map} +1 -1
  164. package/dist/{field-B_yVof52.js → field-DBpFzzBS.js} +3 -3
  165. package/dist/{field-B_yVof52.js.map → field-DBpFzzBS.js.map} +1 -1
  166. package/dist/{filters-cpJCY21R.js → filters-SmEl93za.js} +10 -10
  167. package/dist/filters-SmEl93za.js.map +1 -0
  168. package/dist/{flow-B4v198ot.js → flow-BLzgbq1T.js} +6 -6
  169. package/dist/flow-BLzgbq1T.js.map +1 -0
  170. package/dist/genui.js +2 -2
  171. package/dist/genui.js.map +1 -1
  172. package/dist/{grid-CEd64Lnh.js → grid-CifjQL-5.js} +2 -2
  173. package/dist/{grid-CEd64Lnh.js.map → grid-CifjQL-5.js.map} +1 -1
  174. package/dist/{highlight-to-react-D0Yav4jk.js → highlight-to-react-DN9dUCS2.js} +9 -15
  175. package/dist/highlight-to-react-DN9dUCS2.js.map +1 -0
  176. package/dist/index.js +71 -71
  177. package/dist/index.js.map +1 -1
  178. package/dist/{input-ClB_E4Lb.js → input-COmx2M_R.js} +5 -5
  179. package/dist/{input-ClB_E4Lb.js.map → input-COmx2M_R.js.map} +1 -1
  180. package/dist/{input-B2bbijRh.js → input-GkfMQZC_.js} +3 -3
  181. package/dist/{input-B2bbijRh.js.map → input-GkfMQZC_.js.map} +1 -1
  182. package/dist/{label-DUv_urO1.js → label-CiGZ464N.js} +3 -3
  183. package/dist/{label-DUv_urO1.js.map → label-CiGZ464N.js.map} +1 -1
  184. package/dist/{layer-card-BK7eYfwn.js → layer-card-8l8GuLQr.js} +2 -2
  185. package/dist/{layer-card-BK7eYfwn.js.map → layer-card-8l8GuLQr.js.map} +1 -1
  186. package/dist/{layout-DJHMMap2.js → layout-CWBE0qwx.js} +258 -154
  187. package/dist/layout-CWBE0qwx.js.map +1 -0
  188. package/dist/{link-provider-BUZKXaNE.js → link-provider-BSn8YJon.js} +2 -2
  189. package/dist/link-provider-BSn8YJon.js.map +1 -0
  190. package/dist/{loader-DAcc-Uag.js → loader-BEMz8pJO.js} +1 -1
  191. package/dist/{loader-DAcc-Uag.js.map → loader-BEMz8pJO.js.map} +1 -1
  192. package/dist/{measured-text-BI3dTJmH.js → measured-text-CXkdw9Yr.js} +45 -30
  193. package/dist/measured-text-CXkdw9Yr.js.map +1 -0
  194. package/dist/{menubar-Cxf3xeAt.js → menubar-CoOr4ocj.js} +3 -3
  195. package/dist/{menubar-Cxf3xeAt.js.map → menubar-CoOr4ocj.js.map} +1 -1
  196. package/dist/{meter-BFFe9l5b.js → meter-Pf_VOl59.js} +2 -2
  197. package/dist/{meter-BFFe9l5b.js.map → meter-Pf_VOl59.js.map} +1 -1
  198. package/dist/{pagination-yS372Tr4.js → pagination-DSY279Ta.js} +2 -2
  199. package/dist/{pagination-yS372Tr4.js.map → pagination-DSY279Ta.js.map} +1 -1
  200. package/dist/{popover-SRoJaCZr.js → popover-BY-e9co1.js} +2 -2
  201. package/dist/{popover-SRoJaCZr.js.map → popover-BY-e9co1.js.map} +1 -1
  202. package/dist/{radio-BcwhwYNB.js → radio-DZwL13j0.js} +2 -2
  203. package/dist/{radio-BcwhwYNB.js.map → radio-DZwL13j0.js.map} +1 -1
  204. package/dist/{select-DMhdoHMa.js → select-BFifYqHA.js} +6 -6
  205. package/dist/{select-DMhdoHMa.js.map → select-BFifYqHA.js.map} +1 -1
  206. package/dist/{sensitive-input-CJUpIRal.js → sensitive-input-DHLZcM73.js} +4 -4
  207. package/dist/{sensitive-input-CJUpIRal.js.map → sensitive-input-DHLZcM73.js.map} +1 -1
  208. package/dist/{sidebar-D4zrlYpn.js → sidebar-odGsdvG4.js} +6 -7
  209. package/dist/sidebar-odGsdvG4.js.map +1 -0
  210. package/dist/{signalflare-ai-logo-Bipogceq.js → signalflare-ai-logo-CNaDT_w8.js} +2 -2
  211. package/dist/{signalflare-ai-logo-Bipogceq.js.map → signalflare-ai-logo-CNaDT_w8.js.map} +1 -1
  212. package/dist/{skeleton-line-CH1-h6e2.js → skeleton-line-CxxYVTO2.js} +2 -2
  213. package/dist/{skeleton-line-CH1-h6e2.js.map → skeleton-line-CxxYVTO2.js.map} +1 -1
  214. package/dist/{sparkline-DHmgj1d0.js → sparkline-BQ-4j2W2.js} +2 -2
  215. package/dist/{sparkline-DHmgj1d0.js.map → sparkline-BQ-4j2W2.js.map} +1 -1
  216. package/dist/src/blocks/agent-harness/agent-harness.tsx +11 -11
  217. package/dist/src/blocks/commander/commander.tsx +15 -15
  218. package/dist/src/blocks/map-block/map-block.d.ts.map +1 -1
  219. package/dist/src/blocks/map-block/map-block.tsx +11 -7
  220. package/dist/src/components/ai-approval/ai-approval.d.ts.map +1 -1
  221. package/dist/src/components/ai-code-block/ai-code-block.d.ts +14 -13
  222. package/dist/src/components/ai-code-block/ai-code-block.d.ts.map +1 -1
  223. package/dist/src/components/ai-conversation/ai-conversation.d.ts.map +1 -1
  224. package/dist/src/components/ai-part-group/ai-part-group.d.ts.map +1 -1
  225. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
  226. package/dist/src/components/ai-prompt-input/controller.d.ts.map +1 -1
  227. package/dist/src/components/ai-prompt-input/types.d.ts.map +1 -1
  228. package/dist/src/components/ai-question/ai-question.d.ts.map +1 -1
  229. package/dist/src/components/ai-reasoning/ai-reasoning.d.ts.map +1 -1
  230. package/dist/src/components/ai-response/ai-response.d.ts.map +1 -1
  231. package/dist/src/components/ai-subagent/ai-subagent.d.ts.map +1 -1
  232. package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -1
  233. package/dist/src/components/chart/echart.d.ts.map +1 -1
  234. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
  235. package/dist/src/components/data-grid/data-grid.d.ts +2 -1
  236. package/dist/src/components/data-grid/data-grid.d.ts.map +1 -1
  237. package/dist/src/components/data-grid/features.d.ts +20 -0
  238. package/dist/src/components/data-grid/features.d.ts.map +1 -0
  239. package/dist/src/components/data-grid/types.d.ts +38 -7
  240. package/dist/src/components/data-grid/types.d.ts.map +1 -1
  241. package/dist/src/components/filters/filters.d.ts.map +1 -1
  242. package/dist/src/components/flow/use-children.d.ts +1 -1
  243. package/dist/src/components/link/link.d.ts.map +1 -1
  244. package/dist/src/components/sidebar/sidebar.d.ts +1 -1
  245. package/dist/src/components/signalflare-ai-logo/signalflare-ai-logo.d.ts.map +1 -1
  246. package/dist/src/components/text/text.d.ts +2 -1
  247. package/dist/src/components/text/text.d.ts.map +1 -1
  248. package/dist/src/components/text-roll/text-roll.d.ts.map +1 -1
  249. package/dist/src/components/theme-toggle/theme-toggle.d.ts.map +1 -1
  250. package/dist/src/components/toast/toast.d.ts.map +1 -1
  251. package/dist/src/utils/highlight-to-react.d.ts.map +1 -1
  252. package/dist/src/utils/measured-text.d.ts.map +1 -1
  253. package/dist/src/utils/use-measured-text.d.ts.map +1 -1
  254. package/dist/{stat-card-Ew-ofzEm.js → stat-card-Bspk4XFr.js} +4 -4
  255. package/dist/stat-card-Bspk4XFr.js.map +1 -0
  256. package/dist/styles/sf-standalone.css +1 -1
  257. package/dist/styles/theme-fedramp.css +3 -12
  258. package/dist/styles/theme-minimal.css +26 -104
  259. package/dist/styles/theme-sf.css +37 -142
  260. package/dist/{surface-DGwRlC0o.js → surface-CWdSFVUx.js} +3 -3
  261. package/dist/{surface-DGwRlC0o.js.map → surface-CWdSFVUx.js.map} +1 -1
  262. package/dist/{switch-BxAMfHdt.js → switch-TA4cByCJ.js} +5 -5
  263. package/dist/switch-TA4cByCJ.js.map +1 -0
  264. package/dist/{table-BBeAtYVZ.js → table-BM8JBGBs.js} +3 -3
  265. package/dist/{table-BBeAtYVZ.js.map → table-BM8JBGBs.js.map} +1 -1
  266. package/dist/{tabs-CeHu7Scn.js → tabs-bnH2vGLv.js} +2 -2
  267. package/dist/{tabs-CeHu7Scn.js.map → tabs-bnH2vGLv.js.map} +1 -1
  268. package/dist/{text-Cqryz7rk.js → text-iQ0YUFNg.js} +4 -5
  269. package/dist/{text-Cqryz7rk.js.map → text-iQ0YUFNg.js.map} +1 -1
  270. package/dist/{text-roll-Ch52hcQj.js → text-roll-C3U2jd2u.js} +5 -2
  271. package/dist/text-roll-C3U2jd2u.js.map +1 -0
  272. package/dist/{theme-toggle-LDfIKEqx.js → theme-toggle-BTVxD-fD.js} +10 -9
  273. package/dist/theme-toggle-BTVxD-fD.js.map +1 -0
  274. package/dist/{toast-CaFQNYng.js → toast-CgZVaAkw.js} +3 -3
  275. package/dist/{toast-CaFQNYng.js.map → toast-CgZVaAkw.js.map} +1 -1
  276. package/dist/{tooltip-g9lFsvcT.js → tooltip-uobk6Oh-.js} +3 -3
  277. package/dist/{tooltip-g9lFsvcT.js.map → tooltip-uobk6Oh-.js.map} +1 -1
  278. package/dist/{use-agent-harness-BTcNJdw4.js → use-agent-harness-Dl8w6X5O.js} +3 -3
  279. package/dist/{use-agent-harness-BTcNJdw4.js.map → use-agent-harness-Dl8w6X5O.js.map} +1 -1
  280. package/dist/utils.js +3 -3
  281. package/package.json +27 -25
  282. package/scripts/component-registry/discovery.ts +11 -10
  283. package/scripts/component-registry/example-cleanup.ts +8 -8
  284. package/scripts/component-registry/index.ts +6 -6
  285. package/scripts/component-registry/schema-generator.ts +1 -1
  286. package/scripts/component-registry/sub-components.ts +35 -23
  287. package/scripts/component-registry/utils.ts +11 -11
  288. package/scripts/component-registry/variant-parser.ts +17 -15
  289. package/scripts/convert-demos-to-stories.ts +5 -5
  290. package/scripts/theme-generator/config.ts +1 -5
  291. package/scripts/theme-generator/generate-css.ts +1 -1
  292. package/scripts/theme-generator/migrate.ts +3 -3
  293. package/dist/ai-agent-card-BR2NIYhi.js.map +0 -1
  294. package/dist/ai-code-block-CZtoL73R.js.map +0 -1
  295. package/dist/ai-conversation-Cc7WlaBg.js.map +0 -1
  296. package/dist/ai-part-group-DNb9I446.js.map +0 -1
  297. package/dist/ai-prompt-input-BVvov_KF.js.map +0 -1
  298. package/dist/ai-reasoning-_feFjk56.js.map +0 -1
  299. package/dist/ai-timeline-C42tOUT8.js.map +0 -1
  300. package/dist/ai-tool-03jOTwUI.js.map +0 -1
  301. package/dist/chart-Dg0qUeSc.js.map +0 -1
  302. package/dist/clipboard-text-kLaMogs3.js.map +0 -1
  303. package/dist/command-palette-CuNUyJca.js.map +0 -1
  304. package/dist/data-grid-DGHmU0w3.js +0 -305
  305. package/dist/data-grid-DGHmU0w3.js.map +0 -1
  306. package/dist/dist-B6iWiWwp.js.map +0 -1
  307. package/dist/dropdown-B_nrGXjV.js.map +0 -1
  308. package/dist/filters-cpJCY21R.js.map +0 -1
  309. package/dist/flow-B4v198ot.js.map +0 -1
  310. package/dist/highlight-to-react-D0Yav4jk.js.map +0 -1
  311. package/dist/layout-DJHMMap2.js.map +0 -1
  312. package/dist/link-provider-BUZKXaNE.js.map +0 -1
  313. package/dist/measured-text-BI3dTJmH.js.map +0 -1
  314. package/dist/sidebar-D4zrlYpn.js.map +0 -1
  315. package/dist/stat-card-Ew-ofzEm.js.map +0 -1
  316. package/dist/switch-BxAMfHdt.js.map +0 -1
  317. package/dist/text-roll-Ch52hcQj.js.map +0 -1
  318. package/dist/theme-toggle-LDfIKEqx.js.map +0 -1
@@ -1,10 +1,12 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { a as prepare, i as measureNaturalWidth, o as prepareWithSegments, r as measureLineStats, t as layout } from "./layout-DJHMMap2.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { a as prepare, i as measureNaturalWidth, o as prepareWithSegments, r as measureLineStats, t as layout } from "./layout-CWBE0qwx.js";
4
4
  import { forwardRef, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region src/utils/use-measured-text.ts
7
7
  var preparationCache = /* @__PURE__ */ new Map();
8
+ /** Dev-only: ensures the `system-ui` first-family warning fires at most once. */
9
+ var hasWarnedSystemUi = false;
8
10
  var fontsReadyPromise = null;
9
11
  function getFontsReady() {
10
12
  if (fontsReadyPromise) return fontsReadyPromise;
@@ -62,32 +64,38 @@ function useMeasuredText(text, options = {}) {
62
64
  const ref = useRef(null);
63
65
  const [ready, setReady] = useState(false);
64
66
  const [measurement, setMeasurement] = useState(null);
65
- const [resolvedFont, setResolvedFont] = useState("16px sans-serif");
66
- const [resolvedLineHeight, setResolvedLineHeight] = useState(20);
67
- const [resolvedLetterSpacing, setResolvedLetterSpacing] = useState(0);
68
67
  const readComputedStyles = useCallback(() => {
69
68
  const el = ref.current;
70
69
  if (!el) return;
71
70
  const computed = window.getComputedStyle(el);
72
- const font = computed.font;
73
- const lh = parseFloat(computed.lineHeight);
74
- const ls = parseFloat(computed.letterSpacing) || 0;
75
- setResolvedFont(font || "16px sans-serif");
76
- setResolvedLineHeight(Number.isNaN(lh) ? 20 : lh);
77
- setResolvedLetterSpacing(Number.isNaN(ls) ? 0 : ls);
78
- if (process.env.NODE_ENV === "development") {
79
- if (computed.fontFamily?.includes("system-ui")) console.warn("[useMeasuredText] Font family \"system-ui\" detected on element. This is unsafe for layout accuracy on macOS. Use an explicit font family (e.g., Inter, Helvetica Neue).");
71
+ if (process.env.NODE_ENV === "development" && !hasWarnedSystemUi) {
72
+ if (computed.fontFamily?.split(",")[0]?.trim().replace(/^["']|["']$/gu, "") === "system-ui") {
73
+ hasWarnedSystemUi = true;
74
+ console.warn("[useMeasuredText] \"system-ui\" is the first font family on a measured element. Canvas measurement of system-ui is OS-dependent and unsafe for layout accuracy on macOS. Use an explicit font family first (e.g. Inter, Helvetica Neue), with system-ui only as a fallback.");
75
+ }
80
76
  }
81
77
  }, []);
82
78
  const measure = useCallback(() => {
83
79
  if (isSSR) return;
84
80
  if (typeof globalThis !== "undefined" && globalThis.__SF_PRETEXT_DISABLED__) return;
85
81
  if (!ref.current) return;
86
- const containerWidth = ref.current.getBoundingClientRect().width;
82
+ const el = ref.current;
83
+ const parent = el.parentElement;
84
+ let containerWidth = el.getBoundingClientRect().width;
85
+ if (parent) {
86
+ const parentStyle = getComputedStyle(parent);
87
+ const paddingX = Number.parseFloat(parentStyle.paddingLeft) + Number.parseFloat(parentStyle.paddingRight);
88
+ const parentContentWidth = parent.clientWidth - paddingX;
89
+ if (parentContentWidth > 0) containerWidth = parentContentWidth;
90
+ }
87
91
  if (containerWidth <= 0) return;
88
- const font = resolvedFont;
89
- const lh = lineHeightProp ?? resolvedLineHeight;
90
- const ls = letterSpacingProp ?? resolvedLetterSpacing;
92
+ const computed = window.getComputedStyle(el);
93
+ const computedFont = computed.font || "16px sans-serif";
94
+ const computedLh = Number.parseFloat(computed.lineHeight);
95
+ const computedLs = Number.parseFloat(computed.letterSpacing);
96
+ const font = computedFont;
97
+ const lh = lineHeightProp ?? (Number.isNaN(computedLh) ? 20 : computedLh);
98
+ const ls = letterSpacingProp ?? (Number.isNaN(computedLs) ? 0 : computedLs);
91
99
  try {
92
100
  const { prepared, preparedWithSegments } = getPrepared(text, font, {
93
101
  letterSpacing: ls,
@@ -147,9 +155,6 @@ function useMeasuredText(text, options = {}) {
147
155
  }, [
148
156
  text,
149
157
  mode,
150
- resolvedFont,
151
- resolvedLineHeight,
152
- resolvedLetterSpacing,
153
158
  whiteSpace,
154
159
  wordBreak,
155
160
  reserveLines,
@@ -185,9 +190,15 @@ function useMeasuredText(text, options = {}) {
185
190
  if (mode === "natural") return;
186
191
  const el = ref.current;
187
192
  if (!el) return;
193
+ const target = el.parentElement ?? el;
188
194
  let rafId = null;
189
195
  let pending = false;
196
+ let skipInitial = true;
190
197
  const handleResize = () => {
198
+ if (skipInitial) {
199
+ skipInitial = false;
200
+ return;
201
+ }
191
202
  if (pending) return;
192
203
  pending = true;
193
204
  rafId = requestAnimationFrame(() => {
@@ -197,7 +208,7 @@ function useMeasuredText(text, options = {}) {
197
208
  });
198
209
  };
199
210
  const observer = new ResizeObserver(handleResize);
200
- observer.observe(el);
211
+ observer.observe(target);
201
212
  return () => {
202
213
  observer.disconnect();
203
214
  if (rafId !== null) cancelAnimationFrame(rafId);
@@ -229,7 +240,7 @@ function useMeasuredText(text, options = {}) {
229
240
  * SSR-safe: renders with CSS fallbacks initially; upgrades to measured
230
241
  * values after hydration without layout mismatch.
231
242
  */
232
- var MeasuredText = forwardRef(function MeasuredText({ children, as: Component = "span", wrap = "natural", reserveLines, whiteSpace = "normal", wordBreak = "normal", className, style, ...props }, forwardedRef) {
243
+ var MeasuredText = forwardRef(({ children, as: Component = "span", wrap = "natural", reserveLines, whiteSpace = "normal", wordBreak = "normal", className, style, ...props }, forwardedRef) => {
233
244
  const text = useMemo(() => {
234
245
  if (typeof children === "string") return children;
235
246
  if (typeof children === "number") return String(children);
@@ -247,34 +258,38 @@ var MeasuredText = forwardRef(function MeasuredText({ children, as: Component =
247
258
  if (typeof forwardedRef === "function") forwardedRef(el);
248
259
  else if (forwardedRef) forwardedRef.current = el;
249
260
  };
261
+ const hasMeasuredRef = useRef(false);
262
+ const measured = ready && measurement !== null;
250
263
  const layoutStyles = useMemo(() => {
251
- if (!ready || !measurement) {
252
- if (mode === "balance") return { textWrap: "balance" };
264
+ if (!measured) {
253
265
  if (mode === "reserve" && typeof reserveLines === "number") return { minHeight: `${reserveLines * 1.5}em` };
254
266
  return {};
255
267
  }
268
+ const isFirstMeasurement = !hasMeasuredRef.current;
269
+ hasMeasuredRef.current = true;
270
+ const transition = (prop) => isFirstMeasurement ? void 0 : `${prop} 120ms ease-out`;
256
271
  if (mode === "balance") return {
257
272
  maxWidth: measurement.balancedWidth,
258
- transition: "max-width 120ms ease-out"
273
+ transition: transition("max-width")
259
274
  };
260
275
  if (mode === "shrink") return {
261
276
  maxWidth: measurement.maxLineWidth,
262
- transition: "max-width 120ms ease-out"
277
+ transition: transition("max-width")
263
278
  };
264
279
  if (mode === "reserve") return {
265
280
  minHeight: measurement.height,
266
- transition: "min-height 120ms ease-out"
281
+ transition: transition("min-height")
267
282
  };
268
283
  return {};
269
284
  }, [
270
285
  mode,
271
286
  measurement,
272
- ready,
287
+ measured,
273
288
  reserveLines
274
289
  ]);
275
290
  return /* @__PURE__ */ jsx(Component, {
276
291
  ref: setRefs,
277
- className: cn(mode !== "natural" && "inline-block", className),
292
+ className: cn(measured && mode !== "natural" && "inline-block", className),
278
293
  style: {
279
294
  ...layoutStyles,
280
295
  ...style
@@ -287,4 +302,4 @@ MeasuredText.displayName = "MeasuredText";
287
302
  //#endregion
288
303
  export { useMeasuredText as n, MeasuredText as t };
289
304
 
290
- //# sourceMappingURL=measured-text-BI3dTJmH.js.map
305
+ //# sourceMappingURL=measured-text-CXkdw9Yr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measured-text-CXkdw9Yr.js","names":[],"sources":["../src/utils/use-measured-text.ts","../src/utils/measured-text.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n prepare,\n prepareWithSegments,\n layout,\n measureLineStats,\n measureNaturalWidth,\n type PreparedText,\n type PreparedTextWithSegments,\n} from \"@chenglou/pretext\";\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type MeasuredTextMode = \"natural\" | \"balance\" | \"shrink\" | \"reserve\";\n\nexport interface TextMeasurement {\n /** Total height in pixels */\n height: number;\n /** Number of wrapped lines */\n lineCount: number;\n /** Width of the widest line */\n maxLineWidth: number;\n /**\n * For balance mode: the smallest maxWidth that doesn't increase line count\n * vs natural wrapping. For other modes, same as maxLineWidth.\n */\n balancedWidth: number;\n}\n\nexport interface UseMeasuredTextOptions {\n /** Measurement strategy */\n mode?: MeasuredTextMode;\n /** Expected line height in pixels (syncs with CSS line-height). Auto-detected if omitted. */\n lineHeight?: number;\n /** CSS letter-spacing in pixels. Auto-detected if omitted. */\n letterSpacing?: number;\n /** CSS white-space behavior. @default \"normal\" */\n whiteSpace?: \"normal\" | \"pre-wrap\";\n /** CSS word-break behavior. @default \"normal\" */\n wordBreak?: \"normal\" | \"keep-all\";\n /**\n * For reserve mode: pre-reserve this many lines of height before content arrives.\n * Overrides measurement-based line count when provided.\n */\n reserveLines?: number;\n}\n\nexport interface UseMeasuredTextResult {\n /** Ref to attach to the measured element */\n ref: React.RefObject<HTMLElement | null>;\n /** Measurement result (null when not ready or disabled) */\n measurement: TextMeasurement | null;\n /** Whether measurement is ready (false during SSR and initial paint) */\n ready: boolean;\n}\n\n// ─── Module-level cache ──────────────────────────────────────────────────────\n\ntype CacheKey = string;\n\ninterface CachedPrepared {\n prepared: PreparedText;\n preparedWithSegments: PreparedTextWithSegments;\n}\n\nconst preparationCache = new Map<CacheKey, CachedPrepared>();\n\n/** Dev-only: ensures the `system-ui` first-family warning fires at most once. */\nlet hasWarnedSystemUi = false;\n\nlet fontsReadyPromise: Promise<void> | null = null;\n\nfunction getFontsReady(): Promise<void> {\n if (fontsReadyPromise) return fontsReadyPromise;\n if (typeof document === \"undefined\" || !document.fonts?.ready) {\n fontsReadyPromise = Promise.resolve();\n return fontsReadyPromise;\n }\n fontsReadyPromise = document.fonts.ready.then(() => undefined);\n return fontsReadyPromise;\n}\n\nfunction makeCacheKey(\n text: string,\n font: string,\n letterSpacing: number,\n whiteSpace: string,\n wordBreak: string\n): CacheKey {\n return `${text}|${font}|${letterSpacing}|${whiteSpace}|${wordBreak}`;\n}\n\nfunction getPrepared(\n text: string,\n font: string,\n options: {\n letterSpacing: number;\n whiteSpace: \"normal\" | \"pre-wrap\";\n wordBreak: \"normal\" | \"keep-all\";\n }\n): CachedPrepared {\n const key = makeCacheKey(\n text,\n font,\n options.letterSpacing,\n options.whiteSpace,\n options.wordBreak\n );\n\n const cached = preparationCache.get(key);\n if (cached) return cached;\n\n const prepared = prepare(text, font, {\n letterSpacing: options.letterSpacing,\n whiteSpace: options.whiteSpace,\n wordBreak: options.wordBreak,\n });\n\n const preparedWithSegments = prepareWithSegments(text, font, {\n letterSpacing: options.letterSpacing,\n whiteSpace: options.whiteSpace,\n wordBreak: options.wordBreak,\n });\n\n const entry: CachedPrepared = { prepared, preparedWithSegments };\n preparationCache.set(key, entry);\n return entry;\n}\n\n// ─── Hook ────────────────────────────────────────────────────────────────────\n\nconst isSSR = typeof window === \"undefined\";\nconst useIsomorphicLayoutEffect = isSSR ? useEffect : useLayoutEffect;\n\n/**\n * Measures text layout using @chenglou/pretext without DOM reflow.\n *\n * - Caches `prepare()` results keyed by text + font config (do not re-prepare on resize).\n * - Waits for `document.fonts.ready` before first measurement.\n * - Uses ResizeObserver (rAF-throttled) to recompute layout on container resize.\n * - SSR-safe: returns `ready: false` initially; measures post-hydration.\n *\n * @example\n * ```tsx\n * const { ref, measurement, ready } = useMeasuredText(\n * \"Hello world\",\n * { mode: \"balance\" }\n * );\n * // ready === false on SSR\n * // measurement.balancedWidth available after hydration + fonts load\n * ```\n */\nexport function useMeasuredText(\n text: string,\n options: UseMeasuredTextOptions = {}\n): UseMeasuredTextResult {\n const {\n mode = \"natural\",\n lineHeight: lineHeightProp,\n letterSpacing: letterSpacingProp,\n whiteSpace = \"normal\",\n wordBreak = \"normal\",\n reserveLines,\n } = options;\n\n const ref = useRef<HTMLElement>(null);\n const [ready, setReady] = useState(false);\n const [measurement, setMeasurement] = useState<TextMeasurement | null>(null);\n\n // Read computed styles from the DOM element. Font/line-height/letter-spacing\n // are consumed synchronously inside `measure()`; this callback only exists for\n // the dev-only `system-ui` warning so it doesn't drive any measurement state.\n const readComputedStyles = useCallback(() => {\n const el = ref.current;\n if (!el) return;\n\n const computed = window.getComputedStyle(el);\n\n // Dev-only warning when `system-ui` is the *effective* (first) font family.\n // Canvas measurement of `system-ui` resolves to an OS-dependent face and is\n // unsafe for layout accuracy on macOS (per pretext README). As a trailing\n // fallback (e.g. after a loaded `Inter`) it never gets selected, so we only\n // warn when it is the first family in the stack. Warn once to avoid spam.\n if (process.env.NODE_ENV === \"development\" && !hasWarnedSystemUi) {\n const firstFamily = computed.fontFamily\n ?.split(\",\")[0]\n ?.trim()\n .replace(/^[\"']|[\"']$/gu, \"\");\n if (firstFamily === \"system-ui\") {\n hasWarnedSystemUi = true;\n // eslint-disable-next-line no-console\n console.warn(\n `[useMeasuredText] \"system-ui\" is the first font family on a measured ` +\n `element. Canvas measurement of system-ui is OS-dependent and unsafe ` +\n `for layout accuracy on macOS. Use an explicit font family first ` +\n `(e.g. Inter, Helvetica Neue), with system-ui only as a fallback.`\n );\n }\n }\n }, []);\n\n // Main measurement effect\n const measure = useCallback(() => {\n if (isSSR) return;\n if (\n typeof globalThis !== \"undefined\" &&\n (globalThis as { __SF_PRETEXT_DISABLED__?: boolean })\n .__SF_PRETEXT_DISABLED__\n ) {\n return;\n }\n if (!ref.current) return;\n\n const el = ref.current;\n\n // Once measured the element becomes `inline-block`, so its own\n // bounding box is shrink-to-fit — it reflects the text's *current*\n // (possibly already-wrapped) width, not the width the layout is\n // actually constrained to. Measuring against that collapses the\n // layout and produces spurious wrapping whenever no ancestor sets an\n // explicit width. Instead, measure against the parent's content-box\n // width, which is the real constraint CSS imposes on the text.\n const parent = el.parentElement;\n let containerWidth = el.getBoundingClientRect().width;\n if (parent) {\n const parentStyle = getComputedStyle(parent);\n const paddingX =\n Number.parseFloat(parentStyle.paddingLeft) +\n Number.parseFloat(parentStyle.paddingRight);\n const parentContentWidth = parent.clientWidth - paddingX;\n if (parentContentWidth > 0) {\n containerWidth = parentContentWidth;\n }\n }\n if (containerWidth <= 0) return;\n\n // Read font metrics synchronously from the DOM at measure time rather than\n // from React state. Routing them through state means the first measure runs\n // with the default font (\"16px sans-serif\"), then the state update triggers\n // a *second* measure with the real font — and that second pass animates,\n // producing a visible width jump. Reading directly = one correct measure.\n const computed = window.getComputedStyle(el);\n const computedFont = computed.font || \"16px sans-serif\";\n const computedLh = Number.parseFloat(computed.lineHeight);\n const computedLs = Number.parseFloat(computed.letterSpacing);\n\n const font = computedFont;\n const lh = lineHeightProp ?? (Number.isNaN(computedLh) ? 20 : computedLh);\n const ls = letterSpacingProp ?? (Number.isNaN(computedLs) ? 0 : computedLs);\n\n try {\n const { prepared, preparedWithSegments } = getPrepared(text, font, {\n letterSpacing: ls,\n whiteSpace,\n wordBreak,\n });\n\n // Mode-specific measurement\n let height = 0;\n let lineCount = 0;\n let maxLineWidth = 0;\n let balancedWidth = 0;\n\n if (mode === \"reserve\" && typeof reserveLines === \"number\") {\n // Use reserved line count for height, but still measure width\n const stats = measureLineStats(preparedWithSegments, containerWidth);\n maxLineWidth = stats.maxLineWidth;\n lineCount = reserveLines;\n height = reserveLines * lh;\n balancedWidth = maxLineWidth;\n } else if (mode === \"shrink\") {\n // Measure natural width (widest unwrapped line)\n maxLineWidth = measureNaturalWidth(preparedWithSegments);\n balancedWidth = maxLineWidth;\n // Re-layout at that width to get accurate line count/height\n const result = layout(prepared, maxLineWidth, lh);\n height = result.height;\n lineCount = result.lineCount;\n } else if (mode === \"balance\") {\n // Find balanced width: smallest width that doesn't add lines\n const naturalResult = layout(prepared, containerWidth, lh);\n const naturalLineCount = naturalResult.lineCount;\n\n // Binary search for smallest width that keeps same line count\n let low = 0;\n let high = containerWidth;\n balancedWidth = containerWidth;\n\n for (let i = 0; i < 12; i++) {\n // 12 iterations = ~0.02% precision\n const mid = (low + high) / 2;\n const stats = measureLineStats(preparedWithSegments, mid);\n if (stats.lineCount <= naturalLineCount && stats.lineCount > 0) {\n balancedWidth = mid;\n high = mid;\n } else {\n low = mid;\n }\n }\n\n // Final measurement at balanced width\n const result = layout(prepared, balancedWidth, lh);\n height = result.height;\n lineCount = result.lineCount;\n maxLineWidth =\n naturalResult.lineCount > 0\n ? measureLineStats(preparedWithSegments, containerWidth)\n .maxLineWidth\n : 0;\n } else {\n // natural or default\n const result = layout(prepared, containerWidth, lh);\n height = result.height;\n lineCount = result.lineCount;\n maxLineWidth = measureLineStats(\n preparedWithSegments,\n containerWidth\n ).maxLineWidth;\n balancedWidth = maxLineWidth;\n }\n\n setMeasurement({ height, lineCount, maxLineWidth, balancedWidth });\n setReady(true);\n } catch (err) {\n // Measurement failed (e.g., canvas unavailable) — keep CSS fallback behavior\n if (process.env.NODE_ENV === \"development\") {\n // eslint-disable-next-line no-console\n console.warn(\"[useMeasuredText] Measurement failed:\", err);\n }\n }\n }, [\n text,\n mode,\n whiteSpace,\n wordBreak,\n reserveLines,\n lineHeightProp,\n letterSpacingProp,\n ]);\n\n // Initial measurement after fonts load and layout settles\n useIsomorphicLayoutEffect(() => {\n if (isSSR) return;\n if (mode === \"natural\") {\n // No measurement needed for natural mode\n setReady(true);\n return;\n }\n\n let cancelled = false;\n\n const runMeasurement = async () => {\n await getFontsReady();\n if (cancelled) return;\n\n // Read computed styles first\n readComputedStyles();\n\n // Measure on next frame to ensure layout settled\n requestAnimationFrame(() => {\n if (!cancelled) measure();\n });\n };\n\n runMeasurement();\n\n return () => {\n cancelled = true;\n };\n }, [measure, mode, readComputedStyles]);\n\n // ResizeObserver with rAF throttling\n useEffect(() => {\n if (isSSR) return;\n if (mode === \"natural\") return;\n\n const el = ref.current;\n if (!el) return;\n\n // Observe the *parent*, not the element. The element's own width is what\n // we control via `maxWidth`; observing it creates a feedback loop —\n // applying a measured maxWidth shrinks the element, the observer sees that\n // as a resize, re-measures, and the second pass animates (causing the\n // visible flash). The parent's content box is the real layout constraint,\n // so re-measure only when *that* changes.\n const target = el.parentElement ?? el;\n\n let rafId: number | null = null;\n let pending = false;\n // ResizeObserver fires a synthetic callback immediately on observe with the\n // current size. The initial measurement is already handled by the layout\n // effect, so ignore this first delivery — otherwise it triggers a redundant\n // second measure that animates (the visible flash).\n let skipInitial = true;\n\n const handleResize = () => {\n if (skipInitial) {\n skipInitial = false;\n return;\n }\n if (pending) return;\n pending = true;\n\n rafId = requestAnimationFrame(() => {\n pending = false;\n readComputedStyles();\n measure();\n });\n };\n\n const observer = new ResizeObserver(handleResize);\n observer.observe(target);\n\n return () => {\n observer.disconnect();\n if (rafId !== null) cancelAnimationFrame(rafId);\n };\n }, [measure, mode, readComputedStyles]);\n\n return { ref, measurement, ready };\n}\n","\"use client\";\n\nimport type { ElementType, ReactNode, CSSProperties } from \"react\";\nimport { forwardRef, useMemo, useRef } from \"react\";\n\nimport { cn } from \"./cn\";\nimport { useMeasuredText, type MeasuredTextMode } from \"./use-measured-text\";\n\n// Re-export the type for consumers\nexport type { MeasuredTextMode } from \"./use-measured-text\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface MeasuredTextProps {\n /** Text content to measure and render */\n children: ReactNode;\n /** HTML element to render as. @default \"span\" */\n as?: ElementType;\n /** Measurement/wrapping strategy */\n wrap?: MeasuredTextMode | false;\n /**\n * For reserve mode: pre-reserve this many lines.\n * If omitted in reserve mode, measures children to determine line count.\n */\n reserveLines?: number;\n /** CSS white-space behavior. @default \"normal\" */\n whiteSpace?: \"normal\" | \"pre-wrap\";\n /** CSS word-break behavior. @default \"normal\" */\n wordBreak?: \"normal\" | \"keep-all\";\n /** Additional CSS classes */\n className?: string;\n /** Inline styles (merged with measured styles) */\n style?: CSSProperties;\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\n/**\n * Internal component that renders text with pretext-driven layout.\n *\n * This is NOT exported publicly. It powers the public `Text` component.\n *\n * Strategies:\n * - `balance`: finds smallest maxWidth that doesn't increase line count\n * - `shrink`: hugs the widest natural line (maxWidth = maxLineWidth)\n * - `reserve`: sets minHeight based on line count × lineHeight\n * - `natural` / `false`: no measurement, renders as normal inline element\n *\n * SSR-safe: renders with CSS fallbacks initially; upgrades to measured\n * values after hydration without layout mismatch.\n */\nexport const MeasuredText = forwardRef<HTMLElement, MeasuredTextProps>(\n (\n {\n children,\n as: Component = \"span\",\n wrap = \"natural\",\n reserveLines,\n whiteSpace = \"normal\",\n wordBreak = \"normal\",\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n // Extract text content for measurement (simple stringification for now)\n const text = useMemo(() => {\n if (typeof children === \"string\") return children;\n if (typeof children === \"number\") return String(children);\n // For complex children, we can't measure accurately — fall back to natural\n return \"\";\n }, [children]);\n\n const mode = wrap === false ? \"natural\" : wrap;\n const shouldMeasure = mode !== \"natural\" && text.length > 0;\n\n const { ref, measurement, ready } = useMeasuredText(text, {\n mode: shouldMeasure ? mode : \"natural\",\n whiteSpace,\n wordBreak,\n reserveLines,\n });\n\n // Merge refs\n const setRefs = (el: HTMLElement | null) => {\n (ref as React.MutableRefObject<HTMLElement | null>).current = el;\n if (typeof forwardedRef === \"function\") {\n forwardedRef(el);\n } else if (forwardedRef) {\n (forwardedRef as React.MutableRefObject<HTMLElement | null>).current =\n el;\n }\n };\n\n // Track whether the first real measurement has landed so we only\n // animate *subsequent* changes (e.g. resize). Animating the initial\n // settle makes the layout visibly slide/unwrap on load.\n const hasMeasuredRef = useRef(false);\n const measured = ready && measurement !== null;\n\n // Compute layout styles based on mode and measurement state\n const layoutStyles = useMemo<CSSProperties>(() => {\n if (!measured) {\n // Pre-measurement: render at natural width. Do NOT use\n // `text-wrap: balance` here — combined with `inline-block` and no\n // width it forces the browser to wrap into balanced lines on first\n // paint, which then visibly unwraps once measurement applies a\n // maxWidth. A bare inline-block shrink-wraps to a single line.\n if (mode === \"reserve\" && typeof reserveLines === \"number\") {\n // Heuristic: assume 1.5em line height for SSR reserve\n return { minHeight: `${reserveLines * 1.5}em` };\n }\n return {};\n }\n\n const isFirstMeasurement = !hasMeasuredRef.current;\n hasMeasuredRef.current = true;\n // Only transition on changes after the initial settle.\n const transition = (prop: string) =>\n isFirstMeasurement ? undefined : `${prop} 120ms ease-out`;\n\n // Post-measurement: apply precise values\n if (mode === \"balance\") {\n return {\n maxWidth: measurement.balancedWidth,\n transition: transition(\"max-width\"),\n };\n }\n\n if (mode === \"shrink\") {\n return {\n maxWidth: measurement.maxLineWidth,\n transition: transition(\"max-width\"),\n };\n }\n\n if (mode === \"reserve\") {\n return {\n minHeight: measurement.height,\n transition: transition(\"min-height\"),\n };\n }\n\n return {};\n }, [mode, measurement, measured, reserveLines]);\n\n return (\n <Component\n ref={setRefs}\n className={cn(\n // Only become `inline-block` once measured. `measured` is false both\n // on the server and on the first client render, so hydration matches\n // exactly (no markup/layout swap). First paint therefore uses normal\n // block/inline flow at the full available width — text wraps the same\n // way the browser would naturally — and we only switch to\n // `inline-block` + `maxWidth` to tighten the balance after measuring.\n // A width-less `inline-block` in SSR shrink-wraps to content and is\n // what produced the odd first-paint wrap.\n measured && mode !== \"natural\" && \"inline-block\",\n className\n )}\n style={{\n ...layoutStyles,\n ...style,\n }}\n {...props}\n >\n {children}\n </Component>\n );\n }\n);\n\nMeasuredText.displayName = \"MeasuredText\";\n"],"mappings":";;;;;;AAyEA,IAAM,mCAAmB,IAAI,IAA8B;;AAG3D,IAAI,oBAAoB;AAExB,IAAI,oBAA0C;AAE9C,SAAS,gBAA+B;CACtC,IAAI,mBAAmB,OAAO;CAC9B,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,OAAO,OAAO;EAC7D,oBAAoB,QAAQ,QAAQ;EACpC,OAAO;CACT;CACA,oBAAoB,SAAS,MAAM,MAAM,WAAW,KAAA,CAAS;CAC7D,OAAO;AACT;AAEA,SAAS,aACP,MACA,MACA,eACA,YACA,WACU;CACV,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,cAAc,GAAG,WAAW,GAAG;AAC3D;AAEA,SAAS,YACP,MACA,MACA,SAKgB;CAChB,MAAM,MAAM,aACV,MACA,MACA,QAAQ,eACR,QAAQ,YACR,QAAQ,SACV;CAEA,MAAM,SAAS,iBAAiB,IAAI,GAAG;CACvC,IAAI,QAAQ,OAAO;CAcnB,MAAM,QAAwB;EAAE,UAZf,QAAQ,MAAM,MAAM;GACnC,eAAe,QAAQ;GACvB,YAAY,QAAQ;GACpB,WAAW,QAAQ;EACrB,CAQgC;EAAU,sBANb,oBAAoB,MAAM,MAAM;GAC3D,eAAe,QAAQ;GACvB,YAAY,QAAQ;GACpB,WAAW,QAAQ;EACrB,CAE0C;CAAqB;CAC/D,iBAAiB,IAAI,KAAK,KAAK;CAC/B,OAAO;AACT;AAIA,IAAM,QAAQ,OAAO,WAAW;AAChC,IAAM,4BAA4B,QAAQ,YAAY;;;;;;;;;;;;;;;;;;;AAoBtD,SAAgB,gBACd,MACA,UAAkC,CAAC,GACZ;CACvB,MAAM,EACJ,OAAO,WACP,YAAY,gBACZ,eAAe,mBACf,aAAa,UACb,YAAY,UACZ,iBACE;CAEJ,MAAM,MAAM,OAAoB,IAAI;CACpC,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,CAAC,aAAa,kBAAkB,SAAiC,IAAI;CAK3E,MAAM,qBAAqB,kBAAkB;EAC3C,MAAM,KAAK,IAAI;EACf,IAAI,CAAC,IAAI;EAET,MAAM,WAAW,OAAO,iBAAiB,EAAE;EAO3C,IAAA,QAAA,IAAA,aAA6B,iBAAiB,CAAC;OACzB,SAAS,YACzB,MAAM,GAAG,EAAE,IACX,KAAK,EACN,QAAQ,iBAAiB,EAAE,MACV,aAAa;IAC/B,oBAAoB;IAEpB,QAAQ,KACN,6QAIF;GACF;;CAEJ,GAAG,CAAC,CAAC;CAGL,MAAM,UAAU,kBAAkB;EAChC,IAAI,OAAO;EACX,IACE,OAAO,eAAe,eACrB,WACE,yBAEH;EAEF,IAAI,CAAC,IAAI,SAAS;EAElB,MAAM,KAAK,IAAI;EASf,MAAM,SAAS,GAAG;EAClB,IAAI,iBAAiB,GAAG,sBAAsB,EAAE;EAChD,IAAI,QAAQ;GACV,MAAM,cAAc,iBAAiB,MAAM;GAC3C,MAAM,WACJ,OAAO,WAAW,YAAY,WAAW,IACzC,OAAO,WAAW,YAAY,YAAY;GAC5C,MAAM,qBAAqB,OAAO,cAAc;GAChD,IAAI,qBAAqB,GACvB,iBAAiB;EAErB;EACA,IAAI,kBAAkB,GAAG;EAOzB,MAAM,WAAW,OAAO,iBAAiB,EAAE;EAC3C,MAAM,eAAe,SAAS,QAAQ;EACtC,MAAM,aAAa,OAAO,WAAW,SAAS,UAAU;EACxD,MAAM,aAAa,OAAO,WAAW,SAAS,aAAa;EAE3D,MAAM,OAAO;EACb,MAAM,KAAK,mBAAmB,OAAO,MAAM,UAAU,IAAI,KAAK;EAC9D,MAAM,KAAK,sBAAsB,OAAO,MAAM,UAAU,IAAI,IAAI;EAEhE,IAAI;GACF,MAAM,EAAE,UAAU,yBAAyB,YAAY,MAAM,MAAM;IACjE,eAAe;IACf;IACA;GACF,CAAC;GAGD,IAAI,SAAS;GACb,IAAI,YAAY;GAChB,IAAI,eAAe;GACnB,IAAI,gBAAgB;GAEpB,IAAI,SAAS,aAAa,OAAO,iBAAiB,UAAU;IAG1D,eADc,iBAAiB,sBAAsB,cACtC,EAAM;IACrB,YAAY;IACZ,SAAS,eAAe;IACxB,gBAAgB;GAClB,OAAO,IAAI,SAAS,UAAU;IAE5B,eAAe,oBAAoB,oBAAoB;IACvD,gBAAgB;IAEhB,MAAM,SAAS,OAAO,UAAU,cAAc,EAAE;IAChD,SAAS,OAAO;IAChB,YAAY,OAAO;GACrB,OAAO,IAAI,SAAS,WAAW;IAE7B,MAAM,gBAAgB,OAAO,UAAU,gBAAgB,EAAE;IACzD,MAAM,mBAAmB,cAAc;IAGvC,IAAI,MAAM;IACV,IAAI,OAAO;IACX,gBAAgB;IAEhB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;KAE3B,MAAM,OAAO,MAAM,QAAQ;KAC3B,MAAM,QAAQ,iBAAiB,sBAAsB,GAAG;KACxD,IAAI,MAAM,aAAa,oBAAoB,MAAM,YAAY,GAAG;MAC9D,gBAAgB;MAChB,OAAO;KACT,OACE,MAAM;IAEV;IAGA,MAAM,SAAS,OAAO,UAAU,eAAe,EAAE;IACjD,SAAS,OAAO;IAChB,YAAY,OAAO;IACnB,eACE,cAAc,YAAY,IACtB,iBAAiB,sBAAsB,cAAc,EAClD,eACH;GACR,OAAO;IAEL,MAAM,SAAS,OAAO,UAAU,gBAAgB,EAAE;IAClD,SAAS,OAAO;IAChB,YAAY,OAAO;IACnB,eAAe,iBACb,sBACA,cACF,EAAE;IACF,gBAAgB;GAClB;GAEA,eAAe;IAAE;IAAQ;IAAW;IAAc;GAAc,CAAC;GACjE,SAAS,IAAI;EACf,SAAS,KAAK;GAEZ,IAAA,QAAA,IAAA,aAA6B,eAE3B,QAAQ,KAAK,yCAAyC,GAAG;EAE7D;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAGD,gCAAgC;EAC9B,IAAI,OAAO;EACX,IAAI,SAAS,WAAW;GAEtB,SAAS,IAAI;GACb;EACF;EAEA,IAAI,YAAY;EAEhB,MAAM,iBAAiB,YAAY;GACjC,MAAM,cAAc;GACpB,IAAI,WAAW;GAGf,mBAAmB;GAGnB,4BAA4B;IAC1B,IAAI,CAAC,WAAW,QAAQ;GAC1B,CAAC;EACH;EAEA,eAAe;EAEf,aAAa;GACX,YAAY;EACd;CACF,GAAG;EAAC;EAAS;EAAM;CAAkB,CAAC;CAGtC,gBAAgB;EACd,IAAI,OAAO;EACX,IAAI,SAAS,WAAW;EAExB,MAAM,KAAK,IAAI;EACf,IAAI,CAAC,IAAI;EAQT,MAAM,SAAS,GAAG,iBAAiB;EAEnC,IAAI,QAAuB;EAC3B,IAAI,UAAU;EAKd,IAAI,cAAc;EAElB,MAAM,qBAAqB;GACzB,IAAI,aAAa;IACf,cAAc;IACd;GACF;GACA,IAAI,SAAS;GACb,UAAU;GAEV,QAAQ,4BAA4B;IAClC,UAAU;IACV,mBAAmB;IACnB,QAAQ;GACV,CAAC;EACH;EAEA,MAAM,WAAW,IAAI,eAAe,YAAY;EAChD,SAAS,QAAQ,MAAM;EAEvB,aAAa;GACX,SAAS,WAAW;GACpB,IAAI,UAAU,MAAM,qBAAqB,KAAK;EAChD;CACF,GAAG;EAAC;EAAS;EAAM;CAAkB,CAAC;CAEtC,OAAO;EAAE;EAAK;EAAa;CAAM;AACnC;;;;;;;;;;;;;;;;;ACzXA,IAAa,eAAe,YAExB,EACE,UACA,IAAI,YAAY,QAChB,OAAO,WACP,cACA,aAAa,UACb,YAAY,UACZ,WACA,OACA,GAAG,SAEL,iBACG;CAEH,MAAM,OAAO,cAAc;EACzB,IAAI,OAAO,aAAa,UAAU,OAAO;EACzC,IAAI,OAAO,aAAa,UAAU,OAAO,OAAO,QAAQ;EAExD,OAAO;CACT,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,OAAO,SAAS,QAAQ,YAAY;CAG1C,MAAM,EAAE,KAAK,aAAa,UAAU,gBAAgB,MAAM;EACxD,MAHoB,SAAS,aAAa,KAAK,SAAS,IAGlC,OAAO;EAC7B;EACA;EACA;CACF,CAAC;CAGD,MAAM,WAAW,OAA2B;EAC1C,IAAoD,UAAU;EAC9D,IAAI,OAAO,iBAAiB,YAC1B,aAAa,EAAE;OACV,IAAI,cACT,aAA6D,UAC3D;CAEN;CAKA,MAAM,iBAAiB,OAAO,KAAK;CACnC,MAAM,WAAW,SAAS,gBAAgB;CAG1C,MAAM,eAAe,cAA6B;EAChD,IAAI,CAAC,UAAU;GAMb,IAAI,SAAS,aAAa,OAAO,iBAAiB,UAEhD,OAAO,EAAE,WAAW,GAAG,eAAe,IAAI,IAAI;GAEhD,OAAO,CAAC;EACV;EAEA,MAAM,qBAAqB,CAAC,eAAe;EAC3C,eAAe,UAAU;EAEzB,MAAM,cAAc,SAClB,qBAAqB,KAAA,IAAY,GAAG,KAAK;EAG3C,IAAI,SAAS,WACX,OAAO;GACL,UAAU,YAAY;GACtB,YAAY,WAAW,WAAW;EACpC;EAGF,IAAI,SAAS,UACX,OAAO;GACL,UAAU,YAAY;GACtB,YAAY,WAAW,WAAW;EACpC;EAGF,IAAI,SAAS,WACX,OAAO;GACL,WAAW,YAAY;GACvB,YAAY,WAAW,YAAY;EACrC;EAGF,OAAO,CAAC;CACV,GAAG;EAAC;EAAM;EAAa;EAAU;CAAY,CAAC;CAE9C,OACE,oBAAC,WAAD;EACE,KAAK;EACL,WAAW,GAST,YAAY,SAAS,aAAa,gBAClC,SACF;EACA,OAAO;GACL,GAAG;GACH,GAAG;EACL;EACA,GAAI;EAEH;CACQ,CAAA;AAEf,CACF;AAEA,aAAa,cAAc"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { t as Tooltip } from "./tooltip-g9lFsvcT.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { t as Tooltip } from "./tooltip-uobk6Oh-.js";
4
4
  import { useEffect, useRef } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { IconContext } from "@phosphor-icons/react";
@@ -99,4 +99,4 @@ var MenuBar = ({ className, isActive, options, optionIds = false }) => {
99
99
  //#endregion
100
100
  export { useMenuNavigation as n, MenuBar as t };
101
101
 
102
- //# sourceMappingURL=menubar-Cxf3xeAt.js.map
102
+ //# sourceMappingURL=menubar-CoOr4ocj.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menubar-Cxf3xeAt.js","names":[],"sources":["../src/components/menubar/use-menu-navigation.ts","../src/components/menubar/menubar.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\n\ntype UseMenuNavigationProps = {\n menuRef: React.RefObject<HTMLElement | null>;\n direction?: \"horizontal\" | \"vertical\"; // Default: horizontal\n};\n\nexport const useMenuNavigation = ({\n menuRef,\n direction = \"horizontal\",\n}: UseMenuNavigationProps) => {\n const activeElementRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!menuRef.current) return;\n\n const focusableElements = Array.from(\n menuRef.current.querySelectorAll(\n 'a, button, input, textarea, select, details, [tabindex]:not([tabindex=\"-1\"])'\n )\n ) as HTMLElement[];\n\n if (focusableElements.length === 0) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (!activeElementRef.current) return;\n\n const currentIndex = focusableElements.indexOf(activeElementRef.current);\n let nextIndex = currentIndex;\n\n const isHorizontal = direction === \"horizontal\";\n const forwardKey = isHorizontal ? \"ArrowRight\" : \"ArrowDown\";\n const backwardKey = isHorizontal ? \"ArrowLeft\" : \"ArrowUp\";\n\n if (e.key === forwardKey) {\n e.preventDefault();\n nextIndex = (currentIndex + 1) % focusableElements.length;\n } else if (e.key === backwardKey) {\n e.preventDefault();\n nextIndex =\n (currentIndex - 1 + focusableElements.length) %\n focusableElements.length;\n } else {\n return;\n }\n\n const nextElement = focusableElements[nextIndex];\n activeElementRef.current = nextElement;\n nextElement.focus();\n };\n\n const addKeyListener = () =>\n document.addEventListener(\"keydown\", handleKeyDown);\n const removeKeyListener = () =>\n document.removeEventListener(\"keydown\", handleKeyDown);\n\n const handleFocusIn = () => {\n activeElementRef.current = document.activeElement as HTMLElement;\n addKeyListener();\n };\n\n const handleFocusOut = () => {\n activeElementRef.current = null;\n removeKeyListener();\n };\n\n menuRef.current.addEventListener(\"focusin\", handleFocusIn);\n menuRef.current.addEventListener(\"focusout\", handleFocusOut);\n\n return () => {\n menuRef.current?.removeEventListener(\"focusin\", handleFocusIn);\n menuRef.current?.removeEventListener(\"focusout\", handleFocusOut);\n removeKeyListener();\n };\n }, [menuRef, direction]);\n};\n","import { IconContext } from \"@phosphor-icons/react\";\nimport React, { useRef } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Tooltip } from \"../tooltip\";\nimport { useMenuNavigation } from \"./use-menu-navigation\";\n\n/** MenuBar variant definitions (currently empty, reserved for future additions). */\nexport const SF_MENUBAR_VARIANTS = {\n // MenuBar currently has no variant options but structure is ready for future additions\n} as const;\n\nexport const SF_MENUBAR_DEFAULT_VARIANTS = {} as const;\n\n// Derived types from SF_MENUBAR_VARIANTS\nexport interface SFMenuBarVariantsProps {}\n\nexport function menuBarVariants(_props: SFMenuBarVariantsProps = {}) {\n return cn(\n // Base styles\n \"flex rounded-lg border border-sf-fill bg-sf-fill pl-px shadow-xs transition-colors\"\n );\n}\n\n/** Props for an individual menu option within a MenuBar. */\ntype MenuOptionProps = {\n /** Icon element (typically from `@phosphor-icons/react`) rendered at 18px */\n icon: React.ReactNode;\n /** Unique identifier for the option (used when `optionIds` is true) */\n id?: number | string;\n /** Currently active value from the parent MenuBar */\n isActive?: number | boolean | string | undefined;\n /** Callback when this option is clicked */\n onClick: () => void;\n /** Tooltip text shown on hover */\n tooltip: string;\n};\n\nconst MenuOption = ({\n icon,\n id,\n isActive,\n onClick,\n tooltip,\n}: MenuOptionProps) => {\n return (\n <Tooltip content={tooltip}>\n <button\n className={cn(\n \"focus:inset-ring-focus relative -ml-px flex h-full w-11 cursor-pointer items-center justify-center rounded-md border-none bg-sf-fill first:rounded-l-lg last:rounded-r-lg transition-colors focus:z-10 focus:outline-none focus-visible:z-10 focus-visible:inset-ring-[0.5]\",\n {\n \"z-20 bg-sf-base shadow-xs transition-colors\": isActive === id,\n }\n )}\n onClick={onClick}\n >\n <IconContext.Provider value={{ size: 18 }} {...({} as any)}>\n {icon}\n </IconContext.Provider>\n </button>\n </Tooltip>\n );\n};\n\n/**\n * MenuBar component props.\n *\n * Horizontal icon-button toolbar with keyboard navigation and tooltip labels.\n *\n * @example\n * ```tsx\n * <MenuBar\n * isActive={activeIndex}\n * options={[\n * { icon: <ListIcon />, tooltip: \"List view\", onClick: () => setView(\"list\") },\n * { icon: <GridFourIcon />, tooltip: \"Grid view\", onClick: () => setView(\"grid\") },\n * ]}\n * />\n * ```\n */\ntype MenuBarProps = {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** The currently active option value — matched against option index or `id`. */\n isActive: number | boolean | string | undefined;\n /** Array of menu option configurations. */\n options: MenuOptionProps[];\n /** When true, each option's `id` field is used for matching instead of its array index. */\n optionIds?: boolean;\n};\n\n/**\n * MenuBar — horizontal icon-button toolbar with keyboard arrow-key navigation.\n *\n * Each option renders as a `<button>` with a Tooltip. The active option is\n * visually highlighted with an elevated background.\n *\n * @example\n * ```tsx\n * <MenuBar\n * isActive={0}\n * options={[\n * { icon: <ListIcon />, tooltip: \"List\", onClick: () => {} },\n * { icon: <GridFourIcon />, tooltip: \"Grid\", onClick: () => {} },\n * ]}\n * />\n * ```\n */\nexport const MenuBar = ({\n className,\n isActive,\n options,\n optionIds = false, // if option needs an extra unique ID\n}: MenuBarProps) => {\n const menuRef = useRef<HTMLElement | null>(null);\n\n useMenuNavigation({ menuRef, direction: \"horizontal\" });\n\n return (\n <nav\n className={cn(\n \"flex rounded-lg border border-sf-fill bg-sf-fill pl-px shadow-xs transition-colors\",\n className\n )}\n ref={menuRef}\n >\n {options.map((option, index) => (\n <MenuOption\n key={index}\n {...option}\n isActive={isActive}\n id={optionIds ? option.id : index}\n />\n ))}\n </nav>\n );\n};\n"],"mappings":";;;;;;;AAOA,IAAa,qBAAqB,EAChC,SACA,YAAY,mBACgB;CAC5B,MAAM,mBAAmB,OAA2B,KAAK;AAEzD,iBAAgB;AACd,MAAI,CAAC,QAAQ,QAAS;EAEtB,MAAM,oBAAoB,MAAM,KAC9B,QAAQ,QAAQ,iBACd,iFACD,CACF;AAED,MAAI,kBAAkB,WAAW,EAAG;EAEpC,MAAM,iBAAiB,MAAqB;AAC1C,OAAI,CAAC,iBAAiB,QAAS;GAE/B,MAAM,eAAe,kBAAkB,QAAQ,iBAAiB,QAAQ;GACxE,IAAI,YAAY;GAEhB,MAAM,eAAe,cAAc;GACnC,MAAM,aAAa,eAAe,eAAe;GACjD,MAAM,cAAc,eAAe,cAAc;AAEjD,OAAI,EAAE,QAAQ,YAAY;AACxB,MAAE,gBAAgB;AAClB,iBAAa,eAAe,KAAK,kBAAkB;cAC1C,EAAE,QAAQ,aAAa;AAChC,MAAE,gBAAgB;AAClB,iBACG,eAAe,IAAI,kBAAkB,UACtC,kBAAkB;SAEpB;GAGF,MAAM,cAAc,kBAAkB;AACtC,oBAAiB,UAAU;AAC3B,eAAY,OAAO;;EAGrB,MAAM,uBACJ,SAAS,iBAAiB,WAAW,cAAc;EACrD,MAAM,0BACJ,SAAS,oBAAoB,WAAW,cAAc;EAExD,MAAM,sBAAsB;AAC1B,oBAAiB,UAAU,SAAS;AACpC,mBAAgB;;EAGlB,MAAM,uBAAuB;AAC3B,oBAAiB,UAAU;AAC3B,sBAAmB;;AAGrB,UAAQ,QAAQ,iBAAiB,WAAW,cAAc;AAC1D,UAAQ,QAAQ,iBAAiB,YAAY,eAAe;AAE5D,eAAa;AACX,WAAQ,SAAS,oBAAoB,WAAW,cAAc;AAC9D,WAAQ,SAAS,oBAAoB,YAAY,eAAe;AAChE,sBAAmB;;IAEpB,CAAC,SAAS,UAAU,CAAC;;;;ACpC1B,IAAM,cAAc,EAClB,MACA,IACA,UACA,SACA,cACqB;AACrB,QACE,oBAAC,SAAD;EAAS,SAAS;YAChB,oBAAC,UAAD;GACE,WAAW,GACT,+QACA,EACE,+CAA+C,aAAa,IAC7D,CACF;GACQ;aAET,oBAAC,YAAY,UAAb;IAAsB,OAAO,EAAE,MAAM,IAAI;cACtC;IACoB,CAAA;GAChB,CAAA;EACD,CAAA;;;;;;;;;;;;;;;;;;;AAgDd,IAAa,WAAW,EACtB,WACA,UACA,SACA,YAAY,YACM;CAClB,MAAM,UAAU,OAA2B,KAAK;AAEhD,mBAAkB;EAAE;EAAS,WAAW;EAAc,CAAC;AAEvD,QACE,oBAAC,OAAD;EACE,WAAW,GACT,sFACA,UACD;EACD,KAAK;YAEJ,QAAQ,KAAK,QAAQ,UACpB,oBAAC,YAAD;GAEE,GAAI;GACM;GACV,IAAI,YAAY,OAAO,KAAK;GAC5B,EAJK,MAIL,CACF;EACE,CAAA"}
1
+ {"version":3,"file":"menubar-CoOr4ocj.js","names":[],"sources":["../src/components/menubar/use-menu-navigation.ts","../src/components/menubar/menubar.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\n\ntype UseMenuNavigationProps = {\n menuRef: React.RefObject<HTMLElement | null>;\n direction?: \"horizontal\" | \"vertical\"; // Default: horizontal\n};\n\nexport const useMenuNavigation = ({\n menuRef,\n direction = \"horizontal\",\n}: UseMenuNavigationProps) => {\n const activeElementRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!menuRef.current) return;\n\n const focusableElements = Array.from(\n menuRef.current.querySelectorAll(\n 'a, button, input, textarea, select, details, [tabindex]:not([tabindex=\"-1\"])'\n )\n ) as HTMLElement[];\n\n if (focusableElements.length === 0) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (!activeElementRef.current) return;\n\n const currentIndex = focusableElements.indexOf(activeElementRef.current);\n let nextIndex = currentIndex;\n\n const isHorizontal = direction === \"horizontal\";\n const forwardKey = isHorizontal ? \"ArrowRight\" : \"ArrowDown\";\n const backwardKey = isHorizontal ? \"ArrowLeft\" : \"ArrowUp\";\n\n if (e.key === forwardKey) {\n e.preventDefault();\n nextIndex = (currentIndex + 1) % focusableElements.length;\n } else if (e.key === backwardKey) {\n e.preventDefault();\n nextIndex =\n (currentIndex - 1 + focusableElements.length) %\n focusableElements.length;\n } else {\n return;\n }\n\n const nextElement = focusableElements[nextIndex];\n activeElementRef.current = nextElement;\n nextElement.focus();\n };\n\n const addKeyListener = () =>\n document.addEventListener(\"keydown\", handleKeyDown);\n const removeKeyListener = () =>\n document.removeEventListener(\"keydown\", handleKeyDown);\n\n const handleFocusIn = () => {\n activeElementRef.current = document.activeElement as HTMLElement;\n addKeyListener();\n };\n\n const handleFocusOut = () => {\n activeElementRef.current = null;\n removeKeyListener();\n };\n\n menuRef.current.addEventListener(\"focusin\", handleFocusIn);\n menuRef.current.addEventListener(\"focusout\", handleFocusOut);\n\n return () => {\n menuRef.current?.removeEventListener(\"focusin\", handleFocusIn);\n menuRef.current?.removeEventListener(\"focusout\", handleFocusOut);\n removeKeyListener();\n };\n }, [menuRef, direction]);\n};\n","import { IconContext } from \"@phosphor-icons/react\";\nimport React, { useRef } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Tooltip } from \"../tooltip\";\nimport { useMenuNavigation } from \"./use-menu-navigation\";\n\n/** MenuBar variant definitions (currently empty, reserved for future additions). */\nexport const SF_MENUBAR_VARIANTS = {\n // MenuBar currently has no variant options but structure is ready for future additions\n} as const;\n\nexport const SF_MENUBAR_DEFAULT_VARIANTS = {} as const;\n\n// Derived types from SF_MENUBAR_VARIANTS\nexport interface SFMenuBarVariantsProps {}\n\nexport function menuBarVariants(_props: SFMenuBarVariantsProps = {}) {\n return cn(\n // Base styles\n \"flex rounded-lg border border-sf-fill bg-sf-fill pl-px shadow-xs transition-colors\"\n );\n}\n\n/** Props for an individual menu option within a MenuBar. */\ntype MenuOptionProps = {\n /** Icon element (typically from `@phosphor-icons/react`) rendered at 18px */\n icon: React.ReactNode;\n /** Unique identifier for the option (used when `optionIds` is true) */\n id?: number | string;\n /** Currently active value from the parent MenuBar */\n isActive?: number | boolean | string | undefined;\n /** Callback when this option is clicked */\n onClick: () => void;\n /** Tooltip text shown on hover */\n tooltip: string;\n};\n\nconst MenuOption = ({\n icon,\n id,\n isActive,\n onClick,\n tooltip,\n}: MenuOptionProps) => {\n return (\n <Tooltip content={tooltip}>\n <button\n className={cn(\n \"focus:inset-ring-focus relative -ml-px flex h-full w-11 cursor-pointer items-center justify-center rounded-md border-none bg-sf-fill first:rounded-l-lg last:rounded-r-lg transition-colors focus:z-10 focus:outline-none focus-visible:z-10 focus-visible:inset-ring-[0.5]\",\n {\n \"z-20 bg-sf-base shadow-xs transition-colors\": isActive === id,\n }\n )}\n onClick={onClick}\n >\n <IconContext.Provider value={{ size: 18 }} {...({} as any)}>\n {icon}\n </IconContext.Provider>\n </button>\n </Tooltip>\n );\n};\n\n/**\n * MenuBar component props.\n *\n * Horizontal icon-button toolbar with keyboard navigation and tooltip labels.\n *\n * @example\n * ```tsx\n * <MenuBar\n * isActive={activeIndex}\n * options={[\n * { icon: <ListIcon />, tooltip: \"List view\", onClick: () => setView(\"list\") },\n * { icon: <GridFourIcon />, tooltip: \"Grid view\", onClick: () => setView(\"grid\") },\n * ]}\n * />\n * ```\n */\ntype MenuBarProps = {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** The currently active option value — matched against option index or `id`. */\n isActive: number | boolean | string | undefined;\n /** Array of menu option configurations. */\n options: MenuOptionProps[];\n /** When true, each option's `id` field is used for matching instead of its array index. */\n optionIds?: boolean;\n};\n\n/**\n * MenuBar — horizontal icon-button toolbar with keyboard arrow-key navigation.\n *\n * Each option renders as a `<button>` with a Tooltip. The active option is\n * visually highlighted with an elevated background.\n *\n * @example\n * ```tsx\n * <MenuBar\n * isActive={0}\n * options={[\n * { icon: <ListIcon />, tooltip: \"List\", onClick: () => {} },\n * { icon: <GridFourIcon />, tooltip: \"Grid\", onClick: () => {} },\n * ]}\n * />\n * ```\n */\nexport const MenuBar = ({\n className,\n isActive,\n options,\n optionIds = false, // if option needs an extra unique ID\n}: MenuBarProps) => {\n const menuRef = useRef<HTMLElement | null>(null);\n\n useMenuNavigation({ menuRef, direction: \"horizontal\" });\n\n return (\n <nav\n className={cn(\n \"flex rounded-lg border border-sf-fill bg-sf-fill pl-px shadow-xs transition-colors\",\n className\n )}\n ref={menuRef}\n >\n {options.map((option, index) => (\n <MenuOption\n key={index}\n {...option}\n isActive={isActive}\n id={optionIds ? option.id : index}\n />\n ))}\n </nav>\n );\n};\n"],"mappings":";;;;;;;AAOA,IAAa,qBAAqB,EAChC,SACA,YAAY,mBACgB;CAC5B,MAAM,mBAAmB,OAA2B,IAAI;CAExD,gBAAgB;EACd,IAAI,CAAC,QAAQ,SAAS;EAEtB,MAAM,oBAAoB,MAAM,KAC9B,QAAQ,QAAQ,iBACd,gFACF,CACF;EAEA,IAAI,kBAAkB,WAAW,GAAG;EAEpC,MAAM,iBAAiB,MAAqB;GAC1C,IAAI,CAAC,iBAAiB,SAAS;GAE/B,MAAM,eAAe,kBAAkB,QAAQ,iBAAiB,OAAO;GACvE,IAAI,YAAY;GAEhB,MAAM,eAAe,cAAc;GACnC,MAAM,aAAa,eAAe,eAAe;GACjD,MAAM,cAAc,eAAe,cAAc;GAEjD,IAAI,EAAE,QAAQ,YAAY;IACxB,EAAE,eAAe;IACjB,aAAa,eAAe,KAAK,kBAAkB;GACrD,OAAO,IAAI,EAAE,QAAQ,aAAa;IAChC,EAAE,eAAe;IACjB,aACG,eAAe,IAAI,kBAAkB,UACtC,kBAAkB;GACtB,OACE;GAGF,MAAM,cAAc,kBAAkB;GACtC,iBAAiB,UAAU;GAC3B,YAAY,MAAM;EACpB;EAEA,MAAM,uBACJ,SAAS,iBAAiB,WAAW,aAAa;EACpD,MAAM,0BACJ,SAAS,oBAAoB,WAAW,aAAa;EAEvD,MAAM,sBAAsB;GAC1B,iBAAiB,UAAU,SAAS;GACpC,eAAe;EACjB;EAEA,MAAM,uBAAuB;GAC3B,iBAAiB,UAAU;GAC3B,kBAAkB;EACpB;EAEA,QAAQ,QAAQ,iBAAiB,WAAW,aAAa;EACzD,QAAQ,QAAQ,iBAAiB,YAAY,cAAc;EAE3D,aAAa;GACX,QAAQ,SAAS,oBAAoB,WAAW,aAAa;GAC7D,QAAQ,SAAS,oBAAoB,YAAY,cAAc;GAC/D,kBAAkB;EACpB;CACF,GAAG,CAAC,SAAS,SAAS,CAAC;AACzB;;;ACrCA,IAAM,cAAc,EAClB,MACA,IACA,UACA,SACA,cACqB;CACrB,OACE,oBAAC,SAAD;EAAS,SAAS;YAChB,oBAAC,UAAD;GACE,WAAW,GACT,+QACA,EACE,+CAA+C,aAAa,GAC9D,CACF;GACS;aAET,oBAAC,YAAY,UAAb;IAAsB,OAAO,EAAE,MAAM,GAAG;cACrC;GACmB,CAAA;EAChB,CAAA;CACD,CAAA;AAEb;;;;;;;;;;;;;;;;;;AA8CA,IAAa,WAAW,EACtB,WACA,UACA,SACA,YAAY,YACM;CAClB,MAAM,UAAU,OAA2B,IAAI;CAE/C,kBAAkB;EAAE;EAAS,WAAW;CAAa,CAAC;CAEtD,OACE,oBAAC,OAAD;EACE,WAAW,GACT,sFACA,SACF;EACA,KAAK;YAEJ,QAAQ,KAAK,QAAQ,UACpB,oBAAC,YAAD;GAEE,GAAI;GACM;GACV,IAAI,YAAY,OAAO,KAAK;EAC7B,GAJM,KAIN,CACF;CACE,CAAA;AAET"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
4
  import { Meter } from "@base-ui/react/meter";
5
5
  //#region src/components/meter/meter.tsx
@@ -34,4 +34,4 @@ function Meter$1({ value, customValue, label, showValue = true, className, track
34
34
  //#endregion
35
35
  export { Meter$1 as t };
36
36
 
37
- //# sourceMappingURL=meter-BFFe9l5b.js.map
37
+ //# sourceMappingURL=meter-Pf_VOl59.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"meter-BFFe9l5b.js","names":[],"sources":["../src/components/meter/meter.tsx"],"sourcesContent":["import { Meter as BaseMeter } from \"@base-ui/react/meter\";\nimport { type ComponentPropsWithoutRef } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n/** Meter variant definitions (currently empty, reserved for future additions). */\nexport const SF_METER_VARIANTS = {\n // Meter currently has no variant options but structure is ready for future additions\n} as const;\n\nexport const SF_METER_DEFAULT_VARIANTS = {} as const;\n\n// Derived types from SF_METER_VARIANTS\nexport interface SFMeterVariantsProps {}\n\nexport function meterVariants(_props: SFMeterVariantsProps = {}) {\n return cn(\n // Base styles\n \"flex w-full flex-col gap-2\"\n );\n}\n\ntype RootProps = ComponentPropsWithoutRef<typeof BaseMeter.Root>;\n\n/**\n * Meter component props.\n *\n * @example\n * ```tsx\n * <Meter label=\"Storage used\" value={65} />\n * <Meter label=\"API requests\" value={75} customValue=\"750 / 1,000\" />\n * ```\n */\nexport interface MeterProps extends RootProps, SFMeterVariantsProps {\n /** Custom formatted value text (e.g. \"750 / 1,000\") displayed instead of percentage. */\n customValue?: string;\n /** Label text displayed above the meter track. */\n label: string;\n /**\n * Whether to display the percentage value next to the label.\n * @default true\n */\n showValue?: boolean;\n /** Additional CSS classes for the track (background bar). */\n trackClassName?: string;\n /** Additional CSS classes for the indicator (filled bar). */\n indicatorClassName?: string;\n}\n\n/**\n * Progress bar showing a measured value within a known range (e.g. quota usage).\n *\n * @example\n * ```tsx\n * <Meter label=\"Storage\" value={65} />\n * ```\n */\nexport function Meter({\n value,\n customValue,\n label,\n showValue = true,\n className,\n trackClassName,\n indicatorClassName,\n ...props\n}: MeterProps) {\n return (\n <BaseMeter.Root\n value={value}\n {...props}\n className={cn(\"flex w-full flex-col gap-2\", className)}\n >\n <div className=\"flex items-center justify-between gap-4\">\n <BaseMeter.Label className=\"text-xs text-sf-strong\">\n {label}\n </BaseMeter.Label>\n {customValue ? (\n <span className=\"text-sm font-medium text-sf-default tabular-nums\">\n {customValue}\n </span>\n ) : (\n <>\n {showValue && (\n <BaseMeter.Value className=\"text-sm font-medium text-sf-default tabular-nums\" />\n )}\n </>\n )}\n </div>\n <BaseMeter.Track\n className={cn(\n \"relative h-2 w-full overflow-hidden rounded-full bg-sf-fill\",\n trackClassName\n )}\n >\n <BaseMeter.Indicator\n className={cn(\n \"absolute inset-y-0 left-0 rounded-full bg-linear-to-r from-sf-brand via-sf-brand to-sf-brand transition-[width] duration-300 ease-out\",\n indicatorClassName\n )}\n />\n </BaseMeter.Track>\n </BaseMeter.Root>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAyDA,SAAgB,QAAM,EACpB,OACA,aACA,OACA,YAAY,MACZ,WACA,gBACA,oBACA,GAAG,SACU;AACb,QACE,qBAAC,MAAU,MAAX;EACS;EACP,GAAI;EACJ,WAAW,GAAG,8BAA8B,UAAU;YAHxD,CAKE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,MAAU,OAAX;IAAiB,WAAU;cACxB;IACe,CAAA,EACjB,cACC,oBAAC,QAAD;IAAM,WAAU;cACb;IACI,CAAA,GAEP,oBAAA,UAAA,EAAA,UACG,aACC,oBAAC,MAAU,OAAX,EAAiB,WAAU,oDAAqD,CAAA,EAEjF,CAAA,CAED;MACN,oBAAC,MAAU,OAAX;GACE,WAAW,GACT,+DACA,eACD;aAED,oBAAC,MAAU,WAAX,EACE,WAAW,GACT,yIACA,mBACD,EACD,CAAA;GACc,CAAA,CACH"}
1
+ {"version":3,"file":"meter-Pf_VOl59.js","names":[],"sources":["../src/components/meter/meter.tsx"],"sourcesContent":["import { Meter as BaseMeter } from \"@base-ui/react/meter\";\nimport { type ComponentPropsWithoutRef } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n/** Meter variant definitions (currently empty, reserved for future additions). */\nexport const SF_METER_VARIANTS = {\n // Meter currently has no variant options but structure is ready for future additions\n} as const;\n\nexport const SF_METER_DEFAULT_VARIANTS = {} as const;\n\n// Derived types from SF_METER_VARIANTS\nexport interface SFMeterVariantsProps {}\n\nexport function meterVariants(_props: SFMeterVariantsProps = {}) {\n return cn(\n // Base styles\n \"flex w-full flex-col gap-2\"\n );\n}\n\ntype RootProps = ComponentPropsWithoutRef<typeof BaseMeter.Root>;\n\n/**\n * Meter component props.\n *\n * @example\n * ```tsx\n * <Meter label=\"Storage used\" value={65} />\n * <Meter label=\"API requests\" value={75} customValue=\"750 / 1,000\" />\n * ```\n */\nexport interface MeterProps extends RootProps, SFMeterVariantsProps {\n /** Custom formatted value text (e.g. \"750 / 1,000\") displayed instead of percentage. */\n customValue?: string;\n /** Label text displayed above the meter track. */\n label: string;\n /**\n * Whether to display the percentage value next to the label.\n * @default true\n */\n showValue?: boolean;\n /** Additional CSS classes for the track (background bar). */\n trackClassName?: string;\n /** Additional CSS classes for the indicator (filled bar). */\n indicatorClassName?: string;\n}\n\n/**\n * Progress bar showing a measured value within a known range (e.g. quota usage).\n *\n * @example\n * ```tsx\n * <Meter label=\"Storage\" value={65} />\n * ```\n */\nexport function Meter({\n value,\n customValue,\n label,\n showValue = true,\n className,\n trackClassName,\n indicatorClassName,\n ...props\n}: MeterProps) {\n return (\n <BaseMeter.Root\n value={value}\n {...props}\n className={cn(\"flex w-full flex-col gap-2\", className)}\n >\n <div className=\"flex items-center justify-between gap-4\">\n <BaseMeter.Label className=\"text-xs text-sf-strong\">\n {label}\n </BaseMeter.Label>\n {customValue ? (\n <span className=\"text-sm font-medium text-sf-default tabular-nums\">\n {customValue}\n </span>\n ) : (\n <>\n {showValue && (\n <BaseMeter.Value className=\"text-sm font-medium text-sf-default tabular-nums\" />\n )}\n </>\n )}\n </div>\n <BaseMeter.Track\n className={cn(\n \"relative h-2 w-full overflow-hidden rounded-full bg-sf-fill\",\n trackClassName\n )}\n >\n <BaseMeter.Indicator\n className={cn(\n \"absolute inset-y-0 left-0 rounded-full bg-linear-to-r from-sf-brand via-sf-brand to-sf-brand transition-[width] duration-300 ease-out\",\n indicatorClassName\n )}\n />\n </BaseMeter.Track>\n </BaseMeter.Root>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAyDA,SAAgB,QAAM,EACpB,OACA,aACA,OACA,YAAY,MACZ,WACA,gBACA,oBACA,GAAG,SACU;CACb,OACE,qBAAC,MAAU,MAAX;EACS;EACP,GAAI;EACJ,WAAW,GAAG,8BAA8B,SAAS;YAHvD,CAKE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,MAAU,OAAX;IAAiB,WAAU;cACxB;GACc,CAAA,GAChB,cACC,oBAAC,QAAD;IAAM,WAAU;cACb;GACG,CAAA,IAEN,oBAAA,UAAA,EAAA,UACG,aACC,oBAAC,MAAU,OAAX,EAAiB,WAAU,mDAAoD,CAAA,EAEjF,CAAA,CAED;MACL,oBAAC,MAAU,OAAX;GACE,WAAW,GACT,+DACA,cACF;aAEA,oBAAC,MAAU,WAAX,EACE,WAAW,GACT,yIACA,kBACF,EACD,CAAA;EACc,CAAA,CACH;;AAEpB"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as InputGroup } from "./input-ClB_E4Lb.js";
2
+ import { t as InputGroup } from "./input-COmx2M_R.js";
3
3
  import { useEffect, useMemo, useState } from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { CaretDoubleLeftIcon, CaretDoubleRightIcon, CaretLeftIcon, CaretRightIcon } from "@phosphor-icons/react";
@@ -114,4 +114,4 @@ function Pagination({ page = 1, perPage, totalCount, setPage, text, controls = S
114
114
  //#endregion
115
115
  export { Pagination as t };
116
116
 
117
- //# sourceMappingURL=pagination-yS372Tr4.js.map
117
+ //# sourceMappingURL=pagination-DSY279Ta.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pagination-yS372Tr4.js","names":[],"sources":["../src/components/pagination/pagination.tsx"],"sourcesContent":["import {\n CaretDoubleLeftIcon,\n CaretDoubleRightIcon,\n CaretLeftIcon,\n CaretRightIcon,\n} from \"@phosphor-icons/react\";\nimport { useEffect, useMemo, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { InputGroup } from \"../input\";\n\n/** Pagination controls variant definitions. */\nexport const SF_PAGINATION_VARIANTS = {\n controls: {\n full: {\n classes: \"\",\n description:\n \"Full pagination controls with first, previous, page input, next, and last buttons\",\n },\n simple: {\n classes: \"\",\n description:\n \"Simple pagination controls with only previous and next buttons\",\n },\n },\n} as const;\n\nexport type SFPaginationControls = keyof typeof SF_PAGINATION_VARIANTS.controls;\n\nexport const SF_PAGINATION_DEFAULT_VARIANTS = {\n controls: \"full\",\n} as const;\n\nexport interface SFPaginationVariantsProps {\n controls?: SFPaginationControls;\n}\n\nexport function paginationVariants({\n controls = SF_PAGINATION_DEFAULT_VARIANTS.controls,\n}: SFPaginationVariantsProps = {}) {\n return cn(\n \"flex items-center justify-between gap-2\",\n SF_PAGINATION_VARIANTS.controls[controls].classes\n );\n}\n\n/**\n * Pagination component props.\n *\n * @example\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />\n * <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} controls=\"simple\" />\n * ```\n */\nexport interface PaginationProps extends SFPaginationVariantsProps {\n /** Callback fired when the current page changes. */\n setPage: (page: number) => void;\n /**\n * Current page number (1-indexed).\n * @default 1\n */\n page?: number;\n /** Number of items displayed per page. */\n perPage?: number;\n /** Total number of items across all pages. */\n totalCount?: number;\n /** Method to provide custom pagination text */\n text?: (props: {\n page?: number;\n perPage?: number;\n totalCount?: number;\n pageShowingRange: string;\n }) => React.ReactNode;\n}\n\n/**\n * Page navigation controls with page count display.\n *\n * @example\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />\n * ```\n */\nexport function Pagination({\n page = 1,\n perPage,\n totalCount,\n setPage,\n text,\n controls = SF_PAGINATION_DEFAULT_VARIANTS.controls,\n}: PaginationProps) {\n const [editingPage, setEditingPage] = useState<number>(1);\n\n // Value of the input as its being modified to display in the input, eventually syncs with `pagination.page`\n useEffect(() => {\n setEditingPage(page);\n }, [page]);\n\n const pageShowingRange = useMemo(() => {\n let lower = page * (perPage ?? 1) - (perPage ?? 0) + 1;\n let upper = Math.min(page * (perPage ?? 0), totalCount ?? 0);\n\n if (Number.isNaN(lower)) lower = 0;\n if (Number.isNaN(upper)) upper = 0;\n\n return `${lower}-${upper}`;\n }, [page, perPage, totalCount]);\n\n const maxPage = useMemo(() => {\n return Math.ceil((totalCount ?? 1) / (perPage ?? 1));\n }, [totalCount, perPage]);\n\n const getPaginationText = () => {\n if (text) {\n return text({ page, perPage, totalCount, pageShowingRange });\n } else if (totalCount && totalCount > 0) {\n return `Showing ${pageShowingRange} of ${totalCount}`;\n }\n return null;\n };\n\n return (\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"grow text-sm text-sf-strong\">{getPaginationText()}</div>\n <div>\n <InputGroup focusMode=\"individual\">\n {controls === \"full\" && (\n <InputGroup.Button\n variant=\"secondary\"\n aria-label=\"First page\"\n disabled={page <= 1}\n onClick={() => {\n setPage(1);\n setEditingPage(1);\n }}\n >\n <CaretDoubleLeftIcon size={16} />\n </InputGroup.Button>\n )}\n <InputGroup.Button\n variant=\"secondary\"\n aria-label=\"Previous page\"\n disabled={page <= 1}\n onClick={() => {\n const previousPage = Math.max(page - 1, 1);\n setPage(previousPage);\n setEditingPage(previousPage);\n }}\n >\n <CaretLeftIcon size={16} />\n </InputGroup.Button>\n {controls === \"full\" && (\n <InputGroup.Input\n style={{ width: 50 }}\n className=\"text-center\"\n aria-label=\"Page number\"\n value={editingPage}\n onValueChange={(value: string) => {\n setEditingPage(Number(value));\n }}\n onBlur={() => {\n let number = Math.max(editingPage, 1);\n number = Math.min(number, maxPage);\n setPage(number);\n setEditingPage(number);\n }}\n />\n )}\n <InputGroup.Button\n variant=\"secondary\"\n aria-label=\"Next page\"\n disabled={page === maxPage}\n onClick={() => {\n const nextPage = Math.min(page + 1, maxPage);\n setPage(nextPage);\n setEditingPage(nextPage);\n }}\n >\n <CaretRightIcon size={16} />\n </InputGroup.Button>\n {controls === \"full\" && (\n <InputGroup.Button\n variant=\"secondary\"\n aria-label=\"Last page\"\n disabled={page === maxPage}\n onClick={() => {\n setPage(maxPage);\n setEditingPage(maxPage);\n }}\n >\n <CaretDoubleRightIcon size={16} />\n </InputGroup.Button>\n )}\n </InputGroup>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AA6BA,IAAa,iCAAiC,EAC5C,UAAU,QACX;;;;;;;;;AAqDD,SAAgB,WAAW,EACzB,OAAO,GACP,SACA,YACA,SACA,MACA,WAAW,+BAA+B,YACxB;CAClB,MAAM,CAAC,aAAa,kBAAkB,SAAiB,EAAE;AAGzD,iBAAgB;AACd,iBAAe,KAAK;IACnB,CAAC,KAAK,CAAC;CAEV,MAAM,mBAAmB,cAAc;EACrC,IAAI,QAAQ,QAAQ,WAAW,MAAM,WAAW,KAAK;EACrD,IAAI,QAAQ,KAAK,IAAI,QAAQ,WAAW,IAAI,cAAc,EAAE;AAE5D,MAAI,OAAO,MAAM,MAAM,CAAE,SAAQ;AACjC,MAAI,OAAO,MAAM,MAAM,CAAE,SAAQ;AAEjC,SAAO,GAAG,MAAM,GAAG;IAClB;EAAC;EAAM;EAAS;EAAW,CAAC;CAE/B,MAAM,UAAU,cAAc;AAC5B,SAAO,KAAK,MAAM,cAAc,MAAM,WAAW,GAAG;IACnD,CAAC,YAAY,QAAQ,CAAC;CAEzB,MAAM,0BAA0B;AAC9B,MAAI,KACF,QAAO,KAAK;GAAE;GAAM;GAAS;GAAY;GAAkB,CAAC;WACnD,cAAc,aAAa,EACpC,QAAO,WAAW,iBAAiB,MAAM;AAE3C,SAAO;;AAGT,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,OAAD;GAAK,WAAU;aAA+B,mBAAmB;GAAO,CAAA,EACxE,oBAAC,OAAD,EAAA,UACE,qBAAC,YAAD;GAAY,WAAU;aAAtB;IACG,aAAa,UACZ,oBAAC,WAAW,QAAZ;KACE,SAAQ;KACR,cAAW;KACX,UAAU,QAAQ;KAClB,eAAe;AACb,cAAQ,EAAE;AACV,qBAAe,EAAE;;eAGnB,oBAAC,qBAAD,EAAqB,MAAM,IAAM,CAAA;KACf,CAAA;IAEtB,oBAAC,WAAW,QAAZ;KACE,SAAQ;KACR,cAAW;KACX,UAAU,QAAQ;KAClB,eAAe;MACb,MAAM,eAAe,KAAK,IAAI,OAAO,GAAG,EAAE;AAC1C,cAAQ,aAAa;AACrB,qBAAe,aAAa;;eAG9B,oBAAC,eAAD,EAAe,MAAM,IAAM,CAAA;KACT,CAAA;IACnB,aAAa,UACZ,oBAAC,WAAW,OAAZ;KACE,OAAO,EAAE,OAAO,IAAI;KACpB,WAAU;KACV,cAAW;KACX,OAAO;KACP,gBAAgB,UAAkB;AAChC,qBAAe,OAAO,MAAM,CAAC;;KAE/B,cAAc;MACZ,IAAI,SAAS,KAAK,IAAI,aAAa,EAAE;AACrC,eAAS,KAAK,IAAI,QAAQ,QAAQ;AAClC,cAAQ,OAAO;AACf,qBAAe,OAAO;;KAExB,CAAA;IAEJ,oBAAC,WAAW,QAAZ;KACE,SAAQ;KACR,cAAW;KACX,UAAU,SAAS;KACnB,eAAe;MACb,MAAM,WAAW,KAAK,IAAI,OAAO,GAAG,QAAQ;AAC5C,cAAQ,SAAS;AACjB,qBAAe,SAAS;;eAG1B,oBAAC,gBAAD,EAAgB,MAAM,IAAM,CAAA;KACV,CAAA;IACnB,aAAa,UACZ,oBAAC,WAAW,QAAZ;KACE,SAAQ;KACR,cAAW;KACX,UAAU,SAAS;KACnB,eAAe;AACb,cAAQ,QAAQ;AAChB,qBAAe,QAAQ;;eAGzB,oBAAC,sBAAD,EAAsB,MAAM,IAAM,CAAA;KAChB,CAAA;IAEX;MACT,CAAA,CACF"}
1
+ {"version":3,"file":"pagination-DSY279Ta.js","names":[],"sources":["../src/components/pagination/pagination.tsx"],"sourcesContent":["import {\n CaretDoubleLeftIcon,\n CaretDoubleRightIcon,\n CaretLeftIcon,\n CaretRightIcon,\n} from \"@phosphor-icons/react\";\nimport { useEffect, useMemo, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { InputGroup } from \"../input\";\n\n/** Pagination controls variant definitions. */\nexport const SF_PAGINATION_VARIANTS = {\n controls: {\n full: {\n classes: \"\",\n description:\n \"Full pagination controls with first, previous, page input, next, and last buttons\",\n },\n simple: {\n classes: \"\",\n description:\n \"Simple pagination controls with only previous and next buttons\",\n },\n },\n} as const;\n\nexport type SFPaginationControls = keyof typeof SF_PAGINATION_VARIANTS.controls;\n\nexport const SF_PAGINATION_DEFAULT_VARIANTS = {\n controls: \"full\",\n} as const;\n\nexport interface SFPaginationVariantsProps {\n controls?: SFPaginationControls;\n}\n\nexport function paginationVariants({\n controls = SF_PAGINATION_DEFAULT_VARIANTS.controls,\n}: SFPaginationVariantsProps = {}) {\n return cn(\n \"flex items-center justify-between gap-2\",\n SF_PAGINATION_VARIANTS.controls[controls].classes\n );\n}\n\n/**\n * Pagination component props.\n *\n * @example\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />\n * <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} controls=\"simple\" />\n * ```\n */\nexport interface PaginationProps extends SFPaginationVariantsProps {\n /** Callback fired when the current page changes. */\n setPage: (page: number) => void;\n /**\n * Current page number (1-indexed).\n * @default 1\n */\n page?: number;\n /** Number of items displayed per page. */\n perPage?: number;\n /** Total number of items across all pages. */\n totalCount?: number;\n /** Method to provide custom pagination text */\n text?: (props: {\n page?: number;\n perPage?: number;\n totalCount?: number;\n pageShowingRange: string;\n }) => React.ReactNode;\n}\n\n/**\n * Page navigation controls with page count display.\n *\n * @example\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />\n * ```\n */\nexport function Pagination({\n page = 1,\n perPage,\n totalCount,\n setPage,\n text,\n controls = SF_PAGINATION_DEFAULT_VARIANTS.controls,\n}: PaginationProps) {\n const [editingPage, setEditingPage] = useState<number>(1);\n\n // Value of the input as its being modified to display in the input, eventually syncs with `pagination.page`\n useEffect(() => {\n setEditingPage(page);\n }, [page]);\n\n const pageShowingRange = useMemo(() => {\n let lower = page * (perPage ?? 1) - (perPage ?? 0) + 1;\n let upper = Math.min(page * (perPage ?? 0), totalCount ?? 0);\n\n if (Number.isNaN(lower)) lower = 0;\n if (Number.isNaN(upper)) upper = 0;\n\n return `${lower}-${upper}`;\n }, [page, perPage, totalCount]);\n\n const maxPage = useMemo(() => {\n return Math.ceil((totalCount ?? 1) / (perPage ?? 1));\n }, [totalCount, perPage]);\n\n const getPaginationText = () => {\n if (text) {\n return text({ page, perPage, totalCount, pageShowingRange });\n } else if (totalCount && totalCount > 0) {\n return `Showing ${pageShowingRange} of ${totalCount}`;\n }\n return null;\n };\n\n return (\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"grow text-sm text-sf-strong\">{getPaginationText()}</div>\n <div>\n <InputGroup focusMode=\"individual\">\n {controls === \"full\" && (\n <InputGroup.Button\n variant=\"secondary\"\n aria-label=\"First page\"\n disabled={page <= 1}\n onClick={() => {\n setPage(1);\n setEditingPage(1);\n }}\n >\n <CaretDoubleLeftIcon size={16} />\n </InputGroup.Button>\n )}\n <InputGroup.Button\n variant=\"secondary\"\n aria-label=\"Previous page\"\n disabled={page <= 1}\n onClick={() => {\n const previousPage = Math.max(page - 1, 1);\n setPage(previousPage);\n setEditingPage(previousPage);\n }}\n >\n <CaretLeftIcon size={16} />\n </InputGroup.Button>\n {controls === \"full\" && (\n <InputGroup.Input\n style={{ width: 50 }}\n className=\"text-center\"\n aria-label=\"Page number\"\n value={editingPage}\n onValueChange={(value: string) => {\n setEditingPage(Number(value));\n }}\n onBlur={() => {\n let number = Math.max(editingPage, 1);\n number = Math.min(number, maxPage);\n setPage(number);\n setEditingPage(number);\n }}\n />\n )}\n <InputGroup.Button\n variant=\"secondary\"\n aria-label=\"Next page\"\n disabled={page === maxPage}\n onClick={() => {\n const nextPage = Math.min(page + 1, maxPage);\n setPage(nextPage);\n setEditingPage(nextPage);\n }}\n >\n <CaretRightIcon size={16} />\n </InputGroup.Button>\n {controls === \"full\" && (\n <InputGroup.Button\n variant=\"secondary\"\n aria-label=\"Last page\"\n disabled={page === maxPage}\n onClick={() => {\n setPage(maxPage);\n setEditingPage(maxPage);\n }}\n >\n <CaretDoubleRightIcon size={16} />\n </InputGroup.Button>\n )}\n </InputGroup>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AA6BA,IAAa,iCAAiC,EAC5C,UAAU,OACZ;;;;;;;;;AAqDA,SAAgB,WAAW,EACzB,OAAO,GACP,SACA,YACA,SACA,MACA,WAAW,+BAA+B,YACxB;CAClB,MAAM,CAAC,aAAa,kBAAkB,SAAiB,CAAC;CAGxD,gBAAgB;EACd,eAAe,IAAI;CACrB,GAAG,CAAC,IAAI,CAAC;CAET,MAAM,mBAAmB,cAAc;EACrC,IAAI,QAAQ,QAAQ,WAAW,MAAM,WAAW,KAAK;EACrD,IAAI,QAAQ,KAAK,IAAI,QAAQ,WAAW,IAAI,cAAc,CAAC;EAE3D,IAAI,OAAO,MAAM,KAAK,GAAG,QAAQ;EACjC,IAAI,OAAO,MAAM,KAAK,GAAG,QAAQ;EAEjC,OAAO,GAAG,MAAM,GAAG;CACrB,GAAG;EAAC;EAAM;EAAS;CAAU,CAAC;CAE9B,MAAM,UAAU,cAAc;EAC5B,OAAO,KAAK,MAAM,cAAc,MAAM,WAAW,EAAE;CACrD,GAAG,CAAC,YAAY,OAAO,CAAC;CAExB,MAAM,0BAA0B;EAC9B,IAAI,MACF,OAAO,KAAK;GAAE;GAAM;GAAS;GAAY;EAAiB,CAAC;OACtD,IAAI,cAAc,aAAa,GACpC,OAAO,WAAW,iBAAiB,MAAM;EAE3C,OAAO;CACT;CAEA,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,OAAD;GAAK,WAAU;aAA+B,kBAAkB;EAAO,CAAA,GACvE,oBAAC,OAAD,EAAA,UACE,qBAAC,YAAD;GAAY,WAAU;aAAtB;IACG,aAAa,UACZ,oBAAC,WAAW,QAAZ;KACE,SAAQ;KACR,cAAW;KACX,UAAU,QAAQ;KAClB,eAAe;MACb,QAAQ,CAAC;MACT,eAAe,CAAC;KAClB;eAEA,oBAAC,qBAAD,EAAqB,MAAM,GAAK,CAAA;IACf,CAAA;IAErB,oBAAC,WAAW,QAAZ;KACE,SAAQ;KACR,cAAW;KACX,UAAU,QAAQ;KAClB,eAAe;MACb,MAAM,eAAe,KAAK,IAAI,OAAO,GAAG,CAAC;MACzC,QAAQ,YAAY;MACpB,eAAe,YAAY;KAC7B;eAEA,oBAAC,eAAD,EAAe,MAAM,GAAK,CAAA;IACT,CAAA;IAClB,aAAa,UACZ,oBAAC,WAAW,OAAZ;KACE,OAAO,EAAE,OAAO,GAAG;KACnB,WAAU;KACV,cAAW;KACX,OAAO;KACP,gBAAgB,UAAkB;MAChC,eAAe,OAAO,KAAK,CAAC;KAC9B;KACA,cAAc;MACZ,IAAI,SAAS,KAAK,IAAI,aAAa,CAAC;MACpC,SAAS,KAAK,IAAI,QAAQ,OAAO;MACjC,QAAQ,MAAM;MACd,eAAe,MAAM;KACvB;IACD,CAAA;IAEH,oBAAC,WAAW,QAAZ;KACE,SAAQ;KACR,cAAW;KACX,UAAU,SAAS;KACnB,eAAe;MACb,MAAM,WAAW,KAAK,IAAI,OAAO,GAAG,OAAO;MAC3C,QAAQ,QAAQ;MAChB,eAAe,QAAQ;KACzB;eAEA,oBAAC,gBAAD,EAAgB,MAAM,GAAK,CAAA;IACV,CAAA;IAClB,aAAa,UACZ,oBAAC,WAAW,QAAZ;KACE,SAAQ;KACR,cAAW;KACX,UAAU,SAAS;KACnB,eAAe;MACb,QAAQ,OAAO;MACf,eAAe,OAAO;KACxB;eAEA,oBAAC,sBAAD,EAAsB,MAAM,GAAK,CAAA;IAChB,CAAA;GAEX;KACT,CAAA,CACF;;AAET"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  import { Popover } from "@base-ui/react/popover";
5
5
  //#region src/components/popover/popover.tsx
@@ -144,4 +144,4 @@ var Popover$1 = Object.assign(PopoverRoot, {
144
144
  //#endregion
145
145
  export { PopoverRoot as a, SF_POPOVER_DEFAULT_VARIANTS as c, PopoverDescription as i, SF_POPOVER_VARIANTS as l, PopoverClose as n, PopoverTitle as o, PopoverContent as r, PopoverTrigger as s, Popover$1 as t };
146
146
 
147
- //# sourceMappingURL=popover-SRoJaCZr.js.map
147
+ //# sourceMappingURL=popover-BY-e9co1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"popover-SRoJaCZr.js","names":[],"sources":["../src/components/popover/popover.tsx"],"sourcesContent":["import { Popover as PopoverBase } from \"@base-ui/react/popover\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n/** Popover side variant definitions mapping positions to their Tailwind classes. */\nexport const SF_POPOVER_VARIANTS = {\n side: {\n top: {\n classes: \"\",\n description: \"Popover appears above the trigger\",\n },\n bottom: {\n classes: \"\",\n description: \"Popover appears below the trigger\",\n },\n left: {\n classes: \"\",\n description: \"Popover appears to the left of the trigger\",\n },\n right: {\n classes: \"\",\n description: \"Popover appears to the right of the trigger\",\n },\n },\n} as const;\n\nexport const SF_POPOVER_DEFAULT_VARIANTS = {\n side: \"bottom\",\n} as const;\n\n// Derived types from SF_POPOVER_VARIANTS\nexport type SFPopoverSide = keyof typeof SF_POPOVER_VARIANTS.side;\n\nexport interface SFPopoverVariantsProps {\n /**\n * Which side of the trigger the popover appears on.\n * - `\"top\"` — Above the trigger\n * - `\"bottom\"` — Below the trigger\n * - `\"left\"` — Left of the trigger\n * - `\"right\"` — Right of the trigger\n * @default \"bottom\"\n */\n side?: SFPopoverSide;\n}\n\n// ============================================================================\n// Popover Root\n// ============================================================================\n\ntype BasePopoverRootProps = ComponentPropsWithoutRef<typeof PopoverBase.Root>;\n\nexport type PopoverRootProps = BasePopoverRootProps;\n\nfunction PopoverRoot({ children, ...props }: PopoverRootProps) {\n return <PopoverBase.Root {...props}>{children}</PopoverBase.Root>;\n}\n\nPopoverRoot.displayName = \"Popover\";\n\n// ============================================================================\n// Popover Trigger\n// ============================================================================\n\ntype BasePopoverTriggerProps = ComponentPropsWithoutRef<\n typeof PopoverBase.Trigger\n>;\n\nexport type PopoverTriggerProps = BasePopoverTriggerProps & {\n /** When true, the trigger element will be the child element */\n asChild?: boolean;\n};\n\nfunction PopoverTrigger({\n children,\n className,\n asChild,\n ...props\n}: PopoverTriggerProps) {\n return (\n <PopoverBase.Trigger\n className={className}\n render={\n asChild ? (children as BasePopoverTriggerProps[\"render\"]) : undefined\n }\n {...props}\n >\n {asChild ? undefined : children}\n </PopoverBase.Trigger>\n );\n}\n\nPopoverTrigger.displayName = \"Popover.Trigger\";\n\n// ============================================================================\n// Popover Content\n// ============================================================================\n\n/** Alignment options for popover positioning */\ntype PopoverAlign = \"start\" | \"center\" | \"end\";\n\n/**\n * Popover content panel props.\n *\n * @example\n * ```tsx\n * <Popover.Content side=\"top\" align=\"start\" sideOffset={12}>\n * <p>Popover body</p>\n * </Popover.Content>\n * ```\n */\nexport type PopoverContentProps = SFPopoverVariantsProps & {\n /**\n * How to align the popover relative to the trigger.\n * @default \"center\"\n */\n align?: PopoverAlign;\n /**\n * Distance between the trigger and the popover in pixels.\n * @default 8\n */\n sideOffset?: number;\n /**\n * Additional offset along the alignment axis in pixels.\n * @default 0\n */\n alignOffset?: number;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** Content to render inside the popover. */\n children?: ReactNode;\n};\n\nfunction PopoverContent({\n children,\n side = SF_POPOVER_DEFAULT_VARIANTS.side,\n align = \"center\",\n sideOffset = 8,\n alignOffset = 0,\n className,\n}: PopoverContentProps) {\n return (\n <PopoverBase.Portal>\n <PopoverBase.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <PopoverBase.Popup\n className={cn(\n \"flex origin-(--transform-origin) flex-col rounded-lg bg-sf-elevated px-4 py-3 text-sm text-sf-default\",\n \"shadow-lg shadow-sf-tip-shadow outline outline-sf-fill\",\n \"transition-[transform,scale,opacity] duration-150\",\n \"data-starting-style:scale-90 data-starting-style:opacity-0\",\n \"data-ending-style:scale-90 data-ending-style:opacity-0\",\n \"data-instant:duration-0\",\n \"sf-popover-popup\",\n className\n )}\n >\n <PopoverBase.Arrow\n className={cn(\n \"flex\",\n \"data-[side=bottom]:-top-2\",\n \"data-[side=left]:right-[-13px] data-[side=left]:rotate-90\",\n \"data-[side=right]:left-[-13px] data-[side=right]:-rotate-90\",\n \"data-[side=top]:-bottom-2 data-[side=top]:rotate-180\"\n )}\n >\n <ArrowSvg />\n </PopoverBase.Arrow>\n {children}\n </PopoverBase.Popup>\n </PopoverBase.Positioner>\n </PopoverBase.Portal>\n );\n}\n\nPopoverContent.displayName = \"Popover.Content\";\n\n// ============================================================================\n// Popover Title\n// ============================================================================\n\ntype BasePopoverTitleProps = ComponentPropsWithoutRef<typeof PopoverBase.Title>;\n\nexport type PopoverTitleProps = BasePopoverTitleProps;\n\nfunction PopoverTitle({ className, ...props }: PopoverTitleProps) {\n return (\n <PopoverBase.Title\n className={cn(\"m-0 text-base leading-6 font-medium\", className)}\n {...props}\n />\n );\n}\n\nPopoverTitle.displayName = \"Popover.Title\";\n\n// ============================================================================\n// Popover Description\n// ============================================================================\n\ntype BasePopoverDescriptionProps = ComponentPropsWithoutRef<\n typeof PopoverBase.Description\n>;\n\nexport type PopoverDescriptionProps = BasePopoverDescriptionProps;\n\nfunction PopoverDescription({ className, ...props }: PopoverDescriptionProps) {\n return (\n <PopoverBase.Description\n className={cn(\"m-0 text-base leading-6 text-sf-subtle\", className)}\n {...props}\n />\n );\n}\n\nPopoverDescription.displayName = \"Popover.Description\";\n\n// ============================================================================\n// Popover Close\n// ============================================================================\n\ntype BasePopoverCloseProps = ComponentPropsWithoutRef<typeof PopoverBase.Close>;\n\nexport type PopoverCloseProps = BasePopoverCloseProps & {\n /** When true, the close element will be the child element */\n asChild?: boolean;\n};\n\nfunction PopoverClose({\n children,\n className,\n asChild,\n ...props\n}: PopoverCloseProps) {\n return (\n <PopoverBase.Close\n className={className}\n render={\n asChild ? (children as BasePopoverCloseProps[\"render\"]) : undefined\n }\n {...props}\n >\n {asChild ? undefined : children}\n </PopoverBase.Close>\n );\n}\n\nPopoverClose.displayName = \"Popover.Close\";\n\n// ============================================================================\n// Arrow SVG\n// ============================================================================\n\n/**\n * Arrow SVG with three paths for proper border rendering in both light and dark modes.\n * This approach matches Base UI's popover/tooltip implementation.\n *\n * The three paths are:\n * 1. ArrowFill - The main arrow body, matches popover background\n * 2. ArrowOuterStroke - Border visible in light mode only (transparent in dark)\n * 3. ArrowInnerStroke - Border visible in dark mode only (transparent in light)\n *\n * This is necessary because the outer and inner stroke paths have different geometries,\n * and using both ensures the arrow border aligns perfectly with the popover's outline\n * in both color modes.\n *\n * @see https://base-ui.com/react/components/popover\n */\nfunction ArrowSvg(props: React.ComponentProps<\"svg\">) {\n return (\n <svg width=\"20\" height=\"10\" viewBox=\"0 0 20 10\" fill=\"none\" {...props}>\n <path\n d=\"M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z\"\n className=\"fill-sf-elevated\"\n />\n <path\n d=\"M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z\"\n className=\"fill-sf-tip-shadow\"\n />\n <path\n d=\"M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z\"\n className=\"fill-sf-tip-stroke\"\n />\n </svg>\n );\n}\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\n/**\n * Popover component for displaying accessible popup content anchored to a trigger.\n *\n * @example\n * ```tsx\n * <Popover>\n * <Popover.Trigger asChild>\n * <Button>Open</Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <Popover.Title>Notifications</Popover.Title>\n * <Popover.Description>You are all caught up!</Popover.Description>\n * </Popover.Content>\n * </Popover>\n * ```\n *\n * @see https://base-ui.com/react/components/popover\n */\nexport const Popover = Object.assign(PopoverRoot, {\n Trigger: PopoverTrigger,\n Content: PopoverContent,\n Title: PopoverTitle,\n Description: PopoverDescription,\n Close: PopoverClose,\n});\n\n// Export sub-components for direct access and type inference\nexport {\n PopoverRoot,\n PopoverTrigger,\n PopoverContent,\n PopoverTitle,\n PopoverDescription,\n PopoverClose,\n};\n"],"mappings":";;;;;;AAMA,IAAa,sBAAsB,EACjC,MAAM;CACJ,KAAK;EACH,SAAS;EACT,aAAa;EACd;CACD,QAAQ;EACN,SAAS;EACT,aAAa;EACd;CACD,MAAM;EACJ,SAAS;EACT,aAAa;EACd;CACD,OAAO;EACL,SAAS;EACT,aAAa;EACd;CACF,EACF;AAED,IAAa,8BAA8B,EACzC,MAAM,UACP;AAyBD,SAAS,YAAY,EAAE,UAAU,GAAG,SAA2B;AAC7D,QAAO,oBAAC,QAAY,MAAb;EAAkB,GAAI;EAAQ;EAA4B,CAAA;;AAGnE,YAAY,cAAc;AAe1B,SAAS,eAAe,EACtB,UACA,WACA,SACA,GAAG,SACmB;AACtB,QACE,oBAAC,QAAY,SAAb;EACa;EACX,QACE,UAAW,WAAiD,KAAA;EAE9D,GAAI;YAEH,UAAU,KAAA,IAAY;EACH,CAAA;;AAI1B,eAAe,cAAc;AAyC7B,SAAS,eAAe,EACtB,UACA,OAAO,4BAA4B,MACnC,QAAQ,UACR,aAAa,GACb,cAAc,GACd,aACsB;AACtB,QACE,oBAAC,QAAY,QAAb,EAAA,UACE,oBAAC,QAAY,YAAb;EACS;EACM;EACP;EACM;YAEZ,qBAAC,QAAY,OAAb;GACE,WAAW,GACT,yGACA,0DACA,qDACA,8DACA,0DACA,2BACA,oBACA,UACD;aAVH,CAYE,oBAAC,QAAY,OAAb;IACE,WAAW,GACT,QACA,6BACA,6DACA,+DACA,uDACD;cAED,oBAAC,UAAD,EAAY,CAAA;IACM,CAAA,EACnB,SACiB;;EACG,CAAA,EACN,CAAA;;AAIzB,eAAe,cAAc;AAU7B,SAAS,aAAa,EAAE,WAAW,GAAG,SAA4B;AAChE,QACE,oBAAC,QAAY,OAAb;EACE,WAAW,GAAG,uCAAuC,UAAU;EAC/D,GAAI;EACJ,CAAA;;AAIN,aAAa,cAAc;AAY3B,SAAS,mBAAmB,EAAE,WAAW,GAAG,SAAkC;AAC5E,QACE,oBAAC,QAAY,aAAb;EACE,WAAW,GAAG,0CAA0C,UAAU;EAClE,GAAI;EACJ,CAAA;;AAIN,mBAAmB,cAAc;AAajC,SAAS,aAAa,EACpB,UACA,WACA,SACA,GAAG,SACiB;AACpB,QACE,oBAAC,QAAY,OAAb;EACa;EACX,QACE,UAAW,WAA+C,KAAA;EAE5D,GAAI;YAEH,UAAU,KAAA,IAAY;EACL,CAAA;;AAIxB,aAAa,cAAc;;;;;;;;;;;;;;;;AAqB3B,SAAS,SAAS,OAAoC;AACpD,QACE,qBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EAAO,GAAI;YAAhE;GACE,oBAAC,QAAD;IACE,GAAE;IACF,WAAU;IACV,CAAA;GACF,oBAAC,QAAD;IACE,GAAE;IACF,WAAU;IACV,CAAA;GACF,oBAAC,QAAD;IACE,GAAE;IACF,WAAU;IACV,CAAA;GACE;;;;;;;;;;;;;;;;;;;;;AA0BV,IAAa,YAAU,OAAO,OAAO,aAAa;CAChD,SAAS;CACT,SAAS;CACT,OAAO;CACP,aAAa;CACb,OAAO;CACR,CAAC"}
1
+ {"version":3,"file":"popover-BY-e9co1.js","names":[],"sources":["../src/components/popover/popover.tsx"],"sourcesContent":["import { Popover as PopoverBase } from \"@base-ui/react/popover\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n/** Popover side variant definitions mapping positions to their Tailwind classes. */\nexport const SF_POPOVER_VARIANTS = {\n side: {\n top: {\n classes: \"\",\n description: \"Popover appears above the trigger\",\n },\n bottom: {\n classes: \"\",\n description: \"Popover appears below the trigger\",\n },\n left: {\n classes: \"\",\n description: \"Popover appears to the left of the trigger\",\n },\n right: {\n classes: \"\",\n description: \"Popover appears to the right of the trigger\",\n },\n },\n} as const;\n\nexport const SF_POPOVER_DEFAULT_VARIANTS = {\n side: \"bottom\",\n} as const;\n\n// Derived types from SF_POPOVER_VARIANTS\nexport type SFPopoverSide = keyof typeof SF_POPOVER_VARIANTS.side;\n\nexport interface SFPopoverVariantsProps {\n /**\n * Which side of the trigger the popover appears on.\n * - `\"top\"` — Above the trigger\n * - `\"bottom\"` — Below the trigger\n * - `\"left\"` — Left of the trigger\n * - `\"right\"` — Right of the trigger\n * @default \"bottom\"\n */\n side?: SFPopoverSide;\n}\n\n// ============================================================================\n// Popover Root\n// ============================================================================\n\ntype BasePopoverRootProps = ComponentPropsWithoutRef<typeof PopoverBase.Root>;\n\nexport type PopoverRootProps = BasePopoverRootProps;\n\nfunction PopoverRoot({ children, ...props }: PopoverRootProps) {\n return <PopoverBase.Root {...props}>{children}</PopoverBase.Root>;\n}\n\nPopoverRoot.displayName = \"Popover\";\n\n// ============================================================================\n// Popover Trigger\n// ============================================================================\n\ntype BasePopoverTriggerProps = ComponentPropsWithoutRef<\n typeof PopoverBase.Trigger\n>;\n\nexport type PopoverTriggerProps = BasePopoverTriggerProps & {\n /** When true, the trigger element will be the child element */\n asChild?: boolean;\n};\n\nfunction PopoverTrigger({\n children,\n className,\n asChild,\n ...props\n}: PopoverTriggerProps) {\n return (\n <PopoverBase.Trigger\n className={className}\n render={\n asChild ? (children as BasePopoverTriggerProps[\"render\"]) : undefined\n }\n {...props}\n >\n {asChild ? undefined : children}\n </PopoverBase.Trigger>\n );\n}\n\nPopoverTrigger.displayName = \"Popover.Trigger\";\n\n// ============================================================================\n// Popover Content\n// ============================================================================\n\n/** Alignment options for popover positioning */\ntype PopoverAlign = \"start\" | \"center\" | \"end\";\n\n/**\n * Popover content panel props.\n *\n * @example\n * ```tsx\n * <Popover.Content side=\"top\" align=\"start\" sideOffset={12}>\n * <p>Popover body</p>\n * </Popover.Content>\n * ```\n */\nexport type PopoverContentProps = SFPopoverVariantsProps & {\n /**\n * How to align the popover relative to the trigger.\n * @default \"center\"\n */\n align?: PopoverAlign;\n /**\n * Distance between the trigger and the popover in pixels.\n * @default 8\n */\n sideOffset?: number;\n /**\n * Additional offset along the alignment axis in pixels.\n * @default 0\n */\n alignOffset?: number;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** Content to render inside the popover. */\n children?: ReactNode;\n};\n\nfunction PopoverContent({\n children,\n side = SF_POPOVER_DEFAULT_VARIANTS.side,\n align = \"center\",\n sideOffset = 8,\n alignOffset = 0,\n className,\n}: PopoverContentProps) {\n return (\n <PopoverBase.Portal>\n <PopoverBase.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <PopoverBase.Popup\n className={cn(\n \"flex origin-(--transform-origin) flex-col rounded-lg bg-sf-elevated px-4 py-3 text-sm text-sf-default\",\n \"shadow-lg shadow-sf-tip-shadow outline outline-sf-fill\",\n \"transition-[transform,scale,opacity] duration-150\",\n \"data-starting-style:scale-90 data-starting-style:opacity-0\",\n \"data-ending-style:scale-90 data-ending-style:opacity-0\",\n \"data-instant:duration-0\",\n \"sf-popover-popup\",\n className\n )}\n >\n <PopoverBase.Arrow\n className={cn(\n \"flex\",\n \"data-[side=bottom]:-top-2\",\n \"data-[side=left]:right-[-13px] data-[side=left]:rotate-90\",\n \"data-[side=right]:left-[-13px] data-[side=right]:-rotate-90\",\n \"data-[side=top]:-bottom-2 data-[side=top]:rotate-180\"\n )}\n >\n <ArrowSvg />\n </PopoverBase.Arrow>\n {children}\n </PopoverBase.Popup>\n </PopoverBase.Positioner>\n </PopoverBase.Portal>\n );\n}\n\nPopoverContent.displayName = \"Popover.Content\";\n\n// ============================================================================\n// Popover Title\n// ============================================================================\n\ntype BasePopoverTitleProps = ComponentPropsWithoutRef<typeof PopoverBase.Title>;\n\nexport type PopoverTitleProps = BasePopoverTitleProps;\n\nfunction PopoverTitle({ className, ...props }: PopoverTitleProps) {\n return (\n <PopoverBase.Title\n className={cn(\"m-0 text-base leading-6 font-medium\", className)}\n {...props}\n />\n );\n}\n\nPopoverTitle.displayName = \"Popover.Title\";\n\n// ============================================================================\n// Popover Description\n// ============================================================================\n\ntype BasePopoverDescriptionProps = ComponentPropsWithoutRef<\n typeof PopoverBase.Description\n>;\n\nexport type PopoverDescriptionProps = BasePopoverDescriptionProps;\n\nfunction PopoverDescription({ className, ...props }: PopoverDescriptionProps) {\n return (\n <PopoverBase.Description\n className={cn(\"m-0 text-base leading-6 text-sf-subtle\", className)}\n {...props}\n />\n );\n}\n\nPopoverDescription.displayName = \"Popover.Description\";\n\n// ============================================================================\n// Popover Close\n// ============================================================================\n\ntype BasePopoverCloseProps = ComponentPropsWithoutRef<typeof PopoverBase.Close>;\n\nexport type PopoverCloseProps = BasePopoverCloseProps & {\n /** When true, the close element will be the child element */\n asChild?: boolean;\n};\n\nfunction PopoverClose({\n children,\n className,\n asChild,\n ...props\n}: PopoverCloseProps) {\n return (\n <PopoverBase.Close\n className={className}\n render={\n asChild ? (children as BasePopoverCloseProps[\"render\"]) : undefined\n }\n {...props}\n >\n {asChild ? undefined : children}\n </PopoverBase.Close>\n );\n}\n\nPopoverClose.displayName = \"Popover.Close\";\n\n// ============================================================================\n// Arrow SVG\n// ============================================================================\n\n/**\n * Arrow SVG with three paths for proper border rendering in both light and dark modes.\n * This approach matches Base UI's popover/tooltip implementation.\n *\n * The three paths are:\n * 1. ArrowFill - The main arrow body, matches popover background\n * 2. ArrowOuterStroke - Border visible in light mode only (transparent in dark)\n * 3. ArrowInnerStroke - Border visible in dark mode only (transparent in light)\n *\n * This is necessary because the outer and inner stroke paths have different geometries,\n * and using both ensures the arrow border aligns perfectly with the popover's outline\n * in both color modes.\n *\n * @see https://base-ui.com/react/components/popover\n */\nfunction ArrowSvg(props: React.ComponentProps<\"svg\">) {\n return (\n <svg width=\"20\" height=\"10\" viewBox=\"0 0 20 10\" fill=\"none\" {...props}>\n <path\n d=\"M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z\"\n className=\"fill-sf-elevated\"\n />\n <path\n d=\"M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z\"\n className=\"fill-sf-tip-shadow\"\n />\n <path\n d=\"M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z\"\n className=\"fill-sf-tip-stroke\"\n />\n </svg>\n );\n}\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\n/**\n * Popover component for displaying accessible popup content anchored to a trigger.\n *\n * @example\n * ```tsx\n * <Popover>\n * <Popover.Trigger asChild>\n * <Button>Open</Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <Popover.Title>Notifications</Popover.Title>\n * <Popover.Description>You are all caught up!</Popover.Description>\n * </Popover.Content>\n * </Popover>\n * ```\n *\n * @see https://base-ui.com/react/components/popover\n */\nexport const Popover = Object.assign(PopoverRoot, {\n Trigger: PopoverTrigger,\n Content: PopoverContent,\n Title: PopoverTitle,\n Description: PopoverDescription,\n Close: PopoverClose,\n});\n\n// Export sub-components for direct access and type inference\nexport {\n PopoverRoot,\n PopoverTrigger,\n PopoverContent,\n PopoverTitle,\n PopoverDescription,\n PopoverClose,\n};\n"],"mappings":";;;;;;AAMA,IAAa,sBAAsB,EACjC,MAAM;CACJ,KAAK;EACH,SAAS;EACT,aAAa;CACf;CACA,QAAQ;EACN,SAAS;EACT,aAAa;CACf;CACA,MAAM;EACJ,SAAS;EACT,aAAa;CACf;CACA,OAAO;EACL,SAAS;EACT,aAAa;CACf;AACF,EACF;AAEA,IAAa,8BAA8B,EACzC,MAAM,SACR;AAyBA,SAAS,YAAY,EAAE,UAAU,GAAG,SAA2B;CAC7D,OAAO,oBAAC,QAAY,MAAb;EAAkB,GAAI;EAAQ;CAA2B,CAAA;AAClE;AAEA,YAAY,cAAc;AAe1B,SAAS,eAAe,EACtB,UACA,WACA,SACA,GAAG,SACmB;CACtB,OACE,oBAAC,QAAY,SAAb;EACa;EACX,QACE,UAAW,WAAiD,KAAA;EAE9D,GAAI;YAEH,UAAU,KAAA,IAAY;CACJ,CAAA;AAEzB;AAEA,eAAe,cAAc;AAyC7B,SAAS,eAAe,EACtB,UACA,OAAO,4BAA4B,MACnC,QAAQ,UACR,aAAa,GACb,cAAc,GACd,aACsB;CACtB,OACE,oBAAC,QAAY,QAAb,EAAA,UACE,oBAAC,QAAY,YAAb;EACS;EACM;EACP;EACM;YAEZ,qBAAC,QAAY,OAAb;GACE,WAAW,GACT,yGACA,0DACA,qDACA,8DACA,0DACA,2BACA,oBACA,SACF;aAVF,CAYE,oBAAC,QAAY,OAAb;IACE,WAAW,GACT,QACA,6BACA,6DACA,+DACA,sDACF;cAEA,oBAAC,UAAD,CAAW,CAAA;GACM,CAAA,GAClB,QACgB;;CACG,CAAA,EACN,CAAA;AAExB;AAEA,eAAe,cAAc;AAU7B,SAAS,aAAa,EAAE,WAAW,GAAG,SAA4B;CAChE,OACE,oBAAC,QAAY,OAAb;EACE,WAAW,GAAG,uCAAuC,SAAS;EAC9D,GAAI;CACL,CAAA;AAEL;AAEA,aAAa,cAAc;AAY3B,SAAS,mBAAmB,EAAE,WAAW,GAAG,SAAkC;CAC5E,OACE,oBAAC,QAAY,aAAb;EACE,WAAW,GAAG,0CAA0C,SAAS;EACjE,GAAI;CACL,CAAA;AAEL;AAEA,mBAAmB,cAAc;AAajC,SAAS,aAAa,EACpB,UACA,WACA,SACA,GAAG,SACiB;CACpB,OACE,oBAAC,QAAY,OAAb;EACa;EACX,QACE,UAAW,WAA+C,KAAA;EAE5D,GAAI;YAEH,UAAU,KAAA,IAAY;CACN,CAAA;AAEvB;AAEA,aAAa,cAAc;;;;;;;;;;;;;;;;AAqB3B,SAAS,SAAS,OAAoC;CACpD,OACE,qBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EAAO,GAAI;YAAhE;GACE,oBAAC,QAAD;IACE,GAAE;IACF,WAAU;GACX,CAAA;GACD,oBAAC,QAAD;IACE,GAAE;IACF,WAAU;GACX,CAAA;GACD,oBAAC,QAAD;IACE,GAAE;IACF,WAAU;GACX,CAAA;EACE;;AAET;;;;;;;;;;;;;;;;;;;AAwBA,IAAa,YAAU,OAAO,OAAO,aAAa;CAChD,SAAS;CACT,SAAS;CACT,OAAO;CACP,aAAa;CACb,OAAO;AACT,CAAC"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
3
  import { createContext, forwardRef, useContext } from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { Fieldset } from "@base-ui/react/fieldset";
@@ -98,4 +98,4 @@ var Radio$1 = {
98
98
  //#endregion
99
99
  export { radioVariants as a, SF_RADIO_VARIANTS as i, RadioGroup$1 as n, SF_RADIO_DEFAULT_VARIANTS as r, Radio$1 as t };
100
100
 
101
- //# sourceMappingURL=radio-BcwhwYNB.js.map
101
+ //# sourceMappingURL=radio-DZwL13j0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"radio-BcwhwYNB.js","names":[],"sources":["../src/components/radio/radio.tsx"],"sourcesContent":["import { Fieldset } from \"@base-ui/react/fieldset\";\nimport { Radio as BaseRadio } from \"@base-ui/react/radio\";\nimport { RadioGroup as BaseRadioGroup } from \"@base-ui/react/radio-group\";\nimport { forwardRef, createContext, useContext, type ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n/** Radio variant definitions mapping variant names to their Tailwind classes. */\nexport const SF_RADIO_VARIANTS = {\n variant: {\n default: {\n classes: \"ring-sf-interact\",\n description: \"Default radio appearance\",\n },\n error: {\n classes: \"ring-destructive\",\n description: \"Error state for validation failures\",\n },\n },\n} as const;\n\nexport const SF_RADIO_DEFAULT_VARIANTS = {\n variant: \"default\",\n} as const;\n\n// Derived types from SF_RADIO_VARIANTS\nexport type SFRadioVariant = keyof typeof SF_RADIO_VARIANTS.variant;\n\nexport interface SFRadioVariantsProps {\n /**\n * Visual variant.\n * - `\"default\"` — Standard radio appearance\n * - `\"error\"` — Error state for validation failures\n * @default \"default\"\n */\n variant?: SFRadioVariant;\n}\n\nexport function radioVariants({\n variant = SF_RADIO_DEFAULT_VARIANTS.variant,\n}: SFRadioVariantsProps = {}) {\n return cn(SF_RADIO_VARIANTS.variant[variant].classes);\n}\n\n// Legacy type alias for backwards compatibility\nexport type RadioVariant = SFRadioVariant;\n\n/** Position of the radio control relative to its label */\nexport type RadioControlPosition = \"start\" | \"end\";\n\n// Context for passing controlPosition from Group to Items\nconst RadioGroupContext = createContext<{\n controlPosition: RadioControlPosition;\n}>({\n controlPosition: \"start\",\n});\n\n/**\n * Radio group component props (with built-in Fieldset and RadioGroup)\n *\n * @example\n * // Basic usage\n * ```tsx\n * <Radio.Group legend=\"Notification preference\" defaultValue=\"email\">\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"SMS\" value=\"sms\" />\n * <Radio.Item label=\"Push\" value=\"push\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Horizontal layout\n * ```tsx\n * <Radio.Group legend=\"Size\" orientation=\"horizontal\" defaultValue=\"md\">\n * <Radio.Item label=\"Small\" value=\"sm\" />\n * <Radio.Item label=\"Medium\" value=\"md\" />\n * <Radio.Item label=\"Large\" value=\"lg\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // With error and description\n * ```tsx\n * <Radio.Group\n * legend=\"Payment method\"\n * error=\"Please select a payment method\"\n * description=\"Choose how you'd like to pay\"\n * >\n * <Radio.Item label=\"Credit Card\" value=\"card\" />\n * <Radio.Item label=\"PayPal\" value=\"paypal\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Controlled\n * ```tsx\n * const [value, setValue] = useState(\"email\");\n * <Radio.Group legend=\"Contact\" value={value} onValueChange={setValue}>\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"Phone\" value=\"phone\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Label before radio (controlPosition=\"end\")\n * ```tsx\n * <Radio.Group legend=\"Options\" controlPosition=\"end\" defaultValue=\"a\">\n * <Radio.Item label=\"Option A\" value=\"a\" />\n * <Radio.Item label=\"Option B\" value=\"b\" />\n * </Radio.Group>\n * ```\n */\nexport interface RadioGroupProps {\n /** Legend text for the group (required for accessibility) */\n legend: string;\n /** Child Radio.Item components */\n children: ReactNode;\n /** Layout direction of the radio items */\n orientation?: \"vertical\" | \"horizontal\";\n /** Error message for the group */\n error?: string;\n /** Helper text for the group */\n description?: ReactNode;\n /** Value of the radio that should be initially selected (uncontrolled) */\n defaultValue?: string;\n /** Value of the radio that should be selected (controlled) */\n value?: string;\n /** Event handler called when radio value changes */\n onValueChange?: (value: string) => void;\n /** Whether all radios in the group are disabled */\n disabled?: boolean;\n /** Position of radio control relative to label: \"start\" (default) puts radio before label, \"end\" puts label before radio */\n controlPosition?: RadioControlPosition;\n /** Form submission name for the radio group */\n name?: string;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Individual radio item within a group\n *\n * @example\n * ```tsx\n * <Radio.Item label=\"Option A\" value=\"a\" />\n * ```\n *\n * @example\n * // Disabled item\n * ```tsx\n * <Radio.Item label=\"Unavailable\" value=\"unavailable\" disabled />\n * ```\n */\nexport type RadioItemProps = {\n /** Visual variant: \"default\" or \"error\" for validation failures */\n variant?: RadioVariant;\n /** Label text displayed next to radio (required) */\n label: string;\n /** Value of the radio (required) */\n value: string;\n /** Additional CSS classes for the label wrapper */\n className?: string;\n /** Whether the radio is disabled */\n disabled?: boolean;\n};\n\n// Radio.Item for use within Radio.Group\nconst RadioItem = forwardRef<HTMLButtonElement, RadioItemProps>(\n ({ className, disabled, variant = \"default\", label, value }, ref) => {\n const { controlPosition } = useContext(RadioGroupContext);\n\n return (\n <label\n className={cn(\n \"group relative inline-flex items-center gap-2\",\n // \"start\" (default): radio before label\n // \"end\": label before radio using flex-row-reverse\n controlPosition === \"end\" && \"flex-row-reverse justify-end\",\n disabled ? \"cursor-not-allowed opacity-50\" : \"cursor-pointer\",\n className\n )}\n >\n <BaseRadio.Root\n ref={ref}\n value={value}\n disabled={disabled}\n className={cn(\n \"flex h-4 w-4 items-center justify-center rounded-full border-0 bg-sf-base ring\",\n variant === \"error\" ? \"ring-sf-danger\" : \"ring-sf-interact\",\n !disabled &&\n \"group-hover:ring-sf-ring focus-visible:ring-sf-ring focus-visible:outline-offset-3\",\n \"data-checked:bg-sf-contrast\"\n )}\n >\n <BaseRadio.Indicator className=\"flex items-center justify-center\">\n <span className=\"h-2 w-2 rounded-full bg-sf-base\" />\n </BaseRadio.Indicator>\n </BaseRadio.Root>\n <span className=\"text-base font-medium text-sf-default\">{label}</span>\n </label>\n );\n }\n);\n\nRadioItem.displayName = \"Radio.Item\";\n\n// Radio.Group with built-in Fieldset and RadioGroup\nfunction RadioGroup({\n legend,\n children,\n orientation = \"vertical\",\n error,\n description,\n defaultValue,\n value,\n onValueChange,\n disabled,\n controlPosition = \"start\",\n name,\n className,\n}: RadioGroupProps) {\n return (\n <RadioGroupContext.Provider value={{ controlPosition }}>\n <BaseRadioGroup\n defaultValue={defaultValue}\n value={value}\n onValueChange={(newValue) => onValueChange?.(newValue as string)}\n disabled={disabled}\n name={name}\n >\n <Fieldset.Root\n className={cn(\n \"flex flex-col gap-4 rounded-lg border border-sf-line p-4\",\n className\n )}\n >\n <Fieldset.Legend className=\"text-lg font-medium text-sf-default\">\n {legend}\n </Fieldset.Legend>\n <div\n className={cn(\n \"flex gap-2\",\n orientation === \"vertical\" ? \"flex-col\" : \"flex-row flex-wrap\"\n )}\n >\n {children}\n </div>\n {error && <p className=\"text-sm text-sf-danger\">{error}</p>}\n {description && (\n <p className=\"text-sm text-sf-subtle\">{description}</p>\n )}\n </Fieldset.Root>\n </BaseRadioGroup>\n </RadioGroupContext.Provider>\n );\n}\n\nRadioGroup.displayName = \"Radio.Group\";\n\n// Export RadioGroup directly for external usage\nexport { RadioGroup };\n\n/**\n * Radio — radio button group for single-select choices.\n *\n * Compound component: `Radio.Group` (with built-in Fieldset) and `Radio.Item`.\n * Built on `@base-ui/react/radio-group` + `@base-ui/react/radio`.\n *\n * @example\n * ```tsx\n * <Radio.Group legend=\"Notification preference\" defaultValue=\"email\">\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"SMS\" value=\"sms\" />\n * <Radio.Item label=\"Push\" value=\"push\" />\n * </Radio.Group>\n * ```\n */\nexport const Radio = {\n Item: RadioItem,\n Group: RadioGroup,\n};\n"],"mappings":";;;;;;;;;AAQA,IAAa,oBAAoB,EAC/B,SAAS;CACP,SAAS;EACP,SAAS;EACT,aAAa;EACd;CACD,OAAO;EACL,SAAS;EACT,aAAa;EACd;CACF,EACF;AAED,IAAa,4BAA4B,EACvC,SAAS,WACV;AAeD,SAAgB,cAAc,EAC5B,UAAU,0BAA0B,YACZ,EAAE,EAAE;AAC5B,QAAO,GAAG,kBAAkB,QAAQ,SAAS,QAAQ;;AAUvD,IAAM,oBAAoB,cAEvB,EACD,iBAAiB,SAClB,CAAC;AAgHF,IAAM,YAAY,YACf,EAAE,WAAW,UAAU,UAAU,WAAW,OAAO,SAAS,QAAQ;CACnE,MAAM,EAAE,oBAAoB,WAAW,kBAAkB;AAEzD,QACE,qBAAC,SAAD;EACE,WAAW,GACT,iDAGA,oBAAoB,SAAS,gCAC7B,WAAW,kCAAkC,kBAC7C,UACD;YARH,CAUE,oBAAC,MAAU,MAAX;GACO;GACE;GACG;GACV,WAAW,GACT,kFACA,YAAY,UAAU,mBAAmB,oBACzC,CAAC,YACC,sFACF,8BACD;aAED,oBAAC,MAAU,WAAX;IAAqB,WAAU;cAC7B,oBAAC,QAAD,EAAM,WAAU,mCAAoC,CAAA;IAChC,CAAA;GACP,CAAA,EACjB,oBAAC,QAAD;GAAM,WAAU;aAAyC;GAAa,CAAA,CAChE;;EAGb;AAED,UAAU,cAAc;AAGxB,SAAS,aAAW,EAClB,QACA,UACA,cAAc,YACd,OACA,aACA,cACA,OACA,eACA,UACA,kBAAkB,SAClB,MACA,aACkB;AAClB,QACE,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO,EAAE,iBAAiB;YACpD,oBAAC,YAAD;GACgB;GACP;GACP,gBAAgB,aAAa,gBAAgB,SAAmB;GACtD;GACJ;aAEN,qBAAC,SAAS,MAAV;IACE,WAAW,GACT,4DACA,UACD;cAJH;KAME,oBAAC,SAAS,QAAV;MAAiB,WAAU;gBACxB;MACe,CAAA;KAClB,oBAAC,OAAD;MACE,WAAW,GACT,cACA,gBAAgB,aAAa,aAAa,qBAC3C;MAEA;MACG,CAAA;KACL,SAAS,oBAAC,KAAD;MAAG,WAAU;gBAA0B;MAAU,CAAA;KAC1D,eACC,oBAAC,KAAD;MAAG,WAAU;gBAA0B;MAAgB,CAAA;KAE3C;;GACD,CAAA;EACU,CAAA;;AAIjC,aAAW,cAAc;;;;;;;;;;;;;;;;AAoBzB,IAAa,UAAQ;CACnB,MAAM;CACN,OAAO;CACR"}
1
+ {"version":3,"file":"radio-DZwL13j0.js","names":[],"sources":["../src/components/radio/radio.tsx"],"sourcesContent":["import { Fieldset } from \"@base-ui/react/fieldset\";\nimport { Radio as BaseRadio } from \"@base-ui/react/radio\";\nimport { RadioGroup as BaseRadioGroup } from \"@base-ui/react/radio-group\";\nimport { forwardRef, createContext, useContext, type ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n/** Radio variant definitions mapping variant names to their Tailwind classes. */\nexport const SF_RADIO_VARIANTS = {\n variant: {\n default: {\n classes: \"ring-sf-interact\",\n description: \"Default radio appearance\",\n },\n error: {\n classes: \"ring-destructive\",\n description: \"Error state for validation failures\",\n },\n },\n} as const;\n\nexport const SF_RADIO_DEFAULT_VARIANTS = {\n variant: \"default\",\n} as const;\n\n// Derived types from SF_RADIO_VARIANTS\nexport type SFRadioVariant = keyof typeof SF_RADIO_VARIANTS.variant;\n\nexport interface SFRadioVariantsProps {\n /**\n * Visual variant.\n * - `\"default\"` — Standard radio appearance\n * - `\"error\"` — Error state for validation failures\n * @default \"default\"\n */\n variant?: SFRadioVariant;\n}\n\nexport function radioVariants({\n variant = SF_RADIO_DEFAULT_VARIANTS.variant,\n}: SFRadioVariantsProps = {}) {\n return cn(SF_RADIO_VARIANTS.variant[variant].classes);\n}\n\n// Legacy type alias for backwards compatibility\nexport type RadioVariant = SFRadioVariant;\n\n/** Position of the radio control relative to its label */\nexport type RadioControlPosition = \"start\" | \"end\";\n\n// Context for passing controlPosition from Group to Items\nconst RadioGroupContext = createContext<{\n controlPosition: RadioControlPosition;\n}>({\n controlPosition: \"start\",\n});\n\n/**\n * Radio group component props (with built-in Fieldset and RadioGroup)\n *\n * @example\n * // Basic usage\n * ```tsx\n * <Radio.Group legend=\"Notification preference\" defaultValue=\"email\">\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"SMS\" value=\"sms\" />\n * <Radio.Item label=\"Push\" value=\"push\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Horizontal layout\n * ```tsx\n * <Radio.Group legend=\"Size\" orientation=\"horizontal\" defaultValue=\"md\">\n * <Radio.Item label=\"Small\" value=\"sm\" />\n * <Radio.Item label=\"Medium\" value=\"md\" />\n * <Radio.Item label=\"Large\" value=\"lg\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // With error and description\n * ```tsx\n * <Radio.Group\n * legend=\"Payment method\"\n * error=\"Please select a payment method\"\n * description=\"Choose how you'd like to pay\"\n * >\n * <Radio.Item label=\"Credit Card\" value=\"card\" />\n * <Radio.Item label=\"PayPal\" value=\"paypal\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Controlled\n * ```tsx\n * const [value, setValue] = useState(\"email\");\n * <Radio.Group legend=\"Contact\" value={value} onValueChange={setValue}>\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"Phone\" value=\"phone\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Label before radio (controlPosition=\"end\")\n * ```tsx\n * <Radio.Group legend=\"Options\" controlPosition=\"end\" defaultValue=\"a\">\n * <Radio.Item label=\"Option A\" value=\"a\" />\n * <Radio.Item label=\"Option B\" value=\"b\" />\n * </Radio.Group>\n * ```\n */\nexport interface RadioGroupProps {\n /** Legend text for the group (required for accessibility) */\n legend: string;\n /** Child Radio.Item components */\n children: ReactNode;\n /** Layout direction of the radio items */\n orientation?: \"vertical\" | \"horizontal\";\n /** Error message for the group */\n error?: string;\n /** Helper text for the group */\n description?: ReactNode;\n /** Value of the radio that should be initially selected (uncontrolled) */\n defaultValue?: string;\n /** Value of the radio that should be selected (controlled) */\n value?: string;\n /** Event handler called when radio value changes */\n onValueChange?: (value: string) => void;\n /** Whether all radios in the group are disabled */\n disabled?: boolean;\n /** Position of radio control relative to label: \"start\" (default) puts radio before label, \"end\" puts label before radio */\n controlPosition?: RadioControlPosition;\n /** Form submission name for the radio group */\n name?: string;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Individual radio item within a group\n *\n * @example\n * ```tsx\n * <Radio.Item label=\"Option A\" value=\"a\" />\n * ```\n *\n * @example\n * // Disabled item\n * ```tsx\n * <Radio.Item label=\"Unavailable\" value=\"unavailable\" disabled />\n * ```\n */\nexport type RadioItemProps = {\n /** Visual variant: \"default\" or \"error\" for validation failures */\n variant?: RadioVariant;\n /** Label text displayed next to radio (required) */\n label: string;\n /** Value of the radio (required) */\n value: string;\n /** Additional CSS classes for the label wrapper */\n className?: string;\n /** Whether the radio is disabled */\n disabled?: boolean;\n};\n\n// Radio.Item for use within Radio.Group\nconst RadioItem = forwardRef<HTMLButtonElement, RadioItemProps>(\n ({ className, disabled, variant = \"default\", label, value }, ref) => {\n const { controlPosition } = useContext(RadioGroupContext);\n\n return (\n <label\n className={cn(\n \"group relative inline-flex items-center gap-2\",\n // \"start\" (default): radio before label\n // \"end\": label before radio using flex-row-reverse\n controlPosition === \"end\" && \"flex-row-reverse justify-end\",\n disabled ? \"cursor-not-allowed opacity-50\" : \"cursor-pointer\",\n className\n )}\n >\n <BaseRadio.Root\n ref={ref}\n value={value}\n disabled={disabled}\n className={cn(\n \"flex h-4 w-4 items-center justify-center rounded-full border-0 bg-sf-base ring\",\n variant === \"error\" ? \"ring-sf-danger\" : \"ring-sf-interact\",\n !disabled &&\n \"group-hover:ring-sf-ring focus-visible:ring-sf-ring focus-visible:outline-offset-3\",\n \"data-checked:bg-sf-contrast\"\n )}\n >\n <BaseRadio.Indicator className=\"flex items-center justify-center\">\n <span className=\"h-2 w-2 rounded-full bg-sf-base\" />\n </BaseRadio.Indicator>\n </BaseRadio.Root>\n <span className=\"text-base font-medium text-sf-default\">{label}</span>\n </label>\n );\n }\n);\n\nRadioItem.displayName = \"Radio.Item\";\n\n// Radio.Group with built-in Fieldset and RadioGroup\nfunction RadioGroup({\n legend,\n children,\n orientation = \"vertical\",\n error,\n description,\n defaultValue,\n value,\n onValueChange,\n disabled,\n controlPosition = \"start\",\n name,\n className,\n}: RadioGroupProps) {\n return (\n <RadioGroupContext.Provider value={{ controlPosition }}>\n <BaseRadioGroup\n defaultValue={defaultValue}\n value={value}\n onValueChange={(newValue) => onValueChange?.(newValue as string)}\n disabled={disabled}\n name={name}\n >\n <Fieldset.Root\n className={cn(\n \"flex flex-col gap-4 rounded-lg border border-sf-line p-4\",\n className\n )}\n >\n <Fieldset.Legend className=\"text-lg font-medium text-sf-default\">\n {legend}\n </Fieldset.Legend>\n <div\n className={cn(\n \"flex gap-2\",\n orientation === \"vertical\" ? \"flex-col\" : \"flex-row flex-wrap\"\n )}\n >\n {children}\n </div>\n {error && <p className=\"text-sm text-sf-danger\">{error}</p>}\n {description && (\n <p className=\"text-sm text-sf-subtle\">{description}</p>\n )}\n </Fieldset.Root>\n </BaseRadioGroup>\n </RadioGroupContext.Provider>\n );\n}\n\nRadioGroup.displayName = \"Radio.Group\";\n\n// Export RadioGroup directly for external usage\nexport { RadioGroup };\n\n/**\n * Radio — radio button group for single-select choices.\n *\n * Compound component: `Radio.Group` (with built-in Fieldset) and `Radio.Item`.\n * Built on `@base-ui/react/radio-group` + `@base-ui/react/radio`.\n *\n * @example\n * ```tsx\n * <Radio.Group legend=\"Notification preference\" defaultValue=\"email\">\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"SMS\" value=\"sms\" />\n * <Radio.Item label=\"Push\" value=\"push\" />\n * </Radio.Group>\n * ```\n */\nexport const Radio = {\n Item: RadioItem,\n Group: RadioGroup,\n};\n"],"mappings":";;;;;;;;;AAQA,IAAa,oBAAoB,EAC/B,SAAS;CACP,SAAS;EACP,SAAS;EACT,aAAa;CACf;CACA,OAAO;EACL,SAAS;EACT,aAAa;CACf;AACF,EACF;AAEA,IAAa,4BAA4B,EACvC,SAAS,UACX;AAeA,SAAgB,cAAc,EAC5B,UAAU,0BAA0B,YACZ,CAAC,GAAG;CAC5B,OAAO,GAAG,kBAAkB,QAAQ,SAAS,OAAO;AACtD;AASA,IAAM,oBAAoB,cAEvB,EACD,iBAAiB,QACnB,CAAC;AAgHD,IAAM,YAAY,YACf,EAAE,WAAW,UAAU,UAAU,WAAW,OAAO,SAAS,QAAQ;CACnE,MAAM,EAAE,oBAAoB,WAAW,iBAAiB;CAExD,OACE,qBAAC,SAAD;EACE,WAAW,GACT,iDAGA,oBAAoB,SAAS,gCAC7B,WAAW,kCAAkC,kBAC7C,SACF;YARF,CAUE,oBAAC,MAAU,MAAX;GACO;GACE;GACG;GACV,WAAW,GACT,kFACA,YAAY,UAAU,mBAAmB,oBACzC,CAAC,YACC,sFACF,6BACF;aAEA,oBAAC,MAAU,WAAX;IAAqB,WAAU;cAC7B,oBAAC,QAAD,EAAM,WAAU,kCAAmC,CAAA;GAChC,CAAA;EACP,CAAA,GAChB,oBAAC,QAAD;GAAM,WAAU;aAAyC;EAAY,CAAA,CAChE;;AAEX,CACF;AAEA,UAAU,cAAc;AAGxB,SAAS,aAAW,EAClB,QACA,UACA,cAAc,YACd,OACA,aACA,cACA,OACA,eACA,UACA,kBAAkB,SAClB,MACA,aACkB;CAClB,OACE,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO,EAAE,gBAAgB;YACnD,oBAAC,YAAD;GACgB;GACP;GACP,gBAAgB,aAAa,gBAAgB,QAAkB;GACrD;GACJ;aAEN,qBAAC,SAAS,MAAV;IACE,WAAW,GACT,4DACA,SACF;cAJF;KAME,oBAAC,SAAS,QAAV;MAAiB,WAAU;gBACxB;KACc,CAAA;KACjB,oBAAC,OAAD;MACE,WAAW,GACT,cACA,gBAAgB,aAAa,aAAa,oBAC5C;MAEC;KACE,CAAA;KACJ,SAAS,oBAAC,KAAD;MAAG,WAAU;gBAA0B;KAAS,CAAA;KACzD,eACC,oBAAC,KAAD;MAAG,WAAU;gBAA0B;KAAe,CAAA;IAE3C;;EACD,CAAA;CACU,CAAA;AAEhC;AAEA,aAAW,cAAc;;;;;;;;;;;;;;;;AAoBzB,IAAa,UAAQ;CACnB,MAAM;CACN,OAAO;AACT"}
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { i as buttonVariants } from "./button-CO6-qPax.js";
4
- import { t as Field } from "./field-B_yVof52.js";
5
- import { t as SkeletonLine } from "./skeleton-line-CH1-h6e2.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { i as buttonVariants } from "./button-BHOgXJRU.js";
4
+ import { t as Field } from "./field-DBpFzzBS.js";
5
+ import { t as SkeletonLine } from "./skeleton-line-CxxYVTO2.js";
6
6
  import { useId } from "react";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
8
  import { CaretUpDownIcon, CheckIcon } from "@phosphor-icons/react";
@@ -28,7 +28,7 @@ function Select$1({ children, className, renderValue, label, hideLabel = true, p
28
28
  const fallbackLabel = typeof label === "string" ? label : placeholder;
29
29
  const useFieldWrapper = label && !hideLabel;
30
30
  const triggerLabelledBy = useFieldWrapper ? void 0 : ariaLabelledby ?? (label ? labelId : void 0);
31
- const triggerAriaLabel = ariaLabel ?? (!triggerLabelledBy ? fallbackLabel : void 0);
31
+ const triggerAriaLabel = ariaLabel ?? (triggerLabelledBy ? void 0 : fallbackLabel);
32
32
  let items = props.items;
33
33
  if (placeholder) {
34
34
  if (!items) items = [{
@@ -92,4 +92,4 @@ Select$1.Option = Option;
92
92
  //#endregion
93
93
  export { Select$1 as t };
94
94
 
95
- //# sourceMappingURL=select-DMhdoHMa.js.map
95
+ //# sourceMappingURL=select-BFifYqHA.js.map