@refraction-ui/react 0.20.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/dist/{chunk-ZF3OHCGV.js → chunk-2Q6HHFAN.js} +1 -1
  2. package/dist/chunk-2Q6HHFAN.js.map +7 -0
  3. package/dist/{chunk-533MCMSU.js → chunk-3I3DYDHR.js} +2 -2
  4. package/dist/{chunk-F7B64KT3.js → chunk-3Y2T26QD.js} +13 -7
  5. package/dist/chunk-3Y2T26QD.js.map +7 -0
  6. package/dist/{chunk-H54FLNAF.js → chunk-63N4PZUJ.js} +2 -2
  7. package/dist/{chunk-Y2FNNAIL.js → chunk-EGVPAMQU.js} +2 -2
  8. package/dist/chunk-EGVPAMQU.js.map +1 -0
  9. package/dist/{chunk-WK2IIUFO.js → chunk-QDMLIDYN.js} +2 -2
  10. package/dist/{chunk-BOLFYVI6.js → chunk-QPCKJ2YR.js} +2 -2
  11. package/dist/{chunk-TOZBR4GL.js → chunk-RSWOLRIC.js} +4 -4
  12. package/dist/{chunk-TOZBR4GL.js.map → chunk-RSWOLRIC.js.map} +1 -1
  13. package/dist/{chunk-UNEM2TRI.js → chunk-SDAJVXD4.js} +2 -2
  14. package/dist/{chunk-VK3EQ34F.js → chunk-V24GDHUX.js} +2 -2
  15. package/dist/{chunk-AMK4VCBG.js → chunk-WYKPPK3W.js} +2 -2
  16. package/dist/{chunk-ONACRMG4.js → chunk-XMFNBOPO.js} +2 -2
  17. package/dist/form.cjs.map +1 -1
  18. package/dist/form.js +1 -1
  19. package/dist/index.cjs +632 -47
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +4 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.js +4 -0
  24. package/dist/internal/action-list/index.d.ts +39 -0
  25. package/dist/internal/badge/index.d.cts +2 -2
  26. package/dist/internal/badge/index.d.ts +2 -2
  27. package/dist/internal/button/index.d.cts +4 -4
  28. package/dist/internal/button/index.d.ts +4 -4
  29. package/dist/internal/card/index.d.cts +14 -2
  30. package/dist/internal/card/index.d.ts +14 -2
  31. package/dist/internal/funnel-chart/index.d.ts +60 -0
  32. package/dist/internal/line-chart/index.d.ts +110 -0
  33. package/dist/internal/page-header/index.d.ts +35 -0
  34. package/dist/internal/react-action-list/index.d.ts +28 -0
  35. package/dist/internal/react-card/index.d.cts +12 -3
  36. package/dist/internal/react-card/index.d.ts +12 -3
  37. package/dist/internal/react-funnel-chart/index.d.ts +28 -0
  38. package/dist/internal/react-line-chart/index.d.ts +33 -0
  39. package/dist/internal/react-page-header/index.d.ts +23 -0
  40. package/dist/internal/react-select/index.d.cts +21 -3
  41. package/dist/internal/react-select/index.d.ts +21 -3
  42. package/dist/internal/react-separator/index.d.cts +6 -1
  43. package/dist/internal/react-separator/index.d.ts +6 -1
  44. package/dist/internal/select/index.d.cts +14 -1
  45. package/dist/internal/select/index.d.ts +14 -1
  46. package/dist/internal/separator/index.d.cts +6 -1
  47. package/dist/internal/separator/index.d.ts +6 -1
  48. package/dist/internal/shared/index.d.cts +6 -3
  49. package/dist/internal/shared/index.d.ts +6 -3
  50. package/dist/internal/tabs/index.d.cts +8 -1
  51. package/dist/internal/tabs/index.d.ts +8 -1
  52. package/dist/react-accordion.js +1 -1
  53. package/dist/react-action-list.js +74 -0
  54. package/dist/react-action-list.js.map +7 -0
  55. package/dist/react-ai.js +1 -1
  56. package/dist/react-analytics.js +1 -1
  57. package/dist/react-animated-text.js +1 -1
  58. package/dist/react-app-shell.js +1 -1
  59. package/dist/react-audience-feature-card.js +1 -1
  60. package/dist/react-audio-room.js +1 -1
  61. package/dist/react-auth.js +1 -1
  62. package/dist/react-avatar-group.js +1 -1
  63. package/dist/react-avatar.js +1 -1
  64. package/dist/react-badge.js +16 -4
  65. package/dist/react-badge.js.map +2 -2
  66. package/dist/react-bottom-nav.js +1 -1
  67. package/dist/react-brand-network-cell.js +1 -1
  68. package/dist/react-breadcrumbs.js +1 -1
  69. package/dist/react-browser-chrome-mock.js +1 -1
  70. package/dist/react-browser-chrome-mock.js.map +2 -2
  71. package/dist/react-button.js +3 -3
  72. package/dist/react-calendar.js +1 -1
  73. package/dist/react-call-controls.js +1 -1
  74. package/dist/react-callout.js +8 -3
  75. package/dist/react-callout.js.map +2 -2
  76. package/dist/react-card-grid.js +1 -1
  77. package/dist/react-card.js +15 -6
  78. package/dist/react-card.js.map +2 -2
  79. package/dist/react-carousel.js +1 -1
  80. package/dist/react-charts.js +1 -1
  81. package/dist/react-checkbox.js +1 -1
  82. package/dist/react-checklist.js +1 -1
  83. package/dist/react-code-block.js +1 -1
  84. package/dist/react-code-editor.js +1 -1
  85. package/dist/react-collapsible.js +1 -1
  86. package/dist/react-combobox.js +1 -1
  87. package/dist/react-command-input.js +1 -1
  88. package/dist/react-command.js +1 -1
  89. package/dist/react-composer.js +3 -3
  90. package/dist/react-content-protection.js +1 -1
  91. package/dist/react-conversation.js +5 -5
  92. package/dist/react-cookie-consent.js +1 -1
  93. package/dist/react-data-table.js +1 -1
  94. package/dist/react-date-picker.js +1 -1
  95. package/dist/react-device-frame.js +1 -1
  96. package/dist/react-dialog.js +2 -2
  97. package/dist/react-diff-viewer.js +4 -1
  98. package/dist/react-diff-viewer.js.map +2 -2
  99. package/dist/react-dropdown-menu.js +1 -1
  100. package/dist/react-editor-status-bar.js +1 -1
  101. package/dist/react-editor-tabs.js +1 -1
  102. package/dist/react-emoji-picker.js +2 -2
  103. package/dist/react-empty-state.js +1 -1
  104. package/dist/react-feedback-dialog.js +2 -2
  105. package/dist/react-file-tree.js +1 -1
  106. package/dist/react-file-upload.js +1 -1
  107. package/dist/react-floating-reactions.js +1 -1
  108. package/dist/react-flow-editor.js +2 -2
  109. package/dist/react-footer.js +1 -1
  110. package/dist/react-funnel-chart.js +105 -0
  111. package/dist/react-funnel-chart.js.map +7 -0
  112. package/dist/react-graph-view.js +2 -2
  113. package/dist/react-infinite-canvas.js +2 -2
  114. package/dist/react-inline-editor.js +1 -1
  115. package/dist/react-input-group.js +1 -1
  116. package/dist/react-input.js +2 -2
  117. package/dist/react-install-prompt.js +1 -1
  118. package/dist/react-kanban-board.js +1 -1
  119. package/dist/react-keyboard-shortcut.js +2 -2
  120. package/dist/react-language-selector.js +1 -1
  121. package/dist/react-line-chart.js +242 -0
  122. package/dist/react-line-chart.js.map +7 -0
  123. package/dist/react-link-card.js +1 -1
  124. package/dist/react-live-captions.js +1 -1
  125. package/dist/react-live-cursors.js +1 -1
  126. package/dist/react-live-transcript.js +1 -1
  127. package/dist/react-location-selector.js +1 -1
  128. package/dist/react-logger.js +1 -1
  129. package/dist/react-markdown-renderer.js +2 -2
  130. package/dist/react-marquee-strip.js +1 -1
  131. package/dist/react-mascot.js +1 -1
  132. package/dist/react-mastery-bar.js +1 -1
  133. package/dist/react-mini-map.js +1 -1
  134. package/dist/react-mobile-nav.js +1 -1
  135. package/dist/react-navbar.js +1 -1
  136. package/dist/react-numbered-steps.js +1 -1
  137. package/dist/react-otp-input.js +1 -1
  138. package/dist/react-page-header.js +40 -0
  139. package/dist/react-page-header.js.map +7 -0
  140. package/dist/react-pagination.js +1 -1
  141. package/dist/react-password-input.js +2 -2
  142. package/dist/react-payment.js +1 -1
  143. package/dist/react-popover.js +1 -1
  144. package/dist/react-pre-call-lobby.js +1 -1
  145. package/dist/react-presence-indicator.js +1 -1
  146. package/dist/react-pricing-card.js +1 -1
  147. package/dist/react-progress-display.js +2 -2
  148. package/dist/react-progress-display.js.map +1 -1
  149. package/dist/react-radial-gauge.js +1 -1
  150. package/dist/react-radio.js +1 -1
  151. package/dist/react-rating-scale.js +1 -1
  152. package/dist/react-reaction-bar.js +1 -1
  153. package/dist/react-resizable-layout.js +1 -1
  154. package/dist/react-search-bar.js +1 -1
  155. package/dist/react-section-head.js +1 -1
  156. package/dist/react-segmented-control.js +1 -1
  157. package/dist/react-select.js +94 -20
  158. package/dist/react-select.js.map +3 -3
  159. package/dist/react-separator.js +19 -7
  160. package/dist/react-separator.js.map +2 -2
  161. package/dist/react-sheet.js +1 -1
  162. package/dist/react-sidebar.js +1 -1
  163. package/dist/react-skeleton.js +1 -1
  164. package/dist/react-skip-to-content.js +1 -1
  165. package/dist/react-slide-viewer.js +3 -1
  166. package/dist/react-slide-viewer.js.map +2 -2
  167. package/dist/react-slider.js +1 -1
  168. package/dist/react-slot-picker.js +1 -1
  169. package/dist/react-social-auth-button.js +3 -3
  170. package/dist/react-sortable-list.js +1 -1
  171. package/dist/react-stat-grid.js +1 -1
  172. package/dist/react-status-indicator.js +1 -1
  173. package/dist/react-steps.js +1 -1
  174. package/dist/react-sticky-note.js +3 -1
  175. package/dist/react-sticky-note.js.map +2 -2
  176. package/dist/react-switch.js +1 -1
  177. package/dist/react-table-of-contents.js +1 -1
  178. package/dist/react-tabs.js +50 -2
  179. package/dist/react-tabs.js.map +2 -2
  180. package/dist/react-terminal.js +1 -1
  181. package/dist/react-test-results.js +1 -1
  182. package/dist/react-textarea.js +3 -3
  183. package/dist/react-textarea.js.map +1 -1
  184. package/dist/react-thread-view.js +2 -2
  185. package/dist/react-timeline.js +1 -1
  186. package/dist/react-toast.js +1 -1
  187. package/dist/react-tooltip.js +1 -1
  188. package/dist/react-version-selector.js +1 -1
  189. package/dist/react-video-grid.js +2 -2
  190. package/dist/react-video-player.js +1 -1
  191. package/dist/react-video-tile.js +2 -2
  192. package/dist/react-voice-pill.js +1 -1
  193. package/dist/react-waveform.js +1 -1
  194. package/dist/react-wizard.js +1 -1
  195. package/dist/styles.css +48 -0
  196. package/dist/theme.js +1 -1
  197. package/package.json +5 -1
  198. package/dist/chunk-F7B64KT3.js.map +0 -7
  199. package/dist/chunk-Y2FNNAIL.js.map +0 -1
  200. package/dist/chunk-ZF3OHCGV.js.map +0 -7
  201. /package/dist/{chunk-533MCMSU.js.map → chunk-3I3DYDHR.js.map} +0 -0
  202. /package/dist/{chunk-H54FLNAF.js.map → chunk-63N4PZUJ.js.map} +0 -0
  203. /package/dist/{chunk-WK2IIUFO.js.map → chunk-QDMLIDYN.js.map} +0 -0
  204. /package/dist/{chunk-BOLFYVI6.js.map → chunk-QPCKJ2YR.js.map} +0 -0
  205. /package/dist/{chunk-UNEM2TRI.js.map → chunk-SDAJVXD4.js.map} +0 -0
  206. /package/dist/{chunk-VK3EQ34F.js.map → chunk-V24GDHUX.js.map} +0 -0
  207. /package/dist/{chunk-AMK4VCBG.js.map → chunk-WYKPPK3W.js.map} +0 -0
  208. /package/dist/{chunk-ONACRMG4.js.map → chunk-XMFNBOPO.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-skip-to-content/dist/index.js
7
7
  import * as React from "react";
@@ -2,7 +2,7 @@ import {
2
2
  Keys,
3
3
  cn,
4
4
  cva
5
- } from "./chunk-ZF3OHCGV.js";
5
+ } from "./chunk-2Q6HHFAN.js";
6
6
 
