barua-ui 0.3.0 → 0.3.2
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/css/components/content.css +30 -1
- package/css/components/media.css +28 -0
- package/dist/index.cjs +26 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -3
- package/dist/index.d.ts +23 -3
- package/dist/index.js +27 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -33,7 +33,36 @@
|
|
|
33
33
|
}
|
|
34
34
|
.b-card__title { font-size: var(--b-text-headline); font-weight: var(--b-weight-semibold); }
|
|
35
35
|
.b-card__subtitle { font-size: var(--b-text-footnote); color: var(--b-text-secondary); }
|
|
36
|
-
|
|
36
|
+
/*
|
|
37
|
+
* The media slot works two ways and only one of them used to.
|
|
38
|
+
*
|
|
39
|
+
* When the slot IS the picture — <img class="b-card__media"> — object-fit
|
|
40
|
+
* crops it and all is well. When it WRAPS one, which is what a card with a
|
|
41
|
+
* zoom button or an async image needs, object-fit does nothing: it only
|
|
42
|
+
* applies to replaced elements. The child then rendered at its natural size
|
|
43
|
+
* and burst out of the card, and anything positioned absolutely inside it
|
|
44
|
+
* escaped to the page, because there was no positioned ancestor to hold it.
|
|
45
|
+
*/
|
|
46
|
+
.b-card__media {
|
|
47
|
+
position: relative;
|
|
48
|
+
width: 100%;
|
|
49
|
+
aspect-ratio: 16 / 9;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
object-fit: cover;
|
|
52
|
+
}
|
|
53
|
+
/* Direct children fill the slot; the picture fills whatever wraps it, at any
|
|
54
|
+
depth, because a zoom button or an async-image span usually sits between. */
|
|
55
|
+
.b-card__media > * {
|
|
56
|
+
display: block;
|
|
57
|
+
width: 100%;
|
|
58
|
+
height: 100%;
|
|
59
|
+
}
|
|
60
|
+
.b-card__media :is(img, video, picture) {
|
|
61
|
+
display: block;
|
|
62
|
+
width: 100%;
|
|
63
|
+
height: 100%;
|
|
64
|
+
object-fit: cover;
|
|
65
|
+
}
|
|
37
66
|
.b-card__eyebrow {
|
|
38
67
|
font-size: var(--b-text-caption);
|
|
39
68
|
font-weight: var(--b-weight-semibold);
|
package/css/components/media.css
CHANGED
|
@@ -232,6 +232,34 @@
|
|
|
232
232
|
opacity: 0;
|
|
233
233
|
transition: opacity var(--b-duration-slow) var(--b-ease-out);
|
|
234
234
|
}
|
|
235
|
+
/* ---- Blur-up ------------------------------------------------------------
|
|
236
|
+
*
|
|
237
|
+
* A shimmer says "something is coming". A blurred copy of the actual picture
|
|
238
|
+
* says "this is what is coming", which is a different and better promise —
|
|
239
|
+
* the layout is right, the colours are right, and the photograph resolves
|
|
240
|
+
* rather than appearing.
|
|
241
|
+
*
|
|
242
|
+
* The placeholder is a thumbnail small enough to inline: a 32px-wide JPEG is
|
|
243
|
+
* around a kilobyte, so it costs nothing and arrives with the markup. Give
|
|
244
|
+
* it as a data URI on --b-img-placeholder and mark the host with
|
|
245
|
+
* data-placeholder, which is what tells the shimmer to stand down.
|
|
246
|
+
*/
|
|
247
|
+
.b-async-img[data-placeholder]::before { display: none; }
|
|
248
|
+
|
|
249
|
+
.b-async-img[data-placeholder]::after {
|
|
250
|
+
content: "";
|
|
251
|
+
position: absolute;
|
|
252
|
+
inset: 0;
|
|
253
|
+
background: var(--b-img-placeholder) center / cover no-repeat;
|
|
254
|
+
/* Scaled up because a blur samples past the edges and would otherwise
|
|
255
|
+
leave a soft border all the way round. */
|
|
256
|
+
filter: blur(14px);
|
|
257
|
+
transform: scale(1.1);
|
|
258
|
+
transition: opacity var(--b-duration-slow) var(--b-ease-out);
|
|
259
|
+
pointer-events: none;
|
|
260
|
+
}
|
|
261
|
+
.b-async-img[data-placeholder].is-loaded::after { opacity: 0; }
|
|
262
|
+
|
|
235
263
|
.b-async-img.is-loaded::before { display: none; }
|
|
236
264
|
.b-async-img.is-loaded img { opacity: 1; }
|
|
237
265
|
|
package/dist/index.cjs
CHANGED
|
@@ -2395,7 +2395,32 @@ var OnboardingFeature = (0, import_react19.forwardRef)(
|
|
|
2395
2395
|
var import_react20 = require("react");
|
|
2396
2396
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2397
2397
|
var MediaPlaceholder = block("div", "b-media-placeholder", "MediaPlaceholder");
|
|
2398
|
-
var AsyncImage =
|
|
2398
|
+
var AsyncImage = (0, import_react20.forwardRef)(function AsyncImage2({ src, alt, placeholder, aspect, className, style, ...rest }, ref) {
|
|
2399
|
+
const [loaded, setLoaded] = (0, import_react20.useState)(false);
|
|
2400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2401
|
+
"span",
|
|
2402
|
+
{
|
|
2403
|
+
className: cn("b-async-img", loaded && "is-loaded", className),
|
|
2404
|
+
"data-placeholder": placeholder ? "" : void 0,
|
|
2405
|
+
style: {
|
|
2406
|
+
...aspect ? { aspectRatio: aspect } : null,
|
|
2407
|
+
...placeholder ? { ["--b-img-placeholder"]: `url("${placeholder}")` } : null,
|
|
2408
|
+
...style
|
|
2409
|
+
},
|
|
2410
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2411
|
+
"img",
|
|
2412
|
+
{
|
|
2413
|
+
ref,
|
|
2414
|
+
src,
|
|
2415
|
+
alt,
|
|
2416
|
+
onLoad: () => setLoaded(true),
|
|
2417
|
+
onError: () => setLoaded(true),
|
|
2418
|
+
...rest
|
|
2419
|
+
}
|
|
2420
|
+
)
|
|
2421
|
+
}
|
|
2422
|
+
);
|
|
2423
|
+
});
|
|
2399
2424
|
var Web = block("div", "b-web", "Web");
|
|
2400
2425
|
var Video = block("video", "b-video", "Video");
|
|
2401
2426
|
var Audio = block("div", "b-audio", "Audio");
|