@acronis-platform/shadcn-uikit 0.1.0 → 0.5.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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/theme-switcher.ts"],"sourcesContent":["/**\n * Theme Switcher Utility\n * \n * Provides functions to programmatically switch between themes and color modes.\n * Supports both theme switching (e.g., acronis-default, acronis-ocean) and\n * color mode switching (light/dark).\n */\n\nexport type ThemeName = 'acronis-default' | 'acronis-ocean' | 'custom'\nexport type ColorMode = 'light' | 'dark' | 'system'\n\nconst THEME_CLASS_PREFIX = 'theme-'\nconst DARK_CLASS = 'dark'\nconst THEME_STORAGE_KEY = 'av-theme'\nconst COLOR_MODE_STORAGE_KEY = 'av-color-mode'\n\n/**\n * Apply a theme to the document root element\n * \n * @param theme - The theme name to apply\n * @param persist - Whether to persist the theme choice to localStorage (default: true)\n * \n * @example\n * ```typescript\n * import { applyTheme } from '@acronis/shadcn-uikit/utils/theme-switcher'\n * \n * applyTheme('acronis-ocean')\n * ```\n */\nexport function applyTheme(theme: ThemeName, persist = true): void {\n const root = document.documentElement\n \n root.classList.forEach((className) => {\n if (className.startsWith(THEME_CLASS_PREFIX)) {\n root.classList.remove(className)\n }\n })\n \n const themeClass = `${THEME_CLASS_PREFIX}${theme}`\n root.classList.add(themeClass)\n \n if (persist) {\n try {\n localStorage.setItem(THEME_STORAGE_KEY, theme)\n } catch (error) {\n console.warn('Failed to persist theme to localStorage:', error)\n }\n }\n}\n\n/**\n * Get the currently applied theme\n * \n * @returns The current theme name or null if no theme is explicitly set\n */\nexport function getCurrentTheme(): ThemeName | null {\n const root = document.documentElement\n \n for (const className of root.classList) {\n if (className.startsWith(THEME_CLASS_PREFIX)) {\n return className.replace(THEME_CLASS_PREFIX, '') as ThemeName\n }\n }\n \n return null\n}\n\n/**\n * Load the persisted theme from localStorage and apply it\n * Call this on application startup to restore the user's theme preference\n * \n * @returns The loaded theme name or null if no theme was persisted\n */\nexport function loadPersistedTheme(): ThemeName | null {\n try {\n const persistedTheme = localStorage.getItem(THEME_STORAGE_KEY) as ThemeName | null\n if (persistedTheme) {\n applyTheme(persistedTheme, false)\n return persistedTheme\n }\n } catch (error) {\n console.warn('Failed to load persisted theme from localStorage:', error)\n }\n \n return null\n}\n\n/**\n * Apply a color mode (light/dark/system) to the document root element\n * \n * @param mode - The color mode to apply\n * @param persist - Whether to persist the mode choice to localStorage (default: true)\n * \n * @example\n * ```typescript\n * import { applyColorMode } from '@acronis/shadcn-uikit/utils/theme-switcher'\n * \n * applyColorMode('dark')\n * applyColorMode('system') // Follows system preference\n * ```\n */\nexport function applyColorMode(mode: ColorMode, persist = true): void {\n const root = document.documentElement\n \n if (mode === 'system') {\n const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches\n root.classList.toggle(DARK_CLASS, systemPrefersDark)\n } else {\n root.classList.toggle(DARK_CLASS, mode === 'dark')\n }\n \n if (persist) {\n try {\n localStorage.setItem(COLOR_MODE_STORAGE_KEY, mode)\n } catch (error) {\n console.warn('Failed to persist color mode to localStorage:', error)\n }\n }\n}\n\n/**\n * Get the currently applied color mode\n * \n * @returns 'light' or 'dark' based on the current state\n */\nexport function getCurrentColorMode(): 'light' | 'dark' {\n return document.documentElement.classList.contains(DARK_CLASS) ? 'dark' : 'light'\n}\n\n/**\n * Load the persisted color mode from localStorage and apply it\n * Call this on application startup to restore the user's color mode preference\n * \n * @returns The loaded color mode or null if no mode was persisted\n */\nexport function loadPersistedColorMode(): ColorMode | null {\n try {\n const persistedMode = localStorage.getItem(COLOR_MODE_STORAGE_KEY) as ColorMode | null\n if (persistedMode) {\n applyColorMode(persistedMode, false)\n return persistedMode\n }\n } catch (error) {\n console.warn('Failed to load persisted color mode from localStorage:', error)\n }\n \n return null\n}\n\n/**\n * Toggle between light and dark mode\n * \n * @param persist - Whether to persist the mode choice to localStorage (default: true)\n * @returns The new color mode after toggling\n */\nexport function toggleColorMode(persist = true): 'light' | 'dark' {\n const currentMode = getCurrentColorMode()\n const newMode = currentMode === 'light' ? 'dark' : 'light'\n applyColorMode(newMode, persist)\n return newMode\n}\n\n/**\n * Set up a listener for system color scheme changes\n * Only applies changes if the current mode is set to 'system'\n * \n * @returns A cleanup function to remove the listener\n */\nexport function watchSystemColorScheme(): () => void {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n \n const handler = (e: MediaQueryListEvent) => {\n try {\n const persistedMode = localStorage.getItem(COLOR_MODE_STORAGE_KEY)\n if (persistedMode === 'system') {\n document.documentElement.classList.toggle(DARK_CLASS, e.matches)\n }\n } catch (error) {\n console.warn('Failed to check persisted color mode:', error)\n }\n }\n \n mediaQuery.addEventListener('change', handler)\n \n return () => {\n mediaQuery.removeEventListener('change', handler)\n }\n}\n\n/**\n * Initialize the theme system on application startup\n * Loads persisted theme and color mode preferences\n * Sets up system color scheme watcher if mode is 'system'\n * \n * @returns A cleanup function to remove event listeners\n * \n * @example\n * ```typescript\n * import { initializeThemeSystem } from '@acronis/shadcn-uikit/utils/theme-switcher'\n * \n * // In your app initialization\n * const cleanup = initializeThemeSystem()\n * \n * // Call cleanup when unmounting (e.g., in React useEffect)\n * return cleanup\n * ```\n */\nexport function initializeThemeSystem(): () => void {\n loadPersistedTheme()\n loadPersistedColorMode()\n \n const cleanup = watchSystemColorScheme()\n \n return cleanup\n}\n"],"names":["THEME_CLASS_PREFIX","DARK_CLASS","THEME_STORAGE_KEY","COLOR_MODE_STORAGE_KEY","applyTheme","theme","persist","root","className","themeClass","error","getCurrentTheme","loadPersistedTheme","persistedTheme","applyColorMode","mode","systemPrefersDark","getCurrentColorMode","loadPersistedColorMode","persistedMode","toggleColorMode","newMode","watchSystemColorScheme","mediaQuery","handler","e","initializeThemeSystem"],"mappings":";AAWA,MAAMA,IAAqB,UACrBC,IAAa,QACbC,IAAoB,YACpBC,IAAyB;AAexB,SAASC,EAAWC,GAAkBC,IAAU,IAAY;AACjE,QAAMC,IAAO,SAAS;AAEtB,EAAAA,EAAK,UAAU,QAAQ,CAACC,MAAc;AACpC,IAAIA,EAAU,WAAWR,CAAkB,KACzCO,EAAK,UAAU,OAAOC,CAAS;AAAA,EAEnC,CAAC;AAED,QAAMC,IAAa,GAAGT,CAAkB,GAAGK,CAAK;AAGhD,MAFAE,EAAK,UAAU,IAAIE,CAAU,GAEzBH;AACF,QAAI;AACF,mBAAa,QAAQJ,GAAmBG,CAAK;AAAA,IAC/C,SAASK,GAAO;AACd,cAAQ,KAAK,4CAA4CA,CAAK;AAAA,IAChE;AAEJ;AAOO,SAASC,IAAoC;AAClD,QAAMJ,IAAO,SAAS;AAEtB,aAAWC,KAAaD,EAAK;AAC3B,QAAIC,EAAU,WAAWR,CAAkB;AACzC,aAAOQ,EAAU,QAAQR,GAAoB,EAAE;AAInD,SAAO;AACT;AAQO,SAASY,IAAuC;AACrD,MAAI;AACF,UAAMC,IAAiB,aAAa,QAAQX,CAAiB;AAC7D,QAAIW;AACF,aAAAT,EAAWS,GAAgB,EAAK,GACzBA;AAAA,EAEX,SAASH,GAAO;AACd,YAAQ,KAAK,qDAAqDA,CAAK;AAAA,EACzE;AAEA,SAAO;AACT;AAgBO,SAASI,EAAeC,GAAiBT,IAAU,IAAY;AACpE,QAAMC,IAAO,SAAS;AAEtB,MAAIQ,MAAS,UAAU;AACrB,UAAMC,IAAoB,OAAO,WAAW,8BAA8B,EAAE;AAC5E,IAAAT,EAAK,UAAU,OAAON,GAAYe,CAAiB;AAAA,EACrD;AACE,IAAAT,EAAK,UAAU,OAAON,GAAYc,MAAS,MAAM;AAGnD,MAAIT;AACF,QAAI;AACF,mBAAa,QAAQH,GAAwBY,CAAI;AAAA,IACnD,SAASL,GAAO;AACd,cAAQ,KAAK,iDAAiDA,CAAK;AAAA,IACrE;AAEJ;AAOO,SAASO,IAAwC;AACtD,SAAO,SAAS,gBAAgB,UAAU,SAAShB,CAAU,IAAI,SAAS;AAC5E;AAQO,SAASiB,IAA2C;AACzD,MAAI;AACF,UAAMC,IAAgB,aAAa,QAAQhB,CAAsB;AACjE,QAAIgB;AACF,aAAAL,EAAeK,GAAe,EAAK,GAC5BA;AAAA,EAEX,SAAST,GAAO;AACd,YAAQ,KAAK,0DAA0DA,CAAK;AAAA,EAC9E;AAEA,SAAO;AACT;AAQO,SAASU,EAAgBd,IAAU,IAAwB;AAEhE,QAAMe,IADcJ,EAAA,MACY,UAAU,SAAS;AACnD,SAAAH,EAAeO,GAASf,CAAO,GACxBe;AACT;AAQO,SAASC,IAAqC;AACnD,QAAMC,IAAa,OAAO,WAAW,8BAA8B,GAE7DC,IAAU,CAACC,MAA2B;AAC1C,QAAI;AAEF,MADsB,aAAa,QAAQtB,CAAsB,MAC3C,YACpB,SAAS,gBAAgB,UAAU,OAAOF,GAAYwB,EAAE,OAAO;AAAA,IAEnE,SAASf,GAAO;AACd,cAAQ,KAAK,yCAAyCA,CAAK;AAAA,IAC7D;AAAA,EACF;AAEA,SAAAa,EAAW,iBAAiB,UAAUC,CAAO,GAEtC,MAAM;AACX,IAAAD,EAAW,oBAAoB,UAAUC,CAAO;AAAA,EAClD;AACF;AAoBO,SAASE,IAAoC;AAClD,SAAAd,EAAA,GACAM,EAAA,GAEgBI,EAAA;AAGlB;"}
package/dist/llms.txt ADDED
@@ -0,0 +1,149 @@
1
+ # @acronis-platform/shadcn-uikit
2
+
3
+ > Acronis shadcn UI component library built with TypeScript, following shadcn design principles
4
+
5
+ A React component library built on shadcn/ui principles with Radix UI primitives and Tailwind CSS. Provides 47 production-ready components with TypeScript support, multiple variants, and full accessibility.
6
+
7
+ **Key Features:**
8
+ - Built with React 18+ and TypeScript
9
+ - Radix UI primitives for accessibility
10
+ - Tailwind CSS for styling with CSS variables
11
+ - Class Variance Authority (CVA) for variant management
12
+ - Dark mode support with next-themes
13
+ - Fully customizable through CSS variables
14
+
15
+ **Important Notes:**
16
+ - All components use the "av-" prefix for CSS classes
17
+ - CSS variables follow the pattern: --av-[property]
18
+ - Components support `className` prop for custom styling
19
+ - Import from '@acronis-platform/shadcn-uikit/react' for React components
20
+
21
+ ## Getting Started
22
+
23
+ - [Installation Guide](https://github.com/acronis/shadcn-uikit/blob/main/packages/docs/GETTING_STARTED.md): Complete setup instructions with Tailwind configuration
24
+ - [Architecture Overview](https://github.com/acronis/shadcn-uikit/blob/main/packages/docs/ARCHITECTURE.md): Project structure and design decisions
25
+ - [Main README](https://github.com/acronis/shadcn-uikit/blob/main/README.md): Project overview and quick start
26
+
27
+ ## Usage Examples
28
+
29
+ **Basic Button:**
30
+ ```tsx
31
+ import { Button } from '@acronis-platform/shadcn-uikit/react';
32
+
33
+ <Button variant="default">Click me</Button>
34
+ <Button variant="destructive" size="lg">Delete</Button>
35
+ ```
36
+
37
+ **Card with Form:**
38
+ ```tsx
39
+ import { Card, CardHeader, CardTitle, CardContent, Input, Button } from '@acronis-platform/shadcn-uikit/react';
40
+
41
+ <Card>
42
+ <CardHeader>
43
+ <CardTitle>Login</CardTitle>
44
+ </CardHeader>
45
+ <CardContent>
46
+ <Input placeholder="Email" />
47
+ <Button>Submit</Button>
48
+ </CardContent>
49
+ </Card>
50
+ ```
51
+
52
+ **Dialog:**
53
+ ```tsx
54
+ import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, Button } from '@acronis-platform/shadcn-uikit/react';
55
+
56
+ <Dialog>
57
+ <DialogTrigger asChild>
58
+ <Button>Open Dialog</Button>
59
+ </DialogTrigger>
60
+ <DialogContent>
61
+ <DialogHeader>
62
+ <DialogTitle>Dialog Title</DialogTitle>
63
+ </DialogHeader>
64
+ <p>Dialog content goes here</p>
65
+ </DialogContent>
66
+ </Dialog>
67
+ ```
68
+
69
+ ## Components
70
+
71
+ **Form Inputs:**
72
+ - **calendar**: Date picker calendar component
73
+ - **checkbox**: Toggle input for binary choices
74
+ - **combobox**: Searchable dropdown with autocomplete
75
+ - **date-picker**: Date selection input with calendar popup
76
+ - **input**: Text input field
77
+ - **radio-group**: Mutually exclusive option selector
78
+ - **select**: Dropdown selection input
79
+ - **switch**: Toggle switch for on/off states
80
+ - **textarea**: Multi-line text input
81
+
82
+ **Buttons & Actions:**
83
+ - **button-group**: Group of related buttons with consistent styling
84
+ - **button**: Interactive button with multiple variants and sizes
85
+
86
+ **Layout:**
87
+ - **card**: Container with header, content, and footer sections
88
+ - **scroll-area**: Custom scrollable container
89
+ - **separator**: Visual divider between content
90
+ - **sidebar**: Collapsible side navigation panel
91
+ - **tabs**: Tabbed content switcher
92
+
93
+ **Navigation:**
94
+ - **breadcrumb**: Navigation trail showing current page location
95
+ - **navigation-menu**: Main navigation menu with dropdowns
96
+ - **pagination**: Page navigation controls
97
+ - **secondary-menu**: Secondary navigation menu
98
+
99
+ **Overlays:**
100
+ - **alert-dialog**: Modal dialog for important confirmations and alerts
101
+ - **dialog**: Modal overlay for focused content and forms
102
+ - **drawer**: Slide-out panel from screen edge
103
+ - **popover**: Floating content container
104
+ - **sheet**: Slide-out panel similar to drawer
105
+ - **tooltip**: Contextual hint on hover
106
+
107
+ **Feedback:**
108
+ - **alert**: Contextual feedback messages for user actions
109
+ - **empty**: Empty state placeholder with icon and actions
110
+ - **progress**: Progress indicator bar
111
+ - **skeleton**: Loading placeholder animation
112
+ - **sonner**: Toast notification system
113
+ - **spinner**: Loading spinner indicator
114
+
115
+ **Data Display:**
116
+ - **accordion**: Collapsible content sections with expand/collapse functionality
117
+ - **avatar**: User profile image with fallback support
118
+ - **badge**: Small status indicators and labels
119
+ - **carousel**: Image/content slider with navigation controls
120
+ - **chart**: Data visualization charts using Recharts
121
+ - **chip**: Compact element for tags, filters, or selections
122
+ - **table**: Basic table layout components
123
+ - **tag**: Label or category indicator
124
+ - **tree**: Hierarchical tree view
125
+
126
+ **Forms:**
127
+ - **field**: Form field wrapper with label and validation
128
+ - **filter**: Data filtering controls
129
+ - **form**: Form handling with validation using react-hook-form
130
+ - **label**: Form field label
131
+
132
+ **Menus:**
133
+ - **command**: Command palette for keyboard-driven navigation
134
+ - **dropdown-menu**: Contextual menu with actions and options
135
+
136
+ ## Styling & Customization
137
+
138
+ - [Tailwind Configuration](https://github.com/acronis/shadcn-uikit/blob/main/packages/docs/GETTING_STARTED.md#configure-tailwind-css): Required Tailwind setup
139
+ - CSS Variables: Override theme colors using `--av-primary`, `--av-background`, etc.
140
+ - Dark Mode: Add `dark` class to root element
141
+ - Custom Variants: Use `cn()` utility to merge classes
142
+
143
+ ## Optional
144
+
145
+ - [Radix UI Documentation](https://www.radix-ui.com/primitives/docs/overview/introduction): Underlying primitive components
146
+ - [Tailwind CSS Documentation](https://tailwindcss.com/docs): Styling framework
147
+ - [Class Variance Authority](https://cva.style/docs): Variant management
148
+ - [React Hook Form](https://react-hook-form.com/): Form handling (used in form components)
149
+ - [Recharts Documentation](https://recharts.org/): Chart library (used in chart component)
@@ -1 +1 @@
1
- @charset "UTF-8";:root{--color-brand-primary: 213 65% 46%;--color-brand-secondary: 211 100% 45%;--color-brand-lightest: 213 65% 97%;--color-brand-light: 213 65% 96%;--color-text-primary: 215 26% 20%;--color-text-secondary: 215 26% 46%;--color-text-tertiary: 215 14% 39%;--color-surface-primary: 0 0% 100%;--color-surface-secondary: 210 100% 15%;--color-surface-overlay: 215 26% 20%;--color-surface-elevated: 0 0% 100%;--color-status-success: 73 68% 45%;--color-status-success-light: 84 67% 93%;--color-status-success-dark: 84 98% 21%;--color-status-info: 211 82% 60%;--color-status-info-light: 214 78% 95%;--color-status-info-dark: 214 68% 38%;--color-status-warning: 45 100% 52%;--color-status-warning-light: 45 100% 95%;--color-status-warning-dark: 30 50% 37%;--color-status-danger: 0 77% 57%;--color-status-danger-light: 0 100% 96%;--color-status-danger-dark: 0 72% 45%;--color-status-critical: 25 100% 52%;--color-status-critical-light: 27 95% 92%;--color-status-critical-dark: 11 73% 41%;--color-neutral: 220 11% 62%;--color-neutral-light: 220 11% 92%;--color-neutral-dark: 215 14% 39%;--color-ai: 263deg 77% 57%;--color-ai-light: 273deg 85% 97%;--color-ai-dark: 263deg 77% 57%;--opacity-10: .1;--opacity-20: .2;--opacity-30: .3;--opacity-40: .4;--opacity-50: .5;--opacity-70: .7;--opacity-90: .9}@layer base{:root{--semantic-bg-base: var(--color-surface-primary);--semantic-bg-elevated: var(--color-surface-elevated);--semantic-bg-muted: var(--color-brand-lightest);--semantic-bg-brand: var(--color-brand-primary);--semantic-bg-overlay: var(--color-surface-overlay);--semantic-text-primary: var(--color-text-primary);--semantic-text-secondary: var(--color-text-secondary);--semantic-text-tertiary: var(--color-text-tertiary);--semantic-text-inverse: var(--color-surface-primary);--semantic-text-brand: var(--color-brand-primary);--semantic-border-default: 213 65% 85%;--semantic-border-strong: var(--color-brand-primary);--semantic-border-subtle: 213 65% 92%;--semantic-interactive-default: var(--color-brand-primary);--semantic-interactive-hover: var(--color-brand-light);--semantic-interactive-active: var(--color-brand-primary);--semantic-interactive-disabled: var(--color-text-tertiary);--semantic-interactive-focus: var(--color-brand-primary);--semantic-status-success: var(--color-status-success);--semantic-status-success-bg: var(--color-status-success-light);--semantic-status-success-text: var(--color-status-success-dark);--semantic-status-info: var(--color-status-info);--semantic-status-info-bg: var(--color-status-info-light);--semantic-status-info-text: var(--color-status-info-dark);--semantic-status-warning: var(--color-status-warning);--semantic-status-warning-bg: var(--color-status-warning-light);--semantic-status-warning-text: var(--color-status-warning-dark);--semantic-status-danger: var(--color-status-danger);--semantic-status-danger-bg: var(--color-status-danger-light);--semantic-status-danger-text: var(--color-status-danger-dark);--semantic-status-critical: var(--color-status-critical);--semantic-status-critical-bg: var(--color-status-critical-light);--semantic-status-critical-text: var(--color-status-critical-dark);--semantic-status-neutral: var(--color-neutral);--semantic-status-neutral-bg: var(--color-neutral-light);--semantic-status-neutral-text: var(--color-neutral-dark);--semantic-status-ai: var(--color-ai);--semantic-status-ai-bg: var(--color-ai-light);--semantic-status-ai-text: var(--color-ai-dark);--semantic-nav-bg: var(--color-surface-secondary);--semantic-nav-text: var(--color-surface-primary);--semantic-nav-active: var(--color-brand-secondary);--semantic-radius: .25rem;--av-chart-1: oklch(64.6% .222 41.116deg);--av-chart-2: oklch(60% .118 184.704deg);--av-chart-3: oklch(39.8% .07 227.392deg);--av-chart-4: oklch(82.8% .189 84.429deg);--av-chart-5: oklch(76.9% .188 70.08deg);--av-chart-blue: oklch(52.7% .16 257.94deg);--av-chart-brown: oklch(60.6% .105 62.98deg);--av-chart-critical: oklch(73.4% .184 52.786deg);--av-chart-danger: oklch(61.7% .21 26.1deg);--av-chart-green: oklch(65.4% .11 189deg);--av-chart-grey: oklch(68.4% .01 257.94deg);--av-chart-info: var(--av-brand-secondary);--av-chart-light-blue: oklch(80.9% .09 240deg);--av-chart-neutral: oklch(90.6% 0 257.94deg);--av-chart-purple: oklch(71.4% .19 314.82deg);--av-chart-red: oklch(66.9% .184 23.483deg);--av-chart-success: oklch(75.9% .177 123.498deg);--av-chart-transparent: oklch(80.9% .09 240deg / 50%);--av-chart-turquoise: oklch(70.5% .13 230deg);--av-chart-violet: oklch(51.5% .09 299deg);--av-chart-warning: oklch(84.4% .17 84.9deg);--av-chart-yellow: oklch(84% .14 95deg)}.dark{--semantic-bg-base: var(--color-text-primary);--semantic-bg-elevated: 215 26% 23%;--semantic-bg-muted: 215 26% 30%;--semantic-bg-brand: var(--color-brand-primary);--semantic-bg-overlay: 215 26% 25%;--semantic-text-primary: var(--color-surface-primary);--semantic-text-secondary: 0 0% 70%;--semantic-text-tertiary: 0 0% 60%;--semantic-text-inverse: var(--color-text-primary);--semantic-text-brand: var(--color-brand-primary);--semantic-border-default: 215 26% 35%;--semantic-border-strong: 215 26% 40%;--semantic-border-subtle: 215 26% 25%;--semantic-interactive-default: var(--color-brand-primary);--semantic-interactive-hover: 213 65% 56%;--semantic-interactive-active: var(--color-brand-primary);--semantic-interactive-disabled: 215 26% 40%;--semantic-interactive-focus: var(--color-brand-primary);--semantic-status-success-bg: 73 68% 20%;--semantic-status-success-text: var(--color-status-success-light);--semantic-status-info-bg: 211 82% 20%;--semantic-status-info-text: var(--color-status-info-light);--semantic-status-warning-bg: 45 100% 20%;--semantic-status-warning-text: var(--color-status-warning-light);--semantic-status-danger-bg: 0 77% 20%;--semantic-status-danger-text: var(--color-status-danger-light);--semantic-status-critical-bg: 25 100% 20%;--semantic-status-critical-text: var(--color-status-critical-light);--semantic-status-neutral-bg: 220 11% 25%;--semantic-status-neutral-text: var(--color-neutral-light);--av-chart-1: oklch(48.8% .243 264.376deg);--av-chart-2: oklch(69.6% .17 162.48deg);--av-chart-3: oklch(76.9% .188 70.08deg);--av-chart-4: oklch(62.7% .265 303.9deg);--av-chart-5: oklch(64.5% .246 16.439deg)}}@layer base{*{@apply border-border;}body{@apply bg-background text-foreground;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}}@tailwind base;@tailwind components;@tailwind utilities;
1
+ @charset "UTF-8";:root{--color-brand-primary: 213 65% 46%;--color-brand-secondary: 211 100% 45%;--color-brand-lightest: 213 65% 97%;--color-brand-light: 213 65% 96%;--color-text-inverse: 0 0% 100%;--color-text-primary: 215 26% 20%;--color-text-secondary: 215 26% 46%;--color-text-tertiary: 215 14% 39%;--color-surface-primary: 0 0% 100%;--color-surface-secondary: 210 100% 15%;--color-surface-overlay: 215 26% 20%;--color-surface-elevated: 0 0% 100%;--color-status-success: 73 68% 45%;--color-status-success-light: 84 67% 93%;--color-status-success-dark: 84 98% 21%;--color-status-info: 211 82% 60%;--color-status-info-light: 214 78% 95%;--color-status-info-dark: 214 68% 38%;--color-status-warning: 45 100% 52%;--color-status-warning-light: 45 100% 95%;--color-status-warning-dark: 30 50% 37%;--color-status-danger: 0 77% 57%;--color-status-danger-light: 0 100% 96%;--color-status-danger-dark: 0 72% 45%;--color-status-critical: 25 100% 52%;--color-status-critical-light: 27 95% 92%;--color-status-critical-dark: 11 73% 41%;--color-neutral: 220 11% 62%;--color-neutral-light: 220 11% 92%;--color-neutral-dark: 215 14% 39%;--color-ai: 263deg 77% 57%;--color-ai-light: 273deg 85% 97%;--color-ai-dark: 263deg 77% 57%;--opacity-10: .1;--opacity-20: .2;--opacity-30: .3;--opacity-40: .4;--opacity-50: .5;--opacity-70: .7;--opacity-90: .9}:root{--color-brand-primary: 213 65% 46%;--color-brand-secondary: 211 100% 45%;--color-brand-lightest: 213 65% 97%;--color-brand-light: 213 65% 96%;--color-text-inverse: 0 0% 100%;--color-text-primary: 215 26% 20%;--color-text-secondary: 215 26% 46%;--color-text-tertiary: 215 14% 39%;--color-surface-primary: 0 0% 100%;--color-surface-secondary: 210 100% 15%;--color-surface-overlay: 215 26% 20%;--color-surface-elevated: 0 0% 100%;--color-status-success: 73 68% 45%;--color-status-success-light: 84 67% 93%;--color-status-success-dark: 84 98% 21%;--color-status-info: 211 82% 60%;--color-status-info-light: 214 78% 95%;--color-status-info-dark: 214 68% 38%;--color-status-warning: 45 100% 52%;--color-status-warning-light: 45 100% 95%;--color-status-warning-dark: 30 50% 37%;--color-status-danger: 0 77% 57%;--color-status-danger-light: 0 100% 96%;--color-status-danger-dark: 0 72% 45%;--color-status-critical: 25 100% 52%;--color-status-critical-light: 27 95% 92%;--color-status-critical-dark: 11 73% 41%;--color-neutral: 220 11% 62%;--color-neutral-light: 220 11% 92%;--color-neutral-dark: 215 14% 39%;--color-ai: 263deg 77% 57%;--color-ai-light: 273deg 85% 97%;--color-ai-dark: 263deg 77% 57%;--opacity-10: .1;--opacity-20: .2;--opacity-30: .3;--opacity-40: .4;--opacity-50: .5;--opacity-70: .7;--opacity-90: .9;--av-background: var(--color-surface-primary);--av-elevated: var(--color-surface-elevated);--av-card: var(--av-elevated);--av-muted: var(--color-brand-lightest);--av-primary: var(--color-brand-primary);--av-accent: var(--color-brand-primary);--av-secondary: var(--color-surface-elevated);--av-destructive: var(--color-status-danger);--av-destructive-foreground: var(--color-text-inverse);--av-danger: var(--color-status-danger);--av-success: var(--color-status-success);--av-warning: var(--color-status-warning);--av-info: var(--color-status-info);--av-critical: var(--color-status-critical);--av-neutral: var(--color-status-neutral);--av-popover: var(--av-elevated);--av-tooltip: var(--color-surface-overlay);--av-foreground: var(--color-text-primary);--av-text-primary: var(--color-text-primary);--av-card-foreground: var(--color-text-primary);--av-popover-foreground: var(--color-text-primary);--av-primary-foreground: var(--color-text-inverse);--av-muted-foreground: var(--color-text-secondary);--av-secondary-foreground: var(--color-text-secondary);--av-tertiary-foreground: var(--color-text-tertiary);--av-accent-foreground: var(--color-text-inverse);--av-text-inverse: var(--color-surface-primary);--av-brand-foreground: var(--color-brand-primary);--av-border: 213 65% 85%;--av-input: 213 65% 85%;--av-border-strong: var(--color-brand-primary);--av-border-subtle: 213 65% 92%;--av-interactive-default: var(--color-brand-primary);--av-interactive-hover: var(--color-brand-light);--av-interactive-active: var(--color-brand-primary);--av-interactive-disabled: var(--color-text-tertiary);--av-ring: var(--color-brand-primary);--av-focus: var(--color-brand-primary);--av-status-success: var(--color-status-success);--av-status-success-bg: var(--color-status-success-light);--av-status-success-text: var(--color-status-success-dark);--av-status-info: var(--color-status-info);--av-status-info-bg: var(--color-status-info-light);--av-status-info-text: var(--color-status-info-dark);--av-status-warning: var(--color-status-warning);--av-status-warning-bg: var(--color-status-warning-light);--av-status-warning-text: var(--color-status-warning-dark);--av-status-danger: var(--color-status-danger);--av-status-danger-bg: var(--color-status-danger-light);--av-status-danger-text: var(--color-status-danger-dark);--av-status-critical: var(--color-status-critical);--av-status-critical-bg: var(--color-status-critical-light);--av-status-critical-text: var(--color-status-critical-dark);--av-status-neutral: var(--color-neutral);--av-status-neutral-bg: var(--color-neutral-light);--av-status-neutral-text: var(--color-neutral-dark);--av-status-ai: var(--color-ai);--av-status-ai-bg: var(--color-ai-light);--av-status-ai-text: var(--color-ai-dark);--av-nav-bg: var(--color-surface-secondary);--av-nav-text: var(--color-surface-primary);--av-nav-active: var(--color-brand-secondary);--av-radius: .25rem;--av-chart-1: oklch(64.6% .222 41.116deg);--av-chart-2: oklch(60% .118 184.704deg);--av-chart-3: oklch(39.8% .07 227.392deg);--av-chart-4: oklch(82.8% .189 84.429deg);--av-chart-5: oklch(76.9% .188 70.08deg);--av-chart-blue: oklch(52.7% .16 257.94deg);--av-chart-brown: oklch(60.6% .105 62.98deg);--av-chart-critical: oklch(73.4% .184 52.786deg);--av-chart-danger: oklch(61.7% .21 26.1deg);--av-chart-green: oklch(65.4% .11 189deg);--av-chart-grey: oklch(68.4% .01 257.94deg);--av-chart-info: var(--av-brand-secondary);--av-chart-light-blue: oklch(80.9% .09 240deg);--av-chart-neutral: oklch(90.6% 0 257.94deg);--av-chart-purple: oklch(71.4% .19 314.82deg);--av-chart-red: oklch(66.9% .184 23.483deg);--av-chart-success: oklch(75.9% .177 123.498deg);--av-chart-transparent: oklch(80.9% .09 240deg / 50%);--av-chart-turquoise: oklch(70.5% .13 230deg);--av-chart-violet: oklch(51.5% .09 299deg);--av-chart-warning: oklch(84.4% .17 84.9deg);--av-chart-yellow: oklch(84% .14 95deg)}.dark{--av-background: var(--color-text-primary);--av-elevated: 215 26% 23%;--av-muted: 215 26% 30%;--av-tooltip: 215 26% 25%;--av-foreground: var(--color-surface-primary);--av-text-primary: var(--color-surface-primary);--av-secondary-foreground: 0 0% 70%;--av-tertiary-foreground: 0 0% 60%;--av-text-inverse: var(--color-text-primary);--av-brand-foreground: var(--color-brand-primary);--av-border: 215 26% 35%;--av-border-strong: 215 26% 40%;--av-border-subtle: 215 26% 25%;--av-interactive-default: var(--color-brand-primary);--av-interactive-hover: 213 65% 56%;--av-interactive-active: var(--color-brand-primary);--av-interactive-disabled: 215 26% 40%;--av-focus: var(--color-brand-primary);--av-status-success-bg: 73 68% 20%;--av-status-success-text: var(--color-status-success-light);--av-status-info-bg: 211 82% 20%;--av-status-info-text: var(--color-status-info-light);--av-status-warning-bg: 45 100% 20%;--av-status-warning-text: var(--color-status-warning-light);--av-status-danger-bg: 0 77% 20%;--av-status-danger-text: var(--color-status-danger-light);--av-status-critical-bg: 25 100% 20%;--av-status-critical-text: var(--color-status-critical-light);--av-status-neutral-bg: 220 11% 25%;--av-status-neutral-text: var(--color-neutral-light);--av-chart-1: oklch(48.8% .243 264.376deg);--av-chart-2: oklch(69.6% .17 162.48deg);--av-chart-3: oklch(76.9% .188 70.08deg);--av-chart-4: oklch(62.7% .265 303.9deg);--av-chart-5: oklch(64.5% .246 16.439deg)}.theme-acronis-default{--color-brand-primary: 213 65% 46%;--color-brand-secondary: 211 100% 45%;--color-brand-lightest: 213 65% 97%;--color-brand-light: 213 65% 96%;--color-text-inverse: 0 0% 100%;--color-text-primary: 215 26% 20%;--color-text-secondary: 215 26% 46%;--color-text-tertiary: 215 14% 39%;--color-surface-primary: 0 0% 100%;--color-surface-secondary: 210 100% 15%;--color-surface-overlay: 215 26% 20%;--color-surface-elevated: 0 0% 100%;--color-status-success: 73 68% 45%;--color-status-success-light: 84 67% 93%;--color-status-success-dark: 84 98% 21%;--color-status-info: 211 82% 60%;--color-status-info-light: 214 78% 95%;--color-status-info-dark: 214 68% 38%;--color-status-warning: 45 100% 52%;--color-status-warning-light: 45 100% 95%;--color-status-warning-dark: 30 50% 37%;--color-status-danger: 0 77% 57%;--color-status-danger-light: 0 100% 96%;--color-status-danger-dark: 0 72% 45%;--color-status-critical: 25 100% 52%;--color-status-critical-light: 27 95% 92%;--color-status-critical-dark: 11 73% 41%;--color-neutral: 220 11% 62%;--color-neutral-light: 220 11% 92%;--color-neutral-dark: 215 14% 39%;--color-ai: 263deg 77% 57%;--color-ai-light: 273deg 85% 97%;--color-ai-dark: 263deg 77% 57%;--opacity-10: .1;--opacity-20: .2;--opacity-30: .3;--opacity-40: .4;--opacity-50: .5;--opacity-70: .7;--opacity-90: .9;--av-background: var(--color-surface-primary);--av-elevated: var(--color-surface-elevated);--av-card: var(--av-elevated);--av-muted: var(--color-brand-lightest);--av-primary: var(--color-brand-primary);--av-accent: var(--color-brand-primary);--av-secondary: var(--color-surface-elevated);--av-destructive: var(--color-status-danger);--av-destructive-foreground: var(--color-text-inverse);--av-danger: var(--color-status-danger);--av-success: var(--color-status-success);--av-warning: var(--color-status-warning);--av-info: var(--color-status-info);--av-critical: var(--color-status-critical);--av-neutral: var(--color-status-neutral);--av-popover: var(--av-elevated);--av-tooltip: var(--color-surface-overlay);--av-foreground: var(--color-text-primary);--av-text-primary: var(--color-text-primary);--av-card-foreground: var(--color-text-primary);--av-popover-foreground: var(--color-text-primary);--av-primary-foreground: var(--color-text-inverse);--av-muted-foreground: var(--color-text-secondary);--av-secondary-foreground: var(--color-text-secondary);--av-tertiary-foreground: var(--color-text-tertiary);--av-accent-foreground: var(--color-text-inverse);--av-text-inverse: var(--color-surface-primary);--av-brand-foreground: var(--color-brand-primary);--av-border: 213 65% 85%;--av-input: 213 65% 85%;--av-border-strong: var(--color-brand-primary);--av-border-subtle: 213 65% 92%;--av-interactive-default: var(--color-brand-primary);--av-interactive-hover: var(--color-brand-light);--av-interactive-active: var(--color-brand-primary);--av-interactive-disabled: var(--color-text-tertiary);--av-ring: var(--color-brand-primary);--av-focus: var(--color-brand-primary);--av-status-success: var(--color-status-success);--av-status-success-bg: var(--color-status-success-light);--av-status-success-text: var(--color-status-success-dark);--av-status-info: var(--color-status-info);--av-status-info-bg: var(--color-status-info-light);--av-status-info-text: var(--color-status-info-dark);--av-status-warning: var(--color-status-warning);--av-status-warning-bg: var(--color-status-warning-light);--av-status-warning-text: var(--color-status-warning-dark);--av-status-danger: var(--color-status-danger);--av-status-danger-bg: var(--color-status-danger-light);--av-status-danger-text: var(--color-status-danger-dark);--av-status-critical: var(--color-status-critical);--av-status-critical-bg: var(--color-status-critical-light);--av-status-critical-text: var(--color-status-critical-dark);--av-status-neutral: var(--color-neutral);--av-status-neutral-bg: var(--color-neutral-light);--av-status-neutral-text: var(--color-neutral-dark);--av-status-ai: var(--color-ai);--av-status-ai-bg: var(--color-ai-light);--av-status-ai-text: var(--color-ai-dark);--av-nav-bg: var(--color-surface-secondary);--av-nav-text: var(--color-surface-primary);--av-nav-active: var(--color-brand-secondary);--av-radius: .25rem;--av-chart-1: oklch(64.6% .222 41.116deg);--av-chart-2: oklch(60% .118 184.704deg);--av-chart-3: oklch(39.8% .07 227.392deg);--av-chart-4: oklch(82.8% .189 84.429deg);--av-chart-5: oklch(76.9% .188 70.08deg);--av-chart-blue: oklch(52.7% .16 257.94deg);--av-chart-brown: oklch(60.6% .105 62.98deg);--av-chart-critical: oklch(73.4% .184 52.786deg);--av-chart-danger: oklch(61.7% .21 26.1deg);--av-chart-green: oklch(65.4% .11 189deg);--av-chart-grey: oklch(68.4% .01 257.94deg);--av-chart-info: var(--av-brand-secondary);--av-chart-light-blue: oklch(80.9% .09 240deg);--av-chart-neutral: oklch(90.6% 0 257.94deg);--av-chart-purple: oklch(71.4% .19 314.82deg);--av-chart-red: oklch(66.9% .184 23.483deg);--av-chart-success: oklch(75.9% .177 123.498deg);--av-chart-transparent: oklch(80.9% .09 240deg / 50%);--av-chart-turquoise: oklch(70.5% .13 230deg);--av-chart-violet: oklch(51.5% .09 299deg);--av-chart-warning: oklch(84.4% .17 84.9deg);--av-chart-yellow: oklch(84% .14 95deg)}.theme-acronis-default.dark{--av-background: var(--color-text-primary);--av-elevated: 215 26% 23%;--av-muted: 215 26% 30%;--av-tooltip: 215 26% 25%;--av-foreground: var(--color-surface-primary);--av-text-primary: var(--color-surface-primary);--av-secondary-foreground: 0 0% 70%;--av-tertiary-foreground: 0 0% 60%;--av-text-inverse: var(--color-text-primary);--av-brand-foreground: var(--color-brand-primary);--av-border: 215 26% 35%;--av-border-strong: 215 26% 40%;--av-border-subtle: 215 26% 25%;--av-interactive-default: var(--color-brand-primary);--av-interactive-hover: 213 65% 56%;--av-interactive-active: var(--color-brand-primary);--av-interactive-disabled: 215 26% 40%;--av-focus: var(--color-brand-primary);--av-status-success-bg: 73 68% 20%;--av-status-success-text: var(--color-status-success-light);--av-status-info-bg: 211 82% 20%;--av-status-info-text: var(--color-status-info-light);--av-status-warning-bg: 45 100% 20%;--av-status-warning-text: var(--color-status-warning-light);--av-status-danger-bg: 0 77% 20%;--av-status-danger-text: var(--color-status-danger-light);--av-status-critical-bg: 25 100% 20%;--av-status-critical-text: var(--color-status-critical-light);--av-status-neutral-bg: 220 11% 25%;--av-status-neutral-text: var(--color-neutral-light);--av-chart-1: oklch(48.8% .243 264.376deg);--av-chart-2: oklch(69.6% .17 162.48deg);--av-chart-3: oklch(76.9% .188 70.08deg);--av-chart-4: oklch(62.7% .265 303.9deg);--av-chart-5: oklch(64.5% .246 16.439deg)}@layer base{*{@apply border-border;}body{@apply bg-background text-foreground;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}}@tailwind base;@tailwind components;@tailwind utilities;
@@ -1 +1,2 @@
1
1
  export { cn } from './cn';
2
+ export { applyTheme, getCurrentTheme, loadPersistedTheme, applyColorMode, getCurrentColorMode, loadPersistedColorMode, toggleColorMode, watchSystemColorScheme, initializeThemeSystem, type ThemeName, type ColorMode, } from './theme-switcher';
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Theme Switcher Utility
3
+ *
4
+ * Provides functions to programmatically switch between themes and color modes.
5
+ * Supports both theme switching (e.g., acronis-default, acronis-ocean) and
6
+ * color mode switching (light/dark).
7
+ */
8
+ export type ThemeName = 'acronis-default' | 'acronis-ocean' | 'custom';
9
+ export type ColorMode = 'light' | 'dark' | 'system';
10
+ /**
11
+ * Apply a theme to the document root element
12
+ *
13
+ * @param theme - The theme name to apply
14
+ * @param persist - Whether to persist the theme choice to localStorage (default: true)
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { applyTheme } from '@acronis/shadcn-uikit/utils/theme-switcher'
19
+ *
20
+ * applyTheme('acronis-ocean')
21
+ * ```
22
+ */
23
+ export declare function applyTheme(theme: ThemeName, persist?: boolean): void;
24
+ /**
25
+ * Get the currently applied theme
26
+ *
27
+ * @returns The current theme name or null if no theme is explicitly set
28
+ */
29
+ export declare function getCurrentTheme(): ThemeName | null;
30
+ /**
31
+ * Load the persisted theme from localStorage and apply it
32
+ * Call this on application startup to restore the user's theme preference
33
+ *
34
+ * @returns The loaded theme name or null if no theme was persisted
35
+ */
36
+ export declare function loadPersistedTheme(): ThemeName | null;
37
+ /**
38
+ * Apply a color mode (light/dark/system) to the document root element
39
+ *
40
+ * @param mode - The color mode to apply
41
+ * @param persist - Whether to persist the mode choice to localStorage (default: true)
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * import { applyColorMode } from '@acronis/shadcn-uikit/utils/theme-switcher'
46
+ *
47
+ * applyColorMode('dark')
48
+ * applyColorMode('system') // Follows system preference
49
+ * ```
50
+ */
51
+ export declare function applyColorMode(mode: ColorMode, persist?: boolean): void;
52
+ /**
53
+ * Get the currently applied color mode
54
+ *
55
+ * @returns 'light' or 'dark' based on the current state
56
+ */
57
+ export declare function getCurrentColorMode(): 'light' | 'dark';
58
+ /**
59
+ * Load the persisted color mode from localStorage and apply it
60
+ * Call this on application startup to restore the user's color mode preference
61
+ *
62
+ * @returns The loaded color mode or null if no mode was persisted
63
+ */
64
+ export declare function loadPersistedColorMode(): ColorMode | null;
65
+ /**
66
+ * Toggle between light and dark mode
67
+ *
68
+ * @param persist - Whether to persist the mode choice to localStorage (default: true)
69
+ * @returns The new color mode after toggling
70
+ */
71
+ export declare function toggleColorMode(persist?: boolean): 'light' | 'dark';
72
+ /**
73
+ * Set up a listener for system color scheme changes
74
+ * Only applies changes if the current mode is set to 'system'
75
+ *
76
+ * @returns A cleanup function to remove the listener
77
+ */
78
+ export declare function watchSystemColorScheme(): () => void;
79
+ /**
80
+ * Initialize the theme system on application startup
81
+ * Loads persisted theme and color mode preferences
82
+ * Sets up system color scheme watcher if mode is 'system'
83
+ *
84
+ * @returns A cleanup function to remove event listeners
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * import { initializeThemeSystem } from '@acronis/shadcn-uikit/utils/theme-switcher'
89
+ *
90
+ * // In your app initialization
91
+ * const cleanup = initializeThemeSystem()
92
+ *
93
+ * // Call cleanup when unmounting (e.g., in React useEffect)
94
+ * return cleanup
95
+ * ```
96
+ */
97
+ export declare function initializeThemeSystem(): () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acronis-platform/shadcn-uikit",
3
- "version": "0.1.0",
3
+ "version": "0.5.0",
4
4
  "description": "Acronis shadcn UI component library built with TypeScript, following shadcn design principles",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -74,12 +74,12 @@
74
74
  },
75
75
  "devDependencies": {
76
76
  "@playwright/test": "1.56.1",
77
- "@storybook/addon-a11y": "10.1.10",
78
- "@storybook/addon-docs": "^10.1.10",
79
- "@storybook/addon-links": "^10.1.10",
77
+ "@storybook/addon-a11y": "10.1.11",
78
+ "@storybook/addon-docs": "10.1.11",
79
+ "@storybook/addon-links": "10.1.11",
80
80
  "@storybook/addon-vitest": "10.1.11",
81
- "@storybook/react": "^10.1.10",
82
- "@storybook/react-vite": "^10.1.10",
81
+ "@storybook/react": "10.1.11",
82
+ "@storybook/react-vite": "10.1.11",
83
83
  "@storybook/test-runner": "0.24.2",
84
84
  "@testing-library/jest-dom": "^6.2.0",
85
85
  "@testing-library/react": "^14.1.2",
@@ -98,6 +98,7 @@
98
98
  "storybook": "^10.1.10",
99
99
  "tailwindcss": "^3.4.1",
100
100
  "tailwindcss-animate": "^1.0.7",
101
+ "tsx": "^4.19.2",
101
102
  "typescript": "^5.5.3",
102
103
  "vite": "^6.3.5",
103
104
  "vite-plugin-dts": "^4.3.0",
@@ -120,9 +121,10 @@
120
121
  "access": "public"
121
122
  },
122
123
  "scripts": {
123
- "build": "vite build",
124
+ "build": "npm run build:lib && npm run build:llms",
124
125
  "build:lib": "vite build",
125
126
  "build:types": "tsc --project tsconfig.build.json",
127
+ "build:llms": "tsx scripts/generate-llms-txt.ts",
126
128
  "dev": "vite build --watch",
127
129
  "type-check": "tsc --noEmit",
128
130
  "test": "vitest",