7
7
  // ../react-slide-viewer/dist/index.js
8
8
  import * as React from "react";
@@ -133,6 +133,8 @@ var slideViewerProgressBarVariants = cva({
133
133
  var slideTypeBadgeVariants = cva({
134
134
  base: "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium",
135
135
  variants: {
136
+ // Slide-type accents are a content-category palette (lesson/quiz/exercise…),
137
+ // not status tones — deliberately not routed through the theme tokens.
136
138
  type: {
137
139
  lesson: "bg-blue-100 text-blue-800",
138
140
  quiz: "bg-purple-100 text-purple-800",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../slide-viewer/src/slide-viewer.ts", "../../slide-viewer/src/slide-viewer.styles.ts", "../../react-slide-viewer/src/SlideViewer.tsx"],
4
- "sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { Keys } from '@refraction-ui/shared'\n\nexport type SlideType = 'lesson' | 'quiz' | 'exercise' | 'intro' | 'summary'\n\nexport type BookmarkType = 'important' | 'difficult' | 'to-revise'\n\nexport interface SlideData {\n id: string\n type: SlideType\n content: string\n}\n\nexport interface SlideViewerProps {\n slides: SlideData[]\n initialSlide?: number\n onSlideChange?: (index: number) => void\n onComplete?: () => void\n}\n\nexport interface SlideViewerState {\n currentSlide: number\n totalSlides: number\n bookmarks: Map<number, BookmarkType>\n}\n\nexport interface SlideViewerAPI {\n /** Current viewer state */\n state: SlideViewerState\n /** Navigate to the next slide */\n next: () => void\n /** Navigate to the previous slide */\n prev: () => void\n /** Navigate to a specific slide index */\n goTo: (index: number) => void\n /** Toggle a bookmark on the current slide */\n toggleBookmark: (type: BookmarkType) => void\n /** Get all bookmarks as an array of entries */\n getBookmarks: () => Array<{ slide: number; type: BookmarkType }>\n /** Current progress as a number between 0 and 1 */\n progress: number\n /** Keyboard handlers for slide navigation */\n keyboardHandlers: KeyboardHandlerMap\n /** ARIA props for the current slide */\n getSlideAriaProps: () => Partial<AccessibilityProps> & { 'aria-roledescription'?: string }\n}\n\n/**\n * Create a headless slide viewer.\n *\n * Manages slide navigation state, bookmarks, progress tracking,\n * and keyboard navigation. Framework wrappers handle rendering.\n */\nexport function createSlideViewer(props: SlideViewerProps): SlideViewerAPI {\n const { slides, initialSlide = 0, onSlideChange, onComplete } = props\n\n const totalSlides = slides.length\n const bookmarks = new Map<number, BookmarkType>()\n\n const state: SlideViewerState = {\n currentSlide: Math.max(0, Math.min(initialSlide, totalSlides - 1)),\n totalSlides,\n bookmarks,\n }\n\n function updateProgress(): number {\n if (totalSlides <= 1) return 1\n return state.currentSlide / (totalSlides - 1)\n }\n\n function next() {\n if (state.currentSlide < totalSlides - 1) {\n state.currentSlide++\n api.progress = updateProgress()\n onSlideChange?.(state.currentSlide)\n } else {\n // Already on the last slide — trigger complete\n onComplete?.()\n }\n }\n\n function prev() {\n if (state.currentSlide > 0) {\n state.currentSlide--\n api.progress = updateProgress()\n onSlideChange?.(state.currentSlide)\n }\n }\n\n function goTo(index: number) {\n if (index >= 0 && index < totalSlides) {\n state.currentSlide = index\n api.progress = updateProgress()\n onSlideChange?.(state.currentSlide)\n }\n }\n\n function toggleBookmark(type: BookmarkType) {\n const current = state.currentSlide\n if (bookmarks.has(current) && bookmarks.get(current) === type) {\n bookmarks.delete(current)\n } else {\n bookmarks.set(current, type)\n }\n }\n\n function getBookmarks(): Array<{ slide: number; type: BookmarkType }> {\n const result: Array<{ slide: number; type: BookmarkType }> = []\n for (const [slide, type] of bookmarks.entries()) {\n result.push({ slide, type })\n }\n return result.sort((a, b) => a.slide - b.slide)\n }\n\n const keyboardHandlers: KeyboardHandlerMap = {\n [Keys.ArrowRight]: (e) => {\n e.preventDefault()\n next()\n },\n [Keys.ArrowLeft]: (e) => {\n e.preventDefault()\n prev()\n },\n [Keys.Escape]: (e) => {\n e.preventDefault()\n },\n }\n\n function getSlideAriaProps(): Partial<AccessibilityProps> & { 'aria-roledescription'?: string } {\n const slide = slides[state.currentSlide]\n return {\n role: 'region',\n 'aria-roledescription': 'slide',\n 'aria-label': `Slide ${state.currentSlide + 1} of ${totalSlides}: ${slide?.type ?? 'unknown'} slide`,\n 'aria-live': 'polite',\n }\n }\n\n const api: SlideViewerAPI = {\n state,\n next,\n prev,\n goTo,\n toggleBookmark,\n getBookmarks,\n progress: updateProgress(),\n keyboardHandlers,\n getSlideAriaProps,\n }\n\n return api\n}\n", "import { cva } from '@refraction-ui/shared'\nimport type { TokenContract } from '@refraction-ui/shared'\n\nexport const slideViewerTokens: TokenContract = {\n name: 'slide-viewer',\n tokens: {\n bg: { variable: '--rfr-slide-bg', fallback: 'hsl(var(--background))' },\n fg: { variable: '--rfr-slide-fg', fallback: 'hsl(var(--foreground))' },\n progressBg: { variable: '--rfr-slide-progress-bg', fallback: 'hsl(var(--primary))' },\n progressTrack: { variable: '--rfr-slide-progress-track', fallback: 'hsl(var(--muted))' },\n badgeBg: { variable: '--rfr-slide-badge-bg', fallback: 'hsl(var(--secondary))' },\n },\n}\n\nexport const slideViewerVariants = cva({\n base: 'flex flex-col h-full w-full relative overflow-hidden',\n variants: {\n size: {\n compact: 'max-w-2xl',\n default: 'max-w-4xl',\n full: 'max-w-none',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n})\n\nconst slideViewerProgressBarVariants = cva({\n base: 'h-1 w-full bg-muted rounded-full overflow-hidden',\n variants: {\n position: {\n top: 'rounded-none',\n bottom: 'rounded-none',\n inline: 'rounded-full',\n },\n },\n defaultVariants: {\n position: 'top',\n },\n})\n\nexport { slideViewerProgressBarVariants as progressBarVariants }\n\nexport const slideTypeBadgeVariants = cva({\n base: 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n variants: {\n type: {\n lesson: 'bg-blue-100 text-blue-800',\n quiz: 'bg-purple-100 text-purple-800',\n exercise: 'bg-green-100 text-green-800',\n intro: 'bg-gray-100 text-gray-800',\n summary: 'bg-orange-100 text-orange-800',\n },\n },\n defaultVariants: {\n type: 'lesson',\n },\n})\n", "import * as React from 'react'\nimport {\n createSlideViewer,\n slideViewerVariants,\n progressBarVariants,\n slideTypeBadgeVariants,\n type SlideData,\n type BookmarkType,\n type SlideType,\n} from '@refraction-ui/slide-viewer'\nimport { cn } from '@refraction-ui/shared'\n\nexport type { SlideData, BookmarkType, SlideType }\n\nexport interface SlideViewerProps {\n slides: SlideData[]\n initialSlide?: number\n onSlideChange?: (index: number) => void\n onComplete?: () => void\n className?: string\n size?: 'compact' | 'default' | 'full'\n /** Render function for custom slide content */\n renderSlide?: (slide: SlideData, index: number) => React.ReactNode\n}\n\n/**\n * SlideViewer component — slide-based content viewer with navigation,\n * progress bar, type badges, and bookmark support.\n *\n * Uses the headless @refraction-ui/slide-viewer core for state and navigation.\n */\nexport const SlideViewer = React.forwardRef<HTMLDivElement, SlideViewerProps>(\n function SlideViewer(\n {\n slides,\n initialSlide,\n onSlideChange,\n onComplete,\n className,\n size,\n renderSlide,\n },\n ref,\n ) {\n const [, setTick] = React.useState(0)\n const rerender = () => setTick((t) => t + 1)\n\n const apiRef = React.useRef(\n createSlideViewer({ slides, initialSlide, onSlideChange, onComplete }),\n )\n const api = apiRef.current\n\n const containerClasses = cn(slideViewerVariants({ size }), className)\n const currentSlide = slides[api.state.currentSlide]\n const slideAriaProps = api.getSlideAriaProps()\n // The core's keyboard handlers mutate state in place; re-render after a\n // handled key so the counter, progress bar, and buttons stay in sync.\n function handleKeyDown(event: KeyboardEvent) {\n const handler =\n api.keyboardHandlers[event.key as keyof typeof api.keyboardHandlers]\n if (!handler) return\n handler(event)\n rerender()\n }\n\n function handlePrev() {\n api.prev()\n rerender()\n }\n\n function handleNext() {\n api.next()\n rerender()\n }\n\n function handleBookmark(type: BookmarkType) {\n api.toggleBookmark(type)\n rerender()\n }\n\n const isBookmarked = api.state.bookmarks.has(api.state.currentSlide)\n\n return (\n <div\n ref={ref}\n className={containerClasses}\n onKeyDown={handleKeyDown as unknown as React.KeyboardEventHandler}\n tabIndex={0}\n >\n {/* Progress bar */}\n <div className={progressBarVariants({ position: 'top' })}>\n <div\n className=\"h-full bg-primary transition-all duration-300\"\n style={{ width: `${api.progress * 100}%` }}\n />\n </div>\n\n {/* Header with type badge and bookmark */}\n <div className=\"flex items-center justify-between px-4 py-2 border-b\">\n <div className=\"flex items-center gap-2\">\n {currentSlide && (\n <span className={slideTypeBadgeVariants({ type: currentSlide.type })}>\n {currentSlide.type}\n </span>\n )}\n <span className=\"text-sm text-muted-foreground\">\n {api.state.currentSlide + 1} / {api.state.totalSlides}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={() => handleBookmark('important')}\n className={cn(\n 'px-2 py-1 rounded text-xs transition-colors',\n isBookmarked\n ? 'bg-yellow-100 text-yellow-800'\n : 'hover:bg-muted text-muted-foreground',\n )}\n aria-pressed={isBookmarked}\n aria-label=\"Toggle bookmark\"\n >\n {isBookmarked ? 'Bookmarked' : 'Bookmark'}\n </button>\n </div>\n\n {/* Slide content */}\n <div className=\"flex-1 overflow-auto p-6\" {...slideAriaProps}>\n {currentSlide &&\n (renderSlide\n ? renderSlide(currentSlide, api.state.currentSlide)\n : <div dangerouslySetInnerHTML={{ __html: currentSlide.content }} />)}\n </div>\n\n {/* Navigation buttons */}\n <div className=\"flex items-center justify-between px-4 py-3 border-t\">\n <button\n type=\"button\"\n onClick={handlePrev}\n disabled={api.state.currentSlide === 0}\n className=\"px-4 py-2 rounded text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed hover:bg-muted transition-colors\"\n aria-label=\"Previous slide\"\n >\n Previous\n </button>\n <button\n type=\"button\"\n onClick={handleNext}\n className=\"px-4 py-2 rounded text-sm font-medium bg-primary text-primary-foreground hover:bg-primary/90 transition-colors\"\n aria-label={\n api.state.currentSlide === api.state.totalSlides - 1\n ? 'Complete'\n : 'Next slide'\n }\n >\n {api.state.currentSlide === api.state.totalSlides - 1 ? 'Complete' : 'Next'}\n </button>\n </div>\n </div>\n )\n },\n)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { Keys } from '@refraction-ui/shared'\n\nexport type SlideType = 'lesson' | 'quiz' | 'exercise' | 'intro' | 'summary'\n\nexport type BookmarkType = 'important' | 'difficult' | 'to-revise'\n\nexport interface SlideData {\n id: string\n type: SlideType\n content: string\n}\n\nexport interface SlideViewerProps {\n slides: SlideData[]\n initialSlide?: number\n onSlideChange?: (index: number) => void\n onComplete?: () => void\n}\n\nexport interface SlideViewerState {\n currentSlide: number\n totalSlides: number\n bookmarks: Map<number, BookmarkType>\n}\n\nexport interface SlideViewerAPI {\n /** Current viewer state */\n state: SlideViewerState\n /** Navigate to the next slide */\n next: () => void\n /** Navigate to the previous slide */\n prev: () => void\n /** Navigate to a specific slide index */\n goTo: (index: number) => void\n /** Toggle a bookmark on the current slide */\n toggleBookmark: (type: BookmarkType) => void\n /** Get all bookmarks as an array of entries */\n getBookmarks: () => Array<{ slide: number; type: BookmarkType }>\n /** Current progress as a number between 0 and 1 */\n progress: number\n /** Keyboard handlers for slide navigation */\n keyboardHandlers: KeyboardHandlerMap\n /** ARIA props for the current slide */\n getSlideAriaProps: () => Partial<AccessibilityProps> & { 'aria-roledescription'?: string }\n}\n\n/**\n * Create a headless slide viewer.\n *\n * Manages slide navigation state, bookmarks, progress tracking,\n * and keyboard navigation. Framework wrappers handle rendering.\n */\nexport function createSlideViewer(props: SlideViewerProps): SlideViewerAPI {\n const { slides, initialSlide = 0, onSlideChange, onComplete } = props\n\n const totalSlides = slides.length\n const bookmarks = new Map<number, BookmarkType>()\n\n const state: SlideViewerState = {\n currentSlide: Math.max(0, Math.min(initialSlide, totalSlides - 1)),\n totalSlides,\n bookmarks,\n }\n\n function updateProgress(): number {\n if (totalSlides <= 1) return 1\n return state.currentSlide / (totalSlides - 1)\n }\n\n function next() {\n if (state.currentSlide < totalSlides - 1) {\n state.currentSlide++\n api.progress = updateProgress()\n onSlideChange?.(state.currentSlide)\n } else {\n // Already on the last slide — trigger complete\n onComplete?.()\n }\n }\n\n function prev() {\n if (state.currentSlide > 0) {\n state.currentSlide--\n api.progress = updateProgress()\n onSlideChange?.(state.currentSlide)\n }\n }\n\n function goTo(index: number) {\n if (index >= 0 && index < totalSlides) {\n state.currentSlide = index\n api.progress = updateProgress()\n onSlideChange?.(state.currentSlide)\n }\n }\n\n function toggleBookmark(type: BookmarkType) {\n const current = state.currentSlide\n if (bookmarks.has(current) && bookmarks.get(current) === type) {\n bookmarks.delete(current)\n } else {\n bookmarks.set(current, type)\n }\n }\n\n function getBookmarks(): Array<{ slide: number; type: BookmarkType }> {\n const result: Array<{ slide: number; type: BookmarkType }> = []\n for (const [slide, type] of bookmarks.entries()) {\n result.push({ slide, type })\n }\n return result.sort((a, b) => a.slide - b.slide)\n }\n\n const keyboardHandlers: KeyboardHandlerMap = {\n [Keys.ArrowRight]: (e) => {\n e.preventDefault()\n next()\n },\n [Keys.ArrowLeft]: (e) => {\n e.preventDefault()\n prev()\n },\n [Keys.Escape]: (e) => {\n e.preventDefault()\n },\n }\n\n function getSlideAriaProps(): Partial<AccessibilityProps> & { 'aria-roledescription'?: string } {\n const slide = slides[state.currentSlide]\n return {\n role: 'region',\n 'aria-roledescription': 'slide',\n 'aria-label': `Slide ${state.currentSlide + 1} of ${totalSlides}: ${slide?.type ?? 'unknown'} slide`,\n 'aria-live': 'polite',\n }\n }\n\n const api: SlideViewerAPI = {\n state,\n next,\n prev,\n goTo,\n toggleBookmark,\n getBookmarks,\n progress: updateProgress(),\n keyboardHandlers,\n getSlideAriaProps,\n }\n\n return api\n}\n", "import { cva } from '@refraction-ui/shared'\nimport type { TokenContract } from '@refraction-ui/shared'\n\nexport const slideViewerTokens: TokenContract = {\n name: 'slide-viewer',\n tokens: {\n bg: { variable: '--rfr-slide-bg', fallback: 'hsl(var(--background))' },\n fg: { variable: '--rfr-slide-fg', fallback: 'hsl(var(--foreground))' },\n progressBg: { variable: '--rfr-slide-progress-bg', fallback: 'hsl(var(--primary))' },\n progressTrack: { variable: '--rfr-slide-progress-track', fallback: 'hsl(var(--muted))' },\n badgeBg: { variable: '--rfr-slide-badge-bg', fallback: 'hsl(var(--secondary))' },\n },\n}\n\nexport const slideViewerVariants = cva({\n base: 'flex flex-col h-full w-full relative overflow-hidden',\n variants: {\n size: {\n compact: 'max-w-2xl',\n default: 'max-w-4xl',\n full: 'max-w-none',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n})\n\nconst slideViewerProgressBarVariants = cva({\n base: 'h-1 w-full bg-muted rounded-full overflow-hidden',\n variants: {\n position: {\n top: 'rounded-none',\n bottom: 'rounded-none',\n inline: 'rounded-full',\n },\n },\n defaultVariants: {\n position: 'top',\n },\n})\n\nexport { slideViewerProgressBarVariants as progressBarVariants }\n\nexport const slideTypeBadgeVariants = cva({\n base: 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n variants: {\n // Slide-type accents are a content-category palette (lesson/quiz/exercise…),\n // not status tones — deliberately not routed through the theme tokens.\n type: {\n lesson: 'bg-blue-100 text-blue-800',\n quiz: 'bg-purple-100 text-purple-800',\n exercise: 'bg-green-100 text-green-800',\n intro: 'bg-gray-100 text-gray-800',\n summary: 'bg-orange-100 text-orange-800',\n },\n },\n defaultVariants: {\n type: 'lesson',\n },\n})\n", "import * as React from 'react'\nimport {\n createSlideViewer,\n slideViewerVariants,\n progressBarVariants,\n slideTypeBadgeVariants,\n type SlideData,\n type BookmarkType,\n type SlideType,\n} from '@refraction-ui/slide-viewer'\nimport { cn } from '@refraction-ui/shared'\n\nexport type { SlideData, BookmarkType, SlideType }\n\nexport interface SlideViewerProps {\n slides: SlideData[]\n initialSlide?: number\n onSlideChange?: (index: number) => void\n onComplete?: () => void\n className?: string\n size?: 'compact' | 'default' | 'full'\n /** Render function for custom slide content */\n renderSlide?: (slide: SlideData, index: number) => React.ReactNode\n}\n\n/**\n * SlideViewer component — slide-based content viewer with navigation,\n * progress bar, type badges, and bookmark support.\n *\n * Uses the headless @refraction-ui/slide-viewer core for state and navigation.\n */\nexport const SlideViewer = React.forwardRef<HTMLDivElement, SlideViewerProps>(\n function SlideViewer(\n {\n slides,\n initialSlide,\n onSlideChange,\n onComplete,\n className,\n size,\n renderSlide,\n },\n ref,\n ) {\n const [, setTick] = React.useState(0)\n const rerender = () => setTick((t) => t + 1)\n\n const apiRef = React.useRef(\n createSlideViewer({ slides, initialSlide, onSlideChange, onComplete }),\n )\n const api = apiRef.current\n\n const containerClasses = cn(slideViewerVariants({ size }), className)\n const currentSlide = slides[api.state.currentSlide]\n const slideAriaProps = api.getSlideAriaProps()\n // The core's keyboard handlers mutate state in place; re-render after a\n // handled key so the counter, progress bar, and buttons stay in sync.\n function handleKeyDown(event: KeyboardEvent) {\n const handler =\n api.keyboardHandlers[event.key as keyof typeof api.keyboardHandlers]\n if (!handler) return\n handler(event)\n rerender()\n }\n\n function handlePrev() {\n api.prev()\n rerender()\n }\n\n function handleNext() {\n api.next()\n rerender()\n }\n\n function handleBookmark(type: BookmarkType) {\n api.toggleBookmark(type)\n rerender()\n }\n\n const isBookmarked = api.state.bookmarks.has(api.state.currentSlide)\n\n return (\n <div\n ref={ref}\n className={containerClasses}\n onKeyDown={handleKeyDown as unknown as React.KeyboardEventHandler}\n tabIndex={0}\n >\n {/* Progress bar */}\n <div className={progressBarVariants({ position: 'top' })}>\n <div\n className=\"h-full bg-primary transition-all duration-300\"\n style={{ width: `${api.progress * 100}%` }}\n />\n </div>\n\n {/* Header with type badge and bookmark */}\n <div className=\"flex items-center justify-between px-4 py-2 border-b\">\n <div className=\"flex items-center gap-2\">\n {currentSlide && (\n <span className={slideTypeBadgeVariants({ type: currentSlide.type })}>\n {currentSlide.type}\n </span>\n )}\n <span className=\"text-sm text-muted-foreground\">\n {api.state.currentSlide + 1} / {api.state.totalSlides}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={() => handleBookmark('important')}\n className={cn(\n 'px-2 py-1 rounded text-xs transition-colors',\n isBookmarked\n ? 'bg-yellow-100 text-yellow-800'\n : 'hover:bg-muted text-muted-foreground',\n )}\n aria-pressed={isBookmarked}\n aria-label=\"Toggle bookmark\"\n >\n {isBookmarked ? 'Bookmarked' : 'Bookmark'}\n </button>\n </div>\n\n {/* Slide content */}\n <div className=\"flex-1 overflow-auto p-6\" {...slideAriaProps}>\n {currentSlide &&\n (renderSlide\n ? renderSlide(currentSlide, api.state.currentSlide)\n : <div dangerouslySetInnerHTML={{ __html: currentSlide.content }} />)}\n </div>\n\n {/* Navigation buttons */}\n <div className=\"flex items-center justify-between px-4 py-3 border-t\">\n <button\n type=\"button\"\n onClick={handlePrev}\n disabled={api.state.currentSlide === 0}\n className=\"px-4 py-2 rounded text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed hover:bg-muted transition-colors\"\n aria-label=\"Previous slide\"\n >\n Previous\n </button>\n <button\n type=\"button\"\n onClick={handleNext}\n className=\"px-4 py-2 rounded text-sm font-medium bg-primary text-primary-foreground hover:bg-primary/90 transition-colors\"\n aria-label={\n api.state.currentSlide === api.state.totalSlides - 1\n ? 'Complete'\n : 'Next slide'\n }\n >\n {api.state.currentSlide === api.state.totalSlides - 1 ? 'Complete' : 'Next'}\n </button>\n </div>\n </div>\n )\n },\n)\n"],
5
+ "mappings": ";;;;;;;;;;AAqDO,SAAS,kBAAkB,OAAyC;AACzE,QAAM,EAAE,QAAQ,eAAe,GAAG,eAAe,WAAA,IAAe;AAEhE,QAAM,cAAc,OAAO;AAC3B,QAAM,YAAA,oBAAgB,IAAA;AAEtB,QAAM,QAA0B;IAC9B,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,cAAc,cAAc,CAAC,CAAC;IACjE;IACA;EAAA;AAGF,WAAS,iBAAyB;AAChC,QAAI,eAAe,EAAG,QAAO;AAC7B,WAAO,MAAM,gBAAgB,cAAc;EAC7C;AAEA,WAAS,OAAO;AACd,QAAI,MAAM,eAAe,cAAc,GAAG;AACxC,YAAM;AACN,UAAI,WAAW,eAAA;AACf,sBAAgB,MAAM,YAAY;IACpC,OAAO;AAEL,mBAAA;IACF;EACF;AAEA,WAAS,OAAO;AACd,QAAI,MAAM,eAAe,GAAG;AAC1B,YAAM;AACN,UAAI,WAAW,eAAA;AACf,sBAAgB,MAAM,YAAY;IACpC;EACF;AAEA,WAAS,KAAK,OAAe;AAC3B,QAAI,SAAS,KAAK,QAAQ,aAAa;AACrC,YAAM,eAAe;AACrB,UAAI,WAAW,eAAA;AACf,sBAAgB,MAAM,YAAY;IACpC;EACF;AAEA,WAAS,eAAe,MAAoB;AAC1C,UAAM,UAAU,MAAM;AACtB,QAAI,UAAU,IAAI,OAAO,KAAK,UAAU,IAAI,OAAO,MAAM,MAAM;AAC7D,gBAAU,OAAO,OAAO;IAC1B,OAAO;AACL,gBAAU,IAAI,SAAS,IAAI;IAC7B;EACF;AAEA,WAAS,eAA6D;AACpE,UAAM,SAAuD,CAAA;AAC7D,eAAW,CAAC,OAAO,IAAI,KAAK,UAAU,QAAA,GAAW;AAC/C,aAAO,KAAK,EAAE,OAAO,KAAA,CAAM;IAC7B;AACA,WAAO,OAAO,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;EAChD;AAEA,QAAM,mBAAuC;IAC3C,CAAC,KAAK,UAAU,GAAG,CAAC,MAAM;AACxB,QAAE,eAAA;AACF,WAAA;IACF;IACA,CAAC,KAAK,SAAS,GAAG,CAAC,MAAM;AACvB,QAAE,eAAA;AACF,WAAA;IACF;IACA,CAAC,KAAK,MAAM,GAAG,CAAC,MAAM;AACpB,QAAE,eAAA;IACJ;EAAA;AAGF,WAAS,oBAAuF;AAC9F,UAAM,QAAQ,OAAO,MAAM,YAAY;AACvC,WAAO;MACL,MAAM;MACN,wBAAwB;MACxB,cAAc,SAAS,MAAM,eAAe,CAAC,OAAO,WAAW,KAAK,OAAO,QAAQ,SAAS;MAC5F,aAAa;IAAA;EAEjB;AAEA,QAAM,MAAsB;IAC1B;IACA;IACA;IACA;IACA;IACA;IACA,UAAU,eAAA;IACV;IACA;EAAA;AAGF,SAAO;AACT;ACpJO,IAAM,oBAAmC;EAC9C,MAAM;EACN,QAAQ;IACN,IAAI,EAAE,UAAU,kBAAkB,UAAU,yBAAA;IAC5C,IAAI,EAAE,UAAU,kBAAkB,UAAU,yBAAA;IAC5C,YAAY,EAAE,UAAU,2BAA2B,UAAU,sBAAA;IAC7D,eAAe,EAAE,UAAU,8BAA8B,UAAU,oBAAA;IACnE,SAAS,EAAE,UAAU,wBAAwB,UAAU,wBAAA;EAAwB;AAEnF;AAEO,IAAM,sBAAsB,IAAI;EACrC,MAAM;EACN,UAAU;IACR,MAAM;MACJ,SAAS;MACT,SAAS;MACT,MAAM;IAAA;EACR;EAEF,iBAAiB;IACf,MAAM;EAAA;AAEV,CAAC;AAED,IAAM,iCAAiC,IAAI;EACzC,MAAM;EACN,UAAU;IACR,UAAU;MACR,KAAK;MACL,QAAQ;MACR,QAAQ;IAAA;EACV;EAEF,iBAAiB;IACf,UAAU;EAAA;AAEd,CAAC;AAIM,IAAM,yBAAyB,IAAI;EACxC,MAAM;EACN,UAAU;;;IAGR,MAAM;MACJ,QAAQ;MACR,MAAM;MACN,UAAU;MACV,OAAO;MACP,SAAS;IAAA;EACX;EAEF,iBAAiB;IACf,MAAM;EAAA;AAEV,CAAC;;;;AC7BM,IAAM,cAAoB;EAC/B,SAASA,aACP;IACE;IACA;IACA;IACA;IACA;IACA;IACA;EAAA,GAEF,KACA;AACA,UAAM,CAAA,EAAG,OAAO,IAAU,eAAS,CAAC;AACpC,UAAM,WAAW,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC;AAE3C,UAAM,SAAe;MACnB,kBAAkB,EAAE,QAAQ,cAAc,eAAe,WAAA,CAAY;IAAA;AAEvE,UAAM,MAAM,OAAO;AAEnB,UAAM,mBAAmB,GAAG,oBAAoB,EAAE,KAAA,CAAM,GAAG,SAAS;AACpE,UAAM,eAAe,OAAO,IAAI,MAAM,YAAY;AAClD,UAAM,iBAAiB,IAAI,kBAAA;AAG3B,aAAS,cAAc,OAAsB;AAC3C,YAAM,UACJ,IAAI,iBAAiB,MAAM,GAAwC;AACrE,UAAI,CAAC,QAAS;AACd,cAAQ,KAAK;AACb,eAAA;IACF;AAEA,aAAS,aAAa;AACpB,UAAI,KAAA;AACJ,eAAA;IACF;AAEA,aAAS,aAAa;AACpB,UAAI,KAAA;AACJ,eAAA;IACF;AAEA,aAAS,eAAe,MAAoB;AAC1C,UAAI,eAAe,IAAI;AACvB,eAAA;IACF;AAEA,UAAM,eAAe,IAAI,MAAM,UAAU,IAAI,IAAI,MAAM,YAAY;AAEnE,WACE;MAAC;MAAA;QACC;QACA,WAAW;QACX,WAAW;QACX,UAAU;QAGV,UAAA;UAAA,oBAAC,OAAA,EAAI,WAAW,+BAAoB,EAAE,UAAU,MAAA,CAAO,GACrD,UAAA;YAAC;YAAA;cACC,WAAU;cACV,OAAO,EAAE,OAAO,GAAG,IAAI,WAAW,GAAG,IAAA;YAAI;UAAA,EAC3C,CACF;UAGA,qBAAC,OAAA,EAAI,WAAU,wDACb,UAAA;YAAA,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;cAAA,gBACC,oBAAC,QAAA,EAAK,WAAW,uBAAuB,EAAE,MAAM,aAAa,KAAA,CAAM,GAChE,UAAA,aAAa,KAAA,CAChB;cAEF,qBAAC,QAAA,EAAK,WAAU,iCACb,UAAA;gBAAA,IAAI,MAAM,eAAe;gBAAE;gBAAI,IAAI,MAAM;cAAA,EAAA,CAC5C;YAAA,EAAA,CACF;YACA;cAAC;cAAA;gBACC,MAAK;gBACL,SAAS,MAAM,eAAe,WAAW;gBACzC,WAAW;kBACT;kBACA,eACI,kCACA;gBAAA;gBAEN,gBAAc;gBACd,cAAW;gBAEV,UAAA,eAAe,eAAe;cAAA;YAAA;UACjC,EAAA,CACF;UAGA,oBAAC,OAAA,EAAI,WAAU,4BAA4B,GAAG,gBAC3C,UAAA,iBACE,cACG,YAAY,cAAc,IAAI,MAAM,YAAY,IAAA,oBAC/C,OAAA,EAAI,yBAAyB,EAAE,QAAQ,aAAa,QAAA,EAAQ,CAAG,GAAA,CACxE;UAGA,qBAAC,OAAA,EAAI,WAAU,wDACb,UAAA;YAAA;cAAC;cAAA;gBACC,MAAK;gBACL,SAAS;gBACT,UAAU,IAAI,MAAM,iBAAiB;gBACrC,WAAU;gBACV,cAAW;gBACZ,UAAA;cAAA;YAAA;YAGD;cAAC;cAAA;gBACC,MAAK;gBACL,SAAS;gBACT,WAAU;gBACV,cACE,IAAI,MAAM,iBAAiB,IAAI,MAAM,cAAc,IAC/C,aACA;gBAGL,UAAA,IAAI,MAAM,iBAAiB,IAAI,MAAM,cAAc,IAAI,aAAa;cAAA;YAAA;UACvE,EAAA,CACF;QAAA;MAAA;IAAA;EAGN;AACF;",
6
6
  "names": ["SlideViewer"]
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  cn
3
- } from "./chunk-ZF3OHCGV.js";
3
+ } from "./chunk-2Q6HHFAN.js";
4
4
 
5
5
  // ../react-slider/dist/index.js
6
6
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-slot-picker/dist/index.js
7
7
  import * as React from "react";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  Button
3
- } from "./chunk-F7B64KT3.js";
4
- import "./chunk-WK2IIUFO.js";
3
+ } from "./chunk-3Y2T26QD.js";
4
+ import "./chunk-QDMLIDYN.js";
5
5
  import {
6
6
  cn,
7
7
  cva
8
- } from "./chunk-ZF3OHCGV.js";
8
+ } from "./chunk-2Q6HHFAN.js";
9
9
 
