@nordcraft/core 1.0.50 → 1.0.52

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.
@@ -71,49 +71,81 @@ export type OldTheme = {
71
71
  shadow: Record<string, { value: string; order: number }>
72
72
  breakpoints: Record<string, { value: number; order: number }>
73
73
  }
74
+
74
75
  export type Theme = {
76
+ default?: true
77
+ defaultDark?: true
78
+ defaultLight?: true
79
+ propertyDefinitions?: Record<CustomPropertyName, CustomPropertyDefinition>
75
80
  scheme?: 'dark' | 'light'
76
- color: StyleTokenGroup[]
81
+ color?: StyleTokenGroup[]
77
82
  fonts: FontFamily[]
78
- 'font-size': StyleTokenGroup[]
79
- 'font-weight': StyleTokenGroup[]
80
- spacing: StyleTokenGroup[]
81
- 'border-radius': StyleTokenGroup[]
82
- shadow: StyleTokenGroup[]
83
- 'z-index': StyleTokenGroup[]
84
- categories?: Record<string, CustomCategory>
85
- }
86
-
87
- export type CustomCategory = {
88
- propertyDefinitions: Record<CustomPropertyName, CustomPropertyDefinition>
83
+ 'font-size'?: StyleTokenGroup[]
84
+ 'font-weight'?: StyleTokenGroup[]
85
+ spacing?: StyleTokenGroup[]
86
+ 'border-radius'?: StyleTokenGroup[]
87
+ shadow?: StyleTokenGroup[]
88
+ 'z-index'?: StyleTokenGroup[]
89
89
  }
90
90
 
91
91
  export type CustomPropertyDefinition = {
92
92
  syntax: CssSyntaxNode
93
93
  inherits: boolean
94
- initialValue: string
94
+ initialValue: string | null // Required by CSS specs for default-theme, but we can do a fallback so null is allowed
95
+ value: string | null
95
96
  description: string
96
97
  }
97
98
 
