@leodamours/ds-components 0.3.0 → 0.3.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @leodamours/ds-components
2
2
 
3
- Vue 3 component library with built-in design tokens and theming support via CSS custom properties.
3
+ Vue 3 component library with built-in design tokens, theming via CSS custom properties, and algorithmic palette generation.
4
4
 
5
5
  ## Install
6
6
 
@@ -8,7 +8,9 @@ Vue 3 component library with built-in design tokens and theming support via CSS
8
8
  npm install @leodamours/ds-components
9
9
  ```
10
10
 
11
- **Peer dependency:** `vue ^3.5.0`
11
+ **Peer dependencies:** `vue ^3.5.0`
12
+
13
+ **Optional:** [`@leodamours/ds-icons`](https://www.npmjs.com/package/@leodamours/ds-icons) — 1,920 Lucide-based icon components that pair with this library.
12
14
 
13
15
  ## Setup
14
16
 
@@ -17,7 +19,7 @@ npm install @leodamours/ds-components
17
19
  import '@leodamours/ds-components/style.css'
18
20
  ```
19
21
 
20
- That's it. The stylesheet includes both the default theme (CSS custom properties) and the component styles.
22
+ The stylesheet bundles the default light theme, dark theme (`[data-theme="dark"]`), and all component styles. No additional CSS imports needed.
21
23
 
22
24
  ## Usage
23
25
 
@@ -36,27 +38,308 @@ import { DsButton, DsInput } from '@leodamours/ds-components'
36
38
 
37
39
  | Component | Description |
38
40
  |---|---|
39
- | `DsAvatar` | User avatar with initials fallback |
41
+ | `DsAvatar` | User avatar with image or initials fallback |
40
42
  | `DsBadge` | Status badge / label |
41
43
  | `DsButton` | Button with variants: primary, secondary, outline, ghost, danger, success |
44
+ | `DsCard` | Container card with variants: default, outlined, elevated |
42
45
  | `DsCheckbox` | Checkbox input |
43
46
  | `DsDropdownSelect` | Dropdown select with floating UI positioning |
47
+ | `DsExpandableCard` | Collapsible card with title, supports `v-model` for expand state |
44
48
  | `DsInput` | Text input with label, help text, error state |
45
49
  | `DsLoadingSpinner` | Animated loading spinner |
46
50
  | `DsModal` | Modal dialog with backdrop |
47
51
  | `DsRadio` | Radio input |
48
52
  | `DsSelect` | Native select wrapper |
53
+ | `DsSlider` | Range slider with optional value display |
54
+ | `DsSwitch` | Toggle switch for boolean settings |
49
55
  | `DsTable` | Data table with sorting and pagination |
50
56
  | `DsTabs` | Tab navigation |
51
57
  | `DsTextarea` | Multiline text input |