10
10
  // ../react-social-auth-button/dist/index.js
11
11
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-sortable-list/dist/index.js
7
7
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-stat-grid/dist/index.js
7
7
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-status-indicator/dist/index.js
7
7
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-steps/dist/index.js
7
7
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-sticky-note/dist/index.js
7
7
  import * as React from "react";
@@ -33,6 +33,8 @@ var stickyNoteVariants = cva({
33
33
  "min-w-[160px] min-h-[120px]"
34
34
  ].join(" "),
35
35
  variants: {
36
+ // Named paper colors are product semantics (physical sticky notes),
37
+ // not status tones — deliberately not routed through the theme tokens.
36
38
  color: {
37
39
  yellow: "bg-yellow-100 text-yellow-900",
38
40
  pink: "bg-pink-100 text-pink-900",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../sticky-note/src/sticky-note.ts", "../../sticky-note/src/sticky-note.styles.ts", "../../react-sticky-note/src/sticky-note.tsx"],
4
- "sourcesContent": ["/** The available color variants for a sticky note. */\nexport type StickyNoteColor = 'yellow' | 'pink' | 'blue' | 'green' | 'purple' | 'orange'\n\n/** Ordered list of all sticky note colors — used for cycling and iteration. */\nexport const STICKY_NOTE_COLORS: StickyNoteColor[] = [\n 'yellow',\n 'pink',\n 'blue',\n 'green',\n 'purple',\n 'orange',\n]\n\n/**\n * Returns the next color in the cycle. Wraps from the last color back to the\n * first. Useful for \"add note\" flows that auto-assign colors in sequence.\n */\nexport function nextStickyColor(color: StickyNoteColor): StickyNoteColor {\n const index = STICKY_NOTE_COLORS.indexOf(color)\n const next = (index + 1) % STICKY_NOTE_COLORS.length\n return STICKY_NOTE_COLORS[next]\n}\n\nexport interface CreateStickyNoteOptions {\n /** Color of the note. */\n color: StickyNoteColor\n}\n\nexport interface StickyNoteAPI {\n /** Data attributes for styling hooks; spread onto the note container. */\n dataAttributes: { 'data-color': StickyNoteColor }\n /** ARIA props for the note container. */\n ariaProps: { role: 'group' }\n}\n\n/**\n * Build the framework-agnostic props for a sticky note container.\n *\n * Returns `role=\"group\"` plus the `data-color` attribute that adapters use\n * as a styling hook. Logic is pure and SSR-safe — no Math.random, no Date.\n */\nexport function createStickyNote(options: CreateStickyNoteOptions): StickyNoteAPI {\n return {\n dataAttributes: { 'data-color': options.color },\n ariaProps: { role: 'group' },\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\n/**\n * Note container with color variant.\n *\n * Sticky notes are intrinsically colorful — an approved exception to the\n * semantic-token-only rule. Each color maps to a soft tint background with a\n * readable dark text.\n */\nexport const stickyNoteVariants = cva({\n base: [\n 'relative inline-flex flex-col gap-2 rounded-md p-4',\n 'shadow-md',\n 'min-w-[160px] min-h-[120px]',\n ].join(' '),\n variants: {\n color: {\n yellow: 'bg-yellow-100 text-yellow-900',\n pink: 'bg-pink-100 text-pink-900',\n blue: 'bg-blue-100 text-blue-900',\n green: 'bg-green-100 text-green-900',\n purple: 'bg-purple-100 text-purple-900',\n orange: 'bg-orange-100 text-orange-900',\n },\n },\n defaultVariants: {\n color: 'yellow',\n },\n})\n\n/** Class for the editable/static text area inside the note. */\nexport const stickyNoteTextClass =\n 'flex-1 w-full resize-none bg-transparent text-sm leading-relaxed placeholder:opacity-60 outline-none'\n\n/** Class for the author chip rendered in the note footer. */\nexport const stickyNoteAuthorClass =\n 'mt-auto text-xs font-medium opacity-70 truncate'\n", "import * as React from 'react'\nimport {\n createStickyNote,\n stickyNoteVariants,\n stickyNoteTextClass,\n stickyNoteAuthorClass,\n type StickyNoteColor,\n} from '@refraction-ui/sticky-note'\nimport { cn } from '@refraction-ui/shared'\n\nexport type { StickyNoteColor }\n\nexport interface StickyNoteProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content' | 'onSelect'> {\n /** Color of the sticky note. */\n color?: StickyNoteColor\n /** Text content of the note. */\n text?: string\n /** Called when the text changes (makes text editable via a textarea). */\n onTextChange?: (value: string) => void\n /** Optional author name shown in the note footer. */\n author?: string\n /** Absolute x position in pixels (for board/canvas placement). */\n x?: number\n /** Absolute y position in pixels (for board/canvas placement). */\n y?: number\n /** Whether the note can be dragged. Requires `onMove` to receive updates. */\n draggable?: boolean\n /** Called with the new `{ x, y }` position after a drag completes. */\n onMove?: (position: { x: number; y: number }) => void\n}\n\n/**\n * StickyNote — a draggable colored note for whiteboard / canvas surfaces.\n *\n * - `color` selects the soft-tint palette (yellow, pink, blue, green, purple, orange).\n * - `text` + `onTextChange` switch to an editable textarea; without `onTextChange` the\n * text is static.\n * - `x` / `y` absolutely position the note; pair with `draggable` + `onMove` for\n * drag-to-reposition. Drag is implemented via pointer events and is SSR-safe (no\n * handlers attach until the component mounts on the client).\n * - Forwards the ref to the outer `<div>`.\n */\nexport const StickyNote = React.forwardRef<HTMLDivElement, StickyNoteProps>(\n function StickyNote(\n {\n color = 'yellow',\n text,\n onTextChange,\n author,\n x,\n y,\n draggable = false,\n onMove,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) {\n const { ariaProps, dataAttributes } = createStickyNote({ color })\n\n // Drag state — kept in refs to avoid re-renders during drag.\n const dragOrigin = React.useRef<{ pointerX: number; pointerY: number; noteX: number; noteY: number } | null>(null)\n\n const positionStyle: React.CSSProperties =\n x !== undefined && y !== undefined\n ? { position: 'absolute', left: x, top: y }\n : {}\n\n const handlePointerDown = React.useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggable || !onMove) return\n // Only primary button.\n if (e.button !== 0) return\n e.currentTarget.setPointerCapture(e.pointerId)\n dragOrigin.current = {\n pointerX: e.clientX,\n pointerY: e.clientY,\n noteX: x ?? 0,\n noteY: y ?? 0,\n }\n },\n [draggable, onMove, x, y],\n )\n\n const handlePointerMove = React.useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (!dragOrigin.current || !onMove) return\n const dx = e.clientX - dragOrigin.current.pointerX\n const dy = e.clientY - dragOrigin.current.pointerY\n onMove({ x: dragOrigin.current.noteX + dx, y: dragOrigin.current.noteY + dy })\n },\n [onMove],\n )\n\n const handlePointerUp = React.useCallback(() => {\n dragOrigin.current = null\n }, [])\n\n return (\n <div\n ref={ref}\n className={cn(stickyNoteVariants({ color }), className)}\n style={{ ...positionStyle, ...style }}\n {...ariaProps}\n {...dataAttributes}\n onPointerDown={draggable && onMove ? handlePointerDown : undefined}\n onPointerMove={draggable && onMove ? handlePointerMove : undefined}\n onPointerUp={draggable && onMove ? handlePointerUp : undefined}\n {...props}\n >\n {onTextChange != null ? (\n <textarea\n className={stickyNoteTextClass}\n value={text ?? ''}\n onChange={(e) => onTextChange(e.target.value)}\n placeholder=\"Type a note…\"\n />\n ) : (\n <p className={`${stickyNoteTextClass} whitespace-pre-wrap`}>{text ?? children}</p>\n )}\n {author != null && (\n <span className={stickyNoteAuthorClass}>{author}</span>\n )}\n </div>\n )\n },\n)\n"],
5
- "mappings": ";;;;;;;;;AAIO,IAAM,qBAAwC;EACnD;EACA;EACA;EACA;EACA;EACA;AACF;AAMO,SAAS,gBAAgB,OAAyC;AACvE,QAAM,QAAQ,mBAAmB,QAAQ,KAAK;AAC9C,QAAM,QAAQ,QAAQ,KAAK,mBAAmB;AAC9C,SAAO,mBAAmB,IAAI;AAChC;AAoBO,SAAS,iBAAiB,SAAiD;AAChF,SAAO;IACL,gBAAgB,EAAE,cAAc,QAAQ,MAAA;IACxC,WAAW,EAAE,MAAM,QAAA;EAAQ;AAE/B;ACrCO,IAAM,qBAAqB,IAAI;EACpC,MAAM;IACJ;IACA;IACA;EAAA,EACA,KAAK,GAAG;EACV,UAAU;IACR,OAAO;MACL,QAAQ;MACR,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;MACR,QAAQ;IAAA;EACV;EAEF,iBAAiB;IACf,OAAO;EAAA;AAEX,CAAC;AAGM,IAAM,sBACX;AAGK,IAAM,wBACX;;;;ACOK,IAAM,aAAmB;EAC9B,SAASA,YACP;IACE,QAAQ;IACR;IACA;IACA;IACA;IACA;IACA,YAAY;IACZ;IACA;IACA;IACA;IACA,GAAG;EAAA,GAEL,KACA;AACA,UAAM,EAAE,WAAW,eAAA,IAAmB,iBAAiB,EAAE,MAAA,CAAO;AAGhE,UAAM,aAAmB,aAAoF,IAAI;AAEjH,UAAM,gBACJ,MAAM,UAAa,MAAM,SACrB,EAAE,UAAU,YAAY,MAAM,GAAG,KAAK,EAAA,IACtC,CAAA;AAEN,UAAM,oBAA0B;MAC9B,CAAC,MAA0C;AACzC,YAAI,CAAC,aAAa,CAAC,OAAQ;AAE3B,YAAI,EAAE,WAAW,EAAG;AACpB,UAAE,cAAc,kBAAkB,EAAE,SAAS;AAC7C,mBAAW,UAAU;UACnB,UAAU,EAAE;UACZ,UAAU,EAAE;UACZ,OAAO,KAAK;UACZ,OAAO,KAAK;QAAA;MAEhB;MACA,CAAC,WAAW,QAAQ,GAAG,CAAC;IAAA;AAG1B,UAAM,oBAA0B;MAC9B,CAAC,MAA0C;AACzC,YAAI,CAAC,WAAW,WAAW,CAAC,OAAQ;AACpC,cAAM,KAAK,EAAE,UAAU,WAAW,QAAQ;AAC1C,cAAM,KAAK,EAAE,UAAU,WAAW,QAAQ;AAC1C,eAAO,EAAE,GAAG,WAAW,QAAQ,QAAQ,IAAI,GAAG,WAAW,QAAQ,QAAQ,GAAA,CAAI;MAC/E;MACA,CAAC,MAAM;IAAA;AAGT,UAAM,kBAAwB,kBAAY,MAAM;AAC9C,iBAAW,UAAU;IACvB,GAAG,CAAA,CAAE;AAEL,WACE;MAAC;MAAA;QACC;QACA,WAAW,GAAG,mBAAmB,EAAE,MAAA,CAAO,GAAG,SAAS;QACtD,OAAO,EAAE,GAAG,eAAe,GAAG,MAAA;QAC7B,GAAG;QACH,GAAG;QACJ,eAAe,aAAa,SAAS,oBAAoB;QACzD,eAAe,aAAa,SAAS,oBAAoB;QACzD,aAAa,aAAa,SAAS,kBAAkB;QACpD,GAAG;QAEH,UAAA;UAAA,gBAAgB,OACf;YAAC;YAAA;cACC,WAAW;cACX,OAAO,QAAQ;cACf,UAAU,CAAC,MAAM,aAAa,EAAE,OAAO,KAAK;cAC5C,aAAY;YAAA;UAAA,IACd,oBAEC,KAAA,EAAE,WAAW,GAAG,mBAAmB,wBAAyB,UAAA,QAAQ,SAAA,CAAS;UAE/E,UAAU,QACT,oBAAC,QAAA,EAAK,WAAW,uBAAwB,UAAA,OAAA,CAAO;QAAA;MAAA;IAAA;EAIxD;AACF;",
4
+ "sourcesContent": ["/** The available color variants for a sticky note. */\nexport type StickyNoteColor = 'yellow' | 'pink' | 'blue' | 'green' | 'purple' | 'orange'\n\n/** Ordered list of all sticky note colors — used for cycling and iteration. */\nexport const STICKY_NOTE_COLORS: StickyNoteColor[] = [\n 'yellow',\n 'pink',\n 'blue',\n 'green',\n 'purple',\n 'orange',\n]\n\n/**\n * Returns the next color in the cycle. Wraps from the last color back to the\n * first. Useful for \"add note\" flows that auto-assign colors in sequence.\n */\nexport function nextStickyColor(color: StickyNoteColor): StickyNoteColor {\n const index = STICKY_NOTE_COLORS.indexOf(color)\n const next = (index + 1) % STICKY_NOTE_COLORS.length\n return STICKY_NOTE_COLORS[next]\n}\n\nexport interface CreateStickyNoteOptions {\n /** Color of the note. */\n color: StickyNoteColor\n}\n\nexport interface StickyNoteAPI {\n /** Data attributes for styling hooks; spread onto the note container. */\n dataAttributes: { 'data-color': StickyNoteColor }\n /** ARIA props for the note container. */\n ariaProps: { role: 'group' }\n}\n\n/**\n * Build the framework-agnostic props for a sticky note container.\n *\n * Returns `role=\"group\"` plus the `data-color` attribute that adapters use\n * as a styling hook. Logic is pure and SSR-safe — no Math.random, no Date.\n */\nexport function createStickyNote(options: CreateStickyNoteOptions): StickyNoteAPI {\n return {\n dataAttributes: { 'data-color': options.color },\n ariaProps: { role: 'group' },\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\n/**\n * Note container with color variant.\n *\n * Sticky notes are intrinsically colorful — an approved exception to the\n * semantic-token-only rule. Each color maps to a soft tint background with a\n * readable dark text.\n */\nexport const stickyNoteVariants = cva({\n base: [\n 'relative inline-flex flex-col gap-2 rounded-md p-4',\n 'shadow-md',\n 'min-w-[160px] min-h-[120px]',\n ].join(' '),\n variants: {\n // Named paper colors are product semantics (physical sticky notes),\n // not status tones — deliberately not routed through the theme tokens.\n color: {\n yellow: 'bg-yellow-100 text-yellow-900',\n pink: 'bg-pink-100 text-pink-900',\n blue: 'bg-blue-100 text-blue-900',\n green: 'bg-green-100 text-green-900',\n purple: 'bg-purple-100 text-purple-900',\n orange: 'bg-orange-100 text-orange-900',\n },\n },\n defaultVariants: {\n color: 'yellow',\n },\n})\n\n/** Class for the editable/static text area inside the note. */\nexport const stickyNoteTextClass =\n 'flex-1 w-full resize-none bg-transparent text-sm leading-relaxed placeholder:opacity-60 outline-none'\n\n/** Class for the author chip rendered in the note footer. */\nexport const stickyNoteAuthorClass =\n 'mt-auto text-xs font-medium opacity-70 truncate'\n", "import * as React from 'react'\nimport {\n createStickyNote,\n stickyNoteVariants,\n stickyNoteTextClass,\n stickyNoteAuthorClass,\n type StickyNoteColor,\n} from '@refraction-ui/sticky-note'\nimport { cn } from '@refraction-ui/shared'\n\nexport type { StickyNoteColor }\n\nexport interface StickyNoteProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content' | 'onSelect'> {\n /** Color of the sticky note. */\n color?: StickyNoteColor\n /** Text content of the note. */\n text?: string\n /** Called when the text changes (makes text editable via a textarea). */\n onTextChange?: (value: string) => void\n /** Optional author name shown in the note footer. */\n author?: string\n /** Absolute x position in pixels (for board/canvas placement). */\n x?: number\n /** Absolute y position in pixels (for board/canvas placement). */\n y?: number\n /** Whether the note can be dragged. Requires `onMove` to receive updates. */\n draggable?: boolean\n /** Called with the new `{ x, y }` position after a drag completes. */\n onMove?: (position: { x: number; y: number }) => void\n}\n\n/**\n * StickyNote — a draggable colored note for whiteboard / canvas surfaces.\n *\n * - `color` selects the soft-tint palette (yellow, pink, blue, green, purple, orange).\n * - `text` + `onTextChange` switch to an editable textarea; without `onTextChange` the\n * text is static.\n * - `x` / `y` absolutely position the note; pair with `draggable` + `onMove` for\n * drag-to-reposition. Drag is implemented via pointer events and is SSR-safe (no\n * handlers attach until the component mounts on the client).\n * - Forwards the ref to the outer `<div>`.\n */\nexport const StickyNote = React.forwardRef<HTMLDivElement, StickyNoteProps>(\n function StickyNote(\n {\n color = 'yellow',\n text,\n onTextChange,\n author,\n x,\n y,\n draggable = false,\n onMove,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) {\n const { ariaProps, dataAttributes } = createStickyNote({ color })\n\n // Drag state — kept in refs to avoid re-renders during drag.\n const dragOrigin = React.useRef<{ pointerX: number; pointerY: number; noteX: number; noteY: number } | null>(null)\n\n const positionStyle: React.CSSProperties =\n x !== undefined && y !== undefined\n ? { position: 'absolute', left: x, top: y }\n : {}\n\n const handlePointerDown = React.useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggable || !onMove) return\n // Only primary button.\n if (e.button !== 0) return\n e.currentTarget.setPointerCapture(e.pointerId)\n dragOrigin.current = {\n pointerX: e.clientX,\n pointerY: e.clientY,\n noteX: x ?? 0,\n noteY: y ?? 0,\n }\n },\n [draggable, onMove, x, y],\n )\n\n const handlePointerMove = React.useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (!dragOrigin.current || !onMove) return\n const dx = e.clientX - dragOrigin.current.pointerX\n const dy = e.clientY - dragOrigin.current.pointerY\n onMove({ x: dragOrigin.current.noteX + dx, y: dragOrigin.current.noteY + dy })\n },\n [onMove],\n )\n\n const handlePointerUp = React.useCallback(() => {\n dragOrigin.current = null\n }, [])\n\n return (\n <div\n ref={ref}\n className={cn(stickyNoteVariants({ color }), className)}\n style={{ ...positionStyle, ...style }}\n {...ariaProps}\n {...dataAttributes}\n onPointerDown={draggable && onMove ? handlePointerDown : undefined}\n onPointerMove={draggable && onMove ? handlePointerMove : undefined}\n onPointerUp={draggable && onMove ? handlePointerUp : undefined}\n {...props}\n >\n {onTextChange != null ? (\n <textarea\n className={stickyNoteTextClass}\n value={text ?? ''}\n onChange={(e) => onTextChange(e.target.value)}\n placeholder=\"Type a note…\"\n />\n ) : (\n <p className={`${stickyNoteTextClass} whitespace-pre-wrap`}>{text ?? children}</p>\n )}\n {author != null && (\n <span className={stickyNoteAuthorClass}>{author}</span>\n )}\n </div>\n )\n },\n)\n"],
5
+ "mappings": ";;;;;;;;;AAIO,IAAM,qBAAwC;EACnD;EACA;EACA;EACA;EACA;EACA;AACF;AAMO,SAAS,gBAAgB,OAAyC;AACvE,QAAM,QAAQ,mBAAmB,QAAQ,KAAK;AAC9C,QAAM,QAAQ,QAAQ,KAAK,mBAAmB;AAC9C,SAAO,mBAAmB,IAAI;AAChC;AAoBO,SAAS,iBAAiB,SAAiD;AAChF,SAAO;IACL,gBAAgB,EAAE,cAAc,QAAQ,MAAA;IACxC,WAAW,EAAE,MAAM,QAAA;EAAQ;AAE/B;ACrCO,IAAM,qBAAqB,IAAI;EACpC,MAAM;IACJ;IACA;IACA;EAAA,EACA,KAAK,GAAG;EACV,UAAU;;;IAGR,OAAO;MACL,QAAQ;MACR,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;MACR,QAAQ;IAAA;EACV;EAEF,iBAAiB;IACf,OAAO;EAAA;AAEX,CAAC;AAGM,IAAM,sBACX;AAGK,IAAM,wBACX;;;;ACKK,IAAM,aAAmB;EAC9B,SAASA,YACP;IACE,QAAQ;IACR;IACA;IACA;IACA;IACA;IACA,YAAY;IACZ;IACA;IACA;IACA;IACA,GAAG;EAAA,GAEL,KACA;AACA,UAAM,EAAE,WAAW,eAAA,IAAmB,iBAAiB,EAAE,MAAA,CAAO;AAGhE,UAAM,aAAmB,aAAoF,IAAI;AAEjH,UAAM,gBACJ,MAAM,UAAa,MAAM,SACrB,EAAE,UAAU,YAAY,MAAM,GAAG,KAAK,EAAA,IACtC,CAAA;AAEN,UAAM,oBAA0B;MAC9B,CAAC,MAA0C;AACzC,YAAI,CAAC,aAAa,CAAC,OAAQ;AAE3B,YAAI,EAAE,WAAW,EAAG;AACpB,UAAE,cAAc,kBAAkB,EAAE,SAAS;AAC7C,mBAAW,UAAU;UACnB,UAAU,EAAE;UACZ,UAAU,EAAE;UACZ,OAAO,KAAK;UACZ,OAAO,KAAK;QAAA;MAEhB;MACA,CAAC,WAAW,QAAQ,GAAG,CAAC;IAAA;AAG1B,UAAM,oBAA0B;MAC9B,CAAC,MAA0C;AACzC,YAAI,CAAC,WAAW,WAAW,CAAC,OAAQ;AACpC,cAAM,KAAK,EAAE,UAAU,WAAW,QAAQ;AAC1C,cAAM,KAAK,EAAE,UAAU,WAAW,QAAQ;AAC1C,eAAO,EAAE,GAAG,WAAW,QAAQ,QAAQ,IAAI,GAAG,WAAW,QAAQ,QAAQ,GAAA,CAAI;MAC/E;MACA,CAAC,MAAM;IAAA;AAGT,UAAM,kBAAwB,kBAAY,MAAM;AAC9C,iBAAW,UAAU;IACvB,GAAG,CAAA,CAAE;AAEL,WACE;MAAC;MAAA;QACC;QACA,WAAW,GAAG,mBAAmB,EAAE,MAAA,CAAO,GAAG,SAAS;QACtD,OAAO,EAAE,GAAG,eAAe,GAAG,MAAA;QAC7B,GAAG;QACH,GAAG;QACJ,eAAe,aAAa,SAAS,oBAAoB;QACzD,eAAe,aAAa,SAAS,oBAAoB;QACzD,aAAa,aAAa,SAAS,kBAAkB;QACpD,GAAG;QAEH,UAAA;UAAA,gBAAgB,OACf;YAAC;YAAA;cACC,WAAW;cACX,OAAO,QAAQ;cACf,UAAU,CAAC,MAAM,aAAa,EAAE,OAAO,KAAK;cAC5C,aAAY;YAAA;UAAA,IACd,oBAEC,KAAA,EAAE,WAAW,GAAG,mBAAmB,wBAAyB,UAAA,QAAQ,SAAA,CAAS;UAE/E,UAAU,QACT,oBAAC,QAAA,EAAK,WAAW,uBAAwB,UAAA,OAAA,CAAO;QAAA;MAAA;IAAA;EAIxD;AACF;",
6
6
  "names": ["StickyNote"]
7
7
  }
@@ -2,7 +2,7 @@ import {
2
2
  Keys,
3
3
  cn,
4
4
  cva
5
- } from "./chunk-ZF3OHCGV.js";
5
+ } from "./chunk-2Q6HHFAN.js";
6
6
 
7
7
  // ../react-switch/dist/index.js
8
8
  import * as React from "react";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  cn
3
- } from "./chunk-ZF3OHCGV.js";
3
+ } from "./chunk-2Q6HHFAN.js";
4
4
 
