@nationaldesignstudio/react 0.0.17 → 0.0.19
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/dist/component-registry.md +181 -29
- package/dist/components/atoms/background/background.d.ts +135 -0
- package/dist/components/atoms/button/button.d.ts +64 -82
- package/dist/components/atoms/button/icon-button.d.ts +100 -66
- package/dist/components/organisms/card/card.d.ts +130 -4
- package/dist/components/organisms/us-gov-banner/us-gov-banner.d.ts +120 -2
- package/dist/components/sections/hero/hero.d.ts +166 -150
- package/dist/components/sections/quote-block/quote-block.d.ts +152 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +3868 -5978
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.d.ts +1 -2
- package/dist/tokens.css +207 -16
- package/package.json +2 -4
- package/src/components/atoms/background/background.tsx +377 -0
- package/src/components/atoms/background/index.ts +22 -0
- package/src/components/atoms/button/button.stories.tsx +81 -32
- package/src/components/atoms/button/button.tsx +91 -49
- package/src/components/atoms/button/icon-button.stories.tsx +179 -28
- package/src/components/atoms/button/icon-button.tsx +111 -49
- package/src/components/organisms/card/card.tsx +82 -24
- package/src/components/organisms/card/index.ts +7 -0
- package/src/components/organisms/us-gov-banner/index.ts +5 -1
- package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +72 -16
- package/src/components/sections/hero/hero.stories.tsx +124 -1
- package/src/components/sections/hero/hero.test.tsx +21 -18
- package/src/components/sections/hero/hero.tsx +188 -301
- package/src/components/sections/hero/index.ts +13 -0
- package/src/components/sections/quote-block/index.ts +5 -0
- package/src/components/sections/quote-block/quote-block.tsx +216 -0
- package/src/index.ts +40 -0
- package/src/lib/utils.ts +1 -6
- package/src/stories/ThemeProvider.stories.tsx +5 -5
package/dist/lib/utils.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function cn(...inputs: ClassValue[]): string;
|
|
1
|
+
export { cnBase as cn } from 'tailwind-variants';
|
package/dist/tokens.css
CHANGED
|
@@ -294,7 +294,12 @@
|
|
|
294
294
|
--color-yellow-v200: color(srgb 1 1 0.3294);
|
|
295
295
|
--color-yellow-v300: color(srgb 0.9882 0.9216 0.3059);
|
|
296
296
|
--color-yellow-v400: color(srgb 0.9765 0.8431 0.2863);
|
|
297
|
+
--font-cormorant: Cormorant, serif;
|
|
298
|
+
--font-gloock: Gloock, serif;
|
|
297
299
|
--font-pp-neue-montreal: "PP Neue Montreal";
|
|
300
|
+
--font-sans: "PP Neue Montreal";
|
|
301
|
+
--font-serif-alt: Cormorant, serif;
|
|
302
|
+
--font-serif: Gloock, serif;
|
|
298
303
|
--font-weight-medium: 500;
|
|
299
304
|
--font-weight-regular: 400;
|
|
300
305
|
--font-weight-semibold: 600;
|
|
@@ -601,6 +606,18 @@
|
|
|
601
606
|
--spatial-grid-small-columns: 4;
|
|
602
607
|
--spatial-grid-small-gutter: 12px;
|
|
603
608
|
--spatial-grid-small-margin: 24px;
|
|
609
|
+
--spatial-layout-medium-large-span: 8;
|
|
610
|
+
--spatial-layout-medium-large-start: 3;
|
|
611
|
+
--spatial-layout-medium-medium-span: 10;
|
|
612
|
+
--spatial-layout-medium-medium-start: 2;
|
|
613
|
+
--spatial-layout-narrow-large-span: 8;
|
|
614
|
+
--spatial-layout-narrow-large-start: 3;
|
|
615
|
+
--spatial-layout-narrow-medium-span: 8;
|
|
616
|
+
--spatial-layout-narrow-medium-start: 3;
|
|
617
|
+
--spatial-layout-wide-large-span: 10;
|
|
618
|
+
--spatial-layout-wide-large-start: 2;
|
|
619
|
+
--spatial-layout-wide-medium-span: 12;
|
|
620
|
+
--spatial-layout-wide-medium-start: 1;
|
|
604
621
|
--spatial-section-large-gap: 64px;
|
|
605
622
|
--spatial-section-large-padding: 128px;
|
|
606
623
|
--spatial-section-medium-gap: 56px;
|
|
@@ -957,7 +974,12 @@
|
|
|
957
974
|
--color-yellow-v200: var(--color-yellow-v200);
|
|
958
975
|
--color-yellow-v300: var(--color-yellow-v300);
|
|
959
976
|
--color-yellow-v400: var(--color-yellow-v400);
|
|
977
|
+
--font-cormorant: var(--font-cormorant);
|
|
978
|
+
--font-gloock: var(--font-gloock);
|
|
960
979
|
--font-pp-neue-montreal: var(--font-pp-neue-montreal);
|
|
980
|
+
--font-sans: var(--font-sans);
|
|
981
|
+
--font-serif-alt: var(--font-serif-alt);
|
|
982
|
+
--font-serif: var(--font-serif);
|
|
961
983
|
--font-weight-medium: var(--font-weight-medium);
|
|
962
984
|
--font-weight-regular: var(--font-weight-regular);
|
|
963
985
|
--font-weight-semibold: var(--font-weight-semibold);
|
|
@@ -995,6 +1017,9 @@
|
|
|
995
1017
|
--leading-88: var(--leading-88);
|
|
996
1018
|
--leading-96: var(--leading-96);
|
|
997
1019
|
--leading-9: var(--leading-9);
|
|
1020
|
+
--max-width-desktop: 1440px;
|
|
1021
|
+
--max-width-mobile: 320px;
|
|
1022
|
+
--max-width-tablet: 768px;
|
|
998
1023
|
--radius-0: var(--radius-0);
|
|
999
1024
|
--radius-10: var(--radius-10);
|
|
1000
1025
|
--radius-12: var(--radius-12);
|
|
@@ -1264,6 +1289,18 @@
|
|
|
1264
1289
|
--spatial-grid-small-columns: var(--spatial-grid-small-columns);
|
|
1265
1290
|
--spatial-grid-small-gutter: var(--spatial-grid-small-gutter);
|
|
1266
1291
|
--spatial-grid-small-margin: var(--spatial-grid-small-margin);
|
|
1292
|
+
--spatial-layout-medium-large-span: var(--spatial-layout-medium-large-span);
|
|
1293
|
+
--spatial-layout-medium-large-start: var(--spatial-layout-medium-large-start);
|
|
1294
|
+
--spatial-layout-medium-medium-span: var(--spatial-layout-medium-medium-span);
|
|
1295
|
+
--spatial-layout-medium-medium-start: var(--spatial-layout-medium-medium-start);
|
|
1296
|
+
--spatial-layout-narrow-large-span: var(--spatial-layout-narrow-large-span);
|
|
1297
|
+
--spatial-layout-narrow-large-start: var(--spatial-layout-narrow-large-start);
|
|
1298
|
+
--spatial-layout-narrow-medium-span: var(--spatial-layout-narrow-medium-span);
|
|
1299
|
+
--spatial-layout-narrow-medium-start: var(--spatial-layout-narrow-medium-start);
|
|
1300
|
+
--spatial-layout-wide-large-span: var(--spatial-layout-wide-large-span);
|
|
1301
|
+
--spatial-layout-wide-large-start: var(--spatial-layout-wide-large-start);
|
|
1302
|
+
--spatial-layout-wide-medium-span: var(--spatial-layout-wide-medium-span);
|
|
1303
|
+
--spatial-layout-wide-medium-start: var(--spatial-layout-wide-medium-start);
|
|
1267
1304
|
--spatial-section-large-gap: var(--spatial-section-large-gap);
|
|
1268
1305
|
--spatial-section-large-padding: var(--spatial-section-large-padding);
|
|
1269
1306
|
--spatial-section-medium-gap: var(--spatial-section-medium-gap);
|
|
@@ -1411,26 +1448,26 @@
|
|
|
1411
1448
|
|
|
1412
1449
|
:root {
|
|
1413
1450
|
/* Semantic Color Tokens */
|
|
1414
|
-
--color-accent-brand-soft: color(srgb 0.
|
|
1415
|
-
--color-accent-brand: color(srgb 0.
|
|
1416
|
-
--color-bg-muted: color(srgb
|
|
1417
|
-
--color-bg-page: color(srgb 0.
|
|
1418
|
-
--color-bg-section: color(srgb 0.9608 0.
|
|
1419
|
-
--color-border-divider: color(srgb 0 0 0 / 0.1);
|
|
1420
|
-
--color-border-focus: color(srgb 0.
|
|
1421
|
-
--color-border-strong: color(srgb 0 0 0 / 0.2);
|
|
1422
|
-
--color-border-subtle: color(srgb 0 0 0 / 0.1);
|
|
1423
|
-
--color-button-primary-bg-hover: color(srgb 0.
|
|
1424
|
-
--color-button-primary-bg: color(srgb 0.
|
|
1451
|
+
--color-accent-brand-soft: color(srgb 0.7686 0.6588 0.4392);
|
|
1452
|
+
--color-accent-brand: color(srgb 0.651 0.5451 0.3686);
|
|
1453
|
+
--color-bg-muted: color(srgb 0.9961 0.9922 0.9765);
|
|
1454
|
+
--color-bg-page: color(srgb 0.9961 0.9922 0.9765);
|
|
1455
|
+
--color-bg-section: color(srgb 0.9608 0.9569 0.9373);
|
|
1456
|
+
--color-border-divider: color(srgb 0.149 0.1569 0.2941 / 0.1);
|
|
1457
|
+
--color-border-focus: color(srgb 0.651 0.5451 0.3686);
|
|
1458
|
+
--color-border-strong: color(srgb 0.149 0.1569 0.2941 / 0.2);
|
|
1459
|
+
--color-border-subtle: color(srgb 0.149 0.1569 0.2941 / 0.1);
|
|
1460
|
+
--color-button-primary-bg-hover: color(srgb 0.149 0.1569 0.2941);
|
|
1461
|
+
--color-button-primary-bg: color(srgb 0.0667 0.0745 0.149);
|
|
1425
1462
|
--color-button-secondary-bg-hover: color(srgb 1 1 1);
|
|
1426
1463
|
--color-button-secondary-bg: color(srgb 1 1 1);
|
|
1427
|
-
--color-card-background: color(srgb
|
|
1428
|
-
--color-text-inverted: color(srgb 0.
|
|
1464
|
+
--color-card-background: color(srgb 0.5412 0.4353 0.2588);
|
|
1465
|
+
--color-text-inverted: color(srgb 0.9961 0.9922 0.9765);
|
|
1429
1466
|
--color-text-link-hover: color(srgb 0.3804 0.3804 0.3804);
|
|
1430
1467
|
--color-text-link: color(srgb 0.0784 0.0784 0.0784);
|
|
1431
|
-
--color-text-muted: color(srgb 0.
|
|
1432
|
-
--color-text-primary: color(srgb 0.
|
|
1433
|
-
--color-text-secondary: color(srgb 0.
|
|
1468
|
+
--color-text-muted: color(srgb 0.651 0.5451 0.3686);
|
|
1469
|
+
--color-text-primary: color(srgb 0.0667 0.0745 0.149);
|
|
1470
|
+
--color-text-secondary: color(srgb 0.0667 0.0745 0.149);
|
|
1434
1471
|
--radius-surface-button: var(--radius-6);
|
|
1435
1472
|
--radius-surface-card: var(--radius-4);
|
|
1436
1473
|
--surface-button-stroke: 1px;
|
|
@@ -1466,6 +1503,102 @@
|
|
|
1466
1503
|
}
|
|
1467
1504
|
|
|
1468
1505
|
|
|
1506
|
+
@utility typography-bop-body-large {
|
|
1507
|
+
font-family: var(--font-cormorant);
|
|
1508
|
+
font-size: 28px;
|
|
1509
|
+
font-weight: var(--font-weight-medium);
|
|
1510
|
+
line-height: 1.4;
|
|
1511
|
+
letter-spacing: 0;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
@utility typography-bop-body-medium {
|
|
1515
|
+
font-family: var(--font-cormorant);
|
|
1516
|
+
font-size: 18px;
|
|
1517
|
+
font-weight: var(--font-weight-regular);
|
|
1518
|
+
line-height: 1.5;
|
|
1519
|
+
letter-spacing: 0;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
@utility typography-bop-body-small {
|
|
1523
|
+
font-family: var(--font-cormorant);
|
|
1524
|
+
font-size: 16px;
|
|
1525
|
+
font-weight: var(--font-weight-regular);
|
|
1526
|
+
line-height: 1.5;
|
|
1527
|
+
letter-spacing: 0;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
@utility typography-bop-display-hero {
|
|
1531
|
+
font-family: var(--font-gloock);
|
|
1532
|
+
font-size: 12.5vw;
|
|
1533
|
+
font-weight: var(--font-weight-regular);
|
|
1534
|
+
line-height: 1.1;
|
|
1535
|
+
letter-spacing: -0.03em;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
@utility typography-bop-display-large {
|
|
1539
|
+
font-family: var(--font-gloock);
|
|
1540
|
+
font-size: 8vw;
|
|
1541
|
+
font-weight: var(--font-weight-regular);
|
|
1542
|
+
line-height: 1.1;
|
|
1543
|
+
letter-spacing: -0.025em;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
@utility typography-bop-display-medium {
|
|
1547
|
+
font-family: var(--font-gloock);
|
|
1548
|
+
font-size: 5vw;
|
|
1549
|
+
font-weight: var(--font-weight-regular);
|
|
1550
|
+
line-height: 1.2;
|
|
1551
|
+
letter-spacing: -0.02em;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
@utility typography-bop-headline-large {
|
|
1555
|
+
font-family: var(--font-cormorant);
|
|
1556
|
+
font-size: 48px;
|
|
1557
|
+
font-weight: var(--font-weight-medium);
|
|
1558
|
+
line-height: 1.2;
|
|
1559
|
+
letter-spacing: -1px;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
@utility typography-bop-headline-medium {
|
|
1563
|
+
font-family: var(--font-cormorant);
|
|
1564
|
+
font-size: 32px;
|
|
1565
|
+
font-weight: var(--font-weight-medium);
|
|
1566
|
+
line-height: 0.95;
|
|
1567
|
+
letter-spacing: -1px;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
@utility typography-bop-headline-small {
|
|
1571
|
+
font-family: var(--font-cormorant);
|
|
1572
|
+
font-size: 24px;
|
|
1573
|
+
font-weight: var(--font-weight-medium);
|
|
1574
|
+
line-height: 1.2;
|
|
1575
|
+
letter-spacing: -0.5px;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
@utility typography-bop-ui-button {
|
|
1579
|
+
font-family: var(--font-pp-neue-montreal);
|
|
1580
|
+
font-size: 16px;
|
|
1581
|
+
font-weight: var(--font-weight-medium);
|
|
1582
|
+
line-height: 1;
|
|
1583
|
+
letter-spacing: 0.5px;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
@utility typography-bop-ui-caption {
|
|
1587
|
+
font-family: var(--font-pp-neue-montreal);
|
|
1588
|
+
font-size: 14px;
|
|
1589
|
+
font-weight: var(--font-weight-regular);
|
|
1590
|
+
line-height: 1.4;
|
|
1591
|
+
letter-spacing: 0;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
@utility typography-bop-ui-nav {
|
|
1595
|
+
font-family: var(--font-pp-neue-montreal);
|
|
1596
|
+
font-size: 13px;
|
|
1597
|
+
font-weight: var(--font-weight-medium);
|
|
1598
|
+
line-height: 0.95;
|
|
1599
|
+
letter-spacing: 0;
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1469
1602
|
@utility typography-large-body-large {
|
|
1470
1603
|
font-family: var(--font-pp-neue-montreal);
|
|
1471
1604
|
font-size: var(--text-21);
|
|
@@ -24051,6 +24184,32 @@
|
|
|
24051
24184
|
}
|
|
24052
24185
|
|
|
24053
24186
|
|
|
24187
|
+
/* Font Family Utilities */
|
|
24188
|
+
@utility font-cormorant {
|
|
24189
|
+
font-family: var(--font-cormorant);
|
|
24190
|
+
}
|
|
24191
|
+
|
|
24192
|
+
@utility font-gloock {
|
|
24193
|
+
font-family: var(--font-gloock);
|
|
24194
|
+
}
|
|
24195
|
+
|
|
24196
|
+
@utility font-pp-neue-montreal {
|
|
24197
|
+
font-family: var(--font-pp-neue-montreal);
|
|
24198
|
+
}
|
|
24199
|
+
|
|
24200
|
+
@utility font-sans {
|
|
24201
|
+
font-family: var(--font-sans);
|
|
24202
|
+
}
|
|
24203
|
+
|
|
24204
|
+
@utility font-serif {
|
|
24205
|
+
font-family: var(--font-serif);
|
|
24206
|
+
}
|
|
24207
|
+
|
|
24208
|
+
@utility font-serif-alt {
|
|
24209
|
+
font-family: var(--font-serif-alt);
|
|
24210
|
+
}
|
|
24211
|
+
|
|
24212
|
+
|
|
24054
24213
|
/* Surface Utilities */
|
|
24055
24214
|
@utility rounded-surface-button {
|
|
24056
24215
|
border-radius: var(--radius-surface-button);
|
|
@@ -24158,4 +24317,36 @@
|
|
|
24158
24317
|
@utility stroke-y-surface-card {
|
|
24159
24318
|
border-top-width: var(--surface-card-stroke);
|
|
24160
24319
|
border-bottom-width: var(--surface-card-stroke);
|
|
24320
|
+
}
|
|
24321
|
+
|
|
24322
|
+
|
|
24323
|
+
/* Grid Content Layout Utilities */
|
|
24324
|
+
@utility grid-content-medium {
|
|
24325
|
+
grid-column: 1 / -1;
|
|
24326
|
+
@media (width >= 48rem) {
|
|
24327
|
+
grid-column: 2 / span 10;
|
|
24328
|
+
}
|
|
24329
|
+
@media (width >= 90rem) {
|
|
24330
|
+
grid-column: 3 / span 8;
|
|
24331
|
+
}
|
|
24332
|
+
}
|
|
24333
|
+
|
|
24334
|
+
@utility grid-content-narrow {
|
|
24335
|
+
grid-column: 1 / -1;
|
|
24336
|
+
@media (width >= 48rem) {
|
|
24337
|
+
grid-column: 3 / span 8;
|
|
24338
|
+
}
|
|
24339
|
+
@media (width >= 90rem) {
|
|
24340
|
+
grid-column: 3 / span 8;
|
|
24341
|
+
}
|
|
24342
|
+
}
|
|
24343
|
+
|
|
24344
|
+
@utility grid-content-wide {
|
|
24345
|
+
grid-column: 1 / -1;
|
|
24346
|
+
@media (width >= 48rem) {
|
|
24347
|
+
grid-column: 1 / span 12;
|
|
24348
|
+
}
|
|
24349
|
+
@media (width >= 90rem) {
|
|
24350
|
+
grid-column: 2 / span 10;
|
|
24351
|
+
}
|
|
24161
24352
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nationaldesignstudio/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"*.css"
|
|
@@ -47,9 +47,7 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@base-ui-components/react": "^1.0.0-rc.0",
|
|
49
49
|
"@radix-ui/react-slot": "^1.2.4",
|
|
50
|
-
"tailwind-variants": "^0.3.1"
|
|
51
|
-
"clsx": "^2.1.1",
|
|
52
|
-
"tailwind-merge": "^3.4.0"
|
|
50
|
+
"tailwind-variants": "^0.3.1"
|
|
53
51
|
},
|
|
54
52
|
"devDependencies": {
|
|
55
53
|
"@chromatic-com/storybook": "catalog:",
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
// =============================================================================
|
|
5
|
+
// Background Atomic Component
|
|
6
|
+
// =============================================================================
|
|
7
|
+
|
|
8
|
+
const backgroundVariants = tv({
|
|
9
|
+
base: "absolute inset-0",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Base container for background composition.
|
|
14
|
+
* Use as a wrapper to compose multiple background layers (image, video, overlay, gradient).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <Background>
|
|
19
|
+
* <Background.Image src="/hero.jpg" />
|
|
20
|
+
* <Background.Overlay opacity={0.4} />
|
|
21
|
+
* <Background.Gradient direction="to-t" from="black" to="transparent" />
|
|
22
|
+
* </Background>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export interface BackgroundProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
26
|
+
|
|
27
|
+
const Background = React.forwardRef<HTMLDivElement, BackgroundProps>(
|
|
28
|
+
({ className, children, ...props }, ref) => (
|
|
29
|
+
<div
|
|
30
|
+
ref={ref}
|
|
31
|
+
aria-hidden="true"
|
|
32
|
+
className={backgroundVariants({ class: className })}
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</div>
|
|
37
|
+
),
|
|
38
|
+
);
|
|
39
|
+
Background.displayName = "Background";
|
|
40
|
+
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// Background.Image
|
|
43
|
+
// =============================================================================
|
|
44
|
+
|
|
45
|
+
const backgroundImageVariants = tv({
|
|
46
|
+
base: "absolute inset-0 size-full object-cover",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export interface BackgroundImageProps
|
|
50
|
+
extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src"> {
|
|
51
|
+
/**
|
|
52
|
+
* URL for the background image
|
|
53
|
+
*/
|
|
54
|
+
src: string;
|
|
55
|
+
/**
|
|
56
|
+
* Object position (default: "center")
|
|
57
|
+
*/
|
|
58
|
+
position?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Background image layer using an actual img element with object-cover.
|
|
63
|
+
* Supports native lazy loading, srcset, and better accessibility.
|
|
64
|
+
*/
|
|
65
|
+
const BackgroundImage = React.forwardRef<
|
|
66
|
+
HTMLImageElement,
|
|
67
|
+
BackgroundImageProps
|
|
68
|
+
>(({ className, src, position = "center", alt = "", style, ...props }, ref) => (
|
|
69
|
+
<img
|
|
70
|
+
ref={ref}
|
|
71
|
+
src={src}
|
|
72
|
+
alt={alt}
|
|
73
|
+
className={backgroundImageVariants({ class: className })}
|
|
74
|
+
style={{
|
|
75
|
+
objectPosition: position,
|
|
76
|
+
...style,
|
|
77
|
+
}}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
));
|
|
81
|
+
BackgroundImage.displayName = "Background.Image";
|
|
82
|
+
|
|
83
|
+
// =============================================================================
|
|
84
|
+
// Background.Video
|
|
85
|
+
// =============================================================================
|
|
86
|
+
|
|
87
|
+
const backgroundVideoVariants = tv({
|
|
88
|
+
base: "absolute inset-0 size-full object-cover",
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
export interface BackgroundVideoProps
|
|
92
|
+
extends Omit<React.VideoHTMLAttributes<HTMLVideoElement>, "children"> {
|
|
93
|
+
/**
|
|
94
|
+
* URL for the video source
|
|
95
|
+
*/
|
|
96
|
+
src: string;
|
|
97
|
+
/**
|
|
98
|
+
* Video MIME type (default: auto-detected from src)
|
|
99
|
+
*/
|
|
100
|
+
type?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Poster image URL shown before video loads
|
|
103
|
+
*/
|
|
104
|
+
poster?: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Background video layer using HTML5 video element.
|
|
109
|
+
*/
|
|
110
|
+
const BackgroundVideo = React.forwardRef<
|
|
111
|
+
HTMLVideoElement,
|
|
112
|
+
BackgroundVideoProps
|
|
113
|
+
>(
|
|
114
|
+
(
|
|
115
|
+
{
|
|
116
|
+
className,
|
|
117
|
+
src,
|
|
118
|
+
type,
|
|
119
|
+
poster,
|
|
120
|
+
autoPlay = true,
|
|
121
|
+
loop = true,
|
|
122
|
+
muted = true,
|
|
123
|
+
playsInline = true,
|
|
124
|
+
...props
|
|
125
|
+
},
|
|
126
|
+
ref,
|
|
127
|
+
) => (
|
|
128
|
+
<video
|
|
129
|
+
ref={ref}
|
|
130
|
+
autoPlay={autoPlay}
|
|
131
|
+
loop={loop}
|
|
132
|
+
muted={muted}
|
|
133
|
+
playsInline={playsInline}
|
|
134
|
+
poster={poster}
|
|
135
|
+
className={backgroundVideoVariants({ class: className })}
|
|
136
|
+
{...props}
|
|
137
|
+
>
|
|
138
|
+
<source src={src} type={type} />
|
|
139
|
+
</video>
|
|
140
|
+
),
|
|
141
|
+
);
|
|
142
|
+
BackgroundVideo.displayName = "Background.Video";
|
|
143
|
+
|
|
144
|
+
// =============================================================================
|
|
145
|
+
// Background.Stream
|
|
146
|
+
// =============================================================================
|
|
147
|
+
|
|
148
|
+
const backgroundStreamVariants = tv({
|
|
149
|
+
base: "absolute inset-0 size-full border-0 scale-[1.5] object-cover",
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
export interface BackgroundStreamProps
|
|
153
|
+
extends React.IframeHTMLAttributes<HTMLIFrameElement> {
|
|
154
|
+
/**
|
|
155
|
+
* Cloudflare Stream video ID
|
|
156
|
+
*/
|
|
157
|
+
videoId: string;
|
|
158
|
+
/**
|
|
159
|
+
* Poster image URL (Cloudflare Stream thumbnail or custom)
|
|
160
|
+
*/
|
|
161
|
+
poster?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Whether the video should autoplay (default: true)
|
|
164
|
+
*/
|
|
165
|
+
autoplay?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Whether the video should loop (default: true)
|
|
168
|
+
*/
|
|
169
|
+
loop?: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Whether the video should be muted (default: true)
|
|
172
|
+
*/
|
|
173
|
+
muted?: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* Whether to show playback controls (default: false)
|
|
176
|
+
*/
|
|
177
|
+
controls?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Custom Cloudflare customer subdomain (if using custom domains)
|
|
180
|
+
*/
|
|
181
|
+
customerSubdomain?: string;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Background video layer using Cloudflare Stream.
|
|
186
|
+
*/
|
|
187
|
+
const BackgroundStream = React.forwardRef<
|
|
188
|
+
HTMLIFrameElement,
|
|
189
|
+
BackgroundStreamProps
|
|
190
|
+
>(
|
|
191
|
+
(
|
|
192
|
+
{
|
|
193
|
+
className,
|
|
194
|
+
videoId,
|
|
195
|
+
poster,
|
|
196
|
+
autoplay = true,
|
|
197
|
+
loop = true,
|
|
198
|
+
muted = true,
|
|
199
|
+
controls = false,
|
|
200
|
+
customerSubdomain,
|
|
201
|
+
title = "Background video",
|
|
202
|
+
...props
|
|
203
|
+
},
|
|
204
|
+
ref,
|
|
205
|
+
) => {
|
|
206
|
+
const baseUrl = customerSubdomain
|
|
207
|
+
? `https://${customerSubdomain}.cloudflarestream.com`
|
|
208
|
+
: "https://iframe.videodelivery.net";
|
|
209
|
+
|
|
210
|
+
const params = new URLSearchParams();
|
|
211
|
+
if (autoplay) params.set("autoplay", "true");
|
|
212
|
+
if (loop) params.set("loop", "true");
|
|
213
|
+
if (muted) params.set("muted", "true");
|
|
214
|
+
if (!controls) params.set("controls", "false");
|
|
215
|
+
if (poster) params.set("poster", poster);
|
|
216
|
+
params.set("preload", "auto");
|
|
217
|
+
|
|
218
|
+
const streamUrl = `${baseUrl}/${videoId}?${params.toString()}`;
|
|
219
|
+
|
|
220
|
+
return (
|
|
221
|
+
<iframe
|
|
222
|
+
ref={ref}
|
|
223
|
+
src={streamUrl}
|
|
224
|
+
title={title}
|
|
225
|
+
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
|
226
|
+
allowFullScreen
|
|
227
|
+
className={backgroundStreamVariants({ class: className })}
|
|
228
|
+
{...props}
|
|
229
|
+
/>
|
|
230
|
+
);
|
|
231
|
+
},
|
|
232
|
+
);
|
|
233
|
+
BackgroundStream.displayName = "Background.Stream";
|
|
234
|
+
|
|
235
|
+
// =============================================================================
|
|
236
|
+
// Background.Overlay
|
|
237
|
+
// =============================================================================
|
|
238
|
+
|
|
239
|
+
const backgroundOverlayVariants = tv({
|
|
240
|
+
base: "absolute inset-0 bg-bg-overlay",
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
export interface BackgroundOverlayProps
|
|
244
|
+
extends React.HTMLAttributes<HTMLDivElement> {
|
|
245
|
+
/**
|
|
246
|
+
* Overlay opacity (0-1)
|
|
247
|
+
*/
|
|
248
|
+
opacity?: number;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Solid color overlay layer. Uses semantic bg-overlay token by default.
|
|
253
|
+
* Override with className for different colors.
|
|
254
|
+
*/
|
|
255
|
+
const BackgroundOverlay = React.forwardRef<
|
|
256
|
+
HTMLDivElement,
|
|
257
|
+
BackgroundOverlayProps
|
|
258
|
+
>(({ className, opacity = 0.4, style, ...props }, ref) => (
|
|
259
|
+
<div
|
|
260
|
+
ref={ref}
|
|
261
|
+
aria-hidden="true"
|
|
262
|
+
className={backgroundOverlayVariants({ class: className })}
|
|
263
|
+
style={{
|
|
264
|
+
opacity,
|
|
265
|
+
...style,
|
|
266
|
+
}}
|
|
267
|
+
{...props}
|
|
268
|
+
/>
|
|
269
|
+
));
|
|
270
|
+
BackgroundOverlay.displayName = "Background.Overlay";
|
|
271
|
+
|
|
272
|
+
// =============================================================================
|
|
273
|
+
// Background.Gradient
|
|
274
|
+
// =============================================================================
|
|
275
|
+
|
|
276
|
+
const backgroundGradientVariants = tv({
|
|
277
|
+
base: "absolute inset-0",
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
export interface BackgroundGradientProps
|
|
281
|
+
extends React.HTMLAttributes<HTMLDivElement> {
|
|
282
|
+
/**
|
|
283
|
+
* Gradient direction (Tailwind convention: to-t, to-b, to-l, to-r, etc.)
|
|
284
|
+
* Or CSS gradient direction (to top, to bottom, 45deg, etc.)
|
|
285
|
+
*/
|
|
286
|
+
direction?: string;
|
|
287
|
+
/**
|
|
288
|
+
* Starting color (from)
|
|
289
|
+
*/
|
|
290
|
+
from?: string;
|
|
291
|
+
/**
|
|
292
|
+
* Optional middle color (via)
|
|
293
|
+
*/
|
|
294
|
+
via?: string;
|
|
295
|
+
/**
|
|
296
|
+
* Ending color (to)
|
|
297
|
+
*/
|
|
298
|
+
to?: string;
|
|
299
|
+
/**
|
|
300
|
+
* Full custom gradient string (overrides from/via/to)
|
|
301
|
+
*/
|
|
302
|
+
gradient?: string;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Gradient overlay layer. Use for fading backgrounds or creating depth.
|
|
307
|
+
*/
|
|
308
|
+
const BackgroundGradient = React.forwardRef<
|
|
309
|
+
HTMLDivElement,
|
|
310
|
+
BackgroundGradientProps
|
|
311
|
+
>(
|
|
312
|
+
(
|
|
313
|
+
{
|
|
314
|
+
className,
|
|
315
|
+
direction = "to-b",
|
|
316
|
+
from = "transparent",
|
|
317
|
+
via,
|
|
318
|
+
to = "black",
|
|
319
|
+
gradient,
|
|
320
|
+
style,
|
|
321
|
+
...props
|
|
322
|
+
},
|
|
323
|
+
ref,
|
|
324
|
+
) => {
|
|
325
|
+
// Convert Tailwind-style direction to CSS
|
|
326
|
+
const cssDirection = direction.startsWith("to-")
|
|
327
|
+
? direction.replace("to-", "to ")
|
|
328
|
+
: direction;
|
|
329
|
+
|
|
330
|
+
const gradientValue =
|
|
331
|
+
gradient ||
|
|
332
|
+
(via
|
|
333
|
+
? `linear-gradient(${cssDirection}, ${from}, ${via}, ${to})`
|
|
334
|
+
: `linear-gradient(${cssDirection}, ${from}, ${to})`);
|
|
335
|
+
|
|
336
|
+
return (
|
|
337
|
+
<div
|
|
338
|
+
ref={ref}
|
|
339
|
+
aria-hidden="true"
|
|
340
|
+
className={backgroundGradientVariants({ class: className })}
|
|
341
|
+
style={{
|
|
342
|
+
backgroundImage: gradientValue,
|
|
343
|
+
...style,
|
|
344
|
+
}}
|
|
345
|
+
{...props}
|
|
346
|
+
/>
|
|
347
|
+
);
|
|
348
|
+
},
|
|
349
|
+
);
|
|
350
|
+
BackgroundGradient.displayName = "Background.Gradient";
|
|
351
|
+
|
|
352
|
+
// =============================================================================
|
|
353
|
+
// Compound Export
|
|
354
|
+
// =============================================================================
|
|
355
|
+
|
|
356
|
+
const BackgroundCompound = Object.assign(Background, {
|
|
357
|
+
Image: BackgroundImage,
|
|
358
|
+
Video: BackgroundVideo,
|
|
359
|
+
Stream: BackgroundStream,
|
|
360
|
+
Overlay: BackgroundOverlay,
|
|
361
|
+
Gradient: BackgroundGradient,
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
export {
|
|
365
|
+
BackgroundCompound as Background,
|
|
366
|
+
BackgroundImage,
|
|
367
|
+
BackgroundVideo,
|
|
368
|
+
BackgroundStream,
|
|
369
|
+
BackgroundOverlay,
|
|
370
|
+
BackgroundGradient,
|
|
371
|
+
backgroundVariants,
|
|
372
|
+
backgroundImageVariants,
|
|
373
|
+
backgroundVideoVariants,
|
|
374
|
+
backgroundStreamVariants,
|
|
375
|
+
backgroundOverlayVariants,
|
|
376
|
+
backgroundGradientVariants,
|
|
377
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
BackgroundGradientProps,
|
|
3
|
+
BackgroundImageProps,
|
|
4
|
+
BackgroundOverlayProps,
|
|
5
|
+
BackgroundProps,
|
|
6
|
+
BackgroundStreamProps,
|
|
7
|
+
BackgroundVideoProps,
|
|
8
|
+
} from "./background";
|
|
9
|
+
export {
|
|
10
|
+
Background,
|
|
11
|
+
BackgroundGradient,
|
|
12
|
+
BackgroundImage,
|
|
13
|
+
BackgroundOverlay,
|
|
14
|
+
BackgroundStream,
|
|
15
|
+
BackgroundVideo,
|
|
16
|
+
backgroundGradientVariants,
|
|
17
|
+
backgroundImageVariants,
|
|
18
|
+
backgroundOverlayVariants,
|
|
19
|
+
backgroundStreamVariants,
|
|
20
|
+
backgroundVariants,
|
|
21
|
+
backgroundVideoVariants,
|
|
22
|
+
} from "./background";
|