@at-flux/astroflare 1.0.10 → 1.0.12
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 +1 -1
- package/src/components/ImageFade.astro +64 -10
package/package.json
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
* Reserve layout space with `aspectRatio` to avoid CLS. Styling is theme-aware
|
|
11
11
|
* via `--color-brand` (override with `spinnerColor`).
|
|
12
12
|
*
|
|
13
|
+
* The wrapper only controls the slotted image's opacity — size the image and
|
|
14
|
+
* choose its `object-fit` with your own classes, exactly as you would without
|
|
15
|
+
* this wrapper.
|
|
16
|
+
*
|
|
13
17
|
* @example
|
|
14
18
|
* <ImageFade aspectRatio="16/9" rounded="rounded-2xl">
|
|
15
19
|
* <Image src={hero} alt="…" />
|
|
@@ -26,6 +30,12 @@ interface Props {
|
|
|
26
30
|
duration?: number;
|
|
27
31
|
/** Spinner/skeleton accent colour (defaults to `--color-brand`). */
|
|
28
32
|
spinnerColor?: string;
|
|
33
|
+
/** Second accent, used by the counter-rotating inner ring (defaults to `spinnerColor`). */
|
|
34
|
+
spinnerColorSecondary?: string;
|
|
35
|
+
/** Outer ring diameter, any CSS length. */
|
|
36
|
+
spinnerSize?: string;
|
|
37
|
+
/** Wrapper background shown behind the image. Pass `"transparent"` for `object-contain` images. */
|
|
38
|
+
background?: string;
|
|
29
39
|
/** Show a shimmer skeleton instead of a spinner. */
|
|
30
40
|
skeleton?: boolean;
|
|
31
41
|
}
|
|
@@ -36,12 +46,18 @@ const {
|
|
|
36
46
|
aspectRatio,
|
|
37
47
|
duration = 500,
|
|
38
48
|
spinnerColor,
|
|
49
|
+
spinnerColorSecondary,
|
|
50
|
+
spinnerSize,
|
|
51
|
+
background,
|
|
39
52
|
skeleton = false,
|
|
40
53
|
} = Astro.props;
|
|
41
54
|
|
|
42
55
|
const style = [
|
|
43
56
|
aspectRatio ? `aspect-ratio:${aspectRatio}` : '',
|
|
44
57
|
spinnerColor ? `--if-accent:${spinnerColor}` : '',
|
|
58
|
+
spinnerColorSecondary ? `--if-accent-2:${spinnerColorSecondary}` : '',
|
|
59
|
+
spinnerSize ? `--if-size:${spinnerSize}` : '',
|
|
60
|
+
background ? `--if-bg:${background}` : '',
|
|
45
61
|
`--if-duration:${duration}ms`,
|
|
46
62
|
]
|
|
47
63
|
.filter(Boolean)
|
|
@@ -50,7 +66,13 @@ const style = [
|
|
|
50
66
|
|
|
51
67
|
<image-fade class:list={['image-fade', skeleton && 'is-skeleton', rounded, className]} style={style}>
|
|
52
68
|
<span class='image-fade__placeholder' aria-hidden='true'>
|
|
53
|
-
{
|
|
69
|
+
{
|
|
70
|
+
!skeleton && (
|
|
71
|
+
<span class='image-fade__ring'>
|
|
72
|
+
<span class='image-fade__ring-inner' />
|
|
73
|
+
</span>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
54
76
|
</span>
|
|
55
77
|
<slot />
|
|
56
78
|
</image-fade>
|
|
@@ -60,16 +82,18 @@ const style = [
|
|
|
60
82
|
position: relative;
|
|
61
83
|
display: block;
|
|
62
84
|
overflow: hidden;
|
|
63
|
-
background:
|
|
85
|
+
background: var(
|
|
86
|
+
--if-bg,
|
|
87
|
+
color-mix(in oklab, var(--if-accent, var(--color-brand, #7c5cff)) 8%, transparent)
|
|
88
|
+
);
|
|
64
89
|
}
|
|
65
90
|
|
|
66
|
-
/* Slotted image starts hidden, fades in once loaded
|
|
91
|
+
/* Slotted image starts hidden, fades in once loaded.
|
|
92
|
+
Only opacity is owned here — sizing and `object-fit` stay with the caller
|
|
93
|
+
so consumer classes (`object-contain`, `object-fill`, …) are not overridden. */
|
|
67
94
|
image-fade.image-fade > img,
|
|
68
95
|
image-fade.image-fade > picture > img {
|
|
69
96
|
display: block;
|
|
70
|
-
width: 100%;
|
|
71
|
-
height: 100%;
|
|
72
|
-
object-fit: cover;
|
|
73
97
|
opacity: 0;
|
|
74
98
|
transition: opacity var(--if-duration, 500ms) ease-out;
|
|
75
99
|
}
|
|
@@ -93,8 +117,10 @@ const style = [
|
|
|
93
117
|
}
|
|
94
118
|
|
|
95
119
|
.image-fade__ring {
|
|
96
|
-
|
|
97
|
-
|
|
120
|
+
position: relative;
|
|
121
|
+
display: block;
|
|
122
|
+
width: var(--if-size, 2.5rem);
|
|
123
|
+
height: var(--if-size, 2.5rem);
|
|
98
124
|
border: 3px solid transparent;
|
|
99
125
|
border-top-color: var(--if-accent, var(--color-brand, #7c5cff));
|
|
100
126
|
border-right-color: color-mix(
|
|
@@ -103,7 +129,28 @@ const style = [
|
|
|
103
129
|
transparent
|
|
104
130
|
);
|
|
105
131
|
border-radius: 50%;
|
|
106
|
-
|
|
132
|
+
/* `transform` is reset explicitly: a host page may set a base transform on
|
|
133
|
+
every element (e.g. a `* { transform: translateZ(0) }` GPU hint), which
|
|
134
|
+
would otherwise make the keyframes interpolate as matrices and cancel the
|
|
135
|
+
full turn out to no visible rotation. */
|
|
136
|
+
transform: rotate(0deg);
|
|
137
|
+
animation: image-fade-spin 1.2s linear infinite;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.image-fade__ring-inner {
|
|
141
|
+
position: absolute;
|
|
142
|
+
top: 50%;
|
|
143
|
+
left: 50%;
|
|
144
|
+
display: block;
|
|
145
|
+
width: 60%;
|
|
146
|
+
height: 60%;
|
|
147
|
+
margin: -30% 0 0 -30%;
|
|
148
|
+
border: 2px solid transparent;
|
|
149
|
+
border-top-color: var(--if-accent-2, var(--if-accent, var(--color-brand, #7c5cff)));
|
|
150
|
+
border-right-color: var(--if-accent-2, var(--if-accent, var(--color-brand, #7c5cff)));
|
|
151
|
+
border-radius: 50%;
|
|
152
|
+
transform: rotate(0deg);
|
|
153
|
+
animation: image-fade-spin 0.8s linear infinite reverse;
|
|
107
154
|
}
|
|
108
155
|
|
|
109
156
|
/* Skeleton variant: shimmer sweep instead of a spinner */
|
|
@@ -118,7 +165,13 @@ const style = [
|
|
|
118
165
|
animation: image-fade-shimmer 1.4s ease-in-out infinite;
|
|
119
166
|
}
|
|
120
167
|
|
|
168
|
+
/* Both frames are explicit so the interpolation stays angular. An implicit
|
|
169
|
+
`from` would be taken from the element's computed transform, which is not
|
|
170
|
+
guaranteed to be `none` on every host page. */
|
|
121
171
|
@keyframes image-fade-spin {
|
|
172
|
+
from {
|
|
173
|
+
transform: rotate(0deg);
|
|
174
|
+
}
|
|
122
175
|
to {
|
|
123
176
|
transform: rotate(360deg);
|
|
124
177
|
}
|
|
@@ -138,7 +191,8 @@ const style = [
|
|
|
138
191
|
.image-fade__placeholder {
|
|
139
192
|
transition: none;
|
|
140
193
|
}
|
|
141
|
-
.image-fade__ring
|
|
194
|
+
.image-fade__ring,
|
|
195
|
+
.image-fade__ring-inner {
|
|
142
196
|
animation: none;
|
|
143
197
|
}
|
|
144
198
|
image-fade.image-fade.is-skeleton .image-fade__placeholder {
|