5
5
  // ../react-table-of-contents/dist/index.js
6
6
  import * as React from "react";
@@ -4,7 +4,7 @@ import {
4
4
  cva,
5
5
  devWarn,
6
6
  generateId
7
- } from "./chunk-ZF3OHCGV.js";
7
+ } from "./chunk-2Q6HHFAN.js";
8
8
 
9
9
  // ../react-tabs/dist/index.js
10
10
  import * as React from "react";
@@ -96,6 +96,23 @@ function createTabs(props = {}) {
96
96
  idPrefix
97
97
  };
98
98
  }
99
+ function getNextTabIndex(current, key, count, orientation = "horizontal") {
100
+ if (count === 0) return null;
101
+ const prev = orientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
102
+ const next = orientation === "horizontal" ? "ArrowRight" : "ArrowDown";
103
+ switch (key) {
104
+ case next:
105
+ return current < 0 ? 0 : (current + 1) % count;
106
+ case prev:
107
+ return current < 0 ? count - 1 : (current - 1 + count) % count;
108
+ case "Home":
109
+ return 0;
110
+ case "End":
111
+ return count - 1;
112
+ default:
113
+ return null;
114
+ }
115
+ }
99
116
  var tabsListVariants = cva({
100
117
  base: "inline-flex max-w-full overflow-x-auto items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground"
101
118
  });
