@simple-photo-gallery/theme-modern 2.0.15 → 2.0.17
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/features/themes/base-theme/components/footer/Footer.astro +1 -1
- package/src/features/themes/base-theme/components/gallery-section/GallerySection.astro +11 -1
- package/src/features/themes/base-theme/components/gallery-section/GallerySectionHeader.astro +2 -2
- package/src/features/themes/base-theme/components/hero/Hero.astro +3 -3
- package/src/features/themes/base-theme/layouts/MainLayout.astro +4 -0
- package/src/features/themes/base-theme/pages/index.astro +4 -0
- package/src/features/themes/base-theme/utils/queryParams.ts +159 -0
- package/tsconfig.json +2 -1
package/package.json
CHANGED
|
@@ -40,10 +40,20 @@ const validImages = section.images.filter(
|
|
|
40
40
|
<style>
|
|
41
41
|
.gallery-section {
|
|
42
42
|
padding: 1rem 1rem;
|
|
43
|
+
background-color: var(--section-bg-color-odd, var(--section-bg-color, #ffffff));
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
.gallery-section:nth-child(even) {
|
|
46
|
-
background-color: #f9fafb;
|
|
47
|
+
background-color: var(--section-bg-color-even, var(--section-bg-color, #f9fafb));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Opt-in embed mode: transparent backgrounds for iframe embedding */
|
|
51
|
+
.gallery-section--transparent {
|
|
52
|
+
background-color: var(--section-bg-color-odd, var(--section-bg-color, transparent));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.gallery-section--transparent:nth-child(even) {
|
|
56
|
+
background-color: var(--section-bg-color-even, var(--section-bg-color, transparent));
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
.gallery-section__container {
|
package/src/features/themes/base-theme/components/gallery-section/GallerySectionHeader.astro
CHANGED
|
@@ -27,13 +27,13 @@ const parsedDescription = section.description ? await renderMarkdown(section.des
|
|
|
27
27
|
font-size: clamp(1.5rem, 3vw, 2.5rem);
|
|
28
28
|
font-weight: 700;
|
|
29
29
|
margin-bottom: 1.5rem;
|
|
30
|
-
color: #111827;
|
|
30
|
+
color: var(--typography-color-title, var(--gallery-section-title-color, #111827));
|
|
31
31
|
text-align: center;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
.gallery-section__header-description {
|
|
35
35
|
font-size: 1.125rem;
|
|
36
|
-
color: #6b7280;
|
|
36
|
+
color: var(--typography-color-description, var(--gallery-section-description-color, #6b7280));
|
|
37
37
|
max-width: 42rem;
|
|
38
38
|
margin: 0 auto;
|
|
39
39
|
line-height: 1.6;
|
|
@@ -145,13 +145,13 @@ const headerPhotoPath = getPhotoPath(headerImage || '', mediaBaseUrl);
|
|
|
145
145
|
() => {
|
|
146
146
|
// Final fallback failed, blurhash stays visible
|
|
147
147
|
},
|
|
148
|
-
{ once: true }
|
|
148
|
+
{ once: true },
|
|
149
149
|
);
|
|
150
150
|
|
|
151
151
|
// If fallback succeeds, hide blurhash
|
|
152
152
|
img.addEventListener('load', hideBlurhash, { once: true });
|
|
153
153
|
},
|
|
154
|
-
{ once: true }
|
|
154
|
+
{ once: true },
|
|
155
155
|
);
|
|
156
156
|
})();
|
|
157
157
|
</script>
|
|
@@ -168,7 +168,7 @@ const headerPhotoPath = getPhotoPath(headerImage || '', mediaBaseUrl);
|
|
|
168
168
|
.hero {
|
|
169
169
|
position: relative;
|
|
170
170
|
min-height: 450px;
|
|
171
|
-
height: 100vh;
|
|
171
|
+
height: var(--hero-height, 100vh);
|
|
172
172
|
display: flex;
|
|
173
173
|
align-items: center;
|
|
174
174
|
justify-content: center;
|
|
@@ -58,6 +58,10 @@ const headerImageBasename = headerImage ? path.basename(headerImage, path.extnam
|
|
|
58
58
|
font-weight: 400;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
body.embed-transparent {
|
|
62
|
+
background: transparent;
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
/* Markdown content styles */
|
|
62
66
|
.markdown-content p {
|
|
63
67
|
margin-bottom: 1rem;
|
|
@@ -38,6 +38,8 @@ const showCtaBanner = ctaBanner === true;
|
|
|
38
38
|
<script>
|
|
39
39
|
import { decode } from 'blurhash';
|
|
40
40
|
|
|
41
|
+
import { applyQueryParams } from '@/features/themes/base-theme/utils/queryParams';
|
|
42
|
+
|
|
41
43
|
const blurHashCanvases = document.querySelectorAll<HTMLCanvasElement>('canvas[data-blur-hash]');
|
|
42
44
|
|
|
43
45
|
for (const canvas of blurHashCanvases) {
|
|
@@ -53,6 +55,8 @@ const showCtaBanner = ctaBanner === true;
|
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
}
|
|
58
|
+
|
|
59
|
+
applyQueryParams();
|
|
56
60
|
</script>
|
|
57
61
|
|
|
58
62
|
<MainLayout
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
const TYPOGRAPHY_MODERN_THEME_PRESETS: Record<string, { title: string; description: string }> = {
|
|
2
|
+
light: { title: 'rgba(255, 255, 255, 0.95)', description: 'rgba(255, 255, 255, 0.75)' },
|
|
3
|
+
white: { title: 'rgba(255, 255, 255, 0.95)', description: 'rgba(255, 255, 255, 0.75)' },
|
|
4
|
+
dark: { title: '#111827', description: '#6b7280' },
|
|
5
|
+
black: { title: '#111827', description: '#6b7280' },
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Normalizes hex color values to 6-digit format (e.g., #abc -> #aabbcc).
|
|
10
|
+
* Returns null if the hex value is invalid.
|
|
11
|
+
*/
|
|
12
|
+
const normalizeHex = (hex: string): string | null => {
|
|
13
|
+
hex = hex.replace('#', '');
|
|
14
|
+
if (hex.length === 3) hex = [...hex].map((c) => c + c).join('');
|
|
15
|
+
return hex.length === 6 && /^[0-9A-Fa-f]{6}$/.test(hex) ? `#${hex}` : null;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Parses and validates a color value from query parameters.
|
|
20
|
+
* Supports CSS color names, hex values, rgb/rgba, and 'transparent'.
|
|
21
|
+
* Returns null if the color is invalid.
|
|
22
|
+
*/
|
|
23
|
+
const parseColor = (colorParam: string | null): string | null => {
|
|
24
|
+
if (!colorParam) return null;
|
|
25
|
+
const normalized = colorParam.toLowerCase().trim();
|
|
26
|
+
if (normalized === 'transparent') return 'transparent';
|
|
27
|
+
|
|
28
|
+
const testEl = document.createElement('div');
|
|
29
|
+
testEl.style.color = normalized;
|
|
30
|
+
if (testEl.style.color) return normalized;
|
|
31
|
+
|
|
32
|
+
return normalizeHex(colorParam);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Sets or removes a CSS custom property (variable) on an element.
|
|
37
|
+
* Removes the property if value is null.
|
|
38
|
+
*/
|
|
39
|
+
const setCSSVar = (root: HTMLElement, name: string, value: string | null): void => {
|
|
40
|
+
if (value) {
|
|
41
|
+
root.style.setProperty(name, value);
|
|
42
|
+
} else {
|
|
43
|
+
root.style.removeProperty(name);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Derives a description color from a title color by adjusting opacity to 0.8.
|
|
49
|
+
* Converts rgb to rgba if needed, otherwise returns the original color.
|
|
50
|
+
*/
|
|
51
|
+
const deriveDescriptionColor = (titleColor: string): string => {
|
|
52
|
+
if (titleColor.startsWith('rgba')) {
|
|
53
|
+
return titleColor.replace(/,\s*[\d.]+\)$/, ', 0.8)');
|
|
54
|
+
}
|
|
55
|
+
if (titleColor.startsWith('rgb')) {
|
|
56
|
+
return titleColor.replace('rgb', 'rgba').replace(')', ', 0.8)');
|
|
57
|
+
}
|
|
58
|
+
return titleColor;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Controls the visibility of the hero/header image based on the 'headerImage' query parameter.
|
|
63
|
+
* Hides the hero section if headerImage is 'false' or '0'.
|
|
64
|
+
*/
|
|
65
|
+
const applyHeaderImageVisibility = (params: URLSearchParams): void => {
|
|
66
|
+
const heroSection = document.querySelector<HTMLElement>('.hero');
|
|
67
|
+
if (!heroSection) return;
|
|
68
|
+
|
|
69
|
+
const headerImage = params.get('headerImage');
|
|
70
|
+
heroSection.style.display = headerImage === 'false' || headerImage === '0' ? 'none' : '';
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Applies transparent background styling when 'background=transparent' is in query params.
|
|
75
|
+
* Adds CSS classes and sets background styles on root, body, and gallery sections.
|
|
76
|
+
*/
|
|
77
|
+
const applyTransparentBackground = (params: URLSearchParams): void => {
|
|
78
|
+
const root = document.documentElement;
|
|
79
|
+
const body = document.body;
|
|
80
|
+
const isTransparent = params.get('background') === 'transparent';
|
|
81
|
+
|
|
82
|
+
body.classList.toggle('embed-transparent', isTransparent);
|
|
83
|
+
const bgValue = isTransparent ? 'transparent' : '';
|
|
84
|
+
root.style.background = bgValue;
|
|
85
|
+
body.style.background = bgValue;
|
|
86
|
+
|
|
87
|
+
for (const section of document.querySelectorAll('.gallery-section')) {
|
|
88
|
+
section.classList.toggle('gallery-section--transparent', isTransparent);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Applies typography colors from the 'typographyColor' query parameter.
|
|
94
|
+
* Supports preset values (light, dark, white, black) or custom color values.
|
|
95
|
+
* Automatically derives description color from title color if using custom values.
|
|
96
|
+
*/
|
|
97
|
+
const applyTypographyColors = (params: URLSearchParams): void => {
|
|
98
|
+
const root = document.documentElement;
|
|
99
|
+
const typographyParam = params.get('typographyColor');
|
|
100
|
+
|
|
101
|
+
if (!typographyParam) {
|
|
102
|
+
setCSSVar(root, '--typography-color-title', null);
|
|
103
|
+
setCSSVar(root, '--typography-color-description', null);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const normalized = typographyParam.toLowerCase().trim();
|
|
108
|
+
const preset = TYPOGRAPHY_MODERN_THEME_PRESETS[normalized];
|
|
109
|
+
|
|
110
|
+
if (preset) {
|
|
111
|
+
setCSSVar(root, '--typography-color-title', preset.title);
|
|
112
|
+
setCSSVar(root, '--typography-color-description', preset.description);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const color = parseColor(typographyParam);
|
|
117
|
+
if (color) {
|
|
118
|
+
setCSSVar(root, '--typography-color-title', color);
|
|
119
|
+
setCSSVar(root, '--typography-color-description', deriveDescriptionColor(color));
|
|
120
|
+
} else {
|
|
121
|
+
setCSSVar(root, '--typography-color-title', null);
|
|
122
|
+
setCSSVar(root, '--typography-color-description', null);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Applies section background colors from query parameters.
|
|
128
|
+
* Sets CSS variables for general, even, and odd section background colors.
|
|
129
|
+
*/
|
|
130
|
+
const applySectionBackgroundColors = (params: URLSearchParams): void => {
|
|
131
|
+
const root = document.documentElement;
|
|
132
|
+
setCSSVar(root, '--section-bg-color', parseColor(params.get('sectionBgColor')));
|
|
133
|
+
setCSSVar(root, '--section-bg-color-even', parseColor(params.get('sectionBgColorEven')));
|
|
134
|
+
setCSSVar(root, '--section-bg-color-odd', parseColor(params.get('sectionBgColorOdd')));
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Applies hero height from the 'heroHeight' query parameter.
|
|
139
|
+
* Accepts a number (e.g., '100' for 100vh, '50' for 50vh).
|
|
140
|
+
*/
|
|
141
|
+
const applyHeroHeight = (params: URLSearchParams): void => {
|
|
142
|
+
const value = params.get('heroHeight')?.trim();
|
|
143
|
+
const height = value && /^\d+(\.\d+)?$/.test(value) ? `${value}vh` : null;
|
|
144
|
+
setCSSVar(document.documentElement, '--hero-height', height);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Main function that applies all query parameter configurations to the page.
|
|
149
|
+
* Reads URL search params and applies header visibility, background, typography, and section colors.
|
|
150
|
+
*/
|
|
151
|
+
export const applyQueryParams = (): void => {
|
|
152
|
+
const params = new URLSearchParams(globalThis.location.search);
|
|
153
|
+
|
|
154
|
+
applyHeaderImageVisibility(params);
|
|
155
|
+
applyTransparentBackground(params);
|
|
156
|
+
applyTypographyColors(params);
|
|
157
|
+
applySectionBackgroundColors(params);
|
|
158
|
+
applyHeroHeight(params);
|
|
159
|
+
};
|