shru-design-system 0.0.8 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,231 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Build script to pre-generate all Tailwind utilities needed by components
5
- * This ensures users don't need to configure Tailwind - they just import the CSS
6
- */
7
-
8
- import { readFileSync, writeFileSync, readdirSync, statSync } from 'fs'
9
- import { join, dirname } from 'path'
10
- import { fileURLToPath } from 'url'
11
-
12
- const __filename = fileURLToPath(import.meta.url)
13
- const __dirname = dirname(__filename)
14
- const rootDir = join(__dirname, '..')
15
- const componentsDir = join(rootDir, 'apps/design-system/src/design-system/components')
16
- const stylesDir = join(rootDir, 'apps/design-system/styles')
17
- const outputFile = join(stylesDir, 'globals.css')
18
-
19
- // Extract all Tailwind classes from a string
20
- function extractTailwindClasses(content) {
21
- const classRegex = /className=["']([^"']+)["']/g
22
- const cnRegex = /cn\(["']([^"']+)["']/g
23
- const classes = new Set()
24
-
25
- // Match className="..."
26
- let match
27
- while ((match = classRegex.exec(content)) !== null) {
28
- match[1].split(/\s+/).forEach(cls => {
29
- if (cls && !cls.startsWith('{') && !cls.includes('${')) {
30
- classes.add(cls)
31
- }
32
- })
33
- }
34
-
35
- // Match cn("...")
36
- while ((match = cnRegex.exec(content)) !== null) {
37
- match[1].split(/\s+/).forEach(cls => {
38
- if (cls) classes.add(cls)
39
- })
40
- }
41
-
42
- return Array.from(classes)
43
- }
44
-
45
- // Recursively find all component files
46
- function findComponentFiles(dir, fileList = []) {
47
- const files = readdirSync(dir)
48
-
49
- files.forEach(file => {
50
- const filePath = join(dir, file)
51
- const stat = statSync(filePath)
52
-
53
- if (stat.isDirectory()) {
54
- findComponentFiles(filePath, fileList)
55
- } else if (file.endsWith('.tsx') || file.endsWith('.ts')) {
56
- fileList.push(filePath)
57
- }
58
- })
59
-
60
- return fileList
61
- }
62
-
63
- // Collect all classes from components
64
- const componentFiles = findComponentFiles(componentsDir)
65
- const allClasses = new Set()
66
-
67
- console.log(`Scanning ${componentFiles.length} component files...`)
68
-
69
- componentFiles.forEach(file => {
70
- try {
71
- const content = readFileSync(file, 'utf-8')
72
- const classes = extractTailwindClasses(content)
73
- classes.forEach(cls => allClasses.add(cls))
74
- } catch (err) {
75
- console.warn(`Warning: Could not read ${file}:`, err.message)
76
- }
77
- })
78
-
79
- // Also add common utilities that are always needed
80
- const commonUtilities = [
81
- // Layout
82
- 'flex', 'inline-flex', 'grid', 'block', 'inline-block', 'hidden',
83
- 'items-center', 'items-start', 'items-end', 'justify-center', 'justify-between', 'justify-start', 'justify-end',
84
- 'flex-col', 'flex-row', 'flex-wrap', 'flex-nowrap',
85
- 'gap-1', 'gap-2', 'gap-3', 'gap-4', 'gap-6', 'gap-8',
86
-
87
- // Spacing
88
- 'p-0', 'p-1', 'p-2', 'p-3', 'p-4', 'p-6', 'p-8',
89
- 'px-1', 'px-2', 'px-3', 'px-4', 'px-6', 'px-8',
90
- 'py-1', 'py-2', 'py-3', 'py-4', 'py-6', 'py-8',
91
- 'm-0', 'm-1', 'm-2', 'm-4', 'm-6', 'm-8',
92
- 'mx-auto', 'my-auto',
93
- 'mb-1', 'mb-2', 'mb-4', 'mb-6', 'mb-8',
94
- 'mt-1', 'mt-2', 'mt-4', 'mt-6', 'mt-8',
95
- 'mr-1', 'mr-2', 'mr-4',
96
- 'ml-1', 'ml-2', 'ml-4',
97
-
98
- // Sizing
99
- 'w-full', 'w-auto', 'w-fit', 'w-1/2', 'w-1/3', 'w-2/3', 'w-1/4', 'w-3/4',
100
- 'h-full', 'h-auto', 'h-fit', 'h-screen', 'min-h-screen',
101
- 'h-4', 'h-5', 'h-6', 'h-8', 'h-9', 'h-10', 'h-12', 'h-14', 'h-16',
102
- 'w-4', 'w-5', 'w-6', 'w-8', 'w-10', 'w-12', 'w-14', 'w-16',
103
- 'min-w-0', 'max-w-full', 'max-w-screen-xl', 'max-w-screen-2xl',
104
-
105
- // Border radius
106
- 'rounded-none', 'rounded-sm', 'rounded', 'rounded-md', 'rounded-lg', 'rounded-xl', 'rounded-2xl', 'rounded-full',
107
-
108
- // Colors (common variants)
109
- 'bg-transparent', 'bg-current',
110
- 'text-transparent', 'text-current',
111
- 'border-transparent', 'border-current',
112
-
113
- // Typography
114
- 'text-xs', 'text-sm', 'text-base', 'text-lg', 'text-xl', 'text-2xl', 'text-3xl', 'text-4xl',
115
- 'font-thin', 'font-light', 'font-normal', 'font-medium', 'font-semibold', 'font-bold', 'font-extrabold',
116
- 'leading-none', 'leading-tight', 'leading-normal', 'leading-relaxed', 'leading-loose',
117
- 'text-left', 'text-center', 'text-right', 'text-justify',
118
- 'uppercase', 'lowercase', 'capitalize', 'normal-case',
119
- 'whitespace-normal', 'whitespace-nowrap', 'whitespace-pre',
120
-
121
- // Effects
122
- 'shadow-sm', 'shadow', 'shadow-md', 'shadow-lg', 'shadow-xl', 'shadow-2xl', 'shadow-none',
123
- 'opacity-0', 'opacity-25', 'opacity-50', 'opacity-75', 'opacity-100',
124
-
125
- // Transitions
126
- 'transition', 'transition-all', 'transition-colors', 'transition-opacity', 'transition-transform',
127
- 'duration-75', 'duration-100', 'duration-150', 'duration-200', 'duration-300', 'duration-500',
128
- 'ease-in', 'ease-out', 'ease-in-out',
129
-
130
- // Transforms
131
- 'scale-95', 'scale-100', 'scale-105', 'scale-110',
132
- 'rotate-0', 'rotate-90', 'rotate-180',
133
-
134
- // Position
135
- 'relative', 'absolute', 'fixed', 'sticky', 'static',
136
- 'inset-0', 'top-0', 'right-0', 'bottom-0', 'left-0',
137
- 'z-0', 'z-10', 'z-20', 'z-30', 'z-40', 'z-50',
138
-
139
- // Overflow
140
- 'overflow-hidden', 'overflow-auto', 'overflow-scroll', 'overflow-visible',
141
- 'overflow-x-hidden', 'overflow-y-hidden',
142
-
143
- // Display
144
- 'sr-only', 'not-sr-only',
145
-
146
- // Interactive
147
- 'cursor-pointer', 'cursor-not-allowed', 'cursor-default',
148
- 'select-none', 'select-text', 'select-all',
149
- 'pointer-events-none', 'pointer-events-auto',
150
-
151
- // States
152
- 'hover:opacity-80', 'hover:opacity-90', 'hover:scale-105', 'hover:scale-110',
153
- 'active:scale-95', 'active:opacity-80',
154
- 'focus:outline-none', 'focus:ring-2', 'focus:ring-offset-2',
155
- 'disabled:opacity-50', 'disabled:cursor-not-allowed', 'disabled:pointer-events-none',
156
-
157
- // Responsive (common breakpoints)
158
- 'sm:block', 'sm:hidden', 'md:block', 'md:hidden', 'lg:block', 'lg:hidden',
159
- 'sm:flex', 'md:flex', 'lg:flex',
160
- ]
161
-
162
- commonUtilities.forEach(cls => allClasses.add(cls))
163
-
164
- console.log(`Found ${allClasses.size} unique Tailwind classes`)
165
-
166
- // Read the current globals.css
167
- let globalsContent = readFileSync(outputFile, 'utf-8')
168
-
169
- // Remove the old @layer utilities section if it exists
170
- const utilitiesStart = globalsContent.indexOf('@layer utilities {')
171
- const utilitiesEnd = globalsContent.indexOf('}\n\n@layer components', utilitiesStart)
172
- if (utilitiesStart !== -1 && utilitiesEnd !== -1) {
173
- globalsContent = globalsContent.slice(0, utilitiesStart) + globalsContent.slice(utilitiesEnd + 2)
174
- }
175
-
176
- // Generate safelist comment
177
- const safelistComment = `/*
178
- * Pre-generated utility classes for design system components
179
- * These utilities are explicitly defined to ensure they work in consuming apps
180
- * without requiring Tailwind configuration or scanning
181
- *
182
- * Generated from ${componentFiles.length} component files
183
- * Total classes: ${allClasses.size}
184
- */\n\n`
185
-
186
- // Generate utility classes
187
- const utilityClasses = Array.from(allClasses)
188
- .sort()
189
- .map(cls => {
190
- // Skip complex classes with variables for now - handle common ones
191
- if (cls.includes('${') || cls.includes('{')) return null
192
-
193
- // Generate CSS for common patterns
194
- if (cls.startsWith('rounded-')) {
195
- if (cls === 'rounded-full') return `.${cls} { border-radius: 9999px !important; }`
196
- if (cls === 'rounded-none') return `.${cls} { border-radius: 0 !important; }`
197
- if (cls === 'rounded') return `.${cls} { border-radius: var(--radius) !important; }`
198
- if (cls === 'rounded-sm') return `.${cls} { border-radius: var(--radius-sm) !important; }`
199
- if (cls === 'rounded-md') return `.${cls} { border-radius: var(--radius-md) !important; }`
200
- if (cls === 'rounded-lg') return `.${cls} { border-radius: var(--radius-lg) !important; }`
201
- if (cls === 'rounded-xl') return `.${cls} { border-radius: var(--radius-xl) !important; }`
202
- if (cls === 'rounded-2xl') return `.${cls} { border-radius: calc(var(--radius) + 8px) !important; }`
203
- }
204
-
205
- // For other classes, we'll let Tailwind generate them
206
- // But we need to ensure they're in the safelist
207
- return null
208
- })
209
- .filter(Boolean)
210
- .join('\n')
211
-
212
- // Insert the safelist and utilities before @layer components
213
- const componentsMarker = globalsContent.indexOf('@layer components')
214
- if (componentsMarker !== -1) {
215
- const beforeComponents = globalsContent.slice(0, componentsMarker)
216
- const afterComponents = globalsContent.slice(componentsMarker)
217
-
218
- globalsContent = beforeComponents +
219
- safelistComment +
220
- `@layer utilities {\n${utilityClasses}\n}\n\n` +
221
- afterComponents
222
- } else {
223
- // Append if no components layer found
224
- globalsContent += '\n\n' + safelistComment + `@layer utilities {\n${utilityClasses}\n}\n`
225
- }
226
-
227
- writeFileSync(outputFile, globalsContent, 'utf-8')
228
- console.log(`✅ Updated ${outputFile}`)
229
- console.log(` Added ${utilityClasses.split('\n').filter(l => l.trim()).length} explicit utility overrides`)
230
- console.log(` Total classes scanned: ${allClasses.size}`)
231
-
@@ -1,106 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Copy Globals CSS Script
5
- * Copies globals.css from the package to the user's project
6
- */
7
-
8
- const fs = require('fs')
9
- const path = require('path')
10
-
11
- // Try to find globals.css in multiple locations
12
- let sourceFile
13
- const nodeModulesPath = path.join(process.cwd(), 'node_modules/@shru/theme-toggle')
14
-
15
- // Try different possible locations
16
- const possibleSources = [
17
- path.join(nodeModulesPath, 'apps/design-system/styles/globals.css'), // GitHub install
18
- path.join(nodeModulesPath, 'globals.css'), // If included in package files
19
- path.join(__dirname, '../apps/design-system/styles/globals.css'), // Development/repo root
20
- ]
21
-
22
- for (const possibleSource of possibleSources) {
23
- if (fs.existsSync(possibleSource)) {
24
- sourceFile = possibleSource
25
- break
26
- }
27
- }
28
-
29
- // Default target locations to try (in order of preference)
30
- const possibleTargets = [
31
- path.join(process.cwd(), 'app/globals.css'),
32
- path.join(process.cwd(), 'src/app/globals.css'),
33
- path.join(process.cwd(), 'styles/globals.css'),
34
- path.join(process.cwd(), 'src/styles/globals.css'),
35
- ]
36
-
37
- function findExistingGlobals() {
38
- for (const target of possibleTargets) {
39
- if (fs.existsSync(target)) {
40
- return target
41
- }
42
- }
43
- return null
44
- }
45
-
46
- function findBestTarget() {
47
- // Check if any globals.css already exists
48
- const existing = findExistingGlobals()
49
- if (existing) {
50
- return existing
51
- }
52
-
53
- // Use the first possible target that has a parent directory
54
- for (const target of possibleTargets) {
55
- const parentDir = path.dirname(target)
56
- if (fs.existsSync(parentDir)) {
57
- return target
58
- }
59
- }
60
-
61
- // Default to app/globals.css
62
- return possibleTargets[0]
63
- }
64
-
65
- try {
66
- if (!sourceFile || !fs.existsSync(sourceFile)) {
67
- console.error('Source file not found. Tried:')
68
- const possibleSources = [
69
- path.join(nodeModulesPath, 'apps/design-system/styles/globals.css'),
70
- path.join(nodeModulesPath, 'globals.css'),
71
- path.join(__dirname, '../apps/design-system/styles/globals.css'),
72
- ]
73
- possibleSources.forEach(src => console.error(` - ${src}`))
74
- console.error('\nMake sure you are running this from a project that has @shru/theme-toggle installed')
75
- console.error('Or run this from the repository root if developing')
76
- process.exit(1)
77
- }
78
-
79
- const targetFile = findBestTarget()
80
- const targetDir = path.dirname(targetFile)
81
-
82
- // Create target directory if it doesn't exist
83
- if (!fs.existsSync(targetDir)) {
84
- fs.mkdirSync(targetDir, { recursive: true })
85
- }
86
-
87
- // Check if file already exists
88
- if (fs.existsSync(targetFile)) {
89
- console.warn(`⚠️ File already exists: ${targetFile}`)
90
- console.warn('Skipping copy. If you want to overwrite, delete the file first.')
91
- console.log(`\nCurrent globals.css location: ${targetFile}`)
92
- process.exit(0)
93
- }
94
-
95
- console.log(`Copying globals.css from ${sourceFile} to ${targetFile}...`)
96
- fs.copyFileSync(sourceFile, targetFile)
97
- console.log('✅ globals.css copied successfully!')
98
- console.log(`\nFile location: ${targetFile}`)
99
- console.log('\nNext steps:')
100
- console.log(` 1. Import it in your root layout: import './globals.css'`)
101
- console.log(' 2. Make sure Tailwind v4 is installed: npm install tailwindcss@next @tailwindcss/postcss@next')
102
- console.log(' 3. Configure PostCSS with @tailwindcss/postcss plugin')
103
- } catch (error) {
104
- console.error('Error copying globals.css:', error)
105
- process.exit(1)
106
- }
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Copy Tokens Script
5
- * Copies token files from the package to the user's public folder
6
- */
7
-
8
- const fs = require('fs')
9
- const path = require('path')
10
-
11
- const sourceDir = path.join(__dirname, '../src/tokens')
12
- const targetDir = path.join(process.cwd(), 'public/tokens')
13
-
14
- function copyRecursive(src, dest) {
15
- const exists = fs.existsSync(src)
16
- const stats = exists && fs.statSync(src)
17
- const isDirectory = exists && stats.isDirectory()
18
-
19
- if (isDirectory) {
20
- if (!fs.existsSync(dest)) {
21
- fs.mkdirSync(dest, { recursive: true })
22
- }
23
- fs.readdirSync(src).forEach(childItemName => {
24
- copyRecursive(
25
- path.join(src, childItemName),
26
- path.join(dest, childItemName)
27
- )
28
- })
29
- } else {
30
- // Ensure parent directory exists
31
- const parentDir = path.dirname(dest)
32
- if (!fs.existsSync(parentDir)) {
33
- fs.mkdirSync(parentDir, { recursive: true })
34
- }
35
- fs.copyFileSync(src, dest)
36
- }
37
- }
38
-
39
- try {
40
- if (!fs.existsSync(sourceDir)) {
41
- console.error(`Source directory not found: ${sourceDir}`)
42
- console.error('Make sure you are running this from a project that has @shru/theme-toggle installed')
43
- process.exit(1)
44
- }
45
-
46
- // Create target directory if it doesn't exist
47
- if (!fs.existsSync(path.join(process.cwd(), 'public'))) {
48
- fs.mkdirSync(path.join(process.cwd(), 'public'), { recursive: true })
49
- }
50
-
51
- console.log(`Copying tokens from ${sourceDir} to ${targetDir}...`)
52
- copyRecursive(sourceDir, targetDir)
53
- console.log('✅ Tokens copied successfully!')
54
- console.log(`\nTokens are now available at: ${targetDir}`)
55
- console.log('\nYou can now add custom token files to extend themes:')
56
- console.log(' - Add new theme files to public/tokens/themes/{category}/{name}.json')
57
- console.log(' - Use registerTheme() or they will be auto-discovered on next load')
58
- } catch (error) {
59
- console.error('Error copying tokens:', error)
60
- process.exit(1)
61
- }
62
-
@@ -1,161 +0,0 @@
1
- {
2
- "color": {
3
- "primary": "{palette.blue.500}",
4
- "primary-hover": "{palette.blue.600}",
5
- "primary-foreground": "{palette.white}",
6
- "secondary": "{palette.gray.100}",
7
- "secondary-foreground": "{palette.gray.900}",
8
- "background": "{palette.white}",
9
- "foreground": "{palette.gray.900}",
10
- "card": "{palette.white}",
11
- "card-foreground": "{palette.gray.900}",
12
- "popover": "{palette.white}",
13
- "popover-foreground": "{palette.gray.900}",
14
- "muted": "{palette.gray.100}",
15
- "muted-foreground": "{palette.gray.500}",
16
- "accent": "{palette.gray.100}",
17
- "accent-foreground": "{palette.gray.900}",
18
- "destructive": "{palette.red.500}",
19
- "destructive-foreground": "{palette.white}",
20
- "border": "{palette.gray.200}",
21
- "input": "{palette.gray.200}",
22
- "ring": "{palette.gray.400}",
23
- "chart-1": "{palette.blue.300}",
24
- "chart-2": "{palette.blue.500}",
25
- "chart-3": "{palette.blue.600}",
26
- "chart-4": "{palette.blue.700}",
27
- "chart-5": "{palette.blue.800}",
28
- "sidebar": "{palette.white}",
29
- "sidebar-foreground": "{palette.gray.900}",
30
- "sidebar-primary": "{palette.blue.600}",
31
- "sidebar-primary-foreground": "{palette.white}",
32
- "sidebar-accent": "{palette.gray.100}",
33
- "sidebar-accent-foreground": "{palette.gray.900}",
34
- "sidebar-border": "{palette.gray.200}",
35
- "sidebar-ring": "{palette.gray.400}",
36
- "surface": "{palette.gray.50}",
37
- "surface-foreground": "{palette.gray.900}",
38
- "code": "{palette.gray.50}",
39
- "code-foreground": "{palette.gray.900}",
40
- "code-highlight": "{palette.gray.100}",
41
- "code-number": "{palette.gray.500}",
42
- "selection": "{palette.gray.900}",
43
- "selection-foreground": "{palette.white}",
44
- "skeleton": "{palette.gray.200}"
45
- },
46
- "spacing": {
47
- "component": {
48
- "xs": "0.25rem",
49
- "sm": "0.5rem",
50
- "md": "1rem",
51
- "lg": "1.5rem",
52
- "xl": "2rem"
53
- },
54
- "layout": {
55
- "sm": "1rem",
56
- "md": "2rem",
57
- "lg": "3rem",
58
- "xl": "4rem",
59
- "2xl": "6rem"
60
- },
61
- "section": {
62
- "sm": "2rem",
63
- "md": "4rem",
64
- "lg": "6rem",
65
- "xl": "8rem"
66
- },
67
- "base": "0.25rem"
68
- },
69
- "typography": {
70
- "font": {
71
- "sans": "var(--font-sans)",
72
- "mono": "var(--font-mono)"
73
- },
74
- "fontSize": {
75
- "xs": "0.75rem",
76
- "sm": "0.875rem",
77
- "base": "1rem",
78
- "lg": "1.125rem",
79
- "xl": "1.25rem",
80
- "2xl": "1.5rem",
81
- "3xl": "1.875rem",
82
- "4xl": "2.25rem",
83
- "5xl": "3rem",
84
- "6xl": "3.75rem",
85
- "7xl": "4.5rem",
86
- "8xl": "6rem"
87
- },
88
- "fontWeight": {
89
- "normal": "400",
90
- "medium": "500",
91
- "semibold": "600",
92
- "bold": "700"
93
- },
94
- "lineHeight": {
95
- "tight": "1.25",
96
- "normal": "1.5",
97
- "relaxed": "1.75"
98
- }
99
- },
100
- "shape": {
101
- "radius": {
102
- "none": "0",
103
- "sm": "0.25rem",
104
- "md": "0.5rem",
105
- "lg": "0.625rem",
106
- "xl": "0.75rem",
107
- "2xl": "1rem",
108
- "full": "9999px"
109
- },
110
- "radiusComponent": {
111
- "button": "{shape.radius.md}",
112
- "card": "{shape.radius.lg}",
113
- "input": "{shape.radius.md}",
114
- "modal": "{shape.radius.xl}",
115
- "tooltip": "{shape.radius.md}",
116
- "badge": "{shape.radius.full}"
117
- }
118
- },
119
- "motion": {
120
- "duration": {
121
- "fast": "150ms",
122
- "normal": "200ms",
123
- "slow": "300ms"
124
- },
125
- "easing": {
126
- "ease": "cubic-bezier(0.4, 0, 0.2, 1)",
127
- "ease-in": "cubic-bezier(0.4, 0, 1, 1)",
128
- "ease-out": "cubic-bezier(0, 0, 0.2, 1)",
129
- "ease-in-out": "cubic-bezier(0.4, 0, 0.2, 1)"
130
- }
131
- },
132
- "shadow": {
133
- "xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
134
- "sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
135
- "md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
136
- "lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
137
- "xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
138
- "2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
139
- "none": "none"
140
- },
141
- "zIndex": {
142
- "base": "0",
143
- "dropdown": "1000",
144
- "sticky": "1020",
145
- "fixed": "1030",
146
- "modal-backdrop": "1040",
147
- "modal": "1050",
148
- "popover": "1060",
149
- "tooltip": "1070"
150
- },
151
- "breakpoint": {
152
- "sm": "640px",
153
- "md": "768px",
154
- "lg": "1024px",
155
- "xl": "1280px",
156
- "2xl": "1536px",
157
- "3xl": "1600px",
158
- "4xl": "2000px"
159
- }
160
- }
161
-