@@ -152,17 +169,48 @@ var Tabs = React.forwardRef(
152
169
  }
153
170
  );
154
171
  var TabsList = React.forwardRef(
155
- function TabsList2({ className, ...props }, ref) {
172
+ function TabsList2({ className, onKeyDown, ...props }, forwardedRef) {
156
173
  const { orientation } = useTabsContext();
174
+ const listRef = React.useRef(null);
175
+ const ref = React.useCallback(
176
+ (node) => {
177
+ listRef.current = node;
178
+ if (typeof forwardedRef === "function") forwardedRef(node);
179
+ else if (forwardedRef) forwardedRef.current = node;
180
+ },
181
+ [forwardedRef]
182
+ );
183
+ React.useEffect(() => {
184
+ const tabs = enabledTabs(listRef.current);
185
+ const stop = tabs.find((tab) => tab.getAttribute("aria-selected") === "true") ?? tabs[0];
186
+ for (const tab of tabs) tab.tabIndex = tab === stop ? 0 : -1;
187
+ });
188
+ const handleKeyDown = (e) => {
189
+ onKeyDown?.(e);
190
+ if (e.defaultPrevented) return;
191
+ const tabs = enabledTabs(listRef.current);
192
+ const current = tabs.indexOf(e.target);
193
+ if (current === -1) return;
194
+ const next = getNextTabIndex(current, e.key, tabs.length, orientation);
195
+ if (next === null) return;
196
+ e.preventDefault();
197
+ tabs[next].focus();
198
+ tabs[next].click();
199
+ };
157
200
  return React.createElement("div", {
158
201
  ref,
159
202
  role: "tablist",
160
203
  "aria-orientation": orientation,
161
204
  className: cn(tabsListVariants(), className),
205
+ onKeyDown: handleKeyDown,
162
206
  ...props
163
207
  });
164
208
  }
165
209
  );
210
+ function enabledTabs(list) {
211
+ if (!list) return [];
212
+ return Array.from(list.querySelectorAll('[role="tab"]:not([disabled])'));
213
+ }
166
214
  var TabsTrigger = React.forwardRef(
167
215
  function TabsTrigger2({ value, className, onClick, onKeyDown, children, ...props }, ref) {
168
216
  const { value: activeValue, onValueChange, orientation, idPrefix } = useTabsContext();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../tabs/src/tabs.ts", "../../tabs/src/tabs.styles.ts", "../../react-tabs/src/tabs.tsx"],
4
- "sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { Keys, generateId } from '@refraction-ui/shared'\n\nexport interface TabsProps {\n /** The active tab value (controlled) */\n value?: string\n /** The default active tab value (uncontrolled) */\n defaultValue?: string\n /** Callback when active tab changes */\n onValueChange?: (value: string) => void\n /** Orientation of the tab list */\n orientation?: 'horizontal' | 'vertical'\n}\n\nexport interface TabsState {\n activeValue: string\n}\n\nexport interface TabsAPI {\n /** Current tabs state */\n state: TabsState\n /** ARIA attributes for the tab list */\n listProps: Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for individual tab trigger props */\n getTabProps(value: string): Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for individual tab panel props */\n getPanelProps(value: string): Partial<AccessibilityProps> & Record<string, unknown>\n /** Select a tab by value */\n select(value: string): void\n /** Keyboard handlers for the tab list */\n keyboardHandlers: KeyboardHandlerMap\n /** Generated ID prefix for aria linking */\n idPrefix: string\n}\n\nexport function createTabs(props: TabsProps = {}): TabsAPI {\n const {\n value: controlledValue,\n defaultValue = '',\n onValueChange,\n orientation = 'horizontal',\n } = props\n\n let uncontrolledValue = controlledValue ?? defaultValue\n const idPrefix = generateId('rfr-tabs')\n\n function getActiveValue(): string {\n if (controlledValue !== undefined) return controlledValue\n return uncontrolledValue\n }\n\n function select(value: string): void {\n uncontrolledValue = value\n onValueChange?.(value)\n }\n\n function getTabId(value: string): string {\n return `${idPrefix}-tab-${value}`\n }\n\n function getPanelId(value: string): string {\n return `${idPrefix}-panel-${value}`\n }\n\n function getTabProps(value: string): Partial<AccessibilityProps> & Record<string, unknown> {\n const isSelected = getActiveValue() === value\n return {\n role: 'tab',\n 'aria-selected': isSelected,\n 'aria-controls': getPanelId(value),\n tabIndex: isSelected ? 0 : -1,\n id: getTabId(value),\n 'data-state': isSelected ? 'active' : 'inactive',\n }\n }\n\n function getPanelProps(value: string): Partial<AccessibilityProps> & Record<string, unknown> {\n const isSelected = getActiveValue() === value\n return {\n role: 'tabpanel',\n 'aria-labelledby': getTabId(value),\n id: getPanelId(value),\n hidden: !isSelected || undefined,\n tabIndex: 0,\n 'data-state': isSelected ? 'active' : 'inactive',\n }\n }\n\n const listProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'tablist',\n 'aria-orientation': orientation,\n }\n\n const keyboardHandlers: KeyboardHandlerMap = orientation === 'horizontal'\n ? {\n [Keys.ArrowLeft]: (e) => {\n e.preventDefault()\n },\n [Keys.ArrowRight]: (e) => {\n e.preventDefault()\n },\n [Keys.Home]: (e) => {\n e.preventDefault()\n },\n [Keys.End]: (e) => {\n e.preventDefault()\n },\n }\n : {\n [Keys.ArrowUp]: (e) => {\n e.preventDefault()\n },\n [Keys.ArrowDown]: (e) => {\n e.preventDefault()\n },\n [Keys.Home]: (e) => {\n e.preventDefault()\n },\n [Keys.End]: (e) => {\n e.preventDefault()\n },\n }\n\n return {\n state: { activeValue: getActiveValue() },\n listProps,\n getTabProps,\n getPanelProps,\n select,\n keyboardHandlers,\n idPrefix,\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const tabsListVariants = cva({\n base: 'inline-flex max-w-full overflow-x-auto items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',\n})\n\nexport const tabsTriggerVariants = cva({\n base: 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',\n})\n", "import * as React from 'react'\nimport {\n createTabs,\n tabsListVariants,\n tabsTriggerVariants,\n type TabsProps as CoreTabsProps,\n} from '@refraction-ui/tabs'\nimport { cn, createKeyboardHandler, Keys, devWarn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface TabsContextValue {\n value: string\n onValueChange: (value: string) => void\n orientation: 'horizontal' | 'vertical'\n idPrefix: string\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null)\n\nfunction useTabsContext(): TabsContextValue {\n const ctx = React.useContext(TabsContext)\n if (!ctx) {\n devWarn(\n 'react-tabs/context-outside-provider',\n 'Tabs compound components (TabsList/TabsTrigger/TabsContent) must be rendered inside a <Tabs>. The missing TabsContext makes this throw.',\n )\n throw new Error('Tabs compound components must be used within <Tabs>')\n }\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Tabs (root provider)\n// ---------------------------------------------------------------------------\n\nexport interface TabsProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n orientation?: 'horizontal' | 'vertical'\n className?: string\n children?: React.ReactNode\n}\n\nexport const Tabs = React.forwardRef<HTMLDivElement, TabsProps>(\n function Tabs({ value: controlledValue, defaultValue = '', onValueChange, orientation = 'horizontal', className, children, ...props }: TabsProps, ref) {\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue)\n const isControlled = controlledValue !== undefined\n const value = isControlled ? controlledValue : uncontrolledValue\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n if (!isControlled) {\n setUncontrolledValue(next)\n }\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n // Use the headless core to get stable IDs\n const apiRef = React.useRef<ReturnType<typeof createTabs> | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createTabs({ value, orientation })\n }\n const api = apiRef.current\n\n const ctx = React.useMemo<TabsContextValue>(\n () => ({\n value,\n onValueChange: handleValueChange,\n orientation,\n idPrefix: api.idPrefix,\n }),\n [value, handleValueChange, orientation, api.idPrefix],\n )\n\n return React.createElement(\n 'div',\n { ref, className, 'data-orientation': orientation, ...props },\n React.createElement(TabsContext.Provider, { value: ctx }, children),\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// TabsList\n// ---------------------------------------------------------------------------\n\nexport interface TabsListProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const TabsList = React.forwardRef<HTMLDivElement, TabsListProps>(\n function TabsList({ className, ...props }, ref) {\n const { orientation } = useTabsContext()\n\n return React.createElement('div', {\n ref,\n role: 'tablist',\n 'aria-orientation': orientation,\n className: cn(tabsListVariants(), className),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// TabsTrigger\n// ---------------------------------------------------------------------------\n\nexport interface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n value: string\n}\n\nexport const TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(\n function TabsTrigger({ value, className, onClick, onKeyDown, children, ...props }, ref) {\n const { value: activeValue, onValueChange, orientation, idPrefix } = useTabsContext()\n\n const isSelected = activeValue === value\n const tabId = `${idPrefix}-tab-${value}`\n const panelId = `${idPrefix}-panel-${value}`\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange(value)\n onClick?.(e)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n // Navigation keys are handled at the list level by convention,\n // but we expose them here for convenience in SSR-only scenarios\n onKeyDown?.(e)\n }\n\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n role: 'tab',\n 'aria-selected': isSelected,\n 'aria-controls': panelId,\n tabIndex: isSelected ? 0 : -1,\n id: tabId,\n 'data-state': isSelected ? 'active' : 'inactive',\n className: cn(tabsTriggerVariants(), className),\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n ...props,\n },\n children,\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// TabsContent\n// ---------------------------------------------------------------------------\n\nexport interface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string\n}\n\nexport const TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(\n function TabsContent({ value, className, children, ...props }, ref) {\n const { value: activeValue, idPrefix } = useTabsContext()\n\n const isSelected = activeValue === value\n const tabId = `${idPrefix}-tab-${value}`\n const panelId = `${idPrefix}-panel-${value}`\n\n if (!isSelected) return null\n\n return React.createElement(\n 'div',\n {\n ref,\n role: 'tabpanel',\n 'aria-labelledby': tabId,\n id: panelId,\n tabIndex: 0,\n 'data-state': 'active',\n className,\n ...props,\n },\n children,\n )\n },\n)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { Keys, generateId } from '@refraction-ui/shared'\n\nexport interface TabsProps {\n /** The active tab value (controlled) */\n value?: string\n /** The default active tab value (uncontrolled) */\n defaultValue?: string\n /** Callback when active tab changes */\n onValueChange?: (value: string) => void\n /** Orientation of the tab list */\n orientation?: 'horizontal' | 'vertical'\n}\n\nexport interface TabsState {\n activeValue: string\n}\n\nexport interface TabsAPI {\n /** Current tabs state */\n state: TabsState\n /** ARIA attributes for the tab list */\n listProps: Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for individual tab trigger props */\n getTabProps(value: string): Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for individual tab panel props */\n getPanelProps(value: string): Partial<AccessibilityProps> & Record<string, unknown>\n /** Select a tab by value */\n select(value: string): void\n /** Keyboard handlers for the tab list */\n keyboardHandlers: KeyboardHandlerMap\n /** Generated ID prefix for aria linking */\n idPrefix: string\n}\n\nexport function createTabs(props: TabsProps = {}): TabsAPI {\n const {\n value: controlledValue,\n defaultValue = '',\n onValueChange,\n orientation = 'horizontal',\n } = props\n\n let uncontrolledValue = controlledValue ?? defaultValue\n const idPrefix = generateId('rfr-tabs')\n\n function getActiveValue(): string {\n if (controlledValue !== undefined) return controlledValue\n return uncontrolledValue\n }\n\n function select(value: string): void {\n uncontrolledValue = value\n onValueChange?.(value)\n }\n\n function getTabId(value: string): string {\n return `${idPrefix}-tab-${value}`\n }\n\n function getPanelId(value: string): string {\n return `${idPrefix}-panel-${value}`\n }\n\n function getTabProps(value: string): Partial<AccessibilityProps> & Record<string, unknown> {\n const isSelected = getActiveValue() === value\n return {\n role: 'tab',\n 'aria-selected': isSelected,\n 'aria-controls': getPanelId(value),\n tabIndex: isSelected ? 0 : -1,\n id: getTabId(value),\n 'data-state': isSelected ? 'active' : 'inactive',\n }\n }\n\n function getPanelProps(value: string): Partial<AccessibilityProps> & Record<string, unknown> {\n const isSelected = getActiveValue() === value\n return {\n role: 'tabpanel',\n 'aria-labelledby': getTabId(value),\n id: getPanelId(value),\n hidden: !isSelected || undefined,\n tabIndex: 0,\n 'data-state': isSelected ? 'active' : 'inactive',\n }\n }\n\n const listProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'tablist',\n 'aria-orientation': orientation,\n }\n\n const keyboardHandlers: KeyboardHandlerMap = orientation === 'horizontal'\n ? {\n [Keys.ArrowLeft]: (e) => {\n e.preventDefault()\n },\n [Keys.ArrowRight]: (e) => {\n e.preventDefault()\n },\n [Keys.Home]: (e) => {\n e.preventDefault()\n },\n [Keys.End]: (e) => {\n e.preventDefault()\n },\n }\n : {\n [Keys.ArrowUp]: (e) => {\n e.preventDefault()\n },\n [Keys.ArrowDown]: (e) => {\n e.preventDefault()\n },\n [Keys.Home]: (e) => {\n e.preventDefault()\n },\n [Keys.End]: (e) => {\n e.preventDefault()\n },\n }\n\n return {\n state: { activeValue: getActiveValue() },\n listProps,\n getTabProps,\n getPanelProps,\n select,\n keyboardHandlers,\n idPrefix,\n }\n}\n\n/**\n * Roving-focus target for a key press inside a tab list (WAI-ARIA Tabs\n * pattern). Given the index of the focused tab among the ENABLED tabs, returns\n * the index to move to, or `null` when the key is not a navigation key for this\n * orientation. Arrow keys wrap; Home/End jump to the ends.\n */\nexport function getNextTabIndex(\n current: number,\n key: string,\n count: number,\n orientation: 'horizontal' | 'vertical' = 'horizontal',\n): number | null {\n if (count === 0) return null\n const prev = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp'\n const next = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown'\n switch (key) {\n case next:\n return current < 0 ? 0 : (current + 1) % count\n case prev:\n return current < 0 ? count - 1 : (current - 1 + count) % count\n case 'Home':\n return 0\n case 'End':\n return count - 1\n default:\n return null\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const tabsListVariants = cva({\n base: 'inline-flex max-w-full overflow-x-auto items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',\n})\n\nexport const tabsTriggerVariants = cva({\n base: 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',\n})\n", "import * as React from 'react'\nimport {\n createTabs,\n getNextTabIndex,\n tabsListVariants,\n tabsTriggerVariants,\n type TabsProps as CoreTabsProps,\n} from '@refraction-ui/tabs'\nimport { cn, createKeyboardHandler, Keys, devWarn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface TabsContextValue {\n value: string\n onValueChange: (value: string) => void\n orientation: 'horizontal' | 'vertical'\n idPrefix: string\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null)\n\nfunction useTabsContext(): TabsContextValue {\n const ctx = React.useContext(TabsContext)\n if (!ctx) {\n devWarn(\n 'react-tabs/context-outside-provider',\n 'Tabs compound components (TabsList/TabsTrigger/TabsContent) must be rendered inside a <Tabs>. The missing TabsContext makes this throw.',\n )\n throw new Error('Tabs compound components must be used within <Tabs>')\n }\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Tabs (root provider)\n// ---------------------------------------------------------------------------\n\nexport interface TabsProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n orientation?: 'horizontal' | 'vertical'\n className?: string\n children?: React.ReactNode\n}\n\nexport const Tabs = React.forwardRef<HTMLDivElement, TabsProps>(\n function Tabs({ value: controlledValue, defaultValue = '', onValueChange, orientation = 'horizontal', className, children, ...props }: TabsProps, ref) {\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue)\n const isControlled = controlledValue !== undefined\n const value = isControlled ? controlledValue : uncontrolledValue\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n if (!isControlled) {\n setUncontrolledValue(next)\n }\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n // Use the headless core to get stable IDs\n const apiRef = React.useRef<ReturnType<typeof createTabs> | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createTabs({ value, orientation })\n }\n const api = apiRef.current\n\n const ctx = React.useMemo<TabsContextValue>(\n () => ({\n value,\n onValueChange: handleValueChange,\n orientation,\n idPrefix: api.idPrefix,\n }),\n [value, handleValueChange, orientation, api.idPrefix],\n )\n\n return React.createElement(\n 'div',\n { ref, className, 'data-orientation': orientation, ...props },\n React.createElement(TabsContext.Provider, { value: ctx }, children),\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// TabsList\n// ---------------------------------------------------------------------------\n\nexport interface TabsListProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const TabsList = React.forwardRef<HTMLDivElement, TabsListProps>(\n function TabsList({ className, onKeyDown, ...props }, forwardedRef) {\n const { orientation } = useTabsContext()\n const listRef = React.useRef<HTMLDivElement | null>(null)\n const ref = React.useCallback(\n (node: HTMLDivElement | null) => {\n listRef.current = node\n if (typeof forwardedRef === 'function') forwardedRef(node)\n else if (forwardedRef) forwardedRef.current = node\n },\n [forwardedRef],\n )\n\n // Roving tabindex needs exactly one tab stop. A trigger only knows whether\n // IT is selected, so when no enabled trigger matches the value (no\n // defaultValue, or the selected tab is disabled) nothing would be\n // tabbable; make the first enabled tab the stop in that case.\n // This effect owns the final tabindex of every trigger (React leaves a\n // DOM value alone while its prop is unchanged, so patching only the\n // fallback would leave two tab stops after the next selection).\n React.useEffect(() => {\n const tabs = enabledTabs(listRef.current)\n const stop = tabs.find((tab) => tab.getAttribute('aria-selected') === 'true') ?? tabs[0]\n for (const tab of tabs) tab.tabIndex = tab === stop ? 0 : -1\n })\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(e)\n if (e.defaultPrevented) return\n const tabs = enabledTabs(listRef.current)\n const current = tabs.indexOf(e.target as HTMLButtonElement)\n if (current === -1) return\n const next = getNextTabIndex(current, e.key, tabs.length, orientation)\n if (next === null) return\n e.preventDefault()\n tabs[next].focus()\n // Automatic activation: moving focus selects the tab.\n tabs[next].click()\n }\n\n return React.createElement('div', {\n ref,\n role: 'tablist',\n 'aria-orientation': orientation,\n className: cn(tabsListVariants(), className),\n onKeyDown: handleKeyDown,\n ...props,\n })\n },\n)\n\nfunction enabledTabs(list: HTMLElement | null): HTMLButtonElement[] {\n if (!list) return []\n return Array.from(list.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]:not([disabled])'))\n}\n\n// ---------------------------------------------------------------------------\n// TabsTrigger\n// ---------------------------------------------------------------------------\n\nexport interface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n value: string\n}\n\nexport const TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(\n function TabsTrigger({ value, className, onClick, onKeyDown, children, ...props }, ref) {\n const { value: activeValue, onValueChange, orientation, idPrefix } = useTabsContext()\n\n const isSelected = activeValue === value\n const tabId = `${idPrefix}-tab-${value}`\n const panelId = `${idPrefix}-panel-${value}`\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange(value)\n onClick?.(e)\n }\n\n // Arrow / Home / End navigation is handled by TabsList (roving focus);\n // a consumer onKeyDown runs first and can preventDefault to opt out.\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(e)\n }\n\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n role: 'tab',\n 'aria-selected': isSelected,\n 'aria-controls': panelId,\n tabIndex: isSelected ? 0 : -1,\n id: tabId,\n 'data-state': isSelected ? 'active' : 'inactive',\n className: cn(tabsTriggerVariants(), className),\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n ...props,\n },\n children,\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// TabsContent\n// ---------------------------------------------------------------------------\n\nexport interface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string\n}\n\nexport const TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(\n function TabsContent({ value, className, children, ...props }, ref) {\n const { value: activeValue, idPrefix } = useTabsContext()\n\n const isSelected = activeValue === value\n const tabId = `${idPrefix}-tab-${value}`\n const panelId = `${idPrefix}-panel-${value}`\n\n if (!isSelected) return null\n\n return React.createElement(\n 'div',\n {\n ref,\n role: 'tabpanel',\n 'aria-labelledby': tabId,\n id: panelId,\n tabIndex: 0,\n 'data-state': 'active',\n className,\n ...props,\n },\n children,\n )\n },\n)\n"],
5
+ "mappings": "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",
6
6
  "names": ["Tabs", "TabsList", "TabsTrigger", "TabsContent"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-terminal/dist/index.js
7
7
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-test-results/dist/index.js
7
7
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-textarea/dist/index.js
7
7
  import * as React from "react";
@@ -40,11 +40,11 @@ function createTextarea(props = {}) {
40
40
  };
41
41
  }
42
42
  var textareaVariants = cva({
43
- base: "flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
43
+ base: "flex w-full rounded-md border border-input bg-transparent px-3 py-2 shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
44
44
  variants: {
45
45
  size: {
46
46
  sm: "min-h-[40px] text-xs",
47
- default: "min-h-[60px]",
47
+ default: "min-h-[60px] text-sm",
48
48
  lg: "min-h-[80px] text-base"
49
49
  }
50
50
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../textarea/src/textarea.ts", "../../textarea/src/textarea.styles.ts", "../../react-textarea/src/textarea.tsx"],
4
- "sourcesContent": ["import type { AccessibilityProps } from '@refraction-ui/shared'\n\nexport interface TextareaProps {\n disabled?: boolean\n readOnly?: boolean\n required?: boolean\n 'aria-invalid'?: boolean\n rows?: number\n maxRows?: number\n}\n\nexport interface TextareaAPI {\n /** ARIA attributes to spread on the element */\n ariaProps: Partial<AccessibilityProps> & { 'aria-invalid'?: boolean; 'aria-required'?: boolean }\n /** Data attributes for CSS styling hooks */\n dataAttributes: Record<string, string>\n}\n\nexport function createTextarea(props: TextareaProps = {}): TextareaAPI {\n const {\n disabled = false,\n readOnly = false,\n required = false,\n 'aria-invalid': ariaInvalid,\n } = props\n\n const ariaProps: TextareaAPI['ariaProps'] = {}\n\n if (disabled) {\n ariaProps['aria-disabled'] = true\n }\n\n if (ariaInvalid) {\n ariaProps['aria-invalid'] = true\n }\n\n if (required) {\n ariaProps['aria-required'] = true\n }\n\n const dataAttributes: Record<string, string> = {}\n\n if (disabled) {\n dataAttributes['data-disabled'] = ''\n }\n\n if (readOnly) {\n dataAttributes['data-readonly'] = ''\n }\n\n if (ariaInvalid) {\n dataAttributes['data-invalid'] = ''\n }\n\n return {\n ariaProps,\n dataAttributes,\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const textareaVariants = cva({\n base: 'flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n variants: {\n size: {\n sm: 'min-h-[40px] text-xs',\n default: 'min-h-[60px]',\n lg: 'min-h-[80px] text-base',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n})\n", "import * as React from 'react'\nimport {\n createTextarea,\n textareaVariants,\n} from '@refraction-ui/textarea'\nimport { cn } from '@refraction-ui/shared'\n\nexport interface TextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'> {\n size?: 'sm' | 'default' | 'lg'\n maxRows?: number\n}\n\n/**\n * Textarea component — renders a styled textarea with size support.\n *\n * Uses the headless @refraction-ui/textarea core for state, ARIA, and data attributes.\n * Styling via Tailwind utility classes (no external CSS-in-JS).\n */\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n function Textarea({ size, className, disabled, readOnly, required, rows, maxRows, 'aria-invalid': ariaInvalid, ...props }, ref) {\n const api = createTextarea({\n disabled,\n readOnly,\n required,\n rows,\n maxRows,\n 'aria-invalid': ariaInvalid === true ? true : undefined,\n })\n\n const classes = cn(textareaVariants({ size }), className)\n\n return (\n <textarea\n ref={ref}\n className={classes}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n rows={rows}\n {...api.ariaProps}\n {...api.dataAttributes}\n {...props}\n />\n )\n },\n)\n"],
4
+ "sourcesContent": ["import type { AccessibilityProps } from '@refraction-ui/shared'\n\nexport interface TextareaProps {\n disabled?: boolean\n readOnly?: boolean\n required?: boolean\n 'aria-invalid'?: boolean\n rows?: number\n maxRows?: number\n}\n\nexport interface TextareaAPI {\n /** ARIA attributes to spread on the element */\n ariaProps: Partial<AccessibilityProps> & { 'aria-invalid'?: boolean; 'aria-required'?: boolean }\n /** Data attributes for CSS styling hooks */\n dataAttributes: Record<string, string>\n}\n\nexport function createTextarea(props: TextareaProps = {}): TextareaAPI {\n const {\n disabled = false,\n readOnly = false,\n required = false,\n 'aria-invalid': ariaInvalid,\n } = props\n\n const ariaProps: TextareaAPI['ariaProps'] = {}\n\n if (disabled) {\n ariaProps['aria-disabled'] = true\n }\n\n if (ariaInvalid) {\n ariaProps['aria-invalid'] = true\n }\n\n if (required) {\n ariaProps['aria-required'] = true\n }\n\n const dataAttributes: Record<string, string> = {}\n\n if (disabled) {\n dataAttributes['data-disabled'] = ''\n }\n\n if (readOnly) {\n dataAttributes['data-readonly'] = ''\n }\n\n if (ariaInvalid) {\n dataAttributes['data-invalid'] = ''\n }\n\n return {\n ariaProps,\n dataAttributes,\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const textareaVariants = cva({\n base: 'flex w-full rounded-md border border-input bg-transparent px-3 py-2 shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n variants: {\n size: {\n sm: 'min-h-[40px] text-xs',\n default: 'min-h-[60px] text-sm',\n lg: 'min-h-[80px] text-base',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n})\n", "import * as React from 'react'\nimport {\n createTextarea,\n textareaVariants,\n} from '@refraction-ui/textarea'\nimport { cn } from '@refraction-ui/shared'\n\nexport interface TextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'> {\n size?: 'sm' | 'default' | 'lg'\n maxRows?: number\n}\n\n/**\n * Textarea component — renders a styled textarea with size support.\n *\n * Uses the headless @refraction-ui/textarea core for state, ARIA, and data attributes.\n * Styling via Tailwind utility classes (no external CSS-in-JS).\n */\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n function Textarea({ size, className, disabled, readOnly, required, rows, maxRows, 'aria-invalid': ariaInvalid, ...props }, ref) {\n const api = createTextarea({\n disabled,\n readOnly,\n required,\n rows,\n maxRows,\n 'aria-invalid': ariaInvalid === true ? true : undefined,\n })\n\n const classes = cn(textareaVariants({ size }), className)\n\n return (\n <textarea\n ref={ref}\n className={classes}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n rows={rows}\n {...api.ariaProps}\n {...api.dataAttributes}\n {...props}\n />\n )\n },\n)\n"],
5
5
  "mappings": ";;;;;;;;;AAkBO,SAAS,eAAe,QAAuB,CAAA,GAAiB;AACrE,QAAM;IACJ,WAAW;IACX,WAAW;IACX,WAAW;IACX,gBAAgB;EAAA,IACd;AAEJ,QAAM,YAAsC,CAAA;AAE5C,MAAI,UAAU;AACZ,cAAU,eAAe,IAAI;EAC/B;AAEA,MAAI,aAAa;AACf,cAAU,cAAc,IAAI;EAC9B;AAEA,MAAI,UAAU;AACZ,cAAU,eAAe,IAAI;EAC/B;AAEA,QAAM,iBAAyC,CAAA;AAE/C,MAAI,UAAU;AACZ,mBAAe,eAAe,IAAI;EACpC;AAEA,MAAI,UAAU;AACZ,mBAAe,eAAe,IAAI;EACpC;AAEA,MAAI,aAAa;AACf,mBAAe,cAAc,IAAI;EACnC;AAEA,SAAO;IACL;IACA;EAAA;AAEJ;ACxDO,IAAM,mBAAmB,IAAI;EAClC,MAAM;EACN,UAAU;IACR,MAAM;MACJ,IAAI;MACJ,SAAS;MACT,IAAI;IAAA;EACN;EAEF,iBAAiB;IACf,MAAM;EAAA;AAEV,CAAC;;;;ACIM,IAAM,WAAiB;EAC5B,SAASA,UAAS,EAAE,MAAM,WAAW,UAAU,UAAU,UAAU,MAAM,SAAS,gBAAgB,aAAa,GAAG,MAAA,GAAS,KAAK;AAC9H,UAAM,MAAM,eAAe;MACzB;MACA;MACA;MACA;MACA;MACA,gBAAgB,gBAAgB,OAAO,OAAO;IAAA,CAC/C;AAED,UAAM,UAAU,GAAG,iBAAiB,EAAE,KAAA,CAAM,GAAG,SAAS;AAExD,WACE;MAAC;MAAA;QACC;QACA,WAAW;QACX;QACA;QACA;QACA;QACC,GAAG,IAAI;QACP,GAAG,IAAI;QACP,GAAG;MAAA;IAAA;EAGV;AACF;",
6
6
  "names": ["Textarea"]
7
7
  }
@@ -14,10 +14,10 @@ import {
14
14
  threadReactionsStyles,
15
15
  threadReplyIndicatorStyles,
16
16
  threadTimestampStyles
17
- } from "./chunk-ONACRMG4.js";
17
+ } from "./chunk-XMFNBOPO.js";
18
18
  import {
19
19
  cn
20
- } from "./chunk-ZF3OHCGV.js";
20
+ } from "./chunk-2Q6HHFAN.js";
21
21
 
22
22
  // ../react-thread-view/dist/index.js
23
23
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-timeline/dist/index.js
7
7
  import * as React from "react";
@@ -3,7 +3,7 @@ import {
3
3
  cva,
4
4
  devWarn,
5
5
  generateId
6
- } from "./chunk-ZF3OHCGV.js";
6
+ } from "./chunk-2Q6HHFAN.js";
7
7
 
8
8
  // ../react-toast/dist/index.js
9
9
  import * as React from "react";
@@ -3,7 +3,7 @@ import {
3
3
  cva,
4
4
  devWarn,
5
5
  generateId
6
- } from "./chunk-ZF3OHCGV.js";
6
+ } from "./chunk-2Q6HHFAN.js";
7
7
 
