@codeleap/styles 5.8.1 → 5.8.3
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/package.json +9 -15
- package/package.json.bak +8 -14
- package/src/classes/Cacher.ts +169 -0
- package/src/classes/StaleControl.ts +125 -0
- package/src/classes/StyleCache.ts +116 -0
- package/src/classes/StylePersistor.ts +62 -0
- package/src/{lib → classes}/StyleRegistry.ts +7 -12
- package/src/classes/index.ts +2 -0
- package/src/classes/tests/Cache.spec.ts +371 -0
- package/src/classes/tests/StaleControl.spec.ts +175 -0
- package/src/classes/tests/StyleCache.spec.ts +452 -0
- package/src/classes/tests/StylePersistor.spec.ts +231 -0
- package/src/{lib/constants.ts → constants.ts} +1 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/tests/useCompositionStyles.spec.ts +107 -0
- package/src/hooks/tests/useStyleObserver.spec.ts +89 -0
- package/src/hooks/useCompositionStyles.ts +33 -0
- package/src/hooks/useNestedStylesByKey.ts +13 -0
- package/src/hooks/useStyleObserver.ts +19 -0
- package/src/hooks/useTheme.ts +16 -0
- package/src/index.ts +9 -5
- package/src/lib/createStyles.ts +10 -1
- package/src/lib/createTheme.ts +22 -13
- package/src/lib/index.ts +1 -10
- package/src/lib/tests/createStyles.spec.ts +151 -0
- package/src/tests/colors/baseColors.ts +166 -0
- package/src/tests/colors/darkMode.ts +232 -0
- package/src/tests/colors/lightMode.ts +285 -0
- package/src/tests/measures.ts +31 -0
- package/src/tests/theme.ts +58 -0
- package/src/theme/generateColorScheme.ts +53 -0
- package/src/theme/index.ts +3 -0
- package/src/theme/tests/generateColorScheme.spec.ts +118 -0
- package/src/theme/tests/themeStore.spec.ts +698 -0
- package/src/theme/tests/validateTheme.spec.ts +173 -0
- package/src/{lib → theme}/themeStore.ts +68 -3
- package/src/{lib → theme}/validateTheme.ts +13 -0
- package/src/tools/colors.ts +83 -39
- package/src/tools/deepClone.ts +10 -0
- package/src/tools/deepmerge.ts +10 -0
- package/src/{lib → tools}/hashKey.ts +7 -0
- package/src/tools/index.ts +6 -1
- package/src/tools/minifier.ts +38 -0
- package/src/tools/tests/colors.spec.ts +233 -0
- package/src/tools/tests/deepClone.spec.ts +102 -0
- package/src/tools/tests/deepmerge.spec.ts +155 -0
- package/src/tools/tests/hashKey.spec.ts +69 -0
- package/src/tools/tests/minifier.spec.ts +173 -0
- package/src/types/store.ts +2 -2
- package/src/types/style.ts +3 -3
- package/src/types/theme.ts +4 -4
- package/src/{lib/utils.ts → utils.ts} +3 -3
- package/src/{lib → variants}/borderCreator.ts +2 -2
- package/src/{lib → variants}/createAppVariants.ts +1 -1
- package/src/{lib → variants}/dynamicVariants.ts +1 -1
- package/src/variants/index.ts +6 -0
- package/src/{lib → variants}/spacing.ts +37 -24
- package/src/variants/tests/borderCreator.spec.ts +180 -0
- package/src/variants/tests/dynamicVariants.spec.ts +194 -0
- package/src/variants/tests/spacing.spec.ts +177 -0
- package/src/lib/Cacher.ts +0 -112
- package/src/lib/StaleControl.ts +0 -73
- package/src/lib/StyleCache.ts +0 -81
- package/src/lib/StylePersistor.ts +0 -28
- package/src/lib/hooks.ts +0 -60
- package/src/lib/minifier.ts +0 -20
- /package/src/{lib → tools}/multiplierProperty.ts +0 -0
- /package/src/{lib → variants}/defaultVariants.ts +0 -0
- /package/src/{lib → variants}/mediaQuery.ts +0 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { describe, expect, test, beforeEach } from 'bun:test'
|
|
2
|
+
import { createDynamicVariants } from '../dynamicVariants'
|
|
3
|
+
import { IColors, IBorderRadius, IEffects } from '../../types'
|
|
4
|
+
|
|
5
|
+
const mockTheme = {
|
|
6
|
+
colors: {
|
|
7
|
+
primary: '#007bff',
|
|
8
|
+
secondary: '#6c757d',
|
|
9
|
+
success: '#28a745',
|
|
10
|
+
danger: '#dc3545',
|
|
11
|
+
warning: '#ffc107',
|
|
12
|
+
info: '#17a2b8',
|
|
13
|
+
light: '#f8f9fa',
|
|
14
|
+
dark: '#343a40',
|
|
15
|
+
white: '#ffffff',
|
|
16
|
+
black: '#000000'
|
|
17
|
+
} as IColors,
|
|
18
|
+
radius: {
|
|
19
|
+
none: '0',
|
|
20
|
+
sm: '0.125rem',
|
|
21
|
+
md: '0.375rem',
|
|
22
|
+
lg: '0.5rem',
|
|
23
|
+
xl: '0.75rem',
|
|
24
|
+
'2xl': '1rem',
|
|
25
|
+
'3xl': '1.5rem',
|
|
26
|
+
full: '9999px'
|
|
27
|
+
} as IBorderRadius,
|
|
28
|
+
effects: {
|
|
29
|
+
shadowSm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
30
|
+
shadowMd: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
|
|
31
|
+
shadowLg: '0 10px 15px -3px rgba(0, 0, 0, 0.1)'
|
|
32
|
+
} as IEffects,
|
|
33
|
+
isBrowser: true
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe('createDynamicVariants', () => {
|
|
37
|
+
let dynamicVariants: any
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
dynamicVariants = createDynamicVariants()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('should create color variants', () => {
|
|
44
|
+
expect(dynamicVariants.backgroundColor).toBeDefined()
|
|
45
|
+
expect(dynamicVariants.color).toBeDefined()
|
|
46
|
+
|
|
47
|
+
const bgResult = dynamicVariants.backgroundColor(mockTheme, 'primary')
|
|
48
|
+
expect(bgResult).toEqual({ backgroundColor: '#007bff' })
|
|
49
|
+
|
|
50
|
+
const colorResult = dynamicVariants.color(mockTheme, 'secondary')
|
|
51
|
+
expect(colorResult).toEqual({ color: '#6c757d' })
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('should create border property variants', () => {
|
|
55
|
+
expect(dynamicVariants.borderColor).toBeDefined()
|
|
56
|
+
const borderColorResult = dynamicVariants.borderColor(mockTheme, 'success')
|
|
57
|
+
expect(borderColorResult).toEqual({ borderColor: '#28a745' })
|
|
58
|
+
|
|
59
|
+
expect(dynamicVariants.borderWidth).toBeDefined()
|
|
60
|
+
const borderWidthResult = dynamicVariants.borderWidth(mockTheme, 'md')
|
|
61
|
+
expect(borderWidthResult).toEqual({ borderWidth: '0.375rem' })
|
|
62
|
+
|
|
63
|
+
expect(dynamicVariants.borderRadius).toBeDefined()
|
|
64
|
+
const borderRadiusResult = dynamicVariants.borderRadius(mockTheme, 'lg')
|
|
65
|
+
expect(borderRadiusResult).toEqual({ borderRadius: '0.5rem' })
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('should create directional border variants', () => {
|
|
69
|
+
expect(dynamicVariants.borderTopColor).toBeDefined()
|
|
70
|
+
expect(dynamicVariants.borderRightColor).toBeDefined()
|
|
71
|
+
expect(dynamicVariants.borderBottomColor).toBeDefined()
|
|
72
|
+
expect(dynamicVariants.borderLeftColor).toBeDefined()
|
|
73
|
+
|
|
74
|
+
const topColorResult = dynamicVariants.borderTopColor(mockTheme, 'danger')
|
|
75
|
+
expect(topColorResult).toEqual({ borderTopColor: '#dc3545' })
|
|
76
|
+
|
|
77
|
+
const leftWidthResult = dynamicVariants.borderLeftWidth(mockTheme, 'sm')
|
|
78
|
+
expect(leftWidthResult).toEqual({ borderLeftWidth: '0.125rem' })
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('should create combined border radius variants', () => {
|
|
82
|
+
expect(dynamicVariants.borderTopLeftRadius).toBeDefined()
|
|
83
|
+
expect(dynamicVariants.borderTopRightRadius).toBeDefined()
|
|
84
|
+
expect(dynamicVariants.borderBottomLeftRadius).toBeDefined()
|
|
85
|
+
expect(dynamicVariants.borderBottomRightRadius).toBeDefined()
|
|
86
|
+
|
|
87
|
+
const topLeftResult = dynamicVariants.borderTopLeftRadius(mockTheme, 'xl')
|
|
88
|
+
expect(topLeftResult).toEqual({ borderTopLeftRadius: '0.75rem' })
|
|
89
|
+
|
|
90
|
+
const bottomRightResult = dynamicVariants.borderBottomRightRadius(mockTheme, '2xl')
|
|
91
|
+
expect(bottomRightResult).toEqual({ borderBottomRightRadius: '1rem' })
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('should create cursor variant', () => {
|
|
95
|
+
expect(dynamicVariants.cursor).toBeDefined()
|
|
96
|
+
|
|
97
|
+
const pointerResult = dynamicVariants.cursor(mockTheme, 'pointer')
|
|
98
|
+
expect(pointerResult).toEqual({ cursor: 'pointer' })
|
|
99
|
+
|
|
100
|
+
const notAllowedResult = dynamicVariants.cursor(mockTheme, 'not-allowed')
|
|
101
|
+
expect(notAllowedResult).toEqual({ cursor: 'not-allowed' })
|
|
102
|
+
|
|
103
|
+
const emptyResult = dynamicVariants.cursor(mockTheme, '')
|
|
104
|
+
expect(emptyResult).toEqual({ cursor: '' })
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('should create bg shortcut variant', () => {
|
|
108
|
+
expect(dynamicVariants.bg).toBeDefined()
|
|
109
|
+
|
|
110
|
+
const bgResult = dynamicVariants.bg(mockTheme, 'warning')
|
|
111
|
+
expect(bgResult).toEqual({ backgroundColor: '#ffc107' })
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('should create br shortcut variant', () => {
|
|
115
|
+
expect(dynamicVariants.br).toBeDefined()
|
|
116
|
+
|
|
117
|
+
const brResult = dynamicVariants.br(mockTheme, 'full')
|
|
118
|
+
expect(brResult).toEqual({ borderRadius: '9999px' })
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('should create effect variant', () => {
|
|
122
|
+
expect(dynamicVariants.effect).toBeDefined()
|
|
123
|
+
|
|
124
|
+
const effectResult = dynamicVariants.effect(mockTheme, 'shadowMd')
|
|
125
|
+
expect(effectResult).toEqual('0 4px 6px -1px rgba(0, 0, 0, 0.1)')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
test('should create scale variant', () => {
|
|
129
|
+
expect(dynamicVariants.scale).toBeDefined()
|
|
130
|
+
|
|
131
|
+
// Test in browser environment
|
|
132
|
+
const scaleResult = dynamicVariants.scale(mockTheme, 1.5)
|
|
133
|
+
expect(scaleResult).toEqual({ transform: 'scale(1.5)' })
|
|
134
|
+
|
|
135
|
+
// Test in non-browser environment
|
|
136
|
+
const serverTheme = { ...mockTheme, isBrowser: false }
|
|
137
|
+
const serverScaleResult = dynamicVariants.scale(serverTheme, 0.8)
|
|
138
|
+
expect(serverScaleResult).toEqual({ transform: [{ scale: 0.8 }] })
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test('should handle numeric values for scale', () => {
|
|
142
|
+
const scaleResult = dynamicVariants.scale(mockTheme, 2)
|
|
143
|
+
expect(scaleResult).toEqual({ transform: 'scale(2)' })
|
|
144
|
+
|
|
145
|
+
const decimalResult = dynamicVariants.scale(mockTheme, 1.25)
|
|
146
|
+
expect(decimalResult).toEqual({ transform: 'scale(1.25)' })
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
test('should handle empty string for cursor', () => {
|
|
150
|
+
const result = dynamicVariants.cursor(mockTheme, '')
|
|
151
|
+
expect(result).toEqual({ cursor: '' })
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('should return all expected variant functions', () => {
|
|
155
|
+
const expectedVariants = [
|
|
156
|
+
'backgroundColor',
|
|
157
|
+
'color',
|
|
158
|
+
'borderColor',
|
|
159
|
+
'borderWidth',
|
|
160
|
+
'borderRadius',
|
|
161
|
+
'borderTopColor',
|
|
162
|
+
'borderRightColor',
|
|
163
|
+
'borderBottomColor',
|
|
164
|
+
'borderLeftColor',
|
|
165
|
+
'borderTopWidth',
|
|
166
|
+
'borderRightWidth',
|
|
167
|
+
'borderBottomWidth',
|
|
168
|
+
'borderLeftWidth',
|
|
169
|
+
'borderTopRadius',
|
|
170
|
+
'borderRightRadius',
|
|
171
|
+
'borderBottomRadius',
|
|
172
|
+
'borderLeftRadius',
|
|
173
|
+
'borderTopLeftRadius',
|
|
174
|
+
'borderTopRightRadius',
|
|
175
|
+
'borderBottomLeftRadius',
|
|
176
|
+
'borderBottomRightRadius',
|
|
177
|
+
'cursor',
|
|
178
|
+
'bg',
|
|
179
|
+
'effect',
|
|
180
|
+
'scale',
|
|
181
|
+
'br'
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
expectedVariants.forEach(variant => {
|
|
185
|
+
expect(dynamicVariants[variant]).toBeDefined()
|
|
186
|
+
expect(typeof dynamicVariants[variant]).toBe('function')
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('should handle non-existent color gracefully', () => {
|
|
191
|
+
const result = dynamicVariants.backgroundColor(mockTheme, 'nonexistent')
|
|
192
|
+
expect(result).toHaveProperty('backgroundColor')
|
|
193
|
+
})
|
|
194
|
+
})
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
2
|
+
import { spacingFactory } from '../spacing'
|
|
3
|
+
import { ICSS } from '../../types'
|
|
4
|
+
|
|
5
|
+
describe('spacing', () => {
|
|
6
|
+
const base = 8
|
|
7
|
+
const property = 'margin'
|
|
8
|
+
|
|
9
|
+
test('should create basic spacing function', () => {
|
|
10
|
+
const margin = spacingFactory(base, property, false)
|
|
11
|
+
|
|
12
|
+
expect(margin.margin).toBeDefined()
|
|
13
|
+
expect(typeof margin.margin).toBe('function')
|
|
14
|
+
|
|
15
|
+
const result = margin.margin(2) as ICSS
|
|
16
|
+
expect(result).toEqual({
|
|
17
|
+
marginTop: 16,
|
|
18
|
+
marginRight: 16,
|
|
19
|
+
marginBottom: 16,
|
|
20
|
+
marginLeft: 16
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('should handle string numbers', () => {
|
|
25
|
+
const margin = spacingFactory(base, property, false)
|
|
26
|
+
|
|
27
|
+
const result = margin.margin('2') as ICSS
|
|
28
|
+
expect(result).toEqual({
|
|
29
|
+
marginTop: 16,
|
|
30
|
+
marginRight: 16,
|
|
31
|
+
marginBottom: 16,
|
|
32
|
+
marginLeft: 16
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('should create all spacing variants', () => {
|
|
37
|
+
const margin = spacingFactory(base, property, false)
|
|
38
|
+
|
|
39
|
+
// Test all long form variants
|
|
40
|
+
expect(margin.marginTop(2)).toEqual({ marginTop: 16 })
|
|
41
|
+
expect(margin.marginRight(2)).toEqual({ marginRight: 16 })
|
|
42
|
+
expect(margin.marginBottom(2)).toEqual({ marginBottom: 16 })
|
|
43
|
+
expect(margin.marginLeft(2)).toEqual({ marginLeft: 16 })
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('should work with short form notation', () => {
|
|
47
|
+
const margin = spacingFactory(base, 'm', true)
|
|
48
|
+
|
|
49
|
+
// Test short form variants
|
|
50
|
+
expect(margin.mt(2)).toEqual({ marginTop: 16 })
|
|
51
|
+
expect(margin.mr(2)).toEqual({ marginRight: 16 })
|
|
52
|
+
expect(margin.mb(2)).toEqual({ marginBottom: 16 })
|
|
53
|
+
expect(margin.ml(2)).toEqual({ marginLeft: 16 })
|
|
54
|
+
expect(margin.mx(2)).toEqual({ marginLeft: 16, marginRight: 16 })
|
|
55
|
+
expect(margin.my(2)).toEqual({ marginTop: 16, marginBottom: 16 })
|
|
56
|
+
expect(margin.m(2)).toEqual({ marginTop: 16, marginBottom: 16, marginLeft: 16, marginRight: 16 })
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('should handle horizontal and vertical shortcuts', () => {
|
|
60
|
+
const margin = spacingFactory(base, 'm', true)
|
|
61
|
+
|
|
62
|
+
const horizontalResult = margin.mx(2) as ICSS
|
|
63
|
+
expect(horizontalResult).toEqual({
|
|
64
|
+
marginLeft: 16,
|
|
65
|
+
marginRight: 16
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const verticalResult = margin.my(2) as ICSS
|
|
69
|
+
expect(verticalResult).toEqual({
|
|
70
|
+
marginTop: 16,
|
|
71
|
+
marginBottom: 16
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('should handle "auto" values', () => {
|
|
76
|
+
const margin = spacingFactory(base, property, false)
|
|
77
|
+
|
|
78
|
+
const result = margin.margin('auto') as ICSS
|
|
79
|
+
expect(result).toEqual({
|
|
80
|
+
marginTop: 'auto',
|
|
81
|
+
marginRight: 'auto',
|
|
82
|
+
marginBottom: 'auto',
|
|
83
|
+
marginLeft: 'auto'
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const topResult = margin.marginTop('auto') as ICSS
|
|
87
|
+
expect(topResult).toEqual({ marginTop: 'auto' })
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('should work with padding property', () => {
|
|
91
|
+
const padding = spacingFactory(base, 'padding', false)
|
|
92
|
+
|
|
93
|
+
expect(padding.padding(2)).toEqual({
|
|
94
|
+
paddingTop: 16,
|
|
95
|
+
paddingRight: 16,
|
|
96
|
+
paddingBottom: 16,
|
|
97
|
+
paddingLeft: 16
|
|
98
|
+
})
|
|
99
|
+
expect(padding.paddingTop(2)).toEqual({ paddingTop: 16 })
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test('should work with short form padding', () => {
|
|
103
|
+
const padding = spacingFactory(base, 'p', true)
|
|
104
|
+
|
|
105
|
+
expect(padding.pt(2)).toEqual({ paddingTop: 16 })
|
|
106
|
+
expect(padding.px(2)).toEqual({ paddingLeft: 16, paddingRight: 16 })
|
|
107
|
+
expect(padding.p(2)).toEqual({ paddingLeft: 16, paddingRight: 16, paddingBottom: 16, paddingTop: 16 })
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('should handle decimal multipliers', () => {
|
|
111
|
+
const margin = spacingFactory(base, property, false)
|
|
112
|
+
|
|
113
|
+
const result = margin.margin(0.5) as ICSS
|
|
114
|
+
expect(result).toEqual({
|
|
115
|
+
marginTop: 4,
|
|
116
|
+
marginRight: 4,
|
|
117
|
+
marginBottom: 4,
|
|
118
|
+
marginLeft: 4
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('should handle zero values', () => {
|
|
123
|
+
const margin = spacingFactory(base, property, false)
|
|
124
|
+
|
|
125
|
+
const result = margin.margin(0) as ICSS
|
|
126
|
+
expect(result).toEqual({
|
|
127
|
+
marginTop: 0,
|
|
128
|
+
marginRight: 0,
|
|
129
|
+
marginBottom: 0,
|
|
130
|
+
marginLeft: 0
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
test('should return correct structure with all properties', () => {
|
|
135
|
+
const margin = spacingFactory(base, property, false)
|
|
136
|
+
|
|
137
|
+
// Check that all expected properties exist
|
|
138
|
+
expect(margin).toHaveProperty('margin')
|
|
139
|
+
expect(margin).toHaveProperty('marginTop')
|
|
140
|
+
expect(margin).toHaveProperty('marginRight')
|
|
141
|
+
expect(margin).toHaveProperty('marginBottom')
|
|
142
|
+
expect(margin).toHaveProperty('marginLeft')
|
|
143
|
+
|
|
144
|
+
// Check that they are functions
|
|
145
|
+
expect(typeof margin.margin).toBe('function')
|
|
146
|
+
expect(typeof margin.marginTop).toBe('function')
|
|
147
|
+
expect(typeof margin.marginRight).toBe('function')
|
|
148
|
+
expect(typeof margin.marginBottom).toBe('function')
|
|
149
|
+
expect(typeof margin.marginLeft).toBe('function')
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('should handle edge cases with invalid numbers', () => {
|
|
153
|
+
const margin = spacingFactory(base, property, false)
|
|
154
|
+
|
|
155
|
+
// Should handle NaN by converting to NaN (since Number('invalid') returns NaN)
|
|
156
|
+
const result = margin.margin('invalid') as ICSS
|
|
157
|
+
expect(result).toEqual({
|
|
158
|
+
marginTop: NaN,
|
|
159
|
+
marginRight: NaN,
|
|
160
|
+
marginBottom: NaN,
|
|
161
|
+
marginLeft: NaN
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
test('should handle empty string position for full spacing', () => {
|
|
166
|
+
const margin = spacingFactory(base, property, false)
|
|
167
|
+
|
|
168
|
+
// This tests the case where position is empty string
|
|
169
|
+
const result = margin.margin(2) as ICSS
|
|
170
|
+
expect(result).toEqual({
|
|
171
|
+
marginTop: 16,
|
|
172
|
+
marginRight: 16,
|
|
173
|
+
marginBottom: 16,
|
|
174
|
+
marginLeft: 16
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
})
|
package/src/lib/Cacher.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { CacheType } from '../types/cache'
|
|
2
|
-
import { StyleConstants } from './constants'
|
|
3
|
-
import { hashKey } from './hashKey'
|
|
4
|
-
import { StateStorage } from '../types/store'
|
|
5
|
-
|
|
6
|
-
function getStaleTime() {
|
|
7
|
-
const time = 7
|
|
8
|
-
|
|
9
|
-
let currentTime = new Date()
|
|
10
|
-
|
|
11
|
-
currentTime.setDate(currentTime.getDate() + time)
|
|
12
|
-
|
|
13
|
-
return currentTime
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export class Cache<T extends any = any> {
|
|
17
|
-
cache: Record<string, T> = {}
|
|
18
|
-
|
|
19
|
-
get persistKeyCache() {
|
|
20
|
-
return `@styles.caches.${this.registryName}.cache`
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get persistKeyStaleTime() {
|
|
24
|
-
return `@styles.caches.${this.registryName}.staleTime`
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
constructor(
|
|
28
|
-
public registryName: CacheType,
|
|
29
|
-
private storage: StateStorage = null,
|
|
30
|
-
public persistCache: boolean = !!storage,
|
|
31
|
-
) {
|
|
32
|
-
if (!persistCache || !StyleConstants.STORE_CACHE_ENABLED) return
|
|
33
|
-
|
|
34
|
-
const { persistedCache, persistedStaleTime } = this.loadStorage()
|
|
35
|
-
|
|
36
|
-
const currentTime = new Date()
|
|
37
|
-
|
|
38
|
-
const isStaled = currentTime > persistedStaleTime
|
|
39
|
-
|
|
40
|
-
if (isStaled) {
|
|
41
|
-
this.clearStorage()
|
|
42
|
-
return
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
this.setCache(persistedCache)
|
|
46
|
-
this.storeStaleTime(persistedStaleTime)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
keyFor(cacheBaseKey: string, data: Array<any> | any) {
|
|
50
|
-
const values = [cacheBaseKey, data]
|
|
51
|
-
|
|
52
|
-
const cacheKey = hashKey(values)
|
|
53
|
-
const cachedValue = this.cache[cacheKey] ?? null
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
key: cacheKey,
|
|
57
|
-
value: cachedValue,
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
cacheFor(key: string, cache: T) {
|
|
62
|
-
this.cache[key] = cache
|
|
63
|
-
if (this.persistCache) this.storeCache()
|
|
64
|
-
return cache
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// utils
|
|
68
|
-
|
|
69
|
-
setCache(cache: Record<string, T>) {
|
|
70
|
-
this.cache = cache ?? {}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
clear() {
|
|
74
|
-
this.cache = {}
|
|
75
|
-
this.clearStorage()
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// storage
|
|
79
|
-
|
|
80
|
-
loadStorage() {
|
|
81
|
-
if (!this.persistCache) return
|
|
82
|
-
|
|
83
|
-
const persistedStaleTime = this.storage.getItem(this.persistKeyStaleTime)
|
|
84
|
-
const persistedCache = JSON.parse(this.storage.getItem(this.persistKeyCache))
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
persistedStaleTime: !persistedStaleTime ? getStaleTime() : new Date(persistedStaleTime),
|
|
88
|
-
persistedCache,
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
clearStorage() {
|
|
93
|
-
if (!this.persistCache) return
|
|
94
|
-
|
|
95
|
-
this.storage.removeItem(this.persistKeyStaleTime)
|
|
96
|
-
this.storage.removeItem(this.persistKeyCache)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
storeCache(cache: Record<string, T> = null) {
|
|
100
|
-
if (!this.persistCache) return
|
|
101
|
-
|
|
102
|
-
const value = JSON.stringify(cache ?? this.cache)
|
|
103
|
-
this.storage.setItem(this.persistKeyCache, value)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
storeStaleTime(staleTime: Date) {
|
|
107
|
-
if (!this.persistCache) return
|
|
108
|
-
|
|
109
|
-
const value = staleTime.toISOString()
|
|
110
|
-
this.storage.setItem(this.persistKeyStaleTime, value)
|
|
111
|
-
}
|
|
112
|
-
}
|
package/src/lib/StaleControl.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export class StaleControl {
|
|
3
|
-
private wiperId: NodeJS.Timer = null
|
|
4
|
-
|
|
5
|
-
constructor(
|
|
6
|
-
private staleTime: number = 60, // minutes
|
|
7
|
-
private staleTimeIdentifier: string = '//:',
|
|
8
|
-
private wiperInterval: number = 30 * 60 * 1000, // 30 minutes
|
|
9
|
-
) {}
|
|
10
|
-
|
|
11
|
-
isStaled(value: string) {
|
|
12
|
-
const { staleTime } = this.extractStaleTime(value)
|
|
13
|
-
|
|
14
|
-
const currentTime = new Date()
|
|
15
|
-
|
|
16
|
-
const isStaled = currentTime > staleTime
|
|
17
|
-
|
|
18
|
-
return isStaled
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
insertStaleTime(value: string) {
|
|
22
|
-
let currentTime = new Date()
|
|
23
|
-
|
|
24
|
-
currentTime.setMinutes(currentTime.getMinutes() + this.staleTime)
|
|
25
|
-
|
|
26
|
-
const staleTime = currentTime.toISOString()
|
|
27
|
-
|
|
28
|
-
const valueWithStaleTime = `${value}${this.staleTimeIdentifier}${staleTime}`
|
|
29
|
-
|
|
30
|
-
return valueWithStaleTime
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
refreshStaleTime(value: string) {
|
|
34
|
-
const { value: extractedValue } = this.extractStaleTime(value)
|
|
35
|
-
|
|
36
|
-
const refreshedValue = this.insertStaleTime(extractedValue)
|
|
37
|
-
|
|
38
|
-
return refreshedValue
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
extractStaleTime(value: string) {
|
|
42
|
-
const [extractedValue, _staleTime] = value?.split(this.staleTimeIdentifier)
|
|
43
|
-
|
|
44
|
-
const staleTime = new Date(_staleTime)
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
staleTime,
|
|
48
|
-
value: extractedValue,
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* wipe staled cache; verify isStaled values and remove
|
|
54
|
-
*/
|
|
55
|
-
cacheWiper() {
|
|
56
|
-
throw new Error('Cache Wiper not implement')
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
registerCacheWiper() {
|
|
60
|
-
if (this.wiperId !== null) {
|
|
61
|
-
this.unregisterCacheWiper()
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
this.wiperId = setInterval(() => {
|
|
65
|
-
this.cacheWiper()
|
|
66
|
-
}, this.wiperInterval)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
unregisterCacheWiper() {
|
|
70
|
-
clearInterval(this.wiperId)
|
|
71
|
-
this.wiperId = null
|
|
72
|
-
}
|
|
73
|
-
}
|
package/src/lib/StyleCache.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { Cache } from './Cacher'
|
|
2
|
-
import { hashKey } from './hashKey'
|
|
3
|
-
import { StyleConstants } from './constants'
|
|
4
|
-
import { CacheType } from '../types/cache'
|
|
5
|
-
import { minifier } from './minifier'
|
|
6
|
-
import { StateStorage } from '../types/store'
|
|
7
|
-
|
|
8
|
-
export class StyleCache {
|
|
9
|
-
baseKey: string
|
|
10
|
-
|
|
11
|
-
styles = new Cache('styles')
|
|
12
|
-
|
|
13
|
-
compositions = new Cache('compositions')
|
|
14
|
-
|
|
15
|
-
responsive = new Cache('responsive')
|
|
16
|
-
|
|
17
|
-
variants: Cache
|
|
18
|
-
|
|
19
|
-
common: Cache
|
|
20
|
-
|
|
21
|
-
components: Cache
|
|
22
|
-
|
|
23
|
-
constructor(storage: StateStorage) {
|
|
24
|
-
this.variants = new Cache('variants', storage)
|
|
25
|
-
this.common = new Cache('common', storage)
|
|
26
|
-
this.components = new Cache('components', storage)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
registerBaseKey(keys: Array<any>) {
|
|
30
|
-
keys.push(StyleConstants.STORES_PERSIST_VERSION)
|
|
31
|
-
|
|
32
|
-
const baseKey = hashKey(keys)
|
|
33
|
-
|
|
34
|
-
this.baseKey = baseKey
|
|
35
|
-
|
|
36
|
-
return baseKey
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
wipeCache() {
|
|
40
|
-
this.components.clear()
|
|
41
|
-
this.responsive.clear()
|
|
42
|
-
this.compositions.clear()
|
|
43
|
-
this.variants.clear()
|
|
44
|
-
this.common.clear()
|
|
45
|
-
this.styles.clear()
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
keyFor(type: CacheType, keyData: Array<any> | any) {
|
|
49
|
-
const cache = this[type]
|
|
50
|
-
|
|
51
|
-
const withFunctionsHash = Object.values(keyData).map((value) => {
|
|
52
|
-
if (typeof value === 'function') {
|
|
53
|
-
return value.toString()
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return value
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
const values = [this.baseKey, ...withFunctionsHash]
|
|
60
|
-
|
|
61
|
-
const cacheKey = hashKey(values)
|
|
62
|
-
const cachedValue = minifier.decompress(cache.cache[cacheKey] ?? null)
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
key: cacheKey,
|
|
66
|
-
value: cachedValue,
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
cacheFor(type: CacheType, key: string, value: any) {
|
|
71
|
-
if (!StyleConstants.CACHE_ENABLED) {
|
|
72
|
-
return value
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const cache = this[type]
|
|
76
|
-
|
|
77
|
-
const minifiedValue = minifier.compress(value)
|
|
78
|
-
|
|
79
|
-
return cache.cacheFor(key, minifiedValue)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { StateStorage } from '../types/store'
|
|
2
|
-
import { minifier } from './minifier'
|
|
3
|
-
|
|
4
|
-
export type StoragePersistor = {
|
|
5
|
-
set: (key: string, value: any) => void
|
|
6
|
-
get: (key: string) => any
|
|
7
|
-
del: (key: string) => void
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class StylePersistor implements StateStorage {
|
|
11
|
-
constructor(
|
|
12
|
-
private storage: StoragePersistor
|
|
13
|
-
) {}
|
|
14
|
-
|
|
15
|
-
setItem(name: string, value: string): void {
|
|
16
|
-
return this.storage.set(name, value)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
getItem(name: string): string | null {
|
|
20
|
-
const persistedValue = this.storage?.get(name)
|
|
21
|
-
|
|
22
|
-
return minifier.decompress(persistedValue ?? null)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
removeItem(name: string): void {
|
|
26
|
-
return this.storage.del(name)
|
|
27
|
-
}
|
|
28
|
-
}
|