klip-components 0.3.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,13 +9,11 @@ A modern, flexible, and reusable React component library built with TypeScript a
9
9
  ## ✨ Features
10
10
 
11
11
  - 🎨 **Modern Design**: Clean and professional UI components
12
- - 🌈 **Theme System**: Client-side theme generation with custom colors and dark/light mode
13
12
  - 🔧 **TypeScript**: Full TypeScript support with comprehensive type definitions
14
13
  - 📱 **Responsive**: Mobile-first design approach
15
14
  - ♿ **Accessible**: Built with accessibility best practices in mind
16
- - 🎯 **Flexible**: Highly customizable with variants, sizes, and theme overrides
15
+ - 🎯 **Flexible**: Highly customizable with variants and properties
17
16
  - 📦 **Tree Shakable**: Import only what you need
18
- - ⚡ **Zero Setup**: No server configuration required - works with static builds
19
17
  - 📚 **Well Documented**: Complete Storybook documentation
20
18
 
21
19
  ## 📦 Installation
@@ -30,99 +28,73 @@ bun add klip-components
30
28
 
31
29
  ## 🔧 Quick Start
32
30
 
31
+ Here's how to import and use some of the components from `klip-components`.
32
+
33
+ ### Button
34
+
33
35
  ```tsx
34
- import { ThemeProvider, Button } from 'klip-components';
36
+ import { Button } from 'klip-components';
35
37
 
36
38
  function App() {
37
39
  return (
38
- <ThemeProvider
39
- theme={{
40
- colors: {
41
- primary: { main: '#ff6b6b', hover: '#ff5252' },
42
- },
43
- }}
44
- >
45
- <Button variant="primary">Custom Themed Button</Button>
46
- </ThemeProvider>
40
+ <Button variant="primary" onClick={() => alert('Button clicked!')}>
41
+ Click Me
42
+ </Button>
47
43
  );
48
44
  }
49
45
  ```
50
46
 
51
- ### Theme Provider Setup
52
-
53
- For custom themes and dark/light mode support, wrap your app with the `ThemeProvider`:
47
+ ### Input
54
48
 
55
49
  ```tsx
56
- import { ThemeProvider, Button, ThemeToggle } from 'klip-components';
57
-
58
- // Custom brand colors
59
- const customTheme = {
60
- colors: {
61
- primary: {
62
- main: '#8b5cf6', // Purple
63
- hover: '#7c3aed',
64
- },
65
- secondary: {
66
- main: '#10b981', // Emerald
67
- hover: '#059669',
68
- },
69
- },
70
- };
50
+ import { Input } from 'klip-components';
51
+ import { useState } from 'react';
71
52
 
72
53
  function App() {
54
+ const [value, setValue] = useState('');
55
+
73
56
  return (
74
- <ThemeProvider defaultMode="auto" theme={customTheme}>
75
- <div>
76
- <ThemeToggle />
77
- <Button variant="primary" size="lg">
78
- Themed Button
79
- </Button>
80
- <Button variant="secondary" size="sm">
81
- Secondary Button
82
- </Button>
83
- </div>
84
- </ThemeProvider>
57
+ <Input
58
+ label="Username"
59
+ placeholder="Enter your username"
60
+ value={value}
61
+ onChange={setValue}
62
+ helperText="This is a hint for the user."
63
+ />
85
64
  );
86
65
  }
87
66
  ```
88
67
 
89
- ### Using Theme Hooks
90
-
91
- Access theme values and controls in your components:
68
+ ### Toggle Switch
92
69
 
93
70
  ```tsx
94
- import { useTheme } from 'klip-components';
95
-
96
- function ThemedComponent() {
97
- const { theme, isDark, setMode, updateTheme } = useTheme();
71
+ import { Toggle } from 'klip-components';
72
+ import { useState } from 'react';
98
73
 
99
- const handleCustomize = () => {
100
- updateTheme({
101
- colors: {
102
- primary: { main: '#ff6b6b', hover: '#ff5252' },
103
- },
104
- });
105
- };
74
+ function App() {
75
+ const [isEnabled, setIsEnabled] = useState(false);
106
76
 
107
- return (
108
- <div>
109
- <h2>Current Mode: {isDark ? 'Dark' : 'Light'}</h2>
110
- <button onClick={() => setMode(isDark ? 'light' : 'dark')}>Toggle Theme</button>
111
- <button onClick={handleCustomize}>Customize Colors</button>
112
- </div>
113
- );
77
+ return <Toggle label="Enable Feature" checked={isEnabled} onChange={setIsEnabled} />;
114
78
  }
115
79
  ```
116
80
 
117
- ## 🎨 Theme System
81
+ ### Button Select
118
82
 
