@furystack/shades 11.0.35 → 12.0.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 +337 -0
- package/README.md +99 -13
- 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/component-factory.spec.js +13 -5
- package/esm/component-factory.spec.js.map +1 -1
- package/esm/components/index.d.ts +4 -1
- package/esm/components/index.d.ts.map +1 -1
- package/esm/components/index.js +4 -1
- package/esm/components/index.js.map +1 -1
- package/esm/components/lazy-load.d.ts +2 -4
- package/esm/components/lazy-load.d.ts.map +1 -1
- package/esm/components/lazy-load.js +40 -24
- package/esm/components/lazy-load.js.map +1 -1
- package/esm/components/lazy-load.spec.js +57 -50
- package/esm/components/lazy-load.spec.js.map +1 -1
- package/esm/components/link-to-route.d.ts +2 -0
- package/esm/components/link-to-route.d.ts.map +1 -1
- package/esm/components/link-to-route.js +3 -2
- package/esm/components/link-to-route.js.map +1 -1
- package/esm/components/link-to-route.spec.js +13 -9
- package/esm/components/link-to-route.spec.js.map +1 -1
- package/esm/components/nested-route-link.d.ts +62 -0
- package/esm/components/nested-route-link.d.ts.map +1 -0
- package/esm/components/nested-route-link.js +66 -0
- package/esm/components/nested-route-link.js.map +1 -0
- package/esm/components/nested-route-link.spec.d.ts +2 -0
- package/esm/components/nested-route-link.spec.d.ts.map +1 -0
- package/esm/components/nested-route-link.spec.js +179 -0
- package/esm/components/nested-route-link.spec.js.map +1 -0
- package/esm/components/nested-route-types.d.ts +37 -0
- package/esm/components/nested-route-types.d.ts.map +1 -0
- package/esm/components/nested-route-types.js +2 -0
- package/esm/components/nested-route-types.js.map +1 -0
- package/esm/components/nested-router.d.ts +103 -0
- package/esm/components/nested-router.d.ts.map +1 -0
- package/esm/components/nested-router.js +178 -0
- package/esm/components/nested-router.js.map +1 -0
- package/esm/components/nested-router.spec.d.ts +2 -0
- package/esm/components/nested-router.spec.d.ts.map +1 -0
- package/esm/components/nested-router.spec.js +659 -0
- package/esm/components/nested-router.spec.js.map +1 -0
- package/esm/components/route-link.d.ts +4 -0
- package/esm/components/route-link.d.ts.map +1 -1
- package/esm/components/route-link.js +9 -10
- package/esm/components/route-link.js.map +1 -1
- package/esm/components/route-link.spec.js +16 -12
- package/esm/components/route-link.spec.js.map +1 -1
- package/esm/components/router.d.ts +20 -2
- package/esm/components/router.d.ts.map +1 -1
- package/esm/components/router.js +3 -0
- package/esm/components/router.js.map +1 -1
- package/esm/components/router.spec.js +75 -74
- package/esm/components/router.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/initialize.d.ts +11 -0
- package/esm/initialize.d.ts.map +1 -1
- package/esm/initialize.js +5 -0
- package/esm/initialize.js.map +1 -1
- package/esm/jsx.d.ts +83 -2
- package/esm/jsx.d.ts.map +1 -1
- package/esm/models/children-list.d.ts +5 -1
- package/esm/models/children-list.d.ts.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/models/partial-element.d.ts +12 -2
- package/esm/models/partial-element.d.ts.map +1 -1
- package/esm/models/render-options.d.ts +89 -3
- package/esm/models/render-options.d.ts.map +1 -1
- package/esm/models/selection-state.d.ts +4 -0
- package/esm/models/selection-state.d.ts.map +1 -1
- package/esm/services/location-service.d.ts +11 -0
- package/esm/services/location-service.d.ts.map +1 -1
- package/esm/services/location-service.js +11 -0
- package/esm/services/location-service.js.map +1 -1
- package/esm/services/resource-manager.d.ts +24 -0
- package/esm/services/resource-manager.d.ts.map +1 -1
- package/esm/services/resource-manager.js +30 -0
- package/esm/services/resource-manager.js.map +1 -1
- package/esm/services/resource-manager.spec.js +93 -0
- package/esm/services/resource-manager.spec.js.map +1 -1
- package/esm/services/screen-service.d.ts +81 -4
- package/esm/services/screen-service.d.ts.map +1 -1
- package/esm/services/screen-service.js +75 -4
- package/esm/services/screen-service.js.map +1 -1
- package/esm/services/screen-service.spec.js +91 -7
- package/esm/services/screen-service.spec.js.map +1 -1
- package/esm/shade-component.d.ts +17 -4
- package/esm/shade-component.d.ts.map +1 -1
- package/esm/shade-component.js +67 -5
- package/esm/shade-component.js.map +1 -1
- package/esm/shade-host-props-ref.integration.spec.d.ts +2 -0
- package/esm/shade-host-props-ref.integration.spec.d.ts.map +1 -0
- package/esm/shade-host-props-ref.integration.spec.js +381 -0
- package/esm/shade-host-props-ref.integration.spec.js.map +1 -0
- package/esm/shade-resources.integration.spec.js +208 -39
- package/esm/shade-resources.integration.spec.js.map +1 -1
- package/esm/shade.d.ts +34 -15
- package/esm/shade.d.ts.map +1 -1
- package/esm/shade.js +180 -33
- 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 +198 -0
- package/esm/shade.spec.js.map +1 -0
- package/esm/shades.integration.spec.js +135 -72
- package/esm/shades.integration.spec.js.map +1 -1
- 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/esm/svg-types.d.ts +389 -0
- package/esm/svg-types.d.ts.map +1 -0
- package/esm/svg-types.js +9 -0
- package/esm/svg-types.js.map +1 -0
- package/esm/svg.d.ts +15 -0
- package/esm/svg.d.ts.map +1 -0
- package/esm/svg.js +76 -0
- package/esm/svg.js.map +1 -0
- package/esm/svg.spec.d.ts +2 -0
- package/esm/svg.spec.d.ts.map +1 -0
- package/esm/svg.spec.js +80 -0
- package/esm/svg.spec.js.map +1 -0
- package/esm/vnode.d.ts +103 -0
- package/esm/vnode.d.ts.map +1 -0
- package/esm/vnode.integration.spec.d.ts +2 -0
- package/esm/vnode.integration.spec.d.ts.map +1 -0
- package/esm/vnode.integration.spec.js +494 -0
- package/esm/vnode.integration.spec.js.map +1 -0
- package/esm/vnode.js +453 -0
- package/esm/vnode.js.map +1 -0
- package/esm/vnode.spec.d.ts +2 -0
- package/esm/vnode.spec.d.ts.map +1 -0
- package/esm/vnode.spec.js +473 -0
- package/esm/vnode.spec.js.map +1 -0
- package/package.json +3 -3
- package/src/compile-route.spec.ts +39 -0
- package/src/component-factory.spec.tsx +18 -5
- package/src/components/index.ts +4 -1
- package/src/components/lazy-load.spec.tsx +82 -75
- package/src/components/lazy-load.tsx +49 -27
- package/src/components/link-to-route.spec.tsx +25 -21
- package/src/components/link-to-route.tsx +4 -2
- package/src/components/nested-route-link.spec.tsx +303 -0
- package/src/components/nested-route-link.tsx +100 -0
- package/src/components/nested-route-types.ts +42 -0
- package/src/components/nested-router.spec.tsx +817 -0
- package/src/components/nested-router.tsx +256 -0
- package/src/components/route-link.spec.tsx +22 -18
- package/src/components/route-link.tsx +10 -10
- package/src/components/router.spec.tsx +109 -108
- package/src/components/router.tsx +15 -2
- package/src/css-generator.spec.ts +183 -0
- package/src/css-generator.ts +117 -0
- package/src/index.ts +2 -0
- package/src/initialize.ts +12 -0
- package/src/jsx.ts +129 -2
- package/src/models/children-list.ts +7 -1
- package/src/models/css-object.ts +34 -0
- package/src/models/index.ts +1 -0
- package/src/models/partial-element.ts +13 -2
- package/src/models/render-options.ts +90 -3
- package/src/models/selection-state.ts +4 -0
- package/src/services/location-service.tsx +11 -0
- package/src/services/resource-manager.spec.ts +116 -0
- package/src/services/resource-manager.ts +30 -0
- package/src/services/screen-service.spec.ts +109 -7
- package/src/services/screen-service.ts +81 -4
- package/src/shade-component.ts +72 -6
- package/src/shade-host-props-ref.integration.spec.tsx +460 -0
- package/src/shade-resources.integration.spec.tsx +276 -52
- package/src/shade.spec.tsx +239 -0
- package/src/shade.ts +211 -56
- package/src/shades.integration.spec.tsx +154 -80
- 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
- package/src/svg-types.ts +437 -0
- package/src/svg.spec.ts +89 -0
- package/src/svg.ts +78 -0
- package/src/vnode.integration.spec.tsx +657 -0
- package/src/vnode.spec.ts +579 -0
- package/src/vnode.ts +508 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { generateCSS } from './css-generator.js'
|
|
2
|
+
import type { CSSObject } from './models/css-object.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Singleton that manages component CSS injection.
|
|
6
|
+
* Creates and maintains a shared `<style>` element in the document head,
|
|
7
|
+
* and tracks registered component styles to avoid duplicates.
|
|
8
|
+
*/
|
|
9
|
+
class StyleManagerClass {
|
|
10
|
+
private styleElement: HTMLStyleElement | null = null
|
|
11
|
+
private registeredComponents = new Set<string>()
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Gets or creates the shared style element
|
|
15
|
+
* @returns The style element for CSS injection
|
|
16
|
+
*/
|
|
17
|
+
private getStyleElement(): HTMLStyleElement {
|
|
18
|
+
if (!this.styleElement) {
|
|
19
|
+
this.styleElement = document.createElement('style')
|
|
20
|
+
this.styleElement.setAttribute('data-shades-styles', '')
|
|
21
|
+
document.head.appendChild(this.styleElement)
|
|
22
|
+
}
|
|
23
|
+
return this.styleElement
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Registers CSS styles for a component.
|
|
28
|
+
* Styles are only injected once per component (based on the custom element name).
|
|
29
|
+
*
|
|
30
|
+
* @param shadowDomName - The custom element tag name (used as CSS selector)
|
|
31
|
+
* @param cssObject - The CSSObject containing styles and nested selectors
|
|
32
|
+
* @param elementBaseName - Optional base element name for customized built-in elements (e.g., 'a', 'button').
|
|
33
|
+
* When provided, generates selector like `a[is="component-name"]` instead of `component-name`
|
|
34
|
+
* @returns True if styles were injected, false if already registered
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* // Regular custom element
|
|
39
|
+
* StyleManager.registerComponentStyles('my-button', {
|
|
40
|
+
* padding: '12px',
|
|
41
|
+
* '&:hover': { backgroundColor: 'blue' }
|
|
42
|
+
* })
|
|
43
|
+
*
|
|
44
|
+
* // Customized built-in element (extends anchor)
|
|
45
|
+
* StyleManager.registerComponentStyles('my-link', {
|
|
46
|
+
* color: 'blue',
|
|
47
|
+
* '&:hover': { textDecoration: 'underline' }
|
|
48
|
+
* }, 'a')
|
|
49
|
+
* // Generates: a[is="my-link"] { color: blue; }
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
public registerComponentStyles(shadowDomName: string, cssObject: CSSObject, elementBaseName?: string): boolean {
|
|
53
|
+
if (this.registeredComponents.has(shadowDomName)) {
|
|
54
|
+
return false
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const selector = elementBaseName ? `${elementBaseName}[is="${shadowDomName}"]` : shadowDomName
|
|
58
|
+
const css = generateCSS(selector, cssObject)
|
|
59
|
+
if (css) {
|
|
60
|
+
const styleElement = this.getStyleElement()
|
|
61
|
+
styleElement.textContent += `\n/* ${shadowDomName} */\n${css}\n`
|
|
62
|
+
this.registeredComponents.add(shadowDomName)
|
|
63
|
+
return true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Checks if a component's styles have already been registered
|
|
71
|
+
* @param shadowDomName - The component identifier to check
|
|
72
|
+
* @returns True if styles are already registered
|
|
73
|
+
*/
|
|
74
|
+
public isRegistered(shadowDomName: string): boolean {
|
|
75
|
+
return this.registeredComponents.has(shadowDomName)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Gets all registered component names (for debugging/testing)
|
|
80
|
+
* @returns Set of registered component names
|
|
81
|
+
*/
|
|
82
|
+
public getRegisteredComponents(): ReadonlySet<string> {
|
|
83
|
+
return this.registeredComponents
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Clears all registered styles (useful for testing)
|
|
88
|
+
*/
|
|
89
|
+
public clear(): void {
|
|
90
|
+
this.registeredComponents.clear()
|
|
91
|
+
if (this.styleElement) {
|
|
92
|
+
this.styleElement.textContent = ''
|
|
93
|
+
this.styleElement.remove()
|
|
94
|
+
this.styleElement = null
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Singleton instance for managing component CSS styles.
|
|
101
|
+
* Use this to register component-level styles that support
|
|
102
|
+
* pseudo-selectors and nested selectors.
|
|
103
|
+
*/
|
|
104
|
+
export const StyleManager = new StyleManagerClass()
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { styledElement } from './styled-element.js'
|
|
3
|
+
|
|
4
|
+
describe('styled-element', () => {
|
|
5
|
+
describe('styledElement', () => {
|
|
6
|
+
it('should apply additional styles to an intrinsic element', () => {
|
|
7
|
+
const additionalStyles = { color: 'red', padding: '10px' }
|
|
8
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
9
|
+
|
|
10
|
+
const result = StyledDiv({}, [])
|
|
11
|
+
|
|
12
|
+
expect(result.style.color).toBe('red')
|
|
13
|
+
expect(result.style.padding).toBe('10px')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should merge styles when element already has styles', () => {
|
|
17
|
+
const additionalStyles = { color: 'red' }
|
|
18
|
+
const existingStyles = { backgroundColor: 'blue' }
|
|
19
|
+
|
|
20
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
21
|
+
const result = StyledDiv({ style: existingStyles }, [])
|
|
22
|
+
|
|
23
|
+
expect(result.style.backgroundColor).toBe('blue')
|
|
24
|
+
expect(result.style.color).toBe('red')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should override existing styles with additional styles', () => {
|
|
28
|
+
const additionalStyles = { color: 'red' }
|
|
29
|
+
const existingStyles = { color: 'blue' }
|
|
30
|
+
|
|
31
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
32
|
+
const result = StyledDiv({ style: existingStyles }, [])
|
|
33
|
+
|
|
34
|
+
expect(result.style.color).toBe('red')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should preserve original props', () => {
|
|
38
|
+
const additionalStyles = { color: 'red' }
|
|
39
|
+
|
|
40
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
41
|
+
const result = StyledDiv({ className: 'my-class', id: 'my-id' }, [])
|
|
42
|
+
|
|
43
|
+
expect(result.className).toBe('my-class')
|
|
44
|
+
expect(result.id).toBe('my-id')
|
|
45
|
+
expect(result.style.color).toBe('red')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('should pass children correctly', () => {
|
|
49
|
+
const additionalStyles = { color: 'red' }
|
|
50
|
+
|
|
51
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
52
|
+
const child1 = document.createElement('span')
|
|
53
|
+
child1.textContent = 'child1'
|
|
54
|
+
const child2 = document.createElement('span')
|
|
55
|
+
child2.textContent = 'child2'
|
|
56
|
+
|
|
57
|
+
const result = StyledDiv({}, [child1, child2])
|
|
58
|
+
|
|
59
|
+
expect(result.children.length).toBe(2)
|
|
60
|
+
expect(result.children[0]).toBe(child1)
|
|
61
|
+
expect(result.children[1]).toBe(child2)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('should handle text children', () => {
|
|
65
|
+
const additionalStyles = { color: 'red' }
|
|
66
|
+
|
|
67
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
68
|
+
const result = StyledDiv({}, ['Hello', ' ', 'World'])
|
|
69
|
+
|
|
70
|
+
expect(result.textContent).toBe('Hello World')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('should return an HTMLElement', () => {
|
|
74
|
+
const additionalStyles = { color: 'red' }
|
|
75
|
+
|
|
76
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
77
|
+
const result = StyledDiv({}, [])
|
|
78
|
+
|
|
79
|
+
expect(result).toBeInstanceOf(HTMLElement)
|
|
80
|
+
expect(result.tagName.toLowerCase()).toBe('div')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('should work with different element types', () => {
|
|
84
|
+
const spanStyles = { fontWeight: 'bold' }
|
|
85
|
+
const buttonStyles = { cursor: 'pointer' }
|
|
86
|
+
|
|
87
|
+
const StyledSpan = styledElement('span', spanStyles)
|
|
88
|
+
const StyledButton = styledElement('button', buttonStyles)
|
|
89
|
+
|
|
90
|
+
const spanResult = StyledSpan({}, [])
|
|
91
|
+
const buttonResult = StyledButton({}, [])
|
|
92
|
+
|
|
93
|
+
expect(spanResult.tagName.toLowerCase()).toBe('span')
|
|
94
|
+
expect(spanResult.style.fontWeight).toBe('bold')
|
|
95
|
+
expect(buttonResult.tagName.toLowerCase()).toBe('button')
|
|
96
|
+
expect(buttonResult.style.cursor).toBe('pointer')
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('should handle props being undefined', () => {
|
|
100
|
+
const additionalStyles = { color: 'red' }
|
|
101
|
+
|
|
102
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
103
|
+
const result = StyledDiv(undefined as unknown as Record<string, unknown>, [])
|
|
104
|
+
|
|
105
|
+
expect(result.style.color).toBe('red')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('should handle empty children list', () => {
|
|
109
|
+
const additionalStyles = { color: 'red' }
|
|
110
|
+
|
|
111
|
+
const StyledDiv = styledElement('div', additionalStyles)
|
|
112
|
+
const result = StyledDiv({}, [])
|
|
113
|
+
|
|
114
|
+
expect(result.children.length).toBe(0)
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
})
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { styledShade } from './styled-shade.js'
|
|
3
|
+
|
|
4
|
+
describe('styled-shade', () => {
|
|
5
|
+
describe('styledShade', () => {
|
|
6
|
+
it('should apply additional styles to a component', () => {
|
|
7
|
+
const mockElement = vi.fn().mockReturnValue({} as JSX.Element)
|
|
8
|
+
const additionalStyles = { color: 'red', padding: '10px' }
|
|
9
|
+
|
|
10
|
+
const StyledComponent = styledShade(mockElement, additionalStyles)
|
|
11
|
+
StyledComponent({})
|
|
12
|
+
|
|
13
|
+
expect(mockElement).toHaveBeenCalledTimes(1)
|
|
14
|
+
const [props] = mockElement.mock.calls[0] as [{ style: Record<string, string> }]
|
|
15
|
+
expect(props.style.color).toBe('red')
|
|
16
|
+
expect(props.style.padding).toBe('10px')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('should merge styles when component already has styles', () => {
|
|
20
|
+
const mockElement = vi.fn().mockReturnValue({} as JSX.Element)
|
|
21
|
+
const additionalStyles = { color: 'red' }
|
|
22
|
+
const existingStyles = { backgroundColor: 'blue' }
|
|
23
|
+
|
|
24
|
+
const StyledComponent = styledShade(mockElement, additionalStyles)
|
|
25
|
+
StyledComponent({ style: existingStyles })
|
|
26
|
+
|
|
27
|
+
expect(mockElement).toHaveBeenCalledTimes(1)
|
|
28
|
+
const [props] = mockElement.mock.calls[0] as [{ style: Record<string, string> }]
|
|
29
|
+
expect(props.style.backgroundColor).toBe('blue')
|
|
30
|
+
expect(props.style.color).toBe('red')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('should override existing styles with additional styles', () => {
|
|
34
|
+
const mockElement = vi.fn().mockReturnValue({} as JSX.Element)
|
|
35
|
+
const additionalStyles = { color: 'red' }
|
|
36
|
+
const existingStyles = { color: 'blue' }
|
|
37
|
+
|
|
38
|
+
const StyledComponent = styledShade(mockElement, additionalStyles)
|
|
39
|
+
StyledComponent({ style: existingStyles })
|
|
40
|
+
|
|
41
|
+
expect(mockElement).toHaveBeenCalledTimes(1)
|
|
42
|
+
const [props] = mockElement.mock.calls[0] as [{ style: Record<string, string> }]
|
|
43
|
+
expect(props.style.color).toBe('red')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('should preserve original props', () => {
|
|
47
|
+
const mockElement = vi.fn().mockReturnValue({} as JSX.Element)
|
|
48
|
+
const additionalStyles = { color: 'red' }
|
|
49
|
+
|
|
50
|
+
const StyledComponent = styledShade<{ className?: string; style?: Partial<CSSStyleDeclaration> }>(
|
|
51
|
+
mockElement,
|
|
52
|
+
additionalStyles,
|
|
53
|
+
)
|
|
54
|
+
StyledComponent({ className: 'my-class' })
|
|
55
|
+
|
|
56
|
+
expect(mockElement).toHaveBeenCalledTimes(1)
|
|
57
|
+
const [props] = mockElement.mock.calls[0] as [{ className: string; style: Record<string, string> }]
|
|
58
|
+
expect(props.className).toBe('my-class')
|
|
59
|
+
expect(props.style.color).toBe('red')
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('should pass children correctly', () => {
|
|
63
|
+
const mockElement = vi.fn().mockReturnValue({} as JSX.Element)
|
|
64
|
+
const additionalStyles = { color: 'red' }
|
|
65
|
+
const children = ['child1', 'child2'] as unknown as JSX.Element[]
|
|
66
|
+
|
|
67
|
+
const StyledComponent = styledShade(mockElement, additionalStyles)
|
|
68
|
+
StyledComponent({}, children)
|
|
69
|
+
|
|
70
|
+
expect(mockElement).toHaveBeenCalledTimes(1)
|
|
71
|
+
const [, passedChildren] = mockElement.mock.calls[0] as [unknown, JSX.Element[]]
|
|
72
|
+
expect(passedChildren).toBe(children)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('should return a function that returns JSX.Element', () => {
|
|
76
|
+
const expectedElement = { tagName: 'div' } as unknown as JSX.Element
|
|
77
|
+
const mockElement = vi.fn().mockReturnValue(expectedElement)
|
|
78
|
+
const additionalStyles = { color: 'red' }
|
|
79
|
+
|
|
80
|
+
const StyledComponent = styledShade(mockElement, additionalStyles)
|
|
81
|
+
const result = StyledComponent({})
|
|
82
|
+
|
|
83
|
+
expect(result).toBe(expectedElement)
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
})
|