@qdesignsystems/design-system-core 0.1.3 → 0.1.5
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 +82 -28
- package/package.json +8 -2
- package/scripts/init.cjs +156 -0
package/README.md
CHANGED
|
@@ -1,45 +1,99 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @qdesignsystems/design-system-core
|
|
2
2
|
|
|
3
|
-
Core
|
|
3
|
+
Core component library for the Q Design System, built on shadcn/ui and Radix UI.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Setup
|
|
8
|
+
|
|
9
|
+
### Step 1 — Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# With the MYRA theme
|
|
13
|
+
npm install @qdesignsystems/design-system-core@latest @qdesignsystems/theme-myra@latest
|
|
14
|
+
|
|
15
|
+
# With the Q theme
|
|
16
|
+
npm install @qdesignsystems/design-system-core@latest @qdesignsystems/theme-q@latest
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Step 2 — Run the init command
|
|
20
|
+
|
|
21
|
+
The init command automatically patches your `index.css` and `main.tsx` for you:
|
|
6
22
|
|
|
7
23
|
```bash
|
|
8
|
-
|
|
24
|
+
# For the MYRA theme
|
|
25
|
+
npx qds-init --theme=myra
|
|
26
|
+
|
|
27
|
+
# For the Q theme
|
|
28
|
+
npx qds-init --theme=q
|
|
9
29
|
```
|
|
10
30
|
|
|
11
|
-
|
|
31
|
+
This will:
|
|
32
|
+
1. Remove the default `:root { }` and `.dark { }` CSS variable blocks from `src/index.css` (they override the theme if left in)
|
|
33
|
+
2. Add the correct CSS imports to `src/main.tsx` in the right order
|
|
34
|
+
|
|
35
|
+
### Step 3 — Done
|
|
36
|
+
|
|
37
|
+
Your app now uses the Q Design System with the selected theme.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Manual Setup
|
|
42
|
+
|
|
43
|
+
If you prefer to set things up manually:
|
|
44
|
+
|
|
45
|
+
### 1. Add imports to `src/main.tsx` (at the very top, before all other imports)
|
|
12
46
|
|
|
13
47
|
```tsx
|
|
14
|
-
import
|
|
15
|
-
import '@
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
48
|
+
import '@qdesignsystems/design-system-core/styles.css';
|
|
49
|
+
import '@qdesignsystems/theme-myra/styles.css'; // or theme-q
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Clean up `src/index.css`
|
|
53
|
+
|
|
54
|
+
Remove the `:root { }` and `.dark { }` blocks that contain CSS variable declarations (lines like `--primary: ...`, `--background: ...`). These override the theme.
|
|
55
|
+
|
|
56
|
+
Your `index.css` should contain only:
|
|
57
|
+
|
|
58
|
+
```css
|
|
59
|
+
@tailwind base;
|
|
60
|
+
@tailwind components;
|
|
61
|
+
@tailwind utilities;
|
|
62
|
+
|
|
63
|
+
@layer base {
|
|
64
|
+
* {
|
|
65
|
+
@apply border-border;
|
|
66
|
+
}
|
|
67
|
+
body {
|
|
68
|
+
@apply bg-background text-foreground;
|
|
69
|
+
}
|
|
23
70
|
}
|
|
24
71
|
```
|
|
25
72
|
|
|
26
|
-
|
|
73
|
+
> **Why?** CSS follows "last one wins". The default `index.css` in a Vite/shadcn project contains hardcoded CSS variable values that override the theme package's variables. Removing them lets the theme apply correctly.
|
|
27
74
|
|
|
28
|
-
|
|
75
|
+
---
|
|
29
76
|
|
|
30
|
-
|
|
77
|
+
## Available Themes
|
|
78
|
+
|
|
79
|
+
| Package | Description |
|
|
80
|
+
|---|---|
|
|
81
|
+
| `@qdesignsystems/theme-myra` | MYRA theme — blue primary, warm background |
|
|
82
|
+
| `@qdesignsystems/theme-q` | Q theme — black primary, clean minimal |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Import Order
|
|
87
|
+
|
|
88
|
+
The import order in `main.tsx` matters:
|
|
31
89
|
|
|
32
90
|
```tsx
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<Button variant="default">Default</Button>
|
|
36
|
-
<Button variant="destructive">Destructive</Button>
|
|
37
|
-
<Button variant="outline">Outline</Button>
|
|
38
|
-
<Button variant="secondary">Secondary</Button>
|
|
39
|
-
<Button variant="ghost">Ghost</Button>
|
|
40
|
-
<Button variant="link">Link</Button>
|
|
41
|
-
```
|
|
91
|
+
// 1. Core styles (defines base variables)
|
|
92
|
+
import '@qdesignsystems/design-system-core/styles.css';
|
|
42
93
|
|
|
43
|
-
|
|
94
|
+
// 2. Theme styles (overrides base variables with theme values)
|
|
95
|
+
import '@qdesignsystems/theme-myra/styles.css';
|
|
44
96
|
|
|
45
|
-
|
|
97
|
+
// 3. Your app styles (should NOT contain :root variable blocks)
|
|
98
|
+
import './index.css';
|
|
99
|
+
```
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qdesignsystems/design-system-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org"
|
|
7
7
|
},
|
|
8
8
|
"description": "Core component library built on shadcn/ui",
|
|
9
|
+
"bin": {
|
|
10
|
+
"qds-init": "./scripts/init.cjs"
|
|
11
|
+
},
|
|
9
12
|
"main": "./dist/index.js",
|
|
10
13
|
"module": "./dist/index.mjs",
|
|
11
14
|
"types": "./dist/index.d.ts",
|
|
@@ -16,13 +19,16 @@
|
|
|
16
19
|
"types": "./dist/index.d.ts"
|
|
17
20
|
},
|
|
18
21
|
"./styles": "./dist/styles.css",
|
|
22
|
+
"./styles.css": "./dist/styles.css",
|
|
23
|
+
"./dist/styles.css": "./dist/styles.css",
|
|
19
24
|
"./package.json": "./package.json"
|
|
20
25
|
},
|
|
21
26
|
"sideEffects": [
|
|
22
27
|
"**/*.css"
|
|
23
28
|
],
|
|
24
29
|
"files": [
|
|
25
|
-
"dist"
|
|
30
|
+
"dist",
|
|
31
|
+
"scripts/init.cjs"
|
|
26
32
|
],
|
|
27
33
|
"scripts": {
|
|
28
34
|
"build": "tsup && node scripts/strip-css-sourcemap.cjs",
|
package/scripts/init.cjs
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const RESET = '\x1b[0m';
|
|
8
|
+
const GREEN = '\x1b[32m';
|
|
9
|
+
const YELLOW = '\x1b[33m';
|
|
10
|
+
const CYAN = '\x1b[36m';
|
|
11
|
+
const RED = '\x1b[31m';
|
|
12
|
+
const BOLD = '\x1b[1m';
|
|
13
|
+
|
|
14
|
+
function log(color, symbol, msg) {
|
|
15
|
+
console.log(`${color}${symbol}${RESET} ${msg}`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// ─── Resolve project root (where package.json lives) ─────────────────────────
|
|
19
|
+
// When run via npx inside a project, cwd is the project root.
|
|
20
|
+
const projectRoot = process.cwd();
|
|
21
|
+
|
|
22
|
+
// ─── Detect theme from argv ───────────────────────────────────────────────────
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
const themeArg = args.find(a => a.startsWith('--theme='));
|
|
25
|
+
const theme = themeArg ? themeArg.replace('--theme=', '').toLowerCase() : null;
|
|
26
|
+
|
|
27
|
+
const SUPPORTED_THEMES = ['myra', 'q'];
|
|
28
|
+
|
|
29
|
+
console.log('');
|
|
30
|
+
console.log(`${BOLD}${CYAN}Q Design System — Init${RESET}`);
|
|
31
|
+
console.log('─'.repeat(40));
|
|
32
|
+
|
|
33
|
+
if (theme && !SUPPORTED_THEMES.includes(theme)) {
|
|
34
|
+
log(RED, '✖', `Unknown theme "${theme}". Supported themes: ${SUPPORTED_THEMES.join(', ')}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ─── 1. Patch index.css ───────────────────────────────────────────────────────
|
|
39
|
+
const CSS_CANDIDATES = [
|
|
40
|
+
'src/index.css',
|
|
41
|
+
'src/App.css',
|
|
42
|
+
'src/globals.css',
|
|
43
|
+
'src/global.css',
|
|
44
|
+
'src/styles/index.css',
|
|
45
|
+
'src/styles/globals.css',
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const CLEAN_CSS = `@tailwind base;
|
|
49
|
+
@tailwind components;
|
|
50
|
+
@tailwind utilities;
|
|
51
|
+
|
|
52
|
+
@layer base {
|
|
53
|
+
* {
|
|
54
|
+
@apply border-border;
|
|
55
|
+
}
|
|
56
|
+
body {
|
|
57
|
+
@apply bg-background text-foreground;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
// Regex that matches a :root { ... } or .dark { ... } block containing CSS vars
|
|
63
|
+
const CSS_VAR_BLOCK_RE = /(?::root|\.dark)\s*\{[^}]*--[a-zA-Z][^}]*\}/gs;
|
|
64
|
+
|
|
65
|
+
let cssPatched = false;
|
|
66
|
+
for (const candidate of CSS_CANDIDATES) {
|
|
67
|
+
const cssPath = path.join(projectRoot, candidate);
|
|
68
|
+
if (fs.existsSync(cssPath)) {
|
|
69
|
+
const original = fs.readFileSync(cssPath, 'utf8');
|
|
70
|
+
if (CSS_VAR_BLOCK_RE.test(original)) {
|
|
71
|
+
// Remove :root and .dark CSS variable blocks, keep the rest
|
|
72
|
+
const patched = original.replace(CSS_VAR_BLOCK_RE, '').replace(/\n{3,}/g, '\n\n').trim();
|
|
73
|
+
// Ensure Tailwind directives are present
|
|
74
|
+
const hasTailwind = patched.includes('@tailwind base');
|
|
75
|
+
const final = hasTailwind ? patched + '\n' : CLEAN_CSS;
|
|
76
|
+
fs.writeFileSync(cssPath, final, 'utf8');
|
|
77
|
+
log(GREEN, '✔', `Removed CSS variable overrides from ${candidate}`);
|
|
78
|
+
cssPatched = true;
|
|
79
|
+
} else {
|
|
80
|
+
log(GREEN, '✔', `${candidate} looks clean — no CSS variable overrides found`);
|
|
81
|
+
cssPatched = true;
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!cssPatched) {
|
|
88
|
+
log(YELLOW, '⚠', 'Could not find index.css — please manually remove :root { } and .dark { } variable blocks');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── 2. Patch main entry file ─────────────────────────────────────────────────
|
|
92
|
+
const ENTRY_CANDIDATES = [
|
|
93
|
+
'src/main.tsx',
|
|
94
|
+
'src/main.ts',
|
|
95
|
+
'src/index.tsx',
|
|
96
|
+
'src/index.ts',
|
|
97
|
+
'src/main.jsx',
|
|
98
|
+
'src/index.jsx',
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
const CORE_IMPORT = `import '@qdesignsystems/design-system-core/styles.css';`;
|
|
102
|
+
const THEME_IMPORT = theme ? `import '@qdesignsystems/theme-${theme}/styles.css';` : null;
|
|
103
|
+
|
|
104
|
+
let entryPatched = false;
|
|
105
|
+
for (const candidate of ENTRY_CANDIDATES) {
|
|
106
|
+
const entryPath = path.join(projectRoot, candidate);
|
|
107
|
+
if (fs.existsSync(entryPath)) {
|
|
108
|
+
let content = fs.readFileSync(entryPath, 'utf8');
|
|
109
|
+
let changed = false;
|
|
110
|
+
|
|
111
|
+
if (!content.includes(CORE_IMPORT)) {
|
|
112
|
+
content = CORE_IMPORT + '\n' + content;
|
|
113
|
+
changed = true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (THEME_IMPORT && !content.includes(THEME_IMPORT)) {
|
|
117
|
+
// Insert theme import right after core import
|
|
118
|
+
content = content.replace(CORE_IMPORT, CORE_IMPORT + '\n' + THEME_IMPORT);
|
|
119
|
+
changed = true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (changed) {
|
|
123
|
+
fs.writeFileSync(entryPath, content, 'utf8');
|
|
124
|
+
log(GREEN, '✔', `Added theme imports to ${candidate}`);
|
|
125
|
+
} else {
|
|
126
|
+
log(GREEN, '✔', `${candidate} already has the correct imports`);
|
|
127
|
+
}
|
|
128
|
+
entryPatched = true;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!entryPatched) {
|
|
134
|
+
log(YELLOW, '⚠', 'Could not find main entry file — please add imports manually (see below)');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ─── 3. Summary ───────────────────────────────────────────────────────────────
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log(`${BOLD}Setup complete!${RESET}`);
|
|
140
|
+
console.log('');
|
|
141
|
+
|
|
142
|
+
if (!theme) {
|
|
143
|
+
console.log(`${YELLOW}No theme specified. To apply a theme, run:${RESET}`);
|
|
144
|
+
console.log(` npx @qdesignsystems/design-system-core init --theme=myra`);
|
|
145
|
+
console.log(` npx @qdesignsystems/design-system-core init --theme=q`);
|
|
146
|
+
console.log('');
|
|
147
|
+
console.log('Then install the theme package:');
|
|
148
|
+
console.log(' npm install @qdesignsystems/theme-myra@latest');
|
|
149
|
+
console.log(' npm install @qdesignsystems/theme-q@latest');
|
|
150
|
+
} else {
|
|
151
|
+
console.log(`${GREEN}Theme applied: ${theme.toUpperCase()}${RESET}`);
|
|
152
|
+
console.log('');
|
|
153
|
+
console.log('Make sure the theme package is installed:');
|
|
154
|
+
console.log(` npm install @qdesignsystems/theme-${theme}@latest`);
|
|
155
|
+
}
|
|
156
|
+
console.log('');
|