@refraction-ui/astro 0.3.1 → 0.4.2
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/astro-accordion/Button.astro +55 -0
- package/dist/astro-accordion/index.ts +1 -0
- package/dist/astro-ai/AIScript.astro +69 -0
- package/dist/astro-ai/TTSScript.astro +60 -0
- package/dist/astro-ai/index.ts +16 -0
- package/dist/astro-animated-text/AnimatedText.astro +81 -0
- package/dist/astro-animated-text/TypewriterText.astro +90 -0
- package/dist/astro-animated-text/index.ts +1 -0
- package/dist/astro-app-shell/AppShell.astro +195 -0
- package/dist/astro-app-shell/AppShellContent.astro +29 -0
- package/dist/astro-app-shell/AppShellHeader.astro +54 -0
- package/dist/astro-app-shell/AppShellMain.astro +18 -0
- package/dist/astro-app-shell/AppShellMobileNav.astro +27 -0
- package/dist/astro-app-shell/AppShellOverlay.astro +21 -0
- package/dist/astro-app-shell/AppShellSidebar.astro +26 -0
- package/dist/astro-app-shell/AuthShell.astro +31 -0
- package/dist/astro-app-shell/AuthShellCard.astro +24 -0
- package/dist/astro-app-shell/PageShell.astro +36 -0
- package/dist/astro-app-shell/PageShellFooter.astro +30 -0
- package/dist/astro-app-shell/PageShellNav.astro +33 -0
- package/dist/astro-app-shell/PageShellSection.astro +32 -0
- package/dist/astro-app-shell/index.ts +21 -0
- package/dist/astro-auth/AuthGuard.astro +133 -0
- package/dist/astro-auth/index.ts +5 -0
- package/dist/astro-avatar/Avatar.astro +22 -0
- package/dist/astro-avatar/AvatarFallback.astro +18 -0
- package/dist/astro-avatar/AvatarImage.astro +48 -0
- package/dist/astro-avatar/index.ts +1 -0
- package/dist/astro-avatar-group/AvatarGroup.astro +42 -0
- package/dist/astro-avatar-group/index.ts +1 -0
- package/dist/astro-badge/Badge.astro +27 -0
- package/dist/astro-badge/index.ts +1 -0
- package/dist/astro-bottom-nav/BottomNav.astro +40 -0
- package/dist/astro-bottom-nav/index.ts +1 -0
- package/dist/astro-breadcrumbs/Breadcrumbs.astro +56 -0
- package/dist/astro-breadcrumbs/index.ts +1 -0
- package/dist/astro-button/Button.astro +55 -0
- package/dist/astro-button/index.ts +1 -0
- package/dist/astro-calendar/Calendar.astro +259 -0
- package/dist/astro-calendar/index.ts +1 -0
- package/dist/astro-callout/Callout.astro +3 -0
- package/dist/astro-callout/index.ts +1 -0
- package/dist/astro-card/Card.astro +20 -0
- package/dist/astro-card/CardContent.astro +13 -0
- package/dist/astro-card/CardDescription.astro +13 -0
- package/dist/astro-card/CardFooter.astro +13 -0
- package/dist/astro-card/CardHeader.astro +13 -0
- package/dist/astro-card/CardTitle.astro +15 -0
- package/dist/astro-card/index.ts +1 -0
- package/dist/astro-card-grid/CardGrid.astro +17 -0
- package/dist/astro-card-grid/index.ts +1 -0
- package/dist/astro-carousel/Button.astro +55 -0
- package/dist/astro-carousel/index.ts +1 -0
- package/dist/astro-charts/Bars.astro +53 -0
- package/dist/astro-charts/Chart.astro +31 -0
- package/dist/astro-charts/Circles.astro +48 -0
- package/dist/astro-charts/Gradient.astro +34 -0
- package/dist/astro-charts/Histogram.astro +107 -0
- package/dist/astro-charts/Line.astro +55 -0
- package/dist/astro-charts/PieChart.astro +63 -0
- package/dist/astro-charts/ScatterPlot.astro +95 -0
- package/dist/astro-charts/XAxis.astro +46 -0
- package/dist/astro-charts/YAxis.astro +44 -0
- package/dist/astro-charts/index.ts +26 -0
- package/dist/astro-checkbox/Checkbox.astro +129 -0
- package/dist/astro-checkbox/index.ts +1 -0
- package/dist/astro-code-block/CodeBlock.astro +3 -0
- package/dist/astro-code-block/index.ts +1 -0
- package/dist/astro-code-editor/CodeEditor.astro +123 -0
- package/dist/astro-code-editor/index.ts +1 -0
- package/dist/astro-collapsible/Collapsible.astro +58 -0
- package/dist/astro-collapsible/CollapsibleContent.astro +21 -0
- package/dist/astro-collapsible/CollapsibleTrigger.astro +17 -0
- package/dist/astro-collapsible/index.ts +1 -0
- package/dist/astro-command/Command.astro +170 -0
- package/dist/astro-command/CommandEmpty.astro +17 -0
- package/dist/astro-command/CommandGroup.astro +25 -0
- package/dist/astro-command/CommandInput.astro +21 -0
- package/dist/astro-command/CommandItem.astro +26 -0
- package/dist/astro-command/CommandList.astro +17 -0
- package/dist/astro-command/CommandSeparator.astro +14 -0
- package/dist/astro-command/index.ts +1 -0
- package/dist/astro-command-input/CommandInput.astro +6 -0
- package/dist/astro-command-input/index.ts +1 -0
- package/dist/astro-content-protection/ContentProtection.astro +104 -0
- package/dist/astro-content-protection/index.ts +1 -0
- package/dist/astro-data-table/DataTable.astro +263 -0
- package/dist/astro-data-table/index.ts +1 -0
- package/dist/astro-date-picker/DatePicker.astro +398 -0
- package/dist/astro-date-picker/index.ts +1 -0
- package/dist/astro-device-frame/DeviceFrame.astro +44 -0
- package/dist/astro-device-frame/index.ts +1 -0
- package/dist/astro-dialog/Dialog.astro +138 -0
- package/dist/astro-dialog/DialogClose.astro +16 -0
- package/dist/astro-dialog/DialogContent.astro +24 -0
- package/dist/astro-dialog/DialogDescription.astro +15 -0
- package/dist/astro-dialog/DialogFooter.astro +14 -0
- package/dist/astro-dialog/DialogHeader.astro +14 -0
- package/dist/astro-dialog/DialogOverlay.astro +17 -0
- package/dist/astro-dialog/DialogTitle.astro +15 -0
- package/dist/astro-dialog/DialogTrigger.astro +18 -0
- package/dist/astro-dialog/index.ts +1 -0
- package/dist/astro-diff-viewer/DiffViewer.astro +371 -0
- package/dist/astro-diff-viewer/index.ts +1 -0
- package/dist/astro-dropdown-menu/DropdownMenu.astro +138 -0
- package/dist/astro-dropdown-menu/DropdownMenuContent.astro +20 -0
- package/dist/astro-dropdown-menu/DropdownMenuItem.astro +21 -0
- package/dist/astro-dropdown-menu/DropdownMenuLabel.astro +14 -0
- package/dist/astro-dropdown-menu/DropdownMenuSeparator.astro +14 -0
- package/dist/astro-dropdown-menu/DropdownMenuTrigger.astro +18 -0
- package/dist/astro-dropdown-menu/index.ts +1 -0
- package/dist/astro-emoji-picker/EmojiPicker.astro +255 -0
- package/dist/astro-emoji-picker/index.ts +1 -0
- package/dist/astro-feedback-dialog/FeedbackDialog.astro +152 -0
- package/dist/astro-feedback-dialog/index.ts +1 -0
- package/dist/astro-file-tree/astro-file-tree.astro +4 -0
- package/dist/astro-file-tree/index.ts +1 -0
- package/dist/astro-file-upload/FileUpload.astro +306 -0
- package/dist/astro-file-upload/index.ts +1 -0
- package/dist/astro-footer/Footer.astro +61 -0
- package/dist/astro-footer/index.ts +1 -0
- package/dist/astro-icon-system/astro-icon-system.astro +4 -0
- package/dist/astro-icon-system/index.ts +1 -0
- package/dist/astro-inline-editor/InlineEditor.astro +169 -0
- package/dist/astro-inline-editor/index.ts +1 -0
- package/dist/astro-input/Input.astro +49 -0
- package/dist/astro-input/index.ts +1 -0
- package/dist/astro-input-group/InputGroup.astro +29 -0
- package/dist/astro-input-group/InputGroupAddon.astro +14 -0
- package/dist/astro-input-group/InputGroupButton.astro +19 -0
- package/dist/astro-input-group/InputGroupText.astro +11 -0
- package/dist/astro-input-group/index.ts +1 -0
- package/dist/astro-install-prompt/InstallPrompt.astro +115 -0
- package/dist/astro-install-prompt/index.ts +1 -0
- package/dist/astro-keyboard-shortcut/KeyboardShortcut.astro +83 -0
- package/dist/astro-keyboard-shortcut/ShortcutBadge.astro +41 -0
- package/dist/astro-keyboard-shortcut/index.ts +1 -0
- package/dist/astro-language-selector/LanguageSelector.astro +247 -0
- package/dist/astro-language-selector/index.ts +1 -0
- package/dist/astro-link-card/LinkCard.astro +17 -0
- package/dist/astro-link-card/index.ts +1 -0
- package/dist/astro-markdown-renderer/MarkdownRenderer.astro +62 -0
- package/dist/astro-markdown-renderer/index.ts +1 -0
- package/dist/astro-mobile-nav/MobileNav.astro +84 -0
- package/dist/astro-mobile-nav/MobileNavContent.astro +29 -0
- package/dist/astro-mobile-nav/MobileNavLink.astro +16 -0
- package/dist/astro-mobile-nav/MobileNavTrigger.astro +57 -0
- package/dist/astro-mobile-nav/index.ts +1 -0
- package/dist/astro-navbar/Navbar.astro +49 -0
- package/dist/astro-navbar/index.ts +1 -0
- package/dist/astro-otp-input/OtpInput.astro +253 -0
- package/dist/astro-otp-input/index.ts +1 -0
- package/dist/astro-pagination/Pagination.astro +3 -0
- package/dist/astro-pagination/index.ts +1 -0
- package/dist/astro-payment/Payment.astro +19 -0
- package/dist/astro-payment/index.ts +1 -0
- package/dist/astro-popover/Popover.astro +87 -0
- package/dist/astro-popover/PopoverClose.astro +16 -0
- package/dist/astro-popover/PopoverContent.astro +23 -0
- package/dist/astro-popover/PopoverTrigger.astro +18 -0
- package/dist/astro-popover/index.ts +1 -0
- package/dist/astro-presence-indicator/PresenceIndicator.astro +26 -0
- package/dist/astro-presence-indicator/index.ts +1 -0
- package/dist/astro-progress-display/BadgeDisplay.astro +33 -0
- package/dist/astro-progress-display/ProgressBar.astro +27 -0
- package/dist/astro-progress-display/StatsGrid.astro +32 -0
- package/dist/astro-progress-display/index.ts +1 -0
- package/dist/astro-radio/RadioGroup.astro +111 -0
- package/dist/astro-radio/RadioItem.astro +36 -0
- package/dist/astro-radio/index.ts +1 -0
- package/dist/astro-reaction-bar/ReactionBar.astro +117 -0
- package/dist/astro-reaction-bar/index.ts +1 -0
- package/dist/astro-resizable-layout/ResizableDivider.astro +27 -0
- package/dist/astro-resizable-layout/ResizableLayout.astro +162 -0
- package/dist/astro-resizable-layout/ResizablePane.astro +28 -0
- package/dist/astro-resizable-layout/index.ts +11 -0
- package/dist/astro-rich-editor/RichEditor.astro +260 -0
- package/dist/astro-rich-editor/index.ts +25 -0
- package/dist/astro-search-bar/SearchBar.astro +140 -0
- package/dist/astro-search-bar/SearchResultItem.astro +16 -0
- package/dist/astro-search-bar/SearchResults.astro +17 -0
- package/dist/astro-search-bar/index.ts +1 -0
- package/dist/astro-select/Select.astro +165 -0
- package/dist/astro-select/SelectContent.astro +19 -0
- package/dist/astro-select/SelectItem.astro +42 -0
- package/dist/astro-select/SelectTrigger.astro +36 -0
- package/dist/astro-select/index.ts +1 -0
- package/dist/astro-sidebar/Sidebar.astro +64 -0
- package/dist/astro-sidebar/index.ts +1 -0
- package/dist/astro-skeleton/Skeleton.astro +39 -0
- package/dist/astro-skeleton/SkeletonText.astro +22 -0
- package/dist/astro-skeleton/index.ts +1 -0
- package/dist/astro-skip-to-content/SkipToContent.astro +3 -0
- package/dist/astro-skip-to-content/index.ts +1 -0
- package/dist/astro-slide-viewer/SlideViewer.astro +231 -0
- package/dist/astro-slide-viewer/index.ts +1 -0
- package/dist/astro-slider/index.ts +1 -0
- package/dist/astro-status-indicator/StatusIndicator.astro +31 -0
- package/dist/astro-status-indicator/index.ts +1 -0
- package/dist/astro-steps/Steps.astro +3 -0
- package/dist/astro-steps/index.ts +1 -0
- package/dist/astro-switch/Switch.astro +89 -0
- package/dist/astro-switch/index.ts +1 -0
- package/dist/astro-table-of-contents/TableOfContents.astro +53 -0
- package/dist/astro-table-of-contents/index.ts +1 -0
- package/dist/astro-tabs/Tabs.astro +96 -0
- package/dist/astro-tabs/TabsContent.astro +20 -0
- package/dist/astro-tabs/TabsList.astro +16 -0
- package/dist/astro-tabs/TabsTrigger.astro +24 -0
- package/dist/astro-tabs/index.ts +1 -0
- package/dist/astro-textarea/Textarea.astro +51 -0
- package/dist/astro-textarea/index.ts +1 -0
- package/dist/astro-theme/ThemeScript.astro +13 -0
- package/dist/astro-theme/ThemeToggle.astro +279 -0
- package/dist/astro-theme/index.ts +1 -0
- package/dist/astro-thread-view/ThreadView.astro +159 -0
- package/dist/astro-thread-view/index.ts +1 -0
- package/dist/astro-toast/Toast.astro +49 -0
- package/dist/astro-toast/Toaster.astro +142 -0
- package/dist/astro-toast/index.ts +1 -0
- package/dist/astro-tooltip/Tooltip.astro +95 -0
- package/dist/astro-tooltip/TooltipContent.astro +22 -0
- package/dist/astro-tooltip/TooltipTrigger.astro +16 -0
- package/dist/astro-tooltip/index.ts +1 -0
- package/dist/astro-version-selector/VersionSelector.astro +174 -0
- package/dist/astro-version-selector/index.ts +1 -0
- package/dist/astro-video-player/VideoPlayer.astro +153 -0
- package/dist/astro-video-player/index.ts +1 -0
- package/dist/index.ts +77 -0
- package/dist/shared/a11y.ts +33 -0
- package/dist/shared/aria.ts +30 -0
- package/dist/shared/cn.ts +35 -0
- package/dist/shared/cva.ts +79 -0
- package/dist/shared/engine-adapter.ts +10 -0
- package/dist/shared/focus-trap.ts +123 -0
- package/dist/shared/index.ts +60 -0
- package/dist/shared/keyboard.ts +36 -0
- package/dist/shared/live-region.ts +90 -0
- package/dist/shared/motion.ts +15 -0
- package/dist/shared/skip-link.ts +35 -0
- package/dist/shared/state-machine.ts +57 -0
- package/dist/shared/tokens.ts +16 -0
- package/dist/shared/types.ts +45 -0
- package/dist/shared/variants.ts +17 -0
- package/package.json +22 -20
- package/src/index.ts +0 -92
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
createButton,
|
|
4
|
+
buttonVariants,
|
|
5
|
+
getButtonType,
|
|
6
|
+
type ButtonVariant,
|
|
7
|
+
type ButtonSize,
|
|
8
|
+
} from '@refraction-ui/button'
|
|
9
|
+
import { cn } from '../shared/index.ts'
|
|
10
|
+
|
|
11
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
12
|
+
variant?: ButtonVariant
|
|
13
|
+
size?: ButtonSize
|
|
14
|
+
loading?: boolean
|
|
15
|
+
disabled?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { variant, size, loading, disabled, class: className, ...props } = Astro.props
|
|
19
|
+
const api = createButton({ variant, size, disabled, loading, type: props.type as string })
|
|
20
|
+
const classes = cn(buttonVariants({ variant, size }), className)
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<button
|
|
24
|
+
type={getButtonType({ type: props.type as string }) as any}
|
|
25
|
+
class={classes}
|
|
26
|
+
disabled={disabled || loading}
|
|
27
|
+
{...api.ariaProps}
|
|
28
|
+
{...api.dataAttributes}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{loading && (
|
|
32
|
+
<svg
|
|
33
|
+
class="animate-spin h-4 w-4"
|
|
34
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
35
|
+
fill="none"
|
|
36
|
+
viewBox="0 0 24 24"
|
|
37
|
+
aria-hidden="true"
|
|
38
|
+
>
|
|
39
|
+
<circle
|
|
40
|
+
class="opacity-25"
|
|
41
|
+
cx="12"
|
|
42
|
+
cy="12"
|
|
43
|
+
r="10"
|
|
44
|
+
stroke="currentColor"
|
|
45
|
+
stroke-width="4"
|
|
46
|
+
/>
|
|
47
|
+
<path
|
|
48
|
+
class="opacity-75"
|
|
49
|
+
fill="currentColor"
|
|
50
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
51
|
+
/>
|
|
52
|
+
</svg>
|
|
53
|
+
)}
|
|
54
|
+
<slot />
|
|
55
|
+
</button>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* AIScript — injects a <script> that initializes the AI client on the page.
|
|
4
|
+
* Exposes `window.__rfr_ai` for other scripts to call generateText / generateJSON.
|
|
5
|
+
*
|
|
6
|
+
* Props mirror AIConfig from @refraction-ui/ai.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
10
|
+
/** Default provider name */
|
|
11
|
+
default?: string
|
|
12
|
+
/** Fallback chain of provider names */
|
|
13
|
+
fallback?: string[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { default: defaultProvider, fallback, ...props } = Astro.props
|
|
17
|
+
|
|
18
|
+
const configJSON = JSON.stringify({
|
|
19
|
+
default: defaultProvider,
|
|
20
|
+
fallback,
|
|
21
|
+
})
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<script
|
|
25
|
+
data-rfr-ai-config={configJSON}
|
|
26
|
+
{...props}
|
|
27
|
+
is:inline
|
|
28
|
+
>
|
|
29
|
+
;(function () {
|
|
30
|
+
// Only initialize once
|
|
31
|
+
if (window.__rfr_ai) return
|
|
32
|
+
|
|
33
|
+
// We cannot import ES modules from an inline script, so we stash the config
|
|
34
|
+
// and let the consumer call the init function from their own module script.
|
|
35
|
+
// This inline script sets up the namespace and a deferred init helper.
|
|
36
|
+
var configEl = document.querySelector('[data-rfr-ai-config]')
|
|
37
|
+
var config = {}
|
|
38
|
+
if (configEl) {
|
|
39
|
+
try { config = JSON.parse(configEl.getAttribute('data-rfr-ai-config') || '{}') } catch (_) { /* */ }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Placeholder that will be replaced once createAI is called
|
|
43
|
+
window.__rfr_ai = {
|
|
44
|
+
_config: config,
|
|
45
|
+
_api: null,
|
|
46
|
+
_ready: false,
|
|
47
|
+
init: function (createAI, providers) {
|
|
48
|
+
var api = createAI(config)
|
|
49
|
+
if (providers) {
|
|
50
|
+
Object.keys(providers).forEach(function (name) {
|
|
51
|
+
api.addProvider(name, providers[name])
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
window.__rfr_ai._api = api
|
|
55
|
+
window.__rfr_ai._ready = true
|
|
56
|
+
window.__rfr_ai.generateText = api.generateText.bind(api)
|
|
57
|
+
window.__rfr_ai.generateJSON = api.generateJSON.bind(api)
|
|
58
|
+
window.__rfr_ai.addProvider = api.addProvider.bind(api)
|
|
59
|
+
window.__rfr_ai.removeProvider = api.removeProvider.bind(api)
|
|
60
|
+
window.__rfr_ai.providers = api.providers
|
|
61
|
+
},
|
|
62
|
+
generateText: function () { throw new Error('AI not initialized. Call window.__rfr_ai.init(createAI, providers) first.') },
|
|
63
|
+
generateJSON: function () { throw new Error('AI not initialized. Call window.__rfr_ai.init(createAI, providers) first.') },
|
|
64
|
+
addProvider: function () { throw new Error('AI not initialized.') },
|
|
65
|
+
removeProvider: function () { throw new Error('AI not initialized.') },
|
|
66
|
+
providers: [],
|
|
67
|
+
}
|
|
68
|
+
})()
|
|
69
|
+
</script>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* TTSScript — injects a <script> that initializes TTS on the page.
|
|
4
|
+
* Exposes `window.__rfr_tts` for other scripts to call speak / stop.
|
|
5
|
+
*
|
|
6
|
+
* Props mirror TTSConfig from @refraction-ui/ai.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
10
|
+
/** Default TTS provider name */
|
|
11
|
+
default?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { default: defaultProvider, ...props } = Astro.props
|
|
15
|
+
|
|
16
|
+
const configJSON = JSON.stringify({
|
|
17
|
+
default: defaultProvider,
|
|
18
|
+
})
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<script
|
|
22
|
+
data-rfr-tts-config={configJSON}
|
|
23
|
+
{...props}
|
|
24
|
+
is:inline
|
|
25
|
+
>
|
|
26
|
+
;(function () {
|
|
27
|
+
if (window.__rfr_tts) return
|
|
28
|
+
|
|
29
|
+
var configEl = document.querySelector('[data-rfr-tts-config]')
|
|
30
|
+
var config = {}
|
|
31
|
+
if (configEl) {
|
|
32
|
+
try { config = JSON.parse(configEl.getAttribute('data-rfr-tts-config') || '{}') } catch (_) { /* */ }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
window.__rfr_tts = {
|
|
36
|
+
_config: config,
|
|
37
|
+
_api: null,
|
|
38
|
+
_ready: false,
|
|
39
|
+
init: function (createTTS, providers) {
|
|
40
|
+
var api = createTTS(config)
|
|
41
|
+
if (providers) {
|
|
42
|
+
Object.keys(providers).forEach(function (name) {
|
|
43
|
+
api.addProvider(name, providers[name])
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
window.__rfr_tts._api = api
|
|
47
|
+
window.__rfr_tts._ready = true
|
|
48
|
+
window.__rfr_tts.speak = api.speak.bind(api)
|
|
49
|
+
window.__rfr_tts.stop = api.stop.bind(api)
|
|
50
|
+
window.__rfr_tts.addProvider = api.addProvider.bind(api)
|
|
51
|
+
window.__rfr_tts.providers = api.providers
|
|
52
|
+
},
|
|
53
|
+
speak: function () { throw new Error('TTS not initialized. Call window.__rfr_tts.init(createTTS, providers) first.') },
|
|
54
|
+
stop: function () { throw new Error('TTS not initialized.') },
|
|
55
|
+
addProvider: function () { throw new Error('TTS not initialized.') },
|
|
56
|
+
providers: [],
|
|
57
|
+
isSpeaking: false,
|
|
58
|
+
}
|
|
59
|
+
})()
|
|
60
|
+
</script>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { default as AIScript } from './AIScript.astro'
|
|
2
|
+
export { default as TTSScript } from './TTSScript.astro'
|
|
3
|
+
|
|
4
|
+
// Re-export core types and factories for convenience
|
|
5
|
+
export {
|
|
6
|
+
createAI,
|
|
7
|
+
createTTS,
|
|
8
|
+
type AIConfig,
|
|
9
|
+
type TTSConfig,
|
|
10
|
+
type AIAPI,
|
|
11
|
+
type TTSAPI,
|
|
12
|
+
type AIProvider,
|
|
13
|
+
type TTSProvider,
|
|
14
|
+
type GenerateOptions,
|
|
15
|
+
type TTSOptions,
|
|
16
|
+
} from '@refraction-ui/ai'
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { animatedTextVariants } from '@refraction-ui/animated-text'
|
|
3
|
+
import { cn } from '../shared/index.ts'
|
|
4
|
+
|
|
5
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
6
|
+
/** Array of words to cycle through */
|
|
7
|
+
words: string[]
|
|
8
|
+
/** Interval between word changes in ms. Default: 2500 */
|
|
9
|
+
interval?: number
|
|
10
|
+
/** Duration of the transition in ms. Default: 1000 */
|
|
11
|
+
transitionDuration?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
words,
|
|
16
|
+
interval = 2500,
|
|
17
|
+
transitionDuration = 1000,
|
|
18
|
+
class: className,
|
|
19
|
+
...props
|
|
20
|
+
} = Astro.props
|
|
21
|
+
|
|
22
|
+
const classes = cn(animatedTextVariants({ state: 'idle' }), className)
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<span
|
|
26
|
+
data-rfr-animated-text
|
|
27
|
+
data-rfr-animated-words={JSON.stringify(words)}
|
|
28
|
+
data-rfr-animated-interval={interval}
|
|
29
|
+
data-rfr-animated-transition-duration={transitionDuration}
|
|
30
|
+
class={classes}
|
|
31
|
+
aria-live="polite"
|
|
32
|
+
aria-atomic="true"
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
{words.length > 0 ? words[0] : ''}
|
|
36
|
+
</span>
|
|
37
|
+
|
|
38
|
+
<script>
|
|
39
|
+
function initAnimatedTexts() {
|
|
40
|
+
document.querySelectorAll<HTMLElement>('[data-rfr-animated-text]').forEach((el) => {
|
|
41
|
+
if (el.hasAttribute('data-rfr-animated-text-init')) return
|
|
42
|
+
el.setAttribute('data-rfr-animated-text-init', '')
|
|
43
|
+
|
|
44
|
+
const words: string[] = JSON.parse(el.getAttribute('data-rfr-animated-words') || '[]')
|
|
45
|
+
const interval = Number(el.getAttribute('data-rfr-animated-interval') || 2500)
|
|
46
|
+
const transitionDuration = Number(el.getAttribute('data-rfr-animated-transition-duration') || 1000)
|
|
47
|
+
|
|
48
|
+
if (words.length <= 1) return
|
|
49
|
+
|
|
50
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
51
|
+
let currentIndex = 0
|
|
52
|
+
|
|
53
|
+
const tick = setInterval(() => {
|
|
54
|
+
if (prefersReducedMotion) {
|
|
55
|
+
currentIndex = (currentIndex + 1) % words.length
|
|
56
|
+
el.textContent = words[currentIndex]
|
|
57
|
+
} else {
|
|
58
|
+
// Exit transition
|
|
59
|
+
el.style.opacity = '0'
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
currentIndex = (currentIndex + 1) % words.length
|
|
62
|
+
el.textContent = words[currentIndex]
|
|
63
|
+
// Enter transition
|
|
64
|
+
el.style.opacity = '1'
|
|
65
|
+
}, transitionDuration / 2)
|
|
66
|
+
}
|
|
67
|
+
}, interval)
|
|
68
|
+
|
|
69
|
+
// Set transition style if motion is allowed
|
|
70
|
+
if (!prefersReducedMotion) {
|
|
71
|
+
el.style.transition = `opacity ${transitionDuration / 2}ms ease`
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Cleanup on removal (Astro page transitions)
|
|
75
|
+
el.addEventListener('astro:before-swap', () => clearInterval(tick), { once: true })
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
initAnimatedTexts()
|
|
80
|
+
document.addEventListener('astro:after-swap', initAnimatedTexts)
|
|
81
|
+
</script>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { typewriterVariants } from '@refraction-ui/animated-text'
|
|
3
|
+
import { cn } from '../shared/index.ts'
|
|
4
|
+
|
|
5
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
6
|
+
/** The text to type out */
|
|
7
|
+
text: string
|
|
8
|
+
/** Typing speed in ms per character. Default: 50 */
|
|
9
|
+
speed?: number
|
|
10
|
+
/** Delay before starting in ms. Default: 0 */
|
|
11
|
+
startDelay?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
text,
|
|
16
|
+
speed = 50,
|
|
17
|
+
startDelay = 0,
|
|
18
|
+
class: className,
|
|
19
|
+
...props
|
|
20
|
+
} = Astro.props
|
|
21
|
+
|
|
22
|
+
const classes = cn(typewriterVariants({ cursor: 'blinking' }), className)
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<span
|
|
26
|
+
data-rfr-typewriter
|
|
27
|
+
data-rfr-typewriter-text={text}
|
|
28
|
+
data-rfr-typewriter-speed={speed}
|
|
29
|
+
data-rfr-typewriter-start-delay={startDelay}
|
|
30
|
+
class={classes}
|
|
31
|
+
aria-label={text}
|
|
32
|
+
{...props}
|
|
33
|
+
></span>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
function initTypewriters() {
|
|
37
|
+
document.querySelectorAll<HTMLElement>('[data-rfr-typewriter]').forEach((el) => {
|
|
38
|
+
if (el.hasAttribute('data-rfr-typewriter-init')) return
|
|
39
|
+
el.setAttribute('data-rfr-typewriter-init', '')
|
|
40
|
+
|
|
41
|
+
const text = el.getAttribute('data-rfr-typewriter-text') || ''
|
|
42
|
+
const speed = Number(el.getAttribute('data-rfr-typewriter-speed') || 50)
|
|
43
|
+
const startDelay = Number(el.getAttribute('data-rfr-typewriter-start-delay') || 0)
|
|
44
|
+
|
|
45
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
46
|
+
|
|
47
|
+
if (prefersReducedMotion) {
|
|
48
|
+
el.textContent = text
|
|
49
|
+
// Remove cursor classes when complete
|
|
50
|
+
el.className = el.className
|
|
51
|
+
.replace(/after:inline-block/g, '')
|
|
52
|
+
.replace(/after:w-\[2px\]/g, '')
|
|
53
|
+
.replace(/after:h-\[1em\]/g, '')
|
|
54
|
+
.replace(/after:bg-current/g, '')
|
|
55
|
+
.replace(/after:ml-\[1px\]/g, '')
|
|
56
|
+
.replace(/after:animate-blink/g, '')
|
|
57
|
+
.replace(/after:align-text-bottom/g, '')
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let currentIndex = 0
|
|
62
|
+
|
|
63
|
+
const startTimeout = setTimeout(() => {
|
|
64
|
+
function tick() {
|
|
65
|
+
if (currentIndex < text.length) {
|
|
66
|
+
currentIndex += 1
|
|
67
|
+
el.textContent = text.slice(0, currentIndex)
|
|
68
|
+
setTimeout(tick, speed)
|
|
69
|
+
} else {
|
|
70
|
+
// Typing complete — remove cursor
|
|
71
|
+
el.className = el.className
|
|
72
|
+
.replace(/after:inline-block/g, '')
|
|
73
|
+
.replace(/after:w-\[2px\]/g, '')
|
|
74
|
+
.replace(/after:h-\[1em\]/g, '')
|
|
75
|
+
.replace(/after:bg-current/g, '')
|
|
76
|
+
.replace(/after:ml-\[1px\]/g, '')
|
|
77
|
+
.replace(/after:animate-blink/g, '')
|
|
78
|
+
.replace(/after:align-text-bottom/g, '')
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
tick()
|
|
82
|
+
}, startDelay)
|
|
83
|
+
|
|
84
|
+
el.addEventListener('astro:before-swap', () => clearTimeout(startTimeout), { once: true })
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
initTypewriters()
|
|
89
|
+
document.addEventListener('astro:after-swap', initTypewriters)
|
|
90
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* AppShell — root layout container for app-style layouts with sidebar, header, and main content.
|
|
4
|
+
* Includes a client-side script for responsive breakpoint detection and sidebar toggling.
|
|
5
|
+
*/
|
|
6
|
+
import { createAppShell, type AppShellConfig } from '@refraction-ui/app-shell'
|
|
7
|
+
import { cn } from '../shared/index.ts'
|
|
8
|
+
|
|
9
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
10
|
+
/** Sidebar width when expanded (default '16rem') */
|
|
11
|
+
sidebarWidth?: string
|
|
12
|
+
/** Sidebar width when collapsed (default '4rem') */
|
|
13
|
+
sidebarCollapsedWidth?: string
|
|
14
|
+
/** Header height (default '3.5rem') */
|
|
15
|
+
headerHeight?: string
|
|
16
|
+
/** Breakpoint below which layout is mobile (default 768) */
|
|
17
|
+
mobileBreakpoint?: number
|
|
18
|
+
/** Breakpoint below which layout is tablet (default 1024) */
|
|
19
|
+
tabletBreakpoint?: number
|
|
20
|
+
/** Sidebar position (default 'left') */
|
|
21
|
+
sidebarPosition?: 'left' | 'right'
|
|
22
|
+
/** Whether sidebar can collapse on desktop (default true) */
|
|
23
|
+
sidebarCollapsible?: boolean
|
|
24
|
+
/** Whether sidebar starts collapsed (default false) */
|
|
25
|
+
sidebarDefaultCollapsed?: boolean
|
|
26
|
+
/** Mobile nav position (default 'bottom') */
|
|
27
|
+
mobileNavPosition?: 'bottom' | 'none'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
sidebarWidth,
|
|
32
|
+
sidebarCollapsedWidth,
|
|
33
|
+
headerHeight,
|
|
34
|
+
mobileBreakpoint,
|
|
35
|
+
tabletBreakpoint,
|
|
36
|
+
sidebarPosition,
|
|
37
|
+
sidebarCollapsible,
|
|
38
|
+
sidebarDefaultCollapsed,
|
|
39
|
+
mobileNavPosition,
|
|
40
|
+
class: className,
|
|
41
|
+
...props
|
|
42
|
+
} = Astro.props
|
|
43
|
+
|
|
44
|
+
const config: AppShellConfig = {
|
|
45
|
+
sidebarWidth,
|
|
46
|
+
sidebarCollapsedWidth,
|
|
47
|
+
headerHeight,
|
|
48
|
+
mobileBreakpoint,
|
|
49
|
+
tabletBreakpoint,
|
|
50
|
+
sidebarPosition,
|
|
51
|
+
sidebarCollapsible,
|
|
52
|
+
sidebarDefaultCollapsed,
|
|
53
|
+
mobileNavPosition,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const api = createAppShell(config)
|
|
57
|
+
const cssVars = api.getCSSVariables()
|
|
58
|
+
const styleStr = Object.entries(cssVars).map(([k, v]) => `${k}:${v}`).join(';')
|
|
59
|
+
|
|
60
|
+
const configJSON = JSON.stringify(api.config)
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
<div
|
|
64
|
+
class={cn('flex h-screen w-full overflow-hidden', className)}
|
|
65
|
+
style={styleStr}
|
|
66
|
+
data-rfr-shell
|
|
67
|
+
data-rfr-shell-config={configJSON}
|
|
68
|
+
{...props}
|
|
69
|
+
>
|
|
70
|
+
<slot />
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<script is:inline>
|
|
74
|
+
;(function () {
|
|
75
|
+
var shell = document.querySelector('[data-rfr-shell]')
|
|
76
|
+
if (!shell) return
|
|
77
|
+
|
|
78
|
+
var config = {}
|
|
79
|
+
try { config = JSON.parse(shell.getAttribute('data-rfr-shell-config') || '{}') } catch (_) { /* */ }
|
|
80
|
+
|
|
81
|
+
var mobileBp = config.mobileBreakpoint || 768
|
|
82
|
+
var tabletBp = config.tabletBreakpoint || 1024
|
|
83
|
+
var sidebarCollapsible = config.sidebarCollapsible !== false
|
|
84
|
+
var sidebarWidth = config.sidebarWidth || '16rem'
|
|
85
|
+
var sidebarCollapsedWidth = config.sidebarCollapsedWidth || '4rem'
|
|
86
|
+
var sidebarPosition = config.sidebarPosition || 'left'
|
|
87
|
+
|
|
88
|
+
var state = {
|
|
89
|
+
breakpoint: 'desktop',
|
|
90
|
+
sidebarOpen: false,
|
|
91
|
+
sidebarCollapsed: config.sidebarDefaultCollapsed || false,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function isMobile() { return state.breakpoint === 'mobile' }
|
|
95
|
+
|
|
96
|
+
function updateBreakpoint() {
|
|
97
|
+
var w = window.innerWidth
|
|
98
|
+
var bp = w < mobileBp ? 'mobile' : w < tabletBp ? 'tablet' : 'desktop'
|
|
99
|
+
if (bp !== state.breakpoint) {
|
|
100
|
+
state.breakpoint = bp
|
|
101
|
+
if (bp !== 'mobile') state.sidebarOpen = false
|
|
102
|
+
applyState()
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function toggleSidebar() {
|
|
107
|
+
if (isMobile()) {
|
|
108
|
+
state.sidebarOpen = !state.sidebarOpen
|
|
109
|
+
} else if (sidebarCollapsible) {
|
|
110
|
+
state.sidebarCollapsed = !state.sidebarCollapsed
|
|
111
|
+
}
|
|
112
|
+
applyState()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function closeSidebar() {
|
|
116
|
+
state.sidebarOpen = false
|
|
117
|
+
applyState()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function applyState() {
|
|
121
|
+
var sidebar = shell.querySelector('[data-rfr-shell-sidebar]')
|
|
122
|
+
var overlay = shell.querySelector('[data-rfr-shell-overlay]')
|
|
123
|
+
var mobileNav = shell.querySelector('[data-rfr-shell-mobile-nav]')
|
|
124
|
+
var hamburgers = shell.querySelectorAll('[data-rfr-shell-toggle]')
|
|
125
|
+
|
|
126
|
+
// Update CSS variable for sidebar width
|
|
127
|
+
var currentWidth = state.sidebarCollapsed ? sidebarCollapsedWidth : sidebarWidth
|
|
128
|
+
shell.style.setProperty('--shell-sidebar-width', currentWidth)
|
|
129
|
+
|
|
130
|
+
if (sidebar) {
|
|
131
|
+
if (isMobile()) {
|
|
132
|
+
sidebar.style.position = 'fixed'
|
|
133
|
+
sidebar.style.top = '0'
|
|
134
|
+
sidebar.style.zIndex = '40'
|
|
135
|
+
sidebar.style.width = sidebarWidth
|
|
136
|
+
sidebar.style[sidebarPosition === 'right' ? 'right' : 'left'] = '0'
|
|
137
|
+
sidebar.style.transform = state.sidebarOpen
|
|
138
|
+
? 'translateX(0)'
|
|
139
|
+
: sidebarPosition === 'right' ? 'translateX(100%)' : 'translateX(-100%)'
|
|
140
|
+
sidebar.removeAttribute('data-collapsed')
|
|
141
|
+
} else {
|
|
142
|
+
sidebar.style.position = 'relative'
|
|
143
|
+
sidebar.style.transform = ''
|
|
144
|
+
sidebar.style.width = currentWidth
|
|
145
|
+
if (state.sidebarCollapsed) {
|
|
146
|
+
sidebar.setAttribute('data-collapsed', '')
|
|
147
|
+
} else {
|
|
148
|
+
sidebar.removeAttribute('data-collapsed')
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (state.sidebarOpen) {
|
|
152
|
+
sidebar.setAttribute('data-open', '')
|
|
153
|
+
} else {
|
|
154
|
+
sidebar.removeAttribute('data-open')
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (overlay) {
|
|
159
|
+
if (isMobile() && state.sidebarOpen) {
|
|
160
|
+
overlay.style.display = ''
|
|
161
|
+
} else {
|
|
162
|
+
overlay.style.display = 'none'
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (mobileNav) {
|
|
167
|
+
mobileNav.style.display = isMobile() ? '' : 'none'
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
hamburgers.forEach(function (btn) {
|
|
171
|
+
btn.setAttribute('aria-expanded', String(state.sidebarOpen))
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Bind toggle buttons
|
|
176
|
+
shell.addEventListener('click', function (e) {
|
|
177
|
+
var toggle = e.target.closest('[data-rfr-shell-toggle]')
|
|
178
|
+
if (toggle) {
|
|
179
|
+
toggleSidebar()
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
var overlayClick = e.target.closest('[data-rfr-shell-overlay]')
|
|
183
|
+
if (overlayClick) {
|
|
184
|
+
closeSidebar()
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// Expose API for external scripts
|
|
189
|
+
window.__rfr_shell = { toggleSidebar: toggleSidebar, closeSidebar: closeSidebar, state: state }
|
|
190
|
+
|
|
191
|
+
// Responsive listener
|
|
192
|
+
window.addEventListener('resize', updateBreakpoint)
|
|
193
|
+
updateBreakpoint()
|
|
194
|
+
})()
|
|
195
|
+
</script>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* AppShellContent — scrollable content area within AppShellMain.
|
|
4
|
+
*/
|
|
5
|
+
import { cn } from '../shared/index.ts'
|
|
6
|
+
|
|
7
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
8
|
+
/** Tailwind max-width class suffix, e.g. '6xl' -> max-w-6xl */
|
|
9
|
+
maxWidth?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { maxWidth, class: className, ...props } = Astro.props
|
|
13
|
+
|
|
14
|
+
const mwClass = maxWidth ? `max-w-${maxWidth} mx-auto w-full` : ''
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<main
|
|
18
|
+
role="main"
|
|
19
|
+
class={cn(
|
|
20
|
+
'flex-1 overflow-y-auto',
|
|
21
|
+
mwClass,
|
|
22
|
+
'px-4 sm:px-6 lg:px-8 py-6',
|
|
23
|
+
className,
|
|
24
|
+
)}
|
|
25
|
+
data-rfr-shell-content
|
|
26
|
+
{...props}
|
|
27
|
+
>
|
|
28
|
+
<slot />
|
|
29
|
+
</main>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* AppShellHeader — header area within the AppShell.
|
|
4
|
+
* On mobile, automatically renders a hamburger toggle button.
|
|
5
|
+
*/
|
|
6
|
+
import { cn } from '../shared/index.ts'
|
|
7
|
+
|
|
8
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
9
|
+
/** Hide the hamburger menu button */
|
|
10
|
+
hideToggle?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { hideToggle, class: className, ...props } = Astro.props
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<header
|
|
17
|
+
role="banner"
|
|
18
|
+
class={cn(
|
|
19
|
+
'sticky top-0 z-30 flex items-center shrink-0',
|
|
20
|
+
'h-[var(--shell-header-height)]',
|
|
21
|
+
'border-b bg-background px-4',
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
data-rfr-shell-header
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
{!hideToggle && (
|
|
28
|
+
<button
|
|
29
|
+
type="button"
|
|
30
|
+
aria-label="Toggle sidebar"
|
|
31
|
+
aria-expanded="false"
|
|
32
|
+
class="inline-flex items-center justify-center p-2 mr-2 md:hidden"
|
|
33
|
+
data-rfr-shell-toggle
|
|
34
|
+
>
|
|
35
|
+
<svg
|
|
36
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
37
|
+
width="24"
|
|
38
|
+
height="24"
|
|
39
|
+
viewBox="0 0 24 24"
|
|
40
|
+
fill="none"
|
|
41
|
+
stroke="currentColor"
|
|
42
|
+
stroke-width="2"
|
|
43
|
+
stroke-linecap="round"
|
|
44
|
+
stroke-linejoin="round"
|
|
45
|
+
aria-hidden="true"
|
|
46
|
+
>
|
|
47
|
+
<line x1="3" y1="6" x2="21" y2="6" />
|
|
48
|
+
<line x1="3" y1="12" x2="21" y2="12" />
|
|
49
|
+
<line x1="3" y1="18" x2="21" y2="18" />
|
|
50
|
+
</svg>
|
|
51
|
+
</button>
|
|
52
|
+
)}
|
|
53
|
+
<slot />
|
|
54
|
+
</header>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* AppShellMain — main content area wrapper (flex column).
|
|
4
|
+
*/
|
|
5
|
+
import { cn } from '../shared/index.ts'
|
|
6
|
+
|
|
7
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {}
|
|
8
|
+
|
|
9
|
+
const { class: className, ...props } = Astro.props
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<div
|
|
13
|
+
class={cn('flex flex-1 flex-col min-w-0 h-full', className)}
|
|
14
|
+
data-rfr-shell-main
|
|
15
|
+
{...props}
|
|
16
|
+
>
|
|
17
|
+
<slot />
|
|
18
|
+
</div>
|