@scalably/ui 0.1.0 → 0.2.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Scalably
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Scalably UI Component Library
2
2
 
3
+ ![npm version](https://img.shields.io/npm/v/@scalably/ui)
4
+ ![license](https://img.shields.io/npm/l/@scalably/ui)
5
+
3
6
  A modern, accessible, and fully isolated React component library built with TypeScript and Tailwind CSS. Designed to work seamlessly across multiple projects without style conflicts.
4
7
 
5
8
  ## 🚀 Features
@@ -20,19 +23,11 @@ npm install @scalably/ui
20
23
 
21
24
  ## 🎨 Usage
22
25
 
23
- ### 1. Import the CSS
26
+ ### 1. Use Components (Styles Auto-Injected)
24
27
 
25
- Add the component library styles to your main entry point:
28
+ The `ScalablyUIProvider` automatically injects styles into `document.head`, so you don't need to manually import CSS. This ensures styles work correctly in portals (modals, tooltips, etc.). No wrapper or scope class is required—just wrap your app once.
26
29
 
27
30
  ```tsx
28
- // In your main.tsx, App.tsx, or index.tsx
29
- import "@scalably/ui/styles";
30
- ```
31
-
32
- ### 2. Use Components
33
-
34
- ```tsx
35
- import "@scalably/ui/styles";
36
31
  import { ScalablyUIProvider, Form, FormField, Input, Button, ToastContainer, Toast } from "@scalably/ui";
37
32
 
38
33
  export default function App() {
@@ -55,28 +50,40 @@ export default function App() {
55
50
  }
56
51
  ```
57
52
 
58
- ### 3. Add the provider once (recommended)
53
+ ### 2. Optional: Manual CSS Import
59
54
 
60
- Instead of adding the `sui-scope` class manually, wrap your app with the provider:
55
+ If you prefer to import CSS manually (e.g., for better control or SSR optimization), you can disable automatic injection:
61
56
 
62
57
  ```tsx
58
+ // In your main.tsx, App.tsx, or index.tsx
63
59
  import "@scalably/ui/styles";
64
60
  import { ScalablyUIProvider } from "@scalably/ui";
65
61
 
66
62
  export default function App() {
67
- return <ScalablyUIProvider>{/* your app */}</ScalablyUIProvider>;
63
+ return (
64
+ <ScalablyUIProvider injectStyles={false}>
65
+ {/* your app */}
66
+ </ScalablyUIProvider>
67
+ );
68
68
  }
69
69
  ```
70
70
 
71
- Optional no extra DOM element:
71
+ ### 3. Portal Support
72
+
73
+ Styles automatically work in portaled components (modals, tooltips, popovers, etc.) because:
74
+ - Styles are injected globally into `document.head`
75
+ - CSS variables propagate to all elements
76
+ - No parent selector dependencies
72
77
 
73
78
  ```tsx
74
- <ScalablyUIProvider asChild>
75
- <main>{/* your app */}</main>
76
- {/* merges the scope onto <main> */}
77
- </ScalablyUIProvider>
79
+ // Tooltips, modals, and other portaled components work automatically
80
+ <Tooltip content="This works in portals!" portal>
81
+ <Button>Hover me</Button>
82
+ </Tooltip>
78
83
  ```
79
84
 
85
+ Note: Toasts in this library are intentionally declarative. Render a `Toast` inside a `ToastContainer` when you want it visible (e.g., based on component state). This avoids hidden globals and keeps UI state predictable. If you prefer an imperative API, you can wrap your own tiny helper around local state to toggle a `Toast` component.
86
+
80
87
  ### 4. React import guidance
81
88
 
82
89
  If you reference the React namespace (e.g., `React.useState`, `React.forwardRef`, `React.SVGProps`) add an explicit import to avoid UMD global errors:
@@ -145,13 +152,11 @@ All components use prefixed Tailwind classes (`sui-*`) to ensure complete style
145
152
 
146
153
  ```tsx
147
154
  // ✅ Correct - components are properly isolated
148
- <div className="sui-scope">
149
- <Button>Isolated Button</Button>
150
- </div>
155
+ <Button>Isolated Button</Button>
151
156
 
152
- // Avoid - mixing prefixed and non-prefixed classes
153
- <div className="p-4"> {/* This won't conflict */}
154
- <Button>Button with ui-* classes</Button>
157
+ // Your global styles won't break the components
158
+ <div className="p-4 bg-red-500">
159
+ <Button>Isolated Button</Button>
155
160
  </div>
156
161
  ```
157
162
 
@@ -222,14 +227,14 @@ Visit our Storybook documentation for:
222
227
 
223
228
  ### Colors
224
229
 
225
- - **Primary**: `#36499B` - Main brand color for primary actions
226
- - **Secondary**: `#F2F6FC` - Light background colors with multiple levels
227
- - **Success**: `#22BC4D` - Green for positive actions and success states
228
- - **Warning**: `#FF7A00` - Orange for caution and in-progress states
229
- - **Info**: `#2772F0` - Blue for informational content
230
- - **Error**: `#EA3540` - Red for destructive actions and errors
231
- - **Inactive**: `#777E90` - Gray for inactive or completed states
232
- - **Disabled**: `#B2BBC7` - Light gray for disabled elements
230
+ - **Primary**: `#36499B` Main brand color for primary actions (`sui-bg-primary`, `sui-text-primary`)
231
+ - **Secondary**: `#F2F6FC` Light background colors (`sui-bg-secondary`, `sui-text-secondary`)
232
+ - **Success**: `#22BC4D` Positive actions and success states (`sui-bg-success`, `sui-text-success`)
233
+ - **Warning**: `#FF7A00` Caution and in-progress states (`sui-bg-warning`, `sui-text-warning`)
234
+ - **Info**: `#2772F0` Informational content (`sui-bg-info`, `sui-text-info`)
235
+ - **Error**: `#EA3540` Destructive actions and errors (`sui-bg-error`, `sui-text-error`)
236
+ - **Inactive**: `#777E90` Inactive or completed states (`sui-text-inactive`, `sui-border-inactive`)
237
+ - **Disabled**: `#B2BBC7` Disabled elements (`sui-text-disabled`, `sui-border-disabled`)
233
238
 
234
239
  ### Typography
235
240
 
@@ -243,10 +248,12 @@ Visit our Storybook documentation for:
243
248
 
244
249
  The library uses a custom Tailwind configuration with:
245
250
 
246
- - **Prefix**: `sui-` for all utility classes
247
- - **Important**: `.sui-scope` for style isolation
251
+ - **Prefix**: `sui-` for all utility classes (provides style isolation)
252
+ - **Global Styles**: Automatically injected via `ScalablyUIProvider`
253
+ - **CSS Variables**: Design tokens available globally for theming
248
254
  - **Custom Colors**: Brand-specific color palette
249
255
  - **Custom Shadows**: Soft, medium, and strong shadow variants
256
+ - **Portal Support**: Styles work in portaled components (modals, tooltips, etc.)
250
257
 
251
258
  ### Build Configuration
252
259
 
package/dist/index.d.cts CHANGED
@@ -3,7 +3,6 @@ import { ReactNode } from 'react';
3
3
  import * as class_variance_authority_types from 'class-variance-authority/types';
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
- import { ClassValue } from 'clsx';
7
6
  import * as date_fns from 'date-fns';
8
7
  export { addMonths, endOfMonth, isSameDay, startOfMonth } from 'date-fns';
9
8
 
@@ -142,7 +141,7 @@ interface StatusBadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "
142
141
  declare const StatusBadge: react.ForwardRefExoticComponent<StatusBadgeProps & react.RefAttributes<HTMLSpanElement>>;
143
142
 
144
143
  declare const buttonVariants: (props?: ({
145
- variant?: "default" | "link" | "text" | "outline" | "destructive" | "secondary" | null | undefined;
144
+ variant?: "link" | "text" | "outline" | "default" | "destructive" | "secondary" | null | undefined;
146
145
  size?: "icon" | "md" | "lg" | null | undefined;
147
146
  } & class_variance_authority_types.ClassProp) | undefined) => string;
148
147
  type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
@@ -750,6 +749,13 @@ interface FileUploadProps {
750
749
  * This runs after internal type/size validation.
751
750
  */
752
751
  onValidateFile?: (file: File) => FileUploadError | null | undefined;
752
+ /** Enable video thumbnail capture UI via modal when a video file is selected. */
753
+ enableVideoThumbnail?: boolean;
754
+ /**
755
+ * Called when a thumbnail is captured from the selected video's current frame.
756
+ * Provides the Blob (image/jpeg) and a data URL for immediate preview.
757
+ */
758
+ onThumbnailCapture?: (thumbnail: Blob, dataUrl: string, file: FileUploadFile) => void;
753
759
  }
754
760
  /**
755
761
  * File upload component with drag-and-drop, validation, previews, and accessibility support.
@@ -1569,29 +1575,55 @@ declare const ViewToggle: React.FC<ViewToggleProps>;
1569
1575
 
1570
1576
  interface ScalablyUIProviderProps {
1571
1577
  children: React.ReactNode;
1578
+ /**
1579
+ * @deprecated `className` is no longer needed. Styles are applied globally.
1580
+ */
1572
1581
  className?: string;
1573
1582
  /**
1574
- * When true, merges the scope class onto the single child instead of adding an extra wrapper div.
1583
+ * @deprecated `asChild` is no longer needed. Styles are applied globally.
1575
1584
  */
1576
1585
  asChild?: boolean;
1586
+ /**
1587
+ * When true, automatically injects the component library styles into document.head.
1588
+ * This ensures styles work in portals (modals, tooltips, etc.) without requiring
1589
+ * manual CSS imports. Defaults to true.
1590
+ */
1591
+ injectStyles?: boolean;
1577
1592
  }
1578
1593
  /**
1579
1594
  * ScalablyUIProvider
1580
1595
  *
1581
- * Adds the required `sui-scope` wrapper so prefixed Tailwind styles apply.
1596
+ * Provides the Scalably UI component library context and automatically injects styles.
1597
+ * All classes are globally prefixed (`sui-*`), so no wrapper element is required.
1598
+ *
1599
+ * Features:
1600
+ * - Automatically injects CSS into document.head (prevents double-injection)
1601
+ * - Works with SSR (only injects on client-side)
1602
+ * - Ensures styles are available for portaled components
1603
+ * - Maintains style isolation via 'sui-' prefix
1582
1604
  *
1583
1605
  * Usage:
1606
+ * ```tsx
1584
1607
  * <ScalablyUIProvider>
1585
1608
  * <App />
1586
1609
  * </ScalablyUIProvider>
1610
+ * ```
1587
1611
  *
1588
- * Or to avoid an extra DOM node:
1589
- * <ScalablyUIProvider asChild>
1590
- * <main />
1612
+ * To disable automatic style injection (if you import CSS manually):
1613
+ * ```tsx
1614
+ * <ScalablyUIProvider injectStyles={false}>
1615
+ * <App />
1591
1616
  * </ScalablyUIProvider>
1617
+ * ```
1592
1618
  */
1593
1619
  declare const ScalablyUIProvider: React.FC<ScalablyUIProviderProps>;
1594
1620
 
1621
+ /**
1622
+ * Type for class values accepted by clsx
1623
+ */
1624
+ type ClassValue = ClassArray | ClassDictionary | string | number | bigint | null | boolean | undefined;
1625
+ type ClassDictionary = Record<string, unknown>;
1626
+ type ClassArray = ClassValue[];
1595
1627
  /**
1596
1628
  * Utility function to merge Tailwind CSS classes intelligently
1597
1629
  * Combines clsx for conditional classes and tailwind-merge for conflict resolution
package/dist/index.d.ts CHANGED
@@ -3,7 +3,6 @@ import { ReactNode } from 'react';
3
3
  import * as class_variance_authority_types from 'class-variance-authority/types';
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
- import { ClassValue } from 'clsx';
7
6
  import * as date_fns from 'date-fns';
8
7
  export { addMonths, endOfMonth, isSameDay, startOfMonth } from 'date-fns';
9
8
 
@@ -142,7 +141,7 @@ interface StatusBadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "
142
141
  declare const StatusBadge: react.ForwardRefExoticComponent<StatusBadgeProps & react.RefAttributes<HTMLSpanElement>>;
143
142
 
144
143
  declare const buttonVariants: (props?: ({
145
- variant?: "default" | "link" | "text" | "outline" | "destructive" | "secondary" | null | undefined;
144
+ variant?: "link" | "text" | "outline" | "default" | "destructive" | "secondary" | null | undefined;
146
145
  size?: "icon" | "md" | "lg" | null | undefined;
147
146
  } & class_variance_authority_types.ClassProp) | undefined) => string;
148
147
  type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
@@ -750,6 +749,13 @@ interface FileUploadProps {
750
749
  * This runs after internal type/size validation.
751
750
  */
752
751
  onValidateFile?: (file: File) => FileUploadError | null | undefined;
752
+ /** Enable video thumbnail capture UI via modal when a video file is selected. */
753
+ enableVideoThumbnail?: boolean;
754
+ /**
755
+ * Called when a thumbnail is captured from the selected video's current frame.
756
+ * Provides the Blob (image/jpeg) and a data URL for immediate preview.
757
+ */
758
+ onThumbnailCapture?: (thumbnail: Blob, dataUrl: string, file: FileUploadFile) => void;
753
759
  }
