@pixelated-tech/components 3.11.3 → 3.11.5
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/components/admin/site-health/site-health-axe-core.integration.js +1 -1
- package/dist/components/admin/site-health/site-health-github.integration.js +0 -1
- package/dist/components/general/global-error.css +41 -0
- package/dist/components/general/global-error.js +19 -0
- package/dist/components/general/skeleton-loading.css +97 -0
- package/dist/components/general/skeleton-loading.js +26 -0
- package/dist/components/general/skeleton.css +48 -0
- package/dist/components/general/skeleton.js +21 -0
- package/dist/components/general/tiles.css +132 -32
- package/dist/components/general/tiles.js +12 -2
- package/dist/components/sitebuilder/form/formutils.js +12 -1
- package/dist/config/pixelated.config.json.enc +1 -1
- package/dist/index.js +3 -0
- package/dist/index.server.js +1 -0
- package/dist/scripts/pixelated-eslint-plugin.js +110 -0
- package/dist/types/components/admin/site-health/site-health-axe-core.integration.d.ts +1 -63
- package/dist/types/components/admin/site-health/site-health-axe-core.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-github.integration.d.ts +1 -6
- package/dist/types/components/admin/site-health/site-health-github.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-security.integration.d.ts +1 -8
- package/dist/types/components/admin/site-health/site-health-security.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-types.d.ts +2 -0
- package/dist/types/components/admin/site-health/site-health-types.d.ts.map +1 -1
- package/dist/types/components/general/global-error.d.ts +13 -0
- package/dist/types/components/general/global-error.d.ts.map +1 -0
- package/dist/types/components/general/skeleton-loading.d.ts +18 -0
- package/dist/types/components/general/skeleton-loading.d.ts.map +1 -0
- package/dist/types/components/general/skeleton.d.ts +14 -0
- package/dist/types/components/general/skeleton.d.ts.map +1 -0
- package/dist/types/components/general/tiles.d.ts +9 -0
- package/dist/types/components/general/tiles.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formutils.d.ts +0 -4
- package/dist/types/components/sitebuilder/form/formutils.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.server.d.ts +1 -0
- package/dist/types/scripts/pixelated-eslint-plugin.d.ts +48 -0
- package/dist/types/stories/general/global-error.stories.d.ts +26 -0
- package/dist/types/stories/general/global-error.stories.d.ts.map +1 -0
- package/dist/types/stories/general/skeleton-loading.stories.d.ts +14 -0
- package/dist/types/stories/general/skeleton-loading.stories.d.ts.map +1 -0
- package/dist/types/stories/general/skeleton.stories.d.ts +21 -0
- package/dist/types/stories/general/skeleton.stories.d.ts.map +1 -0
- package/dist/types/stories/general/tiles.stories.d.ts +12 -0
- package/dist/types/stories/general/tiles.stories.d.ts.map +1 -1
- package/dist/types/stories/sitebuilder/form.honeypot.stories.d.ts.map +1 -1
- package/dist/types/tests/global-error.test.d.ts +2 -0
- package/dist/types/tests/global-error.test.d.ts.map +1 -0
- package/dist/types/tests/skeleton-loading.test.d.ts +2 -0
- package/dist/types/tests/skeleton-loading.test.d.ts.map +1 -0
- package/dist/types/tests/skeleton.test.d.ts +2 -0
- package/dist/types/tests/skeleton.test.d.ts.map +1 -0
- package/package.json +2 -2
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import puppeteer from 'puppeteer';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
|
+
import { getFullPixelatedConfig } from '../../config/config';
|
|
5
6
|
const debug = false;
|
|
6
7
|
export async function performAxeCoreAnalysis(url, runtime_env = 'auto') {
|
|
7
8
|
try {
|
|
@@ -66,7 +67,6 @@ export async function performAxeCoreAnalysis(url, runtime_env = 'auto') {
|
|
|
66
67
|
};
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
|
-
import { getFullPixelatedConfig } from '../../config/config';
|
|
70
70
|
/**
|
|
71
71
|
* runAxeCoreAnalysis(url, runtime_env)
|
|
72
72
|
*
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { getFullPixelatedConfig } from '../../config/config';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
// Version extraction: we derive a version from commit messages (e.g., v1.2.3) instead of fetching tags and fuzzy-matching.
|
|
5
4
|
// Debug logging is off by default. Set to true/false here (do not use env vars).
|
|
6
5
|
const debug = false;
|
|
7
6
|
/**
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/* Canonical styles for the Global Error boundary — componentized and shipped with the library */
|
|
2
|
+
:root {
|
|
3
|
+
--ge-bg: linear-gradient(180deg,#fff,#f7f7fb);
|
|
4
|
+
--ge-foreground: #111;
|
|
5
|
+
--ge-muted: #889;
|
|
6
|
+
--ge-panel: #0b0b0b;
|
|
7
|
+
--ge-panel-ink: #e6e6e6;
|
|
8
|
+
--ge-radius: 8px;
|
|
9
|
+
--ge-gap: 12px;
|
|
10
|
+
--ge-max: 720px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.global-error {
|
|
14
|
+
min-height: 80vh;
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
padding: 3rem;
|
|
19
|
+
background: var(--ge-bg);
|
|
20
|
+
color: var(--ge-foreground);
|
|
21
|
+
font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ge-inner {
|
|
25
|
+
max-width: var(--ge-max);
|
|
26
|
+
width: 100%;
|
|
27
|
+
text-align: center;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ge-title { margin: 0; font-size: 1.75rem; }
|
|
31
|
+
.ge-lead { color: #334; margin-top: 0.75rem; }
|
|
32
|
+
|
|
33
|
+
.ge-actions { display: flex; gap: var(--ge-gap); justify-content: center; margin-top: 20px; flex-wrap: wrap; }
|
|
34
|
+
.ge-btn { border-radius: var(--ge-radius); padding: 0.6rem 1rem; cursor: pointer; border: none; background: transparent; }
|
|
35
|
+
.ge-btn--primary { background: var(--ge-foreground); color: #fff; }
|
|
36
|
+
.ge-link { color: var(--ge-foreground); text-decoration: underline; align-self: center; }
|
|
37
|
+
.ge-toggle { background: transparent; border: 1px solid #ddd; padding: 0.5rem 0.85rem; border-radius: var(--ge-radius); }
|
|
38
|
+
|
|
39
|
+
.ge-details { text-align: left; margin-top: 20px; padding: 16px; background: var(--ge-panel); color: var(--ge-panel-ink); border-radius: var(--ge-radius); overflow: auto; white-space: pre-wrap; }
|
|
40
|
+
.ge-note { margin-top: 18px; color: var(--ge-muted); }
|
|
41
|
+
.ge-unavailable { color: #666; align-self: center; }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import './global-error.css';
|
|
6
|
+
GlobalError.propTypes = {
|
|
7
|
+
error: PropTypes.any,
|
|
8
|
+
reset: PropTypes.func,
|
|
9
|
+
siteInfo: PropTypes.object,
|
|
10
|
+
className: PropTypes.string,
|
|
11
|
+
};
|
|
12
|
+
export function GlobalError({ error = null, reset, siteInfo, className = '' }) {
|
|
13
|
+
const [showDetails, setShowDetails] = useState(false);
|
|
14
|
+
const si = siteInfo;
|
|
15
|
+
const contactHref = typeof si?.email === 'string'
|
|
16
|
+
? `mailto:${si.email}`
|
|
17
|
+
: undefined;
|
|
18
|
+
return (_jsx("main", { role: "alert", "aria-live": "polite", className: `global-error ${className}`, children: _jsxs("div", { className: "ge-inner", children: [_jsx("h1", { className: "ge-title", children: "Something went wrong" }), _jsx("p", { className: "ge-lead", children: "We encountered an unexpected error. Please try again or contact the site maintainer." }), _jsxs("div", { className: "ge-actions", children: [_jsx("button", { onClick: () => reset?.(), className: "ge-btn ge-btn--primary", children: "Try again" }), contactHref ? (_jsx("a", { href: contactHref, rel: "noopener noreferrer", className: "ge-link", children: "Contact support" })) : (_jsx("span", { className: "ge-unavailable", children: "Contact info unavailable" })), _jsx("button", { onClick: () => setShowDetails(s => !s), "aria-pressed": showDetails, className: "ge-btn ge-toggle", children: showDetails ? 'Hide details' : 'Show details' })] }), showDetails && (_jsxs("pre", { "data-testid": "error-details", className: "ge-details", children: [String(error?.message ?? 'Unknown error'), '\n', error?.stack ?? ''] })), _jsx("p", { className: "ge-note", children: "If this keeps happening, please file an issue or reach out to the maintainer." })] }) }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/* Page-level loading / skeleton-loading styles
|
|
2
|
+
NOTE: this is the canonical stylesheet for the app-level loading UI and
|
|
3
|
+
should be consumed via the `SkeletonLoading` component in this package. */
|
|
4
|
+
|
|
5
|
+
.loading-page {
|
|
6
|
+
min-height: 100vh;
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: flex-start;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
padding: clamp(0, 3vw, 3rem);
|
|
11
|
+
background: var(--bg, #fff);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.loading-container {
|
|
15
|
+
width: 100%;
|
|
16
|
+
max-width: 72rem;
|
|
17
|
+
display: block;
|
|
18
|
+
gap: 2rem;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.visually-hidden {
|
|
22
|
+
position: absolute !important;
|
|
23
|
+
width: 1px;
|
|
24
|
+
height: 1px;
|
|
25
|
+
padding: 0;
|
|
26
|
+
margin: -1px;
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
clip: rect(0, 0, 0, 0);
|
|
29
|
+
white-space: nowrap;
|
|
30
|
+
border: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.hero {
|
|
34
|
+
display: block;
|
|
35
|
+
gap: 1.5rem;
|
|
36
|
+
padding: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.hero-row {
|
|
40
|
+
display: flex;
|
|
41
|
+
gap: 1rem;
|
|
42
|
+
align-items: center
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.hero-avatar-wrap {
|
|
46
|
+
width: 6rem
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.hero-meta {
|
|
50
|
+
display: block;
|
|
51
|
+
gap: .75rem
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.cards-grid {
|
|
55
|
+
display: grid;
|
|
56
|
+
grid-template-columns: 1fr;
|
|
57
|
+
gap: 1.5rem
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@media(min-width:640px) {
|
|
61
|
+
.cards-grid {
|
|
62
|
+
grid-template-columns: repeat(2, 1fr)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@media(min-width:1024px) {
|
|
67
|
+
.cards-grid {
|
|
68
|
+
grid-template-columns: repeat(3, 1fr)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.card-skeleton {
|
|
73
|
+
padding: 1rem;
|
|
74
|
+
border-radius: .5rem;
|
|
75
|
+
border: 1px solid rgba(17, 24, 39, 0.06);
|
|
76
|
+
background: transparent
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.card-row {
|
|
80
|
+
display: flex;
|
|
81
|
+
gap: 1rem;
|
|
82
|
+
align-items: flex-start
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.card-body {
|
|
86
|
+
flex: 1 1 0%
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.card-body-extra {
|
|
90
|
+
margin-top: .75rem
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* keep a11y focus rules here */
|
|
94
|
+
:focus {
|
|
95
|
+
outline: 3px solid Highlight;
|
|
96
|
+
outline-offset: 2px
|
|
97
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import { ToggleLoading } from './loading';
|
|
6
|
+
import { Skeleton } from './skeleton';
|
|
7
|
+
import './skeleton-loading.css';
|
|
8
|
+
SkeletonLoading.propTypes = {
|
|
9
|
+
heroHeight: PropTypes.number,
|
|
10
|
+
cardCount: PropTypes.number,
|
|
11
|
+
className: PropTypes.string,
|
|
12
|
+
};
|
|
13
|
+
export function SkeletonLoading({ heroHeight = 220, cardCount = 6, className = '' }) {
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
// Keep the app-level ToggleLoading behavior for global spinner consumers
|
|
16
|
+
try {
|
|
17
|
+
ToggleLoading({ show: true });
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
// defensive: ToggleLoading is best-effort
|
|
21
|
+
}
|
|
22
|
+
}, []);
|
|
23
|
+
const count = Math.max(0, Number(cardCount || 0));
|
|
24
|
+
return (_jsx("main", { className: `loading-page ${className}`, children: _jsxs("div", { className: "loading-container", children: [_jsx("div", { className: "visually-hidden", role: "status", "aria-live": "polite", children: "Loading\u2026" }), _jsx("section", { id: "hero-loading", "aria-hidden": true, className: "hero", children: _jsx(Skeleton, { variant: "rect", height: heroHeight }) }), _jsx("section", { id: "cards-loading", className: "cards-grid", "aria-hidden": true, children: Array.from({ length: count }).map((_, i) => (_jsx("article", { className: "card-skeleton", children: _jsxs("div", { className: "card-row", children: [_jsx(Skeleton, { variant: "avatar" }), _jsxs("div", { className: "card-body", children: [_jsx(Skeleton, { lines: 2 }), _jsx("div", { className: "card-body-extra", children: _jsx(Skeleton, { lines: 3, width: "90%" }) })] })] }) }, i))) })] }) }));
|
|
25
|
+
}
|
|
26
|
+
export default SkeletonLoading;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* Token defaults removed — values have been inlined to make this file self-contained */
|
|
2
|
+
|
|
3
|
+
/* Skeleton primitive styles (shared component) */
|
|
4
|
+
.skeleton {
|
|
5
|
+
background-color: #e6e6e6;
|
|
6
|
+
border-radius: .5rem;
|
|
7
|
+
display: block;
|
|
8
|
+
min-height: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.skeleton--animated {
|
|
12
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.skeleton--avatar {
|
|
16
|
+
width: 3rem;
|
|
17
|
+
height: 3rem;
|
|
18
|
+
border-radius: 9999px;
|
|
19
|
+
display: inline-block;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.skeleton--rect {
|
|
23
|
+
display: block;
|
|
24
|
+
width: 100%;
|
|
25
|
+
height: 160px;
|
|
26
|
+
border-radius: .5rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.skeleton-text {
|
|
30
|
+
display: block;
|
|
31
|
+
width: 100%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.skeleton-line {
|
|
35
|
+
height: 1rem;
|
|
36
|
+
display: block;
|
|
37
|
+
margin-top: .5rem;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@keyframes pulse {
|
|
41
|
+
0% { opacity: 1 }
|
|
42
|
+
50% { opacity: .5 }
|
|
43
|
+
100% { opacity: 1 }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@media (prefers-reduced-motion: reduce) {
|
|
47
|
+
.skeleton--animated { animation: none }
|
|
48
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import './skeleton.css';
|
|
4
|
+
Skeleton.propTypes = {
|
|
5
|
+
variant: PropTypes.oneOf(['text', 'rect', 'avatar']),
|
|
6
|
+
lines: PropTypes.number,
|
|
7
|
+
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
8
|
+
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
9
|
+
animated: PropTypes.bool,
|
|
10
|
+
};
|
|
11
|
+
export function Skeleton({ variant = 'text', lines = 1, width, height, animated = true, }) {
|
|
12
|
+
const base = `skeleton ${animated ? 'skeleton--animated' : ''}`;
|
|
13
|
+
if (variant === 'avatar') {
|
|
14
|
+
const avatarStyle = width != null || height != null ? { ...(width != null ? { width } : {}), ...(height != null ? { height } : {}) } : undefined;
|
|
15
|
+
return _jsx("div", { "aria-hidden": "true", className: `${base} skeleton--avatar`, style: avatarStyle });
|
|
16
|
+
}
|
|
17
|
+
if (variant === 'rect') {
|
|
18
|
+
return (_jsx("div", { "aria-hidden": "true", className: `${base} skeleton--rect`, style: { width: width ?? '100%', height: height ?? 160 } }));
|
|
19
|
+
}
|
|
20
|
+
return (_jsx("div", { "aria-hidden": "true", className: "skeleton-text", children: Array.from({ length: Math.max(1, Number(lines || 1)) }).map((_, i) => (_jsx("div", { className: base + ' skeleton-line', style: { width: typeof width === 'number' ? `${width}%` : (width ?? (i === (lines || 1) - 1 ? '60%' : '100%')) } }, i))) }));
|
|
21
|
+
}
|
|
@@ -11,12 +11,9 @@
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.tile-image {
|
|
14
|
-
position: relative;
|
|
15
|
-
aspect-ratio: 1;
|
|
16
14
|
border: 2px solid #CCC;
|
|
17
15
|
/* border-radius: 20px; */
|
|
18
16
|
overflow: hidden;
|
|
19
|
-
margin: 10px;
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
.tile-image.clickable {
|
|
@@ -26,23 +23,11 @@
|
|
|
26
23
|
.tile-image img {
|
|
27
24
|
width: 100%;
|
|
28
25
|
height: 100% !important;
|
|
29
|
-
position: relative;
|
|
30
|
-
display: inline-block;
|
|
31
26
|
align-self: start;
|
|
32
27
|
object-fit: cover;
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
.tile-image-overlay {
|
|
36
|
-
visibility: hidden;
|
|
37
|
-
position: absolute;
|
|
38
|
-
width: 0%;
|
|
39
|
-
height: 100%;
|
|
40
|
-
bottom: 0;
|
|
41
|
-
left: 0;
|
|
42
|
-
display: inline-block;
|
|
43
|
-
background: rgba(51, 102, 153, .7);
|
|
44
|
-
transition: all 0.25s ease-in-out;
|
|
45
|
-
/* All other styling - see example */
|
|
46
31
|
img {
|
|
47
32
|
vertical-align: top; /* Default is baseline, this fixes a common alignment issue */
|
|
48
33
|
}
|
|
@@ -54,27 +39,10 @@
|
|
|
54
39
|
cursor: pointer;
|
|
55
40
|
}
|
|
56
41
|
|
|
57
|
-
.tile-image:hover .tile-image-overlay {
|
|
58
|
-
visibility: visible;
|
|
59
|
-
width: 100% !important;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
42
|
.tile-image-overlay-text {
|
|
63
|
-
position: absolute;
|
|
64
43
|
padding: 20px;
|
|
65
|
-
left: 0;
|
|
66
|
-
bottom: 0;
|
|
67
|
-
color: white;
|
|
68
44
|
font-size: 20px;
|
|
69
45
|
font-weight: bold;
|
|
70
|
-
visibility: hidden;
|
|
71
|
-
transition: visibility 0s ease-in-out;
|
|
72
|
-
transition-delay: 0s;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.tile-image:hover .tile-image-overlay-text {
|
|
76
|
-
visibility: visible;
|
|
77
|
-
transition-delay: 0.25s;
|
|
78
46
|
}
|
|
79
47
|
|
|
80
48
|
.tile-image-overlay-title {
|
|
@@ -85,3 +53,135 @@
|
|
|
85
53
|
font-size: 16px;
|
|
86
54
|
font-weight: initial;
|
|
87
55
|
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
/* ====== OVERLAY VARIANT (CSS-only) ======
|
|
61
|
+
- Applied by adding `variant="overlay"` to <Tiles/> (adds `.overlay` to each `.tile`)
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
.tile.overlay {
|
|
65
|
+
|
|
66
|
+
.tile-image {
|
|
67
|
+
position: relative;
|
|
68
|
+
aspect-ratio: 1;
|
|
69
|
+
margin: 10px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.tile-image img {
|
|
73
|
+
width: 100%;
|
|
74
|
+
height: 100% !important;
|
|
75
|
+
position: relative;
|
|
76
|
+
display: inline-block;
|
|
77
|
+
align-self: start;
|
|
78
|
+
object-fit: cover;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.tile-image-overlay {
|
|
82
|
+
visibility: hidden;
|
|
83
|
+
position: absolute;
|
|
84
|
+
width: 0%;
|
|
85
|
+
height: 100%;
|
|
86
|
+
bottom: 0;
|
|
87
|
+
left: 0;
|
|
88
|
+
display: inline-block;
|
|
89
|
+
background: rgba(51, 102, 153, .7);
|
|
90
|
+
transition: all 0.25s ease-in-out;
|
|
91
|
+
/* All other styling - see example */
|
|
92
|
+
img {
|
|
93
|
+
vertical-align: top; /* Default is baseline, this fixes a common alignment issue */
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.tile-image:hover .tile-image-overlay {
|
|
98
|
+
visibility: visible;
|
|
99
|
+
width: 100% !important;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.tile-image-overlay-text {
|
|
103
|
+
position: absolute;
|
|
104
|
+
padding: 20px;
|
|
105
|
+
left: 0;
|
|
106
|
+
bottom: 0;
|
|
107
|
+
color: white;
|
|
108
|
+
font-size: 20px;
|
|
109
|
+
font-weight: bold;
|
|
110
|
+
visibility: hidden;
|
|
111
|
+
transition: visibility 0s ease-in-out;
|
|
112
|
+
transition-delay: 0s;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.tile-image:hover .tile-image-overlay-text {
|
|
116
|
+
visibility: visible;
|
|
117
|
+
transition-delay: 0.25s;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.tile-image-overlay-title {
|
|
121
|
+
margin-bottom: 10px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.tile-image-overlay-body{
|
|
125
|
+
font-size: 16px;
|
|
126
|
+
font-weight: initial;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
/* ====== CAPTION VARIANT (CSS-only) ======
|
|
136
|
+
- Applied by adding `variant="caption"` to <Tiles/> (adds `.caption` to each `.tile`)
|
|
137
|
+
*/
|
|
138
|
+
.tile.caption {
|
|
139
|
+
* {
|
|
140
|
+
visibility: visible;
|
|
141
|
+
display: block;
|
|
142
|
+
position: relative;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.tile-image {
|
|
146
|
+
aspect-ratio: auto;
|
|
147
|
+
border-radius: 10px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.tile-image img {
|
|
151
|
+
width: 100%;
|
|
152
|
+
height: 100% !important;
|
|
153
|
+
align-self: start;
|
|
154
|
+
object-fit: cover;
|
|
155
|
+
aspect-ratio: 1;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.tile-image-overlay {
|
|
159
|
+
background-color: #EEEEEE;
|
|
160
|
+
height: 100px !important;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.tile-image-overlay,
|
|
164
|
+
.tile-image-overlay * {
|
|
165
|
+
width: 100% !important;
|
|
166
|
+
height: auto;
|
|
167
|
+
transition: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.tile-image-overlay-title {
|
|
171
|
+
margin-bottom: 0px;
|
|
172
|
+
color: black;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.tile-image-overlay-text {
|
|
176
|
+
transition: none;
|
|
177
|
+
color: black;
|
|
178
|
+
padding: 10px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.tile-image-overlay-body{
|
|
182
|
+
font-size: var(--font-size-base);
|
|
183
|
+
font-weight: bold;
|
|
184
|
+
color: black;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
}
|
|
@@ -6,15 +6,21 @@ import { SmartImage } from "./smartimage";
|
|
|
6
6
|
import { usePixelatedConfig } from '../config/config.client';
|
|
7
7
|
import "../../css/pixelated.grid.scss";
|
|
8
8
|
import "./tiles.css";
|
|
9
|
+
export const TilesVariants = ['caption', 'overlay'];
|
|
9
10
|
Tiles.propTypes = {
|
|
10
11
|
cards: PropTypes.array.isRequired,
|
|
11
12
|
rowCount: PropTypes.number,
|
|
12
13
|
imgClick: PropTypes.func,
|
|
14
|
+
/**
|
|
15
|
+
* Optional visual variant. Allowed values are enumerated so consumers get
|
|
16
|
+
* a discoverable, typed API.
|
|
17
|
+
*/
|
|
18
|
+
variant: PropTypes.oneOf(TilesVariants),
|
|
13
19
|
};
|
|
14
20
|
export function Tiles(props) {
|
|
15
21
|
const rowCount = props.rowCount ?? 2;
|
|
16
22
|
if (props.cards && props.cards.length > 0) {
|
|
17
|
-
return (_jsx("div", { className: "tiles-container", children: _jsx("div", { className: `tile-container row-${rowCount}col`, children: props.cards.map((card, i) => (_jsx("div", { className: "gridItem", children: _jsx(Tile, { index: i, cardLength: props.cards.length, link: card.link, image: card.image, imageAlt: card.imageAlt, bodyText: card.bodyText, imgClick: props.imgClick }) }, i))) }) }));
|
|
23
|
+
return (_jsx("div", { className: "tiles-container", children: _jsx("div", { className: `tile-container row-${rowCount}col`, children: props.cards.map((card, i) => (_jsx("div", { className: "gridItem", children: _jsx(Tile, { index: i, cardLength: props.cards.length, link: card.link, image: card.image, imageAlt: card.imageAlt, bodyText: card.bodyText, imgClick: props.imgClick, variant: (props.variant ?? "overlay") }) }, i))) }) }));
|
|
18
24
|
}
|
|
19
25
|
else {
|
|
20
26
|
return (_jsx(Loading, {}));
|
|
@@ -29,12 +35,16 @@ Tile.propTypes = {
|
|
|
29
35
|
imageAlt: PropTypes.string,
|
|
30
36
|
bodyText: PropTypes.string,
|
|
31
37
|
imgClick: PropTypes.func,
|
|
38
|
+
/** 'caption' - visual caption beneath image (prefers bodyText, falls back to imageAlt) */
|
|
39
|
+
variant: PropTypes.oneOf(TilesVariants),
|
|
32
40
|
};
|
|
33
41
|
function Tile(props) {
|
|
34
42
|
const config = usePixelatedConfig();
|
|
35
43
|
const imgClick = props.imgClick;
|
|
44
|
+
const captionText = (props.bodyText && props.bodyText.length > 0) ? props.bodyText : (props.imageAlt ?? "");
|
|
36
45
|
const tileBody = _jsxs("div", { className: "tile-image" + (imgClick ? " clickable" : ""), children: [_jsx(SmartImage, { src: props.image, title: props?.imageAlt ?? undefined, alt: props?.imageAlt ?? "", onClick: imgClick ? (event) => imgClick(event, props.image) : undefined, cloudinaryEnv: config?.cloudinary?.product_env ?? undefined }), _jsx("div", { className: "tile-image-overlay", children: _jsxs("div", { className: "tile-image-overlay-text", children: [_jsx("div", { className: "tile-image-overlay-title", children: props.imageAlt }), _jsx("div", { className: "tile-image-overlay-body", children: props.bodyText })] }) })] });
|
|
37
|
-
|
|
46
|
+
const rootClass = `tile${(props.variant) ? ' ' + props.variant : ''}`;
|
|
47
|
+
return (_jsx("div", { className: rootClass, id: 'tile-' + props.index, children: props.link ?
|
|
38
48
|
_jsx("a", { href: props.link, className: "tileLink", children: tileBody })
|
|
39
49
|
:
|
|
40
50
|
tileBody }));
|
|
@@ -18,8 +18,19 @@ export function mapTypeToComponent(myType) {
|
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Generates field JSON for form building
|
|
21
|
+
*
|
|
22
|
+
* NOTE: This implementation is currently unused by other modules in-repo and
|
|
23
|
+
* is exported by the package barrel which previously caused a duplicate
|
|
24
|
+
* export collision with `componentGeneration.generateFieldJSON` during
|
|
25
|
+
* Storybook's webpack build. To avoid accidental breakage for external
|
|
26
|
+
* consumers we are making this implementation internal (non-exported)
|
|
27
|
+
* and marking it for removal in a future maintenance sweep.
|
|
28
|
+
*
|
|
29
|
+
* TODO (cleanup): remove this function and any remaining aliases once
|
|
30
|
+
* consumers have migrated — see `docs/roadmap.md` (Refactoring & Cleanup).
|
|
31
|
+
* @deprecated internal-only — slated for removal
|
|
21
32
|
*/
|
|
22
|
-
|
|
33
|
+
function generateFieldJSON(component, type) {
|
|
23
34
|
const form = {};
|
|
24
35
|
form.fields = [];
|
|
25
36
|
// Common fields for all components
|
|
@@ -1 +1 @@
|
|
|
1
|
-
pxl:v1:
|
|
1
|
+
pxl:v1:d8ee214a9235b0be63c1821f:99ee9079e869f46bcd02f78dfa428019:e1ee34f0c4412ca17d6c39343bea8c728534cc8de7bdfc3881e5b3dfddd093e89ed1ff5de7164220d66cf8dd200451049ce1f2f111d77beb13ce2bdbbe3780579d9399c71f480cd50bfc8ee4c5223c9f86dee4641583d8f7441a58f9fc394dda8249f03f0e26658ddb9aa43ba0512465d73c1457369d2106f6449aa271e4058473083e442b09d62932a1106bfffab15a2e12f181a71ffcd9046eb66e3b63ee2dae496cea8bd867fb41c4030b48d0c5cfb9c9e395ee4c9683d5060e6a559d0721ffa33acf5913ef86d427b1efecfafb5812e97ed98e76599bae1081558969e93ed29ad7f80571016e5cda51f27ff33555d35746fa4906e986ca02f634d64fafb104ea988a3fb300eba00bb1f3924b513f1a4dd251b5959032935bd1f30d43a6f31fdd1c9535f1a5960de7594680a6a244f35dc97514acafa4b3fbb35ed74408a1efa705ce75dcd9c2d308d5fceee6e9aa8fffdd15ae2af99b0a4b2b9434f0e262d6a79dd49f78bacfbaaf977de083beeb1fef29763a191d4727f993425c79d88dfee3cae8d8b147be860dba0724afa66451568a688b2debcf4222164ee5ac7cc2d556a363a821f07ab309b22d9dbeb2116335193be4da5703f34498c743a58a7d8dd80b450123aec0ada689aed8985b9dacf5ac3c6d5f972ea85996fcb3d79d0a2911c30b91ea879b9c1af57c57d52103fa61653f107aeeb97845cdb70314812e6a4cc8b5d2e0042234c31415cb348ee6a0f3fb946029d574eec7ffc857e272dd9f43820f93341330a20bcc71e39e0a936878dcce4131afea923d734f3f6ffefe56574b9ec8829880bd4ebe1859acf0f9a2df770ec6c4ed11d8a0904c5fa5ee6fe3ed10ec3542ea067ecc3a604cd16171564f85403cac6929c9c00f40b298748fdca9de517dbbf3b824e364556a7d7d83dd02370830acd09205730f033ce30bcfd0ff700dcaf821898b61af59a584db14cd6e456ea872acbde4d5e26dee0c841b662b5989f41c32a7efa34ae343049885e8613ff5100191b64c9b55030f512ca33d838495f29df1d9e3c69308ee64b9be0a431c5c4aa3c16bfdbcf965fa156cdc444595d054e6a8b03aa0a1292952853ff0524b8e2b7daac711897d1a34dff463655062642cdea65355f396aebb7017e0df6abc08982400c25941860591b6aef62e50da0e1f8266b8dea211c53ac0cf4ed0fd09a96300468702d3fb4d947558b921dfd84c46470c0a24f321e9a6e42941ee47bf3e99bf5dd2db66d1cfb70b9bac3ab6172671e3ee958a06e0f14ac8f5baa4d3794354e8900970afed3bb31055d0ab37c2f33a5c3f14739c171adc05eaaf7d74d11c63cc7cb3a50bca0ceceb61e2d84e598d610f907cbd381156e88c85031e80922ea10b39342468a6b7988157693fd0368ffd7e7154674b57b421b7f7addc976675dca1c7809a69de056a05ea849b6a360b1baae80c3ec43b173d3b4671874bc89cae36dd836ac4450c5fce613734505e6cb562c8e9db423cd1643bfcefccacdfd6a3a84f1dadab3e29343fcf60d23c29dade0190abd814d0077f9eae50783485a1644355bef3b43fc5fdab3a3d0b1b7aad074cffa3ad7b141e20051167c0b26ea87e98b8502868d702800a02c551af66abbc547faccebef188841e8bb27bf83f641a0c0ba61009caf64fe3bdaa86759d2176af9cab61d73b945a31252bd6438f1ed98fe82161a4fe94f7594d466bab3c55e89ff46d8765ff2b89a8ccc93f16efd6a4de5ddb369454d3d92f0a20ca17c9beda1e09b6f2078c4fa8e736e367fe0b38158fa3f10b441d5b094ca4a2e0cb3a37705dcb13cf8b0ff3afd80dfb077e66233486d85478b47db9b5b5bb2d12d0ad4db37962985ccbf9149326d8189215683342003a191ebb40661666b729a3146ff115a5b2a960d38734eba2d8e2f88e0897728b858ee6eb4f3eba61934d810bb02bf8bbd315a12332259bb0829570a04e902a4cd31a65d5583ddeeef27559ca2788890c612573e243a88cce49ae8cee782c7a3c5999b8cda409003460d8651b5e7d8be0dc94f6762d9b240e7c35cfa8645ccc1b13e16277b6616eed9175ab686ccafd7d84c73fd3e8a57c3ad23bd4b4e1601fd70827c3f74e0a6e8bef4844a21750a2d43b75c1af051bfb127c491578d86e27dcc284b86feab6669178a3500513ebfc0e8e057a9387f4629dfc6f4ff96f0ea22a3b43d851251d5f6d5b6f76052665d3fe698201df361477498307cdab07710e677e1180fe092ca763d397ff872f2d8dca515fd6d32f7d26c967d3d771c880f6a4691207074848450f8608f126d1d58d9f17cc10891098d304d311fd5618663e91e6e90dfe06322f078052a0da01313f929279e05057970bd653408a6418b8672efd3f9fc6d5ff2963738f25645bcade30ea79a96c4290c1e9c700e26587a2e02ad1ae91303e003814db7c38c04111bb5becd16601ef144012d8693f0577191176752de57a7c07e129325605d7249c75a71639b4a62cdc52148a97c0d4e6c1bfc5fa8f2890671f267c9249c91154db401f28b764c4ae3245a4c70e6b5a38167a323a2411786dcf82aa4209dc61aa9f16f10c7fe62a337e96d8c49c8b8244f0a2225bfffd5d9e61b9407815e73be43506787514fcb78d56719485ac6a4033ac0e817de79bb29b36d203a2a30c0e2c82345efc607e199629ca10d8b5a0e6d53c414e2afcf82946848122de0a62d484f2e1e21d1e1f491f2c9d407ac6c359f4d76dad00f75b787841c9db1793aa57cf1d336a882756f2b551dc8c88ce721ec1cdd8174d277736b27ddea9fcbf8fa26e182f2bcc5746621216c2474cba743029ab72faa45cfec71196054dc157d80a306cbe8e23882974cc5e5e473a5a0bb184535d35bbd8bbc765b673642886531b7c51228dac55f4573ccf9c2705ce566959f18a0fdb017556b0a7b33c9b2a1ea58816067f1b1627f872326e0e5da25f2fba26ef1091d86ffb0fbe95dab442d7a605d9bb49f49ad03154ef1e563385051776cb0bc6546a07b5118eced0684a215231df3e65c7818d2ee88e19c7ba5e39ecb7bf1b511214ac1f9394ebf76278014df1044068e33ddffc7db9cb2ed779b399a041e8f21624e55099a556158b12a18e91e8cad8ffab836d28ee19df9d5aabbd8fe18f25f6447eeaab2537122275ba0a049ee25038c61aff6182df6bda1d8b7ee4bb6772cf70cadeed09d94a341851453dd43f4b8e8c368be52be2e7d56c80d67979623ba8d109ca83f617457a11c780884c71ffe250a3160a2f4b4e8dd6cc96127c21839f6a549735f7d0878ebfdc312794120cfcd09e3ec69358e8c0b5e0638e067f45af974ca4526c23578f24f22b624ec7acad116affbf893052960d4a2bc5a7b372a1fdc0336500313bbe067beaa6cb58aa3c962a6b19f02449ea5f5f9f93b16aef64d93ed6a34e387b70167d9bb01dec55d03610ed790b54bc29075b3902348b8f7dff56abbeef88b1c8c74554fe84fbe370640c580306570173b2efaa740c7d39b86977ce890d1e626706ebbdd6bede3c4d347b3ab85c863eb7aa35c802a8267c1c8835e2eadb0d0858fb5740945bf45635b69fed7474db273b470cc0cc8c73137c654ecd1c2057f9c235303097b3731ff37dd6db7d2846d495f2fdb7f7e510cb718799a972b17855ef4cef1497e79f08309280985a99f91d4611984184bf4a9be5b05568d4e88a4aadf3a75be76067d1c52db6128a17dd628d92f45732f9c9b1a0e7aff9840aeba6bbf3c37af8004827056ca28acfb15ac7e32f58e82e9f0b87bc35d138659938f4cb2fc8d359982fc76233a7a27364b0d12ffe7a9f58fa50dc6428c5244d77a8f314c2a568b9dadc031576699ad2e4a633ab4a657f29c99439a7f3af2a08c850d2d60262ceb0f2023b93c352170188260c1d95a34b00ac901b2d34b4f251d569063e4a561539bbfde32c1a2586cb380817a2cf1c9950547c7fa199949de50f0cd80e810345a9383b1df6d9ac63d5ffff8f07e095ef3beddd9a3b175961c1056f247d905b609b7b1de6bf1aec79df4e0b04935b54631ce40f89b4718dff91e969c1307a21242eed79da0d8f7094d66c4c5303ad9022d9f2432439285f1b08fd82e56ba8740c6fcdc26a8179886e0679216e088b89f8baae5c6c738f87282d351a6a86da1c9ca99973ef797c1100fdd8f0dad238a24f107a34b63ed5bd0ecd9f7d0c46f016bc4ea777d189b3b92af311882103fcdd818c58ae2ca5cbcf590b307bbcccf19fb0009e5aba10e8d8db859eddd26a11b1f89faff0fb832092061651a5919cae7586eb8e6ea7b3e8ce8f7e7cab30b425b788e8290cb899d08633077cefa37c65ce4a6b19462d9353548c4fcbb6b9841a22763ae479ebd1028fc34e7cbdf782cd59d6d94404cb32903b262feb084ee942b14e5d4d1a1dd9b36054d7db60553c27c9188d0f5024425462eea0af3fed59cf1ba37105ec31f792fe716562636ca3ef9f5ac98896e3300ff1b130a1c53da4d1fa67f600bd671278adfbca42e0b341e0a195790432d738e1cbdbcd45e8255ea63bc28e4911f55382eceb15673be67f6cdf4bc159c8eba7809c14592d3531c0118a565bd96e8e3822cf77734944d0e245daf83f74aa86e2bc8d9d1ddc35482b131ae8b11e3874f4647457bdfbfc5f2328141917386d187ed75f99a305acddf54a60a687cf9b0600e240412b4ed812759339dd300f5a77ff670c1f3be96dcf0a03183eb9d0bcfce273c913a291802326d0e25de9454543565798537866fb286adf9c37837c17a29a518ce816974156c770707d92d81dfaf7002716051c4372735c775b98bb92bcaef8ae5de7859e82e4593985b991a623d9f54c54458d5ae2339bef432d6a249edf3ad369a378dec7263c9374bcdb9281eaa80d38fb6a663d077e910eec1e471ceb88ce6fce4a022a5db1a3a367baf9c452d207a3c10c2862a98a741ad5038a22a5490e68ad323b5d582e792eb959bf2cee6874ad3c531770ae446727d0d3a4b931a423d971324fbed9d952d2ba9849b940cc3df8189c9795b42dd8f96b956e718ceb2fa99fe6f4a456644108fed7e649f8935f0f4fe273477e91b2ea2b80e5ca1bcc5fcfe54c9ba5653e83ebe11988b54865e41a85f0ecd00de756ae02f6731dc38eedf9f195d07178ea3a133e050207e02ba5662123
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,8 @@ export * from './components/general/faq-accordion';
|
|
|
15
15
|
export * from './components/general/image';
|
|
16
16
|
export * from './components/general/intersection-observer';
|
|
17
17
|
export * from './components/general/loading';
|
|
18
|
+
export * from './components/general/skeleton';
|
|
19
|
+
export * from './components/general/skeleton-loading';
|
|
18
20
|
export * from './components/general/splitscroll';
|
|
19
21
|
export * from './components/general/manifest';
|
|
20
22
|
export * from './components/general/markdown';
|
|
@@ -40,6 +42,7 @@ export * from './components/general/semantic';
|
|
|
40
42
|
export * from './components/general/sidepanel';
|
|
41
43
|
export * from './components/general/sitemap';
|
|
42
44
|
export * from './components/general/smartimage';
|
|
45
|
+
export * from './components/general/global-error';
|
|
43
46
|
export * from './components/general/tab';
|
|
44
47
|
export * from './components/general/table';
|
|
45
48
|
export * from './components/general/tiles';
|
package/dist/index.server.js
CHANGED
|
@@ -22,6 +22,7 @@ export * from './components/general/schema-services';
|
|
|
22
22
|
export * from './components/general/schema-website';
|
|
23
23
|
export * from './components/general/sitemap';
|
|
24
24
|
export * from './components/general/utilities';
|
|
25
|
+
export * from './components/general/skeleton';
|
|
25
26
|
export * from './components/integrations/contentful.delivery';
|
|
26
27
|
export * from './components/integrations/contentful.management';
|
|
27
28
|
export * from './components/integrations/flickr';
|