@furystack/shades 11.0.35 → 11.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +86 -0
- package/esm/compile-route.spec.d.ts +2 -0
- package/esm/compile-route.spec.d.ts.map +1 -0
- package/esm/compile-route.spec.js +34 -0
- package/esm/compile-route.spec.js.map +1 -0
- package/esm/components/route-link.d.ts.map +1 -1
- package/esm/components/route-link.js +4 -5
- package/esm/components/route-link.js.map +1 -1
- package/esm/components/route-link.spec.js +1 -1
- package/esm/components/route-link.spec.js.map +1 -1
- package/esm/css-generator.d.ts +50 -0
- package/esm/css-generator.d.ts.map +1 -0
- package/esm/css-generator.js +107 -0
- package/esm/css-generator.js.map +1 -0
- package/esm/css-generator.spec.d.ts +2 -0
- package/esm/css-generator.spec.d.ts.map +1 -0
- package/esm/css-generator.spec.js +162 -0
- package/esm/css-generator.spec.js.map +1 -0
- package/esm/index.d.ts +2 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +2 -0
- package/esm/index.js.map +1 -1
- package/esm/models/css-object.d.ts +33 -0
- package/esm/models/css-object.d.ts.map +1 -0
- package/esm/models/css-object.js +2 -0
- package/esm/models/css-object.js.map +1 -0
- package/esm/models/index.d.ts +1 -0
- package/esm/models/index.d.ts.map +1 -1
- package/esm/models/index.js +1 -0
- package/esm/models/index.js.map +1 -1
- package/esm/shade.d.ts +18 -2
- package/esm/shade.d.ts.map +1 -1
- package/esm/shade.js +8 -0
- package/esm/shade.js.map +1 -1
- package/esm/shade.spec.d.ts +2 -0
- package/esm/shade.spec.d.ts.map +1 -0
- package/esm/shade.spec.js +197 -0
- package/esm/shade.spec.js.map +1 -0
- package/esm/style-manager.d.ts +65 -0
- package/esm/style-manager.d.ts.map +1 -0
- package/esm/style-manager.js +95 -0
- package/esm/style-manager.js.map +1 -0
- package/esm/style-manager.spec.d.ts +2 -0
- package/esm/style-manager.spec.d.ts.map +1 -0
- package/esm/style-manager.spec.js +179 -0
- package/esm/style-manager.spec.js.map +1 -0
- package/esm/styled-element.spec.d.ts +2 -0
- package/esm/styled-element.spec.d.ts.map +1 -0
- package/esm/styled-element.spec.js +86 -0
- package/esm/styled-element.spec.js.map +1 -0
- package/esm/styled-shade.spec.d.ts +2 -0
- package/esm/styled-shade.spec.d.ts.map +1 -0
- package/esm/styled-shade.spec.js +66 -0
- package/esm/styled-shade.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/compile-route.spec.ts +39 -0
- package/src/components/route-link.spec.tsx +1 -1
- package/src/components/route-link.tsx +4 -5
- package/src/css-generator.spec.ts +183 -0
- package/src/css-generator.ts +117 -0
- package/src/index.ts +2 -0
- package/src/models/css-object.ts +34 -0
- package/src/models/index.ts +1 -0
- package/src/shade.spec.tsx +238 -0
- package/src/shade.ts +29 -2
- package/src/style-manager.spec.ts +229 -0
- package/src/style-manager.ts +104 -0
- package/src/styled-element.spec.tsx +117 -0
- package/src/styled-shade.spec.ts +86 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { Shade } from './shade.js';
|
|
3
|
+
import { StyleManager } from './style-manager.js';
|
|
4
|
+
describe('StyleManager', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
StyleManager.clear();
|
|
7
|
+
});
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
StyleManager.clear();
|
|
10
|
+
});
|
|
11
|
+
describe('registerComponentStyles', () => {
|
|
12
|
+
it('should register styles for a component', () => {
|
|
13
|
+
const result = StyleManager.registerComponentStyles('test-component', {
|
|
14
|
+
color: 'red',
|
|
15
|
+
padding: '10px',
|
|
16
|
+
});
|
|
17
|
+
expect(result).toBe(true);
|
|
18
|
+
expect(StyleManager.isRegistered('test-component')).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it('should inject CSS into a style element', () => {
|
|
21
|
+
StyleManager.registerComponentStyles('test-component', {
|
|
22
|
+
color: 'red',
|
|
23
|
+
});
|
|
24
|
+
const styleElement = document.querySelector('[data-shades-styles]');
|
|
25
|
+
expect(styleElement).not.toBeNull();
|
|
26
|
+
expect(styleElement?.textContent).toContain('test-component');
|
|
27
|
+
expect(styleElement?.textContent).toContain('color: red');
|
|
28
|
+
});
|
|
29
|
+
it('should not register the same component twice', () => {
|
|
30
|
+
const result1 = StyleManager.registerComponentStyles('test-component', {
|
|
31
|
+
color: 'red',
|
|
32
|
+
});
|
|
33
|
+
const result2 = StyleManager.registerComponentStyles('test-component', {
|
|
34
|
+
color: 'blue',
|
|
35
|
+
});
|
|
36
|
+
expect(result1).toBe(true);
|
|
37
|
+
expect(result2).toBe(false);
|
|
38
|
+
// Should only have the first style
|
|
39
|
+
const styleElement = document.querySelector('[data-shades-styles]');
|
|
40
|
+
expect(styleElement?.textContent).toContain('color: red');
|
|
41
|
+
expect(styleElement?.textContent).not.toContain('color: blue');
|
|
42
|
+
});
|
|
43
|
+
it('should handle pseudo-selectors', () => {
|
|
44
|
+
StyleManager.registerComponentStyles('test-button', {
|
|
45
|
+
backgroundColor: 'blue',
|
|
46
|
+
'&:hover': { backgroundColor: 'darkblue' },
|
|
47
|
+
});
|
|
48
|
+
const styleElement = document.querySelector('[data-shades-styles]');
|
|
49
|
+
expect(styleElement?.textContent).toContain('test-button:hover');
|
|
50
|
+
expect(styleElement?.textContent).toContain('background-color: darkblue');
|
|
51
|
+
});
|
|
52
|
+
it('should return false for empty CSS object', () => {
|
|
53
|
+
const result = StyleManager.registerComponentStyles('empty-component', {});
|
|
54
|
+
expect(result).toBe(false);
|
|
55
|
+
expect(StyleManager.isRegistered('empty-component')).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
it('should add comments with component name', () => {
|
|
58
|
+
StyleManager.registerComponentStyles('my-component', {
|
|
59
|
+
color: 'red',
|
|
60
|
+
});
|
|
61
|
+
const styleElement = document.querySelector('[data-shades-styles]');
|
|
62
|
+
expect(styleElement?.textContent).toContain('/* my-component */');
|
|
63
|
+
});
|
|
64
|
+
it('should generate attribute selector for customized built-in elements', () => {
|
|
65
|
+
StyleManager.registerComponentStyles('my-link', {
|
|
66
|
+
color: 'blue',
|
|
67
|
+
textDecoration: 'none',
|
|
68
|
+
}, 'a');
|
|
69
|
+
const styleElement = document.querySelector('[data-shades-styles]');
|
|
70
|
+
expect(styleElement?.textContent).toContain('a[is="my-link"]');
|
|
71
|
+
expect(styleElement?.textContent).toContain('color: blue');
|
|
72
|
+
expect(styleElement?.textContent).toContain('text-decoration: none');
|
|
73
|
+
});
|
|
74
|
+
it('should handle pseudo-selectors for customized built-in elements', () => {
|
|
75
|
+
StyleManager.registerComponentStyles('my-button', {
|
|
76
|
+
backgroundColor: 'gray',
|
|
77
|
+
'&:hover': { backgroundColor: 'darkgray' },
|
|
78
|
+
'&:active': { transform: 'scale(0.98)' },
|
|
79
|
+
}, 'button');
|
|
80
|
+
const styleElement = document.querySelector('[data-shades-styles]');
|
|
81
|
+
expect(styleElement?.textContent).toContain('button[is="my-button"]');
|
|
82
|
+
expect(styleElement?.textContent).toContain('button[is="my-button"]:hover');
|
|
83
|
+
expect(styleElement?.textContent).toContain('button[is="my-button"]:active');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('isRegistered', () => {
|
|
87
|
+
it('should return true for registered components', () => {
|
|
88
|
+
StyleManager.registerComponentStyles('test-component', { color: 'red' });
|
|
89
|
+
expect(StyleManager.isRegistered('test-component')).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
it('should return false for unregistered components', () => {
|
|
92
|
+
expect(StyleManager.isRegistered('unknown-component')).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('getRegisteredComponents', () => {
|
|
96
|
+
it('should return all registered component names', () => {
|
|
97
|
+
StyleManager.registerComponentStyles('component-a', { color: 'red' });
|
|
98
|
+
StyleManager.registerComponentStyles('component-b', { color: 'blue' });
|
|
99
|
+
const registered = StyleManager.getRegisteredComponents();
|
|
100
|
+
expect(registered.has('component-a')).toBe(true);
|
|
101
|
+
expect(registered.has('component-b')).toBe(true);
|
|
102
|
+
expect(registered.size).toBe(2);
|
|
103
|
+
});
|
|
104
|
+
it('should return empty set when no components registered', () => {
|
|
105
|
+
const registered = StyleManager.getRegisteredComponents();
|
|
106
|
+
expect(registered.size).toBe(0);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('clear', () => {
|
|
110
|
+
it('should clear all registered components', () => {
|
|
111
|
+
StyleManager.registerComponentStyles('test-component', { color: 'red' });
|
|
112
|
+
expect(StyleManager.isRegistered('test-component')).toBe(true);
|
|
113
|
+
StyleManager.clear();
|
|
114
|
+
expect(StyleManager.isRegistered('test-component')).toBe(false);
|
|
115
|
+
expect(StyleManager.getRegisteredComponents().size).toBe(0);
|
|
116
|
+
});
|
|
117
|
+
it('should remove style element on clear', () => {
|
|
118
|
+
StyleManager.registerComponentStyles('test-component', { color: 'red' });
|
|
119
|
+
let styleElement = document.querySelector('[data-shades-styles]');
|
|
120
|
+
expect(styleElement).not.toBeNull();
|
|
121
|
+
StyleManager.clear();
|
|
122
|
+
styleElement = document.querySelector('[data-shades-styles]');
|
|
123
|
+
expect(styleElement).toBeNull();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('reusing style element', () => {
|
|
127
|
+
it('should use the same style element for multiple components', () => {
|
|
128
|
+
StyleManager.registerComponentStyles('component-a', { color: 'red' });
|
|
129
|
+
StyleManager.registerComponentStyles('component-b', { color: 'blue' });
|
|
130
|
+
const styleElements = document.querySelectorAll('[data-shades-styles]');
|
|
131
|
+
expect(styleElements.length).toBe(1);
|
|
132
|
+
const styleElement = styleElements[0];
|
|
133
|
+
expect(styleElement?.textContent).toContain('component-a');
|
|
134
|
+
expect(styleElement?.textContent).toContain('component-b');
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
describe('Shade integration', () => {
|
|
138
|
+
it('should register CSS styles when Shade component is created with css property', () => {
|
|
139
|
+
Shade({
|
|
140
|
+
shadowDomName: 'shade-css-test-component',
|
|
141
|
+
css: {
|
|
142
|
+
color: 'red',
|
|
143
|
+
padding: '10px',
|
|
144
|
+
'&:hover': { color: 'blue' },
|
|
145
|
+
},
|
|
146
|
+
render: () => null,
|
|
147
|
+
});
|
|
148
|
+
expect(StyleManager.isRegistered('shade-css-test-component')).toBe(true);
|
|
149
|
+
const styleElement = document.querySelector('[data-shades-styles]');
|
|
150
|
+
expect(styleElement?.textContent).toContain('shade-css-test-component');
|
|
151
|
+
expect(styleElement?.textContent).toContain('color: red');
|
|
152
|
+
expect(styleElement?.textContent).toContain('shade-css-test-component:hover');
|
|
153
|
+
});
|
|
154
|
+
it('should register CSS with attribute selector for customized built-in elements', () => {
|
|
155
|
+
Shade({
|
|
156
|
+
shadowDomName: 'shade-css-test-button',
|
|
157
|
+
elementBase: HTMLButtonElement,
|
|
158
|
+
elementBaseName: 'button',
|
|
159
|
+
css: {
|
|
160
|
+
backgroundColor: 'blue',
|
|
161
|
+
'&:hover': { backgroundColor: 'darkblue' },
|
|
162
|
+
},
|
|
163
|
+
render: () => null,
|
|
164
|
+
});
|
|
165
|
+
expect(StyleManager.isRegistered('shade-css-test-button')).toBe(true);
|
|
166
|
+
const styleElement = document.querySelector('[data-shades-styles]');
|
|
167
|
+
expect(styleElement?.textContent).toContain('button[is="shade-css-test-button"]');
|
|
168
|
+
expect(styleElement?.textContent).toContain('button[is="shade-css-test-button"]:hover');
|
|
169
|
+
});
|
|
170
|
+
it('should not register styles when Shade component has no css property', () => {
|
|
171
|
+
Shade({
|
|
172
|
+
shadowDomName: 'shade-no-css-component',
|
|
173
|
+
render: () => null,
|
|
174
|
+
});
|
|
175
|
+
expect(StyleManager.isRegistered('shade-no-css-component')).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
//# sourceMappingURL=style-manager.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style-manager.spec.js","sourceRoot":"","sources":["../src/style-manager.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styled-element.spec.d.ts","sourceRoot":"","sources":["../src/styled-element.spec.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { styledElement } from './styled-element.js';
|
|
3
|
+
describe('styled-element', () => {
|
|
4
|
+
describe('styledElement', () => {
|
|
5
|
+
it('should apply additional styles to an intrinsic element', () => {
|
|
6
|
+
const additionalStyles = { color: 'red', padding: '10px' };
|
|
7
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
8
|
+
const result = StyledDiv({}, []);
|
|
9
|
+
expect(result.style.color).toBe('red');
|
|
10
|
+
expect(result.style.padding).toBe('10px');
|
|
11
|
+
});
|
|
12
|
+
it('should merge styles when element already has styles', () => {
|
|
13
|
+
const additionalStyles = { color: 'red' };
|
|
14
|
+
const existingStyles = { backgroundColor: 'blue' };
|
|
15
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
16
|
+
const result = StyledDiv({ style: existingStyles }, []);
|
|
17
|
+
expect(result.style.backgroundColor).toBe('blue');
|
|
18
|
+
expect(result.style.color).toBe('red');
|
|
19
|
+
});
|
|
20
|
+
it('should override existing styles with additional styles', () => {
|
|
21
|
+
const additionalStyles = { color: 'red' };
|
|
22
|
+
const existingStyles = { color: 'blue' };
|
|
23
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
24
|
+
const result = StyledDiv({ style: existingStyles }, []);
|
|
25
|
+
expect(result.style.color).toBe('red');
|
|
26
|
+
});
|
|
27
|
+
it('should preserve original props', () => {
|
|
28
|
+
const additionalStyles = { color: 'red' };
|
|
29
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
30
|
+
const result = StyledDiv({ className: 'my-class', id: 'my-id' }, []);
|
|
31
|
+
expect(result.className).toBe('my-class');
|
|
32
|
+
expect(result.id).toBe('my-id');
|
|
33
|
+
expect(result.style.color).toBe('red');
|
|
34
|
+
});
|
|
35
|
+
it('should pass children correctly', () => {
|
|
36
|
+
const additionalStyles = { color: 'red' };
|
|
37
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
38
|
+
const child1 = document.createElement('span');
|
|
39
|
+
child1.textContent = 'child1';
|
|
40
|
+
const child2 = document.createElement('span');
|
|
41
|
+
child2.textContent = 'child2';
|
|
42
|
+
const result = StyledDiv({}, [child1, child2]);
|
|
43
|
+
expect(result.children.length).toBe(2);
|
|
44
|
+
expect(result.children[0]).toBe(child1);
|
|
45
|
+
expect(result.children[1]).toBe(child2);
|
|
46
|
+
});
|
|
47
|
+
it('should handle text children', () => {
|
|
48
|
+
const additionalStyles = { color: 'red' };
|
|
49
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
50
|
+
const result = StyledDiv({}, ['Hello', ' ', 'World']);
|
|
51
|
+
expect(result.textContent).toBe('Hello World');
|
|
52
|
+
});
|
|
53
|
+
it('should return an HTMLElement', () => {
|
|
54
|
+
const additionalStyles = { color: 'red' };
|
|
55
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
56
|
+
const result = StyledDiv({}, []);
|
|
57
|
+
expect(result).toBeInstanceOf(HTMLElement);
|
|
58
|
+
expect(result.tagName.toLowerCase()).toBe('div');
|
|
59
|
+
});
|
|
60
|
+
it('should work with different element types', () => {
|
|
61
|
+
const spanStyles = { fontWeight: 'bold' };
|
|
62
|
+
const buttonStyles = { cursor: 'pointer' };
|
|
63
|
+
const StyledSpan = styledElement('span', spanStyles);
|
|
64
|
+
const StyledButton = styledElement('button', buttonStyles);
|
|
65
|
+
const spanResult = StyledSpan({}, []);
|
|
66
|
+
const buttonResult = StyledButton({}, []);
|
|
67
|
+
expect(spanResult.tagName.toLowerCase()).toBe('span');
|
|
68
|
+
expect(spanResult.style.fontWeight).toBe('bold');
|
|
69
|
+
expect(buttonResult.tagName.toLowerCase()).toBe('button');
|
|
70
|
+
expect(buttonResult.style.cursor).toBe('pointer');
|
|
71
|
+
});
|
|
72
|
+
it('should handle props being undefined', () => {
|
|
73
|
+
const additionalStyles = { color: 'red' };
|
|
74
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
75
|
+
const result = StyledDiv(undefined, []);
|
|
76
|
+
expect(result.style.color).toBe('red');
|
|
77
|
+
});
|
|
78
|
+
it('should handle empty children list', () => {
|
|
79
|
+
const additionalStyles = { color: 'red' };
|
|
80
|
+
const StyledDiv = styledElement('div', additionalStyles);
|
|
81
|
+
const result = StyledDiv({}, []);
|
|
82
|
+
expect(result.children.length).toBe(0);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=styled-element.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styled-element.spec.js","sourceRoot":"","sources":["../src/styled-element.spec.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styled-shade.spec.d.ts","sourceRoot":"","sources":["../src/styled-shade.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { styledShade } from './styled-shade.js';
|
|
3
|
+
describe('styled-shade', () => {
|
|
4
|
+
describe('styledShade', () => {
|
|
5
|
+
it('should apply additional styles to a component', () => {
|
|
6
|
+
const mockElement = vi.fn().mockReturnValue({});
|
|
7
|
+
const additionalStyles = { color: 'red', padding: '10px' };
|
|
8
|
+
const StyledComponent = styledShade(mockElement, additionalStyles);
|
|
9
|
+
StyledComponent({});
|
|
10
|
+
expect(mockElement).toHaveBeenCalledTimes(1);
|
|
11
|
+
const [props] = mockElement.mock.calls[0];
|
|
12
|
+
expect(props.style.color).toBe('red');
|
|
13
|
+
expect(props.style.padding).toBe('10px');
|
|
14
|
+
});
|
|
15
|
+
it('should merge styles when component already has styles', () => {
|
|
16
|
+
const mockElement = vi.fn().mockReturnValue({});
|
|
17
|
+
const additionalStyles = { color: 'red' };
|
|
18
|
+
const existingStyles = { backgroundColor: 'blue' };
|
|
19
|
+
const StyledComponent = styledShade(mockElement, additionalStyles);
|
|
20
|
+
StyledComponent({ style: existingStyles });
|
|
21
|
+
expect(mockElement).toHaveBeenCalledTimes(1);
|
|
22
|
+
const [props] = mockElement.mock.calls[0];
|
|
23
|
+
expect(props.style.backgroundColor).toBe('blue');
|
|
24
|
+
expect(props.style.color).toBe('red');
|
|
25
|
+
});
|
|
26
|
+
it('should override existing styles with additional styles', () => {
|
|
27
|
+
const mockElement = vi.fn().mockReturnValue({});
|
|
28
|
+
const additionalStyles = { color: 'red' };
|
|
29
|
+
const existingStyles = { color: 'blue' };
|
|
30
|
+
const StyledComponent = styledShade(mockElement, additionalStyles);
|
|
31
|
+
StyledComponent({ style: existingStyles });
|
|
32
|
+
expect(mockElement).toHaveBeenCalledTimes(1);
|
|
33
|
+
const [props] = mockElement.mock.calls[0];
|
|
34
|
+
expect(props.style.color).toBe('red');
|
|
35
|
+
});
|
|
36
|
+
it('should preserve original props', () => {
|
|
37
|
+
const mockElement = vi.fn().mockReturnValue({});
|
|
38
|
+
const additionalStyles = { color: 'red' };
|
|
39
|
+
const StyledComponent = styledShade(mockElement, additionalStyles);
|
|
40
|
+
StyledComponent({ className: 'my-class' });
|
|
41
|
+
expect(mockElement).toHaveBeenCalledTimes(1);
|
|
42
|
+
const [props] = mockElement.mock.calls[0];
|
|
43
|
+
expect(props.className).toBe('my-class');
|
|
44
|
+
expect(props.style.color).toBe('red');
|
|
45
|
+
});
|
|
46
|
+
it('should pass children correctly', () => {
|
|
47
|
+
const mockElement = vi.fn().mockReturnValue({});
|
|
48
|
+
const additionalStyles = { color: 'red' };
|
|
49
|
+
const children = ['child1', 'child2'];
|
|
50
|
+
const StyledComponent = styledShade(mockElement, additionalStyles);
|
|
51
|
+
StyledComponent({}, children);
|
|
52
|
+
expect(mockElement).toHaveBeenCalledTimes(1);
|
|
53
|
+
const [, passedChildren] = mockElement.mock.calls[0];
|
|
54
|
+
expect(passedChildren).toBe(children);
|
|
55
|
+
});
|
|
56
|
+
it('should return a function that returns JSX.Element', () => {
|
|
57
|
+
const expectedElement = { tagName: 'div' };
|
|
58
|
+
const mockElement = vi.fn().mockReturnValue(expectedElement);
|
|
59
|
+
const additionalStyles = { color: 'red' };
|
|
60
|
+
const StyledComponent = styledShade(mockElement, additionalStyles);
|
|
61
|
+
const result = StyledComponent({});
|
|
62
|
+
expect(result).toBe(expectedElement);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=styled-shade.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styled-shade.spec.js","sourceRoot":"","sources":["../src/styled-shade.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;YACvD,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,EAAiB,CAAC,CAAA;YAC9D,MAAM,gBAAgB,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;YAE1D,MAAM,eAAe,GAAG,WAAW,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;YAClE,eAAe,CAAC,EAAE,CAAC,CAAA;YAEnB,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;YAC5C,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAwC,CAAA;YAChF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACrC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,EAAiB,CAAC,CAAA;YAC9D,MAAM,gBAAgB,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;YACzC,MAAM,cAAc,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,CAAA;YAElD,MAAM,eAAe,GAAG,WAAW,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;YAClE,eAAe,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAA;YAE1C,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;YAC5C,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAwC,CAAA;YAChF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAChD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,EAAiB,CAAC,CAAA;YAC9D,MAAM,gBAAgB,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;YACzC,MAAM,cAAc,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;YAExC,MAAM,eAAe,GAAG,WAAW,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;YAClE,eAAe,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAA;YAE1C,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;YAC5C,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAwC,CAAA;YAChF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,EAAiB,CAAC,CAAA;YAC9D,MAAM,gBAAgB,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;YAEzC,MAAM,eAAe,GAAG,WAAW,CACjC,WAAW,EACX,gBAAgB,CACjB,CAAA;YACD,eAAe,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAA;YAE1C,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;YAC5C,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA2D,CAAA;YACnG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YACxC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,EAAiB,CAAC,CAAA;YAC9D,MAAM,gBAAgB,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;YACzC,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAA6B,CAAA;YAEjE,MAAM,eAAe,GAAG,WAAW,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;YAClE,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;YAE7B,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;YAC5C,MAAM,CAAC,EAAE,cAAc,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA6B,CAAA;YAChF,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACvC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,eAAe,GAAG,EAAE,OAAO,EAAE,KAAK,EAA4B,CAAA;YACpE,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,eAAe,CAAC,CAAA;YAC5D,MAAM,gBAAgB,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;YAEzC,MAAM,eAAe,GAAG,WAAW,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;YAClE,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC,CAAA;YAElC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QACtC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { compileRoute } from './compile-route.js'
|
|
3
|
+
|
|
4
|
+
describe('compile-route', () => {
|
|
5
|
+
describe('compileRoute', () => {
|
|
6
|
+
it('should compile route with string params', () => {
|
|
7
|
+
const result = compileRoute('/users/:id', { id: 'abc123' })
|
|
8
|
+
expect(result).toBe('/users/abc123')
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('should compile route with numeric params (stringified)', () => {
|
|
12
|
+
const result = compileRoute('/users/:id', { id: 42 })
|
|
13
|
+
expect(result).toBe('/users/42')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should compile route with multiple params', () => {
|
|
17
|
+
const result = compileRoute('/users/:userId/posts/:postId', {
|
|
18
|
+
userId: 'user1',
|
|
19
|
+
postId: 'post2',
|
|
20
|
+
})
|
|
21
|
+
expect(result).toBe('/users/user1/posts/post2')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should handle empty params object for static routes', () => {
|
|
25
|
+
const result = compileRoute('/home', {})
|
|
26
|
+
expect(result).toBe('/home')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should handle params with special characters', () => {
|
|
30
|
+
const result = compileRoute('/search/:query', { query: 'hello-world' })
|
|
31
|
+
expect(result).toBe('/search/hello-world')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should handle boolean params (stringified)', () => {
|
|
35
|
+
const result = compileRoute('/feature/:enabled', { enabled: true })
|
|
36
|
+
expect(result).toBe('/feature/true')
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -31,7 +31,7 @@ describe('RouteLink', () => {
|
|
|
31
31
|
),
|
|
32
32
|
})
|
|
33
33
|
expect(document.body.innerHTML).toMatchInlineSnapshot(
|
|
34
|
-
`"<div id="root"><a is="route-link" id="route" href="/subroute"
|
|
34
|
+
`"<div id="root"><a is="route-link" id="route" href="/subroute">Link</a></div>"`,
|
|
35
35
|
)
|
|
36
36
|
expect(onRouteChange).not.toBeCalled()
|
|
37
37
|
document.getElementById('route')?.click()
|
|
@@ -9,14 +9,13 @@ export const RouteLink = Shade<RouteLinkProps>({
|
|
|
9
9
|
shadowDomName: 'route-link',
|
|
10
10
|
elementBase: HTMLAnchorElement,
|
|
11
11
|
elementBaseName: 'a',
|
|
12
|
+
css: {
|
|
13
|
+
color: 'inherit',
|
|
14
|
+
textDecoration: 'inherit',
|
|
15
|
+
},
|
|
12
16
|
render: ({ children, props, injector, element }) => {
|
|
13
17
|
attachProps(element, {
|
|
14
18
|
...props,
|
|
15
|
-
style: {
|
|
16
|
-
color: 'inherit',
|
|
17
|
-
textDecoration: 'inherit',
|
|
18
|
-
...props.style,
|
|
19
|
-
},
|
|
20
19
|
onclick: (ev: MouseEvent) => {
|
|
21
20
|
ev.preventDefault()
|
|
22
21
|
history.pushState('', props.title || '', props.href)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { camelToKebab, generateCSS, generateCSSRule, isSelectorKey, propertiesToCSSString } from './css-generator.js'
|
|
3
|
+
import type { CSSProperties } from './models/css-object.js'
|
|
4
|
+
|
|
5
|
+
describe('css-generator', () => {
|
|
6
|
+
describe('camelToKebab', () => {
|
|
7
|
+
it('should convert camelCase to kebab-case', () => {
|
|
8
|
+
expect(camelToKebab('backgroundColor')).toBe('background-color')
|
|
9
|
+
expect(camelToKebab('fontSize')).toBe('font-size')
|
|
10
|
+
expect(camelToKebab('borderTopLeftRadius')).toBe('border-top-left-radius')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('should handle single word properties', () => {
|
|
14
|
+
expect(camelToKebab('color')).toBe('color')
|
|
15
|
+
expect(camelToKebab('margin')).toBe('margin')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('should handle empty string', () => {
|
|
19
|
+
expect(camelToKebab('')).toBe('')
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
describe('isSelectorKey', () => {
|
|
24
|
+
it('should return true for selector keys starting with &', () => {
|
|
25
|
+
expect(isSelectorKey('&:hover')).toBe(true)
|
|
26
|
+
expect(isSelectorKey('&:active')).toBe(true)
|
|
27
|
+
expect(isSelectorKey('& .className')).toBe(true)
|
|
28
|
+
expect(isSelectorKey('& > div')).toBe(true)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('should return false for regular CSS property keys', () => {
|
|
32
|
+
expect(isSelectorKey('color')).toBe(false)
|
|
33
|
+
expect(isSelectorKey('backgroundColor')).toBe(false)
|
|
34
|
+
expect(isSelectorKey('fontSize')).toBe(false)
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('propertiesToCSSString', () => {
|
|
39
|
+
it('should convert CSS properties object to CSS string', () => {
|
|
40
|
+
const result = propertiesToCSSString({
|
|
41
|
+
color: 'red',
|
|
42
|
+
backgroundColor: 'blue',
|
|
43
|
+
})
|
|
44
|
+
expect(result).toBe('color: red; background-color: blue')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('should skip undefined and null values', () => {
|
|
48
|
+
const result = propertiesToCSSString({
|
|
49
|
+
color: 'red',
|
|
50
|
+
backgroundColor: undefined,
|
|
51
|
+
})
|
|
52
|
+
expect(result).toBe('color: red')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('should skip empty string values', () => {
|
|
56
|
+
const result = propertiesToCSSString({
|
|
57
|
+
color: 'red',
|
|
58
|
+
backgroundColor: '',
|
|
59
|
+
})
|
|
60
|
+
expect(result).toBe('color: red')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('should return empty string for empty object', () => {
|
|
64
|
+
const result = propertiesToCSSString({})
|
|
65
|
+
expect(result).toBe('')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('should ignore selector keys', () => {
|
|
69
|
+
// Type assertion needed to test mixed object with selectors
|
|
70
|
+
const mixedObject = {
|
|
71
|
+
color: 'red',
|
|
72
|
+
'&:hover': { color: 'blue' },
|
|
73
|
+
}
|
|
74
|
+
const result = propertiesToCSSString(mixedObject as unknown as CSSProperties)
|
|
75
|
+
expect(result).toBe('color: red')
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('should filter out non-string values', () => {
|
|
79
|
+
// Type assertion to test edge case with non-string values
|
|
80
|
+
const mixedObject = {
|
|
81
|
+
color: 'red',
|
|
82
|
+
opacity: 0.5, // number - should be filtered
|
|
83
|
+
display: 'flex',
|
|
84
|
+
hidden: true, // boolean - should be filtered
|
|
85
|
+
}
|
|
86
|
+
const result = propertiesToCSSString(mixedObject as unknown as CSSProperties)
|
|
87
|
+
expect(result).toBe('color: red; display: flex')
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
describe('generateCSSRule', () => {
|
|
92
|
+
it('should generate a complete CSS rule', () => {
|
|
93
|
+
const result = generateCSSRule('my-component', {
|
|
94
|
+
color: 'red',
|
|
95
|
+
padding: '10px',
|
|
96
|
+
})
|
|
97
|
+
expect(result).toBe('my-component { color: red; padding: 10px; }')
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('should return empty string for empty properties', () => {
|
|
101
|
+
const result = generateCSSRule('my-component', {})
|
|
102
|
+
expect(result).toBe('')
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
describe('generateCSS', () => {
|
|
107
|
+
it('should generate CSS for base properties only', () => {
|
|
108
|
+
const result = generateCSS('my-component', {
|
|
109
|
+
color: 'red',
|
|
110
|
+
padding: '10px',
|
|
111
|
+
})
|
|
112
|
+
expect(result).toBe('my-component { color: red; padding: 10px; }')
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('should generate CSS with pseudo-selectors', () => {
|
|
116
|
+
const result = generateCSS('my-component', {
|
|
117
|
+
color: 'red',
|
|
118
|
+
'&:hover': { color: 'blue' },
|
|
119
|
+
})
|
|
120
|
+
expect(result).toContain('my-component { color: red; }')
|
|
121
|
+
expect(result).toContain('my-component:hover { color: blue; }')
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('should generate CSS with nested class selectors', () => {
|
|
125
|
+
const result = generateCSS('my-component', {
|
|
126
|
+
padding: '10px',
|
|
127
|
+
'& .inner': { fontWeight: 'bold' },
|
|
128
|
+
})
|
|
129
|
+
expect(result).toContain('my-component { padding: 10px; }')
|
|
130
|
+
expect(result).toContain('my-component .inner { font-weight: bold; }')
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('should generate CSS with child selectors', () => {
|
|
134
|
+
const result = generateCSS('my-component', {
|
|
135
|
+
display: 'flex',
|
|
136
|
+
'& > div': { margin: '5px' },
|
|
137
|
+
})
|
|
138
|
+
expect(result).toContain('my-component { display: flex; }')
|
|
139
|
+
expect(result).toContain('my-component > div { margin: 5px; }')
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('should handle multiple pseudo-selectors', () => {
|
|
143
|
+
const result = generateCSS('my-button', {
|
|
144
|
+
backgroundColor: 'blue',
|
|
145
|
+
'&:hover': { backgroundColor: 'darkblue' },
|
|
146
|
+
'&:active': { backgroundColor: 'navy' },
|
|
147
|
+
'&:disabled': { opacity: '0.5' },
|
|
148
|
+
})
|
|
149
|
+
expect(result).toContain('my-button { background-color: blue; }')
|
|
150
|
+
expect(result).toContain('my-button:hover { background-color: darkblue; }')
|
|
151
|
+
expect(result).toContain('my-button:active { background-color: navy; }')
|
|
152
|
+
expect(result).toContain('my-button:disabled { opacity: 0.5; }')
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it('should handle empty css object', () => {
|
|
156
|
+
const result = generateCSS('my-component', {})
|
|
157
|
+
expect(result).toBe('')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('should handle css object with only selectors', () => {
|
|
161
|
+
const result = generateCSS('my-component', {
|
|
162
|
+
'&:hover': { color: 'blue' },
|
|
163
|
+
})
|
|
164
|
+
expect(result).toBe('my-component:hover { color: blue; }')
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('should skip selector keys with non-object values', () => {
|
|
168
|
+
// Type assertion to test edge case with invalid selector values
|
|
169
|
+
const cssObject = {
|
|
170
|
+
color: 'red',
|
|
171
|
+
'&:hover': 'invalid', // string instead of object - should be skipped
|
|
172
|
+
'&:active': null, // null - should be skipped
|
|
173
|
+
'&:focus': { backgroundColor: 'blue' }, // valid - should be included
|
|
174
|
+
}
|
|
175
|
+
const result = generateCSS('my-component', cssObject as unknown as Parameters<typeof generateCSS>[1])
|
|
176
|
+
expect(result).toContain('my-component { color: red; }')
|
|
177
|
+
expect(result).toContain('my-component:focus { background-color: blue; }')
|
|
178
|
+
expect(result).not.toContain('invalid')
|
|
179
|
+
expect(result).not.toContain(':hover')
|
|
180
|
+
expect(result).not.toContain(':active')
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
})
|