@marcoschwartz/lite-ui 0.1.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/README.md +208 -0
- package/dist/index.d.mts +87 -0
- package/dist/index.d.ts +87 -0
- package/dist/index.js +358 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +326 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Lite UI
|
|
2
|
+
|
|
3
|
+
A lightweight UI component library built with Tailwind CSS and React.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Built with TypeScript
|
|
8
|
+
- Styled with Tailwind CSS
|
|
9
|
+
- Tree-shakeable ESM and CJS builds
|
|
10
|
+
- Live development with hot module reloading
|
|
11
|
+
- Server Component compatible (works in Next.js App Router and other RSC frameworks)
|
|
12
|
+
- Components are framework-agnostic React components
|
|
13
|
+
- Built-in theming system with multiple pre-built themes
|
|
14
|
+
|
|
15
|
+
## Development
|
|
16
|
+
|
|
17
|
+
### Quick Start
|
|
18
|
+
|
|
19
|
+
Run the library build watcher and demo app simultaneously:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm run dev:all
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This single command will:
|
|
26
|
+
1. Start the UI library build in watch mode (auto-rebuilds on changes)
|
|
27
|
+
2. Start the Next.js demo app on http://localhost:3000
|
|
28
|
+
3. Automatically reflect changes from the library in the demo app
|
|
29
|
+
|
|
30
|
+
### Individual Commands
|
|
31
|
+
|
|
32
|
+
Build the library once:
|
|
33
|
+
```bash
|
|
34
|
+
npm run build
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Build the library in watch mode:
|
|
38
|
+
```bash
|
|
39
|
+
npm run dev
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Run the demo app only:
|
|
43
|
+
```bash
|
|
44
|
+
cd demo && npm run dev
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Components
|
|
48
|
+
|
|
49
|
+
### Button
|
|
50
|
+
|
|
51
|
+
A versatile button component with multiple variants and sizes.
|
|
52
|
+
|
|
53
|
+
#### Variants
|
|
54
|
+
- `primary` (default) - Blue button
|
|
55
|
+
- `secondary` - Gray button
|
|
56
|
+
- `success` - Green button
|
|
57
|
+
- `danger` - Red button
|
|
58
|
+
- `warning` - Yellow button
|
|
59
|
+
- `info` - Cyan button
|
|
60
|
+
|
|
61
|
+
#### Sizes
|
|
62
|
+
- `sm` - Small
|
|
63
|
+
- `md` (default) - Medium
|
|
64
|
+
- `lg` - Large
|
|
65
|
+
- `xl` - Extra Large
|
|
66
|
+
|
|
67
|
+
#### Usage
|
|
68
|
+
|
|
69
|
+
**In Server Components (Next.js App Router):**
|
|
70
|
+
```tsx
|
|
71
|
+
// app/page.tsx (Server Component)
|
|
72
|
+
import { Button } from 'lite-ui';
|
|
73
|
+
|
|
74
|
+
export default function Page() {
|
|
75
|
+
return (
|
|
76
|
+
<div>
|
|
77
|
+
<Button variant="primary" size="md">
|
|
78
|
+
Static Button (Server Rendered)
|
|
79
|
+
</Button>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**In Client Components (with interactivity):**
|
|
86
|
+
```tsx
|
|
87
|
+
// app/components/InteractiveButton.tsx
|
|
88
|
+
"use client";
|
|
89
|
+
|
|
90
|
+
import { Button } from 'lite-ui';
|
|
91
|
+
|
|
92
|
+
export function InteractiveButton() {
|
|
93
|
+
return (
|
|
94
|
+
<Button variant="success" onClick={() => alert('Clicked!')}>
|
|
95
|
+
Click Me
|
|
96
|
+
</Button>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**In any React app:**
|
|
102
|
+
```tsx
|
|
103
|
+
import { Button } from 'lite-ui';
|
|
104
|
+
|
|
105
|
+
function App() {
|
|
106
|
+
return (
|
|
107
|
+
<div>
|
|
108
|
+
<Button variant="primary" size="md">
|
|
109
|
+
Click Me
|
|
110
|
+
</Button>
|
|
111
|
+
|
|
112
|
+
<Button variant="success" size="lg" onClick={() => alert('Success!')}>
|
|
113
|
+
Submit
|
|
114
|
+
</Button>
|
|
115
|
+
|
|
116
|
+
<Button variant="danger" disabled>
|
|
117
|
+
Disabled
|
|
118
|
+
</Button>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Structure
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
lite-ui-js/
|
|
128
|
+
├── src/ # UI library source code
|
|
129
|
+
│ ├── components/ # React components
|
|
130
|
+
│ └── index.ts # Main export file
|
|
131
|
+
├── demo/ # Next.js demo application
|
|
132
|
+
├── dist/ # Built library (generated)
|
|
133
|
+
└── dev.sh # Development script
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Theming
|
|
137
|
+
|
|
138
|
+
Lite UI includes a built-in theming system that allows you to easily switch between different visual styles.
|
|
139
|
+
|
|
140
|
+
### Available Themes
|
|
141
|
+
|
|
142
|
+
1. **Default** - Vibrant colors, shadows, and smooth animations
|
|
143
|
+
2. **Minimalistic** - Flat design, subtle colors, minimal effects
|
|
144
|
+
|
|
145
|
+
### Usage
|
|
146
|
+
|
|
147
|
+
**Wrap your app with ThemeProvider:**
|
|
148
|
+
```tsx
|
|
149
|
+
import { ThemeProvider } from 'lite-ui';
|
|
150
|
+
|
|
151
|
+
function App() {
|
|
152
|
+
return (
|
|
153
|
+
<ThemeProvider defaultTheme="default">
|
|
154
|
+
{/* your app */}
|
|
155
|
+
</ThemeProvider>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Switch themes dynamically:**
|
|
161
|
+
```tsx
|
|
162
|
+
"use client";
|
|
163
|
+
|
|
164
|
+
import { useTheme, Button } from 'lite-ui';
|
|
165
|
+
|
|
166
|
+
function ThemeSwitcher() {
|
|
167
|
+
const { themeName, setTheme } = useTheme();
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<div>
|
|
171
|
+
<p>Current theme: {themeName}</p>
|
|
172
|
+
<Button onClick={() => setTheme('default')}>Default Theme</Button>
|
|
173
|
+
<Button onClick={() => setTheme('minimalistic')}>Minimalistic Theme</Button>
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Components work without ThemeProvider:**
|
|
180
|
+
If you don't wrap your app in a ThemeProvider, components will automatically use the default theme.
|
|
181
|
+
|
|
182
|
+
### Creating Custom Themes
|
|
183
|
+
|
|
184
|
+
You can create custom themes by extending the theme configuration:
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
import { themes, ThemeProvider } from 'lite-ui';
|
|
188
|
+
|
|
189
|
+
const customTheme = {
|
|
190
|
+
...themes.default,
|
|
191
|
+
name: 'custom',
|
|
192
|
+
button: {
|
|
193
|
+
...themes.default.button,
|
|
194
|
+
variants: {
|
|
195
|
+
...themes.default.button.variants,
|
|
196
|
+
primary: 'bg-purple-600 hover:bg-purple-700 text-white',
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Technology Stack
|
|
203
|
+
|
|
204
|
+
- **React 19** - UI framework
|
|
205
|
+
- **TypeScript** - Type safety
|
|
206
|
+
- **Tailwind CSS v4** - Styling
|
|
207
|
+
- **tsup** - Build tool
|
|
208
|
+
- **Next.js 15** - Demo app framework
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';
|
|
6
|
+
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
declare const Button: React.FC<ButtonProps>;
|
|
10
|
+
|
|
11
|
+
interface SelectOption {
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}
|
|
15
|
+
interface SelectProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'size' | 'onChange' | 'defaultValue'> {
|
|
16
|
+
options: SelectOption[];
|
|
17
|
+
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
value?: string;
|
|
21
|
+
defaultValue?: string;
|
|
22
|
+
onChange?: (value: string) => void;
|
|
23
|
+
}
|
|
24
|
+
declare const Select: React.FC<SelectProps>;
|
|
25
|
+
|
|
26
|
+
type ThemeName = 'default' | 'minimalistic';
|
|
27
|
+
interface ButtonTheme {
|
|
28
|
+
primary: string;
|
|
29
|
+
secondary: string;
|
|
30
|
+
success: string;
|
|
31
|
+
danger: string;
|
|
32
|
+
warning: string;
|
|
33
|
+
info: string;
|
|
34
|
+
}
|
|
35
|
+
interface SelectTheme {
|
|
36
|
+
base: string;
|
|
37
|
+
sizes: {
|
|
38
|
+
sm: string;
|
|
39
|
+
md: string;
|
|
40
|
+
lg: string;
|
|
41
|
+
xl: string;
|
|
42
|
+
};
|
|
43
|
+
disabled: string;
|
|
44
|
+
}
|
|
45
|
+
interface Theme {
|
|
46
|
+
name: ThemeName;
|
|
47
|
+
button: {
|
|
48
|
+
base: string;
|
|
49
|
+
variants: ButtonTheme;
|
|
50
|
+
sizes: {
|
|
51
|
+
sm: string;
|
|
52
|
+
md: string;
|
|
53
|
+
lg: string;
|
|
54
|
+
xl: string;
|
|
55
|
+
};
|
|
56
|
+
disabled: string;
|
|
57
|
+
};
|
|
58
|
+
select: SelectTheme;
|
|
59
|
+
}
|
|
60
|
+
declare const themes: Record<ThemeName, Theme>;
|
|
61
|
+
|
|
62
|
+
type ColorMode = 'light' | 'dark' | 'system';
|
|
63
|
+
interface ThemeContextValue {
|
|
64
|
+
theme: Theme;
|
|
65
|
+
themeName: ThemeName;
|
|
66
|
+
setTheme: (themeName: ThemeName) => void;
|
|
67
|
+
colorMode: ColorMode;
|
|
68
|
+
setColorMode: (mode: ColorMode) => void;
|
|
69
|
+
resolvedColorMode: 'light' | 'dark';
|
|
70
|
+
}
|
|
71
|
+
declare function useTheme(): ThemeContextValue;
|
|
72
|
+
interface ThemeProviderProps {
|
|
73
|
+
children: React.ReactNode;
|
|
74
|
+
defaultTheme?: ThemeName;
|
|
75
|
+
defaultColorMode?: ColorMode;
|
|
76
|
+
}
|
|
77
|
+
declare function ThemeProvider({ children, defaultTheme, defaultColorMode }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Theme initialization script that runs before React hydration
|
|
81
|
+
* This prevents flickering by setting the theme before the page renders
|
|
82
|
+
* Must be inlined in the HTML <head> as a blocking script
|
|
83
|
+
*/
|
|
84
|
+
declare const themeScript = "\n(function() {\n try {\n // Get stored preferences\n const storedTheme = localStorage.getItem('lite-ui-theme') || 'default';\n const storedColorMode = localStorage.getItem('lite-ui-color-mode');\n\n // Determine color mode (system, light, or dark)\n let colorMode = storedColorMode;\n if (!colorMode || colorMode === 'system') {\n colorMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n\n // Set attributes before render\n document.documentElement.setAttribute('data-theme', storedTheme);\n document.documentElement.setAttribute('data-color-mode', colorMode);\n\n // Add dark class for Tailwind\n if (colorMode === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n } catch (e) {\n console.error('Failed to initialize theme:', e);\n }\n})();\n";
|
|
85
|
+
declare function getThemeScript(): string;
|
|
86
|
+
|
|
87
|
+
export { Button, type ButtonProps, type ButtonTheme, type ColorMode, Select, type SelectOption, type SelectProps, type SelectTheme, type Theme, type ThemeName, ThemeProvider, getThemeScript, themeScript, themes, useTheme };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';
|
|
6
|
+
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
declare const Button: React.FC<ButtonProps>;
|
|
10
|
+
|
|
11
|
+
interface SelectOption {
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}
|
|
15
|
+
interface SelectProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'size' | 'onChange' | 'defaultValue'> {
|
|
16
|
+
options: SelectOption[];
|
|
17
|
+
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
value?: string;
|
|
21
|
+
defaultValue?: string;
|
|
22
|
+
onChange?: (value: string) => void;
|
|
23
|
+
}
|
|
24
|
+
declare const Select: React.FC<SelectProps>;
|
|
25
|
+
|
|
26
|
+
type ThemeName = 'default' | 'minimalistic';
|
|
27
|
+
interface ButtonTheme {
|
|
28
|
+
primary: string;
|
|
29
|
+
secondary: string;
|
|
30
|
+
success: string;
|
|
31
|
+
danger: string;
|
|
32
|
+
warning: string;
|
|
33
|
+
info: string;
|
|
34
|
+
}
|
|
35
|
+
interface SelectTheme {
|
|
36
|
+
base: string;
|
|
37
|
+
sizes: {
|
|
38
|
+
sm: string;
|
|
39
|
+
md: string;
|
|
40
|
+
lg: string;
|
|
41
|
+
xl: string;
|
|
42
|
+
};
|
|
43
|
+
disabled: string;
|
|
44
|
+
}
|
|
45
|
+
interface Theme {
|
|
46
|
+
name: ThemeName;
|
|
47
|
+
button: {
|
|
48
|
+
base: string;
|
|
49
|
+
variants: ButtonTheme;
|
|
50
|
+
sizes: {
|
|
51
|
+
sm: string;
|
|
52
|
+
md: string;
|
|
53
|
+
lg: string;
|
|
54
|
+
xl: string;
|
|
55
|
+
};
|
|
56
|
+
disabled: string;
|
|
57
|
+
};
|
|
58
|
+
select: SelectTheme;
|
|
59
|
+
}
|
|
60
|
+
declare const themes: Record<ThemeName, Theme>;
|
|
61
|
+
|
|
62
|
+
type ColorMode = 'light' | 'dark' | 'system';
|
|
63
|
+
interface ThemeContextValue {
|
|
64
|
+
theme: Theme;
|
|
65
|
+
themeName: ThemeName;
|
|
66
|
+
setTheme: (themeName: ThemeName) => void;
|
|
67
|
+
colorMode: ColorMode;
|
|
68
|
+
setColorMode: (mode: ColorMode) => void;
|
|
69
|
+
resolvedColorMode: 'light' | 'dark';
|
|
70
|
+
}
|
|
71
|
+
declare function useTheme(): ThemeContextValue;
|
|
72
|
+
interface ThemeProviderProps {
|
|
73
|
+
children: React.ReactNode;
|
|
74
|
+
defaultTheme?: ThemeName;
|
|
75
|
+
defaultColorMode?: ColorMode;
|
|
76
|
+
}
|
|
77
|
+
declare function ThemeProvider({ children, defaultTheme, defaultColorMode }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Theme initialization script that runs before React hydration
|
|
81
|
+
* This prevents flickering by setting the theme before the page renders
|
|
82
|
+
* Must be inlined in the HTML <head> as a blocking script
|
|
83
|
+
*/
|
|
84
|
+
declare const themeScript = "\n(function() {\n try {\n // Get stored preferences\n const storedTheme = localStorage.getItem('lite-ui-theme') || 'default';\n const storedColorMode = localStorage.getItem('lite-ui-color-mode');\n\n // Determine color mode (system, light, or dark)\n let colorMode = storedColorMode;\n if (!colorMode || colorMode === 'system') {\n colorMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n\n // Set attributes before render\n document.documentElement.setAttribute('data-theme', storedTheme);\n document.documentElement.setAttribute('data-color-mode', colorMode);\n\n // Add dark class for Tailwind\n if (colorMode === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n } catch (e) {\n console.error('Failed to initialize theme:', e);\n }\n})();\n";
|
|
85
|
+
declare function getThemeScript(): string;
|
|
86
|
+
|
|
87
|
+
export { Button, type ButtonProps, type ButtonTheme, type ColorMode, Select, type SelectOption, type SelectProps, type SelectTheme, type Theme, type ThemeName, ThemeProvider, getThemeScript, themeScript, themes, useTheme };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
Button: () => Button,
|
|
25
|
+
Select: () => Select,
|
|
26
|
+
ThemeProvider: () => ThemeProvider,
|
|
27
|
+
getThemeScript: () => getThemeScript,
|
|
28
|
+
themeScript: () => themeScript,
|
|
29
|
+
themes: () => themes,
|
|
30
|
+
useTheme: () => useTheme
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(index_exports);
|
|
33
|
+
|
|
34
|
+
// src/theme/ThemeProvider.tsx
|
|
35
|
+
var import_react = require("react");
|
|
36
|
+
|
|
37
|
+
// src/theme/themes.ts
|
|
38
|
+
var themes = {
|
|
39
|
+
default: {
|
|
40
|
+
name: "default",
|
|
41
|
+
button: {
|
|
42
|
+
base: "font-semibold rounded-lg transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 active:scale-95",
|
|
43
|
+
variants: {
|
|
44
|
+
primary: "bg-blue-600 hover:bg-blue-700 active:bg-blue-800 text-white shadow-sm hover:shadow-md dark:bg-blue-500 dark:hover:bg-blue-600 dark:active:bg-blue-700",
|
|
45
|
+
secondary: "bg-gray-600 hover:bg-gray-700 active:bg-gray-800 text-white shadow-sm hover:shadow-md dark:bg-gray-500 dark:hover:bg-gray-600 dark:active:bg-gray-700",
|
|
46
|
+
success: "bg-green-600 hover:bg-green-700 active:bg-green-800 text-white shadow-sm hover:shadow-md dark:bg-green-500 dark:hover:bg-green-600 dark:active:bg-green-700",
|
|
47
|
+
danger: "bg-red-600 hover:bg-red-700 active:bg-red-800 text-white shadow-sm hover:shadow-md dark:bg-red-500 dark:hover:bg-red-600 dark:active:bg-red-700",
|
|
48
|
+
warning: "bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white shadow-sm hover:shadow-md dark:bg-yellow-400 dark:hover:bg-yellow-500 dark:active:bg-yellow-600",
|
|
49
|
+
info: "bg-cyan-600 hover:bg-cyan-700 active:bg-cyan-800 text-white shadow-sm hover:shadow-md dark:bg-cyan-500 dark:hover:bg-cyan-600 dark:active:bg-cyan-700"
|
|
50
|
+
},
|
|
51
|
+
sizes: {
|
|
52
|
+
sm: "px-3 py-1.5 text-sm",
|
|
53
|
+
md: "px-4 py-2 text-base",
|
|
54
|
+
lg: "px-6 py-3 text-lg",
|
|
55
|
+
xl: "px-8 py-4 text-xl"
|
|
56
|
+
},
|
|
57
|
+
disabled: "opacity-50 cursor-not-allowed hover:shadow-sm active:scale-100"
|
|
58
|
+
},
|
|
59
|
+
select: {
|
|
60
|
+
base: "w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 pr-10 cursor-pointer dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500",
|
|
61
|
+
sizes: {
|
|
62
|
+
sm: "px-3 py-1.5 text-sm",
|
|
63
|
+
md: "px-4 py-2.5 text-base",
|
|
64
|
+
lg: "px-4 py-3 text-lg",
|
|
65
|
+
xl: "px-5 py-4 text-xl"
|
|
66
|
+
},
|
|
67
|
+
disabled: "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
minimalistic: {
|
|
71
|
+
name: "minimalistic",
|
|
72
|
+
button: {
|
|
73
|
+
base: "font-normal rounded-none transition-colors duration-200 focus:outline-none border-2",
|
|
74
|
+
variants: {
|
|
75
|
+
primary: "bg-transparent border-white text-white hover:bg-white hover:text-black",
|
|
76
|
+
secondary: "bg-transparent border-gray-400 text-gray-400 hover:bg-gray-400 hover:text-black",
|
|
77
|
+
success: "bg-transparent border-green-400 text-green-400 hover:bg-green-400 hover:text-black",
|
|
78
|
+
danger: "bg-transparent border-red-400 text-red-400 hover:bg-red-400 hover:text-black",
|
|
79
|
+
warning: "bg-transparent border-yellow-400 text-yellow-400 hover:bg-yellow-400 hover:text-black",
|
|
80
|
+
info: "bg-transparent border-blue-400 text-blue-400 hover:bg-blue-400 hover:text-black"
|
|
81
|
+
},
|
|
82
|
+
sizes: {
|
|
83
|
+
sm: "px-4 py-2 text-sm uppercase tracking-wide",
|
|
84
|
+
md: "px-6 py-3 text-base uppercase tracking-wide",
|
|
85
|
+
lg: "px-8 py-4 text-lg uppercase tracking-wider",
|
|
86
|
+
xl: "px-10 py-5 text-xl uppercase tracking-wider"
|
|
87
|
+
},
|
|
88
|
+
disabled: "opacity-30 cursor-not-allowed hover:bg-transparent"
|
|
89
|
+
},
|
|
90
|
+
select: {
|
|
91
|
+
base: "w-full appearance-none rounded-none border-2 border-white bg-transparent text-white transition-colors duration-200 focus:outline-none pr-10 cursor-pointer placeholder:text-gray-500",
|
|
92
|
+
sizes: {
|
|
93
|
+
sm: "px-4 py-2 text-sm uppercase tracking-wide",
|
|
94
|
+
md: "px-4 py-3 text-base uppercase tracking-wide",
|
|
95
|
+
lg: "px-4 py-4 text-lg uppercase tracking-wider",
|
|
96
|
+
xl: "px-5 py-5 text-xl uppercase tracking-wider"
|
|
97
|
+
},
|
|
98
|
+
disabled: "opacity-30 cursor-not-allowed"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/theme/ThemeProvider.tsx
|
|
104
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
105
|
+
var ThemeContext = (0, import_react.createContext)(void 0);
|
|
106
|
+
function useTheme() {
|
|
107
|
+
const context = (0, import_react.useContext)(ThemeContext);
|
|
108
|
+
if (!context) {
|
|
109
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
110
|
+
}
|
|
111
|
+
return context;
|
|
112
|
+
}
|
|
113
|
+
function ThemeProvider({
|
|
114
|
+
children,
|
|
115
|
+
defaultTheme = "default",
|
|
116
|
+
defaultColorMode = "system"
|
|
117
|
+
}) {
|
|
118
|
+
const [mounted, setMounted] = (0, import_react.useState)(false);
|
|
119
|
+
const [themeName, setThemeNameState] = (0, import_react.useState)(defaultTheme);
|
|
120
|
+
const [colorMode, setColorModeState] = (0, import_react.useState)(defaultColorMode);
|
|
121
|
+
const [resolvedColorMode, setResolvedColorMode] = (0, import_react.useState)("light");
|
|
122
|
+
(0, import_react.useEffect)(() => {
|
|
123
|
+
setMounted(true);
|
|
124
|
+
const storedTheme = localStorage.getItem("lite-ui-theme");
|
|
125
|
+
const storedColorMode = localStorage.getItem("lite-ui-color-mode");
|
|
126
|
+
const currentColorMode = document.documentElement.getAttribute("data-color-mode");
|
|
127
|
+
if (storedTheme) setThemeNameState(storedTheme);
|
|
128
|
+
if (storedColorMode) setColorModeState(storedColorMode);
|
|
129
|
+
if (currentColorMode) setResolvedColorMode(currentColorMode);
|
|
130
|
+
}, []);
|
|
131
|
+
const theme = themes[themeName];
|
|
132
|
+
const setTheme = (newThemeName) => {
|
|
133
|
+
setThemeNameState(newThemeName);
|
|
134
|
+
if (typeof window !== "undefined") {
|
|
135
|
+
localStorage.setItem("lite-ui-theme", newThemeName);
|
|
136
|
+
document.documentElement.setAttribute("data-theme", newThemeName);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
const setColorMode = (mode) => {
|
|
140
|
+
if (typeof window === "undefined") return;
|
|
141
|
+
setColorModeState(mode);
|
|
142
|
+
localStorage.setItem("lite-ui-color-mode", mode);
|
|
143
|
+
let resolved;
|
|
144
|
+
if (mode === "system") {
|
|
145
|
+
resolved = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
146
|
+
} else {
|
|
147
|
+
resolved = mode;
|
|
148
|
+
}
|
|
149
|
+
setResolvedColorMode(resolved);
|
|
150
|
+
document.documentElement.setAttribute("data-color-mode", resolved);
|
|
151
|
+
if (resolved === "dark") {
|
|
152
|
+
document.documentElement.classList.add("dark");
|
|
153
|
+
} else {
|
|
154
|
+
document.documentElement.classList.remove("dark");
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
(0, import_react.useEffect)(() => {
|
|
158
|
+
if (!mounted) return;
|
|
159
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
160
|
+
const handleChange = (e) => {
|
|
161
|
+
if (colorMode === "system") {
|
|
162
|
+
const resolved = e.matches ? "dark" : "light";
|
|
163
|
+
setResolvedColorMode(resolved);
|
|
164
|
+
document.documentElement.setAttribute("data-color-mode", resolved);
|
|
165
|
+
if (resolved === "dark") {
|
|
166
|
+
document.documentElement.classList.add("dark");
|
|
167
|
+
} else {
|
|
168
|
+
document.documentElement.classList.remove("dark");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
173
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
174
|
+
}, [mounted, colorMode]);
|
|
175
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: {
|
|
176
|
+
theme,
|
|
177
|
+
themeName,
|
|
178
|
+
setTheme,
|
|
179
|
+
colorMode,
|
|
180
|
+
setColorMode,
|
|
181
|
+
resolvedColorMode
|
|
182
|
+
}, children });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/components/Button.tsx
|
|
186
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
187
|
+
var Button = ({
|
|
188
|
+
variant = "primary",
|
|
189
|
+
size = "md",
|
|
190
|
+
className = "",
|
|
191
|
+
children,
|
|
192
|
+
disabled,
|
|
193
|
+
...props
|
|
194
|
+
}) => {
|
|
195
|
+
const { theme } = useTheme();
|
|
196
|
+
const baseStyles = theme.button.base;
|
|
197
|
+
const variantStyles = theme.button.variants[variant];
|
|
198
|
+
const sizeStyles = theme.button.sizes[size];
|
|
199
|
+
const disabledStyles = disabled ? theme.button.disabled : "";
|
|
200
|
+
const classes = `${baseStyles} ${variantStyles} ${sizeStyles} ${disabledStyles} ${className}`.trim();
|
|
201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
202
|
+
"button",
|
|
203
|
+
{
|
|
204
|
+
className: classes,
|
|
205
|
+
disabled,
|
|
206
|
+
...props,
|
|
207
|
+
children
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// src/components/Select.tsx
|
|
213
|
+
var import_react2 = require("react");
|
|
214
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
215
|
+
var Select = ({
|
|
216
|
+
options,
|
|
217
|
+
size = "md",
|
|
218
|
+
placeholder,
|
|
219
|
+
className = "",
|
|
220
|
+
disabled,
|
|
221
|
+
value: controlledValue,
|
|
222
|
+
defaultValue,
|
|
223
|
+
onChange,
|
|
224
|
+
...props
|
|
225
|
+
}) => {
|
|
226
|
+
const { theme, themeName } = useTheme();
|
|
227
|
+
const [isOpen, setIsOpen] = (0, import_react2.useState)(false);
|
|
228
|
+
const [internalValue, setInternalValue] = (0, import_react2.useState)(defaultValue || "");
|
|
229
|
+
const dropdownRef = (0, import_react2.useRef)(null);
|
|
230
|
+
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
231
|
+
const selectedOption = options.find((opt) => opt.value === value);
|
|
232
|
+
const displayText = selectedOption ? selectedOption.label : placeholder || "Select...";
|
|
233
|
+
(0, import_react2.useEffect)(() => {
|
|
234
|
+
const handleClickOutside = (event) => {
|
|
235
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
236
|
+
setIsOpen(false);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
if (isOpen) {
|
|
240
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
241
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
242
|
+
}
|
|
243
|
+
}, [isOpen]);
|
|
244
|
+
const handleSelect = (optionValue) => {
|
|
245
|
+
if (disabled) return;
|
|
246
|
+
setInternalValue(optionValue);
|
|
247
|
+
onChange?.(optionValue);
|
|
248
|
+
setIsOpen(false);
|
|
249
|
+
};
|
|
250
|
+
const handleToggle = () => {
|
|
251
|
+
if (!disabled) {
|
|
252
|
+
setIsOpen(!isOpen);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const baseStyles = theme.select.base;
|
|
256
|
+
const sizeStyles = theme.select.sizes[size];
|
|
257
|
+
const disabledStyles = disabled ? theme.select.disabled : "";
|
|
258
|
+
const buttonClasses = `${baseStyles} ${sizeStyles} ${disabledStyles} ${className}`.trim();
|
|
259
|
+
const iconColor = themeName === "minimalistic" ? disabled ? "text-gray-600" : "text-white" : disabled ? "text-gray-400" : "text-gray-500";
|
|
260
|
+
const dropdownBaseStyles = themeName === "minimalistic" ? "bg-black border-2 border-white" : "bg-white border border-gray-300 shadow-lg dark:bg-gray-800 dark:border-gray-600";
|
|
261
|
+
const optionBaseStyles = themeName === "minimalistic" ? "text-white hover:bg-white hover:text-black transition-colors duration-200" : "text-gray-900 hover:bg-blue-50 transition-colors duration-150 dark:text-gray-100 dark:hover:bg-gray-700";
|
|
262
|
+
const optionSizeStyles = {
|
|
263
|
+
sm: "px-4 py-2 text-sm",
|
|
264
|
+
md: "px-4 py-2.5 text-base",
|
|
265
|
+
lg: "px-4 py-3 text-lg",
|
|
266
|
+
xl: "px-5 py-4 text-xl"
|
|
267
|
+
}[size];
|
|
268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative inline-block w-full", ref: dropdownRef, ...props, children: [
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
270
|
+
"button",
|
|
271
|
+
{
|
|
272
|
+
type: "button",
|
|
273
|
+
className: buttonClasses,
|
|
274
|
+
onClick: handleToggle,
|
|
275
|
+
disabled,
|
|
276
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: !selectedOption && placeholder ? "opacity-50" : "", children: displayText })
|
|
277
|
+
}
|
|
278
|
+
),
|
|
279
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-4", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
280
|
+
"svg",
|
|
281
|
+
{
|
|
282
|
+
className: `h-5 w-5 transition-transform duration-200 ${iconColor} ${isOpen ? "rotate-180" : ""}`,
|
|
283
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
284
|
+
viewBox: "0 0 20 20",
|
|
285
|
+
fill: "currentColor",
|
|
286
|
+
"aria-hidden": "true",
|
|
287
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
288
|
+
"path",
|
|
289
|
+
{
|
|
290
|
+
fillRule: "evenodd",
|
|
291
|
+
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
|
292
|
+
clipRule: "evenodd"
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
}
|
|
296
|
+
) }),
|
|
297
|
+
isOpen && !disabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
298
|
+
"div",
|
|
299
|
+
{
|
|
300
|
+
className: `absolute z-50 w-full mt-1 ${dropdownBaseStyles} rounded-lg overflow-hidden`,
|
|
301
|
+
style: { maxHeight: "300px", overflowY: "auto" },
|
|
302
|
+
children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
303
|
+
"div",
|
|
304
|
+
{
|
|
305
|
+
className: `${optionBaseStyles} ${optionSizeStyles} cursor-pointer ${value === option.value ? themeName === "minimalistic" ? "bg-white text-black" : "bg-blue-100 dark:bg-blue-900" : ""}`,
|
|
306
|
+
onClick: () => handleSelect(option.value),
|
|
307
|
+
children: option.label
|
|
308
|
+
},
|
|
309
|
+
option.value
|
|
310
|
+
))
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
] });
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// src/utils/theme-script.ts
|
|
317
|
+
var themeScript = `
|
|
318
|
+
(function() {
|
|
319
|
+
try {
|
|
320
|
+
// Get stored preferences
|
|
321
|
+
const storedTheme = localStorage.getItem('lite-ui-theme') || 'default';
|
|
322
|
+
const storedColorMode = localStorage.getItem('lite-ui-color-mode');
|
|
323
|
+
|
|
324
|
+
// Determine color mode (system, light, or dark)
|
|
325
|
+
let colorMode = storedColorMode;
|
|
326
|
+
if (!colorMode || colorMode === 'system') {
|
|
327
|
+
colorMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Set attributes before render
|
|
331
|
+
document.documentElement.setAttribute('data-theme', storedTheme);
|
|
332
|
+
document.documentElement.setAttribute('data-color-mode', colorMode);
|
|
333
|
+
|
|
334
|
+
// Add dark class for Tailwind
|
|
335
|
+
if (colorMode === 'dark') {
|
|
336
|
+
document.documentElement.classList.add('dark');
|
|
337
|
+
} else {
|
|
338
|
+
document.documentElement.classList.remove('dark');
|
|
339
|
+
}
|
|
340
|
+
} catch (e) {
|
|
341
|
+
console.error('Failed to initialize theme:', e);
|
|
342
|
+
}
|
|
343
|
+
})();
|
|
344
|
+
`;
|
|
345
|
+
function getThemeScript() {
|
|
346
|
+
return themeScript;
|
|
347
|
+
}
|
|
348
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
349
|
+
0 && (module.exports = {
|
|
350
|
+
Button,
|
|
351
|
+
Select,
|
|
352
|
+
ThemeProvider,
|
|
353
|
+
getThemeScript,
|
|
354
|
+
themeScript,
|
|
355
|
+
themes,
|
|
356
|
+
useTheme
|
|
357
|
+
});
|
|
358
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/theme/ThemeProvider.tsx","../src/theme/themes.ts","../src/components/Button.tsx","../src/components/Select.tsx","../src/utils/theme-script.ts"],"sourcesContent":["export { Button } from './components/Button';\nexport type { ButtonProps } from './components/Button';\n\nexport { Select } from './components/Select';\nexport type { SelectProps, SelectOption } from './components/Select';\n\nexport { ThemeProvider, useTheme } from './theme/ThemeProvider';\nexport type { ColorMode } from './theme/ThemeProvider';\nexport { themes } from './theme/themes';\nexport type { ThemeName, Theme, ButtonTheme, SelectTheme } from './theme/themes';\n\nexport { themeScript, getThemeScript } from './utils/theme-script';\n","\"use client\";\n\nimport React, { createContext, useContext, useState, useEffect } from 'react';\nimport { themes, ThemeName, Theme } from './themes';\n\nexport type ColorMode = 'light' | 'dark' | 'system';\n\ninterface ThemeContextValue {\n theme: Theme;\n themeName: ThemeName;\n setTheme: (themeName: ThemeName) => void;\n colorMode: ColorMode;\n setColorMode: (mode: ColorMode) => void;\n resolvedColorMode: 'light' | 'dark';\n}\n\nconst ThemeContext = createContext<ThemeContextValue | undefined>(undefined);\n\nexport function useTheme() {\n const context = useContext(ThemeContext);\n if (!context) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n return context;\n}\n\ninterface ThemeProviderProps {\n children: React.ReactNode;\n defaultTheme?: ThemeName;\n defaultColorMode?: ColorMode;\n}\n\nexport function ThemeProvider({\n children,\n defaultTheme = 'default',\n defaultColorMode = 'system'\n}: ThemeProviderProps) {\n const [mounted, setMounted] = useState(false);\n\n // Initialize from defaults (will sync with actual values after mount)\n const [themeName, setThemeNameState] = useState<ThemeName>(defaultTheme);\n const [colorMode, setColorModeState] = useState<ColorMode>(defaultColorMode);\n const [resolvedColorMode, setResolvedColorMode] = useState<'light' | 'dark'>('light');\n\n // Sync with actual values after mount to avoid hydration mismatch\n useEffect(() => {\n setMounted(true);\n\n // Read actual values from localStorage and DOM\n const storedTheme = localStorage.getItem('lite-ui-theme') as ThemeName;\n const storedColorMode = localStorage.getItem('lite-ui-color-mode') as ColorMode;\n const currentColorMode = document.documentElement.getAttribute('data-color-mode') as 'light' | 'dark';\n\n if (storedTheme) setThemeNameState(storedTheme);\n if (storedColorMode) setColorModeState(storedColorMode);\n if (currentColorMode) setResolvedColorMode(currentColorMode);\n }, []);\n\n const theme = themes[themeName];\n\n // Update theme\n const setTheme = (newThemeName: ThemeName) => {\n setThemeNameState(newThemeName);\n if (typeof window !== 'undefined') {\n localStorage.setItem('lite-ui-theme', newThemeName);\n document.documentElement.setAttribute('data-theme', newThemeName);\n }\n };\n\n // Update color mode\n const setColorMode = (mode: ColorMode) => {\n if (typeof window === 'undefined') return;\n\n setColorModeState(mode);\n localStorage.setItem('lite-ui-color-mode', mode);\n\n let resolved: 'light' | 'dark';\n if (mode === 'system') {\n resolved = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n } else {\n resolved = mode;\n }\n\n setResolvedColorMode(resolved);\n document.documentElement.setAttribute('data-color-mode', resolved);\n\n if (resolved === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n };\n\n // Listen for system theme changes\n useEffect(() => {\n if (!mounted) return;\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n\n const handleChange = (e: MediaQueryListEvent) => {\n if (colorMode === 'system') {\n const resolved = e.matches ? 'dark' : 'light';\n setResolvedColorMode(resolved);\n document.documentElement.setAttribute('data-color-mode', resolved);\n\n if (resolved === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n }\n };\n\n mediaQuery.addEventListener('change', handleChange);\n return () => mediaQuery.removeEventListener('change', handleChange);\n }, [mounted, colorMode]);\n\n return (\n <ThemeContext.Provider value={{\n theme,\n themeName,\n setTheme,\n colorMode,\n setColorMode,\n resolvedColorMode\n }}>\n {children}\n </ThemeContext.Provider>\n );\n}\n","export type ThemeName = 'default' | 'minimalistic';\n\nexport interface ButtonTheme {\n primary: string;\n secondary: string;\n success: string;\n danger: string;\n warning: string;\n info: string;\n}\n\nexport interface SelectTheme {\n base: string;\n sizes: {\n sm: string;\n md: string;\n lg: string;\n xl: string;\n };\n disabled: string;\n}\n\nexport interface Theme {\n name: ThemeName;\n button: {\n base: string;\n variants: ButtonTheme;\n sizes: {\n sm: string;\n md: string;\n lg: string;\n xl: string;\n };\n disabled: string;\n };\n select: SelectTheme;\n}\n\nexport const themes: Record<ThemeName, Theme> = {\n default: {\n name: 'default',\n button: {\n base: 'font-semibold rounded-lg transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 active:scale-95',\n variants: {\n primary: 'bg-blue-600 hover:bg-blue-700 active:bg-blue-800 text-white shadow-sm hover:shadow-md dark:bg-blue-500 dark:hover:bg-blue-600 dark:active:bg-blue-700',\n secondary: 'bg-gray-600 hover:bg-gray-700 active:bg-gray-800 text-white shadow-sm hover:shadow-md dark:bg-gray-500 dark:hover:bg-gray-600 dark:active:bg-gray-700',\n success: 'bg-green-600 hover:bg-green-700 active:bg-green-800 text-white shadow-sm hover:shadow-md dark:bg-green-500 dark:hover:bg-green-600 dark:active:bg-green-700',\n danger: 'bg-red-600 hover:bg-red-700 active:bg-red-800 text-white shadow-sm hover:shadow-md dark:bg-red-500 dark:hover:bg-red-600 dark:active:bg-red-700',\n warning: 'bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white shadow-sm hover:shadow-md dark:bg-yellow-400 dark:hover:bg-yellow-500 dark:active:bg-yellow-600',\n info: 'bg-cyan-600 hover:bg-cyan-700 active:bg-cyan-800 text-white shadow-sm hover:shadow-md dark:bg-cyan-500 dark:hover:bg-cyan-600 dark:active:bg-cyan-700',\n },\n sizes: {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2 text-base',\n lg: 'px-6 py-3 text-lg',\n xl: 'px-8 py-4 text-xl',\n },\n disabled: 'opacity-50 cursor-not-allowed hover:shadow-sm active:scale-100',\n },\n select: {\n base: 'w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 pr-10 cursor-pointer dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500',\n sizes: {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2.5 text-base',\n lg: 'px-4 py-3 text-lg',\n xl: 'px-5 py-4 text-xl',\n },\n disabled: 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900',\n },\n },\n minimalistic: {\n name: 'minimalistic',\n button: {\n base: 'font-normal rounded-none transition-colors duration-200 focus:outline-none border-2',\n variants: {\n primary: 'bg-transparent border-white text-white hover:bg-white hover:text-black',\n secondary: 'bg-transparent border-gray-400 text-gray-400 hover:bg-gray-400 hover:text-black',\n success: 'bg-transparent border-green-400 text-green-400 hover:bg-green-400 hover:text-black',\n danger: 'bg-transparent border-red-400 text-red-400 hover:bg-red-400 hover:text-black',\n warning: 'bg-transparent border-yellow-400 text-yellow-400 hover:bg-yellow-400 hover:text-black',\n info: 'bg-transparent border-blue-400 text-blue-400 hover:bg-blue-400 hover:text-black',\n },\n sizes: {\n sm: 'px-4 py-2 text-sm uppercase tracking-wide',\n md: 'px-6 py-3 text-base uppercase tracking-wide',\n lg: 'px-8 py-4 text-lg uppercase tracking-wider',\n xl: 'px-10 py-5 text-xl uppercase tracking-wider',\n },\n disabled: 'opacity-30 cursor-not-allowed hover:bg-transparent',\n },\n select: {\n base: 'w-full appearance-none rounded-none border-2 border-white bg-transparent text-white transition-colors duration-200 focus:outline-none pr-10 cursor-pointer placeholder:text-gray-500',\n sizes: {\n sm: 'px-4 py-2 text-sm uppercase tracking-wide',\n md: 'px-4 py-3 text-base uppercase tracking-wide',\n lg: 'px-4 py-4 text-lg uppercase tracking-wider',\n xl: 'px-5 py-5 text-xl uppercase tracking-wider',\n },\n disabled: 'opacity-30 cursor-not-allowed',\n },\n },\n};\n","\"use client\";\n\nimport React from 'react';\nimport { useTheme } from '../theme/ThemeProvider';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';\n size?: 'sm' | 'md' | 'lg' | 'xl';\n children: React.ReactNode;\n}\n\nexport const Button: React.FC<ButtonProps> = ({\n variant = 'primary',\n size = 'md',\n className = '',\n children,\n disabled,\n ...props\n}) => {\n const { theme } = useTheme();\n\n const baseStyles = theme.button.base;\n const variantStyles = theme.button.variants[variant];\n const sizeStyles = theme.button.sizes[size];\n const disabledStyles = disabled ? theme.button.disabled : '';\n\n const classes = `${baseStyles} ${variantStyles} ${sizeStyles} ${disabledStyles} ${className}`.trim();\n\n return (\n <button\n className={classes}\n disabled={disabled}\n {...props}\n >\n {children}\n </button>\n );\n};\n","\"use client\";\n\nimport React, { useState, useRef, useEffect } from 'react';\nimport { useTheme } from '../theme/ThemeProvider';\n\nexport interface SelectOption {\n value: string;\n label: string;\n}\n\nexport interface SelectProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'size' | 'onChange' | 'defaultValue'> {\n options: SelectOption[];\n size?: 'sm' | 'md' | 'lg' | 'xl';\n placeholder?: string;\n disabled?: boolean;\n value?: string;\n defaultValue?: string;\n onChange?: (value: string) => void;\n}\n\nexport const Select: React.FC<SelectProps> = ({\n options,\n size = 'md',\n placeholder,\n className = '',\n disabled,\n value: controlledValue,\n defaultValue,\n onChange,\n ...props\n}) => {\n const { theme, themeName } = useTheme();\n const [isOpen, setIsOpen] = useState(false);\n const [internalValue, setInternalValue] = useState(defaultValue || '');\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Use controlled value if provided, otherwise use internal state\n const value = controlledValue !== undefined ? controlledValue : internalValue;\n\n // Find the selected option\n const selectedOption = options.find(opt => opt.value === value);\n const displayText = selectedOption ? selectedOption.label : placeholder || 'Select...';\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n const handleSelect = (optionValue: string) => {\n if (disabled) return;\n\n setInternalValue(optionValue);\n onChange?.(optionValue);\n setIsOpen(false);\n };\n\n const handleToggle = () => {\n if (!disabled) {\n setIsOpen(!isOpen);\n }\n };\n\n const baseStyles = theme.select.base;\n const sizeStyles = theme.select.sizes[size];\n const disabledStyles = disabled ? theme.select.disabled : '';\n\n const buttonClasses = `${baseStyles} ${sizeStyles} ${disabledStyles} ${className}`.trim();\n\n // Icon color based on theme\n const iconColor = themeName === 'minimalistic'\n ? (disabled ? 'text-gray-600' : 'text-white')\n : (disabled ? 'text-gray-400' : 'text-gray-500');\n\n // Dropdown menu styles based on theme\n const dropdownBaseStyles = themeName === 'minimalistic'\n ? 'bg-black border-2 border-white'\n : 'bg-white border border-gray-300 shadow-lg dark:bg-gray-800 dark:border-gray-600';\n\n const optionBaseStyles = themeName === 'minimalistic'\n ? 'text-white hover:bg-white hover:text-black transition-colors duration-200'\n : 'text-gray-900 hover:bg-blue-50 transition-colors duration-150 dark:text-gray-100 dark:hover:bg-gray-700';\n\n const optionSizeStyles = {\n sm: 'px-4 py-2 text-sm',\n md: 'px-4 py-2.5 text-base',\n lg: 'px-4 py-3 text-lg',\n xl: 'px-5 py-4 text-xl',\n }[size];\n\n return (\n <div className=\"relative inline-block w-full\" ref={dropdownRef} {...props}>\n {/* Custom button that looks like select */}\n <button\n type=\"button\"\n className={buttonClasses}\n onClick={handleToggle}\n disabled={disabled}\n >\n <span className={!selectedOption && placeholder ? 'opacity-50' : ''}>\n {displayText}\n </span>\n </button>\n\n {/* Chevron icon */}\n <div className=\"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-4\">\n <svg\n className={`h-5 w-5 transition-transform duration-200 ${iconColor} ${isOpen ? 'rotate-180' : ''}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </div>\n\n {/* Custom dropdown menu */}\n {isOpen && !disabled && (\n <div\n className={`absolute z-50 w-full mt-1 ${dropdownBaseStyles} rounded-lg overflow-hidden`}\n style={{ maxHeight: '300px', overflowY: 'auto' }}\n >\n {options.map((option) => (\n <div\n key={option.value}\n className={`${optionBaseStyles} ${optionSizeStyles} cursor-pointer ${\n value === option.value ? (themeName === 'minimalistic' ? 'bg-white text-black' : 'bg-blue-100 dark:bg-blue-900') : ''\n }`}\n onClick={() => handleSelect(option.value)}\n >\n {option.label}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n};\n","/**\n * Theme initialization script that runs before React hydration\n * This prevents flickering by setting the theme before the page renders\n * Must be inlined in the HTML <head> as a blocking script\n */\n\nexport const themeScript = `\n(function() {\n try {\n // Get stored preferences\n const storedTheme = localStorage.getItem('lite-ui-theme') || 'default';\n const storedColorMode = localStorage.getItem('lite-ui-color-mode');\n\n // Determine color mode (system, light, or dark)\n let colorMode = storedColorMode;\n if (!colorMode || colorMode === 'system') {\n colorMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n\n // Set attributes before render\n document.documentElement.setAttribute('data-theme', storedTheme);\n document.documentElement.setAttribute('data-color-mode', colorMode);\n\n // Add dark class for Tailwind\n if (colorMode === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n } catch (e) {\n console.error('Failed to initialize theme:', e);\n }\n})();\n`;\n\nexport function getThemeScript() {\n return themeScript;\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_react","import_jsx_runtime"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/theme/ThemeProvider.tsx
|
|
4
|
+
import { createContext, useContext, useState, useEffect } from "react";
|
|
5
|
+
|
|
6
|
+
// src/theme/themes.ts
|
|
7
|
+
var themes = {
|
|
8
|
+
default: {
|
|
9
|
+
name: "default",
|
|
10
|
+
button: {
|
|
11
|
+
base: "font-semibold rounded-lg transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 active:scale-95",
|
|
12
|
+
variants: {
|
|
13
|
+
primary: "bg-blue-600 hover:bg-blue-700 active:bg-blue-800 text-white shadow-sm hover:shadow-md dark:bg-blue-500 dark:hover:bg-blue-600 dark:active:bg-blue-700",
|
|
14
|
+
secondary: "bg-gray-600 hover:bg-gray-700 active:bg-gray-800 text-white shadow-sm hover:shadow-md dark:bg-gray-500 dark:hover:bg-gray-600 dark:active:bg-gray-700",
|
|
15
|
+
success: "bg-green-600 hover:bg-green-700 active:bg-green-800 text-white shadow-sm hover:shadow-md dark:bg-green-500 dark:hover:bg-green-600 dark:active:bg-green-700",
|
|
16
|
+
danger: "bg-red-600 hover:bg-red-700 active:bg-red-800 text-white shadow-sm hover:shadow-md dark:bg-red-500 dark:hover:bg-red-600 dark:active:bg-red-700",
|
|
17
|
+
warning: "bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white shadow-sm hover:shadow-md dark:bg-yellow-400 dark:hover:bg-yellow-500 dark:active:bg-yellow-600",
|
|
18
|
+
info: "bg-cyan-600 hover:bg-cyan-700 active:bg-cyan-800 text-white shadow-sm hover:shadow-md dark:bg-cyan-500 dark:hover:bg-cyan-600 dark:active:bg-cyan-700"
|
|
19
|
+
},
|
|
20
|
+
sizes: {
|
|
21
|
+
sm: "px-3 py-1.5 text-sm",
|
|
22
|
+
md: "px-4 py-2 text-base",
|
|
23
|
+
lg: "px-6 py-3 text-lg",
|
|
24
|
+
xl: "px-8 py-4 text-xl"
|
|
25
|
+
},
|
|
26
|
+
disabled: "opacity-50 cursor-not-allowed hover:shadow-sm active:scale-100"
|
|
27
|
+
},
|
|
28
|
+
select: {
|
|
29
|
+
base: "w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 pr-10 cursor-pointer dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500",
|
|
30
|
+
sizes: {
|
|
31
|
+
sm: "px-3 py-1.5 text-sm",
|
|
32
|
+
md: "px-4 py-2.5 text-base",
|
|
33
|
+
lg: "px-4 py-3 text-lg",
|
|
34
|
+
xl: "px-5 py-4 text-xl"
|
|
35
|
+
},
|
|
36
|
+
disabled: "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
minimalistic: {
|
|
40
|
+
name: "minimalistic",
|
|
41
|
+
button: {
|
|
42
|
+
base: "font-normal rounded-none transition-colors duration-200 focus:outline-none border-2",
|
|
43
|
+
variants: {
|
|
44
|
+
primary: "bg-transparent border-white text-white hover:bg-white hover:text-black",
|
|
45
|
+
secondary: "bg-transparent border-gray-400 text-gray-400 hover:bg-gray-400 hover:text-black",
|
|
46
|
+
success: "bg-transparent border-green-400 text-green-400 hover:bg-green-400 hover:text-black",
|
|
47
|
+
danger: "bg-transparent border-red-400 text-red-400 hover:bg-red-400 hover:text-black",
|
|
48
|
+
warning: "bg-transparent border-yellow-400 text-yellow-400 hover:bg-yellow-400 hover:text-black",
|
|
49
|
+
info: "bg-transparent border-blue-400 text-blue-400 hover:bg-blue-400 hover:text-black"
|
|
50
|
+
},
|
|
51
|
+
sizes: {
|
|
52
|
+
sm: "px-4 py-2 text-sm uppercase tracking-wide",
|
|
53
|
+
md: "px-6 py-3 text-base uppercase tracking-wide",
|
|
54
|
+
lg: "px-8 py-4 text-lg uppercase tracking-wider",
|
|
55
|
+
xl: "px-10 py-5 text-xl uppercase tracking-wider"
|
|
56
|
+
},
|
|
57
|
+
disabled: "opacity-30 cursor-not-allowed hover:bg-transparent"
|
|
58
|
+
},
|
|
59
|
+
select: {
|
|
60
|
+
base: "w-full appearance-none rounded-none border-2 border-white bg-transparent text-white transition-colors duration-200 focus:outline-none pr-10 cursor-pointer placeholder:text-gray-500",
|
|
61
|
+
sizes: {
|
|
62
|
+
sm: "px-4 py-2 text-sm uppercase tracking-wide",
|
|
63
|
+
md: "px-4 py-3 text-base uppercase tracking-wide",
|
|
64
|
+
lg: "px-4 py-4 text-lg uppercase tracking-wider",
|
|
65
|
+
xl: "px-5 py-5 text-xl uppercase tracking-wider"
|
|
66
|
+
},
|
|
67
|
+
disabled: "opacity-30 cursor-not-allowed"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/theme/ThemeProvider.tsx
|
|
73
|
+
import { jsx } from "react/jsx-runtime";
|
|
74
|
+
var ThemeContext = createContext(void 0);
|
|
75
|
+
function useTheme() {
|
|
76
|
+
const context = useContext(ThemeContext);
|
|
77
|
+
if (!context) {
|
|
78
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
79
|
+
}
|
|
80
|
+
return context;
|
|
81
|
+
}
|
|
82
|
+
function ThemeProvider({
|
|
83
|
+
children,
|
|
84
|
+
defaultTheme = "default",
|
|
85
|
+
defaultColorMode = "system"
|
|
86
|
+
}) {
|
|
87
|
+
const [mounted, setMounted] = useState(false);
|
|
88
|
+
const [themeName, setThemeNameState] = useState(defaultTheme);
|
|
89
|
+
const [colorMode, setColorModeState] = useState(defaultColorMode);
|
|
90
|
+
const [resolvedColorMode, setResolvedColorMode] = useState("light");
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
setMounted(true);
|
|
93
|
+
const storedTheme = localStorage.getItem("lite-ui-theme");
|
|
94
|
+
const storedColorMode = localStorage.getItem("lite-ui-color-mode");
|
|
95
|
+
const currentColorMode = document.documentElement.getAttribute("data-color-mode");
|
|
96
|
+
if (storedTheme) setThemeNameState(storedTheme);
|
|
97
|
+
if (storedColorMode) setColorModeState(storedColorMode);
|
|
98
|
+
if (currentColorMode) setResolvedColorMode(currentColorMode);
|
|
99
|
+
}, []);
|
|
100
|
+
const theme = themes[themeName];
|
|
101
|
+
const setTheme = (newThemeName) => {
|
|
102
|
+
setThemeNameState(newThemeName);
|
|
103
|
+
if (typeof window !== "undefined") {
|
|
104
|
+
localStorage.setItem("lite-ui-theme", newThemeName);
|
|
105
|
+
document.documentElement.setAttribute("data-theme", newThemeName);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const setColorMode = (mode) => {
|
|
109
|
+
if (typeof window === "undefined") return;
|
|
110
|
+
setColorModeState(mode);
|
|
111
|
+
localStorage.setItem("lite-ui-color-mode", mode);
|
|
112
|
+
let resolved;
|
|
113
|
+
if (mode === "system") {
|
|
114
|
+
resolved = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
115
|
+
} else {
|
|
116
|
+
resolved = mode;
|
|
117
|
+
}
|
|
118
|
+
setResolvedColorMode(resolved);
|
|
119
|
+
document.documentElement.setAttribute("data-color-mode", resolved);
|
|
120
|
+
if (resolved === "dark") {
|
|
121
|
+
document.documentElement.classList.add("dark");
|
|
122
|
+
} else {
|
|
123
|
+
document.documentElement.classList.remove("dark");
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (!mounted) return;
|
|
128
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
129
|
+
const handleChange = (e) => {
|
|
130
|
+
if (colorMode === "system") {
|
|
131
|
+
const resolved = e.matches ? "dark" : "light";
|
|
132
|
+
setResolvedColorMode(resolved);
|
|
133
|
+
document.documentElement.setAttribute("data-color-mode", resolved);
|
|
134
|
+
if (resolved === "dark") {
|
|
135
|
+
document.documentElement.classList.add("dark");
|
|
136
|
+
} else {
|
|
137
|
+
document.documentElement.classList.remove("dark");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
142
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
143
|
+
}, [mounted, colorMode]);
|
|
144
|
+
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: {
|
|
145
|
+
theme,
|
|
146
|
+
themeName,
|
|
147
|
+
setTheme,
|
|
148
|
+
colorMode,
|
|
149
|
+
setColorMode,
|
|
150
|
+
resolvedColorMode
|
|
151
|
+
}, children });
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/components/Button.tsx
|
|
155
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
156
|
+
var Button = ({
|
|
157
|
+
variant = "primary",
|
|
158
|
+
size = "md",
|
|
159
|
+
className = "",
|
|
160
|
+
children,
|
|
161
|
+
disabled,
|
|
162
|
+
...props
|
|
163
|
+
}) => {
|
|
164
|
+
const { theme } = useTheme();
|
|
165
|
+
const baseStyles = theme.button.base;
|
|
166
|
+
const variantStyles = theme.button.variants[variant];
|
|
167
|
+
const sizeStyles = theme.button.sizes[size];
|
|
168
|
+
const disabledStyles = disabled ? theme.button.disabled : "";
|
|
169
|
+
const classes = `${baseStyles} ${variantStyles} ${sizeStyles} ${disabledStyles} ${className}`.trim();
|
|
170
|
+
return /* @__PURE__ */ jsx2(
|
|
171
|
+
"button",
|
|
172
|
+
{
|
|
173
|
+
className: classes,
|
|
174
|
+
disabled,
|
|
175
|
+
...props,
|
|
176
|
+
children
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// src/components/Select.tsx
|
|
182
|
+
import { useState as useState2, useRef, useEffect as useEffect2 } from "react";
|
|
183
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
184
|
+
var Select = ({
|
|
185
|
+
options,
|
|
186
|
+
size = "md",
|
|
187
|
+
placeholder,
|
|
188
|
+
className = "",
|
|
189
|
+
disabled,
|
|
190
|
+
value: controlledValue,
|
|
191
|
+
defaultValue,
|
|
192
|
+
onChange,
|
|
193
|
+
...props
|
|
194
|
+
}) => {
|
|
195
|
+
const { theme, themeName } = useTheme();
|
|
196
|
+
const [isOpen, setIsOpen] = useState2(false);
|
|
197
|
+
const [internalValue, setInternalValue] = useState2(defaultValue || "");
|
|
198
|
+
const dropdownRef = useRef(null);
|
|
199
|
+
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
200
|
+
const selectedOption = options.find((opt) => opt.value === value);
|
|
201
|
+
const displayText = selectedOption ? selectedOption.label : placeholder || "Select...";
|
|
202
|
+
useEffect2(() => {
|
|
203
|
+
const handleClickOutside = (event) => {
|
|
204
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
205
|
+
setIsOpen(false);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
if (isOpen) {
|
|
209
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
210
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
211
|
+
}
|
|
212
|
+
}, [isOpen]);
|
|
213
|
+
const handleSelect = (optionValue) => {
|
|
214
|
+
if (disabled) return;
|
|
215
|
+
setInternalValue(optionValue);
|
|
216
|
+
onChange?.(optionValue);
|
|
217
|
+
setIsOpen(false);
|
|
218
|
+
};
|
|
219
|
+
const handleToggle = () => {
|
|
220
|
+
if (!disabled) {
|
|
221
|
+
setIsOpen(!isOpen);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const baseStyles = theme.select.base;
|
|
225
|
+
const sizeStyles = theme.select.sizes[size];
|
|
226
|
+
const disabledStyles = disabled ? theme.select.disabled : "";
|
|
227
|
+
const buttonClasses = `${baseStyles} ${sizeStyles} ${disabledStyles} ${className}`.trim();
|
|
228
|
+
const iconColor = themeName === "minimalistic" ? disabled ? "text-gray-600" : "text-white" : disabled ? "text-gray-400" : "text-gray-500";
|
|
229
|
+
const dropdownBaseStyles = themeName === "minimalistic" ? "bg-black border-2 border-white" : "bg-white border border-gray-300 shadow-lg dark:bg-gray-800 dark:border-gray-600";
|
|
230
|
+
const optionBaseStyles = themeName === "minimalistic" ? "text-white hover:bg-white hover:text-black transition-colors duration-200" : "text-gray-900 hover:bg-blue-50 transition-colors duration-150 dark:text-gray-100 dark:hover:bg-gray-700";
|
|
231
|
+
const optionSizeStyles = {
|
|
232
|
+
sm: "px-4 py-2 text-sm",
|
|
233
|
+
md: "px-4 py-2.5 text-base",
|
|
234
|
+
lg: "px-4 py-3 text-lg",
|
|
235
|
+
xl: "px-5 py-4 text-xl"
|
|
236
|
+
}[size];
|
|
237
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative inline-block w-full", ref: dropdownRef, ...props, children: [
|
|
238
|
+
/* @__PURE__ */ jsx3(
|
|
239
|
+
"button",
|
|
240
|
+
{
|
|
241
|
+
type: "button",
|
|
242
|
+
className: buttonClasses,
|
|
243
|
+
onClick: handleToggle,
|
|
244
|
+
disabled,
|
|
245
|
+
children: /* @__PURE__ */ jsx3("span", { className: !selectedOption && placeholder ? "opacity-50" : "", children: displayText })
|
|
246
|
+
}
|
|
247
|
+
),
|
|
248
|
+
/* @__PURE__ */ jsx3("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-4", children: /* @__PURE__ */ jsx3(
|
|
249
|
+
"svg",
|
|
250
|
+
{
|
|
251
|
+
className: `h-5 w-5 transition-transform duration-200 ${iconColor} ${isOpen ? "rotate-180" : ""}`,
|
|
252
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
253
|
+
viewBox: "0 0 20 20",
|
|
254
|
+
fill: "currentColor",
|
|
255
|
+
"aria-hidden": "true",
|
|
256
|
+
children: /* @__PURE__ */ jsx3(
|
|
257
|
+
"path",
|
|
258
|
+
{
|
|
259
|
+
fillRule: "evenodd",
|
|
260
|
+
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
|
261
|
+
clipRule: "evenodd"
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
) }),
|
|
266
|
+
isOpen && !disabled && /* @__PURE__ */ jsx3(
|
|
267
|
+
"div",
|
|
268
|
+
{
|
|
269
|
+
className: `absolute z-50 w-full mt-1 ${dropdownBaseStyles} rounded-lg overflow-hidden`,
|
|
270
|
+
style: { maxHeight: "300px", overflowY: "auto" },
|
|
271
|
+
children: options.map((option) => /* @__PURE__ */ jsx3(
|
|
272
|
+
"div",
|
|
273
|
+
{
|
|
274
|
+
className: `${optionBaseStyles} ${optionSizeStyles} cursor-pointer ${value === option.value ? themeName === "minimalistic" ? "bg-white text-black" : "bg-blue-100 dark:bg-blue-900" : ""}`,
|
|
275
|
+
onClick: () => handleSelect(option.value),
|
|
276
|
+
children: option.label
|
|
277
|
+
},
|
|
278
|
+
option.value
|
|
279
|
+
))
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
] });
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// src/utils/theme-script.ts
|
|
286
|
+
var themeScript = `
|
|
287
|
+
(function() {
|
|
288
|
+
try {
|
|
289
|
+
// Get stored preferences
|
|
290
|
+
const storedTheme = localStorage.getItem('lite-ui-theme') || 'default';
|
|
291
|
+
const storedColorMode = localStorage.getItem('lite-ui-color-mode');
|
|
292
|
+
|
|
293
|
+
// Determine color mode (system, light, or dark)
|
|
294
|
+
let colorMode = storedColorMode;
|
|
295
|
+
if (!colorMode || colorMode === 'system') {
|
|
296
|
+
colorMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Set attributes before render
|
|
300
|
+
document.documentElement.setAttribute('data-theme', storedTheme);
|
|
301
|
+
document.documentElement.setAttribute('data-color-mode', colorMode);
|
|
302
|
+
|
|
303
|
+
// Add dark class for Tailwind
|
|
304
|
+
if (colorMode === 'dark') {
|
|
305
|
+
document.documentElement.classList.add('dark');
|
|
306
|
+
} else {
|
|
307
|
+
document.documentElement.classList.remove('dark');
|
|
308
|
+
}
|
|
309
|
+
} catch (e) {
|
|
310
|
+
console.error('Failed to initialize theme:', e);
|
|
311
|
+
}
|
|
312
|
+
})();
|
|
313
|
+
`;
|
|
314
|
+
function getThemeScript() {
|
|
315
|
+
return themeScript;
|
|
316
|
+
}
|
|
317
|
+
export {
|
|
318
|
+
Button,
|
|
319
|
+
Select,
|
|
320
|
+
ThemeProvider,
|
|
321
|
+
getThemeScript,
|
|
322
|
+
themeScript,
|
|
323
|
+
themes,
|
|
324
|
+
useTheme
|
|
325
|
+
};
|
|
326
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/theme/ThemeProvider.tsx","../src/theme/themes.ts","../src/components/Button.tsx","../src/components/Select.tsx","../src/utils/theme-script.ts"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useState, useEffect } from 'react';\nimport { themes, ThemeName, Theme } from './themes';\n\nexport type ColorMode = 'light' | 'dark' | 'system';\n\ninterface ThemeContextValue {\n theme: Theme;\n themeName: ThemeName;\n setTheme: (themeName: ThemeName) => void;\n colorMode: ColorMode;\n setColorMode: (mode: ColorMode) => void;\n resolvedColorMode: 'light' | 'dark';\n}\n\nconst ThemeContext = createContext<ThemeContextValue | undefined>(undefined);\n\nexport function useTheme() {\n const context = useContext(ThemeContext);\n if (!context) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n return context;\n}\n\ninterface ThemeProviderProps {\n children: React.ReactNode;\n defaultTheme?: ThemeName;\n defaultColorMode?: ColorMode;\n}\n\nexport function ThemeProvider({\n children,\n defaultTheme = 'default',\n defaultColorMode = 'system'\n}: ThemeProviderProps) {\n const [mounted, setMounted] = useState(false);\n\n // Initialize from defaults (will sync with actual values after mount)\n const [themeName, setThemeNameState] = useState<ThemeName>(defaultTheme);\n const [colorMode, setColorModeState] = useState<ColorMode>(defaultColorMode);\n const [resolvedColorMode, setResolvedColorMode] = useState<'light' | 'dark'>('light');\n\n // Sync with actual values after mount to avoid hydration mismatch\n useEffect(() => {\n setMounted(true);\n\n // Read actual values from localStorage and DOM\n const storedTheme = localStorage.getItem('lite-ui-theme') as ThemeName;\n const storedColorMode = localStorage.getItem('lite-ui-color-mode') as ColorMode;\n const currentColorMode = document.documentElement.getAttribute('data-color-mode') as 'light' | 'dark';\n\n if (storedTheme) setThemeNameState(storedTheme);\n if (storedColorMode) setColorModeState(storedColorMode);\n if (currentColorMode) setResolvedColorMode(currentColorMode);\n }, []);\n\n const theme = themes[themeName];\n\n // Update theme\n const setTheme = (newThemeName: ThemeName) => {\n setThemeNameState(newThemeName);\n if (typeof window !== 'undefined') {\n localStorage.setItem('lite-ui-theme', newThemeName);\n document.documentElement.setAttribute('data-theme', newThemeName);\n }\n };\n\n // Update color mode\n const setColorMode = (mode: ColorMode) => {\n if (typeof window === 'undefined') return;\n\n setColorModeState(mode);\n localStorage.setItem('lite-ui-color-mode', mode);\n\n let resolved: 'light' | 'dark';\n if (mode === 'system') {\n resolved = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n } else {\n resolved = mode;\n }\n\n setResolvedColorMode(resolved);\n document.documentElement.setAttribute('data-color-mode', resolved);\n\n if (resolved === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n };\n\n // Listen for system theme changes\n useEffect(() => {\n if (!mounted) return;\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n\n const handleChange = (e: MediaQueryListEvent) => {\n if (colorMode === 'system') {\n const resolved = e.matches ? 'dark' : 'light';\n setResolvedColorMode(resolved);\n document.documentElement.setAttribute('data-color-mode', resolved);\n\n if (resolved === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n }\n };\n\n mediaQuery.addEventListener('change', handleChange);\n return () => mediaQuery.removeEventListener('change', handleChange);\n }, [mounted, colorMode]);\n\n return (\n <ThemeContext.Provider value={{\n theme,\n themeName,\n setTheme,\n colorMode,\n setColorMode,\n resolvedColorMode\n }}>\n {children}\n </ThemeContext.Provider>\n );\n}\n","export type ThemeName = 'default' | 'minimalistic';\n\nexport interface ButtonTheme {\n primary: string;\n secondary: string;\n success: string;\n danger: string;\n warning: string;\n info: string;\n}\n\nexport interface SelectTheme {\n base: string;\n sizes: {\n sm: string;\n md: string;\n lg: string;\n xl: string;\n };\n disabled: string;\n}\n\nexport interface Theme {\n name: ThemeName;\n button: {\n base: string;\n variants: ButtonTheme;\n sizes: {\n sm: string;\n md: string;\n lg: string;\n xl: string;\n };\n disabled: string;\n };\n select: SelectTheme;\n}\n\nexport const themes: Record<ThemeName, Theme> = {\n default: {\n name: 'default',\n button: {\n base: 'font-semibold rounded-lg transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 active:scale-95',\n variants: {\n primary: 'bg-blue-600 hover:bg-blue-700 active:bg-blue-800 text-white shadow-sm hover:shadow-md dark:bg-blue-500 dark:hover:bg-blue-600 dark:active:bg-blue-700',\n secondary: 'bg-gray-600 hover:bg-gray-700 active:bg-gray-800 text-white shadow-sm hover:shadow-md dark:bg-gray-500 dark:hover:bg-gray-600 dark:active:bg-gray-700',\n success: 'bg-green-600 hover:bg-green-700 active:bg-green-800 text-white shadow-sm hover:shadow-md dark:bg-green-500 dark:hover:bg-green-600 dark:active:bg-green-700',\n danger: 'bg-red-600 hover:bg-red-700 active:bg-red-800 text-white shadow-sm hover:shadow-md dark:bg-red-500 dark:hover:bg-red-600 dark:active:bg-red-700',\n warning: 'bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white shadow-sm hover:shadow-md dark:bg-yellow-400 dark:hover:bg-yellow-500 dark:active:bg-yellow-600',\n info: 'bg-cyan-600 hover:bg-cyan-700 active:bg-cyan-800 text-white shadow-sm hover:shadow-md dark:bg-cyan-500 dark:hover:bg-cyan-600 dark:active:bg-cyan-700',\n },\n sizes: {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2 text-base',\n lg: 'px-6 py-3 text-lg',\n xl: 'px-8 py-4 text-xl',\n },\n disabled: 'opacity-50 cursor-not-allowed hover:shadow-sm active:scale-100',\n },\n select: {\n base: 'w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 pr-10 cursor-pointer dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500',\n sizes: {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2.5 text-base',\n lg: 'px-4 py-3 text-lg',\n xl: 'px-5 py-4 text-xl',\n },\n disabled: 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900',\n },\n },\n minimalistic: {\n name: 'minimalistic',\n button: {\n base: 'font-normal rounded-none transition-colors duration-200 focus:outline-none border-2',\n variants: {\n primary: 'bg-transparent border-white text-white hover:bg-white hover:text-black',\n secondary: 'bg-transparent border-gray-400 text-gray-400 hover:bg-gray-400 hover:text-black',\n success: 'bg-transparent border-green-400 text-green-400 hover:bg-green-400 hover:text-black',\n danger: 'bg-transparent border-red-400 text-red-400 hover:bg-red-400 hover:text-black',\n warning: 'bg-transparent border-yellow-400 text-yellow-400 hover:bg-yellow-400 hover:text-black',\n info: 'bg-transparent border-blue-400 text-blue-400 hover:bg-blue-400 hover:text-black',\n },\n sizes: {\n sm: 'px-4 py-2 text-sm uppercase tracking-wide',\n md: 'px-6 py-3 text-base uppercase tracking-wide',\n lg: 'px-8 py-4 text-lg uppercase tracking-wider',\n xl: 'px-10 py-5 text-xl uppercase tracking-wider',\n },\n disabled: 'opacity-30 cursor-not-allowed hover:bg-transparent',\n },\n select: {\n base: 'w-full appearance-none rounded-none border-2 border-white bg-transparent text-white transition-colors duration-200 focus:outline-none pr-10 cursor-pointer placeholder:text-gray-500',\n sizes: {\n sm: 'px-4 py-2 text-sm uppercase tracking-wide',\n md: 'px-4 py-3 text-base uppercase tracking-wide',\n lg: 'px-4 py-4 text-lg uppercase tracking-wider',\n xl: 'px-5 py-5 text-xl uppercase tracking-wider',\n },\n disabled: 'opacity-30 cursor-not-allowed',\n },\n },\n};\n","\"use client\";\n\nimport React from 'react';\nimport { useTheme } from '../theme/ThemeProvider';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';\n size?: 'sm' | 'md' | 'lg' | 'xl';\n children: React.ReactNode;\n}\n\nexport const Button: React.FC<ButtonProps> = ({\n variant = 'primary',\n size = 'md',\n className = '',\n children,\n disabled,\n ...props\n}) => {\n const { theme } = useTheme();\n\n const baseStyles = theme.button.base;\n const variantStyles = theme.button.variants[variant];\n const sizeStyles = theme.button.sizes[size];\n const disabledStyles = disabled ? theme.button.disabled : '';\n\n const classes = `${baseStyles} ${variantStyles} ${sizeStyles} ${disabledStyles} ${className}`.trim();\n\n return (\n <button\n className={classes}\n disabled={disabled}\n {...props}\n >\n {children}\n </button>\n );\n};\n","\"use client\";\n\nimport React, { useState, useRef, useEffect } from 'react';\nimport { useTheme } from '../theme/ThemeProvider';\n\nexport interface SelectOption {\n value: string;\n label: string;\n}\n\nexport interface SelectProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'size' | 'onChange' | 'defaultValue'> {\n options: SelectOption[];\n size?: 'sm' | 'md' | 'lg' | 'xl';\n placeholder?: string;\n disabled?: boolean;\n value?: string;\n defaultValue?: string;\n onChange?: (value: string) => void;\n}\n\nexport const Select: React.FC<SelectProps> = ({\n options,\n size = 'md',\n placeholder,\n className = '',\n disabled,\n value: controlledValue,\n defaultValue,\n onChange,\n ...props\n}) => {\n const { theme, themeName } = useTheme();\n const [isOpen, setIsOpen] = useState(false);\n const [internalValue, setInternalValue] = useState(defaultValue || '');\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Use controlled value if provided, otherwise use internal state\n const value = controlledValue !== undefined ? controlledValue : internalValue;\n\n // Find the selected option\n const selectedOption = options.find(opt => opt.value === value);\n const displayText = selectedOption ? selectedOption.label : placeholder || 'Select...';\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n const handleSelect = (optionValue: string) => {\n if (disabled) return;\n\n setInternalValue(optionValue);\n onChange?.(optionValue);\n setIsOpen(false);\n };\n\n const handleToggle = () => {\n if (!disabled) {\n setIsOpen(!isOpen);\n }\n };\n\n const baseStyles = theme.select.base;\n const sizeStyles = theme.select.sizes[size];\n const disabledStyles = disabled ? theme.select.disabled : '';\n\n const buttonClasses = `${baseStyles} ${sizeStyles} ${disabledStyles} ${className}`.trim();\n\n // Icon color based on theme\n const iconColor = themeName === 'minimalistic'\n ? (disabled ? 'text-gray-600' : 'text-white')\n : (disabled ? 'text-gray-400' : 'text-gray-500');\n\n // Dropdown menu styles based on theme\n const dropdownBaseStyles = themeName === 'minimalistic'\n ? 'bg-black border-2 border-white'\n : 'bg-white border border-gray-300 shadow-lg dark:bg-gray-800 dark:border-gray-600';\n\n const optionBaseStyles = themeName === 'minimalistic'\n ? 'text-white hover:bg-white hover:text-black transition-colors duration-200'\n : 'text-gray-900 hover:bg-blue-50 transition-colors duration-150 dark:text-gray-100 dark:hover:bg-gray-700';\n\n const optionSizeStyles = {\n sm: 'px-4 py-2 text-sm',\n md: 'px-4 py-2.5 text-base',\n lg: 'px-4 py-3 text-lg',\n xl: 'px-5 py-4 text-xl',\n }[size];\n\n return (\n <div className=\"relative inline-block w-full\" ref={dropdownRef} {...props}>\n {/* Custom button that looks like select */}\n <button\n type=\"button\"\n className={buttonClasses}\n onClick={handleToggle}\n disabled={disabled}\n >\n <span className={!selectedOption && placeholder ? 'opacity-50' : ''}>\n {displayText}\n </span>\n </button>\n\n {/* Chevron icon */}\n <div className=\"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-4\">\n <svg\n className={`h-5 w-5 transition-transform duration-200 ${iconColor} ${isOpen ? 'rotate-180' : ''}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </div>\n\n {/* Custom dropdown menu */}\n {isOpen && !disabled && (\n <div\n className={`absolute z-50 w-full mt-1 ${dropdownBaseStyles} rounded-lg overflow-hidden`}\n style={{ maxHeight: '300px', overflowY: 'auto' }}\n >\n {options.map((option) => (\n <div\n key={option.value}\n className={`${optionBaseStyles} ${optionSizeStyles} cursor-pointer ${\n value === option.value ? (themeName === 'minimalistic' ? 'bg-white text-black' : 'bg-blue-100 dark:bg-blue-900') : ''\n }`}\n onClick={() => handleSelect(option.value)}\n >\n {option.label}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n};\n","/**\n * Theme initialization script that runs before React hydration\n * This prevents flickering by setting the theme before the page renders\n * Must be inlined in the HTML <head> as a blocking script\n */\n\nexport const themeScript = `\n(function() {\n try {\n // Get stored preferences\n const storedTheme = localStorage.getItem('lite-ui-theme') || 'default';\n const storedColorMode = localStorage.getItem('lite-ui-color-mode');\n\n // Determine color mode (system, light, or dark)\n let colorMode = storedColorMode;\n if (!colorMode || colorMode === 'system') {\n colorMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n\n // Set attributes before render\n document.documentElement.setAttribute('data-theme', storedTheme);\n document.documentElement.setAttribute('data-color-mode', colorMode);\n\n // Add dark class for Tailwind\n if (colorMode === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n } catch (e) {\n console.error('Failed to initialize theme:', e);\n }\n})();\n`;\n\nexport function getThemeScript() {\n return themeScript;\n}\n"],"mappings":"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","names":["jsx","useState","useEffect","jsx","useState","useEffect"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@marcoschwartz/lite-ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A lightweight UI component library built with Tailwind CSS",
|
|
5
|
+
"author": "Marco Schwartz",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/marcoschwartz/lite-ui.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/marcoschwartz/lite-ui#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/marcoschwartz/lite-ui/issues"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"module": "./dist/index.mjs",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.mjs",
|
|
22
|
+
"require": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./styles.css": "./dist/styles.css"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup",
|
|
33
|
+
"dev": "npm run build -- --watch",
|
|
34
|
+
"dev:all": "./dev.sh",
|
|
35
|
+
"clean": "rm -rf dist",
|
|
36
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"react": ">=18",
|
|
40
|
+
"react-dom": ">=18"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/react": "^19",
|
|
44
|
+
"@types/react-dom": "^19",
|
|
45
|
+
"react": "^19",
|
|
46
|
+
"react-dom": "^19",
|
|
47
|
+
"tailwindcss": "^4",
|
|
48
|
+
"tsup": "^8.0.0",
|
|
49
|
+
"typescript": "^5"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"react",
|
|
53
|
+
"ui",
|
|
54
|
+
"components",
|
|
55
|
+
"tailwind",
|
|
56
|
+
"tailwindcss",
|
|
57
|
+
"react-components",
|
|
58
|
+
"ui-library",
|
|
59
|
+
"design-system",
|
|
60
|
+
"dark-mode",
|
|
61
|
+
"theming"
|
|
62
|
+
],
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
}
|
|
66
|
+
}
|