@refraction-ui/astro 0.4.2 → 0.4.4
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/accordion/index.ts +1 -0
- package/dist/ai/ai-manager.ts +121 -0
- package/dist/ai/index.ts +23 -0
- package/dist/ai/mock-providers.ts +68 -0
- package/dist/ai/sanitizer.ts +174 -0
- package/dist/ai/tts-manager.ts +80 -0
- package/dist/ai/types.ts +72 -0
- package/dist/animated-text/animated-text.styles.ts +28 -0
- package/dist/animated-text/animated-text.ts +83 -0
- package/dist/animated-text/index.ts +15 -0
- package/dist/app-shell/app-shell.ts +252 -0
- package/dist/app-shell/auth-shell.ts +84 -0
- package/dist/app-shell/index.ts +22 -0
- package/dist/app-shell/page-shell.ts +125 -0
- package/dist/astro-accordion/Button.astro +1 -1
- package/dist/astro-ai/index.ts +1 -1
- package/dist/astro-animated-text/AnimatedText.astro +1 -1
- package/dist/astro-animated-text/TypewriterText.astro +1 -1
- package/dist/astro-app-shell/AppShell.astro +1 -1
- package/dist/astro-app-shell/AuthShell.astro +1 -1
- package/dist/astro-app-shell/AuthShellCard.astro +1 -1
- package/dist/astro-app-shell/PageShell.astro +1 -1
- package/dist/astro-app-shell/PageShellSection.astro +1 -1
- package/dist/astro-app-shell/index.ts +1 -1
- package/dist/astro-auth/index.ts +2 -2
- package/dist/astro-avatar/Avatar.astro +1 -1
- package/dist/astro-avatar/AvatarFallback.astro +1 -1
- package/dist/astro-avatar/AvatarImage.astro +1 -1
- package/dist/astro-avatar-group/AvatarGroup.astro +1 -1
- package/dist/astro-badge/Badge.astro +1 -1
- package/dist/astro-bottom-nav/BottomNav.astro +1 -1
- package/dist/astro-breadcrumbs/Breadcrumbs.astro +1 -1
- package/dist/astro-button/Button.astro +1 -1
- package/dist/astro-calendar/Calendar.astro +1 -1
- package/dist/astro-card/Card.astro +1 -1
- package/dist/astro-card/CardContent.astro +1 -1
- package/dist/astro-card/CardDescription.astro +1 -1
- package/dist/astro-card/CardFooter.astro +1 -1
- package/dist/astro-card/CardHeader.astro +1 -1
- package/dist/astro-card/CardTitle.astro +1 -1
- package/dist/astro-card-grid/CardGrid.astro +1 -1
- package/dist/astro-carousel/Button.astro +1 -1
- package/dist/astro-charts/Bars.astro +1 -1
- package/dist/astro-charts/Chart.astro +1 -1
- package/dist/astro-charts/Circles.astro +1 -1
- package/dist/astro-charts/Histogram.astro +1 -1
- package/dist/astro-charts/Line.astro +1 -1
- package/dist/astro-charts/PieChart.astro +1 -1
- package/dist/astro-charts/ScatterPlot.astro +1 -1
- package/dist/astro-charts/index.ts +1 -1
- package/dist/astro-checkbox/Checkbox.astro +1 -1
- package/dist/astro-code-editor/CodeEditor.astro +1 -1
- package/dist/astro-collapsible/Collapsible.astro +1 -1
- package/dist/astro-collapsible/CollapsibleContent.astro +1 -1
- package/dist/astro-command/Command.astro +1 -1
- package/dist/astro-command/CommandGroup.astro +1 -1
- package/dist/astro-command/CommandInput.astro +1 -1
- package/dist/astro-command/CommandItem.astro +1 -1
- package/dist/astro-command-input/CommandInput.astro +1 -1
- package/dist/astro-content-protection/ContentProtection.astro +1 -1
- package/dist/astro-data-table/DataTable.astro +1 -1
- package/dist/astro-date-picker/DatePicker.astro +1 -1
- package/dist/astro-device-frame/DeviceFrame.astro +1 -1
- package/dist/astro-dialog/DialogContent.astro +1 -1
- package/dist/astro-dialog/DialogOverlay.astro +1 -1
- package/dist/astro-diff-viewer/DiffViewer.astro +1 -1
- package/dist/astro-dropdown-menu/DropdownMenuContent.astro +1 -1
- package/dist/astro-dropdown-menu/DropdownMenuItem.astro +1 -1
- package/dist/astro-emoji-picker/EmojiPicker.astro +1 -1
- package/dist/astro-feedback-dialog/FeedbackDialog.astro +1 -1
- package/dist/astro-file-upload/FileUpload.astro +1 -1
- package/dist/astro-footer/Footer.astro +1 -1
- package/dist/astro-inline-editor/InlineEditor.astro +1 -1
- package/dist/astro-input/Input.astro +1 -1
- package/dist/astro-input-group/InputGroup.astro +1 -1
- package/dist/astro-input-group/InputGroupAddon.astro +1 -1
- package/dist/astro-input-group/InputGroupButton.astro +1 -1
- package/dist/astro-install-prompt/InstallPrompt.astro +1 -1
- package/dist/astro-keyboard-shortcut/ShortcutBadge.astro +1 -1
- package/dist/astro-language-selector/LanguageSelector.astro +1 -1
- package/dist/astro-link-card/LinkCard.astro +1 -1
- package/dist/astro-markdown-renderer/MarkdownRenderer.astro +1 -1
- package/dist/astro-mobile-nav/MobileNav.astro +1 -1
- package/dist/astro-mobile-nav/MobileNavLink.astro +1 -1
- package/dist/astro-mobile-nav/MobileNavTrigger.astro +1 -1
- package/dist/astro-navbar/Navbar.astro +1 -1
- package/dist/astro-otp-input/OtpInput.astro +1 -1
- package/dist/astro-payment/Payment.astro +1 -1
- package/dist/astro-popover/PopoverContent.astro +1 -1
- package/dist/astro-presence-indicator/PresenceIndicator.astro +1 -1
- package/dist/astro-progress-display/BadgeDisplay.astro +1 -1
- package/dist/astro-progress-display/ProgressBar.astro +1 -1
- package/dist/astro-progress-display/StatsGrid.astro +1 -1
- package/dist/astro-radio/RadioGroup.astro +1 -1
- package/dist/astro-radio/RadioItem.astro +1 -1
- package/dist/astro-reaction-bar/ReactionBar.astro +1 -1
- package/dist/astro-resizable-layout/ResizableDivider.astro +1 -1
- package/dist/astro-resizable-layout/ResizableLayout.astro +1 -1
- package/dist/astro-resizable-layout/ResizablePane.astro +1 -1
- package/dist/astro-resizable-layout/index.ts +1 -1
- package/dist/astro-rich-editor/index.ts +2 -2
- package/dist/astro-search-bar/SearchBar.astro +1 -1
- package/dist/astro-search-bar/SearchResults.astro +1 -1
- package/dist/astro-select/Select.astro +1 -1
- package/dist/astro-select/SelectContent.astro +1 -1
- package/dist/astro-select/SelectItem.astro +1 -1
- package/dist/astro-select/SelectTrigger.astro +1 -1
- package/dist/astro-sidebar/Sidebar.astro +1 -1
- package/dist/astro-skeleton/Skeleton.astro +1 -1
- package/dist/astro-slide-viewer/SlideViewer.astro +1 -1
- package/dist/astro-status-indicator/StatusIndicator.astro +1 -1
- package/dist/astro-switch/Switch.astro +1 -1
- package/dist/astro-table-of-contents/TableOfContents.astro +1 -1
- package/dist/astro-tabs/Tabs.astro +1 -1
- package/dist/astro-tabs/TabsList.astro +1 -1
- package/dist/astro-tabs/TabsTrigger.astro +1 -1
- package/dist/astro-textarea/Textarea.astro +1 -1
- package/dist/astro-theme/ThemeScript.astro +1 -1
- package/dist/astro-thread-view/ThreadView.astro +1 -1
- package/dist/astro-toast/Toast.astro +1 -1
- package/dist/astro-tooltip/TooltipContent.astro +1 -1
- package/dist/astro-version-selector/VersionSelector.astro +1 -1
- package/dist/astro-video-player/VideoPlayer.astro +1 -1
- package/dist/auth/adapters/mock.ts +74 -0
- package/dist/auth/auth-machine.ts +120 -0
- package/dist/auth/index.ts +22 -0
- package/dist/auth/rbac.ts +44 -0
- package/dist/auth/types.ts +44 -0
- package/dist/avatar/avatar.styles.ts +47 -0
- package/dist/avatar/avatar.ts +73 -0
- package/dist/avatar/index.ts +15 -0
- package/dist/avatar-group/avatar-group.styles.ts +63 -0
- package/dist/avatar-group/avatar-group.ts +106 -0
- package/dist/avatar-group/index.ts +18 -0
- package/dist/badge/badge.styles.ts +24 -0
- package/dist/badge/badge.ts +48 -0
- package/dist/badge/index.ts +10 -0
- package/dist/bottom-nav/bottom-nav.styles.ts +18 -0
- package/dist/bottom-nav/bottom-nav.ts +33 -0
- package/dist/bottom-nav/index.ts +2 -0
- package/dist/breadcrumbs/breadcrumbs.styles.ts +20 -0
- package/dist/breadcrumbs/breadcrumbs.ts +72 -0
- package/dist/breadcrumbs/index.ts +8 -0
- package/dist/button/button.styles.ts +38 -0
- package/dist/button/button.ts +64 -0
- package/dist/button/index.ts +10 -0
- package/dist/calendar/calendar.styles.ts +21 -0
- package/dist/calendar/calendar.ts +202 -0
- package/dist/calendar/index.ts +9 -0
- package/dist/callout/callout.ts +1 -0
- package/dist/callout/index.ts +1 -0
- package/dist/card/card.styles.ts +55 -0
- package/dist/card/card.ts +45 -0
- package/dist/card/index.ts +20 -0
- package/dist/card-grid/card-grid.ts +9 -0
- package/dist/card-grid/index.ts +1 -0
- package/dist/carousel/index.ts +1 -0
- package/dist/charts/axis.ts +50 -0
- package/dist/charts/chart.ts +73 -0
- package/dist/charts/colorblind.ts +100 -0
- package/dist/charts/data.ts +72 -0
- package/dist/charts/geometry.ts +54 -0
- package/dist/charts/index.ts +61 -0
- package/dist/charts/scales.ts +151 -0
- package/dist/checkbox/checkbox.styles.ts +33 -0
- package/dist/checkbox/checkbox.ts +73 -0
- package/dist/checkbox/index.ts +10 -0
- package/dist/code-block/code-block.ts +1 -0
- package/dist/code-block/index.ts +1 -0
- package/dist/code-editor/code-editor.styles.ts +32 -0
- package/dist/code-editor/code-editor.ts +140 -0
- package/dist/code-editor/index.ts +9 -0
- package/dist/collapsible/collapsible.styles.ts +14 -0
- package/dist/collapsible/collapsible.ts +93 -0
- package/dist/collapsible/index.ts +7 -0
- package/dist/command/command.styles.ts +27 -0
- package/dist/command/command.ts +179 -0
- package/dist/command/index.ts +14 -0
- package/dist/command-input/command-input.ts +176 -0
- package/dist/command-input/index.ts +1 -0
- package/dist/content-protection/content-protection.styles.ts +9 -0
- package/dist/content-protection/content-protection.ts +68 -0
- package/dist/content-protection/index.ts +8 -0
- package/dist/data-table/data-table.styles.ts +55 -0
- package/dist/data-table/data-table.ts +183 -0
- package/dist/data-table/index.ts +15 -0
- package/dist/date-picker/date-picker.styles.ts +31 -0
- package/dist/date-picker/date-picker.ts +333 -0
- package/dist/date-picker/index.ts +18 -0
- package/dist/device-frame/device-frame.styles.ts +21 -0
- package/dist/device-frame/device-frame.ts +112 -0
- package/dist/device-frame/index.ts +10 -0
- package/dist/dialog/dialog.styles.ts +8 -0
- package/dist/dialog/dialog.ts +133 -0
- package/dist/dialog/index.ts +8 -0
- package/dist/diff-viewer/diff-viewer.styles.ts +124 -0
- package/dist/diff-viewer/diff-viewer.ts +255 -0
- package/dist/diff-viewer/index.ts +20 -0
- package/dist/dropdown-menu/dropdown-menu.styles.ts +9 -0
- package/dist/dropdown-menu/dropdown-menu.ts +139 -0
- package/dist/dropdown-menu/index.ts +9 -0
- package/dist/emoji-picker/emoji-data.ts +282 -0
- package/dist/emoji-picker/emoji-picker.styles.ts +32 -0
- package/dist/emoji-picker/emoji-picker.ts +165 -0
- package/dist/emoji-picker/index.ts +25 -0
- package/dist/feedback-dialog/feedback-dialog.styles.ts +15 -0
- package/dist/feedback-dialog/feedback-dialog.ts +147 -0
- package/dist/feedback-dialog/index.ts +11 -0
- package/dist/file-upload/file-upload.styles.ts +30 -0
- package/dist/file-upload/file-upload.ts +260 -0
- package/dist/file-upload/index.ts +19 -0
- package/dist/footer/footer.styles.ts +5 -0
- package/dist/footer/footer.ts +32 -0
- package/dist/footer/index.ts +9 -0
- package/dist/index.ts +1 -1
- package/dist/inline-editor/index.ts +13 -0
- package/dist/inline-editor/inline-editor.styles.ts +42 -0
- package/dist/inline-editor/inline-editor.ts +96 -0
- package/dist/input/index.ts +9 -0
- package/dist/input/input.styles.ts +15 -0
- package/dist/input/input.ts +84 -0
- package/dist/input-group/index.ts +13 -0
- package/dist/input-group/input-group.styles.ts +50 -0
- package/dist/input-group/input-group.ts +44 -0
- package/dist/install-prompt/index.ts +9 -0
- package/dist/install-prompt/install-prompt.styles.ts +5 -0
- package/dist/install-prompt/install-prompt.ts +68 -0
- package/dist/keyboard-shortcut/index.ts +12 -0
- package/dist/keyboard-shortcut/keyboard-shortcut.styles.ts +8 -0
- package/dist/keyboard-shortcut/keyboard-shortcut.ts +153 -0
- package/dist/language-selector/index.ts +8 -0
- package/dist/language-selector/language-selector.styles.ts +28 -0
- package/dist/language-selector/language-selector.ts +149 -0
- package/dist/link-card/index.ts +1 -0
- package/dist/link-card/link-card.ts +9 -0
- package/dist/markdown-renderer/index.ts +8 -0
- package/dist/markdown-renderer/markdown-renderer.styles.ts +31 -0
- package/dist/markdown-renderer/markdown-renderer.ts +251 -0
- package/dist/mobile-nav/index.ts +14 -0
- package/dist/mobile-nav/mobile-nav.styles.ts +39 -0
- package/dist/mobile-nav/mobile-nav.ts +74 -0
- package/dist/navbar/index.ts +9 -0
- package/dist/navbar/navbar.styles.ts +29 -0
- package/dist/navbar/navbar.ts +39 -0
- package/dist/otp-input/index.ts +13 -0
- package/dist/otp-input/otp-input.styles.ts +51 -0
- package/dist/otp-input/otp-input.ts +198 -0
- package/dist/pagination/index.ts +1 -0
- package/dist/payment/index.ts +1 -0
- package/dist/payment/payment.ts +16 -0
- package/dist/popover/index.ts +7 -0
- package/dist/popover/popover.styles.ts +16 -0
- package/dist/popover/popover.ts +89 -0
- package/dist/presence-indicator/index.ts +14 -0
- package/dist/presence-indicator/presence-indicator.styles.ts +29 -0
- package/dist/presence-indicator/presence-indicator.ts +63 -0
- package/dist/progress-display/index.ts +15 -0
- package/dist/progress-display/progress-display.styles.ts +72 -0
- package/dist/progress-display/progress-display.ts +60 -0
- package/dist/radio/index.ts +8 -0
- package/dist/radio/radio.styles.ts +34 -0
- package/dist/radio/radio.ts +70 -0
- package/dist/reaction-bar/index.ts +14 -0
- package/dist/reaction-bar/reaction-bar.styles.ts +23 -0
- package/dist/reaction-bar/reaction-bar.ts +87 -0
- package/dist/resizable-layout/index.ts +12 -0
- package/dist/resizable-layout/resizable-layout.styles.ts +50 -0
- package/dist/resizable-layout/resizable-layout.ts +139 -0
- package/dist/rich-editor/editor.ts +342 -0
- package/dist/rich-editor/emoji.ts +175 -0
- package/dist/rich-editor/history.ts +79 -0
- package/dist/rich-editor/index.ts +106 -0
- package/dist/rich-editor/markdown-shortcuts.ts +248 -0
- package/dist/rich-editor/mentions.ts +162 -0
- package/dist/rich-editor/model.ts +206 -0
- package/dist/rich-editor/operations.ts +772 -0
- package/dist/rich-editor/selection.ts +157 -0
- package/dist/rich-editor/serialization.ts +711 -0
- package/dist/rich-editor/slash-commands.ts +212 -0
- package/dist/search-bar/index.ts +7 -0
- package/dist/search-bar/search-bar.styles.ts +29 -0
- package/dist/search-bar/search-bar.ts +130 -0
- package/dist/select/index.ts +13 -0
- package/dist/select/select.styles.ts +52 -0
- package/dist/select/select.ts +152 -0
- package/dist/sidebar/index.ts +9 -0
- package/dist/sidebar/sidebar.styles.ts +27 -0
- package/dist/sidebar/sidebar.ts +59 -0
- package/dist/skeleton/index.ts +8 -0
- package/dist/skeleton/skeleton.styles.ts +16 -0
- package/dist/skeleton/skeleton.ts +39 -0
- package/dist/skip-to-content/index.ts +1 -0
- package/dist/skip-to-content/skip-to-content.ts +1 -0
- package/dist/slide-viewer/index.ts +16 -0
- package/dist/slide-viewer/slide-viewer.styles.ts +57 -0
- package/dist/slide-viewer/slide-viewer.ts +152 -0
- package/dist/slider/index.ts +1 -0
- package/dist/slider/slider.ts +2 -0
- package/dist/status-indicator/index.ts +15 -0
- package/dist/status-indicator/status-indicator.styles.ts +41 -0
- package/dist/status-indicator/status-indicator.ts +66 -0
- package/dist/steps/index.ts +1 -0
- package/dist/steps/steps.ts +1 -0
- package/dist/switch/index.ts +7 -0
- package/dist/switch/switch.styles.ts +55 -0
- package/dist/switch/switch.ts +63 -0
- package/dist/table-of-contents/index.ts +1 -0
- package/dist/table-of-contents/table-of-contents.ts +37 -0
- package/dist/tabs/index.ts +8 -0
- package/dist/tabs/tabs.styles.ts +9 -0
- package/dist/tabs/tabs.ts +133 -0
- package/dist/textarea/index.ts +7 -0
- package/dist/textarea/textarea.styles.ts +15 -0
- package/dist/textarea/textarea.ts +59 -0
- package/dist/theme/dom-adapters.ts +60 -0
- package/dist/theme/index.ts +18 -0
- package/dist/theme/theme-machine.ts +130 -0
- package/dist/theme/theme-script.ts +18 -0
- package/dist/thread-view/index.ts +26 -0
- package/dist/thread-view/thread-view.styles.ts +35 -0
- package/dist/thread-view/thread-view.ts +176 -0
- package/dist/toast/index.ts +13 -0
- package/dist/toast/toast.styles.ts +19 -0
- package/dist/toast/toast.ts +203 -0
- package/dist/tooltip/index.ts +7 -0
- package/dist/tooltip/tooltip.styles.ts +16 -0
- package/dist/tooltip/tooltip.ts +109 -0
- package/dist/version-selector/index.ts +12 -0
- package/dist/version-selector/version-selector.styles.ts +41 -0
- package/dist/version-selector/version-selector.ts +136 -0
- package/dist/video-player/index.ts +12 -0
- package/dist/video-player/video-player.styles.ts +42 -0
- package/dist/video-player/video-player.ts +100 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { cva } from '../shared/index.ts'
|
|
2
|
+
|
|
3
|
+
export const overlayStyles =
|
|
4
|
+
'fixed inset-0 z-50 bg-black/80'
|
|
5
|
+
|
|
6
|
+
export const dialogContentVariants = cva({
|
|
7
|
+
base: 'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg',
|
|
8
|
+
})
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { AccessibilityProps, KeyboardHandlerMap, FocusTrapConfig } from '../shared/index.ts'
|
|
2
|
+
import { createMachine, Keys, generateId } from '../shared/index.ts'
|
|
3
|
+
|
|
4
|
+
export interface DialogProps {
|
|
5
|
+
/** Whether the dialog is open (controlled) */
|
|
6
|
+
open?: boolean
|
|
7
|
+
/** Whether the dialog starts open (uncontrolled) */
|
|
8
|
+
defaultOpen?: boolean
|
|
9
|
+
/** Callback when open state changes */
|
|
10
|
+
onOpenChange?: (open: boolean) => void
|
|
11
|
+
/** Whether the dialog is modal (default: true) */
|
|
12
|
+
modal?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DialogState {
|
|
16
|
+
open: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DialogAPI {
|
|
20
|
+
/** Current dialog state */
|
|
21
|
+
state: DialogState
|
|
22
|
+
/** ARIA attributes for the trigger button */
|
|
23
|
+
triggerProps: Partial<AccessibilityProps> & Record<string, unknown>
|
|
24
|
+
/** ARIA attributes for the dialog content */
|
|
25
|
+
contentProps: Partial<AccessibilityProps> & Record<string, unknown>
|
|
26
|
+
/** Data attributes for the overlay */
|
|
27
|
+
overlayProps: Record<string, string>
|
|
28
|
+
/** Open the dialog */
|
|
29
|
+
open(): void
|
|
30
|
+
/** Close the dialog */
|
|
31
|
+
close(): void
|
|
32
|
+
/** Toggle the dialog */
|
|
33
|
+
toggle(): void
|
|
34
|
+
/** Keyboard handlers (Escape to close) */
|
|
35
|
+
keyboardHandlers: KeyboardHandlerMap
|
|
36
|
+
/** Generated IDs for aria linking */
|
|
37
|
+
ids: {
|
|
38
|
+
content: string
|
|
39
|
+
title: string
|
|
40
|
+
description: string
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Focus trap configuration for framework wrappers.
|
|
44
|
+
* Pass this to createFocusTrap() with a container element.
|
|
45
|
+
*/
|
|
46
|
+
focusTrapConfig: Omit<FocusTrapConfig, 'container'>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function createDialog(props: DialogProps = {}): DialogAPI {
|
|
50
|
+
const { open: controlledOpen, defaultOpen = false, onOpenChange, modal = true } = props
|
|
51
|
+
|
|
52
|
+
const machine = createMachine<'open' | 'closed', 'OPEN' | 'CLOSE'>({
|
|
53
|
+
initial: controlledOpen ?? defaultOpen ? 'open' : 'closed',
|
|
54
|
+
states: {
|
|
55
|
+
closed: { on: { OPEN: 'open' } },
|
|
56
|
+
open: { on: { CLOSE: 'closed' } },
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const contentId = generateId('rfr-dialog')
|
|
61
|
+
const titleId = generateId('rfr-dialog-title')
|
|
62
|
+
const descriptionId = generateId('rfr-dialog-desc')
|
|
63
|
+
|
|
64
|
+
function isOpen(): boolean {
|
|
65
|
+
if (controlledOpen !== undefined) return controlledOpen
|
|
66
|
+
return machine.matches('open')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function openDialog(): void {
|
|
70
|
+
machine.send('OPEN')
|
|
71
|
+
onOpenChange?.(true)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function closeDialog(): void {
|
|
75
|
+
machine.send('CLOSE')
|
|
76
|
+
onOpenChange?.(false)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function toggleDialog(): void {
|
|
80
|
+
if (isOpen()) {
|
|
81
|
+
closeDialog()
|
|
82
|
+
} else {
|
|
83
|
+
openDialog()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const keyboardHandlers: KeyboardHandlerMap = {
|
|
88
|
+
[Keys.Escape]: (e) => {
|
|
89
|
+
e.preventDefault()
|
|
90
|
+
closeDialog()
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const triggerProps: Partial<AccessibilityProps> & Record<string, unknown> = {
|
|
95
|
+
'aria-expanded': isOpen(),
|
|
96
|
+
'aria-controls': contentId,
|
|
97
|
+
'aria-haspopup': 'dialog',
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const contentProps: Partial<AccessibilityProps> & Record<string, unknown> = {
|
|
101
|
+
role: 'dialog',
|
|
102
|
+
'aria-modal': modal,
|
|
103
|
+
'aria-labelledby': titleId,
|
|
104
|
+
'aria-describedby': descriptionId,
|
|
105
|
+
id: contentId,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const overlayProps: Record<string, string> = {
|
|
109
|
+
'data-state': isOpen() ? 'open' : 'closed',
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const focusTrapConfig: Omit<FocusTrapConfig, 'container'> = {
|
|
113
|
+
onEscape: closeDialog,
|
|
114
|
+
returnFocusOnDeactivate: true,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
state: { open: isOpen() },
|
|
119
|
+
triggerProps,
|
|
120
|
+
contentProps,
|
|
121
|
+
overlayProps,
|
|
122
|
+
open: openDialog,
|
|
123
|
+
close: closeDialog,
|
|
124
|
+
toggle: toggleDialog,
|
|
125
|
+
keyboardHandlers,
|
|
126
|
+
ids: {
|
|
127
|
+
content: contentId,
|
|
128
|
+
title: titleId,
|
|
129
|
+
description: descriptionId,
|
|
130
|
+
},
|
|
131
|
+
focusTrapConfig,
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { cva } from '../shared/index.ts'
|
|
2
|
+
import type { TokenContract } from '../shared/index.ts'
|
|
3
|
+
|
|
4
|
+
export const diffViewerTokens: TokenContract = {
|
|
5
|
+
name: 'diff-viewer',
|
|
6
|
+
tokens: {
|
|
7
|
+
bg: { variable: '--rfr-diff-bg', fallback: 'hsl(var(--background))' },
|
|
8
|
+
fg: { variable: '--rfr-diff-fg', fallback: 'hsl(var(--foreground))' },
|
|
9
|
+
sidebarBg: { variable: '--rfr-diff-sidebar-bg', fallback: 'hsl(var(--muted))' },
|
|
10
|
+
headerBg: { variable: '--rfr-diff-header-bg', fallback: 'hsl(var(--muted))' },
|
|
11
|
+
border: { variable: '--rfr-diff-border', fallback: 'hsl(var(--border))' },
|
|
12
|
+
addBg: { variable: '--rfr-diff-add-bg', fallback: 'rgba(46, 160, 67, 0.15)' },
|
|
13
|
+
delBg: { variable: '--rfr-diff-del-bg', fallback: 'rgba(248, 81, 73, 0.15)' },
|
|
14
|
+
addFg: { variable: '--rfr-diff-add-fg', fallback: '#3fb950' },
|
|
15
|
+
delFg: { variable: '--rfr-diff-del-fg', fallback: '#f85149' },
|
|
16
|
+
statusbar: { variable: '--rfr-diff-statusbar', fallback: 'hsl(var(--primary))' },
|
|
17
|
+
statusbarFg: { variable: '--rfr-diff-statusbar-fg', fallback: 'hsl(var(--primary-foreground))' },
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const diffViewerVariants = cva({
|
|
22
|
+
base: 'flex flex-col overflow-hidden font-sans text-sm',
|
|
23
|
+
variants: {
|
|
24
|
+
theme: {
|
|
25
|
+
light: 'bg-white text-gray-900',
|
|
26
|
+
dark: 'bg-gray-950 text-gray-100',
|
|
27
|
+
},
|
|
28
|
+
fullscreen: {
|
|
29
|
+
'true': 'h-screen',
|
|
30
|
+
'false': '',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
defaultVariants: {
|
|
34
|
+
theme: 'dark',
|
|
35
|
+
fullscreen: 'true',
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
export const sidebarVariants = cva({
|
|
40
|
+
base: 'border-r overflow-auto flex-shrink-0',
|
|
41
|
+
variants: {
|
|
42
|
+
theme: {
|
|
43
|
+
light: 'bg-gray-50 border-gray-200',
|
|
44
|
+
dark: 'bg-gray-900 border-gray-800',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
defaultVariants: {
|
|
48
|
+
theme: 'dark',
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
export const sidebarItemVariants = cva({
|
|
53
|
+
base: 'px-2.5 py-1 cursor-pointer text-xs font-mono transition-colors',
|
|
54
|
+
variants: {
|
|
55
|
+
active: {
|
|
56
|
+
'true': 'border-l-2 border-blue-500',
|
|
57
|
+
'false': 'border-l-2 border-transparent',
|
|
58
|
+
},
|
|
59
|
+
theme: {
|
|
60
|
+
light: '',
|
|
61
|
+
dark: '',
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
compoundVariants: [
|
|
65
|
+
{ active: 'true', theme: 'dark', class: 'bg-gray-800 text-gray-100' },
|
|
66
|
+
{ active: 'false', theme: 'dark', class: 'text-gray-400 hover:bg-gray-800/50' },
|
|
67
|
+
{ active: 'true', theme: 'light', class: 'bg-blue-50 text-gray-900' },
|
|
68
|
+
{ active: 'false', theme: 'light', class: 'text-gray-600 hover:bg-gray-100' },
|
|
69
|
+
],
|
|
70
|
+
defaultVariants: {
|
|
71
|
+
active: 'false',
|
|
72
|
+
theme: 'dark',
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
export const tabBarVariants = cva({
|
|
77
|
+
base: 'flex items-center border-b overflow-auto flex-shrink-0',
|
|
78
|
+
variants: {
|
|
79
|
+
theme: {
|
|
80
|
+
light: 'bg-gray-50 border-gray-200',
|
|
81
|
+
dark: 'bg-gray-900 border-gray-800',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
defaultVariants: {
|
|
85
|
+
theme: 'dark',
|
|
86
|
+
},
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
export const tabVariants = cva({
|
|
90
|
+
base: 'px-3 h-[35px] flex items-center gap-1 cursor-pointer text-xs font-mono border-r shrink-0',
|
|
91
|
+
variants: {
|
|
92
|
+
active: {
|
|
93
|
+
'true': '',
|
|
94
|
+
'false': '',
|
|
95
|
+
},
|
|
96
|
+
theme: {
|
|
97
|
+
light: 'border-gray-200',
|
|
98
|
+
dark: 'border-gray-800',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
compoundVariants: [
|
|
102
|
+
{ active: 'true', theme: 'dark', class: 'bg-gray-950 text-gray-100 border-b-gray-950 -mb-px' },
|
|
103
|
+
{ active: 'false', theme: 'dark', class: 'text-gray-400' },
|
|
104
|
+
{ active: 'true', theme: 'light', class: 'bg-white text-gray-900 border-b-white -mb-px' },
|
|
105
|
+
{ active: 'false', theme: 'light', class: 'text-gray-500' },
|
|
106
|
+
],
|
|
107
|
+
defaultVariants: {
|
|
108
|
+
active: 'false',
|
|
109
|
+
theme: 'dark',
|
|
110
|
+
},
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
export const statusBarVariants = cva({
|
|
114
|
+
base: 'h-[22px] flex items-center px-2.5 gap-3 text-[11px] font-mono flex-shrink-0',
|
|
115
|
+
variants: {
|
|
116
|
+
theme: {
|
|
117
|
+
light: 'bg-blue-600 text-white',
|
|
118
|
+
dark: 'bg-blue-700 text-white',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
defaultVariants: {
|
|
122
|
+
theme: 'dark',
|
|
123
|
+
},
|
|
124
|
+
})
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import type { AccessibilityProps } from '../shared/index.ts'
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Types
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
export type DiffViewerTheme = 'light' | 'dark'
|
|
8
|
+
export type DiffViewMode = 'side-by-side' | 'inline'
|
|
9
|
+
|
|
10
|
+
export type DiffFileStatus = 'added' | 'modified' | 'deleted' | 'renamed'
|
|
11
|
+
|
|
12
|
+
export interface DiffFile {
|
|
13
|
+
/** File path */
|
|
14
|
+
path: string
|
|
15
|
+
/** Change status */
|
|
16
|
+
status: DiffFileStatus
|
|
17
|
+
/** Lines added */
|
|
18
|
+
additions: number
|
|
19
|
+
/** Lines deleted */
|
|
20
|
+
deletions: number
|
|
21
|
+
/** Unified diff content for this file */
|
|
22
|
+
diff?: string
|
|
23
|
+
/** Old path for renamed files */
|
|
24
|
+
oldPath?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface DiffViewerProps {
|
|
28
|
+
/** Files in this diff */
|
|
29
|
+
files?: DiffFile[]
|
|
30
|
+
/** Index of the active file */
|
|
31
|
+
activeFileIndex?: number
|
|
32
|
+
/** View mode */
|
|
33
|
+
viewMode?: DiffViewMode
|
|
34
|
+
/** Theme */
|
|
35
|
+
theme?: DiffViewerTheme
|
|
36
|
+
/** Language for syntax highlighting */
|
|
37
|
+
language?: string
|
|
38
|
+
/** Whether the sidebar is visible */
|
|
39
|
+
sidebarOpen?: boolean
|
|
40
|
+
/** Callback when active file changes */
|
|
41
|
+
onFileSelect?: (index: number) => void
|
|
42
|
+
/** Callback when view mode changes */
|
|
43
|
+
onViewModeChange?: (mode: DiffViewMode) => void
|
|
44
|
+
/** Callback when sidebar toggled */
|
|
45
|
+
onSidebarToggle?: () => void
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface DiffViewerState {
|
|
49
|
+
activeFileIndex: number
|
|
50
|
+
viewMode: DiffViewMode
|
|
51
|
+
theme: DiffViewerTheme
|
|
52
|
+
language: string
|
|
53
|
+
sidebarOpen: boolean
|
|
54
|
+
files: DiffFile[]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface DiffViewerAPI {
|
|
58
|
+
/** Current viewer state */
|
|
59
|
+
state: DiffViewerState
|
|
60
|
+
/** ARIA attributes for the root element */
|
|
61
|
+
ariaProps: Partial<AccessibilityProps> & Record<string, unknown>
|
|
62
|
+
/** Data attributes for CSS styling hooks */
|
|
63
|
+
dataAttributes: Record<string, string>
|
|
64
|
+
/** Select a file by index */
|
|
65
|
+
selectFile: (index: number) => void
|
|
66
|
+
/** Move to next file */
|
|
67
|
+
nextFile: () => void
|
|
68
|
+
/** Move to previous file */
|
|
69
|
+
prevFile: () => void
|
|
70
|
+
/** Toggle view mode */
|
|
71
|
+
toggleViewMode: () => void
|
|
72
|
+
/** Toggle sidebar */
|
|
73
|
+
toggleSidebar: () => void
|
|
74
|
+
/** Get language label for a file path */
|
|
75
|
+
getLanguageForFile: (path: string) => string
|
|
76
|
+
/** Get human-readable file status icon */
|
|
77
|
+
getFileStatusIcon: (status: DiffFileStatus) => string
|
|
78
|
+
/** Get total additions across all files */
|
|
79
|
+
totalAdditions: () => number
|
|
80
|
+
/** Get total deletions across all files */
|
|
81
|
+
totalDeletions: () => number
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Language detection
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
const extToLanguage: Record<string, string> = {
|
|
89
|
+
ts: 'typescript',
|
|
90
|
+
tsx: 'typescript',
|
|
91
|
+
js: 'javascript',
|
|
92
|
+
jsx: 'javascript',
|
|
93
|
+
py: 'python',
|
|
94
|
+
go: 'go',
|
|
95
|
+
rs: 'rust',
|
|
96
|
+
rb: 'ruby',
|
|
97
|
+
java: 'java',
|
|
98
|
+
swift: 'swift',
|
|
99
|
+
kt: 'kotlin',
|
|
100
|
+
dart: 'dart',
|
|
101
|
+
php: 'php',
|
|
102
|
+
lua: 'lua',
|
|
103
|
+
r: 'r',
|
|
104
|
+
scala: 'scala',
|
|
105
|
+
json: 'json',
|
|
106
|
+
yaml: 'yaml',
|
|
107
|
+
yml: 'yaml',
|
|
108
|
+
md: 'markdown',
|
|
109
|
+
html: 'html',
|
|
110
|
+
css: 'css',
|
|
111
|
+
scss: 'scss',
|
|
112
|
+
sql: 'sql',
|
|
113
|
+
sh: 'shell',
|
|
114
|
+
bash: 'shell',
|
|
115
|
+
zsh: 'shell',
|
|
116
|
+
xml: 'xml',
|
|
117
|
+
toml: 'toml',
|
|
118
|
+
proto: 'protobuf',
|
|
119
|
+
dockerfile: 'dockerfile',
|
|
120
|
+
cpp: 'cpp',
|
|
121
|
+
c: 'c',
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getLanguageForFile(filePath: string): string {
|
|
125
|
+
const ext = filePath.split('.').pop()?.toLowerCase() || ''
|
|
126
|
+
const basename = filePath.split('/').pop()?.toLowerCase() || ''
|
|
127
|
+
if (basename === 'dockerfile') return 'dockerfile'
|
|
128
|
+
return extToLanguage[ext] || 'plaintext'
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Status icons
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
const statusIcons: Record<DiffFileStatus, string> = {
|
|
136
|
+
added: '\u{1F7E2}', // green circle
|
|
137
|
+
modified: '\u{1F7E1}', // yellow circle
|
|
138
|
+
deleted: '\u{1F534}', // red circle
|
|
139
|
+
renamed: '\u{1F535}', // blue circle
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// Factory
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Create a headless diff viewer API.
|
|
148
|
+
*
|
|
149
|
+
* Manages file selection, view mode, sidebar state, and produces ARIA/data
|
|
150
|
+
* attributes. The actual rendering (Monaco DiffEditor, custom renderer, etc.)
|
|
151
|
+
* is handled by framework-specific wrappers.
|
|
152
|
+
*/
|
|
153
|
+
export function createDiffViewer(props: DiffViewerProps = {}): DiffViewerAPI {
|
|
154
|
+
const {
|
|
155
|
+
files = [],
|
|
156
|
+
activeFileIndex = 0,
|
|
157
|
+
viewMode = 'side-by-side',
|
|
158
|
+
theme = 'dark',
|
|
159
|
+
language,
|
|
160
|
+
sidebarOpen = true,
|
|
161
|
+
onFileSelect,
|
|
162
|
+
onViewModeChange,
|
|
163
|
+
onSidebarToggle,
|
|
164
|
+
} = props
|
|
165
|
+
|
|
166
|
+
let currentIndex = Math.min(activeFileIndex, Math.max(0, files.length - 1))
|
|
167
|
+
let currentViewMode = viewMode
|
|
168
|
+
let currentSidebarOpen = sidebarOpen
|
|
169
|
+
|
|
170
|
+
const state: DiffViewerState = {
|
|
171
|
+
activeFileIndex: currentIndex,
|
|
172
|
+
viewMode: currentViewMode,
|
|
173
|
+
theme,
|
|
174
|
+
language: language || (files[currentIndex] ? getLanguageForFile(files[currentIndex].path) : 'plaintext'),
|
|
175
|
+
sidebarOpen: currentSidebarOpen,
|
|
176
|
+
files,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const ariaProps: Partial<AccessibilityProps> & Record<string, unknown> = {
|
|
180
|
+
role: 'region',
|
|
181
|
+
'aria-label': 'Diff viewer',
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const dataAttributes: Record<string, string> = {
|
|
185
|
+
'data-view-mode': currentViewMode,
|
|
186
|
+
'data-theme': theme,
|
|
187
|
+
'data-file-count': String(files.length),
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (!currentSidebarOpen) {
|
|
191
|
+
dataAttributes['data-sidebar-collapsed'] = ''
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function selectFile(index: number) {
|
|
195
|
+
if (index >= 0 && index < files.length) {
|
|
196
|
+
currentIndex = index
|
|
197
|
+
state.activeFileIndex = index
|
|
198
|
+
state.language = language || getLanguageForFile(files[index].path)
|
|
199
|
+
onFileSelect?.(index)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function nextFile() {
|
|
204
|
+
if (currentIndex < files.length - 1) {
|
|
205
|
+
selectFile(currentIndex + 1)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function prevFile() {
|
|
210
|
+
if (currentIndex > 0) {
|
|
211
|
+
selectFile(currentIndex - 1)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function toggleViewMode() {
|
|
216
|
+
currentViewMode = currentViewMode === 'side-by-side' ? 'inline' : 'side-by-side'
|
|
217
|
+
state.viewMode = currentViewMode
|
|
218
|
+
dataAttributes['data-view-mode'] = currentViewMode
|
|
219
|
+
onViewModeChange?.(currentViewMode)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function toggleSidebar() {
|
|
223
|
+
currentSidebarOpen = !currentSidebarOpen
|
|
224
|
+
state.sidebarOpen = currentSidebarOpen
|
|
225
|
+
if (currentSidebarOpen) {
|
|
226
|
+
delete dataAttributes['data-sidebar-collapsed']
|
|
227
|
+
} else {
|
|
228
|
+
dataAttributes['data-sidebar-collapsed'] = ''
|
|
229
|
+
}
|
|
230
|
+
onSidebarToggle?.()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function totalAdditions(): number {
|
|
234
|
+
return files.reduce((sum, f) => sum + f.additions, 0)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function totalDeletions(): number {
|
|
238
|
+
return files.reduce((sum, f) => sum + f.deletions, 0)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
state,
|
|
243
|
+
ariaProps,
|
|
244
|
+
dataAttributes,
|
|
245
|
+
selectFile,
|
|
246
|
+
nextFile,
|
|
247
|
+
prevFile,
|
|
248
|
+
toggleViewMode,
|
|
249
|
+
toggleSidebar,
|
|
250
|
+
getLanguageForFile,
|
|
251
|
+
getFileStatusIcon: (status: DiffFileStatus) => statusIcons[status] || '\u{26AA}',
|
|
252
|
+
totalAdditions,
|
|
253
|
+
totalDeletions,
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export {
|
|
2
|
+
createDiffViewer,
|
|
3
|
+
type DiffViewerProps,
|
|
4
|
+
type DiffViewerAPI,
|
|
5
|
+
type DiffViewerState,
|
|
6
|
+
type DiffViewerTheme,
|
|
7
|
+
type DiffViewMode,
|
|
8
|
+
type DiffFile,
|
|
9
|
+
type DiffFileStatus,
|
|
10
|
+
} from './diff-viewer.js'
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
diffViewerTokens,
|
|
14
|
+
diffViewerVariants,
|
|
15
|
+
sidebarVariants,
|
|
16
|
+
sidebarItemVariants,
|
|
17
|
+
tabBarVariants,
|
|
18
|
+
tabVariants,
|
|
19
|
+
statusBarVariants,
|
|
20
|
+
} from './diff-viewer.styles.js'
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { cva } from '../shared/index.ts'
|
|
2
|
+
|
|
3
|
+
export const menuContentVariants = cva({
|
|
4
|
+
base: 'z-50 rounded-md border bg-popover shadow-md',
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
export const menuItemVariants = cva({
|
|
8
|
+
base: 'relative flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
9
|
+
})
|