@payfit/unity-themes 2.24.1 → 2.25.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.
- package/dist/css/unity.css +1653 -543
- package/dist/esm/components/unity-theme-provider.d.ts +25 -0
- package/dist/esm/components/unity-theme-provider.js +34 -0
- package/dist/esm/components/unity-theme-provider.test.d.ts +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +8 -5
- package/dist/esm/scripts/actions/compose-multi-theme.d.ts +15 -0
- package/dist/esm/scripts/transforms/tailwind-color-token.d.ts +4 -3
- package/dist/esm/scripts/transforms/tailwind-grid-token.d.ts +2 -1
- package/dist/esm/scripts/transforms/tailwind-spacing-token.d.ts +1 -1
- package/dist/esm/scripts/transforms/tailwind-text-token.d.ts +1 -1
- package/dist/esm/scripts/transforms/tailwind-typography-token.d.ts +1 -4
- package/dist/esm/scripts/utils/prefix-transform.d.ts +4 -0
- package/dist/esm/utils/cn.d.ts +4 -3
- package/package.json +3 -2
- package/src/components/unity-theme-provider.stories.tsx +532 -0
- package/src/components/unity-theme-provider.test.tsx +150 -0
- package/src/components/unity-theme-provider.tsx +72 -0
- package/src/index.ts +8 -0
- package/src/scripts/actions/compose-multi-theme.ts +59 -0
- package/src/scripts/build.ts +261 -55
- package/src/scripts/formats/unity-theme.test.ts +180 -253
- package/src/scripts/formats/unity-theme.ts +27 -64
- package/src/scripts/transforms/tailwind-color-token.test.ts +18 -0
- package/src/scripts/transforms/tailwind-color-token.ts +7 -3
- package/src/scripts/transforms/tailwind-grid-token.test.ts +22 -0
- package/src/scripts/transforms/tailwind-grid-token.ts +7 -3
- package/src/scripts/transforms/tailwind-spacing-token.test.ts +9 -0
- package/src/scripts/transforms/tailwind-spacing-token.ts +15 -2
- package/src/scripts/transforms/tailwind-text-token.test.ts +18 -0
- package/src/scripts/transforms/tailwind-text-token.ts +15 -2
- package/src/scripts/transforms/tailwind-typography-token.test.ts +8 -2
- package/src/scripts/transforms/tailwind-typography-token.ts +5 -1
- package/src/scripts/utils/prefix-transform.test.ts +137 -0
- package/src/scripts/utils/prefix-transform.ts +16 -0
- package/src/utils/cn.ts +2 -2
- package/tokens/common/aspect-ratios.json +11 -0
- package/tokens/common/breakpoints.json +18 -0
- package/tokens/{text.json → common/font-sizes.json} +0 -28
- package/tokens/common/font-weights.json +18 -0
- package/tokens/{radii.json → common/radii.json} +0 -15
- package/tokens/{spacings.json → common/spacings.json} +0 -25
- package/tokens/legacy/radii.json +21 -0
- package/tokens/legacy/text.json +14 -0
- package/tokens/rebrand/colors.json +1400 -0
- package/tokens/rebrand/radii.json +21 -0
- package/tokens/rebrand/shadows.json +81 -0
- package/tokens/rebrand/text.json +14 -0
- package/tokens/rebrand/typography.json +329 -0
- package/dist/esm/scripts/formats/generators/header-generator.d.ts +0 -2
- package/src/scripts/formats/generators/header-generator.ts +0 -32
- /package/tokens/{animations.json → common/animations.json} +0 -0
- /package/tokens/{layout.json → common/layout.json} +0 -0
- /package/tokens/{sizes.json → common/sizes.json} +0 -0
- /package/tokens/{colors.json → legacy/colors.json} +0 -0
- /package/tokens/{shadows.json → legacy/shadows.json} +0 -0
- /package/tokens/{typography.json → legacy/typography.json} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createContext, useContext, useEffect, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import type { PropsWithChildren, RefObject } from 'react'
|
|
4
|
+
|
|
5
|
+
export type UnityTheme = 'legacy' | 'rebrand'
|
|
6
|
+
|
|
7
|
+
interface UnityThemeContextValue {
|
|
8
|
+
theme: UnityTheme
|
|
9
|
+
setTheme: (theme: UnityTheme) => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const UnityThemeContext = createContext<UnityThemeContextValue>({
|
|
13
|
+
// Render legacy by default for backwards compatibility
|
|
14
|
+
theme: 'legacy',
|
|
15
|
+
// Intentional noop. Will be replaced by a set dispatcher from React
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
17
|
+
setTheme: () => {},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
export interface UnityThemeProviderProps {
|
|
21
|
+
/** Initial theme. Can be changed at runtime via `useUnityTheme().setTheme`. */
|
|
22
|
+
theme?: UnityTheme
|
|
23
|
+
/**
|
|
24
|
+
* Element on which `data-uy-theme` is set.
|
|
25
|
+
* - `undefined` (default): uses `document.documentElement` (`<html>`)
|
|
26
|
+
* - A React ref: uses the referenced element
|
|
27
|
+
* - A CSS selector string: uses `document.querySelector(selector)`
|
|
28
|
+
* @default document.documentElement
|
|
29
|
+
*/
|
|
30
|
+
target?: RefObject<HTMLElement | null> | string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolveTarget(
|
|
34
|
+
target: UnityThemeProviderProps['target'],
|
|
35
|
+
): HTMLElement | null {
|
|
36
|
+
if (target === undefined) return document.documentElement
|
|
37
|
+
if (typeof target === 'string') return document.querySelector(target)
|
|
38
|
+
return target.current
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function UnityThemeProvider({
|
|
42
|
+
theme: initialTheme = 'legacy',
|
|
43
|
+
target,
|
|
44
|
+
children,
|
|
45
|
+
}: PropsWithChildren<UnityThemeProviderProps>) {
|
|
46
|
+
const [theme, setTheme] = useState<UnityTheme>(initialTheme)
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
const el = resolveTarget(target)
|
|
50
|
+
if (!el) return
|
|
51
|
+
|
|
52
|
+
el.dataset.uyTheme = theme
|
|
53
|
+
|
|
54
|
+
return () => {
|
|
55
|
+
delete el.dataset.uyTheme
|
|
56
|
+
}
|
|
57
|
+
}, [theme, target])
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<UnityThemeContext.Provider value={{ theme, setTheme }}>
|
|
61
|
+
{children}
|
|
62
|
+
</UnityThemeContext.Provider>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns the current theme and a setter to change it at runtime.
|
|
68
|
+
* Returns `"legacy"` with a no-op setter when used outside a provider.
|
|
69
|
+
*/
|
|
70
|
+
export function useUnityTheme(): UnityThemeContextValue {
|
|
71
|
+
return useContext(UnityThemeContext)
|
|
72
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,3 +5,11 @@ export * from './utils/tailwind-variants'
|
|
|
5
5
|
|
|
6
6
|
// Configuration (for advanced users)
|
|
7
7
|
export { twMergeConfig } from './utils/merge-config'
|
|
8
|
+
|
|
9
|
+
// Theme provider
|
|
10
|
+
export {
|
|
11
|
+
UnityThemeProvider,
|
|
12
|
+
useUnityTheme,
|
|
13
|
+
type UnityTheme,
|
|
14
|
+
type UnityThemeProviderProps,
|
|
15
|
+
} from './components/unity-theme-provider'
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composes the final multi-theme `unity.css` by concatenating the formatted
|
|
3
|
+
* outputs from three SD instances into a single file.
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs'
|
|
6
|
+
import path from 'path'
|
|
7
|
+
|
|
8
|
+
import prettier from 'prettier'
|
|
9
|
+
|
|
10
|
+
export interface ComposeInput {
|
|
11
|
+
/** css/variables output for legacy (:root selector) */
|
|
12
|
+
legacyCss: string
|
|
13
|
+
/** css/variables output for rebrand ([data-uy-theme="rebrand"] selector) */
|
|
14
|
+
rebrandCss: string
|
|
15
|
+
/** css/unity-theme output (@theme block + grid/typography utilities) */
|
|
16
|
+
themeCss: string
|
|
17
|
+
/** File header + imports */
|
|
18
|
+
header: string
|
|
19
|
+
/** Custom variant declarations */
|
|
20
|
+
customVariants: string
|
|
21
|
+
/** Output path for the composed CSS */
|
|
22
|
+
outputPath: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function composeMultiThemeCss(input: ComposeInput): Promise<void> {
|
|
26
|
+
const {
|
|
27
|
+
legacyCss,
|
|
28
|
+
rebrandCss,
|
|
29
|
+
themeCss,
|
|
30
|
+
header,
|
|
31
|
+
customVariants,
|
|
32
|
+
outputPath,
|
|
33
|
+
} = input
|
|
34
|
+
|
|
35
|
+
const css = `${header}
|
|
36
|
+
|
|
37
|
+
@layer base {
|
|
38
|
+
${legacyCss}
|
|
39
|
+
|
|
40
|
+
${rebrandCss}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
${themeCss}
|
|
44
|
+
|
|
45
|
+
${customVariants}
|
|
46
|
+
`
|
|
47
|
+
|
|
48
|
+
console.log(' \x1b[2m→\x1b[0m Formatting with Prettier...')
|
|
49
|
+
const formatted = await prettier.format(css, {
|
|
50
|
+
parser: 'css',
|
|
51
|
+
printWidth: 120,
|
|
52
|
+
tabWidth: 2,
|
|
53
|
+
useTabs: false,
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true })
|
|
57
|
+
fs.writeFileSync(outputPath, formatted)
|
|
58
|
+
console.log(` \x1b[2m→\x1b[0m Written to \x1b[33m${outputPath}\x1b[0m`)
|
|
59
|
+
}
|
package/src/scripts/build.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
1
4
|
import StyleDictionary from 'style-dictionary'
|
|
2
5
|
import {
|
|
3
6
|
logBrokenReferenceLevels,
|
|
4
7
|
logVerbosityLevels,
|
|
5
8
|
logWarningLevels,
|
|
6
|
-
transformGroups,
|
|
7
9
|
} from 'style-dictionary/enums'
|
|
8
10
|
|
|
9
|
-
import
|
|
11
|
+
import { appendAnimations } from './actions/append-animations.js'
|
|
12
|
+
import { composeMultiThemeCss } from './actions/compose-multi-theme.js'
|
|
10
13
|
import {
|
|
11
14
|
unityFileHeader,
|
|
12
15
|
name as unityFileHeaderName,
|
|
@@ -23,6 +26,10 @@ import * as tailwindSpacingTokenTransformer from './transforms/tailwind-spacing-
|
|
|
23
26
|
import * as tailwindTextTokenTransformer from './transforms/tailwind-text-token.js'
|
|
24
27
|
import * as tailwindTypographyTokenTransformer from './transforms/tailwind-typography-token.js'
|
|
25
28
|
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Register extensions (shared by all SD instances)
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
26
33
|
StyleDictionary.registerFormat({
|
|
27
34
|
name: unityThemeFormatName,
|
|
28
35
|
format: unityThemeFormat,
|
|
@@ -84,67 +91,266 @@ StyleDictionary.registerTransform({
|
|
|
84
91
|
transform: tailwindAnimationTokenTransformer.transform,
|
|
85
92
|
})
|
|
86
93
|
|
|
87
|
-
StyleDictionary.registerAction({
|
|
88
|
-
name: 'tailwind/v4/append_animations',
|
|
89
|
-
do: animationAssetProcessor.appendAnimations,
|
|
90
|
-
undo: animationAssetProcessor.removeAnimations,
|
|
91
|
-
})
|
|
92
|
-
|
|
93
94
|
StyleDictionary.registerFileHeader({
|
|
94
95
|
name: unityFileHeaderName,
|
|
95
96
|
fileHeader: unityFileHeader,
|
|
96
97
|
})
|
|
97
98
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Shared config
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
const sharedTransforms = [
|
|
104
|
+
'attribute/cti',
|
|
105
|
+
'name/kebab',
|
|
106
|
+
'name/tailwind/v4/text',
|
|
107
|
+
'name/tailwind/v4/typography',
|
|
108
|
+
'name/tailwind/v4/color',
|
|
109
|
+
'name/tailwind/v4/spacing',
|
|
110
|
+
'name/tailwind/v4/grid',
|
|
111
|
+
'color/oklch',
|
|
112
|
+
'fontFamily/css',
|
|
113
|
+
'typography/css/shorthand',
|
|
114
|
+
'shadow/css/shorthand',
|
|
115
|
+
'cubicBezier/css',
|
|
116
|
+
'tailwind/v4/animations/shorthand',
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
const sharedLogConfig = {
|
|
120
|
+
warnings: logWarningLevels.warn,
|
|
121
|
+
verbosity: logVerbosityLevels.verbose,
|
|
122
|
+
errors: {
|
|
123
|
+
brokenReferences: logBrokenReferenceLevels.throw,
|
|
124
|
+
},
|
|
125
|
+
} as const
|
|
126
|
+
|
|
127
|
+
const BUILD_PATH = './dist/css/'
|
|
128
|
+
const OUTPUT_FILE = 'unity.css'
|
|
129
|
+
const ANIMATIONS_PATH = './assets/animations/'
|
|
130
|
+
const PREFIX = 'uy'
|
|
131
|
+
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// Logging helpers
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
const color = {
|
|
137
|
+
cyan: (s: string) => `\x1b[36m${s}\x1b[0m`,
|
|
138
|
+
green: (s: string) => `\x1b[32m${s}\x1b[0m`,
|
|
139
|
+
yellow: (s: string) => `\x1b[33m${s}\x1b[0m`,
|
|
140
|
+
red: (s: string) => `\x1b[31m${s}\x1b[0m`,
|
|
141
|
+
dim: (s: string) => `\x1b[2m${s}\x1b[0m`,
|
|
142
|
+
bold: (s: string) => `\x1b[1m${s}\x1b[0m`,
|
|
143
|
+
} as const
|
|
144
|
+
|
|
145
|
+
function logStep(step: number, total: number, message: string) {
|
|
146
|
+
console.log(`${color.cyan(`[${step}/${total}]`)} ${color.bold(message)}`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function logDetail(message: string) {
|
|
150
|
+
console.log(` ${color.dim('→')} ${message}`)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// Build
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
|
|
157
|
+
const TOTAL_STEPS = 7
|
|
158
|
+
|
|
159
|
+
async function build() {
|
|
160
|
+
const startTime = performance.now()
|
|
161
|
+
console.log(color.bold('\n🏗 Unity Themes — Build\n'))
|
|
162
|
+
|
|
163
|
+
// 1. Legacy SD — css/variables with :root selector
|
|
164
|
+
logStep(1, TOTAL_STEPS, 'Initializing Style Dictionary instances')
|
|
165
|
+
logDetail(
|
|
166
|
+
`Legacy — tokens/common + tokens/legacy → ${color.yellow(':root')}`,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
const legacySD = new StyleDictionary({
|
|
170
|
+
source: ['./tokens/common/**/*.json', './tokens/legacy/**/*.json'],
|
|
171
|
+
platforms: {
|
|
172
|
+
css: {
|
|
173
|
+
transforms: sharedTransforms,
|
|
174
|
+
prefix: PREFIX,
|
|
175
|
+
buildPath: BUILD_PATH,
|
|
176
|
+
files: [
|
|
177
|
+
{
|
|
178
|
+
destination: '_legacy.css',
|
|
179
|
+
format: 'css/variables',
|
|
180
|
+
options: {
|
|
181
|
+
selector: ':root, [data-uy-theme="legacy"]',
|
|
182
|
+
outputReferences: true,
|
|
183
|
+
showFileHeader: false,
|
|
184
|
+
},
|
|
129
185
|
},
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
actions: ['tailwind/v4/append_animations'],
|
|
186
|
+
],
|
|
187
|
+
},
|
|
133
188
|
},
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
189
|
+
log: sharedLogConfig,
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
// 2. Rebrand SD — css/variables with [data-uy-theme="rebrand"] selector
|
|
193
|
+
logDetail(
|
|
194
|
+
`Rebrand — tokens/common + tokens/rebrand → ${color.yellow(
|
|
195
|
+
'[data-uy-theme="rebrand"]',
|
|
196
|
+
)}`,
|
|
197
|
+
)
|
|
198
|
+
const rebrandSD = new StyleDictionary({
|
|
199
|
+
source: ['./tokens/common/**/*.json', './tokens/rebrand/**/*.json'],
|
|
200
|
+
platforms: {
|
|
201
|
+
css: {
|
|
202
|
+
transforms: sharedTransforms,
|
|
203
|
+
prefix: PREFIX,
|
|
204
|
+
buildPath: BUILD_PATH,
|
|
205
|
+
files: [
|
|
206
|
+
{
|
|
207
|
+
destination: '_rebrand.css',
|
|
208
|
+
format: 'css/variables',
|
|
209
|
+
options: {
|
|
210
|
+
selector: '[data-uy-theme="rebrand"]',
|
|
211
|
+
outputReferences: true,
|
|
212
|
+
showFileHeader: false,
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
},
|
|
140
217
|
},
|
|
141
|
-
|
|
142
|
-
})
|
|
218
|
+
log: sharedLogConfig,
|
|
219
|
+
})
|
|
143
220
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
221
|
+
// 3. Theme SD — css/unity-theme format for @theme block + utilities
|
|
222
|
+
logDetail(`TW theme — → ${color.yellow('@theme')}`)
|
|
223
|
+
const themeSD = new StyleDictionary({
|
|
224
|
+
source: [
|
|
225
|
+
'./tokens/common/**/*.json',
|
|
226
|
+
'./tokens/legacy/**/*.json',
|
|
227
|
+
'./tokens/rebrand/**/*.json',
|
|
228
|
+
],
|
|
229
|
+
platforms: {
|
|
230
|
+
css: {
|
|
231
|
+
transforms: sharedTransforms,
|
|
232
|
+
prefix: PREFIX,
|
|
233
|
+
buildPath: BUILD_PATH,
|
|
234
|
+
files: [
|
|
235
|
+
{
|
|
236
|
+
destination: '_theme.css',
|
|
237
|
+
format: unityThemeFormatName,
|
|
238
|
+
options: {
|
|
239
|
+
prefix: PREFIX,
|
|
240
|
+
selector: '@theme',
|
|
241
|
+
outputReferences: true,
|
|
242
|
+
showFileHeader: false,
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
log: sharedLogConfig,
|
|
147
249
|
})
|
|
148
|
-
|
|
149
|
-
|
|
250
|
+
|
|
251
|
+
// 4. Format all three in memory
|
|
252
|
+
logStep(2, TOTAL_STEPS, 'Formatting tokens (in-memory)')
|
|
253
|
+
const formatStart = performance.now()
|
|
254
|
+
|
|
255
|
+
const [legacyOutputs, rebrandOutputs, themeOutputs] = await Promise.all([
|
|
256
|
+
legacySD.formatPlatform('css'),
|
|
257
|
+
rebrandSD.formatPlatform('css'),
|
|
258
|
+
themeSD.formatPlatform('css'),
|
|
259
|
+
])
|
|
260
|
+
|
|
261
|
+
const legacyCss = String(legacyOutputs[0]?.output ?? '')
|
|
262
|
+
const rebrandCss = String(rebrandOutputs[0]?.output ?? '')
|
|
263
|
+
const themeCss = String(themeOutputs[0]?.output ?? '')
|
|
264
|
+
|
|
265
|
+
const formatDuration = (performance.now() - formatStart).toFixed(0)
|
|
266
|
+
logDetail(
|
|
267
|
+
`Legacy CSS: ${color.green(`${legacyCss.split('\n').length} lines`)}`,
|
|
268
|
+
)
|
|
269
|
+
logDetail(
|
|
270
|
+
`Rebrand CSS: ${color.green(`${rebrandCss.split('\n').length} lines`)}`,
|
|
271
|
+
)
|
|
272
|
+
logDetail(
|
|
273
|
+
`Theme CSS: ${color.green(`${themeCss.split('\n').length} lines`)}`,
|
|
274
|
+
)
|
|
275
|
+
logDetail(color.dim(`Formatted in ${formatDuration}ms`))
|
|
276
|
+
|
|
277
|
+
// 5. Generate header + custom variants
|
|
278
|
+
logStep(3, TOTAL_STEPS, 'Generating file header and font imports')
|
|
279
|
+
const headerLines = unityFileHeader()
|
|
280
|
+
const header = [
|
|
281
|
+
'/**',
|
|
282
|
+
...headerLines.map(l => ` * ${l}`),
|
|
283
|
+
' */\n',
|
|
284
|
+
'@import "@fontsource/inter";',
|
|
285
|
+
'@import "@fontsource/inter/500.css";',
|
|
286
|
+
'@import "@fontsource/inter/600.css";',
|
|
287
|
+
'@import "@fontsource/inter/700.css";',
|
|
288
|
+
'@import "@fontsource/source-serif-4";',
|
|
289
|
+
'@import "@fontsource/source-serif-4/500.css";',
|
|
290
|
+
'@import "@fontsource/source-serif-4/600.css";',
|
|
291
|
+
'@import "@fontsource/source-serif-4/700.css";',
|
|
292
|
+
'@import "@fontsource/roboto-mono";',
|
|
293
|
+
`@import "tailwindcss" prefix(${PREFIX});`,
|
|
294
|
+
].join('\n')
|
|
295
|
+
|
|
296
|
+
logStep(4, TOTAL_STEPS, 'Registering custom variants')
|
|
297
|
+
const customVariants = [
|
|
298
|
+
'@custom-variant theme-legacy (&:where([data-uy-theme="legacy"], [data-uy-theme="legacy"] *));',
|
|
299
|
+
'@custom-variant theme-rebrand (&:where([data-uy-theme="rebrand"], [data-uy-theme="rebrand"] *));',
|
|
300
|
+
].join('\n')
|
|
301
|
+
logDetail('theme-legacy → [data-uy-theme="legacy"]')
|
|
302
|
+
logDetail('theme-rebrand → [data-uy-theme="rebrand"]')
|
|
303
|
+
|
|
304
|
+
// 6. Compose and write
|
|
305
|
+
logStep(5, TOTAL_STEPS, 'Composing multi-theme CSS')
|
|
306
|
+
const outputPath = path.join(BUILD_PATH, OUTPUT_FILE)
|
|
307
|
+
logDetail(`Output: ${color.yellow(outputPath)}`)
|
|
308
|
+
|
|
309
|
+
await composeMultiThemeCss({
|
|
310
|
+
legacyCss,
|
|
311
|
+
rebrandCss,
|
|
312
|
+
themeCss,
|
|
313
|
+
header,
|
|
314
|
+
customVariants,
|
|
315
|
+
outputPath,
|
|
150
316
|
})
|
|
317
|
+
|
|
318
|
+
// 7. Append animation keyframes + reset CSS
|
|
319
|
+
logStep(6, TOTAL_STEPS, 'Appending animation keyframes')
|
|
320
|
+
logDetail(`Source: ${color.yellow(ANIMATIONS_PATH)}`)
|
|
321
|
+
|
|
322
|
+
const legacyDict = await legacySD.getPlatformTokens('css')
|
|
323
|
+
appendAnimations(
|
|
324
|
+
legacyDict,
|
|
325
|
+
{
|
|
326
|
+
animationsPath: ANIMATIONS_PATH,
|
|
327
|
+
buildPath: BUILD_PATH,
|
|
328
|
+
files: [{ destination: OUTPUT_FILE }],
|
|
329
|
+
},
|
|
330
|
+
{}, // kept for SD compatibility
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
// Done
|
|
334
|
+
const totalDuration = (performance.now() - startTime).toFixed(0)
|
|
335
|
+
logStep(7, TOTAL_STEPS, 'Build verification')
|
|
336
|
+
const outputStat = fs.statSync(outputPath)
|
|
337
|
+
logDetail(
|
|
338
|
+
`File size: ${color.green(`${(outputStat.size / 1024).toFixed(1)} KB`)}`,
|
|
339
|
+
)
|
|
340
|
+
logDetail(`Total time: ${color.green(`${totalDuration}ms`)}`)
|
|
341
|
+
|
|
342
|
+
console.log(`\n${color.green('✅ Build completed successfully')}\n`)
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
build().catch((error: unknown) => {
|
|
346
|
+
console.error(`\n${color.red('❌ Build failed')}\n`)
|
|
347
|
+
if (error instanceof Error) {
|
|
348
|
+
console.error(color.red(`Error: ${error.message}`))
|
|
349
|
+
if (error.stack) {
|
|
350
|
+
console.error(color.dim(error.stack))
|
|
351
|
+
}
|
|
352
|
+
} else {
|
|
353
|
+
console.error(error)
|
|
354
|
+
}
|
|
355
|
+
process.exit(1)
|
|
356
|
+
})
|