@animus-ui/theming 0.1.1-beta.3 → 0.1.1-beta.30

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/CHANGELOG.md CHANGED
@@ -3,37 +3,133 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [0.1.1-beta.3](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.2...@animus-ui/theming@0.1.1-beta.3) (2022-01-09)
6
+ ## [0.1.1-beta.30](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.28...@animus-ui/theming@0.1.1-beta.30) (2025-07-01)
7
7
 
8
8
  **Note:** Version bump only for package @animus-ui/theming
9
9
 
10
+ ## 0.1.1-beta.29 (2025-06-15)
10
11
 
12
+ ## 0.1.1-beta.1 (2022-01-09)
11
13
 
14
+ ## 0.1.1-beta.0 (2022-01-09)
12
15
 
16
+ **Note:** Version bump only for package @animus-ui/theming
13
17
 
14
- ## 0.1.1-beta.2 (2022-01-09)
18
+ ## [0.1.1-beta.28](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.27...@animus-ui/theming@0.1.1-beta.28) (2025-06-13)
15
19
 
20
+ **Note:** Version bump only for package @animus-ui/theming
16
21
 
22
+ ## [0.1.1-beta.27](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.26...@animus-ui/theming@0.1.1-beta.27) (2025-05-29)
17
23
 
18
- ## 0.1.1-beta.1 (2022-01-09)
24
+ **Note:** Version bump only for package @animus-ui/theming
19
25
 
26
+ ## [0.1.1-beta.26](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.25...@animus-ui/theming@0.1.1-beta.26) (2025-05-29)
20
27
 
28
+ **Note:** Version bump only for package @animus-ui/theming
21
29
 
22
- ## 0.1.1-beta.0 (2022-01-09)
30
+ ## [0.1.1-beta.25](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.24...@animus-ui/theming@0.1.1-beta.25) (2023-03-15)
23
31
 
24
32
  **Note:** Version bump only for package @animus-ui/theming
25
33
 
34
+ ## [0.1.1-beta.24](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.23...@animus-ui/theming@0.1.1-beta.24) (2023-03-15)
26
35
 
36
+ **Note:** Version bump only for package @animus-ui/theming
27
37
 
38
+ ## [0.1.1-beta.23](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.21...@animus-ui/theming@0.1.1-beta.23) (2023-03-13)
28
39
 
40
+ **Note:** Version bump only for package @animus-ui/theming
29
41
 
30
- ## [0.1.1-beta.1](https://github.com/codecaaron/animus/compare/v0.1.1-beta.0...v0.1.1-beta.1) (2022-01-09)
42
+ ## [0.1.1-beta.22](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.21...@animus-ui/theming@0.1.1-beta.22) (2022-03-25)
43
+
44
+ **Note:** Version bump only for package @animus-ui/theming
45
+
46
+ ## [0.1.1-beta.21](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.20...@animus-ui/theming@0.1.1-beta.21) (2022-02-14)
47
+
48
+ **Note:** Version bump only for package @animus-ui/theming
49
+
50
+ ## [0.1.1-beta.20](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.19...@animus-ui/theming@0.1.1-beta.20) (2022-02-14)
51
+
52
+ **Note:** Version bump only for package @animus-ui/theming
53
+
54
+ ## [0.1.1-beta.19](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.18...@animus-ui/theming@0.1.1-beta.19) (2022-02-12)
55
+
56
+ **Note:** Version bump only for package @animus-ui/theming
57
+
58
+ ## [0.1.1-beta.18](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.17...@animus-ui/theming@0.1.1-beta.18) (2022-02-11)
59
+
60
+ **Note:** Version bump only for package @animus-ui/theming
61
+
62
+ ## [0.1.1-beta.17](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.16...@animus-ui/theming@0.1.1-beta.17) (2022-02-02)
63
+
64
+ **Note:** Version bump only for package @animus-ui/theming
65
+
66
+ ## [0.1.1-beta.16](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.15...@animus-ui/theming@0.1.1-beta.16) (2022-02-02)
67
+
68
+ **Note:** Version bump only for package @animus-ui/theming
69
+
70
+ ## [0.1.1-beta.15](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.14...@animus-ui/theming@0.1.1-beta.15) (2022-01-26)
71
+
72
+ **Note:** Version bump only for package @animus-ui/theming
73
+
74
+ ## [0.1.1-beta.14](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.13...@animus-ui/theming@0.1.1-beta.14) (2022-01-24)
31
75
 
32
76
  **Note:** Version bump only for package @animus-ui/theming
33
77
 
78
+ ## [0.1.1-beta.13](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.12...@animus-ui/theming@0.1.1-beta.13) (2022-01-24)
34
79
 
80
+ **Note:** Version bump only for package @animus-ui/theming
35
81
 
82
+ ## [0.1.1-beta.12](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.11...@animus-ui/theming@0.1.1-beta.12) (2022-01-24)
83
+
84
+ **Note:** Version bump only for package @animus-ui/theming
36
85
 
86
+ ## [0.1.1-beta.11](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.10...@animus-ui/theming@0.1.1-beta.11) (2022-01-24)
87
+
88
+ **Note:** Version bump only for package @animus-ui/theming
89
+
90
+ ## [0.1.1-beta.10](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.9...@animus-ui/theming@0.1.1-beta.10) (2022-01-23)
91
+
92
+ **Note:** Version bump only for package @animus-ui/theming
93
+
94
+ ## [0.1.1-beta.9](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.8...@animus-ui/theming@0.1.1-beta.9) (2022-01-18)
95
+
96
+ **Note:** Version bump only for package @animus-ui/theming
97
+
98
+ ## [0.1.1-beta.8](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.7...@animus-ui/theming@0.1.1-beta.8) (2022-01-16)
99
+
100
+ **Note:** Version bump only for package @animus-ui/theming
101
+
102
+ ## [0.1.1-beta.7](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.6...@animus-ui/theming@0.1.1-beta.7) (2022-01-16)
103
+
104
+ **Note:** Version bump only for package @animus-ui/theming
105
+
106
+ ## [0.1.1-beta.6](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.5...@animus-ui/theming@0.1.1-beta.6) (2022-01-11)
107
+
108
+ **Note:** Version bump only for package @animus-ui/theming
109
+
110
+ ## [0.1.1-beta.5](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.4...@animus-ui/theming@0.1.1-beta.5) (2022-01-09)
111
+
112
+ **Note:** Version bump only for package @animus-ui/theming
113
+
114
+ ## [0.1.1-beta.4](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.3...@animus-ui/theming@0.1.1-beta.4) (2022-01-09)
115
+
116
+ **Note:** Version bump only for package @animus-ui/theming
117
+
118
+ ## [0.1.1-beta.3](https://github.com/codecaaron/animus/compare/@animus-ui/theming@0.1.1-beta.2...@animus-ui/theming@0.1.1-beta.3) (2022-01-09)
119
+
120
+ **Note:** Version bump only for package @animus-ui/theming
121
+
122
+ ## 0.1.1-beta.2 (2022-01-09)
123
+
124
+ ## 0.1.1-beta.1 (2022-01-09)
125
+
126
+ ## 0.1.1-beta.0 (2022-01-09)
127
+
128
+ **Note:** Version bump only for package @animus-ui/theming
129
+
130
+ ## [0.1.1-beta.1](https://github.com/codecaaron/animus/compare/v0.1.1-beta.0...v0.1.1-beta.1) (2022-01-09)
131
+
132
+ **Note:** Version bump only for package @animus-ui/theming
37
133
 
38
134
  ## 0.1.1-beta.0 (2022-01-09)
39
135
 
