@simple-photo-gallery/theme-modern 2.0.13 → 2.0.15-rc.18
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 +2 -2
- 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/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 +148 -0
- package/tsconfig.json +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simple-photo-gallery/theme-modern",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.15-rc.18",
|
|
4
4
|
"description": "Modern theme for Simple Photo Gallery",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Vladimir Haltakov, Tomasz Rusin",
|
|
@@ -54,4 +54,4 @@
|
|
|
54
54
|
"typescript-eslint": "^8.35.1"
|
|
55
55
|
},
|
|
56
56
|
"type": "module"
|
|
57
|
-
}
|
|
57
|
+
}
|
|
@@ -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, transparent));
|
|
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;
|
|
@@ -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,148 @@
|
|
|
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
|
+
* Main function that applies all query parameter configurations to the page.
|
|
139
|
+
* Reads URL search params and applies header visibility, background, typography, and section colors.
|
|
140
|
+
*/
|
|
141
|
+
export const applyQueryParams = (): void => {
|
|
142
|
+
const params = new URLSearchParams(globalThis.location.search);
|
|
143
|
+
|
|
144
|
+
applyHeaderImageVisibility(params);
|
|
145
|
+
applyTransparentBackground(params);
|
|
146
|
+
applyTypographyColors(params);
|
|
147
|
+
applySectionBackgroundColors(params);
|
|
148
|
+
};
|