@pixelated-tech/components 3.2.1 → 3.2.4
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/carousel/carousel.css +5 -0
- package/dist/components/cms/contentful.items.components.js +1 -1
- package/dist/components/cms/google.reviews.components.js +7 -0
- package/dist/components/cms/hubspot.components.js +33 -1
- package/dist/components/cms/wordpress.functions.js +52 -0
- package/dist/components/general/loading.js +16 -15
- package/dist/components/menu/menu-accordion.js +9 -14
- package/dist/components/menu/menu-expando.css +97 -90
- package/dist/components/menu/menu-expando.js +115 -17
- package/dist/components/menu/menu-simple.css +4 -0
- package/dist/components/menu/menu-simple.js +8 -3
- package/dist/components/pagebuilder/components/SaveLoadSection.js +1 -1
- package/dist/components/seo/404.js +1 -1
- package/dist/components/seo/sitemap.js +16 -4
- package/dist/components/shoppingcart/shoppingcart.components.js +1 -1
- package/dist/components/structured/buzzwordbingo.js +1 -1
- package/dist/components/structured/recipe.js +1 -1
- package/dist/components/structured/socialcard.js +1 -1
- package/dist/index.js +1 -2
- package/dist/index.server.js +0 -1
- package/dist/types/components/cms/google.reviews.components.d.ts +10 -0
- package/dist/types/components/cms/google.reviews.components.d.ts.map +1 -1
- package/dist/types/components/cms/hubspot.components.d.ts +16 -0
- package/dist/types/components/cms/hubspot.components.d.ts.map +1 -1
- package/dist/types/components/cms/wordpress.functions.d.ts +31 -0
- package/dist/types/components/cms/wordpress.functions.d.ts.map +1 -1
- package/dist/types/components/general/loading.d.ts.map +1 -1
- package/dist/types/components/menu/menu-accordion.d.ts.map +1 -1
- package/dist/types/components/menu/menu-expando.d.ts.map +1 -1
- package/dist/types/components/menu/menu-simple.d.ts +1 -1
- package/dist/types/components/menu/menu-simple.d.ts.map +1 -1
- package/dist/types/components/seo/sitemap.d.ts +2 -0
- package/dist/types/components/seo/sitemap.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.server.d.ts +0 -1
- package/dist/types/stories/menu/menu-expando.stories.d.ts +8 -0
- package/dist/types/stories/menu/menu-expando.stories.d.ts.map +1 -0
- package/dist/types/tests/api.test.d.ts +2 -0
- package/dist/types/tests/api.test.d.ts.map +1 -0
- package/dist/types/tests/buzzwordbingo.test.d.ts +2 -0
- package/dist/types/tests/buzzwordbingo.test.d.ts.map +1 -0
- package/dist/types/tests/calendly.test.d.ts +2 -0
- package/dist/types/tests/calendly.test.d.ts.map +1 -0
- package/dist/types/tests/callout.test.d.ts +2 -0
- package/dist/types/tests/callout.test.d.ts.map +1 -0
- package/dist/types/tests/carousel-drag.test.d.ts +2 -0
- package/dist/types/tests/carousel-drag.test.d.ts.map +1 -0
- package/dist/types/tests/carousel.test.d.ts +2 -0
- package/dist/types/tests/carousel.test.d.ts.map +1 -0
- package/dist/types/tests/cloudinary-image.test.d.ts +2 -0
- package/dist/types/tests/cloudinary-image.test.d.ts.map +1 -0
- package/dist/types/tests/cloudinary.test.d.ts +2 -0
- package/dist/types/tests/cloudinary.test.d.ts.map +1 -0
- package/dist/types/tests/config.client.test.d.ts +2 -0
- package/dist/types/tests/config.client.test.d.ts.map +1 -0
- package/dist/types/tests/config.server.test.d.ts +2 -0
- package/dist/types/tests/config.server.test.d.ts.map +1 -0
- package/dist/types/tests/contentful-items.test.d.ts +2 -0
- package/dist/types/tests/contentful-items.test.d.ts.map +1 -0
- package/dist/types/tests/contentful.delivery.test.d.ts +2 -0
- package/dist/types/tests/contentful.delivery.test.d.ts.map +1 -0
- package/dist/types/tests/css.test.d.ts +2 -0
- package/dist/types/tests/css.test.d.ts.map +1 -0
- package/dist/types/tests/ebay.test.d.ts +2 -0
- package/dist/types/tests/ebay.test.d.ts.map +1 -0
- package/dist/types/tests/form.test.d.ts +2 -0
- package/dist/types/tests/form.test.d.ts.map +1 -0
- package/dist/types/tests/formcomponents.test.d.ts +2 -0
- package/dist/types/tests/formcomponents.test.d.ts.map +1 -0
- package/dist/types/tests/formvalidations.test.d.ts +2 -0
- package/dist/types/tests/formvalidations.test.d.ts.map +1 -0
- package/dist/types/tests/functions.test.d.ts +2 -0
- package/dist/types/tests/functions.test.d.ts.map +1 -0
- package/dist/types/tests/google-analytics.test.d.ts +2 -0
- package/dist/types/tests/google-analytics.test.d.ts.map +1 -0
- package/dist/types/tests/google-map.test.d.ts +2 -0
- package/dist/types/tests/google-map.test.d.ts.map +1 -0
- package/dist/types/tests/google-reviews.test.d.ts +2 -0
- package/dist/types/tests/google-reviews.test.d.ts.map +1 -0
- package/dist/types/tests/googlesearch.test.d.ts +2 -0
- package/dist/types/tests/googlesearch.test.d.ts.map +1 -0
- package/dist/types/tests/gravatar.test.d.ts +2 -0
- package/dist/types/tests/gravatar.test.d.ts.map +1 -0
- package/dist/types/tests/hubspot.test.d.ts +2 -0
- package/dist/types/tests/hubspot.test.d.ts.map +1 -0
- package/dist/types/tests/image.test.d.ts +2 -0
- package/dist/types/tests/image.test.d.ts.map +1 -0
- package/dist/types/tests/instagram.test.d.ts +2 -0
- package/dist/types/tests/instagram.test.d.ts.map +1 -0
- package/dist/types/tests/loading.test.d.ts +2 -0
- package/dist/types/tests/loading.test.d.ts.map +1 -0
- package/dist/types/tests/markdown.test.d.ts +2 -0
- package/dist/types/tests/markdown.test.d.ts.map +1 -0
- package/dist/types/tests/menu-accordion.test.d.ts +2 -0
- package/dist/types/tests/menu-accordion.test.d.ts.map +1 -0
- package/dist/types/tests/menu-expando.test.d.ts +2 -0
- package/dist/types/tests/menu-expando.test.d.ts.map +1 -0
- package/dist/types/tests/menu-simple.test.d.ts +2 -0
- package/dist/types/tests/menu-simple.test.d.ts.map +1 -0
- package/dist/types/tests/metadata.components.test.d.ts +2 -0
- package/dist/types/tests/metadata.components.test.d.ts.map +1 -0
- package/dist/types/tests/microinteractions.test.d.ts +2 -0
- package/dist/types/tests/microinteractions.test.d.ts.map +1 -0
- package/dist/types/tests/modal.test.d.ts +2 -0
- package/dist/types/tests/modal.test.d.ts.map +1 -0
- package/dist/types/tests/nerdjoke.test.d.ts +2 -0
- package/dist/types/tests/nerdjoke.test.d.ts.map +1 -0
- package/dist/types/tests/paypal.test.d.ts +2 -0
- package/dist/types/tests/paypal.test.d.ts.map +1 -0
- package/dist/types/tests/pixelated.menu-expando.test.d.ts +2 -0
- package/dist/types/tests/pixelated.menu-expando.test.d.ts.map +1 -0
- package/dist/types/tests/recipe.test.d.ts +2 -0
- package/dist/types/tests/recipe.test.d.ts.map +1 -0
- package/dist/types/tests/resume.test.d.ts +2 -0
- package/dist/types/tests/resume.test.d.ts.map +1 -0
- package/dist/types/tests/semantic.test.d.ts +2 -0
- package/dist/types/tests/semantic.test.d.ts.map +1 -0
- package/dist/types/tests/setup.d.ts +2 -0
- package/dist/types/tests/setup.d.ts.map +1 -0
- package/dist/types/tests/shopping-cart.test.d.ts +2 -0
- package/dist/types/tests/shopping-cart.test.d.ts.map +1 -0
- package/dist/types/tests/shoppingcart.components.test.d.ts +2 -0
- package/dist/types/tests/shoppingcart.components.test.d.ts.map +1 -0
- package/dist/types/tests/shoppingcart.functions.test.d.ts +2 -0
- package/dist/types/tests/shoppingcart.functions.test.d.ts.map +1 -0
- package/dist/types/tests/sidepanel.test.d.ts +2 -0
- package/dist/types/tests/sidepanel.test.d.ts.map +1 -0
- package/dist/types/tests/socialcard.test.d.ts +2 -0
- package/dist/types/tests/socialcard.test.d.ts.map +1 -0
- package/dist/types/tests/table.test.d.ts +2 -0
- package/dist/types/tests/table.test.d.ts.map +1 -0
- package/dist/types/tests/tiles.test.d.ts +2 -0
- package/dist/types/tests/tiles.test.d.ts.map +1 -0
- package/dist/types/tests/timeline.test.d.ts +2 -0
- package/dist/types/tests/timeline.test.d.ts.map +1 -0
- package/dist/types/tests/wordpress.test.d.ts +2 -0
- package/dist/types/tests/wordpress.test.d.ts.map +1 -0
- package/dist/types/tests/yelp.test.d.ts +2 -0
- package/dist/types/tests/yelp.test.d.ts.map +1 -0
- package/package.json +20 -7
- package/dist/components/cms/hubspot.js +0 -34
- package/dist/types/components/cms/hubspot.d.ts +0 -18
- package/dist/types/components/cms/hubspot.d.ts.map +0 -1
- package/dist/types/tests/pixelated.api.test.d.ts +0 -2
- package/dist/types/tests/pixelated.api.test.d.ts.map +0 -1
- package/dist/types/tests/pixelated.callout.test.d.ts +0 -2
- package/dist/types/tests/pixelated.callout.test.d.ts.map +0 -1
- package/dist/types/tests/pixelated.carousel.test.d.ts +0 -2
- package/dist/types/tests/pixelated.carousel.test.d.ts.map +0 -1
- package/dist/types/tests/pixelated.menu-accordion.test.d.ts +0 -2
- package/dist/types/tests/pixelated.menu-accordion.test.d.ts.map +0 -1
- package/dist/types/tests/pixelated.menu-simple.test.d.ts +0 -2
- package/dist/types/tests/pixelated.menu-simple.test.d.ts.map +0 -1
- package/dist/types/tests/pixelated.nerdjoke.test.d.ts +0 -2
- package/dist/types/tests/pixelated.nerdjoke.test.d.ts.map +0 -1
- package/dist/types/tests/pixelated.recipe.test.d.ts +0 -2
- package/dist/types/tests/pixelated.recipe.test.d.ts.map +0 -1
- package/dist/types/tests/pixelated.resume.test.d.ts +0 -2
- package/dist/types/tests/pixelated.resume.test.d.ts.map +0 -1
- package/dist/types/tests/pixelated.socialcard.test.d.ts +0 -2
- package/dist/types/tests/pixelated.socialcard.test.d.ts.map +0 -1
|
@@ -146,6 +146,11 @@
|
|
|
146
146
|
background-color: transparent;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
.carousel-container .carousel-buttons button.carousel-button {
|
|
150
|
+
/* fix for buttonring microinteraction */
|
|
151
|
+
outline: none !important;
|
|
152
|
+
}
|
|
153
|
+
|
|
149
154
|
.carousel-arrow,
|
|
150
155
|
.carousel-arrow-left,
|
|
151
156
|
.carousel-arrow-right {
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
4
5
|
import { getGoogleReviewsByPlaceId } from './google.reviews.functions';
|
|
6
|
+
GoogleReviewsCard.propTypes = {
|
|
7
|
+
placeID: PropTypes.string.isRequired,
|
|
8
|
+
language: PropTypes.string,
|
|
9
|
+
maxReviews: PropTypes.number,
|
|
10
|
+
proxyBase: PropTypes.string,
|
|
11
|
+
};
|
|
5
12
|
export function GoogleReviewsCard(props) {
|
|
6
13
|
const [place, setPlace] = useState();
|
|
7
14
|
const [reviews, setReviews] = useState([]);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect } from 'react';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
5
|
export function initializeHubSpotScript(region, portalId) {
|
|
@@ -43,3 +43,35 @@ export function HubSpotForm({ region, portalId, formId, target, containerId = 'h
|
|
|
43
43
|
}, [region, portalId, formId, formTarget]);
|
|
44
44
|
return _jsx("div", { className: "hs-form-frame", "data-region": region, "data-form-id": formId, "data-portal-id": portalId });
|
|
45
45
|
}
|
|
46
|
+
HubspotTrackingCode.propTypes = {
|
|
47
|
+
hubID: PropTypes.string.isRequired,
|
|
48
|
+
};
|
|
49
|
+
export function HubspotTrackingCode(props) {
|
|
50
|
+
return (_jsx(_Fragment, { children: _jsx("script", { type: "text/javascript", id: "hs-script-loader", async: true, defer: true, src: `//js-na2.hs-scripts.com/${props.hubID}.js` }) }));
|
|
51
|
+
}
|
|
52
|
+
getHubspotFormSubmissions.propTypes = {
|
|
53
|
+
proxyURL: PropTypes.string.isRequired,
|
|
54
|
+
formGUID: PropTypes.string.isRequired,
|
|
55
|
+
apiToken: PropTypes.string.isRequired,
|
|
56
|
+
};
|
|
57
|
+
export async function getHubspotFormSubmissions(props) {
|
|
58
|
+
const url = `${props.proxyURL}https://api.hubapi.com/form-integrations/v1/submissions/forms/${props.formGUID}`;
|
|
59
|
+
const headers = {
|
|
60
|
+
Authorization: "Bearer " + props.apiToken,
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(url, {
|
|
64
|
+
method: 'GET',
|
|
65
|
+
headers: headers,
|
|
66
|
+
});
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
69
|
+
}
|
|
70
|
+
const data = await response.json();
|
|
71
|
+
return data;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error('Error fetching HubSpot form submissions:', error);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import PropTypes from "prop-types";
|
|
1
2
|
// const wpSite = "pixelatedviews.wordpress.com";
|
|
2
3
|
// const wpSite = "19824045";
|
|
3
4
|
// const wpSite = "blog.pixelated.tech";
|
|
4
5
|
const wpApiURL = "https://public-api.wordpress.com/rest/v1/sites/";
|
|
5
6
|
const wpCategoriesPath = "/categories";
|
|
7
|
+
getWordPressItems.propTypes = {
|
|
8
|
+
site: PropTypes.string.isRequired,
|
|
9
|
+
count: PropTypes.number,
|
|
10
|
+
};
|
|
6
11
|
export async function getWordPressItems(props) {
|
|
7
12
|
const requested = props.count; // undefined means fetch all available
|
|
8
13
|
const posts = [];
|
|
@@ -31,6 +36,53 @@ export async function getWordPressItems(props) {
|
|
|
31
36
|
}
|
|
32
37
|
return posts;
|
|
33
38
|
}
|
|
39
|
+
getWordPressItemImages.propTypes = {
|
|
40
|
+
item: PropTypes.object.isRequired,
|
|
41
|
+
};
|
|
42
|
+
export function getWordPressItemImages(item) {
|
|
43
|
+
const images = [];
|
|
44
|
+
const seen = new Set();
|
|
45
|
+
// Helper to swap image origin with post origin
|
|
46
|
+
const swapOrigin = (url) => {
|
|
47
|
+
try {
|
|
48
|
+
const postOrigin = new URL(item.URL).origin;
|
|
49
|
+
const urlObj = new URL(url);
|
|
50
|
+
return `${postOrigin}${urlObj.pathname}`;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.log("Error: ", error);
|
|
54
|
+
return url;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
// Featured image
|
|
58
|
+
if (item.featured_image && !seen.has(item.featured_image)) {
|
|
59
|
+
seen.add(item.featured_image);
|
|
60
|
+
images.push({
|
|
61
|
+
url: swapOrigin(item.featured_image),
|
|
62
|
+
title: item.title,
|
|
63
|
+
caption: item.excerpt,
|
|
64
|
+
thumbnail_loc: item.post_thumbnail?.URL,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
// Attachments
|
|
68
|
+
if (item.attachments) {
|
|
69
|
+
for (const key in item.attachments) {
|
|
70
|
+
const att = item.attachments[key];
|
|
71
|
+
if (att.URL && !seen.has(att.URL)) {
|
|
72
|
+
seen.add(att.URL);
|
|
73
|
+
images.push({
|
|
74
|
+
url: swapOrigin(att.URL),
|
|
75
|
+
title: att.title,
|
|
76
|
+
caption: att.caption || att.description,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return images;
|
|
82
|
+
}
|
|
83
|
+
getWordPressCategories.propTypes = {
|
|
84
|
+
site: PropTypes.string.isRequired,
|
|
85
|
+
};
|
|
34
86
|
export async function getWordPressCategories(props) {
|
|
35
87
|
const wpCategoriesURL = wpApiURL + props.site + wpCategoriesPath;
|
|
36
88
|
const categories = [];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
3
|
import PropTypes from "prop-types";
|
|
3
4
|
import "./loading.scss";
|
|
@@ -13,24 +14,24 @@ ToggleLoading.propTypes = {
|
|
|
13
14
|
show: PropTypes.bool,
|
|
14
15
|
};
|
|
15
16
|
export function ToggleLoading(props) {
|
|
16
|
-
if (typeof window
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
if (typeof window === 'undefined' || typeof document === 'undefined')
|
|
18
|
+
return;
|
|
19
|
+
const loadingElem = document.getElementById("loadingSpinner");
|
|
20
|
+
if (!loadingElem)
|
|
21
|
+
return;
|
|
22
|
+
if (props.show === true) {
|
|
23
|
+
loadingElem.style.display = "inline-block";
|
|
24
|
+
}
|
|
25
|
+
else if (props.show === false) {
|
|
26
|
+
loadingElem.style.display = "none";
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Toggle behavior
|
|
30
|
+
if (loadingElem.style.display === "none" || !loadingElem.style.display) {
|
|
21
31
|
loadingElem.style.display = "inline-block";
|
|
22
|
-
return;
|
|
23
|
-
} // Show content
|
|
24
|
-
if (props.show && props.show === false) {
|
|
25
|
-
loadingElem.style.display = "none";
|
|
26
|
-
return;
|
|
27
|
-
} // Hide content
|
|
28
|
-
if (loadingElem && loadingElem.style.display === "none") {
|
|
29
|
-
loadingElem.style.display = "inline-block"; // Show content
|
|
30
32
|
}
|
|
31
33
|
else {
|
|
32
|
-
|
|
33
|
-
loadingElem.style.display = "none"; // Hide content
|
|
34
|
+
loadingElem.style.display = "none";
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -140,7 +140,7 @@ export function MenuAccordion(props) {
|
|
|
140
140
|
document.removeEventListener('click', handleMenuClick);
|
|
141
141
|
};
|
|
142
142
|
}, []);
|
|
143
|
-
return (_jsx("div", { className: "accordionMenuWrapper accordionUp", children: _jsx("div", { className: "accordionMenu", id: "accordionMenu", children: _jsx(MenuAccordionGroup, { menuItems: menuItems, state: undefined }, "accordionRoot") }) }));
|
|
143
|
+
return (_jsx("div", { className: "accordionMenuWrapper accordionUp", suppressHydrationWarning: true, children: _jsx("div", { className: "accordionMenu", id: "accordionMenu", children: _jsx(MenuAccordionGroup, { menuItems: menuItems, state: undefined }, "accordionRoot") }) }));
|
|
144
144
|
}
|
|
145
145
|
/* ========== MENU GROUP ========== */
|
|
146
146
|
MenuAccordionGroup.propTypes = {
|
|
@@ -158,17 +158,9 @@ MenuAccordionItem.propTypes = {
|
|
|
158
158
|
target: PropTypes.string,
|
|
159
159
|
};
|
|
160
160
|
export function MenuAccordionItem(props) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
return (_jsx("li", { children: _jsx("a", { href: props.href, children: props.name }) }, "menu-item-" + props.name));
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
return (_jsx("li", { children: _jsx("a", { children: props.name }) }, "menu-item-" + props.name));
|
|
171
|
-
}
|
|
161
|
+
// Always render the same JSX structure to avoid hydration mismatch
|
|
162
|
+
// href will be undefined or an empty string, target might be undefined
|
|
163
|
+
return (_jsx("li", { children: _jsx("a", { href: props.href || undefined, target: props.target || undefined, children: props.name }) }, "menu-item-" + props.name));
|
|
172
164
|
}
|
|
173
165
|
/* ========== MENU BUTTON ========== */
|
|
174
166
|
/*
|
|
@@ -177,7 +169,10 @@ https://www.unclebigbay.com/blog/building-the-world-simplest-hamburger-with-html
|
|
|
177
169
|
MenuAccordionButton.propTypes = {};
|
|
178
170
|
export function MenuAccordionButton() {
|
|
179
171
|
function slideMobilePanel() {
|
|
180
|
-
window.moveMenu
|
|
172
|
+
if (typeof window !== 'undefined' && window.moveMenu) {
|
|
173
|
+
window.moveMenu();
|
|
174
|
+
}
|
|
181
175
|
}
|
|
182
|
-
|
|
176
|
+
// suppressHydrationWarning suppresses hydration mismatch warnings for this button
|
|
177
|
+
return (_jsx("button", { className: "panelMenuButton", id: "panelMenuButton", onClick: slideMobilePanel, suppressHydrationWarning: true, children: _jsx("span", { className: "hamburger text-outline", children: "|||" }) }));
|
|
183
178
|
}
|
|
@@ -1,127 +1,134 @@
|
|
|
1
1
|
|
|
2
|
+
|
|
2
3
|
/* ========================================
|
|
3
|
-
=====
|
|
4
|
+
===== MENU EXPANDO COMPONENT =====
|
|
4
5
|
======================================== */
|
|
5
6
|
|
|
6
|
-
.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/* display: inline; */
|
|
10
|
-
margin: 0px 10px 0px 0px;
|
|
11
|
-
padding: 5px;
|
|
12
|
-
text-align: center;
|
|
13
|
-
width: 35px;
|
|
7
|
+
.menuExpando {
|
|
8
|
+
display: inline-block;
|
|
9
|
+
}
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-webkit-border-radius: 5px;
|
|
18
|
-
border-radius: 5px;
|
|
11
|
+
details.menuExpandoWrapper {
|
|
12
|
+
display: inline-block;
|
|
19
13
|
}
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
details.menuExpandoWrapper > summary {
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
user-select: none;
|
|
18
|
+
background: #336699;
|
|
19
|
+
color: white;
|
|
20
|
+
padding: 10px 15px;
|
|
21
|
+
border-radius: 4px;
|
|
22
|
+
font-weight: bold;
|
|
23
|
+
display: inline-block;
|
|
24
|
+
transition: background 0.3s ease;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
.
|
|
28
|
-
background
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
padding: 15px;
|
|
27
|
+
details.menuExpandoWrapper > summary:hover {
|
|
28
|
+
background: #2d5a8a;
|
|
29
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
30
|
+
}
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
border-radius: 5px;
|
|
32
|
+
details.menuExpandoWrapper > summary::marker,
|
|
33
|
+
details.menuExpandoWrapper > summary::-webkit-details-marker {
|
|
34
|
+
display: none;
|
|
37
35
|
}
|
|
38
36
|
|
|
37
|
+
details.menuExpandoWrapper > summary::before {
|
|
38
|
+
content: '▼';
|
|
39
|
+
display: inline-block;
|
|
40
|
+
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
details.menuExpandoWrapper[open] > summary::before {
|
|
43
|
+
content: '▲';
|
|
44
|
+
}
|
|
43
45
|
|
|
44
|
-
details.menuExpandoWrapper {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
left: 0px;
|
|
51
|
-
top: 60px;
|
|
52
|
-
/* height: 100%; */
|
|
53
|
-
width: 220px;
|
|
54
|
-
z-index: 1000;
|
|
55
|
-
/* padding: 5px; */
|
|
46
|
+
details.menuExpandoWrapper ul {
|
|
47
|
+
margin-top: 10px;
|
|
48
|
+
padding-left: 20px;
|
|
49
|
+
list-style: none;
|
|
50
|
+
overflow: visible;
|
|
51
|
+
max-height: 1000px;
|
|
56
52
|
}
|
|
57
53
|
|
|
58
|
-
details.menuExpandoWrapper
|
|
59
|
-
|
|
60
|
-
list-style: none;
|
|
61
|
-
height: 0px;
|
|
62
|
-
width: 0px;
|
|
54
|
+
details.menuExpandoWrapper li {
|
|
55
|
+
margin: 5px 0;
|
|
63
56
|
}
|
|
64
57
|
|
|
65
|
-
details.menuExpandoWrapper
|
|
66
|
-
|
|
58
|
+
details.menuExpandoWrapper a {
|
|
59
|
+
color: #333;
|
|
60
|
+
text-decoration: none;
|
|
61
|
+
transition: color 0.2s ease;
|
|
67
62
|
}
|
|
68
63
|
|
|
69
|
-
details.menuExpandoWrapper:
|
|
70
|
-
|
|
64
|
+
details.menuExpandoWrapper a:hover {
|
|
65
|
+
color: #336699;
|
|
66
|
+
text-decoration: underline;
|
|
71
67
|
}
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
details.
|
|
75
|
-
|
|
76
|
-
animation: sweep 1s ease-out;
|
|
69
|
+
/* ========== NESTED MENU STYLING ========== */
|
|
70
|
+
details.menuExpandoNested {
|
|
71
|
+
display: block;
|
|
77
72
|
}
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
details.menuExpandoNested > summary {
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
user-select: none;
|
|
77
|
+
padding: 5px 0;
|
|
78
|
+
font-weight: 500;
|
|
79
|
+
display: list-item;
|
|
80
|
+
color: #333;
|
|
81
|
+
transition: color 0.2s ease;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
details.
|
|
85
|
-
|
|
86
|
-
display:none;
|
|
84
|
+
details.menuExpandoNested > summary:hover {
|
|
85
|
+
color: #336699;
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
display: inline-block;
|
|
93
|
-
list-style-type: none;
|
|
94
|
-
padding: 0;
|
|
95
|
-
width: 200px;
|
|
96
|
-
margin: 10px;
|
|
88
|
+
details.menuExpandoNested > summary a {
|
|
89
|
+
color: inherit;
|
|
90
|
+
text-decoration: none;
|
|
97
91
|
}
|
|
98
92
|
|
|
99
|
-
.
|
|
100
|
-
|
|
101
|
-
border-bottom: 1px solid #FFF;
|
|
93
|
+
details.menuExpandoNested > summary a:hover {
|
|
94
|
+
text-decoration: underline;
|
|
102
95
|
}
|
|
103
96
|
|
|
104
|
-
.
|
|
105
|
-
|
|
106
|
-
|
|
97
|
+
details.menuExpandoNested > summary::marker,
|
|
98
|
+
details.menuExpandoNested > summary::-webkit-details-marker {
|
|
99
|
+
color: #666;
|
|
107
100
|
}
|
|
108
101
|
|
|
109
|
-
.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
102
|
+
details.menuExpandoNested > ul {
|
|
103
|
+
margin: 0px;
|
|
104
|
+
padding-left: 20px;
|
|
105
|
+
list-style: none;
|
|
106
|
+
max-height: 0px;
|
|
107
|
+
opacity: 0;
|
|
108
|
+
overflow: hidden;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
details.menuExpandoNested li {
|
|
112
|
+
margin: 3px 0;
|
|
120
113
|
}
|
|
121
114
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
115
|
+
/* ========== ANIMATIONS ========== */
|
|
116
|
+
@keyframes menuExpandoSlideDown {
|
|
117
|
+
from {
|
|
118
|
+
opacity: 0;
|
|
119
|
+
}
|
|
120
|
+
to {
|
|
121
|
+
opacity: 1;
|
|
122
|
+
}
|
|
127
123
|
}
|
|
124
|
+
|
|
125
|
+
@keyframes menuExpandoSlideUp {
|
|
126
|
+
from {
|
|
127
|
+
opacity: 1;
|
|
128
|
+
}
|
|
129
|
+
to {
|
|
130
|
+
opacity: 0;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
@@ -1,28 +1,131 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
3
4
|
import PropTypes from 'prop-types';
|
|
4
5
|
import './menu-expando.css';
|
|
5
|
-
/*
|
|
6
|
-
NOTE :
|
|
7
|
-
Stopped development on details / summary for now.
|
|
8
|
-
Not enough css control for animation.
|
|
9
|
-
*/
|
|
10
|
-
/* ========== MENU ========== */
|
|
11
6
|
export function MenuExpando(props) {
|
|
12
|
-
|
|
7
|
+
const detailsRef = useRef(null);
|
|
8
|
+
const ulRef = useRef(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const details = detailsRef.current;
|
|
11
|
+
const ul = ulRef.current;
|
|
12
|
+
if (!details || !ul)
|
|
13
|
+
return;
|
|
14
|
+
const summary = details.querySelector('summary');
|
|
15
|
+
if (!summary)
|
|
16
|
+
return;
|
|
17
|
+
// Initialize nested menus to be closed
|
|
18
|
+
const nestedDetails = details.querySelectorAll('details.menuExpandoNested');
|
|
19
|
+
nestedDetails.forEach((nested) => {
|
|
20
|
+
const nestedUl = nested.querySelector('ul');
|
|
21
|
+
if (nestedUl) {
|
|
22
|
+
nestedUl.style.maxHeight = '0px';
|
|
23
|
+
nestedUl.style.opacity = '0';
|
|
24
|
+
nestedUl.style.overflow = 'hidden';
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
let isAnimating = false;
|
|
28
|
+
summary.addEventListener('click', (e) => {
|
|
29
|
+
if (isAnimating) {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
e.preventDefault();
|
|
34
|
+
isAnimating = true;
|
|
35
|
+
if (details.open) {
|
|
36
|
+
// Closing animation
|
|
37
|
+
ul.style.animation = 'menuExpandoSlideUp 0.3s ease-out forwards';
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
details.open = false;
|
|
40
|
+
ul.style.animation = '';
|
|
41
|
+
isAnimating = false;
|
|
42
|
+
}, 300);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Opening animation
|
|
46
|
+
details.open = true;
|
|
47
|
+
ul.style.animation = 'menuExpandoSlideDown 0.3s ease-out forwards';
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
ul.style.animation = '';
|
|
50
|
+
isAnimating = false;
|
|
51
|
+
}, 300);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// Handle nested menu animations
|
|
55
|
+
const nestedDetailsForAnimation = details.querySelectorAll('details.menuExpandoNested');
|
|
56
|
+
nestedDetailsForAnimation.forEach((nested) => {
|
|
57
|
+
nested.addEventListener('toggle', (e) => {
|
|
58
|
+
const nestedUl = nested.querySelector('ul');
|
|
59
|
+
if (nestedUl) {
|
|
60
|
+
if (nested.open) {
|
|
61
|
+
nestedUl.style.maxHeight = '0px';
|
|
62
|
+
nestedUl.style.opacity = '0';
|
|
63
|
+
nestedUl.style.overflow = 'hidden';
|
|
64
|
+
// Force reflow
|
|
65
|
+
void nestedUl.offsetHeight;
|
|
66
|
+
nestedUl.style.transition = 'max-height 0.3s ease-out, opacity 0.3s ease-out';
|
|
67
|
+
nestedUl.style.maxHeight = '500px';
|
|
68
|
+
nestedUl.style.opacity = '1';
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
nestedUl.style.overflow = 'visible';
|
|
71
|
+
nestedUl.style.transition = '';
|
|
72
|
+
}, 300);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
nestedUl.style.overflow = 'hidden';
|
|
76
|
+
nestedUl.style.transition = 'max-height 0.3s ease-out, opacity 0.3s ease-out';
|
|
77
|
+
nestedUl.style.maxHeight = '0px';
|
|
78
|
+
nestedUl.style.opacity = '0';
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
nestedUl.style.transition = '';
|
|
81
|
+
}, 300);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}, []);
|
|
13
87
|
function generateMenuItems() {
|
|
14
88
|
const myItems = [];
|
|
15
|
-
|
|
16
|
-
|
|
89
|
+
console.log('MenuExpando props.menuItems:', props.menuItems);
|
|
90
|
+
console.log('Is array?', Array.isArray(props.menuItems));
|
|
91
|
+
// Handle both object format (name: href) and array format (with name/path properties)
|
|
92
|
+
if (Array.isArray(props.menuItems)) {
|
|
93
|
+
// Array format like MenuAccordion
|
|
94
|
+
console.log('Processing as array, length:', props.menuItems.length);
|
|
95
|
+
for (const item of props.menuItems) {
|
|
96
|
+
console.log('Item:', item);
|
|
97
|
+
if (item.routes && item.routes.length > 0) {
|
|
98
|
+
// Item has nested routes - create expandable submenu
|
|
99
|
+
myItems.push(_jsx("li", { children: _jsxs("details", { className: "menuExpandoNested", children: [_jsx("summary", { children: _jsx("a", { href: item.path, children: item.name }) }), _jsx("ul", { children: item.routes.map((route) => (_jsx(MenuExpandoItem, { name: route.name, href: route.path }, route.name))) })] }) }, item.name));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Regular item without nested routes
|
|
103
|
+
myItems.push(_jsx(MenuExpandoItem, { name: item.name, href: item.path }, item.name));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
17
106
|
}
|
|
107
|
+
else {
|
|
108
|
+
// Object format
|
|
109
|
+
console.log('Processing as object');
|
|
110
|
+
for (const itemKey in props.menuItems) {
|
|
111
|
+
myItems.push(_jsx(MenuExpandoItem, { name: itemKey, href: props.menuItems[itemKey] }, itemKey));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
console.log('Generated items count:', myItems.length);
|
|
18
115
|
return myItems;
|
|
19
116
|
}
|
|
20
|
-
return (_jsx("div", { className: "menuExpando", id: "menuExpando", children: _jsxs("details", { className: "menuExpandoWrapper", id: "menuExpandoWrapper", children: [_jsx("summary", {}), _jsx("ul", { children: generateMenuItems() })] }) }));
|
|
117
|
+
return (_jsx("div", { className: "menuExpando", id: "menuExpando", children: _jsxs("details", { className: "menuExpandoWrapper", id: "menuExpandoWrapper", ref: detailsRef, children: [_jsx("summary", {}), _jsx("ul", { ref: ulRef, children: generateMenuItems() })] }) }));
|
|
21
118
|
}
|
|
22
119
|
MenuExpando.propTypes = {
|
|
23
|
-
menuItems: PropTypes.
|
|
120
|
+
menuItems: PropTypes.oneOfType([
|
|
121
|
+
PropTypes.object,
|
|
122
|
+
PropTypes.arrayOf(PropTypes.shape({
|
|
123
|
+
name: PropTypes.string.isRequired,
|
|
124
|
+
path: PropTypes.string.isRequired,
|
|
125
|
+
routes: PropTypes.array,
|
|
126
|
+
}))
|
|
127
|
+
]).isRequired
|
|
24
128
|
};
|
|
25
|
-
/* ========== MENU ITEM ========== */
|
|
26
129
|
export function MenuExpandoItem(props) {
|
|
27
130
|
return (_jsx("li", { children: _jsx("a", { href: props.href, children: props.name }) }));
|
|
28
131
|
}
|
|
@@ -30,15 +133,10 @@ MenuExpandoItem.propTypes = {
|
|
|
30
133
|
name: PropTypes.string.isRequired,
|
|
31
134
|
href: PropTypes.string.isRequired
|
|
32
135
|
};
|
|
33
|
-
/* ========== MENU BUTTON ========== */
|
|
34
136
|
export function MenuExpandoButton() {
|
|
35
137
|
function handleMenuExpandoButtonClick(event) {
|
|
36
|
-
const debug = false;
|
|
37
|
-
if (debug)
|
|
38
|
-
console.log("MenuExpandoButton clicked");
|
|
39
138
|
event.preventDefault();
|
|
40
139
|
event.stopPropagation();
|
|
41
|
-
// const button = document.getElementById('menuExpandoButton');
|
|
42
140
|
const details = document.getElementById('menuExpandoWrapper');
|
|
43
141
|
if (details)
|
|
44
142
|
details.open = !details.open;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
3
|
import { useEffect } from 'react';
|
|
3
4
|
import PropTypes from "prop-types";
|
|
@@ -26,6 +27,8 @@ export function MenuSimple(props) {
|
|
|
26
27
|
return myItems;
|
|
27
28
|
}
|
|
28
29
|
function styleSelectedMenuItem() {
|
|
30
|
+
if (typeof window === 'undefined')
|
|
31
|
+
return;
|
|
29
32
|
const menuitems = document.querySelectorAll('.menu-item a');
|
|
30
33
|
const currentURL = window.location.href;
|
|
31
34
|
menuitems.forEach((menuitem) => {
|
|
@@ -48,9 +51,11 @@ MenuSimpleItem.propTypes = {
|
|
|
48
51
|
routes: PropTypes.array,
|
|
49
52
|
};
|
|
50
53
|
export function MenuSimpleItem(props) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
const classNames = ['menu-item'];
|
|
55
|
+
if (props.hidden) {
|
|
56
|
+
classNames.push('menu-item-hidden');
|
|
57
|
+
}
|
|
58
|
+
return (_jsx("li", { className: classNames.join(' '), children: props.target
|
|
54
59
|
? _jsx("a", { href: props.path || undefined, target: props.target, children: props.name })
|
|
55
60
|
: _jsx("a", { href: props.path || undefined, children: props.name }) }));
|
|
56
61
|
}
|