@signalflare-ai/ui 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -1
- package/ai/component-registry.json +208 -550
- package/ai/component-registry.md +3042 -3115
- package/ai/schemas.ts +504 -96
- package/dist/.build-complete +1 -1
- package/dist/ai/schemas.d.ts.map +1 -1
- package/dist/{ai-actions-BdUZI3Gk.js → ai-actions-CBfz5XEf.js} +4 -4
- package/dist/{ai-actions-BdUZI3Gk.js.map → ai-actions-CBfz5XEf.js.map} +1 -1
- package/dist/{ai-agent-card-BR2NIYhi.js → ai-agent-card-CByAUe0q.js} +3 -3
- package/dist/ai-agent-card-CByAUe0q.js.map +1 -0
- package/dist/{ai-approval-Ba7mrKba.js → ai-approval-Ci8N70a7.js} +4 -3
- package/dist/{ai-approval-Ba7mrKba.js.map → ai-approval-Ci8N70a7.js.map} +1 -1
- package/dist/{ai-code-block-CZtoL73R.js → ai-code-block-P9TJHvaC.js} +37 -39
- package/dist/ai-code-block-P9TJHvaC.js.map +1 -0
- package/dist/{ai-conversation-Cc7WlaBg.js → ai-conversation-Qslfdi1t.js} +28 -42
- package/dist/ai-conversation-Qslfdi1t.js.map +1 -0
- package/dist/{ai-info-banner-C7EWPBj7.js → ai-info-banner-B_9vtGK3.js} +3 -3
- package/dist/{ai-info-banner-C7EWPBj7.js.map → ai-info-banner-B_9vtGK3.js.map} +1 -1
- package/dist/{ai-message-Bp7L68U_.js → ai-message-Ci3gwM7G.js} +6 -6
- package/dist/{ai-message-Bp7L68U_.js.map → ai-message-Ci3gwM7G.js.map} +1 -1
- package/dist/{ai-mission-header-TiCJfTNt.js → ai-mission-header-CaBc19-t.js} +2 -2
- package/dist/{ai-mission-header-TiCJfTNt.js.map → ai-mission-header-CaBc19-t.js.map} +1 -1
- package/dist/{ai-part-group-DNb9I446.js → ai-part-group-Dx1Mr92B.js} +5 -4
- package/dist/ai-part-group-Dx1Mr92B.js.map +1 -0
- package/dist/{ai-prompt-input-BVvov_KF.js → ai-prompt-input-Bm4XoSj2.js} +19 -17
- package/dist/ai-prompt-input-Bm4XoSj2.js.map +1 -0
- package/dist/{ai-question-GPPMk7YM.js → ai-question-OyJovxGe.js} +4 -3
- package/dist/{ai-question-GPPMk7YM.js.map → ai-question-OyJovxGe.js.map} +1 -1
- package/dist/{ai-reasoning-_feFjk56.js → ai-reasoning-BLfBXx3F.js} +9 -5
- package/dist/ai-reasoning-BLfBXx3F.js.map +1 -0
- package/dist/{ai-response-CvjV3WhV.js → ai-response-hbVCZJmo.js} +2 -2
- package/dist/{ai-response-CvjV3WhV.js.map → ai-response-hbVCZJmo.js.map} +1 -1
- package/dist/{ai-shimmer-j6lKIrjj.js → ai-shimmer-BamNMNK3.js} +2 -2
- package/dist/{ai-shimmer-j6lKIrjj.js.map → ai-shimmer-BamNMNK3.js.map} +1 -1
- package/dist/{ai-status-badge-CSU_QOdz.js → ai-status-badge-BZLczdkI.js} +2 -2
- package/dist/{ai-status-badge-CSU_QOdz.js.map → ai-status-badge-BZLczdkI.js.map} +1 -1
- package/dist/{ai-streaming-text-IWW1BhvZ.js → ai-streaming-text-DgYu64UH.js} +1 -1
- package/dist/{ai-streaming-text-IWW1BhvZ.js.map → ai-streaming-text-DgYu64UH.js.map} +1 -1
- package/dist/{ai-subagent-JA4iIMW3.js → ai-subagent-p97AI1h9.js} +3 -3
- package/dist/{ai-subagent-JA4iIMW3.js.map → ai-subagent-p97AI1h9.js.map} +1 -1
- package/dist/{ai-suggestion-BdO6MBuH.js → ai-suggestion-Bj6vF7CT.js} +3 -3
- package/dist/{ai-suggestion-BdO6MBuH.js.map → ai-suggestion-Bj6vF7CT.js.map} +1 -1
- package/dist/{ai-task-list-DYw4R1FA.js → ai-task-list-C_UQYpk9.js} +6 -4
- package/dist/{ai-task-list-DYw4R1FA.js.map → ai-task-list-C_UQYpk9.js.map} +1 -1
- package/dist/{ai-timeline-C42tOUT8.js → ai-timeline-CePL1LOU.js} +3 -3
- package/dist/ai-timeline-CePL1LOU.js.map +1 -0
- package/dist/{ai-tool-03jOTwUI.js → ai-tool-CfRcwmHT.js} +17 -11
- package/dist/ai-tool-CfRcwmHT.js.map +1 -0
- package/dist/{ai-usage-bar-BRf5LC_b.js → ai-usage-bar-45pVRCGA.js} +2 -2
- package/dist/{ai-usage-bar-BRf5LC_b.js.map → ai-usage-bar-45pVRCGA.js.map} +1 -1
- package/dist/{badge-BheXjMc8.js → badge-Beb-6uut.js} +5 -5
- package/dist/{badge-BheXjMc8.js.map → badge-Beb-6uut.js.map} +1 -1
- package/dist/{banner-CcsjunJg.js → banner-CCEksxPg.js} +3 -3
- package/dist/{banner-CcsjunJg.js.map → banner-CCEksxPg.js.map} +1 -1
- package/dist/{breadcrumbs-CouSyy3H.js → breadcrumbs-HiTmgaZ4.js} +5 -5
- package/dist/{breadcrumbs-CouSyy3H.js.map → breadcrumbs-HiTmgaZ4.js.map} +1 -1
- package/dist/{button-CO6-qPax.js → button-BHOgXJRU.js} +4 -4
- package/dist/{button-CO6-qPax.js.map → button-BHOgXJRU.js.map} +1 -1
- package/dist/catalog.js +1 -1
- package/dist/catalog.js.map +1 -1
- package/dist/{chart-Dg0qUeSc.js → chart-B9FfZdKs.js} +7 -7
- package/dist/chart-B9FfZdKs.js.map +1 -0
- package/dist/{checkbox-D7p4QKsC.js → checkbox-Cy_OCyay.js} +3 -3
- package/dist/{checkbox-D7p4QKsC.js.map → checkbox-Cy_OCyay.js.map} +1 -1
- package/dist/{clipboard-text-kLaMogs3.js → clipboard-text-CKSvNp9L.js} +6 -5
- package/dist/clipboard-text-CKSvNp9L.js.map +1 -0
- package/dist/{cn-YROP2_ox.js → cn-CmAOpn49.js} +2 -2
- package/dist/{cn-YROP2_ox.js.map → cn-CmAOpn49.js.map} +1 -1
- package/dist/{code-BN8InC0G.js → code-JsQz-0G_.js} +4 -4
- package/dist/{code-BN8InC0G.js.map → code-JsQz-0G_.js.map} +1 -1
- package/dist/{collapsible-D_ueZ0jz.js → collapsible-1kOZ-89L.js} +2 -2
- package/dist/{collapsible-D_ueZ0jz.js.map → collapsible-1kOZ-89L.js.map} +1 -1
- package/dist/{combobox-B7TOK0U2.js → combobox-CQwDmqgA.js} +4 -4
- package/dist/{combobox-B7TOK0U2.js.map → combobox-CQwDmqgA.js.map} +1 -1
- package/dist/command-line/cli.js +3 -3
- package/dist/{command-palette-CuNUyJca.js → command-palette-Bkuv3e6o.js} +20 -5
- package/dist/command-palette-Bkuv3e6o.js.map +1 -0
- package/dist/components/ai-actions.js +1 -1
- package/dist/components/ai-agent-card.js +1 -1
- package/dist/components/ai-approval.js +1 -1
- package/dist/components/ai-code-block.js +1 -1
- package/dist/components/ai-conversation.js +1 -1
- package/dist/components/ai-info-banner.js +1 -1
- package/dist/components/ai-message.js +1 -1
- package/dist/components/ai-mission-header.js +1 -1
- package/dist/components/ai-part-group.js +1 -1
- package/dist/components/ai-prompt-input.js +1 -1
- package/dist/components/ai-question.js +1 -1
- package/dist/components/ai-reasoning.js +1 -1
- package/dist/components/ai-response.js +1 -1
- package/dist/components/ai-shimmer.js +1 -1
- package/dist/components/ai-status-badge.js +1 -1
- package/dist/components/ai-streaming-text.js +1 -1
- package/dist/components/ai-subagent.js +1 -1
- package/dist/components/ai-suggestion.js +1 -1
- package/dist/components/ai-task-list.js +1 -1
- package/dist/components/ai-timeline.js +1 -1
- package/dist/components/ai-tool.js +1 -1
- package/dist/components/ai-usage-bar.js +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/banner.js +1 -1
- package/dist/components/breadcrumbs.js +1 -1
- package/dist/components/button.js +1 -1
- package/dist/components/chart.js +2 -2
- package/dist/components/checkbox.js +1 -1
- package/dist/components/clipboard-text.js +1 -1
- package/dist/components/code.js +1 -1
- package/dist/components/collapsible.js +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/components/command-palette.js +1 -1
- package/dist/components/data-grid.js +1 -1
- package/dist/components/date-picker.js +1 -1
- package/dist/components/date-range-picker.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/dropdown.js +1 -1
- package/dist/components/empty.js +1 -1
- package/dist/components/field.js +1 -1
- package/dist/components/filters.js +1 -1
- package/dist/components/flow.js +1 -1
- package/dist/components/grid.js +1 -1
- package/dist/components/input.js +2 -2
- package/dist/components/label.js +1 -1
- package/dist/components/layer-card.js +1 -1
- package/dist/components/link.js +3 -3
- package/dist/components/link.js.map +1 -1
- package/dist/components/loader.js +2 -2
- package/dist/components/menubar.js +1 -1
- package/dist/components/meter.js +1 -1
- package/dist/components/pagination.js +1 -1
- package/dist/components/popover.js +1 -1
- package/dist/components/radio.js +1 -1
- package/dist/components/select.js +1 -1
- package/dist/components/sensitive-input.js +1 -1
- package/dist/components/sidebar.js +1 -1
- package/dist/components/signalflare-ai-logo.js +1 -1
- package/dist/components/sparkline.js +1 -1
- package/dist/components/stat-card.js +1 -1
- package/dist/components/surface.js +1 -1
- package/dist/components/switch.js +1 -1
- package/dist/components/table.js +1 -1
- package/dist/components/tabs.js +1 -1
- package/dist/components/text-roll.js +1 -1
- package/dist/components/text.js +1 -1
- package/dist/components/theme-toggle.js +1 -1
- package/dist/components/toast.js +1 -1
- package/dist/components/tooltip.js +1 -1
- package/dist/components/use-agent-harness.js +1 -1
- package/dist/{data-grid-DGHmU0w3.js → data-grid-DDSFMHud.js} +136 -53
- package/dist/data-grid-DDSFMHud.js.map +1 -0
- package/dist/{date-picker--ox89RBy.js → date-picker-O34AqG3f.js} +2 -2
- package/dist/{date-picker--ox89RBy.js.map → date-picker-O34AqG3f.js.map} +1 -1
- package/dist/{date-range-picker-DVa7QBqE.js → date-range-picker-YKYvum_r.js} +29 -39
- package/dist/{date-range-picker-DVa7QBqE.js.map → date-range-picker-YKYvum_r.js.map} +1 -1
- package/dist/{dialog-Bv1oSFOd.js → dialog-DYqu4aDO.js} +3 -3
- package/dist/{dialog-Bv1oSFOd.js.map → dialog-DYqu4aDO.js.map} +1 -1
- package/dist/{dist-B6iWiWwp.js → dist-6AtBsaJE.js} +153 -47
- package/dist/dist-6AtBsaJE.js.map +1 -0
- package/dist/{dropdown-B_nrGXjV.js → dropdown-XzbnRLYR.js} +15 -5
- package/dist/dropdown-XzbnRLYR.js.map +1 -0
- package/dist/{echart-CdOUaT-r.js → echart-DGBIVAv1.js} +23 -57
- package/dist/{echart-CdOUaT-r.js.map → echart-DGBIVAv1.js.map} +1 -1
- package/dist/{empty-DZnN0zKX.js → empty-C1tAkawe.js} +6 -6
- package/dist/{empty-DZnN0zKX.js.map → empty-C1tAkawe.js.map} +1 -1
- package/dist/{field-B_yVof52.js → field-DBpFzzBS.js} +3 -3
- package/dist/{field-B_yVof52.js.map → field-DBpFzzBS.js.map} +1 -1
- package/dist/{filters-cpJCY21R.js → filters-SmEl93za.js} +10 -10
- package/dist/filters-SmEl93za.js.map +1 -0
- package/dist/{flow-B4v198ot.js → flow-BLzgbq1T.js} +6 -6
- package/dist/flow-BLzgbq1T.js.map +1 -0
- package/dist/genui.js +2 -2
- package/dist/genui.js.map +1 -1
- package/dist/{grid-CEd64Lnh.js → grid-CifjQL-5.js} +2 -2
- package/dist/{grid-CEd64Lnh.js.map → grid-CifjQL-5.js.map} +1 -1
- package/dist/{highlight-to-react-D0Yav4jk.js → highlight-to-react-DN9dUCS2.js} +9 -15
- package/dist/highlight-to-react-DN9dUCS2.js.map +1 -0
- package/dist/index.js +71 -71
- package/dist/index.js.map +1 -1
- package/dist/{input-ClB_E4Lb.js → input-COmx2M_R.js} +5 -5
- package/dist/{input-ClB_E4Lb.js.map → input-COmx2M_R.js.map} +1 -1
- package/dist/{input-B2bbijRh.js → input-GkfMQZC_.js} +3 -3
- package/dist/{input-B2bbijRh.js.map → input-GkfMQZC_.js.map} +1 -1
- package/dist/{label-DUv_urO1.js → label-CiGZ464N.js} +3 -3
- package/dist/{label-DUv_urO1.js.map → label-CiGZ464N.js.map} +1 -1
- package/dist/{layer-card-BK7eYfwn.js → layer-card-8l8GuLQr.js} +2 -2
- package/dist/{layer-card-BK7eYfwn.js.map → layer-card-8l8GuLQr.js.map} +1 -1
- package/dist/{layout-DJHMMap2.js → layout-CWBE0qwx.js} +258 -154
- package/dist/layout-CWBE0qwx.js.map +1 -0
- package/dist/{link-provider-BUZKXaNE.js → link-provider-BSn8YJon.js} +2 -2
- package/dist/link-provider-BSn8YJon.js.map +1 -0
- package/dist/{loader-DAcc-Uag.js → loader-BEMz8pJO.js} +1 -1
- package/dist/{loader-DAcc-Uag.js.map → loader-BEMz8pJO.js.map} +1 -1
- package/dist/{measured-text-BI3dTJmH.js → measured-text-CXkdw9Yr.js} +45 -30
- package/dist/measured-text-CXkdw9Yr.js.map +1 -0
- package/dist/{menubar-Cxf3xeAt.js → menubar-CoOr4ocj.js} +3 -3
- package/dist/{menubar-Cxf3xeAt.js.map → menubar-CoOr4ocj.js.map} +1 -1
- package/dist/{meter-BFFe9l5b.js → meter-Pf_VOl59.js} +2 -2
- package/dist/{meter-BFFe9l5b.js.map → meter-Pf_VOl59.js.map} +1 -1
- package/dist/{pagination-yS372Tr4.js → pagination-DSY279Ta.js} +2 -2
- package/dist/{pagination-yS372Tr4.js.map → pagination-DSY279Ta.js.map} +1 -1
- package/dist/{popover-SRoJaCZr.js → popover-BY-e9co1.js} +2 -2
- package/dist/{popover-SRoJaCZr.js.map → popover-BY-e9co1.js.map} +1 -1
- package/dist/{radio-BcwhwYNB.js → radio-DZwL13j0.js} +2 -2
- package/dist/{radio-BcwhwYNB.js.map → radio-DZwL13j0.js.map} +1 -1
- package/dist/{select-DMhdoHMa.js → select-BFifYqHA.js} +6 -6
- package/dist/{select-DMhdoHMa.js.map → select-BFifYqHA.js.map} +1 -1
- package/dist/{sensitive-input-CJUpIRal.js → sensitive-input-DHLZcM73.js} +4 -4
- package/dist/{sensitive-input-CJUpIRal.js.map → sensitive-input-DHLZcM73.js.map} +1 -1
- package/dist/{sidebar-D4zrlYpn.js → sidebar-odGsdvG4.js} +6 -7
- package/dist/sidebar-odGsdvG4.js.map +1 -0
- package/dist/{signalflare-ai-logo-Bipogceq.js → signalflare-ai-logo-CNaDT_w8.js} +2 -2
- package/dist/{signalflare-ai-logo-Bipogceq.js.map → signalflare-ai-logo-CNaDT_w8.js.map} +1 -1
- package/dist/{skeleton-line-CH1-h6e2.js → skeleton-line-CxxYVTO2.js} +2 -2
- package/dist/{skeleton-line-CH1-h6e2.js.map → skeleton-line-CxxYVTO2.js.map} +1 -1
- package/dist/{sparkline-DHmgj1d0.js → sparkline-BQ-4j2W2.js} +2 -2
- package/dist/{sparkline-DHmgj1d0.js.map → sparkline-BQ-4j2W2.js.map} +1 -1
- package/dist/src/blocks/agent-harness/agent-harness.tsx +11 -11
- package/dist/src/blocks/commander/commander.tsx +15 -15
- package/dist/src/blocks/map-block/map-block.d.ts.map +1 -1
- package/dist/src/blocks/map-block/map-block.tsx +11 -7
- package/dist/src/components/ai-approval/ai-approval.d.ts.map +1 -1
- package/dist/src/components/ai-code-block/ai-code-block.d.ts +14 -13
- package/dist/src/components/ai-code-block/ai-code-block.d.ts.map +1 -1
- package/dist/src/components/ai-conversation/ai-conversation.d.ts.map +1 -1
- package/dist/src/components/ai-part-group/ai-part-group.d.ts.map +1 -1
- package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
- package/dist/src/components/ai-prompt-input/controller.d.ts.map +1 -1
- package/dist/src/components/ai-prompt-input/types.d.ts.map +1 -1
- package/dist/src/components/ai-question/ai-question.d.ts.map +1 -1
- package/dist/src/components/ai-reasoning/ai-reasoning.d.ts.map +1 -1
- package/dist/src/components/ai-response/ai-response.d.ts.map +1 -1
- package/dist/src/components/ai-subagent/ai-subagent.d.ts.map +1 -1
- package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -1
- package/dist/src/components/chart/echart.d.ts.map +1 -1
- package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
- package/dist/src/components/data-grid/data-grid.d.ts +2 -1
- package/dist/src/components/data-grid/data-grid.d.ts.map +1 -1
- package/dist/src/components/data-grid/features.d.ts +20 -0
- package/dist/src/components/data-grid/features.d.ts.map +1 -0
- package/dist/src/components/data-grid/types.d.ts +38 -7
- package/dist/src/components/data-grid/types.d.ts.map +1 -1
- package/dist/src/components/filters/filters.d.ts.map +1 -1
- package/dist/src/components/flow/use-children.d.ts +1 -1
- package/dist/src/components/link/link.d.ts.map +1 -1
- package/dist/src/components/sidebar/sidebar.d.ts +1 -1
- package/dist/src/components/signalflare-ai-logo/signalflare-ai-logo.d.ts.map +1 -1
- package/dist/src/components/text/text.d.ts +2 -1
- package/dist/src/components/text/text.d.ts.map +1 -1
- package/dist/src/components/text-roll/text-roll.d.ts.map +1 -1
- package/dist/src/components/theme-toggle/theme-toggle.d.ts.map +1 -1
- package/dist/src/components/toast/toast.d.ts.map +1 -1
- package/dist/src/utils/highlight-to-react.d.ts.map +1 -1
- package/dist/src/utils/measured-text.d.ts.map +1 -1
- package/dist/src/utils/use-measured-text.d.ts.map +1 -1
- package/dist/{stat-card-Ew-ofzEm.js → stat-card-Bspk4XFr.js} +4 -4
- package/dist/stat-card-Bspk4XFr.js.map +1 -0
- package/dist/styles/sf-standalone.css +1 -1
- package/dist/styles/theme-fedramp.css +3 -12
- package/dist/styles/theme-minimal.css +26 -104
- package/dist/styles/theme-sf.css +37 -142
- package/dist/{surface-DGwRlC0o.js → surface-CWdSFVUx.js} +3 -3
- package/dist/{surface-DGwRlC0o.js.map → surface-CWdSFVUx.js.map} +1 -1
- package/dist/{switch-BxAMfHdt.js → switch-TA4cByCJ.js} +5 -5
- package/dist/switch-TA4cByCJ.js.map +1 -0
- package/dist/{table-BBeAtYVZ.js → table-BM8JBGBs.js} +3 -3
- package/dist/{table-BBeAtYVZ.js.map → table-BM8JBGBs.js.map} +1 -1
- package/dist/{tabs-CeHu7Scn.js → tabs-bnH2vGLv.js} +2 -2
- package/dist/{tabs-CeHu7Scn.js.map → tabs-bnH2vGLv.js.map} +1 -1
- package/dist/{text-Cqryz7rk.js → text-iQ0YUFNg.js} +4 -5
- package/dist/{text-Cqryz7rk.js.map → text-iQ0YUFNg.js.map} +1 -1
- package/dist/{text-roll-Ch52hcQj.js → text-roll-C3U2jd2u.js} +5 -2
- package/dist/text-roll-C3U2jd2u.js.map +1 -0
- package/dist/{theme-toggle-LDfIKEqx.js → theme-toggle-BTVxD-fD.js} +10 -9
- package/dist/theme-toggle-BTVxD-fD.js.map +1 -0
- package/dist/{toast-CaFQNYng.js → toast-CgZVaAkw.js} +3 -3
- package/dist/{toast-CaFQNYng.js.map → toast-CgZVaAkw.js.map} +1 -1
- package/dist/{tooltip-g9lFsvcT.js → tooltip-uobk6Oh-.js} +3 -3
- package/dist/{tooltip-g9lFsvcT.js.map → tooltip-uobk6Oh-.js.map} +1 -1
- package/dist/{use-agent-harness-BTcNJdw4.js → use-agent-harness-Dl8w6X5O.js} +3 -3
- package/dist/{use-agent-harness-BTcNJdw4.js.map → use-agent-harness-Dl8w6X5O.js.map} +1 -1
- package/dist/utils.js +3 -3
- package/package.json +27 -25
- package/scripts/component-registry/discovery.ts +11 -10
- package/scripts/component-registry/example-cleanup.ts +8 -8
- package/scripts/component-registry/index.ts +6 -6
- package/scripts/component-registry/schema-generator.ts +1 -1
- package/scripts/component-registry/sub-components.ts +35 -23
- package/scripts/component-registry/utils.ts +11 -11
- package/scripts/component-registry/variant-parser.ts +17 -15
- package/scripts/convert-demos-to-stories.ts +5 -5
- package/scripts/theme-generator/config.ts +1 -5
- package/scripts/theme-generator/generate-css.ts +1 -1
- package/scripts/theme-generator/migrate.ts +3 -3
- package/dist/ai-agent-card-BR2NIYhi.js.map +0 -1
- package/dist/ai-code-block-CZtoL73R.js.map +0 -1
- package/dist/ai-conversation-Cc7WlaBg.js.map +0 -1
- package/dist/ai-part-group-DNb9I446.js.map +0 -1
- package/dist/ai-prompt-input-BVvov_KF.js.map +0 -1
- package/dist/ai-reasoning-_feFjk56.js.map +0 -1
- package/dist/ai-timeline-C42tOUT8.js.map +0 -1
- package/dist/ai-tool-03jOTwUI.js.map +0 -1
- package/dist/chart-Dg0qUeSc.js.map +0 -1
- package/dist/clipboard-text-kLaMogs3.js.map +0 -1
- package/dist/command-palette-CuNUyJca.js.map +0 -1
- package/dist/data-grid-DGHmU0w3.js.map +0 -1
- package/dist/dist-B6iWiWwp.js.map +0 -1
- package/dist/dropdown-B_nrGXjV.js.map +0 -1
- package/dist/filters-cpJCY21R.js.map +0 -1
- package/dist/flow-B4v198ot.js.map +0 -1
- package/dist/highlight-to-react-D0Yav4jk.js.map +0 -1
- package/dist/layout-DJHMMap2.js.map +0 -1
- package/dist/link-provider-BUZKXaNE.js.map +0 -1
- package/dist/measured-text-BI3dTJmH.js.map +0 -1
- package/dist/sidebar-D4zrlYpn.js.map +0 -1
- package/dist/stat-card-Ew-ofzEm.js.map +0 -1
- package/dist/switch-BxAMfHdt.js.map +0 -1
- package/dist/text-roll-Ch52hcQj.js.map +0 -1
- package/dist/theme-toggle-LDfIKEqx.js.map +0 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { t as cn } from "./cn-
|
|
3
|
-
import { a as prepare, i as measureNaturalWidth, o as prepareWithSegments, r as measureLineStats, t as layout } from "./layout-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
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
|
|
89
|
-
const
|
|
90
|
-
const
|
|
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(
|
|
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(
|
|
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 (!
|
|
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
|
|
273
|
+
transition: transition("max-width")
|
|
259
274
|
};
|
|
260
275
|
if (mode === "shrink") return {
|
|
261
276
|
maxWidth: measurement.maxLineWidth,
|
|
262
|
-
transition: "max-width
|
|
277
|
+
transition: transition("max-width")
|
|
263
278
|
};
|
|
264
279
|
if (mode === "reserve") return {
|
|
265
280
|
minHeight: measurement.height,
|
|
266
|
-
transition: "min-height
|
|
281
|
+
transition: transition("min-height")
|
|
267
282
|
};
|
|
268
283
|
return {};
|
|
269
284
|
}, [
|
|
270
285
|
mode,
|
|
271
286
|
measurement,
|
|
272
|
-
|
|
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-
|
|
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":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { t as cn } from "./cn-
|
|
3
|
-
import { t as Tooltip } from "./tooltip-
|
|
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-
|
|
102
|
+
//# sourceMappingURL=menubar-CoOr4ocj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menubar-
|
|
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-
|
|
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-
|
|
37
|
+
//# sourceMappingURL=meter-Pf_VOl59.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meter-
|
|
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-
|
|
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-
|
|
117
|
+
//# sourceMappingURL=pagination-DSY279Ta.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
3
|
-
import { i as buttonVariants } from "./button-
|
|
4
|
-
import { t as Field } from "./field-
|
|
5
|
-
import { t as SkeletonLine } from "./skeleton-line-
|
|
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 ?? (
|
|
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-
|
|
95
|
+
//# sourceMappingURL=select-BFifYqHA.js.map
|