@manufosela/device-card-stack 1.0.0 → 1.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/package.json +14 -26
- package/src/device-card-stack.js +34 -32
- package/LICENSE +0 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manufosela/device-card-stack",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Accordion-style card stack with 3D perspective and image preview panel",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "manufosela",
|
|
@@ -14,34 +14,22 @@
|
|
|
14
14
|
"import": "./src/device-card-stack.js"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
|
-
"files": [
|
|
18
|
-
"src"
|
|
19
|
-
],
|
|
20
|
-
"repository": {
|
|
21
|
-
"type": "git",
|
|
22
|
-
"url": "https://github.com/manufosela/ui-components",
|
|
23
|
-
"directory": "packages/device-card-stack"
|
|
24
|
-
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
"web-components",
|
|
27
|
-
"lit",
|
|
28
|
-
"card-stack",
|
|
29
|
-
"accordion",
|
|
30
|
-
"device-showcase"
|
|
31
|
-
],
|
|
32
|
-
"homepage": "https://github.com/manufosela/ui-components/tree/main/packages/device-card-stack#readme",
|
|
33
|
-
"bugs": {
|
|
34
|
-
"url": "https://github.com/manufosela/ui-components/issues"
|
|
35
|
-
},
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"lit": "^3.2.1"
|
|
38
|
-
},
|
|
39
|
-
"customElements": "custom-elements.json",
|
|
17
|
+
"files": ["src"],
|
|
40
18
|
"scripts": {
|
|
41
19
|
"start": "web-dev-server --node-resolve --open demo/ --watch",
|
|
42
20
|
"test": "web-test-runner",
|
|
43
21
|
"test:watch": "web-test-runner --watch",
|
|
44
22
|
"test:coverage": "web-test-runner --coverage",
|
|
45
23
|
"build:types": "tsc --declaration --declarationMap --emitDeclarationOnly --allowJs --checkJs --outDir ./src ./src/device-card-stack.js"
|
|
46
|
-
}
|
|
47
|
-
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/manufosela/ui-components",
|
|
28
|
+
"directory": "packages/device-card-stack"
|
|
29
|
+
},
|
|
30
|
+
"keywords": ["web-components", "lit", "card-stack", "accordion", "device-showcase"],
|
|
31
|
+
"homepage": "https://github.com/manufosela/ui-components/tree/main/packages/device-card-stack#readme",
|
|
32
|
+
"bugs": {"url": "https://github.com/manufosela/ui-components/issues"},
|
|
33
|
+
"peerDependencies": {"lit": "^3.0.0"},
|
|
34
|
+
"customElements": "custom-elements.json"
|
|
35
|
+
}
|
package/src/device-card-stack.js
CHANGED
|
@@ -3,27 +3,12 @@ import { LitElement, html, css } from 'lit';
|
|
|
3
3
|
/**
|
|
4
4
|
* Accordion-style card stack with 3D perspective and image preview panel.
|
|
5
5
|
*
|
|
6
|
-
* Cards are provided via slotted elements with `slot="card"` and expand on click
|
|
7
|
-
* to reveal their content. A preview panel on the right displays the image
|
|
8
|
-
* associated with the active card. On mobile viewports the preview panel is
|
|
9
|
-
* hidden and images are shown inline within each card.
|
|
10
|
-
*
|
|
11
6
|
* @element device-card-stack
|
|
12
|
-
*
|
|
13
7
|
* @attr {Number} active-index - Index of the currently active card (default: 0)
|
|
14
|
-
* @attr {Number} mobile-breakpoint - Viewport width
|
|
15
|
-
* @attr {Number} stack-rotation - Rotation angle in degrees
|
|
16
|
-
* @attr {Number} transition-duration - Transition duration in
|
|
17
|
-
*
|
|
18
|
-
* @cssprop [--dcs-border-radius=20px] - Border radius of the outer wrapper
|
|
19
|
-
* @cssprop [--dcs-height=700px] - Height of the component in desktop mode
|
|
20
|
-
* @cssprop [--dcs-preview-bg=#000] - Background color of the preview panel
|
|
21
|
-
* @cssprop [--dcs-text-color=#fff] - Text color for the card body title
|
|
22
|
-
* @cssprop [--dcs-title-size=3.5rem] - Font size of the expanded card title
|
|
23
|
-
*
|
|
24
|
-
* @slot card - Card elements with data-title, data-color, data-image, and data-num attributes
|
|
25
|
-
*
|
|
26
|
-
* @fires card-activated - Fired when a card is activated. detail: { index, title }
|
|
8
|
+
* @attr {Number} mobile-breakpoint - Viewport width below which mobile layout is used (default: 768)
|
|
9
|
+
* @attr {Number} stack-rotation - Rotation angle in degrees for inactive cards (default: 3)
|
|
10
|
+
* @attr {Number} transition-duration - Transition duration in ms (default: 500)
|
|
11
|
+
* @slot card - Card elements with data-title, data-color, data-image, data-num attributes
|
|
27
12
|
*/
|
|
28
13
|
export class DeviceCardStack extends LitElement {
|
|
29
14
|
static properties = {
|
|
@@ -111,6 +96,14 @@ export class DeviceCardStack extends LitElement {
|
|
|
111
96
|
flex-shrink: 0;
|
|
112
97
|
}
|
|
113
98
|
|
|
99
|
+
.card[data-light] .card-header {
|
|
100
|
+
color: rgba(0, 0, 0, 0.85);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.card[data-light] .card-body-title {
|
|
104
|
+
color: #1a1618;
|
|
105
|
+
}
|
|
106
|
+
|
|
114
107
|
.card-num {
|
|
115
108
|
margin-right: 15px;
|
|
116
109
|
font-weight: 400;
|
|
@@ -146,21 +139,18 @@ export class DeviceCardStack extends LitElement {
|
|
|
146
139
|
/* Mobile inline image */
|
|
147
140
|
.card-mobile-image {
|
|
148
141
|
display: none;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
:host([data-mobile]) .card[data-active] .card-mobile-image {
|
|
152
|
-
display: block;
|
|
153
|
-
width: 100%;
|
|
154
|
-
margin-bottom: 20px;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
:host([data-mobile]) .card[data-active] .card-mobile-image img {
|
|
158
142
|
width: 100%;
|
|
143
|
+
height: auto;
|
|
159
144
|
max-height: 200px;
|
|
160
145
|
object-fit: contain;
|
|
146
|
+
margin-bottom: 20px;
|
|
161
147
|
border-radius: 8px;
|
|
162
148
|
}
|
|
163
149
|
|
|
150
|
+
:host([data-mobile]) .card[data-active] .card-mobile-image {
|
|
151
|
+
display: block;
|
|
152
|
+
}
|
|
153
|
+
|
|
164
154
|
/* Preview panel (right) */
|
|
165
155
|
.preview-panel {
|
|
166
156
|
width: 50%;
|
|
@@ -228,7 +218,7 @@ export class DeviceCardStack extends LitElement {
|
|
|
228
218
|
font-size: 2rem;
|
|
229
219
|
}
|
|
230
220
|
|
|
231
|
-
:host([data-mobile]) .card-mobile-image
|
|
221
|
+
:host([data-mobile]) .card-mobile-image {
|
|
232
222
|
max-height: 160px;
|
|
233
223
|
}
|
|
234
224
|
|
|
@@ -381,6 +371,15 @@ export class DeviceCardStack extends LitElement {
|
|
|
381
371
|
});
|
|
382
372
|
}
|
|
383
373
|
|
|
374
|
+
_isLightColor(hex) {
|
|
375
|
+
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
376
|
+
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
377
|
+
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
378
|
+
const toLinear = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
|
|
379
|
+
const luminance = 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
|
|
380
|
+
return luminance > 0.18;
|
|
381
|
+
}
|
|
382
|
+
|
|
384
383
|
_getCardTransform(index) {
|
|
385
384
|
if (this._reducedMotion) return 'none';
|
|
386
385
|
|
|
@@ -430,6 +429,7 @@ export class DeviceCardStack extends LitElement {
|
|
|
430
429
|
role="tab"
|
|
431
430
|
data-index="${i}"
|
|
432
431
|
?data-active=${i === this.activeIndex}
|
|
432
|
+
?data-light=${this._isLightColor(card.color)}
|
|
433
433
|
aria-selected=${i === this.activeIndex ? 'true' : 'false'}
|
|
434
434
|
aria-controls="panel-${i}"
|
|
435
435
|
tabindex=${i === this.activeIndex ? '0' : '-1'}
|
|
@@ -451,13 +451,15 @@ export class DeviceCardStack extends LitElement {
|
|
|
451
451
|
class="card-body"
|
|
452
452
|
role="tabpanel"
|
|
453
453
|
aria-hidden=${i === this.activeIndex ? 'false' : 'true'}
|
|
454
|
+
.inert=${i !== this.activeIndex}
|
|
454
455
|
>
|
|
455
456
|
${card.image
|
|
456
|
-
? html`<picture
|
|
457
|
+
? html`<picture>
|
|
457
458
|
${card.imageWebp
|
|
458
|
-
? html`<source
|
|
459
|
+
? html`<source srcset="${card.imageWebp}" type="image/webp" />`
|
|
459
460
|
: ''}
|
|
460
461
|
<img
|
|
462
|
+
class="card-mobile-image"
|
|
461
463
|
src="${card.image}"
|
|
462
464
|
alt="${card.title}"
|
|
463
465
|
loading="lazy"
|
|
@@ -481,7 +483,7 @@ export class DeviceCardStack extends LitElement {
|
|
|
481
483
|
${card.image
|
|
482
484
|
? html`<picture>
|
|
483
485
|
${card.imageWebp
|
|
484
|
-
? html`<source
|
|
486
|
+
? html`<source srcset="${card.imageWebp}" type="image/webp" />`
|
|
485
487
|
: ''}
|
|
486
488
|
<img
|
|
487
489
|
src="${card.image}"
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 manufosela
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|