package/CLAUDE.md ADDED
@@ -0,0 +1,334 @@
1
+ # ThemeBuilder Architecture & Animus Integration
2
+
3
+ This document captures deep architectural insights about the ThemeBuilder system and its integration with the Animus builder from the core package.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [ThemeBuilder Architecture](#themebuilder-architecture)
8
+ 2. [Design Token Resolution Process](#design-token-resolution-process)
9
+ 3. [Animus Builder Integration](#animus-builder-integration)
10
+ 4. [Critical Integration Points](#critical-integration-points)
11
+ 5. [Recommendations & Improvements](#recommendations--improvements)
12
+ 6. [Open Questions](#open-questions)
13
+
14
+ ## ThemeBuilder Architecture
15
+
16
+ ### Overview
17
+
18
+ The ThemeBuilder provides a fluent, type-safe API for building themes with design tokens, CSS variables, and color modes. It follows a Producer-Consumer pattern where ThemeBuilder produces theme configuration and Animus consumes it via Emotion's ThemeProvider.
19
+
20
+ ### Core Components
21
+
22
+ #### 1. Current ThemeBuilder Implementation (`createTheme.ts`)
23
+
24
+ ```typescript
25
+ export class ThemeBuilder<T extends AbstractTheme> {
26
+ #theme = {} as T;
27
+
28
+ constructor(baseTheme: T) { /* ... */ }
29
+ }
30
+ ```
31
+
32
+ **Key Methods:**
33
+ - `createScaleVariables(key)` - Transforms theme scales into CSS variables
34
+ - `addColors(colors)` - Adds color tokens to the theme
35
+ - `addColorModes(initialMode, modeConfig)` - Implements color mode switching
36
+ - `addScale(key, createScale)` - Adds new scale to the theme
37
+ - `updateScale(key, updateFn)` - Updates existing scale values
38
+ - `build()` - Finalizes the theme
39
+
40
+ #### 2. Legacy ThemeBuilder (`ThemeBuilder.ts`)
41
+
42
+ Uses class inheritance hierarchy:
43
+ ```
44
+ ThemeUnitialized → ThemeWithBreakpoints → ThemeWithRawColors → ThemeWithAll
45
+ ```
46
+
47
+ ### Theme Object Structure
48
+
49
+ The built theme contains three critical structures:
50
+
51
+ 1. **Public Scales** (e.g., `theme.colors`): CSS variable references (`'var(--colors-primary)'`)
52
+ 2. **Private Variables** (`theme._variables`): CSS variable definitions
53
+ 3. **Private Tokens** (`theme._tokens`): Original values (currently redundant)
54
+
55
+ ## Design Token Resolution Process
56
+
57
+ ### 1. Token Definition Phase
58
+
59
+ ```typescript
60
+ createTheme(baseTheme)
61
+ .addColors({ primary: '#007bff' })
62
+ ```
63
+
64
+ ### 2. Serialization Phase
65
+
66
+ The `serializeTokens` function creates:
67
+ - **Token References**: `{ primary: 'var(--colors-primary)' }`
68
+ - **Token Variables**: `{ '--colors-primary': '#007bff' }`
69
+
70
+ ### 3. Storage Phase
71
+
72
+ - `theme.colors.primary` = `'var(--colors-primary)'`
73
+ - `theme._variables.root['--colors-primary']` = `'#007bff'`
74
+ - `theme._tokens.colors.primary` = `'#007bff'`
75
+
76
+ ### 4. Injection Phase (Critical Gap)
77
+
78
+ **Currently missing**: A mechanism to inject CSS variables into the DOM. Applications must implement:
79
+
80
+ ```typescript
81
+ const MyGlobalStyles = () => {
82
+ const theme = useTheme();
83
+ return (
84
+ <Global
85
+ styles={css`
86
+ :root {
87
+ /* Inject theme._variables.root here */
88
+ }
89
+ `}
90
+ />
91
+ );
92
+ };
93
+ ```
94
+
95
+ ### 5. Component Usage Phase
96
+
97
+ ```typescript
98
+ <MyComponent color="primary" />
99
+ ```
100
+
101
+ ### 6. Style Resolution Phase
102
+
103
+ 1. `createPropertyStyle` invoked for `color` prop
104
+ 2. Calls `lookupScaleValue('primary', 'colors', theme)`
105
+ 3. Returns `'var(--colors-primary)'`
106
+ 4. Emotion generates CSS: `color: var(--colors-primary);`
107
+
108
+ ### 7. Browser Resolution Phase
109
+
110
+ Browser applies styles using CSS Custom Properties from injected variables.
111
+
112
+ ## Animus Builder Integration
113
+
114
+ ### Architecture Overview
115
+
116
+ Animus uses a class hierarchy with fluent API:
117
+ ```
118
+ Animus → AnimusWithBase → AnimusWithVariants → AnimusWithStates → AnimusWithSystem → AnimusWithAll
119
+ ```
120
+
121
+ ### Integration Points
122
+
123
+ 1. **Theme Access**: Animus components receive theme via Emotion's ThemeProvider
124
+ 2. **Scale Lookup**: `lookupScaleValue` resolves theme values from scales
125
+ 3. **CSS Variable Support**: Animus treats CSS variable strings as opaque values
126
+ 4. **Responsive Breakpoints**: Both systems use `theme.breakpoints` for media queries
127
+
128
+ ### Value Resolution Flow
129
+
130
+ ```
131
+ Component Prop → createPropertyStyle → lookupScaleValue → Theme Scale → CSS Variable → Browser
132
+ ```
133
+
134
+ ## Critical Integration Points
135
+
136
+ ### 1. Scale Value Resolution
137
+
138
+ The `lookupScaleValue` function in core/src/scales/lookupScaleValue.ts:
139
+ - Resolves values from theme scales
140
+ - Falls back to compatTheme
141
+ - **Limitation**: Doesn't support negative values (e.g., `m="-4"`)
142
+
143
+ ### 2. Responsive Values
144
+
145
+ - **ThemeBuilder**: Creates breakpoint CSS variables
146
+ - **Animus**: Uses breakpoints for media query generation
147
+ - Both systems must coordinate on breakpoint definitions
148
+
149
+ ### 3. Color Modes
150
+
151
+ Current implementation has complexity:
152
+ - `_variables.mode` contains initial mode values
153
+ - `_tokens.modes` structure unclear
154
+ - Application responsible for mode switching logic
155
+
156
+ ## Recommendations & Improvements
157
+
158
+ ### 1. Simplify Theme Contract
159
+
160
+ Remove `_tokens` from final output, keeping only:
161
+ - **Public Scales**: CSS variable references
162
+ - **Private Variables**: CSS variable definitions
163
+
164
+ ### 2. Provide Global Styles Utility
165
+
166
+ ```typescript
167
+ export const createGlobalStyles = (theme) => {
168
+ const { root, modes } = theme._variables;
169
+
170
+ return css`
171
+ :root {
172
+ ${varsToCss(root)}
173
+ }
174
+
175
+ ${Object.entries(modes).map(([mode, vars]) => `
176
+ [data-theme='${mode}'] {
177
+ ${varsToCss(vars)}
178
+ }
179
+ `).join('')}
180
+ `;
181
+ };
182
+ ```
183
+
184
+ ### 3. Support Negative Values
185
+
186
+ Update `lookupScaleValue` to handle string-prefixed negatives:
187
+
188
+ ```typescript
189
+ if (isString(val) && val.startsWith('-')) {
190
+ const positiveKey = val.substring(1);
191
+ const scaleValue = get(usedScale, positiveKey);
192
+
193
+ if (isString(scaleValue) || isNumber(scaleValue)) {
194
+ return `-${scaleValue}`;
195
+ }
196
+ }
197
+ ```
198
+
199
+ ### 4. Improve Color Mode Architecture
200
+
201
+ Restructure `_variables` for clarity:
202
+ ```typescript
203
+ {
204
+ _variables: {
205
+ root: { /* base tokens */ },
206
+ modes: {
207
+ light: { /* semantic aliases */ },
208
+ dark: { /* semantic aliases */ }
209
+ }
210
+ }
211
+ }
212
+ ```
213
+
214
+ ### 5. Type Safety Enhancements
215
+
216
+ - Create comprehensive type tests for chained builder calls
217
+ - Provide `GetAnimusProps<T>` utility type
218
+ - Make `build()` method generic for better inference
219
+
220
+ ## Open Questions
221
+
222
+ ### Critical Architecture Questions
223
+
224
+ 1. **Variable Injection Strategy**: Should we provide an official `ThemeProvider` wrapper that handles CSS variable injection automatically?
225
+ - Current gap: Apps must manually inject `theme._variables` into DOM
226
+ - Consideration: Auto-injection could simplify setup but reduce flexibility
227
+
228
+ 2. **Migration Path**: How do we support gradual migration from literal-value themes to CSS-variable-based themes?
229
+ - Challenge: Mixed themes with both literal values and CSS variables
230
+ - Need: Clear documentation and tooling for incremental adoption
231
+
232
+ 3. **Performance Optimization**: Is the extensive use of `lodash.merge` in builder chains a performance concern?
233
+ - Impact: Each builder method creates new merged objects
234
+ - Alternative: Investigate more performant merge strategies or lazy evaluation
235
+
236
+ 4. **Type Complexity**: How can we simplify the generic type chains while maintaining type safety?
237
+ - Current: Heavy generic usage can create complex error messages
238
+ - Goal: Better developer experience with clearer type errors
239
+
240
+ ### Integration Improvements
241
+
242
+ 5. **Negative Value Support**: Should negative values use string prefix pattern (like Chakra UI)?
243
+ - Current: `lookupScaleValue` doesn't support negative theme values
244
+ - Proposed: Support `m="-4"` syntax for negative margins
245
+
246
+ 6. **Color Mode Architecture**: Should we simplify the current three-source-of-truth pattern?
247
+ - Current: `_variables`, `_tokens`, and public scales create confusion
248
+ - Proposed: Eliminate `_tokens` from final build output
249
+
250
+ 7. **Responsive Value Coordination**: How to ensure array/object responsive syntax works consistently?
251
+ - Need: Integration tests between ThemeBuilder breakpoints and Animus responsive arrays
252
+ - Challenge: Both systems must coordinate on breakpoint definitions
253
+
254
+ ### Developer Experience
255
+
256
+ 8. **Official Global Styles Utility**: Should we provide `createGlobalStyles` helper?
257
+ - Benefit: Standardized way to inject CSS variables
258
+ - Implementation: Could be part of @animus-ui/theming package
259
+
260
+ 9. **Theme Structure Validation**: Should we validate theme structure at runtime?
261
+ - Use case: Catch missing CSS variable injections early
262
+ - Trade-off: Runtime validation vs. bundle size
263
+
264
+ 10. **Documentation Gaps**: Which patterns need more comprehensive examples?
265
+ - Compound components with theming
266
+ - Global styles and CSS resets
267
+ - Performance optimization patterns
268
+ - Common UI patterns (modals, dropdowns, forms)
269
+
270
+ ### Technical Debt
271
+
272
+ 11. **Legacy ThemeBuilder**: Should we deprecate the class inheritance version?
273
+ - Current: Two implementations create confusion
274
+ - Migration: Need clear upgrade path for existing users
275
+
276
+ 12. **Theme Contract Clarity**: How to better document the theme object contract?
277
+ - Issue: Unclear when to use `_variables` vs `_tokens` vs public scales
278
+ - Solution: Clearer separation of concerns in documentation
279
+
280
+ ### New Questions from Real-World Usage Analysis
281
+
282
+ 13. **Gradient Token System**: How should gradient tokens be defined in ThemeBuilder?
283
+ - Observed: Components use `gradient: 'flowX'` tokens
284
+ - Need: Clear pattern for defining complex gradient tokens as CSS variables
285
+
286
+ 14. **Numeric Value Normalization**: How do numeric theme values (0, 1, 0.5) map to CSS?
287
+ - Observed: `width: 1`, `size: 1`, `left: 0.5` in components
288
+ - Question: Is this a percentage system or theme scale reference?
289
+
290
+ 15. **Semantic Token Categories**: What token categories should ThemeBuilder support?
291
+ - Observed: text-shadow tokens ('flush', 'link-raised')
292
+ - Observed: gradient tokens ('flowX')
293
+ - Question: How to organize non-standard CSS tokens?
294
+
295
+ 16. **WebKit-Specific Properties**: Should ThemeBuilder handle vendor prefixes?
296
+ - Observed: `WebkitTextFillColor`, `WebkitBackgroundClip` usage
297
+ - Challenge: CSS variables with vendor prefixes
298
+
299
+ 17. **Grid Template Token Support**: Should grid templates be tokenized?
300
+ - Observed: Complex responsive grid templates in Layout
301
+ - Consideration: Token vs. inline definition trade-offs
302
+
303
+ 18. **Animation Token Integration**: How should keyframe animations work with tokens?
304
+ - Observed: Imported keyframes used with Animus styles
305
+ - Question: Can animations reference theme tokens?
306
+
307
+ 19. **Performance Benchmarks**: What's the performance impact of CSS variables?
308
+ - Heavy use of pseudo-elements with gradient variables
309
+ - Need: Benchmarks comparing literal values vs. CSS variables
310
+
311
+ 20. **Custom Property Mappings**: Should ThemeBuilder know about Animus prop shorthands?
312
+ - Observed: `area` → `gridArea`, `gradient` → complex gradient
313
+ - Question: Where should this mapping knowledge live?
314
+
315
+ ## Technical Notes
316
+
317
+ ### Key Files
318
+
319
+ - `/packages/theming/src/utils/createTheme.ts` - Main builder implementation
320
+ - `/packages/theming/src/utils/serializeTokens.ts` - CSS variable generation
321
+ - `/packages/theming/src/utils/flattenScale.ts` - Object flattening utilities
322
+ - `/packages/core/src/scales/lookupScaleValue.ts` - Theme value resolution
323
+ - `/packages/core/src/Animus.ts` - Style builder integration
324
+
325
+ ### Dependencies
326
+
327
+ - Emotion for CSS-in-JS and theming
328
+ - Lodash for object manipulation
329
+ - TypeScript for type safety
330
+
331
+ ---
332
+
333
+ *Last Updated: January 2025*
334
+ *Analysis based on deep architectural review and integration testing*
@@ -1,34 +1,34 @@
1
- import { Breakpoints } from '@animus-ui/core';
2
- /**
3
- * 1. Breakpoints
4
- * 2. Scales
5
- * 3. Tokens
6
- * 4. Variables
7
- * 5. Colors
8
- * 6. Color Modes
9
- */
10
- export declare class ThemeWithAll<Bps, Scales, Tokens, Vars> {
11
- breakpoints: Bps;
12
- scales: Scales;
13
- tokens: Tokens;
14
- variables: Vars;
15
- constructor(breakpoints: Bps, scales: Scales, tokens: Tokens, vars: Vars);
16
- addScale(): ThemeWithAll<Bps, Scales, Tokens, Vars>;
17
- build(): {
18
- breakpoints: Bps;
19
- } & Scales & {
20
- _tokens: Tokens;
21
- _variables: Vars;
22
- };
23
- }
24
- export declare class ThemeWithRawColors<Bps extends Breakpoints, Scales, Tokens, Vars> extends ThemeWithAll<Bps, Scales, Tokens, Vars> {
25
- constructor(breakpoints: Bps, scales: Scales, tokens: Tokens, vars: Vars);
26
- addColorModes(): ThemeWithAll<Bps, Scales, Tokens, Vars>;
27
- }
28
- export declare class ThemeWithBreakpoints<Bps extends Breakpoints> extends ThemeWithAll<Bps, {}, {}, {}> {
29
- constructor(breakpoints: Bps);
30
- addColors(): ThemeWithRawColors<Bps, {}, {}, {}>;
31
- }
32
- export declare class ThemeUnitialized {
33
- addBreakpoints<Bps extends Breakpoints>(breakpoints: Bps): ThemeWithBreakpoints<Bps>;
34
- }
1
+ import { Breakpoints } from '@animus-ui/core';
2
+ /**
3
+ * 1. Breakpoints
4
+ * 2. Scales
5
+ * 3. Tokens
6
+ * 4. Variables
7
+ * 5. Colors
8
+ * 6. Color Modes
9
+ */
10
+ export declare class ThemeWithAll<Bps, Scales, Tokens, Vars> {
11
+ breakpoints: Bps;
12
+ scales: Scales;
13
+ tokens: Tokens;
14
+ variables: Vars;
15
+ constructor(breakpoints: Bps, scales: Scales, tokens: Tokens, vars: Vars);
16
+ addScale(): ThemeWithAll<Bps, Scales, Tokens, Vars>;
17
+ build(): {
18
+ breakpoints: Bps;
19
+ } & Scales & {
20
+ _tokens: Tokens;
21
+ _variables: Vars;
22
+ };
23
+ }
24
+ export declare class ThemeWithRawColors<Bps extends Breakpoints, Scales, Tokens, Vars> extends ThemeWithAll<Bps, Scales, Tokens, Vars> {
25
+ constructor(breakpoints: Bps, scales: Scales, tokens: Tokens, vars: Vars);
26
+ addColorModes(): ThemeWithAll<Bps, Scales, Tokens, Vars>;
27
+ }
28
+ export declare class ThemeWithBreakpoints<Bps extends Breakpoints> extends ThemeWithAll<Bps, {}, {}, {}> {
29
+ constructor(breakpoints: Bps);
30
+ addColors(): ThemeWithRawColors<Bps, {}, {}, {}>;
31
+ }
32
+ export declare class ThemeUnitialized {
33
+ addBreakpoints<Bps extends Breakpoints>(breakpoints: Bps): ThemeWithBreakpoints<Bps>;
34
+ }
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export * from './utils';
1
+ export * from './utils';
package/dist/index.js ADDED
@@ -0,0 +1,289 @@
1
+ import { isObject, merge, mapValues } from 'lodash';
2
+
3
+ function _assertClassBrand(e, t, n) {
4
+ if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
5
+ throw new TypeError("Private element is not present on this object");
6
+ }
7
+ function _checkPrivateRedeclaration(e, t) {
8
+ if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
9
+ }
10
+ function _classCallCheck(a, n) {
11
+ if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
12
+ }
13
+ function _classPrivateFieldGet2(s, a) {
14
+ return s.get(_assertClassBrand(s, a));
15
+ }
16
+ function _classPrivateFieldInitSpec(e, t, a) {
17
+ _checkPrivateRedeclaration(e, t), t.set(e, a);
18
+ }
19
+ function _defineProperties(e, r) {
20
+ for (var t = 0; t < r.length; t++) {
21
+ var o = r[t];
22
+ o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
23
+ }
24
+ }
25
+ function _createClass(e, r, t) {
26
+ return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
27
+ writable: !1
28
+ }), e;
29
+ }
30
+ function _defineProperty(e, r, t) {
31
+ return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
32
+ value: t,
33
+ enumerable: !0,
34
+ configurable: !0,
35
+ writable: !0
36
+ }) : e[r] = t, e;
37
+ }
38
+ function ownKeys(e, r) {
39
+ var t = Object.keys(e);
40
+ if (Object.getOwnPropertySymbols) {
41
+ var o = Object.getOwnPropertySymbols(e);
42
+ r && (o = o.filter(function (r) {
43
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
44
+ })), t.push.apply(t, o);
45
+ }
46
+ return t;
47
+ }
48
+ function _objectSpread2(e) {
49
+ for (var r = 1; r < arguments.length; r++) {
50
+ var t = null != arguments[r] ? arguments[r] : {};
51
+ r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
52
+ _defineProperty(e, r, t[r]);
53
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
54
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
55
+ });
56
+ }
57
+ return e;
58
+ }
59
+ function _objectWithoutProperties(e, t) {
60
+ if (null == e) return {};
61
+ var o,
62
+ r,
63
+ i = _objectWithoutPropertiesLoose(e, t);
64
+ if (Object.getOwnPropertySymbols) {
65
+ var n = Object.getOwnPropertySymbols(e);
66
+ for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
67
+ }
68
+ return i;
69
+ }
70
+ function _objectWithoutPropertiesLoose(r, e) {
71
+ if (null == r) return {};
72
+ var t = {};
73
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
74
+ if (-1 !== e.indexOf(n)) continue;
75
+ t[n] = r[n];
76
+ }
77
+ return t;
78
+ }
79
+ function _toPrimitive(t, r) {
80
+ if ("object" != typeof t || !t) return t;
81
+ var e = t[Symbol.toPrimitive];
82
+ if (void 0 !== e) {
83
+ var i = e.call(t, r || "default");
84
+ if ("object" != typeof i) return i;
85
+ throw new TypeError("@@toPrimitive must return a primitive value.");
86
+ }
87
+ return ("string" === r ? String : Number)(t);
88
+ }
89
+ function _toPropertyKey(t) {
90
+ var i = _toPrimitive(t, "string");
91
+ return "symbol" == typeof i ? i : i + "";
92
+ }
93
+ function _classApplyDescriptorGet(e, t) {
94
+ return t.get ? t.get.call(e) : t.value;
95
+ }
96
+ function _classApplyDescriptorSet(e, t, l) {
97
+ if (t.set) t.set.call(e, l);else {
98
+ if (!t.writable) throw new TypeError("attempted to set read only private field");
99
+ t.value = l;
100
+ }
101
+ }
102
+ function _classPrivateFieldGet(e, t) {
103
+ var r = _classPrivateFieldGet2(t, e);
104
+ return _classApplyDescriptorGet(e, r);
105
+ }
106
+ function _classPrivateFieldSet(e, t, r) {
107
+ var s = _classPrivateFieldGet2(t, e);
108
+ return _classApplyDescriptorSet(e, s, r), r;
109
+ }
110
+
111
+ function flattenScale(object, path) {
112
+ return Object.keys(object).reduce(function (carry, key) {
113
+ var nextKey = path ? "".concat(path).concat(key === '_' ? '' : "-".concat(key)) : key;
114
+ var current = object[key];
115
+ if (isObject(current)) {
116
+ return _objectSpread2(_objectSpread2({}, carry), flattenScale(current, nextKey));
117
+ }
118
+ return _objectSpread2(_objectSpread2({}, carry), {}, _defineProperty({}, nextKey, object[key]));
119
+ }, {});
120
+ }
121
+
122
+ var _excluded = ["_"];
123
+ var templateBreakpoints = function templateBreakpoints(value, alias, theme) {
124
+ if (isObject(value)) {
125
+ var _ = value._,
126
+ rest = _objectWithoutProperties(value, _excluded);
127
+ var css = _defineProperty({}, alias, _);
128
+ if (theme) {
129
+ var breakpoints = theme.breakpoints;
130
+ Object.keys(breakpoints).forEach(function (key) {
131
+ if (rest[key]) {
132
+ css[breakpoints[key]] = _defineProperty({}, alias, rest[key]);
133
+ }
134
+ });
135
+ }
136
+ return css;
137
+ }
138
+ return _defineProperty({}, alias, value);
139
+ };
140
+ var serializeTokens = function serializeTokens(tokens, prefix, theme) {
141
+ var tokenReferences = {};
142
+ var tokenVariables = {};
143
+ Object.keys(tokens).forEach(function (key) {
144
+ var varName = "--".concat(prefix, "-").concat(key.replace('$', ''));
145
+ tokenReferences[key] = "var(".concat(varName, ")");
146
+ merge(tokenVariables, templateBreakpoints(tokens[key], varName, theme));
147
+ });
148
+ return {
149
+ tokens: tokenReferences,
150
+ variables: tokenVariables
151
+ };
152
+ };
153
+
154
+ var _theme = /*#__PURE__*/new WeakMap();
155
+ var ThemeBuilder = /*#__PURE__*/function () {
156
+ function ThemeBuilder(baseTheme) {
157
+ _classCallCheck(this, ThemeBuilder);
158
+ _classPrivateFieldInitSpec(this, _theme, {
159
+ writable: true,
160
+ value: {}
161
+ });
162
+ _classPrivateFieldSet(this, _theme, baseTheme);
163
+ }
164
+ /**
165
+ *
166
+ * @param key A key of the current theme to transform into CSS Variables and Variable References
167
+ * @example .createScaleVariables('fontSize')
168
+ */
169
+ _createClass(ThemeBuilder, [{
170
+ key: "createScaleVariables",
171
+ value: function createScaleVariables(key) {
172
+ var _merge;
173
+ var _serializeTokens = serializeTokens(_classPrivateFieldGet(this, _theme)[key], key, _classPrivateFieldGet(this, _theme)),
174
+ variables = _serializeTokens.variables,
175
+ tokens = _serializeTokens.tokens;
176
+ _classPrivateFieldSet(this, _theme, merge({}, _classPrivateFieldGet(this, _theme), (_merge = {}, _defineProperty(_merge, key, tokens), _defineProperty(_merge, "_variables", _defineProperty({}, key, variables)), _defineProperty(_merge, "_tokens", _defineProperty({}, key, _classPrivateFieldGet(this, _theme)[key])), _merge)));
177
+ return this;
178
+ }
179
+ /**
180
+ *
181
+ * @param colors A map of color tokens to add to the theme. These tokens are immediately converted to CSS Variables `--color-${key}`.
182
+ * @example .addColors({ navy: 'navy', hyper: 'purple' })
183
+ */
184
+ }, {
185
+ key: "addColors",
186
+ value: function addColors(colors) {
187
+ var flatColors = flattenScale(colors);
188
+ var _serializeTokens2 = serializeTokens(flatColors, 'color', _classPrivateFieldGet(this, _theme)),
189
+ variables = _serializeTokens2.variables,
190
+ tokens = _serializeTokens2.tokens;
191
+ _classPrivateFieldSet(this, _theme, merge({}, _classPrivateFieldGet(this, _theme), {
192
+ colors: tokens,
193
+ _variables: {
194
+ root: variables
195
+ },
196
+ _tokens: {
197
+ colors: flatColors
198
+ }
199
+ }));
200
+ return this;
201
+ }
202
+ /**
203
+ *
204
+ * @param initialMode A key of the object passed for modes. This sets the default state for the theme and transforms the correct variables.
205
+ * @param modes A map of color modes with keys of each possible mode with a value of alias to color keys. This must be called after `addColors`
206
+ * @example .addColorModes('light', { light: { primary: 'hyper' }, { dark: { primary: 'navy' } } })
207
+ */
208
+ }, {
209
+ key: "addColorModes",
210
+ value: function addColorModes(initialMode, modeConfig) {
211
+ var _classPrivateFieldGet2,
212
+ _this = this;
213
+ var modes = mapValues(modeConfig, function (mode) {
214
+ return flattenScale(mode);
215
+ });
216
+ var _serializeTokens3 = serializeTokens(mapValues(merge({}, (_classPrivateFieldGet2 = _classPrivateFieldGet(this, _theme).modes) === null || _classPrivateFieldGet2 === void 0 ? void 0 : _classPrivateFieldGet2[initialMode], modes[initialMode]), function (color) {
217
+ return _classPrivateFieldGet(_this, _theme).colors[color];
218
+ }), 'color', _classPrivateFieldGet(this, _theme)),
219
+ colors = _serializeTokens3.tokens,
220
+ variables = _serializeTokens3.variables;
221
+ var getColorValue = function getColorValue(color) {
222
+ var _classPrivateFieldGet3, _classPrivateFieldGet4;
223
+ return (_classPrivateFieldGet3 = _classPrivateFieldGet(_this, _theme)._tokens) === null || _classPrivateFieldGet3 === void 0 ? void 0 : (_classPrivateFieldGet4 = _classPrivateFieldGet3.colors) === null || _classPrivateFieldGet4 === void 0 ? void 0 : _classPrivateFieldGet4[color];
224
+ };
225
+ _classPrivateFieldSet(this, _theme, merge({}, _classPrivateFieldGet(this, _theme), {
226
+ colors: colors,
227
+ modes: modes,
228
+ mode: initialMode,
229
+ _getColorValue: getColorValue,
230
+ _variables: {
231
+ mode: variables
232
+ },
233
+ _tokens: {
234
+ modes: mapValues(modes, function (mode) {
235
+ return mapValues(mode, getColorValue);
236
+ })
237
+ }
238
+ }));
239
+ return this;
240
+ }
241
+ /**
242
+ *
243
+ * @param key A new key of theme
244
+ * @param createScale A function that accepts the current theme and returns a new object of scale values.
245
+ * @example .addScale('fonts', () => ({ basic: 'Gotham', cool: 'Wingdings' }))
246
+ */
247
+ }, {
248
+ key: "addScale",
249
+ value: function addScale(key, createScale) {
250
+ _classPrivateFieldSet(this, _theme, merge({}, _classPrivateFieldGet(this, _theme), _defineProperty({}, key, flattenScale(createScale(_classPrivateFieldGet(this, _theme))))));
251
+ return this;
252
+ }
253
+ /**
254
+ *
255
+ * @param key A current key of theme to be updated with new or computed values
256
+ * @param updateFn A function that accepts an argument of the current values at the specified keys an returns a map of new values to merge.
257
+ * @example .updateScale('fonts', ({ basic }) => ({ basicFallback: `{basic}, Montserrat` }))
258
+ */
259
+ }, {
260
+ key: "updateScale",
261
+ value: function updateScale(key, updateFn) {
262
+ _classPrivateFieldSet(this, _theme, merge({}, _classPrivateFieldGet(this, _theme), _defineProperty({}, key, updateFn(_classPrivateFieldGet(this, _theme)[key]))));
263
+ return this;
264
+ }
265
+ /**
266
+ * This finalizes the theme build and returns the final theme and variables to be provided.
267
+ */
268
+ }, {
269
+ key: "build",
270
+ value: function build() {
271
+ var _serializeTokens4 = serializeTokens(mapValues(_classPrivateFieldGet(this, _theme).breakpoints, function (val) {
272
+ return "".concat(val, "px");
273
+ }), 'breakpoint', _classPrivateFieldGet(this, _theme)),
274
+ variables = _serializeTokens4.variables;
275
+ return merge({}, _classPrivateFieldGet(this, _theme), {
276
+ _variables: {
277
+ breakpoints: variables
278
+ },
279
+ _tokens: {}
280
+ });
281
+ }
282
+ }]);
283
+ return ThemeBuilder;
284
+ }();
285
+ function createTheme(base) {
286
+ return new ThemeBuilder(base);
287
+ }
288
+
289
+ export { ThemeBuilder, createTheme, flattenScale, serializeTokens };
@@ -1,53 +1,53 @@
1
- import { CSSObject, AbstractTheme } from '@animus-ui/core';
2
- import { LiteralPaths } from './flattenScale';
3
- import { KeyAsVariable } from './serializeTokens';
4
- import { ColorModeConfig, Merge, MergeTheme, PrivateThemeKeys } from './types';
5
- export declare class ThemeBuilder<T extends AbstractTheme> {
6
- #private;
7
- constructor(baseTheme: T);
8
- /**
9
- *
10
- * @param key A key of the current theme to transform into CSS Variables and Variable References
11
- * @example .createScaleVariables('fontSize')
12
- */
13
- createScaleVariables<Key extends keyof Omit<T, 'breakpoints'> & string>(key: Key): ThemeBuilder<MergeTheme<T, PrivateThemeKeys, Record<Key, Record<Key, KeyAsVariable<T[Key], Key>>>>>;
14
- /**
15
- *
16
- * @param colors A map of color tokens to add to the theme. These tokens are immediately converted to CSS Variables `--color-${key}`.
17
- * @example .addColors({ navy: 'navy', hyper: 'purple' })
18
- */
19
- addColors<Colors extends Record<string, string | number | CSSObject>, NextColors extends LiteralPaths<Colors, '-'>>(colors: Colors): ThemeBuilder<MergeTheme<T & PrivateThemeKeys, Record<'colors', KeyAsVariable<NextColors, 'color'>>>>;
20
- /**
21
- *
22
- * @param initialMode A key of the object passed for modes. This sets the default state for the theme and transforms the correct variables.
23
- * @param modes A map of color modes with keys of each possible mode with a value of alias to color keys. This must be called after `addColors`
24
- * @example .addColorModes('light', { light: { primary: 'hyper' }, { dark: { primary: 'navy' } } })
25
- */
26
- addColorModes<Modes extends string, InitialMode extends keyof Config, Colors extends keyof T['colors'], ModeColors extends ColorModeConfig<Colors>, Config extends Record<Modes, ModeColors>, ColorAliases extends {
27
- [K in keyof Config]: LiteralPaths<Config[K], '-', '_'>;
28
- }>(initialMode: InitialMode, modeConfig: Config): ThemeBuilder<MergeTheme<T & PrivateThemeKeys, {
29
- colors: KeyAsVariable<LiteralPaths<Config[keyof Config], '-', '_'>, 'colors'> & T['colors'];
30
- modes: Merge<T['modes'], ColorAliases>;
31
- mode: keyof Config;
32
- _getColorValue: (color: keyof T['colors']) => string;
33
- }>>;
34
- /**
35
- *
36
- * @param key A new key of theme
37
- * @param createScale A function that accepts the current theme and returns a new object of scale values.
38
- * @example .addScale('fonts', () => ({ basic: 'Gotham', cool: 'Wingdings' }))
39
- */
40
- addScale<Key extends string, Fn extends (theme: T) => Record<string | number, string | number | Record<string, string | number>>, NewScale extends LiteralPaths<ReturnType<Fn>, '-'>>(key: Key, createScale: Fn): ThemeBuilder<MergeTheme<T, Record<Key, NewScale>>>;
41
- /**
42
- *
43
- * @param key A current key of theme to be updated with new or computed values
44
- * @param updateFn A function that accepts an argument of the current values at the specified keys an returns a map of new values to merge.
45
- * @example .updateScale('fonts', ({ basic }) => ({ basicFallback: `{basic}, Montserrat` }))
46
- */
47
- updateScale<Key extends keyof T, Fn extends (tokens: T[Key]) => Record<string | number, unknown>>(key: Key, updateFn: Fn): ThemeBuilder<T & Record<Key, T[Key] & ReturnType<Fn>>>;
48
- /**
49
- * This finalizes the theme build and returns the final theme and variables to be provided.
50
- */
51
- build(): T & PrivateThemeKeys;
52
- }
53
- export declare function createTheme<T extends AbstractTheme>(base: T): ThemeBuilder<T>;
1
+ import { AbstractTheme, CSSObject } from '@animus-ui/core';
2
+ import { LiteralPaths } from './flattenScale';
3
+ import { KeyAsVariable } from './serializeTokens';
4
+ import { ColorModeConfig, Merge, MergeTheme, PrivateThemeKeys } from './types';
5
+ export declare class ThemeBuilder<T extends AbstractTheme> {
6
+ #private;
7
+ constructor(baseTheme: T);
8
+ /**
9
+ *
10
+ * @param key A key of the current theme to transform into CSS Variables and Variable References
11
+ * @example .createScaleVariables('fontSize')
12
+ */
13
+ createScaleVariables<Key extends keyof Omit<T, 'breakpoints'> & string>(key: Key): ThemeBuilder<MergeTheme<T, PrivateThemeKeys, Record<Key, Record<Key, KeyAsVariable<T[Key], Key>>>>>;
14
+ /**
15
+ *
16
+ * @param colors A map of color tokens to add to the theme. These tokens are immediately converted to CSS Variables `--color-${key}`.
17
+ * @example .addColors({ navy: 'navy', hyper: 'purple' })
18
+ */
19
+ addColors<Colors extends Record<string, string | number | CSSObject>, NextColors extends LiteralPaths<Colors, '-'>>(colors: Colors): ThemeBuilder<MergeTheme<T & PrivateThemeKeys, Record<'colors', KeyAsVariable<NextColors, 'color'>>>>;
20
+ /**
21
+ *
22
+ * @param initialMode A key of the object passed for modes. This sets the default state for the theme and transforms the correct variables.
23
+ * @param modes A map of color modes with keys of each possible mode with a value of alias to color keys. This must be called after `addColors`
24
+ * @example .addColorModes('light', { light: { primary: 'hyper' }, { dark: { primary: 'navy' } } })
25
+ */
26
+ addColorModes<Modes extends string, InitialMode extends keyof Config, Colors extends keyof T['colors'], ModeColors extends ColorModeConfig<Colors>, Config extends Record<Modes, ModeColors>, ColorAliases extends {
27
+ [K in keyof Config]: LiteralPaths<Config[K], '-', '_'>;
28
+ }>(initialMode: InitialMode, modeConfig: Config): ThemeBuilder<MergeTheme<T & PrivateThemeKeys, {
29
+ colors: KeyAsVariable<LiteralPaths<Config[keyof Config], '-', '_'>, 'colors'> & T['colors'];
30
+ modes: Merge<T['modes'], ColorAliases>;
31
+ mode: keyof Config;
32
+ _getColorValue: (color: keyof T['colors']) => string;
33
+ }>>;
34
+ /**
35
+ *
36
+ * @param key A new key of theme
37
+ * @param createScale A function that accepts the current theme and returns a new object of scale values.
38
+ * @example .addScale('fonts', () => ({ basic: 'Gotham', cool: 'Wingdings' }))
39
+ */
40
+ addScale<Key extends string, Fn extends (theme: T) => Record<string | number, string | number | Record<string, string | number>>, NewScale extends LiteralPaths<ReturnType<Fn>, '-'>>(key: Key, createScale: Fn): ThemeBuilder<MergeTheme<T, Record<Key, NewScale>>>;
41
+ /**
42
+ *
43
+ * @param key A current key of theme to be updated with new or computed values
44
+ * @param updateFn A function that accepts an argument of the current values at the specified keys an returns a map of new values to merge.
45
+ * @example .updateScale('fonts', ({ basic }) => ({ basicFallback: `{basic}, Montserrat` }))
46
+ */
47
+ updateScale<Key extends keyof T, Fn extends (tokens: T[Key]) => Record<string | number, unknown>>(key: Key, updateFn: Fn): ThemeBuilder<T & Record<Key, T[Key] & ReturnType<Fn>>>;
48
+ /**
49
+ * This finalizes the theme build and returns the final theme and variables to be provided.
50
+ */
51
+ build(): T & PrivateThemeKeys;
52
+ }
53
+ export declare function createTheme<T extends AbstractTheme>(base: T): ThemeBuilder<T>;
@@ -1,20 +1,20 @@
1
- /**
2
- * Returns an exhaustive list of all possible paths of an object T for keys K.
3
- * Possibilities are returned as `k1.k2.k3`.
4
- */
5
- export declare type FindPath<T, K extends keyof T, D extends string = '.'> = K extends string | number ? T[K] extends Record<string | number, any> ? T[K] extends ArrayLike<any> ? K | `${K}${D}${FindPath<T[K], Exclude<keyof T[K], keyof any[]>, D>}` : K | `${K}${D}${FindPath<T[K], keyof T[K], D>}` : K : never;
6
- /** Returns valid paths of object T */
7
- export declare type Path<T, D extends string = '.'> = FindPath<T, keyof T, D> | keyof T;
8
- /** Returns the value of a valid path P `k1.k2.k3` in object T */
9
- export declare type PathValue<T, P extends Path<T, D>, D extends string = '.'> = P extends `${infer K}${D}${infer Rest}` ? K extends keyof T ? Rest extends Path<T[K], D> ? PathValue<T[K], Rest, D> : never : never : P extends keyof T ? T[P] : never;
10
- /** Check if path has a primitive end value and return only the union of end paths */
11
- export declare type PathToLiteral<T, K extends Path<T, D>, D extends string = '.', Base extends string = ''> = PathValue<T, K, D> extends string | number ? K extends string | number ? K extends `${infer BasePath}${D}${Base}` ? BasePath : K : never : never;
12
- /**
13
- * Reduce all paths to a single map of paths with primitive values removing all extra non stateful paths
14
- * { path: { sub: 1 } } => { 'path-sub': 1 }
15
- *
16
- */
17
- export declare type LiteralPaths<T extends Record<string | number, any>, D extends string = '.', Base extends string = ''> = {
18
- [K in Path<T, D> as PathToLiteral<T, K, D, Base>]: PathValue<T, PathToLiteral<T, K, D>, D>;
19
- };
20
- export declare function flattenScale<T extends Record<string | number, any>, P extends string>(object: T, path?: P): LiteralPaths<T, '-', '_'>;
1
+ /**
2
+ * Returns an exhaustive list of all possible paths of an object T for keys K.
3
+ * Possibilities are returned as `k1.k2.k3`.
4
+ */
5
+ export type FindPath<T, K extends keyof T, D extends string = '.'> = K extends string | number ? T[K] extends Record<string | number, any> ? T[K] extends ArrayLike<any> ? K | `${K}${D}${FindPath<T[K], Exclude<keyof T[K], keyof any[]>, D>}` : K | `${K}${D}${FindPath<T[K], keyof T[K], D>}` : K : never;
6
+ /** Returns valid paths of object T */
7
+ export type Path<T, D extends string = '.'> = FindPath<T, keyof T, D> | keyof T;
8
+ /** Returns the value of a valid path P `k1.k2.k3` in object T */
9
+ export type PathValue<T, P extends Path<T, D>, D extends string = '.'> = P extends `${infer K}${D}${infer Rest}` ? K extends keyof T ? Rest extends Path<T[K], D> ? PathValue<T[K], Rest, D> : never : never : P extends keyof T ? T[P] : never;
10
+ /** Check if path has a primitive end value and return only the union of end paths */
11
+ export type PathToLiteral<T, K extends Path<T, D>, D extends string = '.', Base extends string = ''> = PathValue<T, K, D> extends string | number ? K extends string | number ? K extends `${infer BasePath}${D}${Base}` ? BasePath : K : never : never;
12
+ /**
13
+ * Reduce all paths to a single map of paths with primitive values removing all extra non stateful paths
14
+ * { path: { sub: 1 } } => { 'path-sub': 1 }
15
+ *
16
+ */
17
+ export type LiteralPaths<T extends Record<string | number, any>, D extends string = '.', Base extends string = ''> = {
18
+ [K in Path<T, D> as PathToLiteral<T, K, D, Base>]: PathValue<T, PathToLiteral<T, K, D>, D>;
19
+ };
20
+ export declare function flattenScale<T extends Record<string | number, unknown>, P extends string>(object: T, path?: P): LiteralPaths<T, '-', '_'>;
@@ -1,3 +1,3 @@
1
- export * from './createTheme';
2
- export * from './serializeTokens';
3
- export * from './flattenScale';
1
+ export * from './createTheme';
2
+ export * from './flattenScale';
3
+ export * from './serializeTokens';
@@ -1,18 +1,19 @@
1
- import { Theme } from '@emotion/react';
2
- import { CSSObject } from '@animus-ui/core';
3
- /**
4
- * Returns an type of any object with { key: 'var(--key) }
5
- */
6
- export declare type KeyAsVariable<T extends Record<string, any>, Prefix extends string> = {
7
- [V in keyof T]: `var(--${Prefix}-${Extract<V, string>})`;
8
- };
9
- declare type SerializedTokensInput = Record<string, string | number | CSSObject | SerializedTokensInputRecursive>;
10
- interface SerializedTokensInputRecursive {
11
- [i: number]: SerializedTokensInput;
12
- [i: string]: SerializedTokensInput;
13
- }
14
- export declare const serializeTokens: <T extends SerializedTokensInput, Prefix extends string>(tokens: T, prefix: Prefix, theme: Theme | undefined) => {
15
- tokens: KeyAsVariable<T, Prefix>;
16
- variables: CSSObject;
17
- };
18
- export {};
1
+ import { CSSObject } from '@animus-ui/core';
2
+ import { Theme } from '@emotion/react';
3
+ /**
4
+ * Returns an type of any object with { key: 'var(--key) }
5
+ */
6
+ export type KeyAsVariable<T extends Record<string, any>, Prefix extends string> = {
7
+ [V in keyof T]: `var(--${Prefix}-${SanitizeKey<Extract<V, string>>})`;
8
+ };
9
+ export type SanitizeKey<T extends string> = T extends `${'$'}${infer Y}` ? Y : T;
10
+ type SerializedTokensInput = Record<string, string | number | CSSObject | SerializedTokensInputRecursive>;
11
+ interface SerializedTokensInputRecursive {
12
+ [i: number]: SerializedTokensInput;
13
+ [i: string]: SerializedTokensInput;
14
+ }
15
+ export declare const serializeTokens: <T extends SerializedTokensInput, Prefix extends string>(tokens: T, prefix: Prefix, theme: Theme | undefined) => {
16
+ tokens: KeyAsVariable<T, Prefix>;
17
+ variables: CSSObject;
18
+ };
19
+ export {};
@@ -1,41 +1,41 @@
1
- import { AbstractTheme, CSSObject } from '@animus-ui/core';
2
- /**
3
- * This is a custom generic that ensures the safety of adding additional values to a theme object without accidentally wiping out
4
- * required keys like `breakpoints`. It works by creating a new mapped type and merging the values of the union of Base & Next:
5
- * 1. If the key exists on both Base and Next return the intersection of both values
6
- * 2. If the key exists on next use the value on next.
7
- * 3. If the key exists on base but nothing else use the value on base.
8
- *
9
- * The resulting type is then rejoined with keys that cannot be mutated (breakpoints) as the next version of Theme
10
- */
11
- export declare type MergeTheme<Base extends AbstractTheme, Next, Unmergable = Record<'breakpoints', Base['breakpoints']>> = Unmergable & Merge<Base, Next>;
12
- /** This merges at 2 levels of depth */
13
- export declare type Merge<A, B> = {
14
- [K in keyof (A & B)]: K extends keyof B ? K extends keyof A ? AssignValueIfUnmergable<A[K], B[K]> : B[K] : K extends keyof A ? A[K] : never;
15
- };
16
- /** Extract mergable objects */
17
- export declare type Mergable<T> = Exclude<T, ((...args: any) => any) | string | boolean | symbol | number | any[]>;
18
- /** Return B if either A or B is unmergable */
19
- export declare type AssignValueIfUnmergable<A, B> = Mergable<A> extends never ? B : Mergable<B> extends never ? B : Assign<A, B>;
20
- /** Prefer all values from B */
21
- export declare type Assign<A, B> = {
22
- [K in keyof A | keyof B]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never;
23
- };
24
- /** These are keys that are consistent for all theme builds - they are loosely typed as they are not meant to be accessed directly */
25
- export declare type PrivateThemeKeys = {
26
- _variables: Record<string, CSSObject>;
27
- _tokens: Record<string | number, any>;
28
- };
29
- /** This allows 3 layers of color aliases to be constructed when adding colorModes
30
- * @example
31
- * {
32
- * button: {
33
- * bg: {
34
- * hover: 'someAlias'
35
- * }
36
- * }
37
- * }
38
- *
39
- * `button-bg-hover`
40
- * */
41
- export declare type ColorModeConfig<Colors> = Record<string, Colors | Record<string, Colors> | Record<string, Colors | Record<string, Colors>>>;
1
+ import { AbstractTheme, CSSObject } from '@animus-ui/core';
2
+ /**
3
+ * This is a custom generic that ensures the safety of adding additional values to a theme object without accidentally wiping out
4
+ * required keys like `breakpoints`. It works by creating a new mapped type and merging the values of the union of Base & Next:
5
+ * 1. If the key exists on both Base and Next return the intersection of both values
6
+ * 2. If the key exists on next use the value on next.
7
+ * 3. If the key exists on base but nothing else use the value on base.
8
+ *
9
+ * The resulting type is then rejoined with keys that cannot be mutated (breakpoints) as the next version of Theme
10
+ */
11
+ export type MergeTheme<Base extends AbstractTheme, Next, Unmergable = Record<'breakpoints', Base['breakpoints']>> = Unmergable & Merge<Base, Next>;
12
+ /** This merges at 2 levels of depth */
13
+ export type Merge<A, B> = {
14
+ [K in keyof (A & B)]: K extends keyof B ? K extends keyof A ? AssignValueIfUnmergable<A[K], B[K]> : B[K] : K extends keyof A ? A[K] : never;
15
+ };
16
+ /** Extract mergable objects */
17
+ export type Mergable<T> = Exclude<T, ((...args: any) => any) | string | boolean | symbol | number | any[]>;
18
+ /** Return B if either A or B is unmergable */
19
+ export type AssignValueIfUnmergable<A, B> = Mergable<A> extends never ? B : Mergable<B> extends never ? B : Assign<A, B>;
20
+ /** Prefer all values from B */
21
+ export type Assign<A, B> = {
22
+ [K in keyof A | keyof B]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never;
23
+ };
24
+ /** These are keys that are consistent for all theme builds - they are loosely typed as they are not meant to be accessed directly */
25
+ export type PrivateThemeKeys = {
26
+ _variables: Record<string, CSSObject>;
27
+ _tokens: Record<string | number, any>;
28
+ };
29
+ /** This allows 3 layers of color aliases to be constructed when adding colorModes
30
+ * @example
31
+ * {
32
+ * button: {
33
+ * bg: {
34
+ * hover: 'someAlias'
35
+ * }
36
+ * }
37
+ * }
38
+ *
39
+ * `button-bg-hover`
40
+ * */
41
+ export type ColorModeConfig<Colors> = Record<string, Colors | Record<string, Colors> | Record<string, Colors | Record<string, Colors>>>;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@animus-ui/theming",
3
- "version": "0.1.1-beta.3",
4
- "description": "> TODO: description",
3
+ "version": "0.1.1-beta.30",
4
+ "description": "Theming Utilities",
5
5
  "author": "Aaron Robb <airrobb@gmail.com>",