8
8
  // ../react-tooltip/dist/index.js
9
9
  import * as React from "react";
@@ -4,7 +4,7 @@ import {
4
4
  createKeyboardHandler,
5
5
  cva,
6
6
  generateId
7
- } from "./chunk-ZF3OHCGV.js";
7
+ } from "./chunk-2Q6HHFAN.js";
8
8
 
9
9
  // ../react-version-selector/dist/index.js
10
10
  import * as React from "react";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  VideoTile
3
- } from "./chunk-H54FLNAF.js";
3
+ } from "./chunk-63N4PZUJ.js";
4
4
  import {
5
5
  cn,
6
6
  cva
7
- } from "./chunk-ZF3OHCGV.js";
7
+ } from "./chunk-2Q6HHFAN.js";
8
8
 
9
9
  // ../react-video-grid/dist/index.js
10
10
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-video-player/dist/index.js
7
7
  import * as React from "react";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  VideoTile
3
- } from "./chunk-H54FLNAF.js";
4
- import "./chunk-ZF3OHCGV.js";
3
+ } from "./chunk-63N4PZUJ.js";
4
+ import "./chunk-2Q6HHFAN.js";
5
5
  export {
6
6
  VideoTile
7
7
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cn,
3
3
  cva
4
- } from "./chunk-ZF3OHCGV.js";
4
+ } from "./chunk-2Q6HHFAN.js";
5
5
 
6
6
  // ../react-voice-pill/dist/index.js
7
7
  import * as React from "react";