@r2digisolutions/components 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -75,6 +75,16 @@ Mismo flujo que usan muchas libs con `bumpp` / `release-it` (tag → CI → npm
75
75
  pnpm add @r2digisolutions/components
76
76
  ```
77
77
 
78
+ Los componentes usan clases de Tailwind 4. En la app consumidora basta con importar el CSS del design system (incluye `@theme`, variables y el `@source` del paquete):
79
+
80
+ ```css
81
+ /* app.css / layout.css del consumidor */
82
+ @import 'tailwindcss';
83
+ @import '@r2digisolutions/components/styles.css';
84
+ ```
85
+
86
+ Ese import registra tokens (`border-border`, `bg-surface`, …) y hace que Tailwind escanee los `.svelte` del paquete. Sin él, las utilidades pueden faltar o `--border` no estar definido.
87
+
78
88
  ## Licencia
79
89
 
80
90
  MIT
@@ -2,7 +2,14 @@ import type { StoryObj } from '@storybook/svelte';
2
2
  declare const meta: {
3
3
  title: string;
4
4
  component: import("svelte").Component<{
5
- cols?: 1 | 2 | 3 | 4;
5
+ cols?: (1 | 2 | 9 | 3 | 4 | 8 | 5 | 6 | 7 | 10 | 11 | 12) | {
6
+ base?: 1 | 2 | 9 | 3 | 4 | 8 | 5 | 6 | 7 | 10 | 11 | 12;
7
+ sm?: 1 | 2 | 9 | 3 | 4 | 8 | 5 | 6 | 7 | 10 | 11 | 12;
8
+ md?: 1 | 2 | 9 | 3 | 4 | 8 | 5 | 6 | 7 | 10 | 11 | 12;
9
+ lg?: 1 | 2 | 9 | 3 | 4 | 8 | 5 | 6 | 7 | 10 | 11 | 12;
10
+ xl?: 1 | 2 | 9 | 3 | 4 | 8 | 5 | 6 | 7 | 10 | 11 | 12;
11
+ '2xl'?: 1 | 2 | 9 | 3 | 4 | 8 | 5 | 6 | 7 | 10 | 11 | 12;
12
+ };
6
13
  }, {}, "">;
7
14
  tags: string[];
8
15
  argTypes: {
@@ -19,3 +26,4 @@ export default meta;
19
26
  type Story = StoryObj<typeof meta>;
20
27
  export declare const Default: Story;
21
28
  export declare const TwoColumns: Story;
29
+ export declare const Responsive: Story;
@@ -11,3 +11,6 @@ const meta = {
11
11
  export default meta;
12
12
  export const Default = {};
13
13
  export const TwoColumns = { args: { cols: 2 } };
14
+ export const Responsive = {
15
+ args: { cols: { base: 1, sm: 2, md: 3, lg: 4, xl: 5, '2xl': 6 } }
16
+ };
@@ -4,8 +4,19 @@
4
4
  type GridGap = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
5
5
  type GridCols = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
6
6
 
7
+ type GridColsConfig =
8
+ | GridCols
9
+ | {
10
+ base?: GridCols;
11
+ sm?: GridCols;
12
+ md?: GridCols;
13
+ lg?: GridCols;
14
+ xl?: GridCols;
15
+ '2xl'?: GridCols;
16
+ };
17
+
7
18
  interface GridProps {
8
- cols?: GridCols;
19
+ cols?: GridColsConfig;
9
20
  gap?: GridGap;
10
21
  class?: string;
11
22
  children?: Snippet;
@@ -36,8 +47,98 @@
36
47
  11: 'grid-cols-11',
37
48
  12: 'grid-cols-12'
38
49
  };
50
+
51
+ const smColClasses: Record<GridCols, string> = {
52
+ 1: 'sm:grid-cols-1',
53
+ 2: 'sm:grid-cols-2',
54
+ 3: 'sm:grid-cols-3',
55
+ 4: 'sm:grid-cols-4',
56
+ 5: 'sm:grid-cols-5',
57
+ 6: 'sm:grid-cols-6',
58
+ 7: 'sm:grid-cols-7',
59
+ 8: 'sm:grid-cols-8',
60
+ 9: 'sm:grid-cols-9',
61
+ 10: 'sm:grid-cols-10',
62
+ 11: 'sm:grid-cols-11',
63
+ 12: 'sm:grid-cols-12'
64
+ };
65
+
66
+ const mdColClasses: Record<GridCols, string> = {
67
+ 1: 'md:grid-cols-1',
68
+ 2: 'md:grid-cols-2',
69
+ 3: 'md:grid-cols-3',
70
+ 4: 'md:grid-cols-4',
71
+ 5: 'md:grid-cols-5',
72
+ 6: 'md:grid-cols-6',
73
+ 7: 'md:grid-cols-7',
74
+ 8: 'md:grid-cols-8',
75
+ 9: 'md:grid-cols-9',
76
+ 10: 'md:grid-cols-10',
77
+ 11: 'md:grid-cols-11',
78
+ 12: 'md:grid-cols-12'
79
+ };
80
+
81
+ const lgColClasses: Record<GridCols, string> = {
82
+ 1: 'lg:grid-cols-1',
83
+ 2: 'lg:grid-cols-2',
84
+ 3: 'lg:grid-cols-3',
85
+ 4: 'lg:grid-cols-4',
86
+ 5: 'lg:grid-cols-5',
87
+ 6: 'lg:grid-cols-6',
88
+ 7: 'lg:grid-cols-7',
89
+ 8: 'lg:grid-cols-8',
90
+ 9: 'lg:grid-cols-9',
91
+ 10: 'lg:grid-cols-10',
92
+ 11: 'lg:grid-cols-11',
93
+ 12: 'lg:grid-cols-12'
94
+ };
95
+
96
+ const xlColClasses: Record<GridCols, string> = {
97
+ 1: 'xl:grid-cols-1',
98
+ 2: 'xl:grid-cols-2',
99
+ 3: 'xl:grid-cols-3',
100
+ 4: 'xl:grid-cols-4',
101
+ 5: 'xl:grid-cols-5',
102
+ 6: 'xl:grid-cols-6',
103
+ 7: 'xl:grid-cols-7',
104
+ 8: 'xl:grid-cols-8',
105
+ 9: 'xl:grid-cols-9',
106
+ 10: 'xl:grid-cols-10',
107
+ 11: 'xl:grid-cols-11',
108
+ 12: 'xl:grid-cols-12'
109
+ };
110
+
111
+ const twoxlColClasses: Record<GridCols, string> = {
112
+ 1: '2xl:grid-cols-1',
113
+ 2: '2xl:grid-cols-2',
114
+ 3: '2xl:grid-cols-3',
115
+ 4: '2xl:grid-cols-4',
116
+ 5: '2xl:grid-cols-5',
117
+ 6: '2xl:grid-cols-6',
118
+ 7: '2xl:grid-cols-7',
119
+ 8: '2xl:grid-cols-8',
120
+ 9: '2xl:grid-cols-9',
121
+ 10: '2xl:grid-cols-10',
122
+ 11: '2xl:grid-cols-11',
123
+ 12: '2xl:grid-cols-12'
124
+ };
125
+
126
+ const resolved = $derived(typeof cols === 'number' ? { base: cols } : cols);
127
+ const baseCols = $derived(resolved.base ?? 3);
39
128
  </script>
40
129
 
41
- <div class={['grid', colClasses[cols], gaps[gap], className]}>
130
+ <div
131
+ class={[
132
+ 'grid',
133
+ colClasses[baseCols],
134
+ resolved.sm != null && smColClasses[resolved.sm],
135
+ resolved.md != null && mdColClasses[resolved.md],
136
+ resolved.lg != null && lgColClasses[resolved.lg],
137
+ resolved.xl != null && xlColClasses[resolved.xl],
138
+ resolved['2xl'] != null && twoxlColClasses[resolved['2xl']],
139
+ gaps[gap],
140
+ className
141
+ ]}
142
+ >
42
143
  {#if children}{@render children()}{/if}
43
144
  </div>
@@ -1,8 +1,16 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  type GridGap = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
3
3
  type GridCols = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
4
+ type GridColsConfig = GridCols | {
5
+ base?: GridCols;
6
+ sm?: GridCols;
7
+ md?: GridCols;
8
+ lg?: GridCols;
9
+ xl?: GridCols;
10
+ '2xl'?: GridCols;
11
+ };
4
12
  interface GridProps {
5
- cols?: GridCols;
13
+ cols?: GridColsConfig;
6
14
  gap?: GridGap;
7
15
  class?: string;
8
16
  children?: Snippet;
@@ -1,12 +1,26 @@
1
1
  <script lang="ts">
2
2
  import Grid from './Grid.svelte';
3
3
 
4
- let props = $props<{ cols?: 1 | 2 | 3 | 4 }>();
4
+ type GridCols = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
5
+ type GridColsConfig =
6
+ | GridCols
7
+ | {
8
+ base?: GridCols;
9
+ sm?: GridCols;
10
+ md?: GridCols;
11
+ lg?: GridCols;
12
+ xl?: GridCols;
13
+ '2xl'?: GridCols;
14
+ };
15
+
16
+ let props = $props<{ cols?: GridColsConfig }>();
5
17
  </script>
6
18
 
7
- <Grid cols={props.cols ?? 3} gap="md" class="w-full max-w-lg">
19
+ <Grid cols={props.cols ?? 3} gap="md" class="w-full max-w-3xl">
8
20
  {#each [1, 2, 3, 4, 5, 6] as n}
9
- <div class="rounded-lg border border-border bg-surface-elevated px-3 py-6 text-center text-sm text-secondary">
21
+ <div
22
+ class="rounded-lg border border-border bg-surface-elevated px-3 py-6 text-center text-sm text-secondary"
23
+ >
10
24
  {n}
11
25
  </div>
12
26
  {/each}
@@ -1,5 +1,14 @@
1
+ type GridCols = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
2
+ type GridColsConfig = GridCols | {
3
+ base?: GridCols;
4
+ sm?: GridCols;
5
+ md?: GridCols;
6
+ lg?: GridCols;
7
+ xl?: GridCols;
8
+ '2xl'?: GridCols;
9
+ };
1
10
  type $$ComponentProps = {
2
- cols?: 1 | 2 | 3 | 4;
11
+ cols?: GridColsConfig;
3
12
  };
4
13
  declare const GridStory: import("svelte").Component<$$ComponentProps, {}, "">;
5
14
  type GridStory = ReturnType<typeof GridStory>;
@@ -0,0 +1,237 @@
1
+ /* Scan this package so consumers only need to @import this file (no extra @source) */
2
+ @source './components/**/*.{svelte,js}';
3
+ @source './utils/**/*.{svelte,js}';
4
+
5
+ /* Match theme tokens (:root.dark) — not prefers-color-scheme alone */
6
+ @custom-variant dark (&:where(.dark, .dark *));
7
+
8
+ /* ─────────────────────────────────────────────────────────────────────────────
9
+ R2DigiSolutions Design System — Tailwind 4 @theme
10
+ ─────────────────────────────────────────────────────────────────────────── */
11
+
12
+ @theme {
13
+ /* Brand colors */
14
+ --color-brand-50: oklch(97% 0.02 265);
15
+ --color-brand-100: oklch(93% 0.05 265);
16
+ --color-brand-200: oklch(86% 0.1 265);
17
+ --color-brand-300: oklch(76% 0.15 265);
18
+ --color-brand-400: oklch(65% 0.2 265);
19
+ --color-brand-500: oklch(55% 0.25 265);
20
+ --color-brand-600: oklch(47% 0.26 265);
21
+ --color-brand-700: oklch(39% 0.24 265);
22
+ --color-brand-800: oklch(31% 0.2 265);
23
+ --color-brand-900: oklch(22% 0.14 265);
24
+ --color-brand-950: oklch(15% 0.08 265);
25
+
26
+ /* Semantic surface tokens */
27
+ --color-surface: var(--surface);
28
+ --color-surface-elevated: var(--surface-elevated);
29
+ --color-surface-overlay: var(--surface-overlay);
30
+ --color-border: var(--border);
31
+ --color-border-strong: var(--border-strong);
32
+ --color-text-primary: var(--text-primary);
33
+ --color-text-secondary: var(--text-secondary);
34
+ --color-text-muted: var(--text-muted);
35
+ --color-text-inverse: var(--text-inverse);
36
+
37
+ /* Typography */
38
+ --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
39
+ --font-mono: 'JetBrains Mono', ui-monospace, monospace;
40
+
41
+ /* Radii */
42
+ --radius-sm: 0.375rem;
43
+ --radius-md: 0.5rem;
44
+ --radius-lg: 0.75rem;
45
+ --radius-xl: 1rem;
46
+ --radius-2xl: 1.5rem;
47
+ --radius-full: 9999px;
48
+
49
+ /* Shadows */
50
+ --shadow-sm: 0 1px 3px 0 oklch(0% 0 0 / 0.08), 0 1px 2px -1px oklch(0% 0 0 / 0.06);
51
+ --shadow-md: 0 4px 6px -1px oklch(0% 0 0 / 0.1), 0 2px 4px -2px oklch(0% 0 0 / 0.08);
52
+ --shadow-lg: 0 10px 15px -3px oklch(0% 0 0 / 0.12), 0 4px 6px -4px oklch(0% 0 0 / 0.08);
53
+ --shadow-xl: 0 20px 25px -5px oklch(0% 0 0 / 0.14), 0 8px 10px -6px oklch(0% 0 0 / 0.08);
54
+
55
+ /* Transitions */
56
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
57
+ --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
58
+ }
59
+
60
+ /* ─────────────────────────────────────────────────────────────────────────────
61
+ Light mode (default)
62
+ ─────────────────────────────────────────────────────────────────────────── */
63
+
64
+ :root {
65
+ color-scheme: light;
66
+
67
+ --surface: oklch(99% 0.005 265);
68
+ --surface-elevated: oklch(100% 0 0);
69
+ --surface-overlay: oklch(97% 0.01 265);
70
+ --border: oklch(88% 0.02 265);
71
+ --border-strong: oklch(75% 0.04 265);
72
+ --text-primary: oklch(15% 0.02 265);
73
+ --text-secondary: oklch(35% 0.03 265);
74
+ --text-muted: oklch(45% 0.02 265);
75
+ --text-inverse: oklch(99% 0 0);
76
+
77
+ /* Alert tones */
78
+ --alert-info-bg: oklch(96% 0.03 240);
79
+ --alert-info-border: oklch(82% 0.06 240);
80
+ --alert-info-fg: oklch(28% 0.08 240);
81
+ --alert-info-muted: oklch(40% 0.06 240);
82
+ --alert-info-icon: oklch(52% 0.14 240);
83
+ --alert-info-accent: oklch(55% 0.16 240);
84
+
85
+ --alert-success-bg: oklch(96% 0.04 150);
86
+ --alert-success-border: oklch(82% 0.07 150);
87
+ --alert-success-fg: oklch(28% 0.08 150);
88
+ --alert-success-muted: oklch(38% 0.06 150);
89
+ --alert-success-icon: oklch(50% 0.14 150);
90
+ --alert-success-accent: oklch(55% 0.16 150);
91
+
92
+ --alert-warning-bg: oklch(96% 0.05 85);
93
+ --alert-warning-border: oklch(84% 0.1 85);
94
+ --alert-warning-fg: oklch(30% 0.08 75);
95
+ --alert-warning-muted: oklch(42% 0.07 75);
96
+ --alert-warning-icon: oklch(58% 0.15 75);
97
+ --alert-warning-accent: oklch(68% 0.16 75);
98
+
99
+ --alert-error-bg: oklch(96% 0.03 25);
100
+ --alert-error-border: oklch(84% 0.08 25);
101
+ --alert-error-fg: oklch(30% 0.1 25);
102
+ --alert-error-muted: oklch(42% 0.08 25);
103
+ --alert-error-icon: oklch(55% 0.18 25);
104
+ --alert-error-accent: oklch(58% 0.2 25);
105
+ }
106
+
107
+ /* ─────────────────────────────────────────────────────────────────────────────
108
+ Dark mode
109
+ ─────────────────────────────────────────────────────────────────────────── */
110
+
111
+ :root.dark {
112
+ color-scheme: dark;
113
+
114
+ --surface: oklch(14% 0.02 265);
115
+ --surface-elevated: oklch(18% 0.025 265);
116
+ --surface-overlay: oklch(20% 0.03 265);
117
+ --border: oklch(28% 0.03 265);
118
+ --border-strong: oklch(40% 0.04 265);
119
+ --text-primary: oklch(96% 0.01 265);
120
+ --text-secondary: oklch(75% 0.03 265);
121
+ --text-muted: oklch(55% 0.03 265);
122
+ --text-inverse: oklch(15% 0.02 265);
123
+
124
+ /* Alert tones */
125
+ --alert-info-bg: oklch(24% 0.04 240);
126
+ --alert-info-border: oklch(38% 0.06 240);
127
+ --alert-info-fg: oklch(92% 0.03 240);
128
+ --alert-info-muted: oklch(78% 0.04 240);
129
+ --alert-info-icon: oklch(72% 0.12 240);
130
+ --alert-info-accent: oklch(65% 0.14 240);
131
+
132
+ --alert-success-bg: oklch(24% 0.04 150);
133
+ --alert-success-border: oklch(38% 0.06 150);
134
+ --alert-success-fg: oklch(92% 0.03 150);
135
+ --alert-success-muted: oklch(78% 0.04 150);
136
+ --alert-success-icon: oklch(72% 0.12 150);
137
+ --alert-success-accent: oklch(65% 0.14 150);
138
+
139
+ --alert-warning-bg: oklch(25% 0.04 85);
140
+ --alert-warning-border: oklch(40% 0.07 85);
141
+ --alert-warning-fg: oklch(93% 0.03 85);
142
+ --alert-warning-muted: oklch(80% 0.04 85);
143
+ --alert-warning-icon: oklch(78% 0.12 85);
144
+ --alert-warning-accent: oklch(72% 0.14 85);
145
+
146
+ --alert-error-bg: oklch(24% 0.05 25);
147
+ --alert-error-border: oklch(40% 0.08 25);
148
+ --alert-error-fg: oklch(93% 0.03 25);
149
+ --alert-error-muted: oklch(80% 0.04 25);
150
+ --alert-error-icon: oklch(72% 0.14 25);
151
+ --alert-error-accent: oklch(65% 0.18 25);
152
+ }
153
+
154
+ /* ─────────────────────────────────────────────────────────────────────────────
155
+ Base styles
156
+ ─────────────────────────────────────────────────────────────────────────── */
157
+
158
+ @layer base {
159
+ *,
160
+ *::before,
161
+ *::after {
162
+ box-sizing: border-box;
163
+ }
164
+
165
+ html {
166
+ -webkit-text-size-adjust: 100%;
167
+ -webkit-font-smoothing: antialiased;
168
+ -moz-osx-font-smoothing: grayscale;
169
+ scroll-behavior: smooth;
170
+ }
171
+
172
+ body {
173
+ margin: 0;
174
+ background-color: var(--surface);
175
+ color: var(--text-primary);
176
+ font-family: var(--font-sans);
177
+ line-height: 1.6;
178
+ transition:
179
+ background-color 0.2s var(--ease-smooth),
180
+ color 0.2s var(--ease-smooth);
181
+ }
182
+
183
+ /* Focus visible styles */
184
+ :focus-visible {
185
+ outline: 2px solid oklch(55% 0.25 265);
186
+ outline-offset: 2px;
187
+ border-radius: var(--radius-sm);
188
+ }
189
+
190
+ /* Selection */
191
+ ::selection {
192
+ background-color: oklch(55% 0.25 265 / 0.25);
193
+ }
194
+ }
195
+
196
+ /* ─────────────────────────────────────────────────────────────────────────────
197
+ Utility layer
198
+ ─────────────────────────────────────────────────────────────────────────── */
199
+
200
+ @layer utilities {
201
+ /* Touch-friendly minimum tap target */
202
+ .touch-target {
203
+ min-height: 44px;
204
+ min-width: 44px;
205
+ }
206
+
207
+ /* Smooth transitions */
208
+ .transition-smooth {
209
+ transition: all 0.2s var(--ease-smooth);
210
+ }
211
+
212
+ .transition-spring {
213
+ transition: all 0.3s var(--ease-spring);
214
+ }
215
+
216
+ /* Glass morphism */
217
+ .glass {
218
+ backdrop-filter: blur(12px) saturate(180%);
219
+ background-color: oklch(100% 0 0 / 0.08);
220
+ border: 1px solid oklch(100% 0 0 / 0.12);
221
+ }
222
+
223
+ .dark .glass {
224
+ background-color: oklch(0% 0 0 / 0.2);
225
+ border-color: oklch(100% 0 0 / 0.08);
226
+ }
227
+
228
+ /* Surface utilities */
229
+ .bg-surface { background-color: var(--surface); }
230
+ .bg-surface-elevated { background-color: var(--surface-elevated); }
231
+ .bg-surface-overlay { background-color: var(--surface-overlay); }
232
+ .border-border { border-color: var(--border); }
233
+ .border-border-strong { border-color: var(--border-strong); }
234
+ .text-primary { color: var(--text-primary); }
235
+ .text-secondary { color: var(--text-secondary); }
236
+ .text-muted { color: var(--text-muted); }
237
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@r2digisolutions/components",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "private": false,
5
5
  "description": "R2DigiSolutions Svelte 5 component library — Atomic Design, Tailwind 4, Light/Dark mode",
6
6
  "license": "MIT",
@@ -43,11 +43,13 @@
43
43
  "svelte": "./dist/index.js",
44
44
  "types": "./dist/index.d.ts",
45
45
  "type": "module",
46
+ "style": "./dist/styles.css",
46
47
  "exports": {
47
48
  ".": {
48
49
  "types": "./dist/index.d.ts",
49
50
  "svelte": "./dist/index.js"
50
- }
51
+ },
52
+ "./styles.css": "./dist/styles.css"
51
53
  },
52
54
  "peerDependencies": {
53
55
  "@lucide/svelte": ">=0.400.0",