6
6
  "homepage": "https://github.com/codecaaron/animus#readme",
7
7
  "license": "MIT",
8
- "main": "dist/index.cjs.js",
9
- "module": "dist/index.esm.js",
10
- "types": "dist/index.d.ts",
8
+ "module": "./dist/index.js",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -18,19 +18,20 @@
18
18
  "scripts": {
19
19
  "build:clean": "rm -rf ./dist",
20
20
  "build": "yarn build:clean && rollup -c",
21
- "lernaBuildTask": "yarn build"
21
+ "lernaBuildTask": "yarn build",
22
+ "compile": "tsc --noEmit"
22
23
  },
23
24
  "bugs": {
24
25
  "url": "https://github.com/codecaaron/animus/issues"
25
26
  },
26
27
  "dependencies": {
27
- "@animus-ui/core": "^0.1.1-beta.3"
28
+ "@animus-ui/core": "^0.2.0-beta.2",
29
+ "@emotion/react": "^11.14.0",
30
+ "@emotion/styled": "^11.14.0"
28
31
  },
29
32
  "peerDependencies": {
30
- "@emotion/react": ">=11.0.0",
31
- "@emotion/styled": ">=11.0.0",
32
33
  "lodash": "*",
33
34
  "typescript": ">=4.3.5"
34
35
  },
