react-18-ui-library 0.1.0 → 0.3.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 +604 -78
- package/dist/styles.css +2 -1
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,41 +1,110 @@
|
|
|
1
1
|
# react-18-ui-library
|
|
2
2
|
|
|
3
|
-
A fully customizable, theme-aware React 18 enterprise UI component library
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
> A fully customizable, theme-aware React 18 enterprise UI component library — 70+ components, schema-driven forms, fluent validation, drag-and-drop file upload, and zero runtime CSS-in-JS overhead.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/react-18-ui-library)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://react.dev/)
|
|
8
|
+
[](https://tailwindcss.com/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://snyk.io/)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Installation](#installation)
|
|
17
|
+
- [Quick Start](#quick-start)
|
|
18
|
+
- [Theme System](#theme-system)
|
|
19
|
+
- [Component Reference](#component-reference)
|
|
20
|
+
- [Layout](#layout)
|
|
21
|
+
- [Navigation](#navigation)
|
|
22
|
+
- [Inputs](#inputs)
|
|
23
|
+
- [Forms](#forms)
|
|
24
|
+
- [Display](#display)
|
|
25
|
+
- [Feedback](#feedback)
|
|
26
|
+
- [Overlay](#overlay)
|
|
27
|
+
- [Typography](#typography)
|
|
28
|
+
- [Actions](#actions)
|
|
29
|
+
- [FormValidator — Fluent Validation API](#formvalidator--fluent-validation-api)
|
|
30
|
+
- [Hooks](#hooks)
|
|
31
|
+
- [CSS Token Reference](#css-token-reference)
|
|
32
|
+
- [Security — Snyk](#security--snyk)
|
|
33
|
+
- [Development](#development)
|
|
34
|
+
- [Peer Dependencies](#peer-dependencies)
|
|
35
|
+
- [License](#license)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
6
40
|
|
|
7
41
|
```bash
|
|
8
42
|
npm install react-18-ui-library
|
|
43
|
+
# or
|
|
44
|
+
yarn add react-18-ui-library
|
|
45
|
+
# or
|
|
46
|
+
pnpm add react-18-ui-library
|
|
9
47
|
```
|
|
10
48
|
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
11
53
|
```tsx
|
|
12
|
-
// 1. Import the
|
|
54
|
+
// 1. Import the library stylesheet once at your app root
|
|
55
|
+
// This single file includes:
|
|
56
|
+
// - All Tailwind utility classes used by components
|
|
57
|
+
// - All CSS custom property tokens (:root variables)
|
|
13
58
|
import 'react-18-ui-library/styles'
|
|
14
59
|
|
|
15
|
-
// 2.
|
|
16
|
-
import { Button, TextField,
|
|
60
|
+
// 2. Import and use components
|
|
61
|
+
import { Button, TextField, JSONForm } from 'react-18-ui-library'
|
|
62
|
+
|
|
63
|
+
export function App() {
|
|
64
|
+
return (
|
|
65
|
+
<div>
|
|
66
|
+
<TextField label="Name" placeholder="John Doe" />
|
|
67
|
+
<Button variant="primary">Submit</Button>
|
|
68
|
+
</div>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
17
71
|
```
|
|
18
72
|
|
|
73
|
+
> **Important:** `react-18-ui-library/styles` must be imported **before** any of your own stylesheets so your CSS token overrides take precedence. You do **not** need Tailwind installed in your consuming app — all utility classes are pre-compiled into the library's stylesheet.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
19
77
|
## Theme System
|
|
20
78
|
|
|
21
|
-
|
|
79
|
+
All components read CSS custom properties from the parent app's `:root`. There are **no hardcoded colors** and no runtime CSS-in-JS overhead.
|
|
80
|
+
|
|
81
|
+
### Override tokens in CSS
|
|
22
82
|
|
|
23
83
|
```css
|
|
24
|
-
/*
|
|
84
|
+
/* globals.css */
|
|
25
85
|
:root {
|
|
26
|
-
--color-primary:
|
|
27
|
-
--color-primary-hover:
|
|
86
|
+
--color-primary: #7c3aed;
|
|
87
|
+
--color-primary-hover: #6d28d9;
|
|
28
88
|
--color-primary-foreground: #ffffff;
|
|
29
|
-
--color-background:
|
|
30
|
-
--color-surface:
|
|
31
|
-
--color-text:
|
|
32
|
-
--
|
|
33
|
-
--
|
|
34
|
-
|
|
89
|
+
--color-background: #fafafa;
|
|
90
|
+
--color-surface: #ffffff;
|
|
91
|
+
--color-text: #111827;
|
|
92
|
+
--color-text-muted: #6b7280;
|
|
93
|
+
--color-border: #e5e7eb;
|
|
94
|
+
--color-error: #ef4444;
|
|
95
|
+
--color-success: #22c55e;
|
|
96
|
+
--color-warning: #f59e0b;
|
|
97
|
+
--radius-sm: 0.25rem;
|
|
98
|
+
--radius-md: 0.5rem;
|
|
99
|
+
--radius-lg: 0.75rem;
|
|
100
|
+
--font-family-base: 'Inter', sans-serif;
|
|
101
|
+
--navbar-height: 64px;
|
|
102
|
+
--sidebar-width: 260px;
|
|
103
|
+
--sidebar-collapsed-width: 64px;
|
|
35
104
|
}
|
|
36
105
|
```
|
|
37
106
|
|
|
38
|
-
Or use
|
|
107
|
+
### Or use `ThemeProvider` programmatically
|
|
39
108
|
|
|
40
109
|
```tsx
|
|
41
110
|
import { ThemeProvider } from 'react-18-ui-library'
|
|
@@ -45,22 +114,22 @@ import { ThemeProvider } from 'react-18-ui-library'
|
|
|
45
114
|
</ThemeProvider>
|
|
46
115
|
```
|
|
47
116
|
|
|
48
|
-
|
|
117
|
+
---
|
|
49
118
|
|
|
50
|
-
|
|
51
|
-
|---|---|
|
|
52
|
-
| **Layout** | `AppShell`, `Navbar`, `Sidebar`, `Container`, `Stack`, `Grid`, `Divider`, `Spacer` |
|
|
53
|
-
| **Navigation** | `Tabs`, `Breadcrumb`, `Pagination`, `StepIndicator` |
|
|
54
|
-
| **Inputs** | `Button`, `IconButton`, `TextField`, `TextArea`, `Select`, `Checkbox`, `RadioGroup`, `Switch` |
|
|
55
|
-
| **Forms** | `FormField`, `JSONForm`, `FileUpload` |
|
|
56
|
-
| **Display** | `Card`, `Box`, `Image`, `Avatar`, `Badge`, `Tag`, `Icon`, `SVG`, `Table`, `List`, `Timeline`, `Stat`, `EmptyState` |
|
|
57
|
-
| **Feedback** | `Alert`, `ToastProvider`, `Spinner`, `Skeleton`, `ProgressBar`, `ErrorBoundary` |
|
|
58
|
-
| **Overlay** | `Modal`, `Drawer`, `Tooltip`, `Popover`, `ContextMenu` |
|
|
59
|
-
| **Typography** | `Heading`, `Text`, `Label`, `Code`, `Link` |
|
|
119
|
+
## Component Reference
|
|
60
120
|
|
|
61
|
-
|
|
121
|
+
### Layout
|
|
62
122
|
|
|
63
|
-
|
|
123
|
+
| Component | Description |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `AppShell` | Full-page layout combining Navbar + Sidebar + main content area |
|
|
126
|
+
| `Navbar` | Top navigation bar with logo, links, and action slots |
|
|
127
|
+
| `Sidebar` | Collapsible sidebar with icons, badges, and nested items |
|
|
128
|
+
| `Container` | Max-width content wrapper with `xs`/`sm`/`md`/`lg`/`xl`/`full` sizes |
|
|
129
|
+
| `Stack` | Flexbox stack — `direction`, `gap`, `align`, `justify` props |
|
|
130
|
+
| `Grid` | CSS grid with responsive column count and gap control |
|
|
131
|
+
| `Divider` | Horizontal or vertical separator with optional label |
|
|
132
|
+
| `Spacer` | Flexible whitespace filler |
|
|
64
133
|
|
|
65
134
|
```tsx
|
|
66
135
|
import { AppShell } from 'react-18-ui-library'
|
|
@@ -68,68 +137,195 @@ import { LayoutDashboard, Users, Settings } from 'lucide-react'
|
|
|
68
137
|
|
|
69
138
|
<AppShell
|
|
70
139
|
navbar={{
|
|
71
|
-
logo: <Logo />,
|
|
140
|
+
logo: <img src="/logo.svg" alt="Logo" height={32} />,
|
|
72
141
|
links: [{ label: 'Home', href: '/', active: true }],
|
|
73
142
|
actions: <Button size="sm">Sign Out</Button>,
|
|
74
143
|
}}
|
|
75
144
|
sidebar={{
|
|
76
145
|
items: [
|
|
77
|
-
{ id: 'dash',
|
|
78
|
-
{ id: 'users',
|
|
79
|
-
{ id: 'settings', label: 'Settings',
|
|
146
|
+
{ id: 'dash', label: 'Dashboard', icon: <LayoutDashboard size={16} />, active: true },
|
|
147
|
+
{ id: 'users', label: 'Users', icon: <Users size={16} />, badge: 5 },
|
|
148
|
+
{ id: 'settings', label: 'Settings', icon: <Settings size={16} /> },
|
|
80
149
|
],
|
|
81
150
|
}}
|
|
82
151
|
>
|
|
83
|
-
<main>
|
|
152
|
+
<main>Page content</main>
|
|
84
153
|
</AppShell>
|
|
85
154
|
```
|
|
86
155
|
|
|
87
|
-
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### Navigation
|
|
159
|
+
|
|
160
|
+
| Component | Description |
|
|
161
|
+
|---|---|
|
|
162
|
+
| `Tabs` | Horizontal/vertical tab panels with `line`, `pill`, `boxed` variants |
|
|
163
|
+
| `Breadcrumb` | Accessible breadcrumb trail with custom separator |
|
|
164
|
+
| `Pagination` | Page navigation with configurable page size and sibling count |
|
|
165
|
+
| `StepIndicator` | Multi-step wizard progress with `completed`/`current`/`upcoming` states |
|
|
88
166
|
|
|
89
167
|
```tsx
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
168
|
+
import { Tabs, StepIndicator, Pagination } from 'react-18-ui-library'
|
|
169
|
+
|
|
170
|
+
<Tabs
|
|
171
|
+
items={[
|
|
172
|
+
{ id: 'profile', label: 'Profile', content: <ProfilePanel /> },
|
|
173
|
+
{ id: 'billing', label: 'Billing', content: <BillingPanel /> },
|
|
174
|
+
{ id: 'security', label: 'Security', content: <SecurityPanel /> },
|
|
175
|
+
]}
|
|
176
|
+
variant="pill"
|
|
177
|
+
/>
|
|
178
|
+
|
|
179
|
+
<StepIndicator
|
|
180
|
+
steps={[
|
|
181
|
+
{ id: '1', label: 'Account', status: 'completed' },
|
|
182
|
+
{ id: '2', label: 'Profile', status: 'current' },
|
|
183
|
+
{ id: '3', label: 'Review', status: 'upcoming' },
|
|
184
|
+
]}
|
|
185
|
+
/>
|
|
186
|
+
|
|
187
|
+
<Pagination
|
|
188
|
+
page={currentPage}
|
|
189
|
+
totalPages={20}
|
|
190
|
+
onPageChange={setCurrentPage}
|
|
95
191
|
/>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
96
195
|
|
|
196
|
+
### Inputs
|
|
197
|
+
|
|
198
|
+
| Component | Description |
|
|
199
|
+
|---|---|
|
|
200
|
+
| `Button` | `primary`, `secondary`, `ghost`, `outline`, `destructive` variants + `xs`/`sm`/`md`/`lg` sizes |
|
|
201
|
+
| `IconButton` | Square icon-only button with same variants |
|
|
202
|
+
| `TextField` | Text input — prefix/suffix icon/text/image, clearable, password toggle, `showMaxLength` |
|
|
203
|
+
| `TextArea` | Auto-resize textarea with character count (`showCharCount` / `showMaxLength`) |
|
|
204
|
+
| `Select` | Radix-powered dropdown with option groups |
|
|
205
|
+
| `MultiSelect` | Multi-value select with chip display |
|
|
206
|
+
| `SearchSelect` | Combobox with single/multi mode and async search |
|
|
207
|
+
| `ChipSelect` | Inline chip-toggle multi-select |
|
|
208
|
+
| `Checkbox` | Accessible checkbox with indeterminate state |
|
|
209
|
+
| `RadioGroup` | Accessible radio group |
|
|
210
|
+
| `Switch` | Toggle switch |
|
|
211
|
+
| `Slider` | Range slider with `min`/`max`/`step` |
|
|
212
|
+
| `NumberInput` | Numeric input — increment/decrement controls, `hideControls`, blocks non-numeric keys, `showMaxLength` |
|
|
213
|
+
| `PhoneInput` | Phone input with country code dropdown (30+ countries), digit-only enforcement, `showMaxLength` |
|
|
214
|
+
| `OTPInput` | One-time password input with configurable digit count and auto-advance |
|
|
215
|
+
| `Rating` | Star rating with half-star support |
|
|
216
|
+
| `TagInput` | Free-form tag entry — Enter/comma separators, duplicate prevention |
|
|
217
|
+
| `DatePicker` | Calendar picker — single/range mode, month+year dropdowns, configurable year range, portal rendering |
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { TextField, PhoneInput, NumberInput, DatePicker, OTPInput } from 'react-18-ui-library'
|
|
221
|
+
import { Search } from 'lucide-react'
|
|
222
|
+
|
|
223
|
+
// Text field with icon prefix and max-length counter
|
|
97
224
|
<TextField
|
|
98
|
-
label="
|
|
225
|
+
label="Username"
|
|
99
226
|
prefixIcon={<Search size={14} />}
|
|
227
|
+
maxLength={30}
|
|
228
|
+
showMaxLength
|
|
100
229
|
clearable
|
|
101
230
|
/>
|
|
102
231
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
232
|
+
// Phone input with country code
|
|
233
|
+
<PhoneInput
|
|
234
|
+
label="Mobile Number"
|
|
235
|
+
defaultCountry="IN"
|
|
236
|
+
maxLength={10}
|
|
237
|
+
showMaxLength
|
|
238
|
+
onChange={(val) => console.log(val.full)} // "+91 9876543210"
|
|
239
|
+
/>
|
|
240
|
+
|
|
241
|
+
// Number input — hide stepper buttons
|
|
242
|
+
<NumberInput
|
|
243
|
+
label="Quantity"
|
|
244
|
+
hideControls
|
|
245
|
+
min={0}
|
|
246
|
+
max={999}
|
|
108
247
|
/>
|
|
248
|
+
|
|
249
|
+
// Date picker — restrict year range
|
|
250
|
+
<DatePicker
|
|
251
|
+
label="Date of Birth"
|
|
252
|
+
yearRangeBefore={80}
|
|
253
|
+
yearRangeAfter={0}
|
|
254
|
+
onChange={(date) => console.log(date)}
|
|
255
|
+
/>
|
|
256
|
+
|
|
257
|
+
// OTP input — 6 digits
|
|
258
|
+
<OTPInput length={6} onComplete={(code) => verifyOTP(code)} />
|
|
109
259
|
```
|
|
110
260
|
|
|
111
|
-
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### Forms
|
|
264
|
+
|
|
265
|
+
#### `JSONForm` — Schema-Driven Forms
|
|
266
|
+
|
|
267
|
+
Build complete, validated forms from a JSON schema array. Powered by `react-hook-form`.
|
|
268
|
+
|
|
269
|
+
**Supported `type` values:** `text` · `email` · `password` · `url` · `tel` · `number` · `textarea` · `select` · `multiselect` · `radio` · `checkbox` · `switch` · `slider` · `chipselect` · `taginput` · `datepicker` · `file`
|
|
112
270
|
|
|
113
271
|
```tsx
|
|
114
|
-
import { JSONForm } from 'react-18-ui-library'
|
|
272
|
+
import { JSONForm, v } from 'react-18-ui-library'
|
|
115
273
|
import type { JSONFormField } from 'react-18-ui-library'
|
|
116
274
|
|
|
117
275
|
const schema: JSONFormField[] = [
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
276
|
+
{
|
|
277
|
+
name: 'firstName',
|
|
278
|
+
type: 'text',
|
|
279
|
+
label: 'First Name',
|
|
280
|
+
colSpan: 1,
|
|
281
|
+
validator: v.string().required().lengthBetween(2, 50),
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
name: 'email',
|
|
285
|
+
type: 'email',
|
|
286
|
+
label: 'Email',
|
|
287
|
+
colSpan: 1,
|
|
288
|
+
validator: v.email().required().blockedDomains(['mailinator.com']),
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
name: 'role',
|
|
292
|
+
type: 'select',
|
|
293
|
+
label: 'Role',
|
|
294
|
+
options: [
|
|
295
|
+
{ value: 'admin', label: 'Admin' },
|
|
296
|
+
{ value: 'editor', label: 'Editor' },
|
|
297
|
+
{ value: 'viewer', label: 'Viewer' },
|
|
298
|
+
],
|
|
299
|
+
validator: v.select().required(),
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
name: 'bio',
|
|
303
|
+
type: 'textarea',
|
|
304
|
+
label: 'Bio',
|
|
305
|
+
colSpan: 2,
|
|
306
|
+
showCharCount: true,
|
|
307
|
+
validator: v.string().maxLength(300),
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
name: 'terms',
|
|
311
|
+
type: 'checkbox',
|
|
312
|
+
label: 'I agree to the Terms and Conditions',
|
|
313
|
+
colSpan: 2,
|
|
314
|
+
validator: v.boolean().mustBeTrue('You must accept the terms'),
|
|
315
|
+
},
|
|
122
316
|
]
|
|
123
317
|
|
|
124
318
|
<JSONForm
|
|
125
319
|
schema={schema}
|
|
126
320
|
columns={2}
|
|
127
321
|
onSubmit={(data) => console.log(data)}
|
|
128
|
-
|
|
322
|
+
onCancel={() => router.back()}
|
|
323
|
+
submitLabel="Create Account"
|
|
324
|
+
cancelLabel="Cancel"
|
|
129
325
|
/>
|
|
130
326
|
```
|
|
131
327
|
|
|
132
|
-
|
|
328
|
+
#### `FileUpload` — Drag & Drop
|
|
133
329
|
|
|
134
330
|
```tsx
|
|
135
331
|
import { FileUpload } from 'react-18-ui-library'
|
|
@@ -145,58 +341,388 @@ import { FileUpload } from 'react-18-ui-library'
|
|
|
145
341
|
/>
|
|
146
342
|
```
|
|
147
343
|
|
|
148
|
-
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## FormValidator — Fluent Validation API
|
|
347
|
+
|
|
348
|
+
A chainable, type-safe validation builder that compiles to `react-hook-form` rules. Import `v` and attach a `.validator` to any `JSONFormField`.
|
|
349
|
+
|
|
350
|
+
### Validator reference
|
|
351
|
+
|
|
352
|
+
| Builder | Field types | Methods |
|
|
353
|
+
|---|---|---|
|
|
354
|
+
| `v.string()` | `text` `textarea` | `.required()` `.minLength(n)` `.maxLength(n)` `.lengthBetween(min,max)` `.length(n)` `.shouldMatch(regex)` `.shouldBeIn([...])` `.notEmpty()` `.noSpaces()` `.alphanumeric()` `.startsWith(s)` `.endsWith(s)` `.custom(name, fn)` |
|
|
355
|
+
| `v.number()` | `number` | `.required()` `.min(n)` `.max(n)` `.between(min,max)` `.integer()` `.positive()` `.negative()` `.nonZero()` `.multipleOf(n)` `.length(digits)` `.custom(name, fn)` |
|
|
356
|
+
| `v.password()` | `password` | `.required()` `.minLength(n)` `.maxLength(n)` `.hasUppercase()` `.hasLowercase()` `.hasDigit()` `.hasSpecialChar()` `.noSpaces()` `.confirmMatch(getter)` `.strong()` `.custom(name, fn)` |
|
|
357
|
+
| `v.email()` | `email` | `.required()` `.domain([...])` `.blockedDomains([...])` `.shouldMatch(regex)` `.custom(name, fn)` |
|
|
358
|
+
| `v.url()` | `url` | `.required()` `.httpsOnly()` `.allowedDomains([...])` `.noTrailingSlash()` `.custom(name, fn)` |
|
|
359
|
+
| `v.tel()` | `tel` | `.required()` `.length(n)` `.minLength(n)` `.maxLength(n)` `.shouldMatch(regex)` `.custom(name, fn)` |
|
|
360
|
+
| `v.date()` | `datepicker` `text` | `.required()` `.validDate()` `.minDate(d)` `.maxDate(d)` `.notInPast()` `.notInFuture()` `.between(min,max)` `.custom(name, fn)` |
|
|
361
|
+
| `v.select()` | `select` `radio` | `.required()` `.shouldBeIn([...])` `.notEmpty()` `.custom(name, fn)` |
|
|
362
|
+
| `v.boolean()` | `checkbox` `switch` | `.required()` `.mustBeTrue(msg)` `.custom(name, fn)` |
|
|
363
|
+
| `v.array()` | `chipselect` `taginput` `multiselect` | `.required()` `.minItems(n)` `.maxItems(n)` `.exactItems(n)` `.shouldBeIn([...])` `.noEmpty()` `.custom(name, fn)` |
|
|
364
|
+
| `v.file()` | `file` | `.required()` `.maxSize(bytes)` `.allowedTypes([...])` `.allowedExtensions([...])` `.maxFiles(n)` `.minFiles(n)` `.custom(name, fn)` |
|
|
365
|
+
|
|
366
|
+
### Usage examples
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
import { v } from 'react-18-ui-library'
|
|
370
|
+
|
|
371
|
+
// String
|
|
372
|
+
v.string().required().lengthBetween(3, 20).noSpaces()
|
|
373
|
+
v.string().required().shouldBeIn(['admin', 'editor', 'viewer'])
|
|
374
|
+
v.string().required().shouldMatch(/^\d{5}(-\d{4})?$/, 'Invalid ZIP code')
|
|
375
|
+
v.string().required().startsWith('INVITE-').alphanumeric()
|
|
376
|
+
|
|
377
|
+
// Number
|
|
378
|
+
v.number().required().between(18, 120).integer()
|
|
379
|
+
v.number().required().positive().nonZero().multipleOf(5)
|
|
380
|
+
v.number().required().length(6) // exactly 6 digits (PIN)
|
|
381
|
+
|
|
382
|
+
// Password with confirm-match
|
|
383
|
+
const passwordRef = useRef('')
|
|
384
|
+
// field 1
|
|
385
|
+
v.password().required().strong()
|
|
386
|
+
// field 2 — reads field 1's value via getter
|
|
387
|
+
v.password().required().confirmMatch(() => passwordRef.current)
|
|
388
|
+
|
|
389
|
+
// Email
|
|
390
|
+
v.email().required()
|
|
391
|
+
v.email().required().domain(['company.com', 'company.org']) // whitelist
|
|
392
|
+
v.email().required().blockedDomains(['mailinator.com', 'yopmail.com']) // blacklist
|
|
393
|
+
|
|
394
|
+
// URL
|
|
395
|
+
v.url().required().httpsOnly().noTrailingSlash()
|
|
396
|
+
v.url().required().allowedDomains(['github.com'])
|
|
397
|
+
|
|
398
|
+
// Phone
|
|
399
|
+
v.tel().required().length(10)
|
|
400
|
+
v.tel().required().minLength(7).maxLength(15)
|
|
401
|
+
|
|
402
|
+
// Date
|
|
403
|
+
v.date().required().notInPast()
|
|
404
|
+
v.date().required().notInFuture()
|
|
405
|
+
v.date().required().between(new Date('2020-01-01'), new Date('2030-12-31'))
|
|
406
|
+
|
|
407
|
+
// Select / Radio
|
|
408
|
+
v.select().required().shouldBeIn(['us', 'gb', 'in', 'au'])
|
|
409
|
+
|
|
410
|
+
// Boolean
|
|
411
|
+
v.boolean().mustBeTrue('You must accept the terms')
|
|
412
|
+
|
|
413
|
+
// Array (chipselect / taginput)
|
|
414
|
+
v.array().required().minItems(2).maxItems(5)
|
|
415
|
+
v.array().required().exactItems(3).noEmpty()
|
|
416
|
+
|
|
417
|
+
// File upload
|
|
418
|
+
v.file().required()
|
|
419
|
+
.maxSize(5 * 1024 * 1024)
|
|
420
|
+
.allowedTypes(['image/*', 'application/pdf'])
|
|
421
|
+
.maxFiles(3)
|
|
422
|
+
|
|
423
|
+
// Custom rule
|
|
424
|
+
v.string().required().custom(
|
|
425
|
+
'noBadWords',
|
|
426
|
+
(val) => !String(val).includes('spam'),
|
|
427
|
+
'Inappropriate content detected'
|
|
428
|
+
)
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
### Display
|
|
434
|
+
|
|
435
|
+
| Component | Description |
|
|
436
|
+
|---|---|
|
|
437
|
+
| `Card` | Surface container with optional header, footer, and padding variants |
|
|
438
|
+
| `Box` | Generic styled `div` with spacing and color props |
|
|
439
|
+
| `Image` | Responsive image with aspect ratio (`square`/`video`/`portrait`) and `fit` control |
|
|
440
|
+
| `Avatar` / `AvatarGroup` | User avatar with fallback initials, status dot, and group stacking |
|
|
441
|
+
| `Badge` / `BadgeAnchor` | Status badge chip and notification dot anchor |
|
|
442
|
+
| `Tag` | Dismissible label chip with color variants |
|
|
443
|
+
| `Icon` | Lucide icon wrapper with `xs`/`sm`/`md`/`lg`/`xl` sizes |
|
|
444
|
+
| `SVG` | Raw SVG wrapper with size props |
|
|
445
|
+
| `Table` | Sortable, selectable data table with sticky header |
|
|
446
|
+
| `DataTable` | Full-featured table with server-side pagination and column visibility |
|
|
447
|
+
| `List` / `ListItem` | Semantic list with icon, description, and action slots |
|
|
448
|
+
| `Timeline` | Vertical event timeline with icon and color variants |
|
|
449
|
+
| `Stat` | Metric card with label, value, delta, and trend indicator |
|
|
450
|
+
| `EmptyState` | Zero-state placeholder with icon, title, description, and CTA |
|
|
451
|
+
| `MarkdownReader` | Renders Markdown with GFM tables and syntax-highlighted code blocks |
|
|
452
|
+
| `Collapsible` | Animated expand/collapse panel |
|
|
453
|
+
| `TreeView` | Recursive tree with expand/collapse nodes and selection |
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
### Feedback
|
|
458
|
+
|
|
459
|
+
| Component | Description |
|
|
460
|
+
|---|---|
|
|
461
|
+
| `Alert` | Inline status message — `info` / `success` / `warning` / `error` |
|
|
462
|
+
| `ToastProvider` + `useToast` | Global toast notification system with position control |
|
|
463
|
+
| `Spinner` | Loading spinner — `xs` through `xl` sizes |
|
|
464
|
+
| `Skeleton` / `SkeletonCard` | Content placeholder shimmer animations |
|
|
465
|
+
| `ProgressBar` | Linear progress with `default` / `success` / `warning` / `error` variants |
|
|
466
|
+
| `ErrorBoundary` | React error boundary with customizable fallback UI |
|
|
467
|
+
| `FullScreenLoader` + `useFullScreenLoader` | Full-viewport loading overlay with programmatic control |
|
|
149
468
|
|
|
150
469
|
```tsx
|
|
151
470
|
import { ToastProvider, useToast } from 'react-18-ui-library'
|
|
152
471
|
|
|
153
|
-
// Wrap your app
|
|
472
|
+
// Wrap your app root
|
|
154
473
|
<ToastProvider toasts={toasts} onDismiss={dismiss} position="bottom-right" />
|
|
155
474
|
|
|
156
475
|
// In any component
|
|
157
|
-
const { toast } = useToast()
|
|
158
|
-
toast({ title: 'Saved!',
|
|
476
|
+
const { toast, dismiss } = useToast()
|
|
477
|
+
toast({ title: 'Saved!', description: 'Changes saved.', variant: 'success' })
|
|
478
|
+
toast({ title: 'Error', description: 'Something went wrong.', variant: 'error' })
|
|
479
|
+
toast({ title: 'Warning', description: 'Low disk space.', variant: 'warning' })
|
|
159
480
|
```
|
|
160
481
|
|
|
161
|
-
|
|
482
|
+
---
|
|
162
483
|
|
|
163
|
-
|
|
164
|
-
# Install dependencies
|
|
165
|
-
npm install
|
|
484
|
+
### Overlay
|
|
166
485
|
|
|
167
|
-
|
|
168
|
-
|
|
486
|
+
| Component | Description |
|
|
487
|
+
|---|---|
|
|
488
|
+
| `Modal` | Radix Dialog modal — `sm`/`md`/`lg`/`xl`/`full` sizes |
|
|
489
|
+
| `Drawer` | Slide-in panel from `top`/`right`/`bottom`/`left` |
|
|
490
|
+
| `Tooltip` | Hover tooltip with `top`/`right`/`bottom`/`left` placement |
|
|
491
|
+
| `Popover` | Click-triggered floating panel |
|
|
492
|
+
| `ContextMenu` | Right-click context menu with icons and dividers |
|
|
493
|
+
| `ConfirmDialog` + `useConfirm` | Programmatic async confirmation dialog |
|
|
494
|
+
| `CommandPalette` + `useCommandPalette` | ⌘K-style command palette with groups and keyboard navigation, portal-rendered |
|
|
169
495
|
|
|
170
|
-
|
|
171
|
-
|
|
496
|
+
```tsx
|
|
497
|
+
import { useConfirm, ConfirmDialogProvider } from 'react-18-ui-library'
|
|
172
498
|
|
|
173
|
-
|
|
174
|
-
|
|
499
|
+
// Wrap app root
|
|
500
|
+
<ConfirmDialogProvider>
|
|
501
|
+
<App />
|
|
502
|
+
</ConfirmDialogProvider>
|
|
503
|
+
|
|
504
|
+
// In any component
|
|
505
|
+
const confirm = useConfirm()
|
|
506
|
+
const ok = await confirm({
|
|
507
|
+
title: 'Delete record?',
|
|
508
|
+
description: 'This action cannot be undone.',
|
|
509
|
+
confirmLabel: 'Delete',
|
|
510
|
+
variant: 'destructive',
|
|
511
|
+
})
|
|
512
|
+
if (ok) deleteRecord()
|
|
175
513
|
```
|
|
176
514
|
|
|
515
|
+
```tsx
|
|
516
|
+
import { CommandPalette, useCommandPalette } from 'react-18-ui-library'
|
|
517
|
+
|
|
518
|
+
const { open, close, isOpen } = useCommandPalette()
|
|
519
|
+
|
|
520
|
+
// Bind ⌘K
|
|
521
|
+
useKeyboard([{ key: 'k', meta: true, handler: open }])
|
|
522
|
+
|
|
523
|
+
<CommandPalette
|
|
524
|
+
open={isOpen}
|
|
525
|
+
onClose={close}
|
|
526
|
+
groups={[
|
|
527
|
+
{
|
|
528
|
+
id: 'nav',
|
|
529
|
+
label: 'Navigation',
|
|
530
|
+
items: [
|
|
531
|
+
{ id: 'dashboard', label: 'Dashboard', icon: <LayoutDashboard size={14} />, onSelect: () => router.push('/') },
|
|
532
|
+
{ id: 'settings', label: 'Settings', icon: <Settings size={14} />, onSelect: () => router.push('/settings') },
|
|
533
|
+
],
|
|
534
|
+
},
|
|
535
|
+
]}
|
|
536
|
+
/>
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
### Typography
|
|
542
|
+
|
|
543
|
+
| Component | Description |
|
|
544
|
+
|---|---|
|
|
545
|
+
| `Heading` | `h1`–`h6` with independent `size` (`xs`–`4xl`) and `weight` props |
|
|
546
|
+
| `Text` | Paragraph / span with `size`, `weight`, `color`, and polymorphic `as` prop |
|
|
547
|
+
| `Label` | Accessible form label |
|
|
548
|
+
| `Code` | Inline code or syntax-highlighted fenced code block (Prism) |
|
|
549
|
+
| `Link` | Anchor with `none`/`hover`/`always` underline variants |
|
|
550
|
+
| `Kbd` | Keyboard shortcut key display |
|
|
551
|
+
|
|
552
|
+
```tsx
|
|
553
|
+
import { Heading, Text, Code, Kbd, Link } from 'react-18-ui-library'
|
|
554
|
+
|
|
555
|
+
<Heading level="h1" size="3xl" weight="bold">Welcome back</Heading>
|
|
556
|
+
<Text color="muted" size="sm">Last updated 2 minutes ago</Text>
|
|
557
|
+
<Text>
|
|
558
|
+
Press <Kbd>⌘</Kbd> + <Kbd>K</Kbd> to open the command palette.
|
|
559
|
+
</Text>
|
|
560
|
+
<Code block language="tsx">{`const x: number = 42`}</Code>
|
|
561
|
+
<Link href="/docs" underline="hover">Read the docs</Link>
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
### Actions
|
|
567
|
+
|
|
568
|
+
| Component | Description |
|
|
569
|
+
|---|---|
|
|
570
|
+
| `CopyButton` | One-click copy to clipboard with animated feedback state |
|
|
571
|
+
|
|
572
|
+
---
|
|
573
|
+
|
|
574
|
+
## Hooks
|
|
575
|
+
|
|
576
|
+
| Hook | Signature | Description |
|
|
577
|
+
|---|---|---|
|
|
578
|
+
| `useToast` | `() => { toast, dismiss, toasts }` | Trigger and dismiss toast notifications |
|
|
579
|
+
| `useTheme` | `() => { tokens, setToken }` | Read and update CSS token values at runtime |
|
|
580
|
+
| `useMediaQuery` | `(query: string) => boolean` | Reactive media query boolean |
|
|
581
|
+
| `useClickOutside` | `(ref, handler)` | Fire handler when clicking outside a ref |
|
|
582
|
+
| `useDebounce` | `(value, delay) => value` | Debounce any value |
|
|
583
|
+
| `useLocalStorage` | `(key, initial) => [value, setter]` | Persistent state backed by `localStorage` |
|
|
584
|
+
| `useClipboard` | `() => { copy, copied }` | Copy text with `copied` feedback state |
|
|
585
|
+
| `useWindowSize` | `() => { width, height }` | Reactive window dimensions |
|
|
586
|
+
| `useIntersectionObserver` | `(ref, options) => entry` | Intersection Observer hook |
|
|
587
|
+
| `useKeyboard` | `(shortcuts[]) => void` | Bind keyboard shortcuts declaratively |
|
|
588
|
+
| `useConfirm` | `() => confirmFn` | Programmatic confirm dialog (needs `ConfirmDialogProvider`) |
|
|
589
|
+
| `useCommandPalette` | `() => { open, close, isOpen }` | Control the command palette |
|
|
590
|
+
| `useFullScreenLoader` | `() => { show, hide, isVisible }` | Show/hide the full-screen loading overlay |
|
|
591
|
+
|
|
592
|
+
```tsx
|
|
593
|
+
import { useDebounce, useLocalStorage, useKeyboard, useClipboard } from 'react-18-ui-library'
|
|
594
|
+
|
|
595
|
+
const debouncedQuery = useDebounce(searchQuery, 300)
|
|
596
|
+
const [theme, setTheme] = useLocalStorage('theme', 'light')
|
|
597
|
+
const { copy, copied } = useClipboard()
|
|
598
|
+
|
|
599
|
+
useKeyboard([
|
|
600
|
+
{ key: 'k', meta: true, handler: () => openPalette() },
|
|
601
|
+
{ key: 'Escape', handler: () => closeModal() },
|
|
602
|
+
])
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
177
607
|
## CSS Token Reference
|
|
178
608
|
|
|
179
609
|
| Token | Default | Purpose |
|
|
180
610
|
|---|---|---|
|
|
181
611
|
| `--color-primary` | `#6366f1` | Primary brand color |
|
|
612
|
+
| `--color-primary-hover` | `#4f46e5` | Primary hover state |
|
|
613
|
+
| `--color-primary-foreground` | `#ffffff` | Text on primary background |
|
|
182
614
|
| `--color-background` | `#f8fafc` | Page background |
|
|
183
|
-
| `--color-surface` | `#ffffff` | Card/panel background |
|
|
615
|
+
| `--color-surface` | `#ffffff` | Card / panel background |
|
|
184
616
|
| `--color-text` | `#0f172a` | Primary text |
|
|
185
|
-
| `--color-text-muted` | `#64748b` | Secondary text |
|
|
186
|
-
| `--color-border` | `#e2e8f0` |
|
|
187
|
-
| `--color-error` | `#ef4444` | Error state |
|
|
188
|
-
| `--color-success` | `#22c55e` | Success state |
|
|
617
|
+
| `--color-text-muted` | `#64748b` | Secondary / helper text |
|
|
618
|
+
| `--color-border` | `#e2e8f0` | Default border color |
|
|
619
|
+
| `--color-error` | `#ef4444` | Error / destructive state |
|
|
620
|
+
| `--color-success` | `#22c55e` | Success / positive state |
|
|
621
|
+
| `--color-warning` | `#f59e0b` | Warning / caution state |
|
|
622
|
+
| `--radius-sm` | `0.25rem` | Small border radius |
|
|
189
623
|
| `--radius-md` | `0.375rem` | Default border radius |
|
|
190
|
-
| `--
|
|
624
|
+
| `--radius-lg` | `0.5rem` | Large border radius |
|
|
625
|
+
| `--font-family-base` | `system-ui` | Base font family |
|
|
191
626
|
| `--navbar-height` | `64px` | Navbar height |
|
|
192
627
|
| `--sidebar-width` | `260px` | Sidebar expanded width |
|
|
193
628
|
| `--sidebar-collapsed-width` | `64px` | Sidebar collapsed width |
|
|
194
629
|
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
## Security — Snyk
|
|
633
|
+
|
|
634
|
+
This library uses [Snyk](https://snyk.io) for dependency vulnerability scanning. Snyk runs automatically as a `prebuild` hook — the build is blocked if any **high** or **critical** severity vulnerabilities are found.
|
|
635
|
+
|
|
636
|
+
### Setup (one-time)
|
|
637
|
+
|
|
638
|
+
```bash
|
|
639
|
+
# Authenticate with Snyk (opens browser)
|
|
640
|
+
npx snyk auth
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### Available security scripts
|
|
644
|
+
|
|
645
|
+
| Script | Description |
|
|
646
|
+
|---|---|
|
|
647
|
+
| `npm run snyk:test` | Scan for high + critical vulnerabilities (used in `prebuild`) |
|
|
648
|
+
| `npm run snyk:test:all` | Scan for all severities including low and medium |
|
|
649
|
+
| `npm run snyk:monitor` | Upload snapshot to Snyk dashboard for continuous monitoring |
|
|
650
|
+
| `npm run snyk:report` | Run scan and generate `reports/snyk-report.html` |
|
|
651
|
+
| `npm run snyk:report:html` | Save raw JSON results then generate HTML report |
|
|
652
|
+
|
|
653
|
+
### How the build gate works
|
|
654
|
+
|
|
655
|
+
```
|
|
656
|
+
npm run build
|
|
657
|
+
└─ prebuild → snyk test --severity-threshold=high
|
|
658
|
+
├─ PASS → build proceeds normally
|
|
659
|
+
└─ FAIL → build aborted (exit code 1)
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
The `.snyk` policy file at the project root can be used to suppress known/accepted vulnerabilities:
|
|
663
|
+
|
|
664
|
+
```yaml
|
|
665
|
+
# .snyk
|
|
666
|
+
ignore:
|
|
667
|
+
SNYK-JS-EXAMPLE-12345:
|
|
668
|
+
- '*':
|
|
669
|
+
reason: Not exploitable in this context
|
|
670
|
+
expires: 2026-12-31T00:00:00.000Z
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
---
|
|
674
|
+
|
|
675
|
+
## Development
|
|
676
|
+
|
|
677
|
+
```bash
|
|
678
|
+
# Install dependencies
|
|
679
|
+
npm install
|
|
680
|
+
|
|
681
|
+
# Authenticate Snyk (first time only)
|
|
682
|
+
npx snyk auth
|
|
683
|
+
|
|
684
|
+
# Start Storybook dev server (port 6006)
|
|
685
|
+
npm run dev
|
|
686
|
+
|
|
687
|
+
# Type check
|
|
688
|
+
npm run type-check
|
|
689
|
+
|
|
690
|
+
# Run tests
|
|
691
|
+
npm test
|
|
692
|
+
|
|
693
|
+
# Run tests with coverage
|
|
694
|
+
npm run test:coverage
|
|
695
|
+
|
|
696
|
+
# Lint
|
|
697
|
+
npm run lint
|
|
698
|
+
|
|
699
|
+
# Build library (runs snyk:test first via prebuild hook)
|
|
700
|
+
npm run build
|
|
701
|
+
|
|
702
|
+
# Build Storybook static site
|
|
703
|
+
npm run build-storybook
|
|
704
|
+
|
|
705
|
+
# Run Snyk vulnerability scan
|
|
706
|
+
npm run snyk:test
|
|
707
|
+
|
|
708
|
+
# Generate HTML vulnerability report
|
|
709
|
+
npm run snyk:report:html
|
|
710
|
+
# → opens reports/snyk-report.html
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
195
715
|
## Peer Dependencies
|
|
196
716
|
|
|
197
|
-
|
|
198
|
-
|
|
717
|
+
| Package | Version |
|
|
718
|
+
|---|---|
|
|
719
|
+
| `react` | `>= 18.0.0` |
|
|
720
|
+
| `react-dom` | `>= 18.0.0` |
|
|
721
|
+
|
|
722
|
+
> TailwindCSS is **not** a peer dependency — the library ships pre-compiled CSS. You do not need Tailwind in your consuming app.
|
|
723
|
+
|
|
724
|
+
---
|
|
199
725
|
|
|
200
726
|
## License
|
|
201
727
|
|
|
202
|
-
MIT
|
|
728
|
+
MIT © react-18-ui-library contributors
|
package/dist/styles.css
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap");:root{--color-primary:#1d4ed8;--color-primary-hover:#1e40af;--color-primary-active:#1e3a8a;--color-primary-subtle:#eff6ff;--color-primary-foreground:#fff;--color-secondary:#334155;--color-secondary-hover:#1e293b;--color-secondary-foreground:#fff;--color-background:#f4f6f9;--color-surface:#fff;--color-surface-hover:#f0f4f8;--color-surface-raised:#fff;--color-border:#d1d9e6;--color-border-strong:#94a3b8;--color-border-focus:#1d4ed8;--color-text:#0d1b2a;--color-text-muted:#4b5e7a;--color-text-subtle:#7a8fa6;--color-text-disabled:#a8b8cc;--color-text-inverse:#fff;--color-text-link:#1d4ed8;--color-error:#dc2626;--color-error-hover:#b91c1c;--color-error-bg:#fef2f2;--color-error-border:#fca5a5;--color-success:#16a34a;--color-success-hover:#15803d;--color-success-bg:#f0fdf4;--color-success-border:#86efac;--color-warning:#d97706;--color-warning-hover:#b45309;--color-warning-bg:#fffbeb;--color-warning-border:#fcd34d;--color-info:#0284c7;--color-info-hover:#0369a1;--color-info-bg:#f0f9ff;--color-info-border:#7dd3fc;--color-overlay:rgba(13,27,42,.6);--color-navbar:#fff;--color-navbar-border:#e2e8f0;--color-navbar-text:#0d1b2a;--color-navbar-text-muted:#4b5e7a;--color-sidebar:#0f1f35;--color-sidebar-header:#0a1628;--color-sidebar-text:#94afc8;--color-sidebar-text-hover:#e2eaf4;--color-sidebar-active:#60a5fa;--color-sidebar-active-bg:rgba(96,165,250,.12);--color-sidebar-border:hsla(0,0%,100%,.06);--color-sidebar-icon:#64849e;--color-accent-violet:#7c3aed;--color-accent-teal:#0d9488;--color-accent-rose:#e11d48;--color-accent-amber:#d97706;--color-accent-cyan:#0891b2;--color-accent-emerald:#059669;--radius-xs:0.1875rem;--radius-sm:0.3125rem;--radius-md:0.5rem;--radius-lg:0.75rem;--radius-xl:1rem;--radius-2xl:1.5rem;--radius-full:9999px;--font-family-base:"Inter",ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;--font-family-mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--font-family-display:"Inter",sans-serif;--font-size-2xs:0.6875rem;--font-size-xs:0.75rem;--font-size-sm:0.875rem;--font-size-base:1rem;--font-size-lg:1.125rem;--font-size-xl:1.25rem;--font-size-2xl:1.5rem;--font-size-3xl:1.875rem;--font-size-4xl:2.25rem;--font-size-5xl:3rem;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--line-height-none:1;--line-height-tight:1.25;--line-height-snug:1.375;--line-height-normal:1.5;--line-height-relaxed:1.625;--line-height-loose:2;--letter-spacing-tight:-0.025em;--letter-spacing-normal:0em;--letter-spacing-wide:0.025em;--letter-spacing-wider:0.05em;--letter-spacing-widest:0.1em;--spacing-unit:0.25rem;--shadow-xs:0 1px 2px 0 rgba(13,27,42,.04);--shadow-sm:0 1px 3px 0 rgba(13,27,42,.08),0 1px 2px -1px rgba(13,27,42,.06);--shadow-md:0 4px 8px -2px rgba(13,27,42,.1),0 2px 4px -2px rgba(13,27,42,.06);--shadow-lg:0 12px 24px -4px rgba(13,27,42,.12),0 4px 8px -2px rgba(13,27,42,.06);--shadow-xl:0 24px 48px -8px rgba(13,27,42,.16),0 8px 16px -4px rgba(13,27,42,.08);--shadow-2xl:0 40px 64px -12px rgba(13,27,42,.22);--shadow-inner:inset 0 2px 4px 0 rgba(13,27,42,.06);--shadow-focus:0 0 0 3px rgba(29,78,216,.25);--shadow-focus-error:0 0 0 3px rgba(220,38,38,.2);--transition-fast:120ms;--transition-speed:200ms;--transition-slow:350ms;--transition-easing:cubic-bezier(0.4,0,0.2,1);--transition-spring:cubic-bezier(0.34,1.56,0.64,1);--transition-ease-in:cubic-bezier(0.4,0,1,1);--transition-ease-out:cubic-bezier(0,0,0.2,1);--z-base:0;--z-raised:10;--z-dropdown:1000;--z-sticky:1020;--z-sidebar:1100;--z-navbar:1200;--z-modal:1300;--z-toast:1400;--z-tooltip:1500;--z-max:9999;--navbar-height:60px;--sidebar-width:256px;--sidebar-collapsed-width:64px;--content-max-width:1280px;--panel-width-sm:320px;--panel-width-md:480px;--panel-width-lg:640px}
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap");:root{--color-primary:#1d4ed8;--color-primary-hover:#1e40af;--color-primary-active:#1e3a8a;--color-primary-subtle:#eff6ff;--color-primary-foreground:#fff;--color-secondary:#334155;--color-secondary-hover:#1e293b;--color-secondary-foreground:#fff;--color-background:#f4f6f9;--color-surface:#fff;--color-surface-hover:#f0f4f8;--color-surface-raised:#fff;--color-border:#d1d9e6;--color-border-strong:#94a3b8;--color-border-focus:#1d4ed8;--color-text:#0d1b2a;--color-text-muted:#4b5e7a;--color-text-subtle:#7a8fa6;--color-text-disabled:#a8b8cc;--color-text-inverse:#fff;--color-text-link:#1d4ed8;--color-error:#dc2626;--color-error-hover:#b91c1c;--color-error-bg:#fef2f2;--color-error-border:#fca5a5;--color-success:#16a34a;--color-success-hover:#15803d;--color-success-bg:#f0fdf4;--color-success-border:#86efac;--color-warning:#d97706;--color-warning-hover:#b45309;--color-warning-bg:#fffbeb;--color-warning-border:#fcd34d;--color-info:#0284c7;--color-info-hover:#0369a1;--color-info-bg:#f0f9ff;--color-info-border:#7dd3fc;--color-overlay:rgba(13,27,42,.6);--color-navbar:#fff;--color-navbar-border:#e2e8f0;--color-navbar-text:#0d1b2a;--color-navbar-text-muted:#4b5e7a;--color-sidebar:#0f1f35;--color-sidebar-header:#0a1628;--color-sidebar-text:#94afc8;--color-sidebar-text-hover:#e2eaf4;--color-sidebar-active:#60a5fa;--color-sidebar-active-bg:rgba(96,165,250,.12);--color-sidebar-border:hsla(0,0%,100%,.06);--color-sidebar-icon:#64849e;--color-accent-violet:#7c3aed;--color-accent-teal:#0d9488;--color-accent-rose:#e11d48;--color-accent-amber:#d97706;--color-accent-cyan:#0891b2;--color-accent-emerald:#059669;--radius-xs:0.1875rem;--radius-sm:0.3125rem;--radius-md:0.5rem;--radius-lg:0.75rem;--radius-xl:1rem;--radius-2xl:1.5rem;--radius-full:9999px;--font-family-base:"Inter",ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;--font-family-mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--font-family-display:"Inter",sans-serif;--font-size-2xs:0.6875rem;--font-size-xs:0.75rem;--font-size-sm:0.875rem;--font-size-base:1rem;--font-size-lg:1.125rem;--font-size-xl:1.25rem;--font-size-2xl:1.5rem;--font-size-3xl:1.875rem;--font-size-4xl:2.25rem;--font-size-5xl:3rem;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--line-height-none:1;--line-height-tight:1.25;--line-height-snug:1.375;--line-height-normal:1.5;--line-height-relaxed:1.625;--line-height-loose:2;--letter-spacing-tight:-0.025em;--letter-spacing-normal:0em;--letter-spacing-wide:0.025em;--letter-spacing-wider:0.05em;--letter-spacing-widest:0.1em;--spacing-unit:0.25rem;--shadow-xs:0 1px 2px 0 rgba(13,27,42,.04);--shadow-sm:0 1px 3px 0 rgba(13,27,42,.08),0 1px 2px -1px rgba(13,27,42,.06);--shadow-md:0 4px 8px -2px rgba(13,27,42,.1),0 2px 4px -2px rgba(13,27,42,.06);--shadow-lg:0 12px 24px -4px rgba(13,27,42,.12),0 4px 8px -2px rgba(13,27,42,.06);--shadow-xl:0 24px 48px -8px rgba(13,27,42,.16),0 8px 16px -4px rgba(13,27,42,.08);--shadow-2xl:0 40px 64px -12px rgba(13,27,42,.22);--shadow-inner:inset 0 2px 4px 0 rgba(13,27,42,.06);--shadow-focus:0 0 0 3px rgba(29,78,216,.25);--shadow-focus-error:0 0 0 3px rgba(220,38,38,.2);--transition-fast:120ms;--transition-speed:200ms;--transition-slow:350ms;--transition-easing:cubic-bezier(0.4,0,0.2,1);--transition-spring:cubic-bezier(0.34,1.56,0.64,1);--transition-ease-in:cubic-bezier(0.4,0,1,1);--transition-ease-out:cubic-bezier(0,0,0.2,1);--z-base:0;--z-raised:10;--z-dropdown:1000;--z-sticky:1020;--z-sidebar:1100;--z-navbar:1200;--z-modal:1300;--z-toast:1400;--z-tooltip:1500;--z-max:9999;--navbar-height:60px;--sidebar-width:256px;--sidebar-collapsed-width:64px;--content-max-width:1280px;--panel-width-sm:320px;--panel-width-md:480px;--panel-width-lg:640px}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }
|
|
2
|
+
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{-webkit-text-size-adjust:100%;font-feature-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-variation-settings:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-feature-settings:normal;font-family:var(--font-family-mono);font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{font-feature-settings:inherit;color:inherit;font-family:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{clip:rect(0,0,0,0);border-width:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.pointer-events-none{pointer-events:none}.\!visible{visibility:visible!important}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-bottom-1{bottom:-.25rem}.-left-1{left:-.25rem}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.-top-8{top:-2rem}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.left-0{left:0}.left-1\/2{left:50%}.left-2{left:.5rem}.left-4{left:1rem}.right-0{right:0}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.top-2{top:.5rem}.top-2\.5{top:.625rem}.top-4{top:1rem}.z-10{z-index:10}.z-50{z-index:50}.z-\[1000\]{z-index:1000}.z-\[1001\]{z-index:1001}.z-\[9999\]{z-index:9999}.z-dropdown{z-index:var(--z-dropdown)}.z-modal{z-index:var(--z-modal)}.z-navbar{z-index:var(--z-navbar)}.z-sidebar{z-index:var(--z-sidebar)}.z-toast{z-index:var(--z-toast)}.z-tooltip{z-index:var(--z-tooltip)}.col-span-1{grid-column:span 1/span 1}.m-0{margin:0}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-bottom:.25rem;margin-top:.25rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-4{margin-bottom:1rem;margin-top:1rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.-mb-px{margin-bottom:-1px}.-ml-2{margin-left:-.5rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-0\.5{margin-left:.125rem}.ml-1{margin-left:.25rem}.ml-3{margin-left:.75rem}.ml-3\.5{margin-left:.875rem}.ml-4{margin-left:1rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-7{margin-top:1.75rem}.mt-8{margin-top:2rem}.line-clamp-1{-webkit-line-clamp:1}.line-clamp-1,.line-clamp-2{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2}.line-clamp-3{-webkit-line-clamp:3}.line-clamp-3,.line-clamp-4{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-4{-webkit-line-clamp:4}.line-clamp-5{-webkit-box-orient:vertical;-webkit-line-clamp:5;display:-webkit-box;overflow:hidden}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-\[2\/3\]{aspect-ratio:2/3}.aspect-\[3\/2\]{aspect-ratio:3/2}.aspect-\[4\/3\]{aspect-ratio:4/3}.aspect-square{aspect-ratio:1/1}.aspect-video{aspect-ratio:16/9}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-20{height:5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-40{height:10rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-80{height:20rem}.h-9{height:2.25rem}.h-96{height:24rem}.h-\[18px\]{height:18px}.h-\[calc\(100vh-2rem\)\]{height:calc(100vh - 2rem)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-0{max-height:0}.max-h-60{max-height:15rem}.max-h-\[9999px\]{max-height:9999px}.min-h-11{min-height:2.75rem}.min-h-8{min-height:2rem}.min-h-9{min-height:2.25rem}.min-h-\[1\.5rem\]{min-height:1.5rem}.min-h-\[80px\]{min-height:80px}.w-0\.5{width:.125rem}.w-1\.5{width:.375rem}.w-1\/2{width:50%}.w-1\/3{width:33.333333%}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-96{width:24rem}.w-\[32rem\]{width:32rem}.w-\[var\(--sidebar-collapsed-width\)\]{width:var(--sidebar-collapsed-width)}.w-\[var\(--sidebar-width\)\]{width:var(--sidebar-width)}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0}.min-w-\[1\.25rem\]{min-width:1.25rem}.min-w-\[1\.5rem\]{min-width:1.5rem}.min-w-\[1\.75rem\]{min-width:1.75rem}.min-w-\[10rem\]{min-width:10rem}.min-w-\[18px\]{min-width:18px}.min-w-\[22px\]{min-width:22px}.min-w-\[28px\]{min-width:28px}.max-w-\[120px\]{max-width:120px}.max-w-\[calc\(100vw-2rem\)\]{max-width:calc(100vw - 2rem)}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.max-w-screen-md{max-width:768px}.max-w-screen-sm{max-width:640px}.max-w-screen-xl{max-width:1280px}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-full{--tw-translate-x:-100%}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x:0px}.rotate-180{--tw-rotate:180deg}.rotate-180,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-grab{cursor:grab}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.resize-y{resize:vertical}.resize{resize:both}.list-outside{list-style-position:outside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.grid-cols-11{grid-template-columns:repeat(11,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.grid-cols-9{grid-template-columns:repeat(9,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.justify-evenly{justify-content:space-evenly}.gap-0{gap:0}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.125rem*var(--tw-space-y-reverse));margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.self-stretch{align-self:stretch}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:var(--radius-md)}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:var(--radius-full)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-l-md{border-bottom-left-radius:var(--radius-md);border-top-left-radius:var(--radius-md)}.rounded-r-md{border-bottom-right-radius:var(--radius-md)}.rounded-r-md,.rounded-t-md{border-top-right-radius:var(--radius-md)}.rounded-t-md{border-top-left-radius:var(--radius-md)}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-0{border-bottom-width:0}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-border{border-color:var(--color-border)}.border-border-focus{border-color:var(--color-border-focus)}.border-error{border-color:var(--color-error)}.border-primary{border-color:var(--color-primary)}.border-surface{border-color:var(--color-surface)}.border-transparent{border-color:transparent}.bg-background{background-color:var(--color-background)}.bg-black\/40{background-color:rgba(0,0,0,.4)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-border{background-color:var(--color-border)}.bg-current{background-color:currentColor}.bg-error{background-color:var(--color-error)}.bg-error-bg{background-color:var(--color-error-bg)}.bg-info{background-color:var(--color-info)}.bg-info-bg{background-color:var(--color-info-bg)}.bg-navbar{background-color:var(--color-navbar)}.bg-overlay{background-color:var(--color-overlay)}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.bg-sidebar{background-color:var(--color-sidebar)}.bg-sidebar-active-bg{background-color:var(--color-sidebar-active-bg)}.bg-success{background-color:var(--color-success)}.bg-success-bg{background-color:var(--color-success-bg)}.bg-surface{background-color:var(--color-surface)}.bg-surface-hover{background-color:var(--color-surface-hover)}.bg-text{background-color:var(--color-text)}.bg-text-muted{background-color:var(--color-text-muted)}.bg-transparent{background-color:transparent}.bg-warning{background-color:var(--color-warning)}.bg-warning-bg{background-color:var(--color-warning-bg)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.fill-border{fill:var(--color-border)}.fill-text{fill:var(--color-text)}.fill-transparent{fill:transparent}.fill-warning{fill:var(--color-warning)}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.object-fill{-o-object-fit:fill;object-fit:fill}.object-none{-o-object-fit:none;object-fit:none}.object-scale-down{-o-object-fit:scale-down;object-fit:scale-down}.p-0{padding:0}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-bottom:.125rem;padding-top:.125rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.py-12{padding-bottom:3rem;padding-top:3rem}.py-16{padding-bottom:4rem;padding-top:4rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py-2\.5{padding-bottom:.625rem;padding-top:.625rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-4{padding-bottom:1rem;padding-top:1rem}.py-6{padding-bottom:1.5rem;padding-top:1.5rem}.py-8{padding-bottom:2rem;padding-top:2rem}.pb-0{padding-bottom:0}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pl-10{padding-left:2.5rem}.pl-2{padding-left:.5rem}.pl-4{padding-left:1rem}.pl-6{padding-left:1.5rem}.pl-7{padding-left:1.75rem}.pl-9{padding-left:2.25rem}.pl-\[calc\(var\(--prefix-width\2c 2\.25rem\)\+0\.5rem\)\]{padding-left:calc(var(--prefix-width,2.25rem) + .5rem)}.pr-1{padding-right:.25rem}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pr-4{padding-right:1rem}.pr-9{padding-right:2.25rem}.pr-\[calc\(var\(--suffix-width\2c 2\.25rem\)\+0\.5rem\)\]{padding-right:calc(var(--suffix-width,2.25rem) + .5rem)}.pt-3{padding-top:.75rem}.pt-\[15vh\]{padding-top:15vh}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-base{font-family:var(--font-family-base)}.font-mono{font-family:var(--font-family-mono)}.text-2xl{font-size:var(--font-size-2xl);line-height:2rem}.text-3xl{font-size:var(--font-size-3xl);line-height:2.25rem}.text-4xl{font-size:var(--font-size-4xl);line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-base{font-size:var(--font-size-base);line-height:1.5rem}.text-lg{font-size:var(--font-size-lg);line-height:1.75rem}.text-sm{font-size:var(--font-size-sm);line-height:1.25rem}.text-xl{font-size:var(--font-size-xl);line-height:1.75rem}.text-xs{font-size:var(--font-size-xs);line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-7{line-height:1.75rem}.leading-none{line-height:1}.leading-normal{line-height:1.5}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:var(--letter-spacing-wide)}.tracking-wider{letter-spacing:var(--letter-spacing-wider)}.text-background{color:var(--color-background)}.text-border{color:var(--color-border)}.text-current{color:currentColor}.text-error{color:var(--color-error)}.text-info{color:var(--color-info)}.text-inherit{color:inherit}.text-primary{color:var(--color-primary)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-secondary{color:var(--color-secondary)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.text-sidebar-text{color:var(--color-sidebar-text)}.text-success{color:var(--color-success)}.text-surface{color:var(--color-surface)}.text-text{color:var(--color-text)}.text-text-disabled{color:var(--color-text-disabled)}.text-text-muted{color:var(--color-text-muted)}.text-warning{color:var(--color-warning)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.underline-offset-2{text-underline-offset:2px}.underline-offset-4{text-underline-offset:4px}.accent-primary{accent-color:var(--color-primary)}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow{--tw-shadow:var(--shadow-md);--tw-shadow-colored:var(--shadow-md)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:var(--shadow-2xl);--tw-shadow-colored:var(--shadow-2xl)}.shadow-\[0_1px_0_1px_var\(--color-border\)\]{--tw-shadow:0 1px 0 1px var(--color-border);--tw-shadow-colored:0 1px 0 1px var(--tw-shadow-color)}.shadow-\[0_1px_0_1px_var\(--color-border\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:var(--shadow-lg);--tw-shadow-colored:var(--shadow-lg)}.shadow-md{--tw-shadow:var(--shadow-md);--tw-shadow-colored:var(--shadow-md)}.shadow-md,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:var(--shadow-sm);--tw-shadow-colored:var(--shadow-sm)}.shadow-xl{--tw-shadow:var(--shadow-xl);--tw-shadow-colored:var(--shadow-xl);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring-0{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-0,.ring-2{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-surface{--tw-ring-color:var(--color-surface)}.blur{--tw-blur:blur(8px)}.blur,.blur-0{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-0{--tw-blur:blur(0)}.blur-sm{--tw-blur:blur(4px)}.blur-sm,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-duration:var(--transition-speed);transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:var(--transition-easing)}.transition-\[filter\]{transition-duration:var(--transition-speed);transition-property:filter;transition-timing-function:var(--transition-easing)}.transition-\[width\]{transition-duration:var(--transition-speed);transition-property:width;transition-timing-function:var(--transition-easing)}.transition-all{transition-duration:var(--transition-speed);transition-property:all;transition-timing-function:var(--transition-easing)}.transition-colors{transition-duration:var(--transition-speed);transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:var(--transition-easing)}.transition-opacity{transition-duration:var(--transition-speed);transition-property:opacity;transition-timing-function:var(--transition-easing)}.transition-shadow{transition-duration:var(--transition-speed);transition-property:box-shadow;transition-timing-function:var(--transition-easing)}.transition-transform{transition-duration:var(--transition-speed);transition-property:transform;transition-timing-function:var(--transition-easing)}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.placeholder\:text-text-muted::-moz-placeholder{color:var(--color-text-muted)}.placeholder\:text-text-muted::placeholder{color:var(--color-text-muted)}.first\:ml-0:first-child{margin-left:0}.first\:mt-0:first-child{margin-top:0}.last\:mb-0:last-child{margin-bottom:0}.last\:border-0:last-child{border-width:0}.focus-within\:border-border-focus:focus-within{border-color:var(--color-border-focus)}.focus-within\:border-error:focus-within{border-color:var(--color-error)}.focus-within\:ring-2:focus-within{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.hover\:scale-100:hover{--tw-scale-x:1;--tw-scale-y:1}.hover\:scale-100:hover,.hover\:scale-110:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:border-border:hover{border-color:var(--color-border)}.hover\:border-primary:hover{border-color:var(--color-primary)}.hover\:bg-black\/10:hover{background-color:rgba(0,0,0,.1)}.hover\:bg-error-bg:hover{background-color:var(--color-error-bg)}.hover\:bg-primary-hover:hover{background-color:var(--color-primary-hover)}.hover\:bg-secondary-hover:hover{background-color:var(--color-secondary-hover)}.hover\:bg-sidebar-active-bg:hover{background-color:var(--color-sidebar-active-bg)}.hover\:bg-surface-hover:hover{background-color:var(--color-surface-hover)}.hover\:bg-transparent:hover{background-color:transparent}.hover\:text-error:hover{color:var(--color-error)}.hover\:text-primary-hover:hover{color:var(--color-primary-hover)}.hover\:text-text:hover{color:var(--color-text)}.hover\:text-text-muted:hover{color:var(--color-text-muted)}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-70:hover{opacity:.7}.hover\:opacity-80:hover{opacity:.8}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-md:hover{--tw-shadow:var(--shadow-md);--tw-shadow-colored:var(--shadow-md);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:border-border-focus:focus{border-color:var(--color-border-focus)}.focus\:border-error:focus{border-color:var(--color-error)}.focus\:bg-surface-hover:focus{background-color:var(--color-surface-hover)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-border-focus:focus-visible{--tw-ring-color:var(--color-border-focus)}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-surface-hover:disabled{background-color:var(--color-surface-hover)}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[state\=checked\]\:translate-x-4[data-state=checked]{--tw-translate-x:1rem}.data-\[state\=checked\]\:translate-x-4[data-state=checked],.data-\[state\=checked\]\:translate-x-5[data-state=checked]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=checked\]\:translate-x-5[data-state=checked]{--tw-translate-x:1.25rem}.data-\[state\=checked\]\:translate-x-6[data-state=checked]{--tw-translate-x:1.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[disabled\]\:cursor-not-allowed[data-disabled]{cursor:not-allowed}.data-\[state\=active\]\:border-border[data-state=active]{border-color:var(--color-border)}.data-\[state\=active\]\:border-primary[data-state=active],.data-\[state\=checked\]\:border-primary[data-state=checked]{border-color:var(--color-primary)}.data-\[highlighted\]\:bg-surface-hover[data-highlighted]{background-color:var(--color-surface-hover)}.data-\[state\=active\]\:bg-primary[data-state=active]{background-color:var(--color-primary)}.data-\[state\=active\]\:bg-surface[data-state=active]{background-color:var(--color-surface)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--color-primary)}.data-\[state\=checked\]\:bg-surface[data-state=checked]{background-color:var(--color-surface)}.data-\[highlighted\]\:text-primary[data-highlighted]{color:var(--color-primary)}.data-\[highlighted\]\:text-text[data-highlighted]{color:var(--color-text)}.data-\[placeholder\]\:text-text-muted[data-placeholder]{color:var(--color-text-muted)}.data-\[state\=active\]\:text-primary[data-state=active]{color:var(--color-primary)}.data-\[state\=active\]\:text-primary-foreground[data-state=active]{color:var(--color-primary-foreground)}.data-\[state\=active\]\:text-text[data-state=active]{color:var(--color-text)}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[state\=closed\]\:duration-200[data-state=closed]{transition-duration:.2s}.data-\[state\=open\]\:duration-300[data-state=open]{transition-duration:.3s}@media (min-width:640px){.sm\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:grid-cols-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:grid-cols-9{grid-template-columns:repeat(9,minmax(0,1fr))}}@media (min-width:768px){.md\:col-span-2{grid-column:span 2/span 2}.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:grid-cols-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:grid-cols-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}}@media (min-width:1024px){.lg\:col-span-3{grid-column:span 3/span 3}.lg\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:grid-cols-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:grid-cols-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}}.\[\&\>li\:last-child\]\:border-0>li:last-child{border-width:0}.\[\&\>li\]\:border-b>li{border-bottom-width:1px}.\[\&\>li\]\:border-border>li{border-color:var(--color-border)}.\[\&\>li\]\:py-1\.5>li{padding-bottom:.375rem;padding-top:.375rem}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-18-ui-library",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A fully customizable, theme-aware React 18 enterprise UI component library",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"dev": "storybook dev -p 6006",
|
|
21
21
|
"prebuild": "npm run snyk:test",
|
|
22
|
-
"build": "
|
|
22
|
+
"build:css": "tailwindcss -i src/styles.css -o dist/styles.css --minify",
|
|
23
|
+
"build": "npm run build:css && rollup -c --configPlugin @rollup/plugin-typescript",
|
|
23
24
|
"build-storybook": "storybook build",
|
|
24
25
|
"test": "vitest run",
|
|
25
26
|
"test:watch": "vitest",
|
|
@@ -30,7 +31,10 @@
|
|
|
30
31
|
"snyk:test:all": "snyk test",
|
|
31
32
|
"snyk:monitor": "snyk monitor",
|
|
32
33
|
"snyk:report": "snyk test --json | node scripts/snyk-report.mjs",
|
|
33
|
-
"snyk:report:html": "snyk test --json-file-output=reports/snyk-results.json; node scripts/snyk-report.mjs"
|
|
34
|
+
"snyk:report:html": "snyk test --json-file-output=reports/snyk-results.json; node scripts/snyk-report.mjs",
|
|
35
|
+
"publish:minor": "npm version minor && npm publish",
|
|
36
|
+
"publish:major": "npm version major && npm publish",
|
|
37
|
+
"publish:patch": "npm version patch && npm publish"
|
|
34
38
|
},
|
|
35
39
|
"peerDependencies": {
|
|
36
40
|
"react": "^18.0.0",
|