@refraction-ui/react 0.19.1 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-533MCMSU.js +2355 -0
- package/dist/chunk-533MCMSU.js.map +7 -0
- package/dist/chunk-AMK4VCBG.js +250 -0
- package/dist/chunk-AMK4VCBG.js.map +7 -0
- package/dist/chunk-BOLFYVI6.js +90 -0
- package/dist/chunk-BOLFYVI6.js.map +7 -0
- package/dist/chunk-F7B64KT3.js +187 -0
- package/dist/chunk-F7B64KT3.js.map +7 -0
- package/dist/chunk-FD37DFCC.js +77 -0
- package/dist/chunk-FD37DFCC.js.map +7 -0
- package/dist/chunk-H54FLNAF.js +132 -0
- package/dist/chunk-H54FLNAF.js.map +7 -0
- package/dist/chunk-INP46354.js +664 -0
- package/dist/chunk-INP46354.js.map +7 -0
- package/dist/chunk-ONACRMG4.js +116 -0
- package/dist/chunk-ONACRMG4.js.map +7 -0
- package/dist/chunk-SDZ3LROZ.js +7 -0
- package/dist/chunk-SDZ3LROZ.js.map +7 -0
- package/dist/chunk-TOZBR4GL.js +154 -0
- package/dist/chunk-TOZBR4GL.js.map +7 -0
- package/dist/chunk-UNEM2TRI.js +225 -0
- package/dist/chunk-UNEM2TRI.js.map +7 -0
- package/dist/chunk-VK3EQ34F.js +92 -0
- package/dist/chunk-VK3EQ34F.js.map +7 -0
- package/dist/chunk-WK2IIUFO.js +316 -0
- package/dist/chunk-WK2IIUFO.js.map +7 -0
- package/dist/chunk-WSPJTQAV.js +59 -0
- package/dist/chunk-WSPJTQAV.js.map +7 -0
- package/dist/chunk-XWP763SH.js +3 -2
- package/dist/chunk-XWP763SH.js.map +7 -1
- package/dist/chunk-Y2FNNAIL.js +80 -0
- package/dist/chunk-Y2FNNAIL.js.map +1 -0
- package/dist/{chunk-4A4BW3GR.js → chunk-ZF3OHCGV.js} +28 -5
- package/dist/chunk-ZF3OHCGV.js.map +7 -0
- package/dist/form.cjs +5 -11
- package/dist/form.cjs.map +1 -1
- package/dist/form.js +6 -12
- package/dist/form.js.map +1 -1
- package/dist/index.cjs +2879 -33936
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +126 -28780
- package/dist/internal/react-app-shell/index.d.cts +2 -22
- package/dist/internal/react-app-shell/index.d.ts +2 -22
- package/dist/internal/react-badge/index.d.cts +5 -0
- package/dist/internal/react-badge/index.d.ts +5 -0
- package/dist/internal/react-callout/index.d.cts +4 -0
- package/dist/internal/react-callout/index.d.ts +4 -0
- package/dist/internal/react-card/index.d.cts +8 -1
- package/dist/internal/react-card/index.d.ts +8 -1
- package/dist/internal/react-collapsible/index.d.cts +0 -3
- package/dist/internal/react-collapsible/index.d.ts +0 -3
- package/dist/internal/react-combobox/index.d.cts +0 -3
- package/dist/internal/react-combobox/index.d.ts +0 -3
- package/dist/internal/react-command/index.d.cts +0 -3
- package/dist/internal/react-command/index.d.ts +0 -3
- package/dist/internal/react-data-table/index.d.cts +0 -3
- package/dist/internal/react-data-table/index.d.ts +0 -3
- package/dist/internal/react-dialog/index.d.cts +0 -3
- package/dist/internal/react-dialog/index.d.ts +0 -3
- package/dist/internal/react-dropdown-menu/index.d.cts +0 -3
- package/dist/internal/react-dropdown-menu/index.d.ts +0 -3
- package/dist/internal/react-feedback-dialog/index.d.cts +0 -3
- package/dist/internal/react-feedback-dialog/index.d.ts +0 -3
- package/dist/internal/react-form/index.d.cts +2 -21
- package/dist/internal/react-form/index.d.ts +2 -21
- package/dist/internal/react-keyboard-shortcut/index.d.cts +0 -6
- package/dist/internal/react-keyboard-shortcut/index.d.ts +0 -6
- package/dist/internal/react-link-card/index.d.cts +8 -2
- package/dist/internal/react-link-card/index.d.ts +8 -2
- package/dist/internal/react-popover/index.d.cts +0 -3
- package/dist/internal/react-popover/index.d.ts +0 -3
- package/dist/internal/react-sheet/index.d.cts +0 -3
- package/dist/internal/react-sheet/index.d.ts +0 -3
- package/dist/internal/react-slot/index.d.cts +23 -0
- package/dist/internal/react-slot/index.d.ts +23 -0
- package/dist/internal/react-toast/index.d.cts +0 -3
- package/dist/internal/react-toast/index.d.ts +0 -3
- package/dist/internal/react-tooltip/index.d.cts +0 -3
- package/dist/internal/react-tooltip/index.d.ts +0 -3
- package/dist/react-accordion.js +125 -0
- package/dist/react-accordion.js.map +7 -0
- package/dist/react-ai.js +257 -0
- package/dist/react-ai.js.map +7 -0
- package/dist/react-analytics.js +1698 -0
- package/dist/react-analytics.js.map +7 -0
- package/dist/react-animated-text.js +164 -0
- package/dist/react-animated-text.js.map +7 -0
- package/dist/react-app-shell.js +631 -0
- package/dist/react-app-shell.js.map +7 -0
- package/dist/react-audience-feature-card.js +53 -0
- package/dist/react-audience-feature-card.js.map +7 -0
- package/dist/react-audio-room.js +166 -0
- package/dist/react-audio-room.js.map +7 -0
- package/dist/react-auth.js +211 -0
- package/dist/react-auth.js.map +7 -0
- package/dist/react-avatar-group.js +154 -0
- package/dist/react-avatar-group.js.map +7 -0
- package/dist/react-avatar.js +168 -0
- package/dist/react-avatar.js.map +7 -0
- package/dist/react-badge.js +86 -0
- package/dist/react-badge.js.map +7 -0
- package/dist/react-bottom-nav.js +67 -0
- package/dist/react-bottom-nav.js.map +7 -0
- package/dist/react-brand-network-cell.js +92 -0
- package/dist/react-brand-network-cell.js.map +7 -0
- package/dist/react-breadcrumbs.js +104 -0
- package/dist/react-breadcrumbs.js.map +7 -0
- package/dist/react-browser-chrome-mock.js +89 -0
- package/dist/react-browser-chrome-mock.js.map +7 -0
- package/dist/react-button.js +13 -0
- package/dist/react-button.js.map +7 -0
- package/dist/react-calendar.js +301 -0
- package/dist/react-calendar.js.map +7 -0
- package/dist/react-call-controls.js +113 -0
- package/dist/react-call-controls.js.map +7 -0
- package/dist/react-callout.js +152 -0
- package/dist/react-callout.js.map +7 -0
- package/dist/react-card-grid.js +34 -0
- package/dist/react-card-grid.js.map +7 -0
- package/dist/react-card.js +200 -0
- package/dist/react-card.js.map +7 -0
- package/dist/react-carousel.js +132 -0
- package/dist/react-carousel.js.map +7 -0
- package/dist/react-charts.js +509 -0
- package/dist/react-charts.js.map +7 -0
- package/dist/react-checkbox.js +156 -0
- package/dist/react-checkbox.js.map +7 -0
- package/dist/react-checklist.js +168 -0
- package/dist/react-checklist.js.map +7 -0
- package/dist/react-code-block.js +78 -0
- package/dist/react-code-block.js.map +7 -0
- package/dist/react-code-editor.js +184 -0
- package/dist/react-code-editor.js.map +7 -0
- package/dist/react-collapsible.js +192 -0
- package/dist/react-collapsible.js.map +7 -0
- package/dist/react-combobox.js +609 -0
- package/dist/react-combobox.js.map +7 -0
- package/dist/react-command-input.js +202 -0
- package/dist/react-command-input.js.map +7 -0
- package/dist/react-command.js +364 -0
- package/dist/react-command.js.map +7 -0
- package/dist/react-composer.js +2036 -0
- package/dist/react-composer.js.map +7 -0
- package/dist/react-content-protection.js +133 -0
- package/dist/react-content-protection.js.map +7 -0
- package/dist/react-conversation.js +1226 -0
- package/dist/react-conversation.js.map +7 -0
- package/dist/react-cookie-consent.js +291 -0
- package/dist/react-cookie-consent.js.map +7 -0
- package/dist/react-data-table.js +310 -0
- package/dist/react-data-table.js.map +7 -0
- package/dist/react-date-picker.js +95 -0
- package/dist/react-date-picker.js.map +7 -0
- package/dist/react-device-frame.js +137 -0
- package/dist/react-device-frame.js.map +7 -0
- package/dist/react-dialog.js +218 -0
- package/dist/react-dialog.js.map +7 -0
- package/dist/react-diff-viewer.js +460 -0
- package/dist/react-diff-viewer.js.map +7 -0
- package/dist/react-dropdown-menu.js +292 -0
- package/dist/react-dropdown-menu.js.map +7 -0
- package/dist/react-editor-status-bar.js +148 -0
- package/dist/react-editor-status-bar.js.map +7 -0
- package/dist/react-editor-tabs.js +159 -0
- package/dist/react-editor-tabs.js.map +7 -0
- package/dist/react-emoji-picker.js +238 -0
- package/dist/react-emoji-picker.js.map +7 -0
- package/dist/react-empty-state.js +90 -0
- package/dist/react-empty-state.js.map +7 -0
- package/dist/react-feedback-dialog.js +275 -0
- package/dist/react-feedback-dialog.js.map +7 -0
- package/dist/react-file-tree.js +376 -0
- package/dist/react-file-tree.js.map +7 -0
- package/dist/react-file-upload.js +360 -0
- package/dist/react-file-upload.js.map +7 -0
- package/dist/react-floating-reactions.js +124 -0
- package/dist/react-floating-reactions.js.map +7 -0
- package/dist/react-flow-editor.js +198 -0
- package/dist/react-flow-editor.js.map +7 -0
- package/dist/react-footer.js +67 -0
- package/dist/react-footer.js.map +7 -0
- package/dist/react-graph-view.js +197 -0
- package/dist/react-graph-view.js.map +7 -0
- package/dist/react-icon-system.js +9 -0
- package/dist/react-icon-system.js.map +7 -0
- package/dist/react-infinite-canvas.js +8 -0
- package/dist/react-infinite-canvas.js.map +7 -0
- package/dist/react-inline-editor.js +216 -0
- package/dist/react-inline-editor.js.map +7 -0
- package/dist/react-input-group.js +150 -0
- package/dist/react-input-group.js.map +7 -0
- package/dist/react-input.js +10 -0
- package/dist/react-input.js.map +7 -0
- package/dist/react-install-prompt.js +132 -0
- package/dist/react-install-prompt.js.map +7 -0
- package/dist/react-kanban-board.js +198 -0
- package/dist/react-kanban-board.js.map +7 -0
- package/dist/react-keyboard-shortcut.js +36 -0
- package/dist/react-keyboard-shortcut.js.map +7 -0
- package/dist/react-language-selector.js +311 -0
- package/dist/react-language-selector.js.map +7 -0
- package/dist/react-link-card.js +48 -0
- package/dist/react-link-card.js.map +7 -0
- package/dist/react-live-captions.js +92 -0
- package/dist/react-live-captions.js.map +7 -0
- package/dist/react-live-cursors.js +145 -0
- package/dist/react-live-cursors.js.map +7 -0
- package/dist/react-live-transcript.js +117 -0
- package/dist/react-live-transcript.js.map +7 -0
- package/dist/react-location-selector.js +252 -0
- package/dist/react-location-selector.js.map +7 -0
- package/dist/react-logger.js +415 -0
- package/dist/react-logger.js.map +7 -0
- package/dist/react-markdown-renderer.js +12 -0
- package/dist/react-markdown-renderer.js.map +7 -0
- package/dist/react-marquee-strip.js +62 -0
- package/dist/react-marquee-strip.js.map +7 -0
- package/dist/react-mascot.js +367 -0
- package/dist/react-mascot.js.map +7 -0
- package/dist/react-mastery-bar.js +97 -0
- package/dist/react-mastery-bar.js.map +7 -0
- package/dist/react-mini-map.js +207 -0
- package/dist/react-mini-map.js.map +7 -0
- package/dist/react-mobile-nav.js +216 -0
- package/dist/react-mobile-nav.js.map +7 -0
- package/dist/react-navbar.js +96 -0
- package/dist/react-navbar.js.map +7 -0
- package/dist/react-numbered-steps.js +67 -0
- package/dist/react-numbered-steps.js.map +7 -0
- package/dist/react-otp-input.js +318 -0
- package/dist/react-otp-input.js.map +7 -0
- package/dist/react-pagination.js +199 -0
- package/dist/react-pagination.js.map +7 -0
- package/dist/react-password-input.js +104 -0
- package/dist/react-password-input.js.map +7 -0
- package/dist/react-payment.js +81 -0
- package/dist/react-payment.js.map +7 -0
- package/dist/react-popover.js +176 -0
- package/dist/react-popover.js.map +7 -0
- package/dist/react-pre-call-lobby.js +309 -0
- package/dist/react-pre-call-lobby.js.map +7 -0
- package/dist/react-presence-indicator.js +86 -0
- package/dist/react-presence-indicator.js.map +7 -0
- package/dist/react-pricing-card.js +142 -0
- package/dist/react-pricing-card.js.map +7 -0
- package/dist/react-progress-display.js +188 -0
- package/dist/react-progress-display.js.map +7 -0
- package/dist/react-radial-gauge.js +193 -0
- package/dist/react-radial-gauge.js.map +7 -0
- package/dist/react-radio.js +169 -0
- package/dist/react-radio.js.map +7 -0
- package/dist/react-rating-scale.js +171 -0
- package/dist/react-rating-scale.js.map +7 -0
- package/dist/react-reaction-bar.js +111 -0
- package/dist/react-reaction-bar.js.map +7 -0
- package/dist/react-resizable-layout.js +298 -0
- package/dist/react-resizable-layout.js.map +7 -0
- package/dist/react-rich-editor.js +1 -0
- package/dist/react-rich-editor.js.map +7 -0
- package/dist/react-search-bar.js +285 -0
- package/dist/react-search-bar.js.map +7 -0
- package/dist/react-section-head.js +65 -0
- package/dist/react-section-head.js.map +7 -0
- package/dist/react-segmented-control.js +215 -0
- package/dist/react-segmented-control.js.map +7 -0
- package/dist/react-select.js +389 -0
- package/dist/react-select.js.map +7 -0
- package/dist/react-separator.js +86 -0
- package/dist/react-separator.js.map +7 -0
- package/dist/react-sheet.js +310 -0
- package/dist/react-sheet.js.map +7 -0
- package/dist/react-sidebar.js +100 -0
- package/dist/react-sidebar.js.map +7 -0
- package/dist/react-skeleton.js +91 -0
- package/dist/react-skeleton.js.map +7 -0
- package/dist/react-skip-to-content.js +38 -0
- package/dist/react-skip-to-content.js.map +7 -0
- package/dist/react-slide-viewer.js +264 -0
- package/dist/react-slide-viewer.js.map +7 -0
- package/dist/react-slider.js +105 -0
- package/dist/react-slider.js.map +7 -0
- package/dist/react-slot-picker.js +184 -0
- package/dist/react-slot-picker.js.map +7 -0
- package/dist/react-slot.js +7 -0
- package/dist/react-slot.js.map +7 -0
- package/dist/react-social-auth-button.js +169 -0
- package/dist/react-social-auth-button.js.map +7 -0
- package/dist/react-sortable-list.js +204 -0
- package/dist/react-sortable-list.js.map +7 -0
- package/dist/react-stat-grid.js +69 -0
- package/dist/react-stat-grid.js.map +7 -0
- package/dist/react-status-indicator.js +117 -0
- package/dist/react-status-indicator.js.map +7 -0
- package/dist/react-steps.js +167 -0
- package/dist/react-steps.js.map +7 -0
- package/dist/react-sticky-note.js +131 -0
- package/dist/react-sticky-note.js.map +7 -0
- package/dist/react-switch.js +139 -0
- package/dist/react-switch.js.map +7 -0
- package/dist/react-table-of-contents.js +80 -0
- package/dist/react-table-of-contents.js.map +7 -0
- package/dist/react-tabs.js +230 -0
- package/dist/react-tabs.js.map +7 -0
- package/dist/react-terminal.js +101 -0
- package/dist/react-terminal.js.map +7 -0
- package/dist/react-test-results.js +158 -0
- package/dist/react-test-results.js.map +7 -0
- package/dist/react-textarea.js +89 -0
- package/dist/react-textarea.js.map +7 -0
- package/dist/react-thread-view.js +139 -0
- package/dist/react-thread-view.js.map +7 -0
- package/dist/react-timeline.js +153 -0
- package/dist/react-timeline.js.map +7 -0
- package/dist/react-toast.js +253 -0
- package/dist/react-toast.js.map +7 -0
- package/dist/react-tooltip.js +221 -0
- package/dist/react-tooltip.js.map +7 -0
- package/dist/react-version-selector.js +270 -0
- package/dist/react-version-selector.js.map +7 -0
- package/dist/react-video-grid.js +129 -0
- package/dist/react-video-grid.js.map +7 -0
- package/dist/react-video-player.js +206 -0
- package/dist/react-video-player.js.map +7 -0
- package/dist/react-video-tile.js +8 -0
- package/dist/react-video-tile.js.map +7 -0
- package/dist/react-voice-pill.js +314 -0
- package/dist/react-voice-pill.js.map +7 -0
- package/dist/react-waveform.js +558 -0
- package/dist/react-waveform.js.map +7 -0
- package/dist/react-wizard.js +337 -0
- package/dist/react-wizard.js.map +7 -0
- package/dist/styles.css +7 -0
- package/dist/theme.js +1 -1
- package/package.json +3 -2
- package/dist/applicationinsights-web-H7OBLIVJ.js +0 -23393
- package/dist/applicationinsights-web-H7OBLIVJ.js.map +0 -1
- package/dist/chunk-4A4BW3GR.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/module-X3HTTRQK.js +0 -6438
- package/dist/module-X3HTTRQK.js.map +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../numbered-steps/src/numbered-steps.ts", "../../numbered-steps/src/numbered-steps.styles.ts", "../../react-numbered-steps/src/numbered-steps.tsx"],
|
|
4
|
+
"sourcesContent": ["/** A single step item in the numbered steps grid. */\nexport type NumberedStepItem = {\n /** Step title displayed prominently below the ordinal badge. */\n title: string\n /** Step body copy displayed below the title. */\n body: string\n}\n\nexport interface NumberedStepsProps {\n /** The step items to display. */\n items: NumberedStepItem[]\n /**\n * Number of grid columns. When omitted, defaults to clamping the item count\n * to the 2–5 range via {@link stepColumns}.\n */\n columns?: number\n}\n\nexport interface NumberedStepsAPI {\n /** ARIA attributes to spread on the container element (`role=\"list\"`). */\n ariaProps: { role: 'list' }\n /** Data attributes for styling hooks. */\n dataAttributes: Record<string, string>\n}\n\n/**\n * Zero-pad a 1-indexed ordinal to at least two digits.\n *\n * @example\n * padOrdinal(1) // '01'\n * padOrdinal(10) // '10'\n */\nexport function padOrdinal(n: number): string {\n return String(n).padStart(2, '0')\n}\n\n/**\n * Derive the number of grid columns from the item count.\n * Clamps the count to the 2–5 range.\n *\n * @example\n * stepColumns(3) // 3\n * stepColumns(1) // 2\n * stepColumns(6) // 5\n */\nexport function stepColumns(count: number): number {\n return Math.min(5, Math.max(2, count))\n}\n\n/**\n * Build the framework-agnostic container props for a numbered-steps grid.\n *\n * Returns `role=\"list\"` plus data attributes; adapters spread these onto their\n * container and render each step as a `role=\"listitem\"`.\n */\nexport function createNumberedSteps(): NumberedStepsAPI {\n const ariaProps = { role: 'list' } as const\n\n const dataAttributes: Record<string, string> = {\n 'data-component': 'numbered-steps',\n }\n\n return { ariaProps, dataAttributes }\n}\n", "import { cva } from '@refraction-ui/shared'\n\n/**\n * Container grid for the numbered steps. The `columns` variant maps to a\n * fixed Tailwind grid-cols class; adapters that need a dynamic column count\n * use `gridTemplateColumns` inline style via {@link stepColumns} instead and\n * omit this variant.\n */\nexport const numberedStepsVariants = cva({\n base: 'grid gap-6',\n variants: {\n columns: {\n '2': 'grid-cols-2',\n '3': 'grid-cols-3',\n '4': 'grid-cols-4',\n '5': 'grid-cols-5',\n },\n },\n defaultVariants: {\n columns: '3',\n },\n})\n\n/** Individual step card. */\nexport const numberedStepsItemClass =\n 'rounded-xl border border-border bg-card p-5'\n\n/** Zero-padded ordinal badge above each step title. */\nexport const numberedStepsOrdinalClass = 'font-mono text-sm text-primary'\n\n/** Step title. */\nexport const numberedStepsTitleClass = 'mt-2 text-sm font-bold text-foreground'\n\n/** Step body copy. */\nexport const numberedStepsBodyClass =\n 'mt-1 text-xs text-muted-foreground leading-relaxed'\n", "import * as React from 'react'\nimport {\n createNumberedSteps,\n padOrdinal,\n stepColumns,\n numberedStepsVariants,\n numberedStepsItemClass,\n numberedStepsOrdinalClass,\n numberedStepsTitleClass,\n numberedStepsBodyClass,\n type NumberedStepItem,\n} from '@refraction-ui/numbered-steps'\nimport { cn } from '@refraction-ui/shared'\n\nexport type { NumberedStepItem }\n\nexport interface NumberedStepsProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content'> {\n /** The step items to display (3–5 recommended). */\n items: NumberedStepItem[]\n /**\n * Override the number of grid columns. Defaults to clamping item count to\n * 2–5 via `stepColumns`.\n */\n columns?: number\n}\n\n/**\n * NumberedSteps — a static how-it-works step grid.\n *\n * Renders a CSS grid of step cards, each with a zero-padded ordinal badge\n * (01, 02…), a title, and body copy. Not a stateful stepper — use the `Steps`\n * component for that. Exposes `role=\"list\"` semantics with each card as\n * `role=\"listitem\"`.\n */\nexport const NumberedSteps = React.forwardRef<\n HTMLDivElement,\n NumberedStepsProps\n>(function NumberedSteps({ items, columns, className, ...props }, ref) {\n const cols = columns ?? stepColumns(items.length)\n const { ariaProps, dataAttributes } = createNumberedSteps()\n\n return (\n <div\n ref={ref}\n className={cn(numberedStepsVariants(), className)}\n style={{ gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` }}\n {...ariaProps}\n {...dataAttributes}\n {...props}\n >\n {items.map((item, index) => (\n <div key={index} role=\"listitem\" className={numberedStepsItemClass}>\n <span className={numberedStepsOrdinalClass}>\n {padOrdinal(index + 1)}\n </span>\n <p className={numberedStepsTitleClass}>{item.title}</p>\n <p className={numberedStepsBodyClass}>{item.body}</p>\n </div>\n ))}\n </div>\n )\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;AAgCO,SAAS,WAAW,GAAmB;AAC5C,SAAO,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG;AAClC;AAWO,SAAS,YAAY,OAAuB;AACjD,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC;AACvC;AAQO,SAAS,sBAAwC;AACtD,QAAM,YAAY,EAAE,MAAM,OAAA;AAE1B,QAAM,iBAAyC;IAC7C,kBAAkB;EAAA;AAGpB,SAAO,EAAE,WAAW,eAAA;AACtB;ACvDO,IAAM,wBAAwB,IAAI;EACvC,MAAM;EACN,UAAU;IACR,SAAS;MACP,KAAK;MACL,KAAK;MACL,KAAK;MACL,KAAK;IAAA;EACP;EAEF,iBAAiB;IACf,SAAS;EAAA;AAEb,CAAC;AAGM,IAAM,yBACX;AAGK,IAAM,4BAA4B;AAGlC,IAAM,0BAA0B;AAGhC,IAAM,yBACX;;;;ACAK,IAAM,gBAAsB,iBAGjC,SAASA,eAAc,EAAE,OAAO,SAAS,WAAW,GAAG,MAAA,GAAS,KAAK;AACrE,QAAM,OAAO,WAAW,YAAY,MAAM,MAAM;AAChD,QAAM,EAAE,WAAW,eAAA,IAAmB,oBAAA;AAEtC,SACE;IAAC;IAAA;MACC;MACA,WAAW,GAAG,sBAAA,GAAyB,SAAS;MAChD,OAAO,EAAE,qBAAqB,UAAU,IAAI,oBAAA;MAC3C,GAAG;MACH,GAAG;MACH,GAAG;MAEH,UAAA,MAAM,IAAI,CAAC,MAAM,UAAA,qBACf,OAAA,EAAgB,MAAK,YAAW,WAAW,wBAC1C,UAAA;QAAA,oBAAC,QAAA,EAAK,WAAW,2BACd,UAAA,WAAW,QAAQ,CAAC,EAAA,CACvB;QACA,oBAAC,KAAA,EAAE,WAAW,yBAA0B,UAAA,KAAK,MAAA,CAAM;QACnD,oBAAC,KAAA,EAAE,WAAW,wBAAyB,UAAA,KAAK,KAAA,CAAK;MAAA,EAAA,GALzC,KAMV,CACD;IAAA;EAAA;AAGP,CAAC;",
|
|
6
|
+
"names": ["NumberedSteps"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Keys,
|
|
3
|
+
cn,
|
|
4
|
+
cva
|
|
5
|
+
} from "./chunk-ZF3OHCGV.js";
|
|
6
|
+
|
|
7
|
+
// ../react-otp-input/dist/index.js
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
|
|
10
|
+
// ../otp-input/dist/index.js
|
|
11
|
+
function createOtpInput(props = {}) {
|
|
12
|
+
const {
|
|
13
|
+
length = 6,
|
|
14
|
+
value = "",
|
|
15
|
+
autoFocus = false,
|
|
16
|
+
type = "number",
|
|
17
|
+
disabled = false
|
|
18
|
+
} = props;
|
|
19
|
+
const isInteractive = !disabled;
|
|
20
|
+
const values = Array.from({ length }, (_, i) => value.charAt(i) || "");
|
|
21
|
+
let focusedIndex = autoFocus ? 0 : -1;
|
|
22
|
+
const rootAriaProps = {
|
|
23
|
+
role: "group",
|
|
24
|
+
"aria-label": "One-time password input"
|
|
25
|
+
};
|
|
26
|
+
function setValue(index, char) {
|
|
27
|
+
if (index < 0 || index >= length) return [...values];
|
|
28
|
+
const filtered = type === "number" ? char.replace(/[^0-9]/g, "") : char;
|
|
29
|
+
const newValues = [...values];
|
|
30
|
+
newValues[index] = filtered.charAt(0) || "";
|
|
31
|
+
for (let i = 0; i < length; i++) {
|
|
32
|
+
values[i] = newValues[i];
|
|
33
|
+
}
|
|
34
|
+
return newValues;
|
|
35
|
+
}
|
|
36
|
+
function getValue() {
|
|
37
|
+
return values.join("");
|
|
38
|
+
}
|
|
39
|
+
function moveFocus(direction) {
|
|
40
|
+
if (direction === "left") {
|
|
41
|
+
focusedIndex = Math.max(0, focusedIndex - 1);
|
|
42
|
+
} else {
|
|
43
|
+
focusedIndex = Math.min(length - 1, focusedIndex + 1);
|
|
44
|
+
}
|
|
45
|
+
return focusedIndex;
|
|
46
|
+
}
|
|
47
|
+
function getSlotProps(index) {
|
|
48
|
+
const isFocused = index === focusedIndex;
|
|
49
|
+
const isFilled = values[index] !== "";
|
|
50
|
+
const ariaProps = {
|
|
51
|
+
"aria-label": `Digit ${index + 1} of ${length}`
|
|
52
|
+
};
|
|
53
|
+
const dataAttributes = {
|
|
54
|
+
"data-slot": "otp-slot"
|
|
55
|
+
};
|
|
56
|
+
if (isFocused) {
|
|
57
|
+
dataAttributes["data-focused"] = "";
|
|
58
|
+
}
|
|
59
|
+
if (isFilled) {
|
|
60
|
+
dataAttributes["data-filled"] = "";
|
|
61
|
+
}
|
|
62
|
+
const inputProps = {
|
|
63
|
+
maxLength: 1,
|
|
64
|
+
inputMode: type === "number" ? "numeric" : "text",
|
|
65
|
+
pattern: type === "number" ? "[0-9]*" : void 0,
|
|
66
|
+
autoComplete: index === 0 ? "one-time-code" : "off",
|
|
67
|
+
disabled
|
|
68
|
+
};
|
|
69
|
+
return { ariaProps, dataAttributes, inputProps };
|
|
70
|
+
}
|
|
71
|
+
function getKeyboardHandlers(index, callbacks) {
|
|
72
|
+
if (!isInteractive) {
|
|
73
|
+
return {
|
|
74
|
+
[Keys.Backspace]: (e) => e.preventDefault(),
|
|
75
|
+
[Keys.ArrowLeft]: (e) => e.preventDefault(),
|
|
76
|
+
[Keys.ArrowRight]: (e) => e.preventDefault()
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
[Keys.Backspace]: (e) => {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
if (values[index]) {
|
|
83
|
+
const newValues = setValue(index, "");
|
|
84
|
+
callbacks?.onSetValue?.(index, newValues);
|
|
85
|
+
} else if (index > 0) {
|
|
86
|
+
focusedIndex = index - 1;
|
|
87
|
+
const newValues = setValue(index - 1, "");
|
|
88
|
+
callbacks?.onSetValue?.(index - 1, newValues);
|
|
89
|
+
callbacks?.onMoveFocus?.(focusedIndex);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
[Keys.ArrowLeft]: (e) => {
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
if (index > 0) {
|
|
95
|
+
focusedIndex = index - 1;
|
|
96
|
+
callbacks?.onMoveFocus?.(focusedIndex);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
[Keys.ArrowRight]: (e) => {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
if (index < length - 1) {
|
|
102
|
+
focusedIndex = index + 1;
|
|
103
|
+
callbacks?.onMoveFocus?.(focusedIndex);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function parsePaste(text) {
|
|
109
|
+
const chars = type === "number" ? text.replace(/[^0-9]/g, "") : text;
|
|
110
|
+
return Array.from({ length }, (_, i) => chars.charAt(i) || "");
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
state: {
|
|
114
|
+
values,
|
|
115
|
+
focusedIndex,
|
|
116
|
+
length,
|
|
117
|
+
disabled
|
|
118
|
+
},
|
|
119
|
+
setValue,
|
|
120
|
+
getValue,
|
|
121
|
+
moveFocus,
|
|
122
|
+
getSlotProps,
|
|
123
|
+
getKeyboardHandlers,
|
|
124
|
+
parsePaste,
|
|
125
|
+
rootAriaProps,
|
|
126
|
+
isInteractive
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
var otpInputTokens = {
|
|
130
|
+
name: "otp-input",
|
|
131
|
+
tokens: {
|
|
132
|
+
bg: { variable: "--rfr-otp-bg", fallback: "hsl(var(--background))" },
|
|
133
|
+
fg: { variable: "--rfr-otp-fg", fallback: "hsl(var(--foreground))" },
|
|
134
|
+
border: { variable: "--rfr-otp-border", fallback: "hsl(var(--border))" },
|
|
135
|
+
"border-filled": { variable: "--rfr-otp-border-filled", fallback: "hsl(var(--primary))" },
|
|
136
|
+
ring: { variable: "--rfr-otp-ring", fallback: "hsl(var(--ring))" }
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
var otpInputContainerVariants = cva({
|
|
140
|
+
base: "flex items-center gap-2",
|
|
141
|
+
variants: {
|
|
142
|
+
size: {
|
|
143
|
+
sm: "gap-1.5",
|
|
144
|
+
default: "gap-2",
|
|
145
|
+
lg: "gap-3"
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
defaultVariants: {
|
|
149
|
+
size: "default"
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
var otpInputSlotVariants = cva({
|
|
153
|
+
base: "relative flex items-center justify-center rounded-md border border-input bg-background text-center font-mono shadow-sm transition-all",
|
|
154
|
+
variants: {
|
|
155
|
+
size: {
|
|
156
|
+
sm: "h-8 w-8 text-sm",
|
|
157
|
+
default: "h-10 w-10 text-base",
|
|
158
|
+
lg: "h-12 w-12 text-lg"
|
|
159
|
+
},
|
|
160
|
+
focused: {
|
|
161
|
+
true: "ring-2 ring-ring ring-offset-background",
|
|
162
|
+
false: ""
|
|
163
|
+
},
|
|
164
|
+
filled: {
|
|
165
|
+
true: "border-primary",
|
|
166
|
+
false: ""
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
defaultVariants: {
|
|
170
|
+
size: "default",
|
|
171
|
+
focused: "false",
|
|
172
|
+
filled: "false"
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// ../react-otp-input/dist/index.js
|
|
177
|
+
import { jsx } from "react/jsx-runtime";
|
|
178
|
+
var OtpInput = React.forwardRef(
|
|
179
|
+
function OtpInput2({
|
|
180
|
+
length = 6,
|
|
181
|
+
value = "",
|
|
182
|
+
onChange,
|
|
183
|
+
autoFocus = false,
|
|
184
|
+
type = "number",
|
|
185
|
+
disabled = false,
|
|
186
|
+
size = "default",
|
|
187
|
+
className,
|
|
188
|
+
...props
|
|
189
|
+
}, ref) {
|
|
190
|
+
const inputRefs = React.useRef([]);
|
|
191
|
+
const [focusedIndex, setFocusedIndex] = React.useState(autoFocus ? 0 : -1);
|
|
192
|
+
const [values, setValues] = React.useState(
|
|
193
|
+
() => Array.from({ length }, (_, i) => value.charAt(i) || "")
|
|
194
|
+
);
|
|
195
|
+
React.useEffect(() => {
|
|
196
|
+
setValues(Array.from({ length }, (_, i) => value.charAt(i) || ""));
|
|
197
|
+
}, [value, length]);
|
|
198
|
+
React.useEffect(() => {
|
|
199
|
+
if (autoFocus && inputRefs.current[0]) {
|
|
200
|
+
inputRefs.current[0].focus();
|
|
201
|
+
}
|
|
202
|
+
}, [autoFocus]);
|
|
203
|
+
const api = createOtpInput({ length, value, autoFocus, type, disabled });
|
|
204
|
+
const updateValue = (index, char) => {
|
|
205
|
+
const filtered = type === "number" ? char.replace(/[^0-9]/g, "") : char;
|
|
206
|
+
const newChar = filtered.charAt(0) || "";
|
|
207
|
+
const newValues = [...values];
|
|
208
|
+
newValues[index] = newChar;
|
|
209
|
+
setValues(newValues);
|
|
210
|
+
onChange?.(newValues.join(""));
|
|
211
|
+
return newChar;
|
|
212
|
+
};
|
|
213
|
+
const handleInput = (index, e) => {
|
|
214
|
+
const inputValue = e.target.value;
|
|
215
|
+
const char = inputValue.slice(-1);
|
|
216
|
+
const result = updateValue(index, char);
|
|
217
|
+
if (result && index < length - 1) {
|
|
218
|
+
setFocusedIndex(index + 1);
|
|
219
|
+
inputRefs.current[index + 1]?.focus();
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
const handleKeyDown = (index, e) => {
|
|
223
|
+
if (e.key === "Backspace") {
|
|
224
|
+
e.preventDefault();
|
|
225
|
+
if (values[index]) {
|
|
226
|
+
updateValue(index, "");
|
|
227
|
+
} else if (index > 0) {
|
|
228
|
+
updateValue(index - 1, "");
|
|
229
|
+
setFocusedIndex(index - 1);
|
|
230
|
+
inputRefs.current[index - 1]?.focus();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (e.key === "ArrowLeft" && index > 0) {
|
|
234
|
+
e.preventDefault();
|
|
235
|
+
setFocusedIndex(index - 1);
|
|
236
|
+
inputRefs.current[index - 1]?.focus();
|
|
237
|
+
}
|
|
238
|
+
if (e.key === "ArrowRight" && index < length - 1) {
|
|
239
|
+
e.preventDefault();
|
|
240
|
+
setFocusedIndex(index + 1);
|
|
241
|
+
inputRefs.current[index + 1]?.focus();
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
const handlePaste = (e) => {
|
|
245
|
+
e.preventDefault();
|
|
246
|
+
const pasteData = e.clipboardData.getData("text");
|
|
247
|
+
const parsed = api.parsePaste(pasteData);
|
|
248
|
+
setValues(parsed);
|
|
249
|
+
onChange?.(parsed.join(""));
|
|
250
|
+
let lastFilledIndex = -1;
|
|
251
|
+
for (let i = parsed.length - 1; i >= 0; i--) {
|
|
252
|
+
if (parsed[i] !== "") {
|
|
253
|
+
lastFilledIndex = i;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const nextIndex = Math.min(lastFilledIndex + 1, length - 1);
|
|
258
|
+
setFocusedIndex(nextIndex);
|
|
259
|
+
inputRefs.current[nextIndex]?.focus();
|
|
260
|
+
};
|
|
261
|
+
const handleFocus = (index) => {
|
|
262
|
+
setFocusedIndex(index);
|
|
263
|
+
};
|
|
264
|
+
const handleBlur = () => {
|
|
265
|
+
setFocusedIndex(-1);
|
|
266
|
+
};
|
|
267
|
+
return /* @__PURE__ */ jsx(
|
|
268
|
+
"div",
|
|
269
|
+
{
|
|
270
|
+
ref,
|
|
271
|
+
className: cn(otpInputContainerVariants({ size }), className),
|
|
272
|
+
...api.rootAriaProps,
|
|
273
|
+
...props,
|
|
274
|
+
children: Array.from({ length }, (_, index) => {
|
|
275
|
+
api.getSlotProps(index);
|
|
276
|
+
const isFocused = index === focusedIndex;
|
|
277
|
+
const isFilled = values[index] !== "";
|
|
278
|
+
return /* @__PURE__ */ jsx(
|
|
279
|
+
"input",
|
|
280
|
+
{
|
|
281
|
+
ref: (el) => {
|
|
282
|
+
inputRefs.current[index] = el;
|
|
283
|
+
},
|
|
284
|
+
className: cn(otpInputSlotVariants({
|
|
285
|
+
size,
|
|
286
|
+
focused: isFocused ? "true" : "false",
|
|
287
|
+
filled: isFilled ? "true" : "false"
|
|
288
|
+
})),
|
|
289
|
+
value: values[index],
|
|
290
|
+
onChange: (e) => handleInput(index, e),
|
|
291
|
+
onKeyDown: (e) => handleKeyDown(index, e),
|
|
292
|
+
onPaste: handlePaste,
|
|
293
|
+
onFocus: () => handleFocus(index),
|
|
294
|
+
onBlur: handleBlur,
|
|
295
|
+
maxLength: 1,
|
|
296
|
+
inputMode: type === "number" ? "numeric" : "text",
|
|
297
|
+
pattern: type === "number" ? "[0-9]*" : void 0,
|
|
298
|
+
autoComplete: index === 0 ? "one-time-code" : "off",
|
|
299
|
+
disabled,
|
|
300
|
+
"aria-label": `Digit ${index + 1} of ${length}`,
|
|
301
|
+
"data-slot": "otp-slot",
|
|
302
|
+
"data-focused": isFocused ? "" : void 0,
|
|
303
|
+
"data-filled": isFilled ? "" : void 0
|
|
304
|
+
},
|
|
305
|
+
index
|
|
306
|
+
);
|
|
307
|
+
})
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
);
|
|
312
|
+
export {
|
|
313
|
+
OtpInput,
|
|
314
|
+
otpInputContainerVariants,
|
|
315
|
+
otpInputSlotVariants,
|
|
316
|
+
otpInputTokens
|
|
317
|
+
};
|
|
318
|
+
//# sourceMappingURL=react-otp-input.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../otp-input/src/otp-input.ts", "../../otp-input/src/otp-input.styles.ts", "../../react-otp-input/src/otp-input.tsx"],
|
|
4
|
+
"sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { Keys } from '@refraction-ui/shared'\n\nexport type OtpInputType = 'number' | 'text'\n\nexport interface OtpInputProps {\n length?: number\n value?: string\n autoFocus?: boolean\n type?: OtpInputType\n disabled?: boolean\n}\n\nexport interface OtpSlotProps {\n ariaProps: Partial<AccessibilityProps>\n dataAttributes: Record<string, string>\n inputProps: {\n maxLength: number\n inputMode: string\n pattern?: string\n autoComplete: string\n disabled: boolean\n }\n}\n\nexport interface OtpInputAPI {\n /** Current state */\n state: {\n values: string[]\n focusedIndex: number\n length: number\n disabled: boolean\n }\n /** Set the value at a specific index */\n setValue: (index: number, char: string) => string[]\n /** Get the combined OTP string */\n getValue: () => string\n /** Move focus in a direction, returns new index */\n moveFocus: (direction: 'left' | 'right') => number\n /** Get aria/input props for a specific slot */\n getSlotProps: (index: number) => OtpSlotProps\n /** Keyboard handlers factory for a specific slot */\n getKeyboardHandlers: (\n index: number,\n callbacks?: {\n onMoveFocus?: (index: number) => void\n onSetValue?: (index: number, values: string[]) => void\n },\n ) => KeyboardHandlerMap\n /** Parse a paste string into values array */\n parsePaste: (text: string) => string[]\n /** Root container ARIA props */\n rootAriaProps: Partial<AccessibilityProps>\n /** Whether interaction should be blocked */\n isInteractive: boolean\n}\n\nexport function createOtpInput(props: OtpInputProps = {}): OtpInputAPI {\n const {\n length = 6,\n value = '',\n autoFocus = false,\n type = 'number',\n disabled = false,\n } = props\n\n const isInteractive = !disabled\n\n // Initialize values from the provided value string\n const values: string[] = Array.from({ length }, (_, i) => value.charAt(i) || '')\n let focusedIndex = autoFocus ? 0 : -1\n\n const rootAriaProps: Partial<AccessibilityProps> = {\n role: 'group',\n 'aria-label': 'One-time password input',\n }\n\n function setValue(index: number, char: string): string[] {\n if (index < 0 || index >= length) return [...values]\n const filtered = type === 'number' ? char.replace(/[^0-9]/g, '') : char\n const newValues = [...values]\n newValues[index] = filtered.charAt(0) || ''\n // Update internal state\n for (let i = 0; i < length; i++) {\n values[i] = newValues[i]\n }\n return newValues\n }\n\n function getValue(): string {\n return values.join('')\n }\n\n function moveFocus(direction: 'left' | 'right'): number {\n if (direction === 'left') {\n focusedIndex = Math.max(0, focusedIndex - 1)\n } else {\n focusedIndex = Math.min(length - 1, focusedIndex + 1)\n }\n return focusedIndex\n }\n\n function getSlotProps(index: number): OtpSlotProps {\n const isFocused = index === focusedIndex\n const isFilled = values[index] !== ''\n\n const ariaProps: Partial<AccessibilityProps> = {\n 'aria-label': `Digit ${index + 1} of ${length}`,\n }\n\n const dataAttributes: Record<string, string> = {\n 'data-slot': 'otp-slot',\n }\n if (isFocused) {\n dataAttributes['data-focused'] = ''\n }\n if (isFilled) {\n dataAttributes['data-filled'] = ''\n }\n\n const inputProps = {\n maxLength: 1,\n inputMode: type === 'number' ? 'numeric' : 'text',\n pattern: type === 'number' ? '[0-9]*' : undefined,\n autoComplete: index === 0 ? 'one-time-code' : 'off',\n disabled,\n }\n\n return { ariaProps, dataAttributes, inputProps }\n }\n\n function getKeyboardHandlers(\n index: number,\n callbacks?: {\n onMoveFocus?: (index: number) => void\n onSetValue?: (index: number, values: string[]) => void\n },\n ): KeyboardHandlerMap {\n if (!isInteractive) {\n return {\n [Keys.Backspace]: (e) => e.preventDefault(),\n [Keys.ArrowLeft]: (e) => e.preventDefault(),\n [Keys.ArrowRight]: (e) => e.preventDefault(),\n }\n }\n\n return {\n [Keys.Backspace]: (e) => {\n e.preventDefault()\n if (values[index]) {\n const newValues = setValue(index, '')\n callbacks?.onSetValue?.(index, newValues)\n } else if (index > 0) {\n focusedIndex = index - 1\n const newValues = setValue(index - 1, '')\n callbacks?.onSetValue?.(index - 1, newValues)\n callbacks?.onMoveFocus?.(focusedIndex)\n }\n },\n [Keys.ArrowLeft]: (e) => {\n e.preventDefault()\n if (index > 0) {\n focusedIndex = index - 1\n callbacks?.onMoveFocus?.(focusedIndex)\n }\n },\n [Keys.ArrowRight]: (e) => {\n e.preventDefault()\n if (index < length - 1) {\n focusedIndex = index + 1\n callbacks?.onMoveFocus?.(focusedIndex)\n }\n },\n }\n }\n\n function parsePaste(text: string): string[] {\n const chars = type === 'number' ? text.replace(/[^0-9]/g, '') : text\n return Array.from({ length }, (_, i) => chars.charAt(i) || '')\n }\n\n return {\n state: {\n values,\n focusedIndex,\n length,\n disabled,\n },\n setValue,\n getValue,\n moveFocus,\n getSlotProps,\n getKeyboardHandlers,\n parsePaste,\n rootAriaProps,\n isInteractive,\n }\n}\n", "import { cva } from '@refraction-ui/shared'\nimport type { TokenContract } from '@refraction-ui/shared'\n\nexport const otpInputTokens: TokenContract = {\n name: 'otp-input',\n tokens: {\n bg: { variable: '--rfr-otp-bg', fallback: 'hsl(var(--background))' },\n fg: { variable: '--rfr-otp-fg', fallback: 'hsl(var(--foreground))' },\n border: { variable: '--rfr-otp-border', fallback: 'hsl(var(--border))' },\n 'border-filled': { variable: '--rfr-otp-border-filled', fallback: 'hsl(var(--primary))' },\n ring: { variable: '--rfr-otp-ring', fallback: 'hsl(var(--ring))' },\n },\n}\n\nexport const otpInputContainerVariants = cva({\n base: 'flex items-center gap-2',\n variants: {\n size: {\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-3',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n})\n\nexport const otpInputSlotVariants = cva({\n base: 'relative flex items-center justify-center rounded-md border border-input bg-background text-center font-mono shadow-sm transition-all',\n variants: {\n size: {\n sm: 'h-8 w-8 text-sm',\n default: 'h-10 w-10 text-base',\n lg: 'h-12 w-12 text-lg',\n },\n focused: {\n true: 'ring-2 ring-ring ring-offset-background',\n false: '',\n },\n filled: {\n true: 'border-primary',\n false: '',\n },\n },\n defaultVariants: {\n size: 'default',\n focused: 'false',\n filled: 'false',\n },\n})\n", "import * as React from 'react'\nimport {\n createOtpInput,\n otpInputContainerVariants,\n otpInputSlotVariants,\n type OtpInputType,\n} from '@refraction-ui/otp-input'\nimport { cn } from '@refraction-ui/shared'\n\nexport interface OtpInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n length?: number\n value?: string\n onChange?: (value: string) => void\n autoFocus?: boolean\n type?: OtpInputType\n disabled?: boolean\n size?: 'sm' | 'default' | 'lg'\n}\n\n/**\n * OtpInput -- a row of individual input boxes for one-time password entry.\n *\n * Features: auto-advance on type, backspace navigation, paste support, numeric/text mode.\n */\nexport const OtpInput = React.forwardRef<HTMLDivElement, OtpInputProps>(\n function OtpInput({\n length = 6,\n value = '',\n onChange,\n autoFocus = false,\n type = 'number',\n disabled = false,\n size = 'default',\n className,\n ...props\n }, ref) {\n const inputRefs = React.useRef<(HTMLInputElement | null)[]>([])\n const [focusedIndex, setFocusedIndex] = React.useState(autoFocus ? 0 : -1)\n const [values, setValues] = React.useState<string[]>(() =>\n Array.from({ length }, (_, i) => value.charAt(i) || ''),\n )\n\n // Sync external value changes\n React.useEffect(() => {\n setValues(Array.from({ length }, (_, i) => value.charAt(i) || ''))\n }, [value, length])\n\n // Auto-focus first input\n React.useEffect(() => {\n if (autoFocus && inputRefs.current[0]) {\n inputRefs.current[0].focus()\n }\n }, [autoFocus])\n\n const api = createOtpInput({ length, value, autoFocus, type, disabled })\n\n const updateValue = (index: number, char: string) => {\n const filtered = type === 'number' ? char.replace(/[^0-9]/g, '') : char\n const newChar = filtered.charAt(0) || ''\n const newValues = [...values]\n newValues[index] = newChar\n setValues(newValues)\n onChange?.(newValues.join(''))\n return newChar\n }\n\n const handleInput = (index: number, e: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = e.target.value\n const char = inputValue.slice(-1)\n const result = updateValue(index, char)\n\n // Auto-advance to next input\n if (result && index < length - 1) {\n setFocusedIndex(index + 1)\n inputRefs.current[index + 1]?.focus()\n }\n }\n\n const handleKeyDown = (index: number, e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Backspace') {\n e.preventDefault()\n if (values[index]) {\n updateValue(index, '')\n } else if (index > 0) {\n updateValue(index - 1, '')\n setFocusedIndex(index - 1)\n inputRefs.current[index - 1]?.focus()\n }\n }\n\n if (e.key === 'ArrowLeft' && index > 0) {\n e.preventDefault()\n setFocusedIndex(index - 1)\n inputRefs.current[index - 1]?.focus()\n }\n\n if (e.key === 'ArrowRight' && index < length - 1) {\n e.preventDefault()\n setFocusedIndex(index + 1)\n inputRefs.current[index + 1]?.focus()\n }\n }\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault()\n const pasteData = e.clipboardData.getData('text')\n const parsed = api.parsePaste(pasteData)\n setValues(parsed)\n onChange?.(parsed.join(''))\n\n // Focus the last filled input or the next empty one\n let lastFilledIndex = -1\n for (let i = parsed.length - 1; i >= 0; i--) {\n if (parsed[i] !== '') { lastFilledIndex = i; break }\n }\n const nextIndex = Math.min(lastFilledIndex + 1, length - 1)\n setFocusedIndex(nextIndex)\n inputRefs.current[nextIndex]?.focus()\n }\n\n const handleFocus = (index: number) => {\n setFocusedIndex(index)\n }\n\n const handleBlur = () => {\n setFocusedIndex(-1)\n }\n\n return (\n <div\n ref={ref}\n className={cn(otpInputContainerVariants({ size }), className)}\n {...api.rootAriaProps}\n {...props}\n >\n {Array.from({ length }, (_, index) => {\n const slotProps = api.getSlotProps(index)\n const isFocused = index === focusedIndex\n const isFilled = values[index] !== ''\n\n return (\n <input\n key={index}\n ref={(el) => { inputRefs.current[index] = el }}\n className={cn(otpInputSlotVariants({\n size,\n focused: isFocused ? 'true' : 'false',\n filled: isFilled ? 'true' : 'false',\n }))}\n value={values[index]}\n onChange={(e) => handleInput(index, e)}\n onKeyDown={(e) => handleKeyDown(index, e)}\n onPaste={handlePaste}\n onFocus={() => handleFocus(index)}\n onBlur={handleBlur}\n maxLength={1}\n inputMode={type === 'number' ? 'numeric' : 'text'}\n pattern={type === 'number' ? '[0-9]*' : undefined}\n autoComplete={index === 0 ? 'one-time-code' : 'off'}\n disabled={disabled}\n aria-label={`Digit ${index + 1} of ${length}`}\n data-slot=\"otp-slot\"\n data-focused={isFocused ? '' : undefined}\n data-filled={isFilled ? '' : undefined}\n />\n )\n })}\n </div>\n )\n },\n)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["OtpInput"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn,
|
|
3
|
+
cva
|
|
4
|
+
} from "./chunk-ZF3OHCGV.js";
|
|
5
|
+
|
|
6
|
+
// ../react-pagination/dist/index.js
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
|
|
9
|
+
// ../pagination/dist/index.js
|
|
10
|
+
function clampPage(page, totalPages) {
|
|
11
|
+
const total = Math.max(1, Math.floor(totalPages));
|
|
12
|
+
if (Number.isNaN(page)) return 1;
|
|
13
|
+
return Math.min(Math.max(1, Math.floor(page)), total);
|
|
14
|
+
}
|
|
15
|
+
function pageItem(page) {
|
|
16
|
+
return { type: "page", page };
|
|
17
|
+
}
|
|
18
|
+
function pageRange(start, end) {
|
|
19
|
+
const items = [];
|
|
20
|
+
for (let p = start; p <= end; p++) items.push(pageItem(p));
|
|
21
|
+
return items;
|
|
22
|
+
}
|
|
23
|
+
function getPaginationItems(current, totalPages, siblingCount = 1) {
|
|
24
|
+
const total = Math.max(0, Math.floor(totalPages));
|
|
25
|
+
if (total === 0) return [];
|
|
26
|
+
const maxVisibleWithoutEllipsis = siblingCount * 2 + 5;
|
|
27
|
+
if (total <= maxVisibleWithoutEllipsis) return pageRange(1, total);
|
|
28
|
+
const currentPage = clampPage(current, total);
|
|
29
|
+
const leftSibling = Math.max(currentPage - siblingCount, 1);
|
|
30
|
+
const rightSibling = Math.min(currentPage + siblingCount, total);
|
|
31
|
+
const showLeftEllipsis = leftSibling > 2;
|
|
32
|
+
const showRightEllipsis = rightSibling < total - 1;
|
|
33
|
+
if (!showLeftEllipsis && showRightEllipsis) {
|
|
34
|
+
const leftCount = 3 + 2 * siblingCount;
|
|
35
|
+
return [...pageRange(1, leftCount), { type: "ellipsis", id: "end" }, pageItem(total)];
|
|
36
|
+
}
|
|
37
|
+
if (showLeftEllipsis && !showRightEllipsis) {
|
|
38
|
+
const rightCount = 3 + 2 * siblingCount;
|
|
39
|
+
return [
|
|
40
|
+
pageItem(1),
|
|
41
|
+
{ type: "ellipsis", id: "start" },
|
|
42
|
+
...pageRange(total - rightCount + 1, total)
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
return [
|
|
46
|
+
pageItem(1),
|
|
47
|
+
{ type: "ellipsis", id: "start" },
|
|
48
|
+
...pageRange(leftSibling, rightSibling),
|
|
49
|
+
{ type: "ellipsis", id: "end" },
|
|
50
|
+
pageItem(total)
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
function createPagination(config = {}) {
|
|
54
|
+
const totalPages = Math.max(1, Math.floor(config.totalPages ?? 1));
|
|
55
|
+
const page = clampPage(config.page ?? 1, totalPages);
|
|
56
|
+
const siblingCount = Math.max(0, Math.floor(config.siblingCount ?? 1));
|
|
57
|
+
const canGoPrevious = page > 1;
|
|
58
|
+
const canGoNext = page < totalPages;
|
|
59
|
+
return {
|
|
60
|
+
ariaProps: {
|
|
61
|
+
role: "navigation",
|
|
62
|
+
"aria-label": config.ariaLabel ?? "Pagination"
|
|
63
|
+
},
|
|
64
|
+
dataAttributes: {
|
|
65
|
+
"data-page": String(page),
|
|
66
|
+
"data-total-pages": String(totalPages)
|
|
67
|
+
},
|
|
68
|
+
page,
|
|
69
|
+
totalPages,
|
|
70
|
+
items: getPaginationItems(page, totalPages, siblingCount),
|
|
71
|
+
canGoPrevious,
|
|
72
|
+
canGoNext,
|
|
73
|
+
previousPage: canGoPrevious ? page - 1 : page,
|
|
74
|
+
nextPage: canGoNext ? page + 1 : page,
|
|
75
|
+
getPageAria(p) {
|
|
76
|
+
return p === page ? { "aria-current": "page" } : {};
|
|
77
|
+
},
|
|
78
|
+
getPreviousAria() {
|
|
79
|
+
return { "aria-label": "Previous page" };
|
|
80
|
+
},
|
|
81
|
+
getNextAria() {
|
|
82
|
+
return { "aria-label": "Next page" };
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
var paginationVariants = cva({
|
|
87
|
+
base: "flex items-center gap-1"
|
|
88
|
+
});
|
|
89
|
+
var paginationItemVariants = cva({
|
|
90
|
+
base: [
|
|
91
|
+
"inline-flex h-9 min-w-9 items-center justify-center rounded-md border px-3",
|
|
92
|
+
"text-sm font-medium transition-colors",
|
|
93
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
94
|
+
"focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
95
|
+
"disabled:pointer-events-none disabled:opacity-50"
|
|
96
|
+
].join(" "),
|
|
97
|
+
variants: {
|
|
98
|
+
state: {
|
|
99
|
+
current: "border-primary bg-primary text-primary-foreground",
|
|
100
|
+
default: "border-border bg-background text-foreground hover:bg-muted"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
defaultVariants: {
|
|
104
|
+
state: "default"
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
var paginationEllipsisClass = "inline-flex h-9 min-w-9 items-center justify-center text-sm text-muted-foreground";
|
|
108
|
+
|
|
109
|
+
// ../react-pagination/dist/index.js
|
|
110
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
111
|
+
var Pagination = React.forwardRef(
|
|
112
|
+
function Pagination2({
|
|
113
|
+
className,
|
|
114
|
+
page: controlledPage,
|
|
115
|
+
defaultPage,
|
|
116
|
+
totalPages = 1,
|
|
117
|
+
siblingCount = 1,
|
|
118
|
+
onPageChange,
|
|
119
|
+
disabled = false,
|
|
120
|
+
children,
|
|
121
|
+
...props
|
|
122
|
+
}, ref) {
|
|
123
|
+
const isControlled = controlledPage !== void 0;
|
|
124
|
+
const [internalPage, setInternalPage] = React.useState(defaultPage ?? 1);
|
|
125
|
+
const api = createPagination({
|
|
126
|
+
page: isControlled ? controlledPage : internalPage,
|
|
127
|
+
totalPages,
|
|
128
|
+
siblingCount
|
|
129
|
+
});
|
|
130
|
+
const goTo = (target) => {
|
|
131
|
+
if (disabled || target === api.page) return;
|
|
132
|
+
if (!isControlled) setInternalPage(target);
|
|
133
|
+
onPageChange?.(target);
|
|
134
|
+
};
|
|
135
|
+
return /* @__PURE__ */ jsx(
|
|
136
|
+
"div",
|
|
137
|
+
{
|
|
138
|
+
ref,
|
|
139
|
+
className: cn(paginationVariants(), className),
|
|
140
|
+
...api.ariaProps,
|
|
141
|
+
...api.dataAttributes,
|
|
142
|
+
...props,
|
|
143
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
144
|
+
/* @__PURE__ */ jsx(
|
|
145
|
+
"button",
|
|
146
|
+
{
|
|
147
|
+
type: "button",
|
|
148
|
+
...api.getPreviousAria(),
|
|
149
|
+
disabled: disabled || !api.canGoPrevious,
|
|
150
|
+
className: paginationItemVariants(),
|
|
151
|
+
onClick: () => goTo(api.previousPage),
|
|
152
|
+
children: "Previous"
|
|
153
|
+
}
|
|
154
|
+
),
|
|
155
|
+
api.items.map(
|
|
156
|
+
(item) => item.type === "ellipsis" ? /* @__PURE__ */ jsx(
|
|
157
|
+
"span",
|
|
158
|
+
{
|
|
159
|
+
"aria-hidden": "true",
|
|
160
|
+
className: paginationEllipsisClass,
|
|
161
|
+
children: "\u2026"
|
|
162
|
+
},
|
|
163
|
+
`ellipsis-${item.id}`
|
|
164
|
+
) : /* @__PURE__ */ jsx(
|
|
165
|
+
"button",
|
|
166
|
+
{
|
|
167
|
+
type: "button",
|
|
168
|
+
...api.getPageAria(item.page),
|
|
169
|
+
disabled,
|
|
170
|
+
"data-state": item.page === api.page ? "current" : "default",
|
|
171
|
+
className: paginationItemVariants({
|
|
172
|
+
state: item.page === api.page ? "current" : "default"
|
|
173
|
+
}),
|
|
174
|
+
onClick: () => goTo(item.page),
|
|
175
|
+
children: item.page
|
|
176
|
+
},
|
|
177
|
+
item.page
|
|
178
|
+
)
|
|
179
|
+
),
|
|
180
|
+
/* @__PURE__ */ jsx(
|
|
181
|
+
"button",
|
|
182
|
+
{
|
|
183
|
+
type: "button",
|
|
184
|
+
...api.getNextAria(),
|
|
185
|
+
disabled: disabled || !api.canGoNext,
|
|
186
|
+
className: paginationItemVariants(),
|
|
187
|
+
onClick: () => goTo(api.nextPage),
|
|
188
|
+
children: "Next"
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
] })
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
export {
|
|
197
|
+
Pagination
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=react-pagination.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../pagination/src/pagination.ts", "../../pagination/src/pagination.styles.ts", "../../react-pagination/src/pagination.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * @refraction-ui/pagination — headless pagination.\n *\n * Owns the *behavior* of page navigation: the windowed page range with\n * ellipses, current-page clamping, and prev/next edge semantics. It has NO UI\n * opinion — adapters render the controls and spread the ARIA objects.\n */\n\n/** One entry of the computed page range: a page number or an ellipsis gap. */\nexport type PaginationItem =\n | { type: 'page'; page: number }\n | { type: 'ellipsis'; id: 'start' | 'end' }\n\n/** Options for {@link createPagination}. */\nexport interface PaginationConfig {\n /** Current page (1-based). Clamped into `[1, totalPages]`. */\n page?: number\n /** Total number of pages. Values < 1 behave as 1. */\n totalPages?: number\n /** Pages shown on each side of the current page (default 1). */\n siblingCount?: number\n /** Accessible label for the nav landmark (default `'Pagination'`). */\n ariaLabel?: string\n}\n\n/** The computed view of a pagination control. */\nexport interface PaginationAPI {\n /** ARIA attributes for the root element (`role=\"navigation\"`). */\n ariaProps: Record<string, string | number | boolean>\n /** Data attributes for styling hooks. */\n dataAttributes: Record<string, string>\n /** Current page after clamping (1-based). */\n page: number\n /** Total number of pages (>= 1). */\n totalPages: number\n /** Windowed range of pages and ellipses to render. */\n items: PaginationItem[]\n /** Whether \"previous\" navigation is possible. */\n canGoPrevious: boolean\n /** Whether \"next\" navigation is possible. */\n canGoNext: boolean\n /** Target page for the previous control (clamped). */\n previousPage: number\n /** Target page for the next control (clamped). */\n nextPage: number\n /** ARIA attributes for a numbered page button (`aria-current` on the current page). */\n getPageAria(page: number): Record<string, string | number | boolean>\n /** ARIA attributes for the previous control. */\n getPreviousAria(): Record<string, string | number | boolean>\n /** ARIA attributes for the next control. */\n getNextAria(): Record<string, string | number | boolean>\n}\n\n/** Clamp a 1-based page number into `[1, max(totalPages, 1)]`. */\nexport function clampPage(page: number, totalPages: number): number {\n const total = Math.max(1, Math.floor(totalPages))\n if (Number.isNaN(page)) return 1\n return Math.min(Math.max(1, Math.floor(page)), total)\n}\n\nfunction pageItem(page: number): PaginationItem {\n return { type: 'page', page }\n}\n\nfunction pageRange(start: number, end: number): PaginationItem[] {\n const items: PaginationItem[] = []\n for (let p = start; p <= end; p++) items.push(pageItem(p))\n return items\n}\n\n/**\n * Compute the windowed page range with ellipses.\n *\n * Always shows the first and last page plus `siblingCount` pages on each side\n * of the current page; gaps of more than one page collapse into an ellipsis.\n * Small totals render every page (no ellipses).\n */\nexport function getPaginationItems(\n current: number,\n totalPages: number,\n siblingCount = 1,\n): PaginationItem[] {\n const total = Math.max(0, Math.floor(totalPages))\n if (total === 0) return []\n\n // first + last + current + 2 siblings + 2 ellipses\n const maxVisibleWithoutEllipsis = siblingCount * 2 + 5\n if (total <= maxVisibleWithoutEllipsis) return pageRange(1, total)\n\n const currentPage = clampPage(current, total)\n const leftSibling = Math.max(currentPage - siblingCount, 1)\n const rightSibling = Math.min(currentPage + siblingCount, total)\n\n const showLeftEllipsis = leftSibling > 2\n const showRightEllipsis = rightSibling < total - 1\n\n if (!showLeftEllipsis && showRightEllipsis) {\n const leftCount = 3 + 2 * siblingCount\n return [...pageRange(1, leftCount), { type: 'ellipsis', id: 'end' }, pageItem(total)]\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n const rightCount = 3 + 2 * siblingCount\n return [\n pageItem(1),\n { type: 'ellipsis', id: 'start' },\n ...pageRange(total - rightCount + 1, total),\n ]\n }\n\n return [\n pageItem(1),\n { type: 'ellipsis', id: 'start' },\n ...pageRange(leftSibling, rightSibling),\n { type: 'ellipsis', id: 'end' },\n pageItem(total),\n ]\n}\n\n/**\n * createPagination — the framework-agnostic view of a pagination control:\n * ARIA objects for the nav landmark and controls, plus the clamped\n * current/total and prev/next edge semantics. Adapters own the page state\n * (controlled/uncontrolled) and call this per render.\n */\nexport function createPagination(config: PaginationConfig = {}): PaginationAPI {\n const totalPages = Math.max(1, Math.floor(config.totalPages ?? 1))\n const page = clampPage(config.page ?? 1, totalPages)\n const siblingCount = Math.max(0, Math.floor(config.siblingCount ?? 1))\n\n const canGoPrevious = page > 1\n const canGoNext = page < totalPages\n\n return {\n ariaProps: {\n role: 'navigation',\n 'aria-label': config.ariaLabel ?? 'Pagination',\n },\n dataAttributes: {\n 'data-page': String(page),\n 'data-total-pages': String(totalPages),\n },\n page,\n totalPages,\n items: getPaginationItems(page, totalPages, siblingCount),\n canGoPrevious,\n canGoNext,\n previousPage: canGoPrevious ? page - 1 : page,\n nextPage: canGoNext ? page + 1 : page,\n getPageAria(p): Record<string, string | number | boolean> {\n return p === page ? { 'aria-current': 'page' } : {}\n },\n getPreviousAria(): Record<string, string | number | boolean> {\n return { 'aria-label': 'Previous page' }\n },\n getNextAria(): Record<string, string | number | boolean> {\n return { 'aria-label': 'Next page' }\n },\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\n/** Row of pagination controls. */\nexport const paginationVariants = cva({\n base: 'flex items-center gap-1',\n})\n\n/**\n * A pagination button (prev / next / numbered page). The `state` variant\n * carries the current-page treatment so adapters never inline these classes.\n */\nexport const paginationItemVariants = cva({\n base: [\n 'inline-flex h-9 min-w-9 items-center justify-center rounded-md border px-3',\n 'text-sm font-medium transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n 'focus-visible:ring-offset-2 focus-visible:ring-offset-background',\n 'disabled:pointer-events-none disabled:opacity-50',\n ].join(' '),\n variants: {\n state: {\n current: 'border-primary bg-primary text-primary-foreground',\n default: 'border-border bg-background text-foreground hover:bg-muted',\n },\n },\n defaultVariants: {\n state: 'default',\n },\n})\n\n/** Ellipsis gap between page numbers (not interactive). */\nexport const paginationEllipsisClass =\n 'inline-flex h-9 min-w-9 items-center justify-center text-sm text-muted-foreground'\n", "import * as React from 'react'\nimport { cn } from '@refraction-ui/shared'\nimport {\n createPagination,\n paginationVariants,\n paginationItemVariants,\n paginationEllipsisClass,\n} from '@refraction-ui/pagination'\n\nexport interface PaginationProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Current page, 1-based (controlled). Pair with `onPageChange`. */\n page?: number\n /** Initial page for uncontrolled usage (default 1). */\n defaultPage?: number\n /** Total number of pages (default 1). */\n totalPages?: number\n /** Pages shown on each side of the current page (default 1). */\n siblingCount?: number\n /** Called with the target page when a control is activated. */\n onPageChange?: (page: number) => void\n /** Disables every control. */\n disabled?: boolean\n}\n\n/**\n * Pagination — page navigation with a windowed page range and ellipses.\n *\n * Renders `role=\"navigation\"` with previous/next controls and numbered page\n * buttons (`aria-current=\"page\"` on the current page). Range computation,\n * clamping, edge semantics, and ARIA come from the headless\n * `@refraction-ui/pagination` core. Pass `children` to render fully custom\n * controls instead of the generated ones.\n */\nexport const Pagination = React.forwardRef<HTMLDivElement, PaginationProps>(\n function Pagination(\n {\n className,\n page: controlledPage,\n defaultPage,\n totalPages = 1,\n siblingCount = 1,\n onPageChange,\n disabled = false,\n children,\n ...props\n },\n ref,\n ) {\n const isControlled = controlledPage !== undefined\n const [internalPage, setInternalPage] = React.useState(defaultPage ?? 1)\n\n const api = createPagination({\n page: isControlled ? controlledPage : internalPage,\n totalPages,\n siblingCount,\n })\n\n const goTo = (target: number) => {\n if (disabled || target === api.page) return\n if (!isControlled) setInternalPage(target)\n onPageChange?.(target)\n }\n\n return (\n <div\n ref={ref}\n className={cn(paginationVariants(), className)}\n {...api.ariaProps}\n {...api.dataAttributes}\n {...props}\n >\n {children ?? (\n <>\n <button\n type=\"button\"\n {...api.getPreviousAria()}\n disabled={disabled || !api.canGoPrevious}\n className={paginationItemVariants()}\n onClick={() => goTo(api.previousPage)}\n >\n Previous\n </button>\n {api.items.map((item) =>\n item.type === 'ellipsis' ? (\n <span\n key={`ellipsis-${item.id}`}\n aria-hidden=\"true\"\n className={paginationEllipsisClass}\n >\n …\n </span>\n ) : (\n <button\n key={item.page}\n type=\"button\"\n {...api.getPageAria(item.page)}\n disabled={disabled}\n data-state={item.page === api.page ? 'current' : 'default'}\n className={paginationItemVariants({\n state: item.page === api.page ? 'current' : 'default',\n })}\n onClick={() => goTo(item.page)}\n >\n {item.page}\n </button>\n ),\n )}\n <button\n type=\"button\"\n {...api.getNextAria()}\n disabled={disabled || !api.canGoNext}\n className={paginationItemVariants()}\n onClick={() => goTo(api.nextPage)}\n >\n Next\n </button>\n </>\n )}\n </div>\n )\n },\n)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Pagination"]
|
|
7
|
+
}
|