754
760
  /**
755
761
  * File upload component with drag-and-drop, validation, previews, and accessibility support.
@@ -1569,29 +1575,55 @@ declare const ViewToggle: React.FC<ViewToggleProps>;
1569
1575
 
1570
1576
  interface ScalablyUIProviderProps {
1571
1577
  children: React.ReactNode;
1578
+ /**
1579
+ * @deprecated `className` is no longer needed. Styles are applied globally.
1580
+ */
1572
1581
  className?: string;
1573
1582
  /**
1574
- * When true, merges the scope class onto the single child instead of adding an extra wrapper div.
1583
+ * @deprecated `asChild` is no longer needed. Styles are applied globally.
1575
1584
  */
1576
1585
  asChild?: boolean;
1586
+ /**
1587
+ * When true, automatically injects the component library styles into document.head.
1588
+ * This ensures styles work in portals (modals, tooltips, etc.) without requiring
1589
+ * manual CSS imports. Defaults to true.
1590
+ */
1591
+ injectStyles?: boolean;
1577
1592
  }
1578
1593
  /**
1579
1594
  * ScalablyUIProvider
1580
1595
  *
1581
- * Adds the required `sui-scope` wrapper so prefixed Tailwind styles apply.
1596
+ * Provides the Scalably UI component library context and automatically injects styles.
1597
+ * All classes are globally prefixed (`sui-*`), so no wrapper element is required.
1598
+ *
1599
+ * Features:
1600
+ * - Automatically injects CSS into document.head (prevents double-injection)
1601
+ * - Works with SSR (only injects on client-side)
1602
+ * - Ensures styles are available for portaled components
1603
+ * - Maintains style isolation via 'sui-' prefix
1582
1604
  *
1583
1605
  * Usage:
1606
+ * ```tsx
1584
1607
  * <ScalablyUIProvider>
1585
1608
  * <App />
1586
1609
  * </ScalablyUIProvider>
1610
+ * ```
1587
1611
  *
1588
- * Or to avoid an extra DOM node:
1589
- * <ScalablyUIProvider asChild>
1590
- * <main />
1612
+ * To disable automatic style injection (if you import CSS manually):
1613
+ * ```tsx
1614
+ * <ScalablyUIProvider injectStyles={false}>
1615
+ * <App />
1591
1616
  * </ScalablyUIProvider>
1617
+ * ```
1592
1618
  */
1593
1619
  declare const ScalablyUIProvider: React.FC<ScalablyUIProviderProps>;
1594
1620
 
1621
+ /**
1622
+ * Type for class values accepted by clsx
1623
+ */
1624
+ type ClassValue = ClassArray | ClassDictionary | string | number | bigint | null | boolean | undefined;
1625
+ type ClassDictionary = Record<string, unknown>;
1626
+ type ClassArray = ClassValue[];
1595
1627
  /**
1596
1628
  * Utility function to merge Tailwind CSS classes intelligently
1597
1629
  * Combines clsx for conditional classes and tailwind-merge for conflict resolution