@gilav21/shadcn-angular 0.0.9 → 0.0.10

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.
@@ -36,29 +36,66 @@ export async function init(options) {
36
36
  config = getDefaultConfig();
37
37
  }
38
38
  else {
39
+ const THEME_COLORS = {
40
+ zinc: '#71717a',
41
+ slate: '#64748b',
42
+ stone: '#78716c',
43
+ gray: '#6b7280',
44
+ neutral: '#737373',
45
+ red: '#ef4444',
46
+ rose: '#f43f5e',
47
+ orange: '#f97316', // bright orange
48
+ green: '#22c55e',
49
+ blue: '#3b82f6',
50
+ yellow: '#eab308',
51
+ violet: '#8b5cf6',
52
+ amber: '#d97706', // warm amber for preview
53
+ };
54
+ const themeChoices = [
55
+ { title: 'Zinc', value: 'zinc' },
56
+ { title: 'Slate', value: 'slate' },
57
+ { title: 'Stone', value: 'stone' },
58
+ { title: 'Gray', value: 'gray' },
59
+ { title: 'Neutral', value: 'neutral' },
60
+ { title: 'Red', value: 'red' },
61
+ { title: 'Rose', value: 'rose' },
62
+ { title: 'Orange', value: 'orange' },
63
+ { title: 'Green', value: 'green' },
64
+ { title: 'Blue', value: 'blue' },
65
+ { title: 'Yellow', value: 'yellow' },
66
+ { title: 'Violet', value: 'violet' },
67
+ { title: 'Amber', value: 'amber' },
68
+ ].map(c => ({
69
+ ...c,
70
+ title: `${chalk.hex(THEME_COLORS[c.value])('██')} ${c.title}`
71
+ }));
72
+ const baseColorChoices = [
73
+ { title: 'Neutral', value: 'neutral' },
74
+ { title: 'Slate', value: 'slate' },
75
+ { title: 'Stone', value: 'stone' },
76
+ { title: 'Gray', value: 'gray' },
77
+ { title: 'Zinc', value: 'zinc' },
78
+ ].map(c => ({
79
+ ...c,
80
+ title: `${chalk.hex(THEME_COLORS[c.value])('██')} ${c.title}`
81
+ }));
39
82
  const responses = await prompts([
40
83
  {
41
84
  type: 'select',
42
- name: 'style',
43
- message: 'Which style would you like to use?',
44
- choices: [
45
- { title: 'Default', value: 'default' },
46
- { title: 'New York', value: 'new-york' },
47
- ],
85
+ name: 'baseColor',
86
+ message: 'Which color would you like to use as base color?',
87
+ choices: baseColorChoices,
48
88
  initial: 0,
49
89
  },
50
90
  {
51
91
  type: 'select',
52
- name: 'baseColor',
53
- message: 'Which color would you like to use as base color?',
54
- choices: [
55
- { title: 'Neutral', value: 'neutral' },
56
- { title: 'Slate', value: 'slate' },
57
- { title: 'Stone', value: 'stone' },
58
- { title: 'Gray', value: 'gray' },
59
- { title: 'Zinc', value: 'zinc' },
60
- ],
61
- initial: 0,
92
+ name: 'theme',
93
+ message: 'Which color would you like to use for the main theme?',
94
+ choices: themeChoices,
95
+ initial: (prev) => {
96
+ const index = themeChoices.findIndex(c => c.value === prev);
97
+ return index === -1 ? 0 : index;
98
+ },
62
99
  },
63
100
  {
64
101
  type: 'text',
@@ -81,10 +118,11 @@ export async function init(options) {
81
118
  ]);
82
119
  config = {
83
120
  $schema: 'https://shadcn-angular.dev/schema.json',
84
- style: responses.style,
121
+ style: 'default',
85
122
  tailwind: {
86
123
  css: responses.globalCss,
87
124
  baseColor: responses.baseColor,
125
+ theme: responses.theme,
88
126
  cssVariables: true,
89
127
  },
90
128
  aliases: {
@@ -115,7 +153,7 @@ export async function init(options) {
115
153
  const stylesDir = path.dirname(path.join(cwd, config.tailwind.css));
116
154
  const tailwindCssPath = path.join(stylesDir, 'tailwind.css');
117
155
  // Write the tailwind.css file with all Tailwind directives
118
- await fs.writeFile(tailwindCssPath, getStylesTemplate(config.tailwind.baseColor));
156
+ await fs.writeFile(tailwindCssPath, getStylesTemplate(config.tailwind.baseColor, config.tailwind.theme));
119
157
  spinner.text = 'Created tailwind.css';
120
158
  // Add import to the user's global styles file if not already present
121
159
  const userStylesPath = path.join(cwd, config.tailwind.css);
@@ -7,6 +7,11 @@ export const registry = {
7
7
  name: 'accordion',
8
8
  files: ['accordion.component.ts'],
9
9
  },
10
+ autocomplete: {
11
+ name: 'autocomplete',
12
+ files: ['autocomplete.component.ts', 'highlight.pipe.ts'],
13
+ dependencies: ['popover', 'command', 'badge'],
14
+ },
10
15
  alert: {
11
16
  name: 'alert',
12
17
  files: ['alert.component.ts'],
@@ -61,6 +66,15 @@ export const registry = {
61
66
  name: 'collapsible',
62
67
  files: ['collapsible.component.ts'],
63
68
  },
69
+ 'color-picker': {
70
+ name: 'color-picker',
71
+ files: ['color-picker.component.ts'],
72
+ dependencies: ['popover', 'input', 'tabs'],
73
+ },
74
+ confetti: {
75
+ name: 'confetti',
76
+ files: ['confetti.directive.ts'],
77
+ },
64
78
  command: {
65
79
  name: 'command',
66
80
  files: ['command.component.ts'],
@@ -95,6 +109,11 @@ export const registry = {
95
109
  name: 'field',
96
110
  files: ['field.component.ts'],
97
111
  },
112
+ 'file-upload': {
113
+ name: 'file-upload',
114
+ files: ['file-upload.component.ts'],
115
+ dependencies: ['button', 'progress'],
116
+ },
98
117
  'hover-card': {
99
118
  name: 'hover-card',
100
119
  files: ['hover-card.component.ts'],
@@ -131,6 +150,10 @@ export const registry = {
131
150
  name: 'navigation-menu',
132
151
  files: ['navigation-menu.component.ts'],
133
152
  },
153
+ 'number-ticker': {
154
+ name: 'number-ticker',
155
+ files: ['number-ticker.component.ts'],
156
+ },
134
157
  pagination: {
135
158
  name: 'pagination',
136
159
  files: ['pagination.component.ts'],
@@ -147,6 +170,10 @@ export const registry = {
147
170
  name: 'radio-group',
148
171
  files: ['radio-group.component.ts'],
149
172
  },
173
+ rating: {
174
+ name: 'rating',
175
+ files: ['rating.component.ts'],
176
+ },
150
177
  resizable: {
151
178
  name: 'resizable',
152
179
  files: ['resizable.component.ts'],
@@ -183,6 +210,10 @@ export const registry = {
183
210
  name: 'spinner',
184
211
  files: ['spinner.component.ts'],
185
212
  },
213
+ stepper: {
214
+ name: 'stepper',
215
+ files: ['stepper.component.ts'],
216
+ },
186
217
  switch: {
187
218
  name: 'switch',
188
219
  files: ['switch.component.ts'],
@@ -199,6 +230,10 @@ export const registry = {
199
230
  name: 'textarea',
200
231
  files: ['textarea.component.ts'],
201
232
  },
233
+ timeline: {
234
+ name: 'timeline',
235
+ files: ['timeline.component.ts'],
236
+ },
202
237
  toast: {
203
238
  name: 'toast',
204
239
  files: ['toast.component.ts'],
@@ -215,6 +250,10 @@ export const registry = {
215
250
  name: 'tooltip',
216
251
  files: ['tooltip.component.ts'],
217
252
  },
253
+ tree: {
254
+ name: 'tree',
255
+ files: ['tree.component.ts'],
256
+ },
218
257
  'speed-dial': {
219
258
  name: 'speed-dial',
220
259
  files: ['speed-dial.component.ts'],
@@ -250,4 +289,69 @@ export const registry = {
250
289
  'scroll-area',
251
290
  ],
252
291
  },
292
+ // Chart Components
293
+ 'pie-chart': {
294
+ name: 'pie-chart',
295
+ files: [
296
+ 'charts/pie-chart.component.ts',
297
+ 'charts/chart.types.ts',
298
+ 'charts/chart.utils.ts',
299
+ ],
300
+ },
301
+ 'pie-chart-drilldown': {
302
+ name: 'pie-chart-drilldown',
303
+ files: [
304
+ 'charts/pie-chart-drilldown.component.ts',
305
+ 'charts/chart.types.ts',
306
+ 'charts/chart.utils.ts',
307
+ ],
308
+ },
309
+ 'bar-chart': {
310
+ name: 'bar-chart',
311
+ files: [
312
+ 'charts/bar-chart.component.ts',
313
+ 'charts/chart.types.ts',
314
+ 'charts/chart.utils.ts',
315
+ ],
316
+ },
317
+ 'bar-chart-drilldown': {
318
+ name: 'bar-chart-drilldown',
319
+ files: [
320
+ 'charts/bar-chart-drilldown.component.ts',
321
+ 'charts/chart.types.ts',
322
+ 'charts/chart.utils.ts',
323
+ ],
324
+ },
325
+ 'stacked-bar-chart': {
326
+ name: 'stacked-bar-chart',
327
+ files: [
328
+ 'charts/stacked-bar-chart.component.ts',
329
+ 'charts/chart.types.ts',
330
+ 'charts/chart.utils.ts',
331
+ ],
332
+ },
333
+ 'column-range-chart': {
334
+ name: 'column-range-chart',
335
+ files: [
336
+ 'charts/column-range-chart.component.ts',
337
+ 'charts/chart.types.ts',
338
+ 'charts/chart.utils.ts',
339
+ ],
340
+ },
341
+ 'bar-race-chart': {
342
+ name: 'bar-race-chart',
343
+ files: [
344
+ 'charts/bar-race-chart.component.ts',
345
+ 'charts/chart.types.ts',
346
+ 'charts/chart.utils.ts',
347
+ ],
348
+ },
349
+ 'org-chart': {
350
+ name: 'org-chart',
351
+ files: [
352
+ 'charts/org-chart.component.ts',
353
+ 'charts/chart.types.ts',
354
+ 'charts/chart.utils.ts',
355
+ ],
356
+ },
253
357
  };
@@ -1,3 +1,4 @@
1
1
  type BaseColor = 'neutral' | 'slate' | 'stone' | 'gray' | 'zinc';
2
- export declare function getStylesTemplate(baseColor?: BaseColor): string;
2
+ type ThemeColor = 'zinc' | 'slate' | 'stone' | 'gray' | 'neutral' | 'red' | 'rose' | 'orange' | 'green' | 'blue' | 'yellow' | 'violet' | 'amber';
3
+ export declare function getStylesTemplate(baseColor?: BaseColor, themeColor?: ThemeColor): string;
3
4
  export {};
@@ -7,8 +7,6 @@ const baseColors = {
7
7
  '--card-foreground': 'oklch(0.145 0 0)',
8
8
  '--popover': 'oklch(1 0 0)',
9
9
  '--popover-foreground': 'oklch(0.145 0 0)',
10
- '--primary': 'oklch(0.205 0 0)',
11
- '--primary-foreground': 'oklch(0.985 0 0)',
12
10
  '--secondary': 'oklch(0.97 0 0)',
13
11
  '--secondary-foreground': 'oklch(0.205 0 0)',
14
12
  '--muted': 'oklch(0.97 0 0)',
@@ -18,7 +16,6 @@ const baseColors = {
18
16
  '--destructive': 'oklch(0.577 0.245 27.325)',
19
17
  '--border': 'oklch(0.922 0 0)',
20
18
  '--input': 'oklch(0.922 0 0)',
21
- '--ring': 'oklch(0.708 0 0)',
22
19
  },
23
20
  dark: {
24
21
  '--background': 'oklch(0.145 0 0)',
@@ -27,8 +24,6 @@ const baseColors = {
27
24
  '--card-foreground': 'oklch(0.985 0 0)',
28
25
  '--popover': 'oklch(0.269 0 0)',
29
26
  '--popover-foreground': 'oklch(0.985 0 0)',
30
- '--primary': 'oklch(0.922 0 0)',
31
- '--primary-foreground': 'oklch(0.205 0 0)',
32
27
  '--secondary': 'oklch(0.269 0 0)',
33
28
  '--secondary-foreground': 'oklch(0.985 0 0)',
34
29
  '--muted': 'oklch(0.269 0 0)',
@@ -38,7 +33,6 @@ const baseColors = {
38
33
  '--destructive': 'oklch(0.704 0.191 22.216)',
39
34
  '--border': 'oklch(1 0 0 / 10%)',
40
35
  '--input': 'oklch(1 0 0 / 15%)',
41
- '--ring': 'oklch(0.556 0 0)',
42
36
  },
43
37
  },
44
38
  slate: {
@@ -49,8 +43,6 @@ const baseColors = {
49
43
  '--card-foreground': 'oklch(0.129 0.042 264.695)',
50
44
  '--popover': 'oklch(1 0 0)',
51
45
  '--popover-foreground': 'oklch(0.129 0.042 264.695)',
52
- '--primary': 'oklch(0.208 0.042 265.755)',
53
- '--primary-foreground': 'oklch(0.984 0.003 247.858)',
54
46
  '--secondary': 'oklch(0.968 0.007 247.896)',
55
47
  '--secondary-foreground': 'oklch(0.208 0.042 265.755)',
56
48
  '--muted': 'oklch(0.968 0.007 247.896)',
@@ -60,7 +52,6 @@ const baseColors = {
60
52
  '--destructive': 'oklch(0.577 0.245 27.325)',
61
53
  '--border': 'oklch(0.929 0.013 255.508)',
62
54
  '--input': 'oklch(0.929 0.013 255.508)',
63
- '--ring': 'oklch(0.704 0.04 256.788)',
64
55
  },
65
56
  dark: {
66
57
  '--background': 'oklch(0.129 0.042 264.695)',
@@ -69,8 +60,6 @@ const baseColors = {
69
60
  '--card-foreground': 'oklch(0.984 0.003 247.858)',
70
61
  '--popover': 'oklch(0.269 0.04 260.031)',
71
62
  '--popover-foreground': 'oklch(0.984 0.003 247.858)',
72
- '--primary': 'oklch(0.929 0.013 255.508)',
73
- '--primary-foreground': 'oklch(0.208 0.042 265.755)',
74
63
  '--secondary': 'oklch(0.269 0.04 260.031)',
75
64
  '--secondary-foreground': 'oklch(0.984 0.003 247.858)',
76
65
  '--muted': 'oklch(0.269 0.04 260.031)',
@@ -80,7 +69,6 @@ const baseColors = {
80
69
  '--destructive': 'oklch(0.704 0.191 22.216)',
81
70
  '--border': 'oklch(1 0 0 / 10%)',
82
71
  '--input': 'oklch(1 0 0 / 15%)',
83
- '--ring': 'oklch(0.554 0.046 257.417)',
84
72
  },
85
73
  },
86
74
  stone: {
@@ -91,8 +79,6 @@ const baseColors = {
91
79
  '--card-foreground': 'oklch(0.147 0.004 49.25)',
92
80
  '--popover': 'oklch(1 0 0)',
93
81
  '--popover-foreground': 'oklch(0.147 0.004 49.25)',
94
- '--primary': 'oklch(0.216 0.006 56.043)',
95
- '--primary-foreground': 'oklch(0.985 0.001 106.423)',
96
82
  '--secondary': 'oklch(0.97 0.001 106.424)',
97
83
  '--secondary-foreground': 'oklch(0.216 0.006 56.043)',
98
84
  '--muted': 'oklch(0.97 0.001 106.424)',
@@ -102,7 +88,6 @@ const baseColors = {
102
88
  '--destructive': 'oklch(0.577 0.245 27.325)',
103
89
  '--border': 'oklch(0.923 0.003 48.717)',
104
90
  '--input': 'oklch(0.923 0.003 48.717)',
105
- '--ring': 'oklch(0.709 0.01 56.259)',
106
91
  },
107
92
  dark: {
108
93
  '--background': 'oklch(0.147 0.004 49.25)',
@@ -111,8 +96,6 @@ const baseColors = {
111
96
  '--card-foreground': 'oklch(0.985 0.001 106.423)',
112
97
  '--popover': 'oklch(0.268 0.007 34.298)',
113
98
  '--popover-foreground': 'oklch(0.985 0.001 106.423)',
114
- '--primary': 'oklch(0.923 0.003 48.717)',
115
- '--primary-foreground': 'oklch(0.216 0.006 56.043)',
116
99
  '--secondary': 'oklch(0.268 0.007 34.298)',
117
100
  '--secondary-foreground': 'oklch(0.985 0.001 106.423)',
118
101
  '--muted': 'oklch(0.268 0.007 34.298)',
@@ -122,7 +105,6 @@ const baseColors = {
122
105
  '--destructive': 'oklch(0.704 0.191 22.216)',
123
106
  '--border': 'oklch(1 0 0 / 10%)',
124
107
  '--input': 'oklch(1 0 0 / 15%)',
125
- '--ring': 'oklch(0.553 0.013 58.071)',
126
108
  },
127
109
  },
128
110
  gray: {
@@ -133,8 +115,6 @@ const baseColors = {
133
115
  '--card-foreground': 'oklch(0.13 0.028 261.692)',
134
116
  '--popover': 'oklch(1 0 0)',
135
117
  '--popover-foreground': 'oklch(0.13 0.028 261.692)',
136
- '--primary': 'oklch(0.21 0.028 264.532)',
137
- '--primary-foreground': 'oklch(0.985 0.002 247.839)',
138
118
  '--secondary': 'oklch(0.967 0.003 264.542)',
139
119
  '--secondary-foreground': 'oklch(0.21 0.028 264.532)',
140
120
  '--muted': 'oklch(0.967 0.003 264.542)',
@@ -144,7 +124,6 @@ const baseColors = {
144
124
  '--destructive': 'oklch(0.577 0.245 27.325)',
145
125
  '--border': 'oklch(0.928 0.006 264.531)',
146
126
  '--input': 'oklch(0.928 0.006 264.531)',
147
- '--ring': 'oklch(0.707 0.022 264.436)',
148
127
  },
149
128
  dark: {
150
129
  '--background': 'oklch(0.13 0.028 261.692)',
@@ -153,8 +132,6 @@ const baseColors = {
153
132
  '--card-foreground': 'oklch(0.985 0.002 247.839)',
154
133
  '--popover': 'oklch(0.274 0.029 256.848)',
155
134
  '--popover-foreground': 'oklch(0.985 0.002 247.839)',
156
- '--primary': 'oklch(0.928 0.006 264.531)',
157
- '--primary-foreground': 'oklch(0.21 0.028 264.532)',
158
135
  '--secondary': 'oklch(0.274 0.029 256.848)',
159
136
  '--secondary-foreground': 'oklch(0.985 0.002 247.839)',
160
137
  '--muted': 'oklch(0.274 0.029 256.848)',
@@ -164,7 +141,6 @@ const baseColors = {
164
141
  '--destructive': 'oklch(0.704 0.191 22.216)',
165
142
  '--border': 'oklch(1 0 0 / 10%)',
166
143
  '--input': 'oklch(1 0 0 / 15%)',
167
- '--ring': 'oklch(0.551 0.027 264.364)',
168
144
  },
169
145
  },
170
146
  zinc: {
@@ -175,8 +151,6 @@ const baseColors = {
175
151
  '--card-foreground': 'oklch(0.141 0.005 285.823)',
176
152
  '--popover': 'oklch(1 0 0)',
177
153
  '--popover-foreground': 'oklch(0.141 0.005 285.823)',
178
- '--primary': 'oklch(0.21 0.006 285.885)',
179
- '--primary-foreground': 'oklch(0.985 0 0)',
180
154
  '--secondary': 'oklch(0.967 0.001 286.375)',
181
155
  '--secondary-foreground': 'oklch(0.21 0.006 285.885)',
182
156
  '--muted': 'oklch(0.967 0.001 286.375)',
@@ -186,7 +160,6 @@ const baseColors = {
186
160
  '--destructive': 'oklch(0.577 0.245 27.325)',
187
161
  '--border': 'oklch(0.92 0.004 286.32)',
188
162
  '--input': 'oklch(0.92 0.004 286.32)',
189
- '--ring': 'oklch(0.705 0.015 286.067)',
190
163
  },
191
164
  dark: {
192
165
  '--background': 'oklch(0.141 0.005 285.823)',
@@ -195,8 +168,6 @@ const baseColors = {
195
168
  '--card-foreground': 'oklch(0.985 0 0)',
196
169
  '--popover': 'oklch(0.274 0.006 286.033)',
197
170
  '--popover-foreground': 'oklch(0.985 0 0)',
198
- '--primary': 'oklch(0.92 0.004 286.32)',
199
- '--primary-foreground': 'oklch(0.21 0.006 285.885)',
200
171
  '--secondary': 'oklch(0.274 0.006 286.033)',
201
172
  '--secondary-foreground': 'oklch(0.985 0 0)',
202
173
  '--muted': 'oklch(0.274 0.006 286.033)',
@@ -206,17 +177,73 @@ const baseColors = {
206
177
  '--destructive': 'oklch(0.704 0.191 22.216)',
207
178
  '--border': 'oklch(1 0 0 / 10%)',
208
179
  '--input': 'oklch(1 0 0 / 15%)',
209
- '--ring': 'oklch(0.552 0.016 285.938)',
210
180
  },
211
181
  },
212
182
  };
183
+ const themeColors = {
184
+ neutral: {
185
+ light: { '--primary': 'oklch(0.205 0 0)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.708 0 0)' },
186
+ dark: { '--primary': 'oklch(0.985 0 0)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.708 0 0)' },
187
+ },
188
+ zinc: {
189
+ light: { '--primary': 'oklch(0.205 0 0)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.708 0 0)' },
190
+ dark: { '--primary': 'oklch(0.985 0 0)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.708 0 0)' },
191
+ },
192
+ slate: {
193
+ light: { '--primary': 'oklch(0.208 0.042 265.755)', '--primary-foreground': 'oklch(0.984 0.003 247.858)', '--ring': 'oklch(0.704 0.04 256.788)' },
194
+ dark: { '--primary': 'oklch(0.929 0.013 255.508)', '--primary-foreground': 'oklch(0.208 0.042 265.755)', '--ring': 'oklch(0.704 0.04 256.788)' },
195
+ },
196
+ stone: {
197
+ light: { '--primary': 'oklch(0.216 0.006 56.043)', '--primary-foreground': 'oklch(0.985 0.001 106.423)', '--ring': 'oklch(0.709 0.01 56.259)' },
198
+ dark: { '--primary': 'oklch(0.923 0.003 48.717)', '--primary-foreground': 'oklch(0.216 0.006 56.043)', '--ring': 'oklch(0.553 0.013 58.071)' },
199
+ },
200
+ gray: {
201
+ light: { '--primary': 'oklch(0.21 0.028 264.532)', '--primary-foreground': 'oklch(0.985 0.002 247.839)', '--ring': 'oklch(0.707 0.022 264.436)' },
202
+ dark: { '--primary': 'oklch(0.928 0.006 264.531)', '--primary-foreground': 'oklch(0.21 0.028 264.532)', '--ring': 'oklch(0.551 0.027 264.364)' },
203
+ },
204
+ red: {
205
+ light: { '--primary': 'oklch(0.577 0.245 27.325)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.577 0.245 27.325)' },
206
+ dark: { '--primary': 'oklch(0.577 0.245 27.325)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.577 0.245 27.325)' },
207
+ },
208
+ rose: {
209
+ light: { '--primary': 'oklch(0.645 0.246 16.439)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.645 0.246 16.439)' },
210
+ dark: { '--primary': 'oklch(0.645 0.246 16.439)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.645 0.246 16.439)' },
211
+ },
212
+ orange: {
213
+ light: { '--primary': 'oklch(0.646 0.222 41.116)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.646 0.222 41.116)' },
214
+ dark: { '--primary': 'oklch(0.646 0.222 41.116)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.646 0.222 41.116)' },
215
+ },
216
+ green: {
217
+ light: { '--primary': 'oklch(0.623 0.214 131.655)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.623 0.214 131.655)' },
218
+ dark: { '--primary': 'oklch(0.623 0.214 131.655)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.623 0.214 131.655)' },
219
+ },
220
+ blue: {
221
+ light: { '--primary': 'oklch(0.546 0.245 262.881)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.546 0.245 262.881)' },
222
+ dark: { '--primary': 'oklch(0.546 0.245 262.881)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.546 0.245 262.881)' },
223
+ },
224
+ yellow: {
225
+ light: { '--primary': 'oklch(0.82 0.185 84.67)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.82 0.185 84.67)' },
226
+ dark: { '--primary': 'oklch(0.82 0.185 84.67)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.82 0.185 84.67)' },
227
+ },
228
+ violet: {
229
+ light: { '--primary': 'oklch(0.558 0.288 302.321)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.558 0.288 302.321)' },
230
+ dark: { '--primary': 'oklch(0.558 0.288 302.321)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.558 0.288 302.321)' },
231
+ },
232
+ amber: {
233
+ light: { '--primary': 'oklch(0.77 0.16 70)', '--primary-foreground': 'oklch(0.145 0 0)', '--ring': 'oklch(0.77 0.16 70)' },
234
+ dark: { '--primary': 'oklch(0.77 0.16 70)', '--primary-foreground': 'oklch(0.145 0 0)', '--ring': 'oklch(0.77 0.16 70)' },
235
+ },
236
+ };
213
237
  function generateCssVars(vars, indent = ' ') {
214
238
  return Object.entries(vars)
215
239
  .map(([key, value]) => `${indent}${key}: ${value};`)
216
240
  .join('\n');
217
241
  }
218
- export function getStylesTemplate(baseColor = 'neutral') {
219
- const colors = baseColors[baseColor];
242
+ export function getStylesTemplate(baseColor = 'neutral', themeColor = 'zinc') {
243
+ const base = baseColors[baseColor];
244
+ const theme = themeColors[themeColor] || themeColors.neutral;
245
+ const lightVars = { ...base.light, ...theme.light };
246
+ const darkVars = { ...base.dark, ...theme.dark };
220
247
  return `@import "tailwindcss";
221
248
 
222
249
  /* Tell Tailwind v4 where to scan for classes */
@@ -227,7 +254,7 @@ export function getStylesTemplate(baseColor = 'neutral') {
227
254
 
228
255
  :root {
229
256
  --radius: 0.625rem;
230
- ${generateCssVars(colors.light)}
257
+ ${generateCssVars(lightVars)}
231
258
  --chart-1: oklch(0.646 0.222 41.116);
232
259
  --chart-2: oklch(0.6 0.118 184.704);
233
260
  --chart-3: oklch(0.398 0.07 227.392);
@@ -244,7 +271,7 @@ ${generateCssVars(colors.light)}
244
271
  }
245
272
 
246
273
  .dark {
247
- ${generateCssVars(colors.dark)}
274
+ ${generateCssVars(darkVars)}
248
275
  --chart-1: oklch(0.488 0.243 264.376);
249
276
  --chart-2: oklch(0.696 0.17 162.48);
250
277
  --chart-3: oklch(0.769 0.188 70.08);
@@ -314,6 +341,7 @@ ${generateCssVars(colors.dark)}
314
341
  }
315
342
  html {
316
343
  font-family: var(--font-sans);
344
+ font-size: 16px;
317
345
  }
318
346
  button:not(:disabled),
319
347
  [role="button"]:not(:disabled) {
@@ -8,5 +8,14 @@ import { twMerge } from 'tailwind-merge';
8
8
  export function cn(...inputs: ClassValue[]): string {
9
9
  return twMerge(clsx(inputs));
10
10
  }
11
+
12
+ /**
13
+ * Check if the current direction is RTL by reading the computed style of the element.
14
+ * This allows components to detect RTL without needing an explicit input.
15
+ */
16
+ export function isRtl(el: HTMLElement): boolean {
17
+ return getComputedStyle(el).direction === 'rtl';
18
+ }
19
+
11
20
  `;
12
21
  }
@@ -1,9 +1,10 @@
1
1
  export interface Config {
2
2
  $schema: string;
3
- style: 'default' | 'new-york';
3
+ style: 'default';
4
4
  tailwind: {
5
5
  css: string;
6
6
  baseColor: 'neutral' | 'slate' | 'stone' | 'gray' | 'zinc';
7
+ theme?: 'zinc' | 'slate' | 'stone' | 'gray' | 'neutral' | 'red' | 'rose' | 'orange' | 'green' | 'blue' | 'yellow' | 'violet' | 'amber';
7
8
  cssVariables: boolean;
8
9
  };
9
10
  aliases: {
@@ -7,6 +7,7 @@ export function getDefaultConfig() {
7
7
  tailwind: {
8
8
  css: 'src/styles.scss',
9
9
  baseColor: 'neutral',
10
+ theme: 'zinc',
10
11
  cssVariables: true,
11
12
  },
12
13
  aliases: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gilav21/shadcn-angular",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "CLI for adding shadcn-angular components to your project",
5
5
  "bin": {
6
6
  "shadcn-angular": "./dist/index.js"
@@ -46,29 +46,70 @@ export async function init(options: InitOptions) {
46
46
  if (options.defaults || options.yes) {
47
47
  config = getDefaultConfig();
48
48
  } else {
49
+ const THEME_COLORS: Record<string, string> = {
50
+ zinc: '#71717a',
51
+ slate: '#64748b',
52
+ stone: '#78716c',
53
+ gray: '#6b7280',
54
+ neutral: '#737373',
55
+ red: '#ef4444',
56
+ rose: '#f43f5e',
57
+ orange: '#f97316', // bright orange
58
+ green: '#22c55e',
59
+ blue: '#3b82f6',
60
+ yellow: '#eab308',
61
+ violet: '#8b5cf6',
62
+ amber: '#d97706', // warm amber for preview
63
+ };
64
+
65
+ const themeChoices = [
66
+ { title: 'Zinc', value: 'zinc' },
67
+ { title: 'Slate', value: 'slate' },
68
+ { title: 'Stone', value: 'stone' },
69
+ { title: 'Gray', value: 'gray' },
70
+ { title: 'Neutral', value: 'neutral' },
71
+ { title: 'Red', value: 'red' },
72
+ { title: 'Rose', value: 'rose' },
73
+ { title: 'Orange', value: 'orange' },
74
+ { title: 'Green', value: 'green' },
75
+ { title: 'Blue', value: 'blue' },
76
+ { title: 'Yellow', value: 'yellow' },
77
+ { title: 'Violet', value: 'violet' },
78
+ { title: 'Amber', value: 'amber' },
79
+ ].map(c => ({
80
+ ...c,
81
+ title: `${chalk.hex(THEME_COLORS[c.value])('██')} ${c.title}`
82
+ }));
83
+
84
+ const baseColorChoices = [
85
+ { title: 'Neutral', value: 'neutral' },
86
+ { title: 'Slate', value: 'slate' },
87
+ { title: 'Stone', value: 'stone' },
88
+ { title: 'Gray', value: 'gray' },
89
+ { title: 'Zinc', value: 'zinc' },
90
+ ].map(c => ({
91
+ ...c,
92
+ title: `${chalk.hex(THEME_COLORS[c.value])('██')} ${c.title}`
93
+ }));
94
+
49
95
  const responses = await prompts([
96
+
50
97
  {
51
98
  type: 'select',
52
- name: 'style',
53
- message: 'Which style would you like to use?',
54
- choices: [
55
- { title: 'Default', value: 'default' },
56
- { title: 'New York', value: 'new-york' },
57
- ],
99
+ name: 'baseColor',
100
+ message: 'Which color would you like to use as base color?',
101
+ choices: baseColorChoices,
58
102
  initial: 0,
59
103
  },
60
104
  {
61
105
  type: 'select',
62
- name: 'baseColor',
63
- message: 'Which color would you like to use as base color?',
64
- choices: [
65
- { title: 'Neutral', value: 'neutral' },
66
- { title: 'Slate', value: 'slate' },
67
- { title: 'Stone', value: 'stone' },
68
- { title: 'Gray', value: 'gray' },
69
- { title: 'Zinc', value: 'zinc' },
70
- ],
71
- initial: 0,
106
+ name: 'theme',
107
+ message: 'Which color would you like to use for the main theme?',
108
+ choices: themeChoices,
109
+ initial: (prev: string) => {
110
+ const index = themeChoices.findIndex(c => c.value === prev);
111
+ return index === -1 ? 0 : index;
112
+ },
72
113
  },
73
114
  {
74
115
  type: 'text',
@@ -92,10 +133,11 @@ export async function init(options: InitOptions) {
92
133
 
93
134
  config = {
94
135
  $schema: 'https://shadcn-angular.dev/schema.json',
95
- style: responses.style,
136
+ style: 'default',
96
137
  tailwind: {
97
138
  css: responses.globalCss,
98
139
  baseColor: responses.baseColor,
140
+ theme: responses.theme,
99
141
  cssVariables: true,
100
142
  },
101
143
  aliases: {
@@ -133,7 +175,7 @@ export async function init(options: InitOptions) {
133
175
  const tailwindCssPath = path.join(stylesDir, 'tailwind.css');
134
176
 
135
177
  // Write the tailwind.css file with all Tailwind directives
136
- await fs.writeFile(tailwindCssPath, getStylesTemplate(config.tailwind.baseColor));
178
+ await fs.writeFile(tailwindCssPath, getStylesTemplate(config.tailwind.baseColor, config.tailwind.theme));
137
179
  spinner.text = 'Created tailwind.css';
138
180
 
139
181
  // Add import to the user's global styles file if not already present
@@ -16,6 +16,11 @@ export const registry: Record<string, ComponentDefinition> = {
16
16
  name: 'accordion',
17
17
  files: ['accordion.component.ts'],
18
18
  },
19
+ autocomplete: {
20
+ name: 'autocomplete',
21
+ files: ['autocomplete.component.ts', 'highlight.pipe.ts'],
22
+ dependencies: ['popover', 'command', 'badge'],
23
+ },
19
24
  alert: {
20
25
  name: 'alert',
21
26
  files: ['alert.component.ts'],
@@ -70,6 +75,15 @@ export const registry: Record<string, ComponentDefinition> = {
70
75
  name: 'collapsible',
71
76
  files: ['collapsible.component.ts'],
72
77
  },
78
+ 'color-picker': {
79
+ name: 'color-picker',
80
+ files: ['color-picker.component.ts'],
81
+ dependencies: ['popover', 'input', 'tabs'],
82
+ },
83
+ confetti: {
84
+ name: 'confetti',
85
+ files: ['confetti.directive.ts'],
86
+ },
73
87
  command: {
74
88
  name: 'command',
75
89
  files: ['command.component.ts'],
@@ -104,6 +118,11 @@ export const registry: Record<string, ComponentDefinition> = {
104
118
  name: 'field',
105
119
  files: ['field.component.ts'],
106
120
  },
121
+ 'file-upload': {
122
+ name: 'file-upload',
123
+ files: ['file-upload.component.ts'],
124
+ dependencies: ['button', 'progress'],
125
+ },
107
126
  'hover-card': {
108
127
  name: 'hover-card',
109
128
  files: ['hover-card.component.ts'],
@@ -140,6 +159,10 @@ export const registry: Record<string, ComponentDefinition> = {
140
159
  name: 'navigation-menu',
141
160
  files: ['navigation-menu.component.ts'],
142
161
  },
162
+ 'number-ticker': {
163
+ name: 'number-ticker',
164
+ files: ['number-ticker.component.ts'],
165
+ },
143
166
  pagination: {
144
167
  name: 'pagination',
145
168
  files: ['pagination.component.ts'],
@@ -156,6 +179,10 @@ export const registry: Record<string, ComponentDefinition> = {
156
179
  name: 'radio-group',
157
180
  files: ['radio-group.component.ts'],
158
181
  },
182
+ rating: {
183
+ name: 'rating',
184
+ files: ['rating.component.ts'],
185
+ },
159
186
  resizable: {
160
187
  name: 'resizable',
161
188
  files: ['resizable.component.ts'],
@@ -192,6 +219,10 @@ export const registry: Record<string, ComponentDefinition> = {
192
219
  name: 'spinner',
193
220
  files: ['spinner.component.ts'],
194
221
  },
222
+ stepper: {
223
+ name: 'stepper',
224
+ files: ['stepper.component.ts'],
225
+ },
195
226
  switch: {
196
227
  name: 'switch',
197
228
  files: ['switch.component.ts'],
@@ -208,6 +239,10 @@ export const registry: Record<string, ComponentDefinition> = {
208
239
  name: 'textarea',
209
240
  files: ['textarea.component.ts'],
210
241
  },
242
+ timeline: {
243
+ name: 'timeline',
244
+ files: ['timeline.component.ts'],
245
+ },
211
246
  toast: {
212
247
  name: 'toast',
213
248
  files: ['toast.component.ts'],
@@ -224,6 +259,10 @@ export const registry: Record<string, ComponentDefinition> = {
224
259
  name: 'tooltip',
225
260
  files: ['tooltip.component.ts'],
226
261
  },
262
+ tree: {
263
+ name: 'tree',
264
+ files: ['tree.component.ts'],
265
+ },
227
266
  'speed-dial': {
228
267
  name: 'speed-dial',
229
268
  files: ['speed-dial.component.ts'],
@@ -259,4 +298,69 @@ export const registry: Record<string, ComponentDefinition> = {
259
298
  'scroll-area',
260
299
  ],
261
300
  },
301
+ // Chart Components
302
+ 'pie-chart': {
303
+ name: 'pie-chart',
304
+ files: [
305
+ 'charts/pie-chart.component.ts',
306
+ 'charts/chart.types.ts',
307
+ 'charts/chart.utils.ts',
308
+ ],
309
+ },
310
+ 'pie-chart-drilldown': {
311
+ name: 'pie-chart-drilldown',
312
+ files: [
313
+ 'charts/pie-chart-drilldown.component.ts',
314
+ 'charts/chart.types.ts',
315
+ 'charts/chart.utils.ts',
316
+ ],
317
+ },
318
+ 'bar-chart': {
319
+ name: 'bar-chart',
320
+ files: [
321
+ 'charts/bar-chart.component.ts',
322
+ 'charts/chart.types.ts',
323
+ 'charts/chart.utils.ts',
324
+ ],
325
+ },
326
+ 'bar-chart-drilldown': {
327
+ name: 'bar-chart-drilldown',
328
+ files: [
329
+ 'charts/bar-chart-drilldown.component.ts',
330
+ 'charts/chart.types.ts',
331
+ 'charts/chart.utils.ts',
332
+ ],
333
+ },
334
+ 'stacked-bar-chart': {
335
+ name: 'stacked-bar-chart',
336
+ files: [
337
+ 'charts/stacked-bar-chart.component.ts',
338
+ 'charts/chart.types.ts',
339
+ 'charts/chart.utils.ts',
340
+ ],
341
+ },
342
+ 'column-range-chart': {
343
+ name: 'column-range-chart',
344
+ files: [
345
+ 'charts/column-range-chart.component.ts',
346
+ 'charts/chart.types.ts',
347
+ 'charts/chart.utils.ts',
348
+ ],
349
+ },
350
+ 'bar-race-chart': {
351
+ name: 'bar-race-chart',
352
+ files: [
353
+ 'charts/bar-race-chart.component.ts',
354
+ 'charts/chart.types.ts',
355
+ 'charts/chart.utils.ts',
356
+ ],
357
+ },
358
+ 'org-chart': {
359
+ name: 'org-chart',
360
+ files: [
361
+ 'charts/org-chart.component.ts',
362
+ 'charts/chart.types.ts',
363
+ 'charts/chart.utils.ts',
364
+ ],
365
+ },
262
366
  };
@@ -1,4 +1,5 @@
1
1
  type BaseColor = 'neutral' | 'slate' | 'stone' | 'gray' | 'zinc';
2
+ type ThemeColor = 'zinc' | 'slate' | 'stone' | 'gray' | 'neutral' | 'red' | 'rose' | 'orange' | 'green' | 'blue' | 'yellow' | 'violet' | 'amber';
2
3
 
3
4
  const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Record<string, string> }> = {
4
5
  neutral: {
@@ -9,8 +10,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
9
10
  '--card-foreground': 'oklch(0.145 0 0)',
10
11
  '--popover': 'oklch(1 0 0)',
11
12
  '--popover-foreground': 'oklch(0.145 0 0)',
12
- '--primary': 'oklch(0.205 0 0)',
13
- '--primary-foreground': 'oklch(0.985 0 0)',
14
13
  '--secondary': 'oklch(0.97 0 0)',
15
14
  '--secondary-foreground': 'oklch(0.205 0 0)',
16
15
  '--muted': 'oklch(0.97 0 0)',
@@ -20,7 +19,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
20
19
  '--destructive': 'oklch(0.577 0.245 27.325)',
21
20
  '--border': 'oklch(0.922 0 0)',
22
21
  '--input': 'oklch(0.922 0 0)',
23
- '--ring': 'oklch(0.708 0 0)',
24
22
  },
25
23
  dark: {
26
24
  '--background': 'oklch(0.145 0 0)',
@@ -29,8 +27,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
29
27
  '--card-foreground': 'oklch(0.985 0 0)',
30
28
  '--popover': 'oklch(0.269 0 0)',
31
29
  '--popover-foreground': 'oklch(0.985 0 0)',
32
- '--primary': 'oklch(0.922 0 0)',
33
- '--primary-foreground': 'oklch(0.205 0 0)',
34
30
  '--secondary': 'oklch(0.269 0 0)',
35
31
  '--secondary-foreground': 'oklch(0.985 0 0)',
36
32
  '--muted': 'oklch(0.269 0 0)',
@@ -40,7 +36,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
40
36
  '--destructive': 'oklch(0.704 0.191 22.216)',
41
37
  '--border': 'oklch(1 0 0 / 10%)',
42
38
  '--input': 'oklch(1 0 0 / 15%)',
43
- '--ring': 'oklch(0.556 0 0)',
44
39
  },
45
40
  },
46
41
  slate: {
@@ -51,8 +46,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
51
46
  '--card-foreground': 'oklch(0.129 0.042 264.695)',
52
47
  '--popover': 'oklch(1 0 0)',
53
48
  '--popover-foreground': 'oklch(0.129 0.042 264.695)',
54
- '--primary': 'oklch(0.208 0.042 265.755)',
55
- '--primary-foreground': 'oklch(0.984 0.003 247.858)',
56
49
  '--secondary': 'oklch(0.968 0.007 247.896)',
57
50
  '--secondary-foreground': 'oklch(0.208 0.042 265.755)',
58
51
  '--muted': 'oklch(0.968 0.007 247.896)',
@@ -62,7 +55,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
62
55
  '--destructive': 'oklch(0.577 0.245 27.325)',
63
56
  '--border': 'oklch(0.929 0.013 255.508)',
64
57
  '--input': 'oklch(0.929 0.013 255.508)',
65
- '--ring': 'oklch(0.704 0.04 256.788)',
66
58
  },
67
59
  dark: {
68
60
  '--background': 'oklch(0.129 0.042 264.695)',
@@ -71,8 +63,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
71
63
  '--card-foreground': 'oklch(0.984 0.003 247.858)',
72
64
  '--popover': 'oklch(0.269 0.04 260.031)',
73
65
  '--popover-foreground': 'oklch(0.984 0.003 247.858)',
74
- '--primary': 'oklch(0.929 0.013 255.508)',
75
- '--primary-foreground': 'oklch(0.208 0.042 265.755)',
76
66
  '--secondary': 'oklch(0.269 0.04 260.031)',
77
67
  '--secondary-foreground': 'oklch(0.984 0.003 247.858)',
78
68
  '--muted': 'oklch(0.269 0.04 260.031)',
@@ -82,7 +72,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
82
72
  '--destructive': 'oklch(0.704 0.191 22.216)',
83
73
  '--border': 'oklch(1 0 0 / 10%)',
84
74
  '--input': 'oklch(1 0 0 / 15%)',
85
- '--ring': 'oklch(0.554 0.046 257.417)',
86
75
  },
87
76
  },
88
77
  stone: {
@@ -93,8 +82,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
93
82
  '--card-foreground': 'oklch(0.147 0.004 49.25)',
94
83
  '--popover': 'oklch(1 0 0)',
95
84
  '--popover-foreground': 'oklch(0.147 0.004 49.25)',
96
- '--primary': 'oklch(0.216 0.006 56.043)',
97
- '--primary-foreground': 'oklch(0.985 0.001 106.423)',
98
85
  '--secondary': 'oklch(0.97 0.001 106.424)',
99
86
  '--secondary-foreground': 'oklch(0.216 0.006 56.043)',
100
87
  '--muted': 'oklch(0.97 0.001 106.424)',
@@ -104,7 +91,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
104
91
  '--destructive': 'oklch(0.577 0.245 27.325)',
105
92
  '--border': 'oklch(0.923 0.003 48.717)',
106
93
  '--input': 'oklch(0.923 0.003 48.717)',
107
- '--ring': 'oklch(0.709 0.01 56.259)',
108
94
  },
109
95
  dark: {
110
96
  '--background': 'oklch(0.147 0.004 49.25)',
@@ -113,8 +99,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
113
99
  '--card-foreground': 'oklch(0.985 0.001 106.423)',
114
100
  '--popover': 'oklch(0.268 0.007 34.298)',
115
101
  '--popover-foreground': 'oklch(0.985 0.001 106.423)',
116
- '--primary': 'oklch(0.923 0.003 48.717)',
117
- '--primary-foreground': 'oklch(0.216 0.006 56.043)',
118
102
  '--secondary': 'oklch(0.268 0.007 34.298)',
119
103
  '--secondary-foreground': 'oklch(0.985 0.001 106.423)',
120
104
  '--muted': 'oklch(0.268 0.007 34.298)',
@@ -124,7 +108,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
124
108
  '--destructive': 'oklch(0.704 0.191 22.216)',
125
109
  '--border': 'oklch(1 0 0 / 10%)',
126
110
  '--input': 'oklch(1 0 0 / 15%)',
127
- '--ring': 'oklch(0.553 0.013 58.071)',
128
111
  },
129
112
  },
130
113
  gray: {
@@ -135,8 +118,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
135
118
  '--card-foreground': 'oklch(0.13 0.028 261.692)',
136
119
  '--popover': 'oklch(1 0 0)',
137
120
  '--popover-foreground': 'oklch(0.13 0.028 261.692)',
138
- '--primary': 'oklch(0.21 0.028 264.532)',
139
- '--primary-foreground': 'oklch(0.985 0.002 247.839)',
140
121
  '--secondary': 'oklch(0.967 0.003 264.542)',
141
122
  '--secondary-foreground': 'oklch(0.21 0.028 264.532)',
142
123
  '--muted': 'oklch(0.967 0.003 264.542)',
@@ -146,7 +127,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
146
127
  '--destructive': 'oklch(0.577 0.245 27.325)',
147
128
  '--border': 'oklch(0.928 0.006 264.531)',
148
129
  '--input': 'oklch(0.928 0.006 264.531)',
149
- '--ring': 'oklch(0.707 0.022 264.436)',
150
130
  },
151
131
  dark: {
152
132
  '--background': 'oklch(0.13 0.028 261.692)',
@@ -155,8 +135,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
155
135
  '--card-foreground': 'oklch(0.985 0.002 247.839)',
156
136
  '--popover': 'oklch(0.274 0.029 256.848)',
157
137
  '--popover-foreground': 'oklch(0.985 0.002 247.839)',
158
- '--primary': 'oklch(0.928 0.006 264.531)',
159
- '--primary-foreground': 'oklch(0.21 0.028 264.532)',
160
138
  '--secondary': 'oklch(0.274 0.029 256.848)',
161
139
  '--secondary-foreground': 'oklch(0.985 0.002 247.839)',
162
140
  '--muted': 'oklch(0.274 0.029 256.848)',
@@ -166,7 +144,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
166
144
  '--destructive': 'oklch(0.704 0.191 22.216)',
167
145
  '--border': 'oklch(1 0 0 / 10%)',
168
146
  '--input': 'oklch(1 0 0 / 15%)',
169
- '--ring': 'oklch(0.551 0.027 264.364)',
170
147
  },
171
148
  },
172
149
  zinc: {
@@ -177,8 +154,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
177
154
  '--card-foreground': 'oklch(0.141 0.005 285.823)',
178
155
  '--popover': 'oklch(1 0 0)',
179
156
  '--popover-foreground': 'oklch(0.141 0.005 285.823)',
180
- '--primary': 'oklch(0.21 0.006 285.885)',
181
- '--primary-foreground': 'oklch(0.985 0 0)',
182
157
  '--secondary': 'oklch(0.967 0.001 286.375)',
183
158
  '--secondary-foreground': 'oklch(0.21 0.006 285.885)',
184
159
  '--muted': 'oklch(0.967 0.001 286.375)',
@@ -188,7 +163,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
188
163
  '--destructive': 'oklch(0.577 0.245 27.325)',
189
164
  '--border': 'oklch(0.92 0.004 286.32)',
190
165
  '--input': 'oklch(0.92 0.004 286.32)',
191
- '--ring': 'oklch(0.705 0.015 286.067)',
192
166
  },
193
167
  dark: {
194
168
  '--background': 'oklch(0.141 0.005 285.823)',
@@ -197,8 +171,6 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
197
171
  '--card-foreground': 'oklch(0.985 0 0)',
198
172
  '--popover': 'oklch(0.274 0.006 286.033)',
199
173
  '--popover-foreground': 'oklch(0.985 0 0)',
200
- '--primary': 'oklch(0.92 0.004 286.32)',
201
- '--primary-foreground': 'oklch(0.21 0.006 285.885)',
202
174
  '--secondary': 'oklch(0.274 0.006 286.033)',
203
175
  '--secondary-foreground': 'oklch(0.985 0 0)',
204
176
  '--muted': 'oklch(0.274 0.006 286.033)',
@@ -208,19 +180,77 @@ const baseColors: Record<BaseColor, { light: Record<string, string>; dark: Recor
208
180
  '--destructive': 'oklch(0.704 0.191 22.216)',
209
181
  '--border': 'oklch(1 0 0 / 10%)',
210
182
  '--input': 'oklch(1 0 0 / 15%)',
211
- '--ring': 'oklch(0.552 0.016 285.938)',
212
183
  },
213
184
  },
214
185
  };
215
186
 
187
+ const themeColors: Record<ThemeColor, { light: Record<string, string>; dark: Record<string, string> }> = {
188
+ neutral: {
189
+ light: { '--primary': 'oklch(0.205 0 0)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.708 0 0)' },
190
+ dark: { '--primary': 'oklch(0.985 0 0)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.708 0 0)' },
191
+ },
192
+ zinc: { // Same as neutral for now
193
+ light: { '--primary': 'oklch(0.205 0 0)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.708 0 0)' },
194
+ dark: { '--primary': 'oklch(0.985 0 0)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.708 0 0)' },
195
+ },
196
+ slate: {
197
+ light: { '--primary': 'oklch(0.208 0.042 265.755)', '--primary-foreground': 'oklch(0.984 0.003 247.858)', '--ring': 'oklch(0.704 0.04 256.788)' },
198
+ dark: { '--primary': 'oklch(0.929 0.013 255.508)', '--primary-foreground': 'oklch(0.208 0.042 265.755)', '--ring': 'oklch(0.704 0.04 256.788)' },
199
+ },
200
+ stone: {
201
+ light: { '--primary': 'oklch(0.216 0.006 56.043)', '--primary-foreground': 'oklch(0.985 0.001 106.423)', '--ring': 'oklch(0.709 0.01 56.259)' },
202
+ dark: { '--primary': 'oklch(0.923 0.003 48.717)', '--primary-foreground': 'oklch(0.216 0.006 56.043)', '--ring': 'oklch(0.553 0.013 58.071)' },
203
+ },
204
+ gray: {
205
+ light: { '--primary': 'oklch(0.21 0.028 264.532)', '--primary-foreground': 'oklch(0.985 0.002 247.839)', '--ring': 'oklch(0.707 0.022 264.436)' },
206
+ dark: { '--primary': 'oklch(0.928 0.006 264.531)', '--primary-foreground': 'oklch(0.21 0.028 264.532)', '--ring': 'oklch(0.551 0.027 264.364)' },
207
+ },
208
+ red: {
209
+ light: { '--primary': 'oklch(0.577 0.245 27.325)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.577 0.245 27.325)' },
210
+ dark: { '--primary': 'oklch(0.577 0.245 27.325)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.577 0.245 27.325)' },
211
+ },
212
+ rose: {
213
+ light: { '--primary': 'oklch(0.645 0.246 16.439)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.645 0.246 16.439)' },
214
+ dark: { '--primary': 'oklch(0.645 0.246 16.439)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.645 0.246 16.439)' },
215
+ },
216
+ orange: {
217
+ light: { '--primary': 'oklch(0.646 0.222 41.116)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.646 0.222 41.116)' },
218
+ dark: { '--primary': 'oklch(0.646 0.222 41.116)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.646 0.222 41.116)' },
219
+ },
220
+ green: {
221
+ light: { '--primary': 'oklch(0.623 0.214 131.655)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.623 0.214 131.655)' },
222
+ dark: { '--primary': 'oklch(0.623 0.214 131.655)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.623 0.214 131.655)' },
223
+ },
224
+ blue: {
225
+ light: { '--primary': 'oklch(0.546 0.245 262.881)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.546 0.245 262.881)' },
226
+ dark: { '--primary': 'oklch(0.546 0.245 262.881)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.546 0.245 262.881)' },
227
+ },
228
+ yellow: {
229
+ light: { '--primary': 'oklch(0.82 0.185 84.67)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.82 0.185 84.67)' },
230
+ dark: { '--primary': 'oklch(0.82 0.185 84.67)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.82 0.185 84.67)' },
231
+ },
232
+ violet: {
233
+ light: { '--primary': 'oklch(0.558 0.288 302.321)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.558 0.288 302.321)' },
234
+ dark: { '--primary': 'oklch(0.558 0.288 302.321)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.558 0.288 302.321)' },
235
+ },
236
+ amber: {
237
+ light: { '--primary': 'oklch(0.77 0.16 70)', '--primary-foreground': 'oklch(0.145 0 0)', '--ring': 'oklch(0.77 0.16 70)' },
238
+ dark: { '--primary': 'oklch(0.77 0.16 70)', '--primary-foreground': 'oklch(0.145 0 0)', '--ring': 'oklch(0.77 0.16 70)' },
239
+ },
240
+ };
241
+
216
242
  function generateCssVars(vars: Record<string, string>, indent: string = ' '): string {
217
243
  return Object.entries(vars)
218
244
  .map(([key, value]) => `${indent}${key}: ${value};`)
219
245
  .join('\n');
220
246
  }
221
247
 
222
- export function getStylesTemplate(baseColor: BaseColor = 'neutral'): string {
223
- const colors = baseColors[baseColor];
248
+ export function getStylesTemplate(baseColor: BaseColor = 'neutral', themeColor: ThemeColor = 'zinc'): string {
249
+ const base = baseColors[baseColor];
250
+ const theme = themeColors[themeColor] || themeColors.neutral;
251
+
252
+ const lightVars = { ...base.light, ...theme.light };
253
+ const darkVars = { ...base.dark, ...theme.dark };
224
254
 
225
255
  return `@import "tailwindcss";
226
256
 
@@ -232,7 +262,7 @@ export function getStylesTemplate(baseColor: BaseColor = 'neutral'): string {
232
262
 
233
263
  :root {
234
264
  --radius: 0.625rem;
235
- ${generateCssVars(colors.light)}
265
+ ${generateCssVars(lightVars)}
236
266
  --chart-1: oklch(0.646 0.222 41.116);
237
267
  --chart-2: oklch(0.6 0.118 184.704);
238
268
  --chart-3: oklch(0.398 0.07 227.392);
@@ -249,7 +279,7 @@ ${generateCssVars(colors.light)}
249
279
  }
250
280
 
251
281
  .dark {
252
- ${generateCssVars(colors.dark)}
282
+ ${generateCssVars(darkVars)}
253
283
  --chart-1: oklch(0.488 0.243 264.376);
254
284
  --chart-2: oklch(0.696 0.17 162.48);
255
285
  --chart-3: oklch(0.769 0.188 70.08);
@@ -319,6 +349,7 @@ ${generateCssVars(colors.dark)}
319
349
  }
320
350
  html {
321
351
  font-family: var(--font-sans);
352
+ font-size: 16px;
322
353
  }
323
354
  button:not(:disabled),
324
355
  [role="button"]:not(:disabled) {
@@ -1,5 +1,5 @@
1
1
  export function getUtilsTemplate(): string {
2
- return `import { clsx, type ClassValue } from 'clsx';
2
+ return `import { clsx, type ClassValue } from 'clsx';
3
3
  import { twMerge } from 'tailwind-merge';
4
4
 
5
5
  /**
@@ -8,5 +8,14 @@ import { twMerge } from 'tailwind-merge';
8
8
  export function cn(...inputs: ClassValue[]): string {
9
9
  return twMerge(clsx(inputs));
10
10
  }
11
+
12
+ /**
13
+ * Check if the current direction is RTL by reading the computed style of the element.
14
+ * This allows components to detect RTL without needing an explicit input.
15
+ */
16
+ export function isRtl(el: HTMLElement): boolean {
17
+ return getComputedStyle(el).direction === 'rtl';
18
+ }
19
+
11
20
  `;
12
21
  }
@@ -3,10 +3,11 @@ import path from 'path';
3
3
 
4
4
  export interface Config {
5
5
  $schema: string;
6
- style: 'default' | 'new-york';
6
+ style: 'default';
7
7
  tailwind: {
8
8
  css: string;
9
9
  baseColor: 'neutral' | 'slate' | 'stone' | 'gray' | 'zinc';
10
+ theme?: 'zinc' | 'slate' | 'stone' | 'gray' | 'neutral' | 'red' | 'rose' | 'orange' | 'green' | 'blue' | 'yellow' | 'violet' | 'amber';
10
11
  cssVariables: boolean;
11
12
  };
12
13
  aliases: {
@@ -24,6 +25,7 @@ export function getDefaultConfig(): Config {
24
25
  tailwind: {
25
26
  css: 'src/styles.scss',
26
27
  baseColor: 'neutral',
28
+ theme: 'zinc',
27
29
  cssVariables: true,
28
30
  },
29
31
  aliases: {