52
- | `DsToast` / `DsToastContainer` | Toast notifications |
58
+ | `DsToast` / `DsToastContainer` | Toast notifications (see [Toast system](#toast-system) below) |
53
59
  | `DsTooltip` | Tooltip on hover |
60
+ | `DsUnderConstruction` | Placeholder for pages not yet built |
61
+
62
+ All components export their prop types (e.g., `DsButtonProps`, `DsCardProps`).
63
+
64
+ ### Component props
65
+
66
+ #### DsAvatar
67
+
68
+ | Prop | Type | Default | Description |
69
+ |---|---|---|---|
70
+ | `src` | `string` | — | Image URL |
71
+ | `alt` | `string` | — | Alt text for image |
72
+ | `name` | `string` | — | Full name (used for initials fallback) |
73
+ | `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Avatar size |
74
+ | `variant` | `'brand' \| 'neutral'` | `'brand'` | Color variant for initials background |
75
+
76
+ #### DsBadge
77
+
78
+ | Prop | Type | Default | Description |
79
+ |---|---|---|---|
80
+ | `label` | `string` | — | Badge text (can also use default slot) |
81
+ | `variant` | `'brand' \| 'neutral' \| 'error' \| 'success' \| 'warning' \| 'info' \| 'processing'` | `'neutral'` | Color variant |
82
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Badge size |
83
+
84
+ #### DsButton
85
+
86
+ | Prop | Type | Default | Description |
87
+ |---|---|---|---|
88
+ | `label` | `string` | — | Button text (can also use default slot) |
89
+ | `variant` | `'primary' \| 'secondary' \| 'outline' \| 'ghost' \| 'danger' \| 'success' \| 'warning'` | `'primary'` | Visual style |
90
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Button size |
91
+ | `htmlType` | `'button' \| 'submit' \| 'reset'` | `'button'` | Native button type |
92
+ | `disabled` | `boolean` | `false` | Disable interaction |
93
+ | `loading` | `boolean` | `false` | Show loading spinner |
94
+ | `fullWidth` | `boolean` | `false` | Expand to fill container |
95
+ | `iconLeft` | `Component` | — | Vue component icon on the left |
96
+ | `iconRight` | `Component` | — | Vue component icon on the right |
97
+ | `ariaLabel` | `string` | — | Accessible label override |
98
+
99
+ #### DsCard
100
+
101
+ | Prop | Type | Default | Description |
102
+ |---|---|---|---|
103
+ | `variant` | `'default' \| 'outlined' \| 'elevated'` | `'default'` | Card style |
104
+ | `noPadding` | `boolean` | `false` | Remove inner padding |
105
+
106
+ Default slot for card content.
107
+
108
+ #### DsCheckbox
109
+
110
+ | Prop | Type | Default | Description |
111
+ |---|---|---|---|
112
+ | `modelValue` | `boolean` | `false` | Checked state (`v-model`) |
113
+ | `label` | `string` | — | Checkbox label |
114
+ | `id` | `string` | auto | HTML id attribute |
115
+ | `value` | `string \| number \| boolean` | — | Form value |
116
+ | `disabled` | `boolean` | `false` | Disable interaction |
117
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Checkbox size |
118
+
119
+ #### DsDropdownSelect
120
+
121
+ | Prop | Type | Default | Description |
122
+ |---|---|---|---|
123
+ | `modelValue` | `string \| number` | — | Selected value (`v-model`) |
124
+ | `options` | `(string \| number \| { label, value, disabled? })[]` | `[]` | List of options |
125
+ | `placeholder` | `string` | `'Select an option'` | Placeholder text |
126
+ | `variant` | `'primary' \| 'secondary' \| 'ghost'` | `'primary'` | Trigger button style |
127
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Trigger button size |
128
+ | `disabled` | `boolean` | `false` | Disable interaction |
129
+ | `loading` | `boolean` | `false` | Show loading state |
130
+ | `iconLeft` | `Component` | — | Icon in the trigger button |
131
+ | `fullWidth` | `boolean` | `false` | Expand to fill container |
132
+ | `emptyText` | `string` | `'No options available'` | Text shown when options list is empty |
133
+
134
+ #### DsExpandableCard
135
+
136
+ | Prop | Type | Default | Description |
137
+ |---|---|---|---|
138
+ | `title` | `string` | **required** | Card header text |
139
+ | `modelValue` | `boolean` | — | Controlled expand state (`v-model`) |
140
+ | `defaultExpanded` | `boolean` | `false` | Initial expand state (uncontrolled) |
141
+ | `variant` | `'default' \| 'outlined' \| 'elevated'` | `'default'` | Card style |
142
+
143
+ Default slot for expandable content.
144
+
145
+ #### DsInput
146
+
147
+ | Prop | Type | Default | Description |
148
+ |---|---|---|---|
149
+ | `modelValue` | `string \| number` | — | Input value (`v-model`) |
150
+ | `label` | `string` | — | Label text |
151
+ | `type` | `'text' \| 'email' \| 'password' \| 'number' \| 'tel' \| 'url' \| 'search'` | `'text'` | Input type |
152
+ | `placeholder` | `string` | — | Placeholder text |
153
+ | `helpText` | `string` | — | Help text below the input |
154
+ | `error` | `string` | — | Error message (replaces help text) |
155
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Input size |
156
+ | `disabled` | `boolean` | `false` | Disable interaction |
157
+ | `readonly` | `boolean` | `false` | Read-only state |
158
+ | `required` | `boolean` | `false` | Mark as required |
159
+ | `clearable` | `boolean` | `false` | Show clear button when filled |
160
+ | `iconLeft` | `Component` | — | Icon on the left |
161
+ | `iconRight` | `Component` | — | Icon on the right |
162
+ | `autocomplete` | `string` | — | HTML autocomplete attribute |
163
+ | `maxLength` | `number` | — | Character limit |
164
+ | `min` | `number \| string` | — | Minimum value (number input) |
165
+ | `max` | `number \| string` | — | Maximum value (number input) |
166
+ | `step` | `number \| string` | — | Step increment (number input) |
167
+
168
+ #### DsLoadingSpinner
169
+
170
+ | Prop | Type | Default | Description |
171
+ |---|---|---|---|
172
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Spinner size |
173
+ | `variant` | `'primary' \| 'secondary' \| 'white' \| 'current'` | `'primary'` | Color variant |
174
+
175
+ #### DsModal
176
+
177
+ | Prop | Type | Default | Description |
178
+ |---|---|---|---|
179
+ | `modelValue` | `boolean` | **required** | Open state (`v-model`) |
180
+ | `title` | `string` | — | Modal title |
181
+ | `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Modal width |
182
+ | `closable` | `boolean` | `true` | Show close button |
183
+ | `persistent` | `boolean` | `false` | Prevent closing on backdrop click |
184
+
185
+ Slots: `default` (body), `header`, `footer`.
186
+
187
+ #### DsRadio
188
+
189
+ | Prop | Type | Default | Description |
190
+ |---|---|---|---|
191
+ | `modelValue` | `string \| number \| boolean` | — | Selected value (`v-model`) |
192
+ | `label` | `string` | — | Radio label |
193
+ | `id` | `string` | auto | HTML id attribute |
194
+ | `name` | `string` | — | Radio group name |
195
+ | `value` | `string \| number \| boolean` | — | This radio's value |
196
+ | `disabled` | `boolean` | `false` | Disable interaction |
197
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Radio size |
198
+
199
+ #### DsSelect
200
+
201
+ | Prop | Type | Default | Description |
202
+ |---|---|---|---|
203
+ | `modelValue` | `string \| number` | — | Selected value (`v-model`) |
204
+ | `label` | `string` | — | Label text |
205
+ | `placeholder` | `string` | — | Placeholder text |
206
+ | `helpText` | `string` | — | Help text below the select |
207
+ | `error` | `string` | — | Error message |
208
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Select size |
209
+ | `disabled` | `boolean` | `false` | Disable interaction |
210
+ | `required` | `boolean` | `false` | Mark as required |
211
+ | `options` | `DsSelectOption[]` | **required** | `{ label: string, value: string \| number, disabled?: boolean }` |
212
+
213
+ #### DsSlider
214
+
215
+ | Prop | Type | Default | Description |
216
+ |---|---|---|---|
217
+ | `modelValue` | `number` | `0` | Slider value (`v-model`) |
218
+ | `min` | `number` | `0` | Minimum value |
219
+ | `max` | `number` | `100` | Maximum value |
220
+ | `step` | `number` | `1` | Step increment |
221
+ | `disabled` | `boolean` | `false` | Disable interaction |
222
+ | `label` | `string` | — | Label text |
223
+ | `showValue` | `boolean` | `false` | Display current value |
224
+
225
+ #### DsSwitch
226
+
227
+ | Prop | Type | Default | Description |
228
+ |---|---|---|---|
229
+ | `modelValue` | `boolean` | `false` | Checked state (`v-model`) |
230
+ | `label` | `string` | — | Label text |
231
+ | `id` | `string` | auto | HTML id attribute |
232
+ | `disabled` | `boolean` | `false` | Disable interaction |
233
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Switch size |
234
+ | `labelPosition` | `'left' \| 'right'` | `'right'` | Label placement |
235
+
236
+ #### DsTable
237
+
238
+ | Prop | Type | Default | Description |
239
+ |---|---|---|---|
240
+ | `columns` | `DsTableColumn[]` | **required** | Column definitions (see below) |
241
+ | `rows` | `Record<string, any>[]` | **required** | Row data |
242
+ | `sortBy` | `string` | — | Active sort column key |
243
+ | `sortOrder` | `'asc' \| 'desc'` | — | Sort direction |
244
+ | `loading` | `boolean` | `false` | Show loading state |
245
+ | `emptyText` | `string` | `'No data available'` | Text when no rows |
246
+ | `striped` | `boolean` | `false` | Alternate row shading |
247
+ | `stickyHeader` | `boolean` | `false` | Sticky column headers |
248
+ | `pagination` | `DsTablePagination` | — | Enable pagination (see below) |
249
+ | `nextPageLabel` | `string` | `'Next'` | Pagination next label |
250
+ | `previousPageLabel` | `string` | `'Previous'` | Pagination previous label |
251
+ | `ofLabel` | `string` | — | Pagination "of" label |
252
+
253
+ **`DsTableColumn`**: `{ key: string, label: string, sortable?: boolean, width?: string, align?: 'left' | 'center' | 'right' }`
254
+
255
+ **`DsTablePagination`**: `{ page: number, perPage: number, total: number }`
256
+
257
+ Column cells can be customized via named slots: `#cell-{key}="{ row, column }"`.
258
+
259
+ #### DsTabs
260
+
261
+ | Prop | Type | Default | Description |
262
+ |---|---|---|---|
263
+ | `modelValue` | `string` | **required** | Active tab key (`v-model`) |
264
+ | `tabs` | `DsTab[]` | **required** | Tab definitions |
265
+ | `variant` | `'line' \| 'pill'` | `'line'` | Tab style |
266
+ | `ariaLabel` | `string` | `'Tabs'` | Accessible label |
267
+
268
+ **`DsTab`**: `{ key: string, label: string, disabled?: boolean }`
269
+
270
+ Tab content is rendered via named slots: `#tab-{key}`.
271
+
272
+ #### DsTextarea
273
+
274
+ | Prop | Type | Default | Description |
275
+ |---|---|---|---|
276
+ | `modelValue` | `string` | — | Textarea value (`v-model`) |
277
+ | `label` | `string` | — | Label text |
278
+ | `placeholder` | `string` | — | Placeholder text |
279
+ | `helpText` | `string` | — | Help text below the textarea |
280
+ | `error` | `string` | — | Error message |
281
+ | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Textarea size |
282
+ | `disabled` | `boolean` | `false` | Disable interaction |
283
+ | `readonly` | `boolean` | `false` | Read-only state |
284
+ | `required` | `boolean` | `false` | Mark as required |
285
+ | `rows` | `number` | `3` | Visible rows |
286
+ | `maxLength` | `number` | — | Character limit (shows counter) |
287
+
288
+ #### DsTooltip
289
+
290
+ | Prop | Type | Default | Description |
291
+ |---|---|---|---|
292
+ | `content` | `string` | **required** | Tooltip text |
293
+ | `placement` | `Placement` | `'top'` | Position (`'top'`, `'bottom'`, `'left'`, `'right'`, etc.) |
294
+ | `disabled` | `boolean` | `false` | Disable tooltip |
295
+
296
+ Wrap any element in `<DsTooltip>` — the default slot is the trigger.
297
+
298
+ #### DsUnderConstruction
299
+
300
+ | Prop | Type | Default | Description |
301
+ |---|---|---|---|
302
+ | `title` | `string` | `'Under Construction'` | Heading text |
303
+ | `description` | `string` | `'This page is under construction...'` | Body text |
304
+
305
+ ## Toast system
306
+
307
+ Place `<DsToastContainer />` once at the root of your app, then trigger toasts from anywhere via the `useToast` composable:
308
+
309
+ ```vue
310
+ <!-- App.vue -->
311
+ <script setup>
312
+ import { DsToastContainer } from '@leodamours/ds-components'
313
+ </script>
314
+
315
+ <template>
316
+ <router-view />
317
+ <DsToastContainer />
318
+ </template>
319
+ ```
54
320
 
55
- All components export their prop types (e.g., `DsButtonProps`, `DsInputProps`).
321
+ ```ts
322
+ // Any component or composable
323
+ import { useToast } from '@leodamours/ds-components'
324
+
325
+ const toast = useToast()
326
+
327
+ toast.success('Saved successfully')
328
+ toast.error('Something went wrong', { title: 'Error' })
329
+ toast.warning('Session expiring soon', { duration: 8000 })
330
+ toast.info('New version available')
331
+ toast.brand('Welcome back!')
332
+ ```
333
+
334
+ Each method accepts `(message, options?)` where options are `{ title?: string, duration?: number }`. Default duration is 5000ms.
56
335
 
57
336
  ## Theming
58
337
 
59
- Every color in the library flows through CSS custom properties prefixed with `--ds-`. The default theme is included in `style.css`. To customize, override the variables you need:
338
+ Every color in the library flows through CSS custom properties prefixed with `--ds-`. The default theme is included in `style.css`.
339
+
340
+ ### Option 1: CSS overrides
341
+
342
+ Override only the variables you need:
60
343
 
61
344
  ```css
62
345
  /* my-theme.css */
@@ -66,77 +349,237 @@ Every color in the library flows through CSS custom properties prefixed with `--
66
349
  --ds-brand-active: #6D28D9;
67
350
  --ds-brand-on-solid: #FFFFFF;
68
351
  --ds-bg: #FAFAFA;
69
- --ds-error: #DC2626;
70
352
  /* Only override what differs — everything else inherits defaults */
71
353
  }
72
354
  ```
73
355
 
74
356
  ```ts
75
357
  import '@leodamours/ds-components/style.css' // defaults
76
- import './my-theme.css' // overrides
358
+ import './my-theme.css' // your overrides
77
359
  ```
78
360
 
79
- ### Token naming convention
80
-
81
- Tokens follow a **role + tone** pattern: `{role}[-{tone}][-{state}]`
361
+ ### Option 2: Generate a full theme from 7 base colors
82
362
 
83
- | Role | Purpose | Example tokens |
84
- |---|---|---|
85
- | Core | Page-level UI | `bg`, `fg`, `border`, `icon`, `surface-hover` |
86
- | `brand` | Primary actions | `brand`, `brand-hover`, `brand-soft`, `brand-on-solid` |
87
- | `neutral` | Secondary actions | `neutral-soft`, `neutral-on-soft`, `neutral-border` |
88
- | `error` | Error / destructive | `error`, `error-soft`, `error-on-solid`, `error-border` |
89
- | `success` | Success feedback | `success`, `success-soft`, `success-on-solid` |
90
- | `warning` | Warning feedback | `warning`, `warning-soft`, `warning-on-soft` |
91
- | `info` | Informational | `info`, `info-soft`, `info-on-soft` |
92
-
93
- **Tones:**
94
- - `{role}` — the solid color (e.g., `--ds-error` = `#EF4444`)
95
- - `{role}-soft` — light background variant (e.g., `--ds-error-soft` = `#FEF2F2`)
96
- - `{role}-on-solid` — text/icon color on the solid bg (e.g., `--ds-error-on-solid` = `#FFFFFF`)
97
- - `{role}-on-soft` — text/icon color on the soft bg (e.g., `--ds-error-on-soft` = `#EF4444`)
98
- - `{role}-border` — border color for that role
363
+ The `generateFullTheme` function derives all hover, soft, border, contrast, and disabled variants automatically from just one hex per semantic role:
99
364
 
100
- ### Runtime theme switching
365
+ ```ts
366
+ import { generateFullTheme } from '@leodamours/ds-components'
367
+
368
+ const css = generateFullTheme(
369
+ {
370
+ brand: '#8B5CF6',
371
+ error: '#E11D48',
372
+ success: '#059669',
373
+ warning: '#EA580C',
374
+ info: '#6366F1',
375
+ processing: '#D946EF',
376
+ neutral: '#6B5F7D',
377
+ },
378
+ '[data-theme="purple"]', // CSS selector (defaults to ':root')
379
+ )
101
380
 
102
- ```css
103
- [data-theme="dark"] {
104
- --ds-bg: #0F172A;
105
- --ds-fg: #F8FAFC;
106
- --ds-border: #334155;
107
- --ds-brand: #38BDF8;
108
- }
381
+ // Inject into a <style> tag
382
+ const style = document.createElement('style')
383
+ style.textContent = css
384
+ document.head.appendChild(style)
109
385
  ```
110
386
 
387
+ For finer control, `generatePalette(hex)` returns the full variant set for a single color:
388
+
111
389
  ```ts
112
- document.documentElement.dataset.theme = 'dark'
390
+ import { generatePalette } from '@leodamours/ds-components'
391
+
392
+ const brandPalette = generatePalette('#8B5CF6')
393
+ // => { base, hover, active, disabled, soft, soft-hover, soft-active,
394
+ // on-solid, on-soft, border, border-hover, border-strong }
113
395
  ```
114
396
 
115
- ### Programmatic theme generation
397
+ ### Option 3: Override individual tokens at runtime
116
398
 
117
399
  ```ts
118
400
  import { generateThemeCss } from '@leodamours/ds-components'
119
401
 
120
402
  const css = generateThemeCss(
121
403
  { brand: '#8B5CF6', 'brand-hover': '#7C3AED' },
122
- '[data-theme="purple"]'
404
+ '[data-theme="purple"]',
123
405
  )
124
- // Returns a CSS string you can inject into a <style> tag
125
406
  ```
126
407
 
127
- ## Exports
408
+ ### Runtime theme switching
409
+
410
+ A dark theme is bundled and activates via `data-theme`:
411
+
412
+ ```ts
413
+ // Switch to dark
414
+ document.documentElement.dataset.theme = 'dark'
415
+
416
+ // Switch back to light
417
+ delete document.documentElement.dataset.theme
418
+ ```
419
+
420
+ ### Token naming convention
421
+
422
+ Tokens follow a **role + tone** pattern: `--ds-{role}[-{tone}][-{state}]`
423
+
424
+ **Core UI tokens:**
425
+
426
+ | Token | Purpose |
427
+ |---|---|
428
+ | `bg`, `bg-secondary`, `bg-tertiary` | Page backgrounds |
429
+ | `bg-inverse`, `bg-inverse-secondary` | Inverted backgrounds |
430
+ | `fg`, `fg-secondary`, `fg-tertiary`, `fg-inverse`, `fg-disabled` | Text colors |
431
+ | `icon`, `icon-hover`, `icon-active`, `icon-inverse`, `icon-disabled` | Icon colors |
432
+ | `border`, `border-light`, `border-strong`, `border-focus` | Border colors |
433
+ | `surface-hover`, `surface-hover-light`, `surface-active`, `surface-disabled` | Interactive surfaces |
434
+ | `overlay`, `focus-ring` | Overlays and focus states |
435
+
436
+ **Semantic role tokens** — each role (`brand`, `error`, `success`, `warning`, `info`, `processing`, `neutral`) has:
437
+
438
+ | Tone | Purpose | Example |
439
+ |---|---|---|
440
+ | `{role}` | Solid color | `--ds-brand` |
441
+ | `{role}-hover` | Hover state | `--ds-brand-hover` |
442
+ | `{role}-active` | Active/pressed state | `--ds-brand-active` |
443
+ | `{role}-soft` | Light background | `--ds-error-soft` |
444
+ | `{role}-soft-hover` | Soft hover state | `--ds-error-soft-hover` |
445
+ | `{role}-soft-active` | Soft active state | `--ds-error-soft-active` |
446
+ | `{role}-on-solid` | Text on solid bg | `--ds-success-on-solid` |
447
+ | `{role}-on-soft` | Text on soft bg | `--ds-success-on-soft` |
448
+ | `{role}-border` | Border color | `--ds-warning-border` |
449
+ | `{role}-border-hover` | Border hover | `--ds-warning-border-hover` |
450
+ | `{role}-border-strong` | Strong border | `--ds-info-border-strong` |
451
+
452
+ ## UnoCSS Preset
453
+
454
+ If your app uses UnoCSS, import the design system preset instead of configuring tokens manually. It includes the full theme, rules, shortcuts, variants, and CSS custom properties.
455
+
456
+ ### Basic setup
457
+
458
+ ```ts
459
+ // uno.config.ts
460
+ import { defineConfig, presetUno } from 'unocss'
461
+ import { dsPreset } from '@leodamours/ds-components/uno'
462
+
463
+ export default defineConfig({
464
+ presets: [presetUno(), dsPreset()],
465
+ })
466
+ ```
467
+
468
+ ### Custom palette
469
+
470
+ Pass base colors to override the default palette. All hover, soft, border, and contrast variants are derived automatically:
471
+
472
+ ```ts
473
+ dsPreset({
474
+ brand: '#8B5CF6',
475
+ error: '#E11D48',
476
+ success: '#059669',
477
+ warning: '#EA580C',
478
+ info: '#6366F1',
479
+ processing: '#D946EF',
480
+ neutral: '#6B5F7D',
481
+ })
482
+ ```
483
+
484
+ Only override what differs — unspecified roles keep their defaults. The preset accepts these roles: `brand`, `error`, `success`, `warning`, `info`, `processing`, `neutral`.
485
+
486
+ ## Full export reference
487
+
488
+ ### Components
489
+
490
+ ```ts
491
+ import {
492
+ DsAvatar,
493
+ DsBadge,
494
+ DsButton,
495
+ DsCard,
496
+ DsCheckbox,
497
+ DsDropdownSelect,
498
+ DsExpandableCard,
499
+ DsInput,
500
+ DsLoadingSpinner,
501
+ DsModal,
502
+ DsRadio,
503
+ DsSelect,
504
+ DsSlider,
505
+ DsSwitch,
506
+ DsTable,
507
+ DsTabs,
508
+ DsTextarea,
509
+ DsToast,
510
+ DsToastContainer,
511
+ DsTooltip,
512
+ DsUnderConstruction,
513
+ } from '@leodamours/ds-components'
514
+ ```
515
+
516
+ ### Prop types
517
+
518
+ ```ts
519
+ import type {
520
+ DsAvatarProps,
521
+ DsBadgeProps,
522
+ DsButtonProps,
523
+ DsCardProps,
524
+ DsCheckboxProps,
525
+ DsDropdownSelectProps,
526
+ DsExpandableCardProps,
527
+ DsInputProps,
528
+ DsLoadingSpinnerProps,
529
+ DsModalProps,
530
+ DsRadioProps,
531
+ DsSelectProps,
532
+ DsSelectOption,
533
+ DsSliderProps,
534
+ DsSwitchProps,
535
+ DsTableProps,
536
+ DsTableColumn,
537
+ DsTablePagination,
538
+ DsTabsProps,
539
+ DsTab,
540
+ DsTextareaProps,
541
+ DsTooltipProps,
542
+ DsUnderConstructionProps,
543
+ Toast,
544
+ ToastVariant,
545
+ } from '@leodamours/ds-components'
546
+ ```
547
+
548
+ ### Token utilities
128
549
 
129
550
  ```ts
130
- // Components
131
- import { DsButton, DsInput, /* ... */ } from '@leodamours/ds-components'
551
+ import {
552
+ colorTokens, // All color token values as a JS object
553
+ spacingTokens, // Spacing scale values
554
+ radiusTokens, // Border radius values
555
+ shadowTokens, // Box shadow values
556
+ allTokens, // All tokens combined
557
+ generateThemeCss, // Override specific tokens → CSS string
558
+ tokenToCssVar, // Convert token name to CSS var reference
559
+ } from '@leodamours/ds-components'
560
+
561
+ import type { ColorToken, SpacingToken, RadiusToken, ShadowToken, ThemeOverride } from '@leodamours/ds-components'
562
+ ```
132
563
 
133
- // Prop types
134
- import type { DsButtonProps, DsInputProps } from '@leodamours/ds-components'
564
+ ### Palette generation
135
565
 
136
- // Token utilities
137
- import { colorTokens, generateThemeCss, tokenToCssVar } from '@leodamours/ds-components'
138
- import type { ColorToken, ThemeOverride } from '@leodamours/ds-components'
566
+ ```ts
567
+ import {
568
+ generatePalette, // Single hex full SemanticPalette (12 variants)
569
+ generateFullTheme, // 7 base colors → complete CSS theme string
570
+ expandBases, // 7 base colors → flat token map (no CSS wrapping)
571
+ hexToHSL, // Hex → { h, s, l }
572
+ hslToHex, // (h, s, l) → hex string
573
+ } from '@leodamours/ds-components'
574
+
575
+ import type { SemanticPalette, ThemeBases, SemanticRole } from '@leodamours/ds-components'
576
+ ```
577
+
578
+ ### Composables
139
579
 
140
- // Composables
580
+ ```ts
141
581
  import { useToast, useId } from '@leodamours/ds-components'
142
582
  ```
583
+
584
+ - **`useToast()`** — returns `{ toasts, removeToast, success, error, warning, info, brand }` (see [Toast system](#toast-system))
585
+ - **`useId()`** — generates unique IDs for accessible form element associations
@@ -0,0 +1,57 @@
1
+ export interface DsSwitchProps {
2
+ modelValue?: boolean;
3
+ label?: string;
4
+ id?: string;
5
+ disabled?: boolean;
6
+ size?: 'small' | 'medium' | 'large';
7
+ labelPosition?: 'left' | 'right';
8
+ }
9
+ declare function __VLS_template(): {
10
+ default?(_: {}): any;
11
+ };
12
+ declare const __VLS_component: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<DsSwitchProps>, {
13
+ modelValue: boolean;
14
+ disabled: boolean;
15
+ size: string;
16
+ labelPosition: string;
17
+ }>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
18
+ "update:modelValue": (value: boolean) => void;
19
+ change: (value: boolean, event: Event) => void;
20
+ }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<DsSwitchProps>, {
21
+ modelValue: boolean;
22
+ disabled: boolean;
23
+ size: string;
24
+ labelPosition: string;
25
+ }>>> & Readonly<{
26
+ "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
27
+ onChange?: ((value: boolean, event: Event) => any) | undefined;
28
+ }>, {
29
+ size: "small" | "medium" | "large";
30
+ disabled: boolean;
31
+ modelValue: boolean;
32
+ labelPosition: "left" | "right";
33
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
34
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
35
+ export default _default;
36
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
37
+ type __VLS_TypePropsToRuntimeProps<T> = {
38
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
39
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
40
+ } : {
41
+ type: import('vue').PropType<T[K]>;
42
+ required: true;
43
+ };
44
+ };
45
+ type __VLS_WithDefaults<P, D> = {
46
+ [K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
47
+ default: D[K];
48
+ }> : P[K];
49
+ };
50
+ type __VLS_Prettify<T> = {
51
+ [K in keyof T]: T[K];
52
+ } & {};
53
+ type __VLS_WithTemplateSlots<T, S> = T & {
54
+ new (): {
55
+ $slots: S;
56
+ };
57
+ };
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export { default as DsModal } from './components/DsModal.vue';
12
12
  export { default as DsRadio } from './components/DsRadio.vue';
13
13
  export { default as DsSelect } from './components/DsSelect.vue';
14
14
  export { default as DsSlider } from './components/DsSlider.vue';
15
+ export { default as DsSwitch } from './components/DsSwitch.vue';
15
16
  export { default as DsTable } from './components/DsTable.vue';
16
17
  export { default as DsTabs } from './components/DsTabs.vue';
17
18
  export { default as DsTextarea } from './components/DsTextarea.vue';
@@ -38,6 +39,7 @@ export type { DsModalProps } from './components/DsModal.vue';
38
39
  export type { DsRadioProps } from './components/DsRadio.vue';
39
40
  export type { DsSelectProps, DsSelectOption } from './components/DsSelect.vue';
40
41
  export type { DsSliderProps } from './components/DsSlider.vue';
42
+ export type { DsSwitchProps } from './components/DsSwitch.vue';
41
43
  export type { DsTableProps, DsTableColumn, DsTablePagination } from './components/DsTable.vue';
42
44
  export type { DsTabsProps, DsTab } from './components/DsTabs.vue';
43
45
  export type { DsTextareaProps } from './components/DsTextarea.vue';