35
- "gitHead": "76793243982d4b91436115077c74ac8b4444b471"
36
+ "gitHead": "fbc53708e472bbc9b68a06d81a97614c504c8025"
36
37
  }
package/rollup.config.js CHANGED
@@ -1,3 +1,3 @@
1
- import config from '../../rollup.config';
1
+ const config = require('../../rollup.config');
2
2
 
3
- export default config();
3
+ module.exports = config();
package/tsconfig.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "extends": "../../tsconfig.json",
3
3
  "compilerOptions": {
4
- // "emitDeclarationOnly": true,
4
+ "declaration": true,
5
+ "rootDir": "./src",
5
6
  "outDir": "./dist"
6
7
  },
7
- "include": ["../../typings/*.d.ts", "./src/**/*.ts", "./src/**/*.tsx"],
8
- "exclude": ["./**/*.test.tsx", "./**/*.test.ts"]
8
+ "include": ["src/**/*.ts", "src/**/*.tsx"],
9
+ "exclude": ["**/*.test.ts", "**/*.test.tsx"]
9
10
  }
package/dist/index.cjs.js DELETED
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("lodash");function t(s,r){return Object.keys(s).reduce(((o,h)=>{const i=r?`${r}${"_"===h?"":`-${h}`}`:h,a=s[h];return e.isObject(a)?{...o,...t(a,i)}:{...o,[i]:s[h]}}),{})}const s=(t,s,r)=>{const o={},h={};return Object.keys(t).forEach((i=>{const a=`--${s}-${i}`;o[i]=`var(${a})`,e.merge(h,((t,s,r)=>{if(e.isObject(t)){const{_:e,base:o,...h}=t,i={[s]:e??o};if(r){const{breakpoints:e}=r;Object.keys(e).forEach((t=>{i[e[t]]={[s]:h[t]}}))}return i}return{[s]:t}})(t[i],a,r))})),{tokens:o,variables:h}};class r{#e={};constructor(e){this.#e=e}createScaleVariables(t){const{variables:r,tokens:o}=s(this.#e[t],t,this.#e);return this.#e=e.merge({},this.#e,{[t]:o,_variables:{root:r},_tokens:{[t]:this.#e[t]}}),this}addColors(r){const o=t(r),{variables:h,tokens:i}=s(o,"color",this.#e);return this.#e=e.merge({},this.#e,{colors:i,_variables:{root:h},_tokens:{colors:o}}),this}addColorModes(r,o){const h=e.mapValues(o,(e=>t(e))),{tokens:i,variables:a}=s(e.mapValues(e.merge({},this.#e.modes?.[r],h[r]),(e=>this.#e.colors[e])),"color",this.#e),m=e=>this.#e._tokens?.colors?.[e];return this.#e=e.merge({},this.#e,{colors:i,modes:h,mode:r,_getColorValue:m,_variables:{mode:a},_tokens:{modes:e.mapValues(h,(t=>e.mapValues(t,m)))}}),this}addScale(s,r){return this.#e=e.merge({},this.#e,{[s]:t(r(this.#e))}),this}updateScale(t,s){return this.#e=e.merge({},this.#e,{[t]:s(this.#e[t])}),this}build(){return e.merge({},this.#e,{_variables:{},_tokens:{}})}}exports.ThemeBuilder=r,exports.createTheme=function(e){return new r(e)},exports.flattenScale=t,exports.serializeTokens=s;
package/dist/index.esm.js DELETED
@@ -1 +0,0 @@
1
- import{isObject as e,merge as t,mapValues as s}from"lodash";function o(t,s){return Object.keys(t).reduce(((r,h)=>{const i=s?`${s}${"_"===h?"":`-${h}`}`:h,n=t[h];return e(n)?{...r,...o(n,i)}:{...r,[i]:t[h]}}),{})}const r=(s,o,r)=>{const h={},i={};return Object.keys(s).forEach((n=>{const a=`--${o}-${n}`;h[n]=`var(${a})`,t(i,((t,s,o)=>{if(e(t)){const{_:e,base:r,...h}=t,i={[s]:e??r};if(o){const{breakpoints:e}=o;Object.keys(e).forEach((t=>{i[e[t]]={[s]:h[t]}}))}return i}return{[s]:t}})(s[n],a,r))})),{tokens:h,variables:i}};class h{#e={};constructor(e){this.#e=e}createScaleVariables(e){const{variables:s,tokens:o}=r(this.#e[e],e,this.#e);return this.#e=t({},this.#e,{[e]:o,_variables:{root:s},_tokens:{[e]:this.#e[e]}}),this}addColors(e){const s=o(e),{variables:h,tokens:i}=r(s,"color",this.#e);return this.#e=t({},this.#e,{colors:i,_variables:{root:h},_tokens:{colors:s}}),this}addColorModes(e,h){const i=s(h,(e=>o(e))),{tokens:n,variables:a}=r(s(t({},this.#e.modes?.[e],i[e]),(e=>this.#e.colors[e])),"color",this.#e),c=e=>this.#e._tokens?.colors?.[e];return this.#e=t({},this.#e,{colors:n,modes:i,mode:e,_getColorValue:c,_variables:{mode:a},_tokens:{modes:s(i,(e=>s(e,c)))}}),this}addScale(e,s){return this.#e=t({},this.#e,{[e]:o(s(this.#e))}),this}updateScale(e,s){return this.#e=t({},this.#e,{[e]:s(this.#e[e])}),this}build(){return t({},this.#e,{_variables:{},_tokens:{}})}}function i(e){return new h(e)}export{h as ThemeBuilder,i as createTheme,o as flattenScale,r as serializeTokens};