@marvalt/shcoder 0.1.1 → 0.1.3
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/MemberCardsGrid.d.ts.map +1 -1
- package/dist/hooks/useMembers.d.ts +13 -0
- package/dist/hooks/useMembers.d.ts.map +1 -1
- package/dist/index.cjs +131 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +131 -61
- package/dist/index.esm.js.map +1 -1
- package/dist/utils/cloudflareImageUrl.d.ts +14 -0
- package/dist/utils/cloudflareImageUrl.d.ts.map +1 -0
- package/package.json +10 -2
package/dist/index.esm.js
CHANGED
|
@@ -35,6 +35,42 @@ function getApiUrl$1() {
|
|
|
35
35
|
}
|
|
36
36
|
// Initialize API URL
|
|
37
37
|
apiUrl$1 = getApiUrl$1();
|
|
38
|
+
let staticDataProvider = null;
|
|
39
|
+
function setStaticDataProvider(provider) {
|
|
40
|
+
staticDataProvider = provider;
|
|
41
|
+
}
|
|
42
|
+
// Helper function to extract featured image from member data
|
|
43
|
+
function extractFeaturedImage(member) {
|
|
44
|
+
if (member.featured_image_urls) {
|
|
45
|
+
return member.featured_image_urls;
|
|
46
|
+
}
|
|
47
|
+
if (member._embedded?.['wp:featuredmedia']?.[0]) {
|
|
48
|
+
const featuredMedia = member._embedded['wp:featuredmedia'][0];
|
|
49
|
+
return {
|
|
50
|
+
thumbnail: featuredMedia.media_details?.sizes?.thumbnail ? {
|
|
51
|
+
url: featuredMedia.media_details.sizes.thumbnail.source_url,
|
|
52
|
+
width: featuredMedia.media_details.sizes.thumbnail.width,
|
|
53
|
+
height: featuredMedia.media_details.sizes.thumbnail.height,
|
|
54
|
+
} : undefined,
|
|
55
|
+
medium: featuredMedia.media_details?.sizes?.medium ? {
|
|
56
|
+
url: featuredMedia.media_details.sizes.medium.source_url,
|
|
57
|
+
width: featuredMedia.media_details.sizes.medium.width,
|
|
58
|
+
height: featuredMedia.media_details.sizes.medium.height,
|
|
59
|
+
} : undefined,
|
|
60
|
+
large: featuredMedia.media_details?.sizes?.large ? {
|
|
61
|
+
url: featuredMedia.media_details.sizes.large.source_url,
|
|
62
|
+
width: featuredMedia.media_details.sizes.large.width,
|
|
63
|
+
height: featuredMedia.media_details.sizes.large.height,
|
|
64
|
+
} : undefined,
|
|
65
|
+
full: {
|
|
66
|
+
url: featuredMedia.source_url || featuredMedia.media_details?.sizes?.full?.source_url || '',
|
|
67
|
+
width: featuredMedia.media_details?.width || 0,
|
|
68
|
+
height: featuredMedia.media_details?.height || 0,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
38
74
|
/**
|
|
39
75
|
* Hook to fetch members based on shortcode attributes
|
|
40
76
|
*/
|
|
@@ -43,15 +79,39 @@ function useMembers(attrs) {
|
|
|
43
79
|
const [loading, setLoading] = useState(true);
|
|
44
80
|
const [error, setError] = useState(null);
|
|
45
81
|
useEffect(() => {
|
|
46
|
-
if (!apiUrl$1) {
|
|
47
|
-
setError(new Error('WordPress API URL not configured'));
|
|
48
|
-
setLoading(false);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
82
|
async function fetchMembers() {
|
|
52
83
|
try {
|
|
53
84
|
setLoading(true);
|
|
54
85
|
setError(null);
|
|
86
|
+
// Use static data if available (preferred method)
|
|
87
|
+
if (staticDataProvider) {
|
|
88
|
+
const provider = staticDataProvider();
|
|
89
|
+
const filtered = provider.filterMembers({
|
|
90
|
+
category: attrs.tax || attrs.category,
|
|
91
|
+
role: attrs.role,
|
|
92
|
+
limit: attrs.limit ? parseInt(attrs.limit, 10) : undefined,
|
|
93
|
+
orderby: attrs.orderby || 'date',
|
|
94
|
+
order: attrs.order || 'desc',
|
|
95
|
+
});
|
|
96
|
+
// Process members to match Member interface
|
|
97
|
+
const processedMembers = filtered.map((member) => {
|
|
98
|
+
const processed = {
|
|
99
|
+
...member,
|
|
100
|
+
member_meta: member.member_meta || {},
|
|
101
|
+
featured_image_urls: extractFeaturedImage(member),
|
|
102
|
+
};
|
|
103
|
+
return processed;
|
|
104
|
+
});
|
|
105
|
+
setMembers(processedMembers);
|
|
106
|
+
setLoading(false);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Fallback to API (should not happen in production with static data)
|
|
110
|
+
if (!apiUrl$1) {
|
|
111
|
+
setError(new Error('WordPress API URL not configured and no static data provider available'));
|
|
112
|
+
setLoading(false);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
55
115
|
// Build query params from shortcode attributes
|
|
56
116
|
const params = {
|
|
57
117
|
per_page: (attrs.limit ? parseInt(attrs.limit, 10) : 100).toString(),
|
|
@@ -84,33 +144,8 @@ function useMembers(attrs) {
|
|
|
84
144
|
const processed = {
|
|
85
145
|
...member,
|
|
86
146
|
member_meta: member.member_meta || {},
|
|
147
|
+
featured_image_urls: extractFeaturedImage(member),
|
|
87
148
|
};
|
|
88
|
-
// Extract featured image from _embedded
|
|
89
|
-
if (member._embedded && member._embedded['wp:featuredmedia'] && member._embedded['wp:featuredmedia'][0]) {
|
|
90
|
-
const featuredMedia = member._embedded['wp:featuredmedia'][0];
|
|
91
|
-
processed.featured_image_urls = {
|
|
92
|
-
thumbnail: featuredMedia.media_details?.sizes?.thumbnail ? {
|
|
93
|
-
url: featuredMedia.media_details.sizes.thumbnail.source_url,
|
|
94
|
-
width: featuredMedia.media_details.sizes.thumbnail.width,
|
|
95
|
-
height: featuredMedia.media_details.sizes.thumbnail.height,
|
|
96
|
-
} : undefined,
|
|
97
|
-
medium: featuredMedia.media_details?.sizes?.medium ? {
|
|
98
|
-
url: featuredMedia.media_details.sizes.medium.source_url,
|
|
99
|
-
width: featuredMedia.media_details.sizes.medium.width,
|
|
100
|
-
height: featuredMedia.media_details.sizes.medium.height,
|
|
101
|
-
} : undefined,
|
|
102
|
-
large: featuredMedia.media_details?.sizes?.large ? {
|
|
103
|
-
url: featuredMedia.media_details.sizes.large.source_url,
|
|
104
|
-
width: featuredMedia.media_details.sizes.large.width,
|
|
105
|
-
height: featuredMedia.media_details.sizes.large.height,
|
|
106
|
-
} : undefined,
|
|
107
|
-
full: {
|
|
108
|
-
url: featuredMedia.source_url || featuredMedia.media_details?.sizes?.full?.source_url || '',
|
|
109
|
-
width: featuredMedia.media_details?.width || 0,
|
|
110
|
-
height: featuredMedia.media_details?.height || 0,
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
149
|
return processed;
|
|
115
150
|
});
|
|
116
151
|
setMembers(processedMembers);
|
|
@@ -135,7 +170,7 @@ function useMember(id) {
|
|
|
135
170
|
const [loading, setLoading] = useState(true);
|
|
136
171
|
const [error, setError] = useState(null);
|
|
137
172
|
useEffect(() => {
|
|
138
|
-
if (!
|
|
173
|
+
if (!id) {
|
|
139
174
|
setLoading(false);
|
|
140
175
|
return;
|
|
141
176
|
}
|
|
@@ -143,6 +178,31 @@ function useMember(id) {
|
|
|
143
178
|
try {
|
|
144
179
|
setLoading(true);
|
|
145
180
|
setError(null);
|
|
181
|
+
// Use static data if available (preferred method)
|
|
182
|
+
if (staticDataProvider) {
|
|
183
|
+
const provider = staticDataProvider();
|
|
184
|
+
const found = provider.getMemberById(id);
|
|
185
|
+
if (found) {
|
|
186
|
+
// Process member to match Member interface
|
|
187
|
+
const processed = {
|
|
188
|
+
...found,
|
|
189
|
+
member_meta: found.member_meta || {},
|
|
190
|
+
featured_image_urls: extractFeaturedImage(found),
|
|
191
|
+
};
|
|
192
|
+
setMember(processed);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
setMember(null);
|
|
196
|
+
}
|
|
197
|
+
setLoading(false);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// Fallback to API (should not happen in production with static data)
|
|
201
|
+
if (!apiUrl$1) {
|
|
202
|
+
setError(new Error('WordPress API URL not configured and no static data provider available'));
|
|
203
|
+
setLoading(false);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
146
206
|
const response = await fetch(`${apiUrl$1}/wp/v2/member/${id}?_embed=true`);
|
|
147
207
|
if (!response.ok) {
|
|
148
208
|
throw new Error(`Failed to fetch member: ${response.statusText}`);
|
|
@@ -152,33 +212,8 @@ function useMember(id) {
|
|
|
152
212
|
const processed = {
|
|
153
213
|
...data,
|
|
154
214
|
member_meta: data.member_meta || {},
|
|
215
|
+
featured_image_urls: extractFeaturedImage(data),
|
|
155
216
|
};
|
|
156
|
-
// Extract featured image from _embedded
|
|
157
|
-
if (data._embedded && data._embedded['wp:featuredmedia'] && data._embedded['wp:featuredmedia'][0]) {
|
|
158
|
-
const featuredMedia = data._embedded['wp:featuredmedia'][0];
|
|
159
|
-
processed.featured_image_urls = {
|
|
160
|
-
thumbnail: featuredMedia.media_details?.sizes?.thumbnail ? {
|
|
161
|
-
url: featuredMedia.media_details.sizes.thumbnail.source_url,
|
|
162
|
-
width: featuredMedia.media_details.sizes.thumbnail.width,
|
|
163
|
-
height: featuredMedia.media_details.sizes.thumbnail.height,
|
|
164
|
-
} : undefined,
|
|
165
|
-
medium: featuredMedia.media_details?.sizes?.medium ? {
|
|
166
|
-
url: featuredMedia.media_details.sizes.medium.source_url,
|
|
167
|
-
width: featuredMedia.media_details.sizes.medium.width,
|
|
168
|
-
height: featuredMedia.media_details.sizes.medium.height,
|
|
169
|
-
} : undefined,
|
|
170
|
-
large: featuredMedia.media_details?.sizes?.large ? {
|
|
171
|
-
url: featuredMedia.media_details.sizes.large.source_url,
|
|
172
|
-
width: featuredMedia.media_details.sizes.large.width,
|
|
173
|
-
height: featuredMedia.media_details.sizes.large.height,
|
|
174
|
-
} : undefined,
|
|
175
|
-
full: {
|
|
176
|
-
url: featuredMedia.source_url || featuredMedia.media_details?.sizes?.full?.source_url || '',
|
|
177
|
-
width: featuredMedia.media_details?.width || 0,
|
|
178
|
-
height: featuredMedia.media_details?.height || 0,
|
|
179
|
-
},
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
217
|
setMember(processed);
|
|
183
218
|
}
|
|
184
219
|
catch (err) {
|
|
@@ -1705,6 +1740,37 @@ const MemberCard = ({ id, className = '' }) => {
|
|
|
1705
1740
|
return (jsxRuntimeExports.jsxs("div", { className: `member-card ${className}`, children: [imageUrl && (jsxRuntimeExports.jsx("div", { className: "member-card-image", children: jsxRuntimeExports.jsx("img", { src: imageUrl, alt: fullName, className: "w-full h-auto rounded-lg" }) })), jsxRuntimeExports.jsxs("div", { className: "member-card-content", children: [jsxRuntimeExports.jsx("h3", { className: "member-card-name", children: fullName }), meta.member_role && jsxRuntimeExports.jsx("p", { className: "member-card-role", children: meta.member_role }), meta.business_name && jsxRuntimeExports.jsx("p", { className: "member-card-company", children: meta.business_name }), meta.tagline && jsxRuntimeExports.jsx("p", { className: "member-card-tagline", children: meta.tagline }), meta.member_bio && (jsxRuntimeExports.jsx("div", { className: "member-card-bio", dangerouslySetInnerHTML: { __html: meta.member_bio } })), meta.website && (jsxRuntimeExports.jsx("a", { href: meta.website, target: "_blank", rel: "noopener noreferrer", className: "member-card-website", children: "Visit Website" }))] })] }));
|
|
1706
1741
|
};
|
|
1707
1742
|
|
|
1743
|
+
/**
|
|
1744
|
+
* Cloudflare Images variant URL helper for member card images.
|
|
1745
|
+
* Only Cloudflare URLs (imagedelivery.net) are supported; WordPress URLs are not used.
|
|
1746
|
+
*/
|
|
1747
|
+
function isCloudflareImageUrl(url) {
|
|
1748
|
+
if (!url)
|
|
1749
|
+
return false;
|
|
1750
|
+
try {
|
|
1751
|
+
const u = new URL(url);
|
|
1752
|
+
return u.hostname.toLowerCase().includes('imagedelivery.net');
|
|
1753
|
+
}
|
|
1754
|
+
catch {
|
|
1755
|
+
return false;
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
/**
|
|
1759
|
+
* Append Cloudflare Images variant (e.g. w=720,h=1280 for 9:16) to the base URL.
|
|
1760
|
+
* Returns the original url if it is not a Cloudflare URL.
|
|
1761
|
+
*/
|
|
1762
|
+
function getCloudflareVariantUrl(url, options) {
|
|
1763
|
+
if (!isCloudflareImageUrl(url))
|
|
1764
|
+
return url;
|
|
1765
|
+
if (/\/w=\d+/.test(url) || /\/(public|thumbnail|banner|avatar)/.test(url)) {
|
|
1766
|
+
return url;
|
|
1767
|
+
}
|
|
1768
|
+
const { width, height } = options;
|
|
1769
|
+
const base = url.endsWith('/') ? url.slice(0, -1) : url;
|
|
1770
|
+
const variant = `w=${Math.max(1, Math.floor(width))}` + (`,h=${Math.max(1, Math.floor(height))}` );
|
|
1771
|
+
return `${base}/${variant}`;
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1708
1774
|
/**
|
|
1709
1775
|
* MemberCardsGrid component - displays multiple members in a grid
|
|
1710
1776
|
* Usage: [member_cards tax="leadership" cols="3" image="true"]
|
|
@@ -1737,12 +1803,16 @@ const MemberCardsGrid = ({ tax, category, role, cols = '3', image = 'true', limi
|
|
|
1737
1803
|
}[colsNum] || 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3';
|
|
1738
1804
|
return (jsxRuntimeExports.jsx("div", { className: `member-cards-grid grid ${gridCols} gap-6 ${className}`, children: members.map((member) => {
|
|
1739
1805
|
const meta = member.member_meta || {};
|
|
1740
|
-
const
|
|
1806
|
+
const rawImageUrl = showImage
|
|
1741
1807
|
? (member.featured_image_urls?.medium?.url || member.featured_image_urls?.full?.url)
|
|
1742
1808
|
: null;
|
|
1809
|
+
// Only use Cloudflare URLs; request 9:16 at 720x1280 for sharp display
|
|
1810
|
+
const imageUrl = rawImageUrl && isCloudflareImageUrl(rawImageUrl)
|
|
1811
|
+
? getCloudflareVariantUrl(rawImageUrl, { width: 720, height: 1280 })
|
|
1812
|
+
: null;
|
|
1743
1813
|
const fullName = [meta.members_firstname, meta.members_last_name].filter(Boolean).join(' ')
|
|
1744
1814
|
|| member.title.rendered;
|
|
1745
|
-
return (jsxRuntimeExports.jsxs("div", { className: "member-card bg-white rounded-lg shadow-md overflow-hidden", children: [imageUrl && (jsxRuntimeExports.jsx("div", { className: "member-card-image", children: jsxRuntimeExports.jsx("img", { src: imageUrl, alt: fullName, className: "
|
|
1815
|
+
return (jsxRuntimeExports.jsxs("div", { className: "member-card bg-white rounded-lg shadow-md overflow-hidden", children: [imageUrl && (jsxRuntimeExports.jsx("div", { className: "member-card-image aspect-[9/16] w-full overflow-hidden bg-slate-100", children: jsxRuntimeExports.jsx("img", { src: imageUrl, alt: fullName, className: "h-full w-full object-cover" }) })), jsxRuntimeExports.jsxs("div", { className: "member-card-content p-6", children: [jsxRuntimeExports.jsx("h3", { className: "member-card-name text-xl font-bold mb-2", children: fullName }), meta.member_role && (jsxRuntimeExports.jsx("p", { className: "member-card-role text-gray-600 mb-2", children: meta.member_role })), meta.business_name && (jsxRuntimeExports.jsx("p", { className: "member-card-company text-sm text-gray-500 mb-2", children: meta.business_name })), meta.tagline && (jsxRuntimeExports.jsx("p", { className: "member-card-tagline text-sm italic mb-3", children: meta.tagline })), meta.member_pitch && (jsxRuntimeExports.jsx("p", { className: "member-card-pitch text-sm mb-3 line-clamp-3", children: meta.member_pitch })), meta.website && (jsxRuntimeExports.jsx("a", { href: meta.website, target: "_blank", rel: "noopener noreferrer", className: "member-card-website text-blue-600 hover:underline text-sm", children: "Visit Website \u2192" }))] })] }, member.id));
|
|
1746
1816
|
}) }));
|
|
1747
1817
|
};
|
|
1748
1818
|
|
|
@@ -1878,5 +1948,5 @@ const TestimonialSlideshow = ({ tax, category, forPostId, limit = '5', interval
|
|
|
1878
1948
|
return (jsxRuntimeExports.jsxs("div", { className: `testimonial-slideshow relative ${className}`, children: [jsxRuntimeExports.jsxs("div", { className: "testimonial-slideshow-slide bg-white rounded-lg shadow-md p-8", children: [showContent === 'true' && (jsxRuntimeExports.jsx("div", { className: "testimonial-slideshow-content text-xl mb-6 italic", dangerouslySetInnerHTML: { __html: currentTestimonial.content.rendered } })), jsxRuntimeExports.jsxs("div", { className: "testimonial-slideshow-author", children: [showName === 'true' && (jsxRuntimeExports.jsx("p", { className: "testimonial-slideshow-name text-lg font-bold", children: meta.submitter_name || 'Anonymous' })), showRole === 'true' && meta.submitter_role && (jsxRuntimeExports.jsx("p", { className: "testimonial-slideshow-role text-sm text-gray-600", children: meta.submitter_role })), showBusinessName === 'true' && meta.submitter_business_name && (jsxRuntimeExports.jsx("p", { className: "testimonial-slideshow-business text-sm text-gray-500", children: meta.submitter_business_name })), showCompanyUrl === 'true' && meta.submitter_company && (jsxRuntimeExports.jsx("a", { href: meta.submitter_company, target: "_blank", rel: "noopener noreferrer", className: "testimonial-slideshow-company text-sm text-blue-600 hover:underline", children: meta.submitter_company }))] }), showKudos === 'true' && meta.kudos && meta.kudos.length > 0 && (jsxRuntimeExports.jsx("div", { className: "testimonial-slideshow-kudos mt-4 flex gap-2 justify-center", children: meta.kudos.map((kudo, index) => (jsxRuntimeExports.jsx("span", { className: "text-2xl", title: kudo, children: kudo }, index))) }))] }), testimonials.length > 1 && (jsxRuntimeExports.jsx("div", { className: "testimonial-slideshow-dots flex justify-center gap-2 mt-6", children: testimonials.map((_, index) => (jsxRuntimeExports.jsx("button", { onClick: () => setCurrentIndex(index), className: `w-3 h-3 rounded-full transition-colors ${index === currentIndex ? 'bg-blue-600' : 'bg-gray-300'}`, "aria-label": `Go to slide ${index + 1}` }, index))) }))] }));
|
|
1879
1949
|
};
|
|
1880
1950
|
|
|
1881
|
-
export { MemberCard, MemberCardsGrid, MemberSlideshow, TestimonialCard, TestimonialCardsGrid, TestimonialSlideshow, setWordPressApiUrl, useMember, useMembers, useTestimonial, useTestimonials };
|
|
1951
|
+
export { MemberCard, MemberCardsGrid, MemberSlideshow, TestimonialCard, TestimonialCardsGrid, TestimonialSlideshow, setStaticDataProvider, setWordPressApiUrl, useMember, useMembers, useTestimonial, useTestimonials };
|
|
1882
1952
|
//# sourceMappingURL=index.esm.js.map
|