119
- The theme system is **zero-configuration** and works perfectly with static builds:
83
+ ```tsx
84
+ import { ButtonSelect } from 'klip-components';
85
+ import { useState } from 'react';
120
86
 
121
- - **No server setup required** - pure client-side CSS generation
122
- - **Zero FOUC** - themes load before React renders
123
- - **Static build friendly** - works with any hosting platform
124
- - **Dynamic theming** - change colors at runtime
125
- - **Dark/light mode** - automatic system detection with manual override
87
+ function App() {
88
+ const [selectedValue, setSelectedValue] = useState('option1');
89
+ const options = [
90
+ { value: 'option1', label: 'Option 1' },
91
+ { value: 'option2', label: 'Option 2' },
92
+ { value: 'option3', label: 'Option 3' },
93
+ ];
94
+
95
+ return <ButtonSelect options={options} value={selectedValue} onChange={setSelectedValue} />;
96
+ }
97
+ ```
126
98
 
127
99
  ## 📖 Documentation
128
100
 
@@ -216,7 +188,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
216
188
  - Built with [React](https://reactjs.org/)
217
189
  - Bundled with [Vite](https://vitejs.dev/)
218
190
  - Documented with [Storybook](https://storybook.js.org/)
219
- - Styled with CSS Variables
191
+ - Styled with plain CSS and CSS Variables
220
192
 
221
193
  ---
222
194
 
package/dist/index.d.ts CHANGED
@@ -1,20 +1,6 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  import { clsx } from 'clsx';
3
- import { Context } from 'react';
4
3
  import { default as default_2 } from 'react';
5
- import { JSX } from 'react/jsx-runtime';
6
-
7
- /**
8
- * Applies theme CSS custom properties to the DOM
9
- */
10
- export declare function applyThemeToDOM(theme: Theme, target?: HTMLElement): void;
11
-
12
- export declare interface BorderRadius {
13
- sm: string;
14
- base: string;
15
- lg: string;
16
- full: string;
17
- }
18
4
 
19
5
  /**
20
6
  * A flexible and reusable Button component with multiple variants, sizes, and styling options.
@@ -64,10 +50,35 @@ export declare const Button: default_2.FC<ButtonProps>;
64
50
  export declare interface ButtonProps extends default_2.ButtonHTMLAttributes<HTMLButtonElement> {
65
51
  /** Visual style variant of the button */
66
52
  variant?: ButtonVariant;
53
+ /** Size of the button */
54
+ size?: ButtonSize;
55
+ /** Icon to display at the start of the button */
56
+ startIcon?: default_2.ReactNode;
57
+ /** Icon to display at the end of the button */
58
+ endIcon?: default_2.ReactNode;
67
59
  /** Content to be rendered inside the button */
68
60
  children: default_2.ReactNode;
69
61
  }
70
62
 
63
+ export declare const ButtonSelect: default_2.FC<ButtonSelectProps>;
64
+
65
+ export declare interface ButtonSelectOption {
66
+ value: string;
67
+ child: default_2.ReactNode;
68
+ }
69
+
70
+ export declare interface ButtonSelectProps {
71
+ options: ButtonSelectOption[];
72
+ value: ButtonSelectValue;
73
+ onChange: (value: ButtonSelectValue) => void;
74
+ disabled?: boolean;
75
+ multiple?: boolean;
76
+ }
77
+
78
+ export declare type ButtonSelectValue = string | string[];
79
+
80
+ declare type ButtonSize = 'sm' | 'md' | 'lg';
81
+
71
82
  /**
72
83
  * Props interface for the Button component.
73
84
  * Extends standard HTML button attributes with additional styling options.
@@ -96,58 +107,68 @@ export { clsx }
96
107
  */
97
108
  export declare function cn(...inputs: ClassValue[]): string;
98
109
 
99
- /**
100
- * Theme system type definitions for klip-components
101
- * Provides type safety for color palettes and design tokens
102
- */
103
- export declare interface ColorPalette {
104
- /** Primary color variants */
105
- primary: {
106
- main: string;
107
- hover: string;
108
- };
109
- /** Secondary color variants */
110
- secondary: {
111
- main: string;
112
- hover: string;
113
- };
114
- /** Semantic colors */
115
- semantic: {
116
- success: string;
117
- danger: string;
118
- warning: string;
119
- info: string;
120
- light: string;
121
- dark: string;
122
- link: string;
123
- };
124
- }
125
-
126
- /**
127
- * Creates CSS custom property name from theme path
128
- */
129
- export declare function createCSSVariable(path: string): string;
110
+ export declare type HtmlInput = Omit<default_2.InputHTMLAttributes<HTMLInputElement>, 'prefix' | 'suffix' | 'type' | 'onChange'>;
130
111
 
131
112
  /**
132
- * Example dark theme
113
+ * A utility type to extract valid HTML attributes for an input element,
114
+ * while omitting props that are explicitly handled by the Toggle component.
133
115
  */
134
- export declare const darkTheme: Theme;
116
+ declare type HtmlToggle = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'checked' | 'onChange'>;
135
117
 
136
118
  /**
137
- * Default light theme configuration
138
- * Based on the existing CSS variables in variables.css
139
- */
140
- export declare const defaultTheme: Theme;
141
-
142
- /**
143
- * Detects user's preferred color scheme
144
- */
145
- export declare function detectColorScheme(): 'light' | 'dark';
119
+ * A versatile input component with support for variants, labels, prefixes, suffixes, and helper text.
120
+ *
121
+ * It's a controlled component that wraps a standard HTML input and extends its functionality.
122
+ * It forwards most standard input props like `placeholder`, `disabled`, and `value`. The `onChange`
123
+ * callback receives the input value directly as a string, making it easier to work with.
124
+ *
125
+ * @param {InputProps} props The props for the component.
126
+ * @returns {React.ReactElement} The rendered input component.
127
+ *
128
+ * @example
129
+ * // Example of a parent component managing the input's state.
130
+ * import { useState } from 'react';
131
+ * // Assuming you have an icon component or SVG, for example from heroicons
132
+ * // import { UserIcon } from '@heroicons/react/24/solid';
133
+ *
134
+ * const MyForm = () => {
135
+ * const [username, setUsername] = useState('');
136
+ *
137
+ * return (
138
+ * <Input
139
+ * variant="primary"
140
+ * type="text"
141
+ * label="Username"
142
+ * placeholder="Enter your username"
143
+ * value={username}
144
+ * onChange={setUsername}
145
+ * prefix={<span>@</span>}
146
+ * helperText="Your public display name."
147
+ * aria-label="Username"
148
+ * />
149
+ * );
150
+ * };
151
+ */
152
+ export declare const Input: default_2.FC<InputProps>;
153
+
154
+ export declare interface InputProps extends HtmlInput {
155
+ /** Callback function invoked when the input value changes */
156
+ onChange?: (value: string) => void;
157
+ /** Visual style variant of the input */
158
+ variant?: InputVariant;
159
+ /** Type of the input field */
160
+ type?: default_2.HTMLInputTypeAttribute;
161
+ /** Label text to be displayed above the input */
162
+ label?: string;
163
+ /** Content to be rendered before the input (can be text, icon, or any React node) */
164
+ prefix?: default_2.ReactNode;
165
+ /** Content to be rendered after the input (can be text, icon, or any React node) */
166
+ suffix?: default_2.ReactNode;
167
+ /** Helper text to be displayed below the input */
168
+ helperText?: string;
169
+ }
146
170
 
147
- /**
148
- * Gets CSS custom property value from theme
149
- */
150
- export declare function getThemeValue(theme: Theme, path: string): string | undefined;
171
+ export declare type InputVariant = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'ghost';
151
172
 
152
173
  /**
153
174
  * Merges multiple CSS class strings and removes duplicates while preserving order.
@@ -168,192 +189,48 @@ export declare function getThemeValue(theme: Theme, path: string): string | unde
168
189
  export declare function mergeClasses(...classes: string[]): string;
169
190
 
170
191
  /**
171
- * Merges theme overrides with base theme
172
- * Performs deep merge to allow partial customization
173
- */
174
- export declare function mergeTheme(baseTheme: Theme, override: ThemeOverride): Theme;
175
-
176
- export declare interface Shadows {
177
- sm: string;
178
- md: string;
179
- lg: string;
180
- }
181
-
182
- export declare interface SpacingScale {
183
- xs: string;
184
- sm: string;
185
- md: string;
186
- lg: string;
187
- xl: string;
188
- }
189
-
190
- /**
191
- * Complete theme configuration
192
- */
193
- export declare interface Theme {
194
- colors: ColorPalette;
195
- spacing: SpacingScale;
196
- borderRadius: BorderRadius;
197
- typography: Typography;
198
- shadows: Shadows;
199
- }
200
-
201
- export declare const ThemeContext: Context<ThemeContextValue | undefined>;
202
-
203
- export declare interface ThemeContextValue {
204
- /** Current active theme */
205
- theme: Theme;
206
- /** Current theme mode */
207
- mode: ThemeMode;
208
- /** Set theme mode */
209
- setMode: (mode: ThemeMode) => void;
210
- /** Update theme with overrides */
211
- updateTheme: (override: ThemeOverride) => void;
212
- /** Reset theme to default */
213
- resetTheme: () => void;
214
- /** Whether dark mode is active */
215
- isDark: boolean;
216
- }
217
-
218
- /**
219
- * Theme mode options
220
- */
221
- export declare type ThemeMode = 'light' | 'dark' | 'auto';
222
-
223
- /**
224
- * Partial theme for customization - allows users to override only specific parts
225
- */
226
- export declare type ThemeOverride = {
227
- colors?: Partial<ColorPalette>;
228
- spacing?: Partial<SpacingScale>;
229
- borderRadius?: Partial<BorderRadius>;
230
- typography?: Partial<Typography>;
231
- shadows?: Partial<Shadows>;
232
- };
233
-
234
- /**
235
- * Theme Provider component that manages theme state and applies themes to the DOM
192
+ * A customizable toggle component.
236
193
  *
237
- * @example
238
- * ```tsx
239
- * import { ThemeProvider } from 'klip-components';
194
+ * It functions as a controlled component, with its state managed by the `checked`
195
+ * and `onChange` props. It supports labels, custom sizes, colors, and all
196
+ * standard input attributes like `disabled` or `aria-label`.
240
197
  *
241
- * function App() {
242
- * return (
243
- * <ThemeProvider
244
- * defaultMode="auto"
245
- * theme={{
246
- * colors: {
247
- * primary: { main: '#ff6b6b', hover: '#ff5252' }
248
- * }
249
- * }}
250
- * >
251
- * <YourApp />
252
- * </ThemeProvider>
253
- * );
254
- * }
255
- * ```
256
- */
257
- export declare function ThemeProvider({ children, defaultMode, theme, darkTheme, }: ThemeProviderProps): JSX.Element;
258
-
259
- export declare interface ThemeProviderProps {
260
- /** Children components */
261
- children: default_2.ReactNode;
262
- /** Initial theme mode */
263
- defaultMode?: ThemeMode;
264
- /** Initial theme overrides */
265
- theme?: ThemeOverride;
266
- /** Custom dark theme (overrides default) */
267
- darkTheme?: Theme;
268
- }
269
-
270
- /**
271
- * A simple theme toggle button component that demonstrates theme usage
272
- * Shows how to use the useTheme hook and access theme values
273
- */
274
- export declare function ThemeToggle({ className }: ThemeToggleProps): JSX.Element;
275
-
276
- export declare interface ThemeToggleProps {
277
- className?: string;
278
- }
279
-
280
- export declare interface Typography {
281
- fontFamily: string;
282
- fontSize: {
283
- sm: string;
284
- base: string;
285
- lg: string;
286
- };
287
- }
288
-
289
- /**
290
- * Hook to access theme context
291
- * Must be used within a ThemeProvider
198
+ * @param {ToggleProps} props The props for the component.
199
+ * @returns {React.ReactElement} The rendered switch component.
292
200
  *
293
201
  * @example
294
- * ```tsx
295
- * function MyComponent() {
296
- * const { theme, isDark, setMode } = useTheme();
202
+ * // Example of a parent component managing the switch's state.
203
+ * import { useState } from 'react';
297
204
  *
298
- * return (
299
- * <div style={{ color: theme.colors.primary.main }}>
300
- * <button onClick={() => setMode(isDark ? 'light' : 'dark')}>
301
- * Toggle theme
302
- * </button>
303
- * </div>
304
- * );
305
- * }
306
- * ```
307
- */
308
- export declare function useTheme(): ThemeContextValue;
309
-
310
- /**
311
- * Hook to get theme-aware CSS variables
312
- *
313
- * @example
314
- * ```tsx
315
- * function MyComponent() {
316
- * const cssVars = useThemeVariables();
205
+ * const MyComponent = () => {
206
+ * const [isEnabled, setIsEnabled] = useState(false);
317
207
  *
318
208
  * return (
319
- * <div style={{
320
- * backgroundColor: cssVars.primaryColor,
321
- * padding: cssVars.spacingMd,
322
- * }}>
323
- * Content
324
- * </div>
209
+ * <Switch
210
+ * checked={isEnabled}
211
+ * onChange={setIsEnabled}
212
+ * label="Enable Feature"
213
+ * labelPosition="right"
214
+ * aria-label="Feature Toggle"
215
+ * />
325
216
  * );
326
- * }
327
- * ```
328
- */
329
- export declare function useThemeVariables(): {
330
- primaryColor: string;
331
- primaryHover: string;
332
- secondaryColor: string;
333
- secondaryHover: string;
334
- successColor: string;
335
- dangerColor: string;
336
- warningColor: string;
337
- infoColor: string;
338
- lightColor: string;
339
- darkColor: string;
340
- linkColor: string;
341
- spacingXs: string;
342
- spacingSm: string;
343
- spacingMd: string;
344
- spacingLg: string;
345
- spacingXl: string;
346
- borderRadiusSm: string;
347
- borderRadius: string;
348
- borderRadiusLg: string;
349
- borderRadiusFull: string;
350
- fontFamily: string;
351
- fontSizeSm: string;
352
- fontSizeBase: string;
353
- fontSizeLg: string;
354
- shadowSm: string;
355
- shadowMd: string;
356
- shadowLg: string;
357
- };
217
+ * };
218
+ */
219
+ export declare const Toggle: React.FC<ToggleProps>;
220
+
221
+ export declare interface ToggleProps extends HtmlToggle {
222
+ /** Color of the toggle when in the "on" state. */
223
+ color?: string;
224
+ /** The total width of the toggle. Can be any valid CSS unit (e.g., '4rem', '60px'). */
225
+ size?: string;
226
+ /** Determines if the toggle is in the "on" (true) or "off" (false) state. */
227
+ checked?: boolean;
228
+ /** Callback function that is invoked when the toggle's state changes. */
229
+ onChange?: (checked: boolean) => void;
230
+ /** Optional text label to display next to the toggle. */
231
+ label?: string;
232
+ /** Position of the label relative to the toggle. Defaults to 'right'. */
233
+ labelPosition?: 'left' | 'right' | 'top' | 'bottom';
234
+ }
358
235
 
359
236
  export { }
@@ -1 +1 @@
1
- "use strict";var r=Object.defineProperty,e=Object.defineProperties,o=Object.getOwnPropertyDescriptors,s=Object.getOwnPropertySymbols,l=Object.prototype.hasOwnProperty,n=Object.prototype.propertyIsEnumerable,a=(e,o,s)=>o in e?r(e,o,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[o]=s,t=(r,e)=>{for(var o in e||(e={}))l.call(e,o)&&a(r,o,e[o]);if(s)for(var o of s(e))n.call(e,o)&&a(r,o,e[o]);return r},i=(r,s)=>e(r,o(s));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react/jsx-runtime"),c=require("react");function u(r){var e,o,s="";if("string"==typeof r||"number"==typeof r)s+=r;else if("object"==typeof r)if(Array.isArray(r)){var l=r.length;for(e=0;e<l;e++)r[e]&&(o=u(r[e]))&&(s&&(s+=" "),s+=o)}else for(o in r)r[o]&&(s&&(s+=" "),s+=o);return s}function p(){for(var r,e,o=0,s="",l=arguments.length;o<l;o++)(r=arguments[o])&&(e=u(r))&&(s&&(s+=" "),s+=e);return s}function m(...r){const e=r.join(" ").split(" ").filter(Boolean);return[...new Set(e)].join(" ")}function g(...r){return m(p(...r))}const y=c.createContext(void 0);function f(){const r=c.useContext(y);if(void 0===r)throw new Error("useTheme must be used within a ThemeProvider");return r}const h={colors:{primary:{main:"#2d99ff",hover:"#2682d9"},secondary:{main:"#f5f7fa",hover:"#e3e5e8"},semantic:{success:"#18a558",danger:"#db1f48",warning:"#e9b210",info:"#75e6da",light:"#ffffff",dark:"#1a1926",link:"#2d99ff"}},spacing:{xs:"0.25rem",sm:"0.5rem",md:"1rem",lg:"1.5rem",xl:"2rem"},borderRadius:{sm:"4px",base:"12px",lg:"20px",full:"50%"},typography:{fontFamily:"Nunito, -apple-system, BlinkMacSystemFont, 'Segoe UI',\n Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",fontSize:{sm:"0.875rem",base:"1rem",lg:"1.125rem"}},shadows:{sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1)"}},v={colors:{primary:{main:"#2d99ff",hover:"#2682d9"},secondary:{main:"#f5f7fa",hover:"#e3e5e8"},semantic:{success:"#18a558",danger:"#db1f48",warning:"#e9b210",info:"#75e6da",light:"#ffffff",dark:"#1a1926",link:"#2d99ff"}},spacing:{xs:"0.25rem",sm:"0.5rem",md:"1rem",lg:"1.5rem",xl:"2rem"},borderRadius:{sm:"4px",base:"12px",lg:"20px",full:"50%"},typography:{fontFamily:"Nunito, -apple-system, BlinkMacSystemFont, 'Segoe UI',\n Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",fontSize:{sm:"0.875rem",base:"1rem",lg:"1.125rem"}},shadows:{sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1)"}};function b(r,e){var o,s,l,n;return{colors:{primary:t(t({},r.colors.primary),null==(o=e.colors)?void 0:o.primary),secondary:t(t({},r.colors.secondary),null==(s=e.colors)?void 0:s.secondary),semantic:t(t({},r.colors.semantic),null==(l=e.colors)?void 0:l.semantic)},spacing:t(t({},r.spacing),e.spacing),borderRadius:t(t({},r.borderRadius),e.borderRadius),typography:i(t(t({},r.typography),e.typography),{fontSize:t(t({},r.typography.fontSize),null==(n=e.typography)?void 0:n.fontSize)}),shadows:t(t({},r.shadows),e.shadows)}}function x(){return"undefined"==typeof window?"light":window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}exports.Button=r=>{var e=r,{variant:o="primary",className:a="",children:c}=e,u=((r,e)=>{var o={};for(var a in r)l.call(r,a)&&e.indexOf(a)<0&&(o[a]=r[a]);if(null!=r&&s)for(var a of s(r))e.indexOf(a)<0&&n.call(r,a)&&(o[a]=r[a]);return o})(e,["variant","className","children"]);return d.jsx("button",i(t({className:g("rounded btn",`btn-${o}`,a)},u),{children:c}))},exports.ThemeContext=y,exports.ThemeProvider=function({children:r,defaultMode:e="auto",theme:o,darkTheme:s=v}){const[l,n]=c.useState(e),[a,i]=c.useState(o||{}),[u,p]=c.useState(()=>"dark"===x()),m="dark"===l||"auto"===l&&u,g=b(m?s:h,a),f=c.useCallback(r=>{n(r)},[]),$=c.useCallback(r=>{i(e=>b(t(t({},h),e),r))},[]),w=c.useCallback(()=>{i({})},[]);c.useEffect(()=>{if("undefined"==typeof window)return;const r=window.matchMedia("(prefers-color-scheme: dark)"),e=r=>{p(r.matches)};return r.addEventListener("change",e),()=>r.removeEventListener("change",e)},[]),c.useLayoutEffect(()=>{const r=function(r,e=":root"){var o,s,l,n,a,t,i,d,c,u,p,m,g,y,f,h,v,b,x,$,w,S,k,P,C,z,R,j,T,E,O,M,F,L,I,A,N,B,D,U,H,V,q,X,G,J,K,Q,W,Y,Z,_,rr,er,or,sr,lr,nr,ar,tr,ir,dr,cr,ur,pr,mr,gr,yr;return`${e}{${[`--color-primary:${null!=(l=null==(s=null==(o=r.colors)?void 0:o.primary)?void 0:s.main)?l:""}`,`--hover-primary:${null!=(t=null==(a=null==(n=r.colors)?void 0:n.primary)?void 0:a.hover)?t:""}`,`--color-secondary:${null!=(c=null==(d=null==(i=r.colors)?void 0:i.secondary)?void 0:d.main)?c:""}`,`--hover-secondary:${null!=(m=null==(p=null==(u=r.colors)?void 0:u.secondary)?void 0:p.hover)?m:""}`,`--color-success:${null!=(f=null==(y=null==(g=r.colors)?void 0:g.semantic)?void 0:y.success)?f:""}`,`--color-danger:${null!=(b=null==(v=null==(h=r.colors)?void 0:h.semantic)?void 0:v.danger)?b:""}`,`--color-warning:${null!=(w=null==($=null==(x=r.colors)?void 0:x.semantic)?void 0:$.warning)?w:""}`,`--color-info:${null!=(P=null==(k=null==(S=r.colors)?void 0:S.semantic)?void 0:k.info)?P:""}`,`--color-light:${null!=(R=null==(z=null==(C=r.colors)?void 0:C.semantic)?void 0:z.light)?R:""}`,`--color-dark:${null!=(E=null==(T=null==(j=r.colors)?void 0:j.semantic)?void 0:T.dark)?E:""}`,`--color-link:${null!=(F=null==(M=null==(O=r.colors)?void 0:O.semantic)?void 0:M.link)?F:""}`,`--rounded:${null!=(I=null==(L=r.borderRadius)?void 0:L.base)?I:""}`,`--rounded-sm:${null!=(N=null==(A=r.borderRadius)?void 0:A.sm)?N:""}`,`--rounded-lg:${null!=(D=null==(B=r.borderRadius)?void 0:B.lg)?D:""}`,`--rounded-full:${null!=(H=null==(U=r.borderRadius)?void 0:U.full)?H:""}`,`--font-family:${null!=(q=null==(V=r.typography)?void 0:V.fontFamily)?q:""}`,`--font-sm:${null!=(J=null==(G=null==(X=r.typography)?void 0:X.fontSize)?void 0:G.sm)?J:""}`,`--font-base:${null!=(W=null==(Q=null==(K=r.typography)?void 0:K.fontSize)?void 0:Q.base)?W:""}`,`--font-lg:${null!=(_=null==(Z=null==(Y=r.typography)?void 0:Y.fontSize)?void 0:Z.lg)?_:""}`,`--spacing-xs:${null!=(er=null==(rr=r.spacing)?void 0:rr.xs)?er:""}`,`--spacing-sm:${null!=(sr=null==(or=r.spacing)?void 0:or.sm)?sr:""}`,`--spacing-md:${null!=(nr=null==(lr=r.spacing)?void 0:lr.md)?nr:""}`,`--spacing-lg:${null!=(tr=null==(ar=r.spacing)?void 0:ar.lg)?tr:""}`,`--spacing-xl:${null!=(dr=null==(ir=r.spacing)?void 0:ir.xl)?dr:""}`,`--shadow-sm:${null!=(ur=null==(cr=r.shadows)?void 0:cr.sm)?ur:""}`,`--shadow-md:${null!=(mr=null==(pr=r.shadows)?void 0:pr.md)?mr:""}`,`--shadow-lg:${null!=(yr=null==(gr=r.shadows)?void 0:gr.lg)?yr:""}`].join(";")}}`}(g),e=document.getElementById("klip-custom-theme");e&&e.remove();const o=document.createElement("style");o.id="klip-custom-theme",o.textContent=r,document.head.appendChild(o)},[g]);const S={theme:g,mode:l,setMode:f,updateTheme:$,resetTheme:w,isDark:m};return d.jsx(y.Provider,{value:S,children:r})},exports.ThemeToggle=function({className:r}){const{mode:e,setMode:o,isDark:s}=f();return d.jsx("button",{onClick:()=>{o("auto"===e?"light":"light"===e?"dark":"auto")},className:g("px-3 py-2 rounded-md text-sm font-medium transition-colors","bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600","text-gray-900 dark:text-gray-100",r),title:`Current theme: ${e}${"auto"===e?` (${s?"dark":"light"})`:""}`,children:(()=>{switch(e){case"light":return"☀️ Light";case"dark":return"🌙 Dark";case"auto":return`🔄 Auto (${s?"Dark":"Light"})`;default:return"Theme"}})()})},exports.applyThemeToDOM=function(r,e=document.documentElement){e.style.setProperty("--primary-color",r.colors.primary.main),e.style.setProperty("--primary-hover",r.colors.primary.hover),e.style.setProperty("--secondary-color",r.colors.secondary.main),e.style.setProperty("--secondary-hover",r.colors.secondary.hover),e.style.setProperty("--success-color",r.colors.semantic.success),e.style.setProperty("--danger-color",r.colors.semantic.danger),e.style.setProperty("--warning-color",r.colors.semantic.warning),e.style.setProperty("--info-color",r.colors.semantic.info),e.style.setProperty("--spacing-xs",r.spacing.xs),e.style.setProperty("--spacing-sm",r.spacing.sm),e.style.setProperty("--spacing-md",r.spacing.md),e.style.setProperty("--spacing-lg",r.spacing.lg),e.style.setProperty("--spacing-xl",r.spacing.xl),e.style.setProperty("--border-radius-sm",r.borderRadius.sm),e.style.setProperty("--border-radius",r.borderRadius.base),e.style.setProperty("--border-radius-lg",r.borderRadius.lg),e.style.setProperty("--font-family",r.typography.fontFamily),e.style.setProperty("--font-size-sm",r.typography.fontSize.sm),e.style.setProperty("--font-size-base",r.typography.fontSize.base),e.style.setProperty("--font-size-lg",r.typography.fontSize.lg),e.style.setProperty("--shadow-sm",r.shadows.sm),e.style.setProperty("--shadow-md",r.shadows.md),e.style.setProperty("--shadow-lg",r.shadows.lg)},exports.clsx=p,exports.cn=g,exports.createCSSVariable=function(r){return`--${r.replace(/\./g,"-")}`},exports.darkTheme=v,exports.defaultTheme=h,exports.detectColorScheme=x,exports.getThemeValue=function(r,e){const o=e.split(".");let s=r;for(const l of o){if("object"!=typeof s||null===s||!(l in s))return;s=s[l]}return"string"==typeof s?s:void 0},exports.mergeClasses=m,exports.mergeTheme=b,exports.useTheme=f,exports.useThemeVariables=function(){const{theme:r}=f();return{primaryColor:`var(--primary-color, ${r.colors.primary.main})`,primaryHover:`var(--primary-hover, ${r.colors.primary.hover})`,secondaryColor:`var(--secondary-color, ${r.colors.secondary.main})`,secondaryHover:`var(--secondary-hover, ${r.colors.secondary.hover})`,successColor:`var(--success-color, ${r.colors.semantic.success})`,dangerColor:`var(--danger-color, ${r.colors.semantic.danger})`,warningColor:`var(--warning-color, ${r.colors.semantic.warning})`,infoColor:`var(--info-color, ${r.colors.semantic.info})`,lightColor:`var(--light-color, ${r.colors.semantic.light})`,darkColor:`var(--dark-color, ${r.colors.semantic.dark})`,linkColor:`var(--link-color, ${r.colors.semantic.link})`,spacingXs:`var(--spacing-xs, ${r.spacing.xs})`,spacingSm:`var(--spacing-sm, ${r.spacing.sm})`,spacingMd:`var(--spacing-md, ${r.spacing.md})`,spacingLg:`var(--spacing-lg, ${r.spacing.lg})`,spacingXl:`var(--spacing-xl, ${r.spacing.xl})`,borderRadiusSm:`var(--border-radius-sm, ${r.borderRadius.sm})`,borderRadius:`var(--border-radius, ${r.borderRadius.base})`,borderRadiusLg:`var(--border-radius-lg, ${r.borderRadius.lg})`,borderRadiusFull:`var(--border-radius-full, ${r.borderRadius.full})`,fontFamily:`var(--font-family, ${r.typography.fontFamily})`,fontSizeSm:`var(--font-size-sm, ${r.typography.fontSize.sm})`,fontSizeBase:`var(--font-size-base, ${r.typography.fontSize.base})`,fontSizeLg:`var(--font-size-lg, ${r.typography.fontSize.lg})`,shadowSm:`var(--shadow-sm, ${r.shadows.sm})`,shadowMd:`var(--shadow-md, ${r.shadows.md})`,shadowLg:`var(--shadow-lg, ${r.shadows.lg})`}};
1
+ "use strict";var e=Object.defineProperty,r=Object.defineProperties,t=Object.getOwnPropertyDescriptors,n=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable,l=(r,t,n)=>t in r?e(r,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):r[t]=n,i=(e,r)=>{for(var t in r||(r={}))s.call(r,t)&&l(e,t,r[t]);if(n)for(var t of n(r))a.call(r,t)&&l(e,t,r[t]);return e},c=(e,r)=>{var t={};for(var l in e)s.call(e,l)&&r.indexOf(l)<0&&(t[l]=e[l]);if(null!=e&&n)for(var l of n(e))r.indexOf(l)<0&&a.call(e,l)&&(t[l]=e[l]);return t};Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),p=require("react");function u(e){var r,t,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var s=e.length;for(r=0;r<s;r++)e[r]&&(t=u(e[r]))&&(n&&(n+=" "),n+=t)}else for(t in e)e[t]&&(n&&(n+=" "),n+=t);return n}function d(){for(var e,r,t=0,n="",s=arguments.length;t<s;t++)(e=arguments[t])&&(r=u(e))&&(n&&(n+=" "),n+=r);return n}function f(...e){const r=e.join(" ").split(" ").filter(Boolean);return[...new Set(r)].join(" ")}function h(...e){return f(d(...e))}exports.Button=e=>{var n,s=e,{variant:a="primary",size:l="md",startIcon:p,endIcon:u,className:d="",children:f}=s,x=c(s,["variant","size","startIcon","endIcon","className","children"]);return o.jsxs("button",(n=i({className:h("rounded btn",`btn-${a}`,`btn-${l}`,d)},x),r(n,t({children:[p&&o.jsx("span",{className:"btn-icon-start",children:p}),f,u&&o.jsx("span",{className:"btn-icon-end",children:u})]}))))},exports.ButtonSelect=({options:e,value:r,onChange:t,disabled:n=!1,multiple:s=!1})=>{const a=e=>Array.isArray(r)?r.includes(e):e===r;return o.jsx("div",{className:"button-select "+(n?"disabled":""),children:e.map(({value:e,child:l})=>o.jsx("button",{className:"button-select-option "+(a(e)?"selected":""),onClick:()=>(e=>{if(n)return;if(!s)return void t(e);const a=Array.isArray(r)?r:[],l=a.includes(e)?a.filter(r=>r!==e):[...a,e];t(l)})(e),disabled:n,type:"button",children:l},e))})},exports.Input=e=>{var r=e,{variant:t="primary",type:n="text",label:s,prefix:a,suffix:l,helperText:u,className:d,onChange:f,id:x}=r,b=c(r,["variant","type","label","prefix","suffix","helperText","className","onChange","id"]);const m=p.useId(),j=x||`input-${m}`,v=h("form-field",{prefix:!!a,suffix:!!l},{[`variant-${t}`]:t},d);return o.jsxs("article",{className:"input-container",children:[s&&o.jsx("label",{htmlFor:j,className:"input-label",children:s}),o.jsxs("section",{className:"input-wrapper",children:[a&&o.jsx("article",{className:"input-addon input-prefix",children:a}),o.jsx("input",i({id:j,type:n,className:v,onChange:e=>null==f?void 0:f(e.target.value)},b)),l&&o.jsx("article",{className:"input-addon input-suffix",children:l})]}),u&&o.jsx("small",{className:"input-helper-text",children:u})]})},exports.Toggle=e=>{var r=e,{color:t="var(--color-primary)",size:n="3.75rem",checked:s=!1,onChange:a,label:l,labelPosition:p="right",className:u}=r,d=c(r,["color","size","checked","onChange","label","labelPosition","className"]);return o.jsxs("label",{className:h("switch-container",p,u),children:[o.jsxs("div",{className:"toggle-switch",style:{"--switch-size":n,"--switch-color":t},children:[o.jsx("input",i({type:"checkbox",role:"switch",checked:s,onChange:e=>null==a?void 0:a(e.target.checked)},d)),o.jsx("span",{className:"slider"})]}),l&&o.jsx("span",{className:"switch-label",children:l})]})},exports.clsx=d,exports.cn=h,exports.mergeClasses=f;