98
- export const getThemeCss = (theme: Theme | OldTheme, options: ThemeOptions) => {
99
- if ('breakpoints' in theme) {
100
- return getOldThemeCss(theme)
101
- }
99
+ export const getThemeCss = (
100
+ theme: Record<string, OldTheme | Theme>,
101
+ options: ThemeOptions,
102
+ ) => {
103
+ const [themesV1, themesV2] = Object.entries(theme).reduce(
104
+ ([legacy, modern], [key, value]) => {
105
+ if ('breakpoints' in value) {
106
+ legacy[key] = value
107
+ } else {
108
+ modern[key] = value
109
+ }
110
+ return [legacy, modern]
111
+ },
112
+ [{}, {}] as [Record<string, OldTheme>, Record<string, Theme>],
113
+ )
102
114
 
103
- return `${Object.values(theme.categories ?? {})
104
- .map((category) =>
105
- Object.entries(category.propertyDefinitions)
106
- .map(([propertyName, property]) =>
107
- renderSyntaxDefinition(propertyName as CustomPropertyName, property),
108
- )
109
- .join('\n'),
115
+ const defaultTheme =
116
+ Object.values(themesV2).find((t) => t.default) ?? Object.values(themesV2)[0]
117
+ const defaultDarkTheme = Object.values(themesV2).find((t) => t.defaultDark)
118
+ const defaultLightTheme = Object.values(themesV2).find((t) => t.defaultLight)
119
+
120
+ return `
121
+ ${Object.values(themesV1)
122
+ .map((t) => getOldThemeCss(t))
123
+ .join('\n')}
124
+
125
+ ${Object.entries(defaultTheme.propertyDefinitions ?? {})
126
+ .map(([propertyName, property]) =>
127
+ renderSyntaxDefinition(
128
+ propertyName as CustomPropertyName,
129
+ property,
130
+ defaultTheme,
131
+ ),
110
132
  )
111
133
  .join('\n')}
134
+
135
+ ${renderTheme(':host, :root', defaultTheme)}
136
+ ${renderTheme(':host, :root', defaultDarkTheme, '@media (prefers-color-scheme: dark)')}
137
+ ${renderTheme(':host, :root', defaultLightTheme, '@media (prefers-color-scheme: light)')}
138
+ ${Object.entries(themesV2)
139
+ .map(([key, t]) => renderTheme(`[data-theme~="${key}"]`, t))
140
+ .join('\n')}
141
+
112
142
  ${options.includeResetStyle ? RESET_STYLES : ''}
113
143
  @layer base {
114
144
  ${
115
145
  options.createFontFaces
116
- ? theme.fonts
146
+ ? Object.values(themesV2)
147
+ .map(({ fonts }) => fonts)
148
+ .flat()
117
149
  .map(
118
150
  (font) => `
119
151
  ${font.variants
@@ -141,18 +173,24 @@ ${options.includeResetStyle ? RESET_STYLES : ''}
141
173
  }
142
174
  body, :host {
143
175
  /* Color */
144
- ${theme.color
176
+ ${Object.values(themesV2)
177
+ .map(({ color }) => color ?? [])
178
+ .flat()
145
179
  .flatMap((group) =>
146
180
  group.tokens.map((color) => `--${color.name}: ${color.value};`),
147
181
  )
148
182
  .join('\n')}
149
183
  /* Fonts */
150
- ${theme.fonts
184
+ ${Object.values(themesV2)
185
+ .map(({ fonts }) => fonts)
186
+ .flat()
151
187
  .map((font) => `--font-${font.name}: '${font.family}',${font.type};`)
152
188
  .join('\n')}
153
189
 
154
190
  /* Font size */
155
- ${theme['font-size']
191
+ ${Object.values(themesV2)
192
+ .map(({ 'font-size': fontSize }) => fontSize ?? [])
193
+ .flat()
156
194
  .flatMap((group) =>
157
195
  group.tokens.map(
158
196
  (variable) =>
@@ -165,7 +203,9 @@ ${options.includeResetStyle ? RESET_STYLES : ''}
165
203
  )
166
204
  .join('\n')}
167
205
  /* Font weight */
168
- ${theme['font-weight']
206
+ ${Object.values(themesV2)
207
+ .map(({ 'font-weight': fontWeight }) => fontWeight ?? [])
208
+ .flat()
169
209
  .flatMap((group) => {
170
210
  return group.tokens.map(
171
211
  (variable) =>
@@ -178,7 +218,9 @@ ${options.includeResetStyle ? RESET_STYLES : ''}
178
218
  })
179
219
  .join('\n')}
180
220
  /* Shadows */
181
- ${theme.shadow
221
+ ${Object.values(themesV2)
222
+ .map(({ shadow }) => shadow ?? [])
223
+ .flat()
182
224
  .flatMap((group) => {
183
225
  return group.tokens.map(
184
226
  (variable) =>
@@ -191,7 +233,9 @@ ${options.includeResetStyle ? RESET_STYLES : ''}
191
233
  })
192
234
  .join('\n')}
193
235
  /* Border radius */
194
- ${theme['border-radius']
236
+ ${Object.values(themesV2)
237
+ .map(({ 'border-radius': borderRadius }) => borderRadius ?? [])
238
+ .flat()
195
239
  .flatMap((group) => {
196
240
  return group.tokens.map(
197
241
  (token) =>
@@ -202,7 +246,9 @@ ${options.includeResetStyle ? RESET_STYLES : ''}
202
246
  })
203
247
  .join('\n')}
204
248
  /* Spacing */
205
- ${theme.spacing
249
+ ${Object.values(themesV2)
250
+ .map(({ spacing }) => spacing ?? [])
251
+ .flat()
206
252
  .map((group) => {
207
253
  return group.tokens
208
254
  .map(
@@ -217,7 +263,9 @@ ${options.includeResetStyle ? RESET_STYLES : ''}
217
263
  })
218
264
  .join('\n')}
219
265
  /* Z-index */
220
- ${theme['z-index']
266
+ ${Object.values(themesV2)
267
+ .map(({ 'z-index': zIndex }) => zIndex ?? [])
268
+ .flat()
221
269
  .map((group) => {
222
270
  return group.tokens
223
271
  .map(
@@ -353,3 +401,34 @@ ${RESET_STYLES}
353
401
  }
354
402
  }`
355
403
  }
404
+
405
+ export function renderTheme(
406
+ selector: string,
407
+ theme: Theme | undefined,
408
+ mediaQuery?: string,
409
+ ) {
410
+ if (!theme?.propertyDefinitions) {
411
+ return ''
412
+ }
413
+
414
+ const properties = Object.entries(theme.propertyDefinitions).filter(
415
+ ([, property]) => property.value,
416
+ )
417
+ if (properties.length === 0) {
418
+ return ''
419
+ }
420
+
421
+ const css = `${selector} {
422
+ ${properties
423
+ .map(([propertyName, property]) => `${propertyName}: ${property.value};`)
424
+ .join('\n ')}
425
+ }`
426
+
427
+ if (mediaQuery) {
428
+ return `${mediaQuery} {
429
+ ${css}
430
+ }`
431
+ }
432
+
433
+ return css
434
+ }