@levo-so/blocks 0.1.98 → 0.1.100
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 +5 -5
- package/src/blocks/blogs/blog-listing-1.tsx +4 -4
- package/src/blocks/blogs/blog-listing-2.tsx +4 -4
- package/src/blocks/blogs/blog-listing-3.tsx +4 -4
- package/src/blocks/community/community-1.tsx +15 -15
- package/src/blocks/community/community-post-1.tsx +15 -15
- package/src/blocks/content/content-10.schema.ts +1 -1
- package/src/blocks/content/content-10.tsx +2 -2
- package/src/blocks/embed/embed-2.schema.ts +36 -0
- package/src/blocks/embed/embed-2.tsx +10 -0
- package/src/blocks/event/event-details.tsx +2 -2
- package/src/blocks/event/event-listing-2.tsx +4 -4
- package/src/blocks/event/event-listing-3.tsx +4 -4
- package/src/blocks/event/event-listing-4.tsx +4 -4
- package/src/blocks/event/event-listing.tsx +4 -4
- package/src/blocks/index.ts +2 -0
- package/src/blocks/jobs/jobs-1.schema.ts +1 -1
- package/src/blocks/jobs/jobs-1.tsx +2 -1
- package/src/blocks/polling/polling-1.tsx +5 -5
- package/src/blocks/profile/profile-4.schema.ts +1 -1
- package/src/blocks/profile/profile-4.tsx +2 -2
- package/src/blocks/profile/profile-5.schema.ts +1 -1
- package/src/blocks/profile/profile-5.tsx +2 -1
- package/src/blocks/services/service-2.tsx +2 -2
- package/src/blocks/services/service-3.tsx +2 -2
- package/src/blocks/termsAndPrivacy/terms-and-conditions-1.schema.ts +1 -1
- package/src/blocks/termsAndPrivacy/terms-and-conditions-1.tsx +2 -1
- package/src/schemas/blocks.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@levo-so/blocks",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.100",
|
|
4
4
|
"author": "Levo Engineering <devs@theinternetfolks.com>",
|
|
5
5
|
"description": "Set of blocks for Levo studio",
|
|
6
6
|
"type": "module",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"react": ">=18",
|
|
17
17
|
"react-dom": ">=18",
|
|
18
18
|
"@levo-so/react": "0.1.86",
|
|
19
|
-
"@levo-so/studio": "0.1.
|
|
19
|
+
"@levo-so/studio": "0.1.100",
|
|
20
20
|
"@levo-so/core": "0.1.82"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"@types/react": "19.2.14",
|
|
30
30
|
"@types/react-dom": "19.2.3",
|
|
31
31
|
"typescript": "5.9.3",
|
|
32
|
+
"@levo/ts-config": "0.0.0",
|
|
32
33
|
"@levo-so/react": "0.1.86",
|
|
33
|
-
"@levo-so/studio": "0.1.
|
|
34
|
-
"@levo-so/core": "0.1.82"
|
|
35
|
-
"@levo/ts-config": "0.0.0"
|
|
34
|
+
"@levo-so/studio": "0.1.100",
|
|
35
|
+
"@levo-so/core": "0.1.82"
|
|
36
36
|
},
|
|
37
37
|
"main": "./src/index.ts",
|
|
38
38
|
"exports": {
|
|
@@ -31,7 +31,7 @@ interface IBlogMeta {
|
|
|
31
31
|
|
|
32
32
|
const BlogListing1: React.FC<ILevoBlockBaseProps<IBlogListing1Content>> = ({ content }) => {
|
|
33
33
|
const { response, query, setQuery } = useContextEngine<IPost, IBlogMeta>("blogs");
|
|
34
|
-
const {
|
|
34
|
+
const { isStudio, blockData } = useBlockContext();
|
|
35
35
|
|
|
36
36
|
const handleNext = () => setQuery({ page: (query?.page || 0) + 1 });
|
|
37
37
|
const handlePrevious = () => setQuery({ page: (query?.page || 0) - 1 });
|
|
@@ -67,14 +67,14 @@ const BlogListing1: React.FC<ILevoBlockBaseProps<IBlogListing1Content>> = ({ con
|
|
|
67
67
|
key={index}
|
|
68
68
|
elementKey={`blogs.${index}.blog`}
|
|
69
69
|
config={
|
|
70
|
-
(
|
|
70
|
+
(isStudio && studioConfig?.preview_url) || (!isStudio && studioConfig?.live_url)
|
|
71
71
|
? {
|
|
72
72
|
action: {
|
|
73
73
|
type: "external_link",
|
|
74
74
|
value:
|
|
75
|
-
|
|
75
|
+
isStudio && studioConfig.preview_url
|
|
76
76
|
? studioConfig.preview_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
77
|
-
: !
|
|
77
|
+
: !isStudio && studioConfig.live_url
|
|
78
78
|
? studioConfig.live_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
79
79
|
: "",
|
|
80
80
|
options: {},
|
|
@@ -31,7 +31,7 @@ interface IBlogMeta {
|
|
|
31
31
|
|
|
32
32
|
const BlogListing2: React.FC<ILevoBlockBaseProps<IBlogListing2Content>> = ({ content }) => {
|
|
33
33
|
const { response, query, setQuery } = useContextEngine<IPost, IBlogMeta>("blogs");
|
|
34
|
-
const {
|
|
34
|
+
const { isStudio, blockData } = useBlockContext();
|
|
35
35
|
|
|
36
36
|
const handleNext = () => setQuery({ page: (query?.page || 0) + 1 });
|
|
37
37
|
const handlePrevious = () => setQuery({ page: (query?.page || 0) - 1 });
|
|
@@ -67,14 +67,14 @@ const BlogListing2: React.FC<ILevoBlockBaseProps<IBlogListing2Content>> = ({ con
|
|
|
67
67
|
data-levo_group_item
|
|
68
68
|
elementKey={`blogs.${index}.blog`}
|
|
69
69
|
config={
|
|
70
|
-
(
|
|
70
|
+
(isStudio && studioConfig?.preview_url) || (!isStudio && studioConfig?.live_url)
|
|
71
71
|
? {
|
|
72
72
|
action: {
|
|
73
73
|
type: "external_link",
|
|
74
74
|
value:
|
|
75
|
-
|
|
75
|
+
isStudio && studioConfig.preview_url
|
|
76
76
|
? studioConfig.preview_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
77
|
-
: !
|
|
77
|
+
: !isStudio && studioConfig.live_url
|
|
78
78
|
? studioConfig.live_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
79
79
|
: "",
|
|
80
80
|
options: {},
|
|
@@ -31,7 +31,7 @@ interface IBlogMeta {
|
|
|
31
31
|
|
|
32
32
|
const BlogListing3: React.FC<ILevoBlockBaseProps<IBlogListing3Content>> = ({ content, config }) => {
|
|
33
33
|
const { response, query, setQuery } = useContextEngine<IPost, IBlogMeta>("blogs");
|
|
34
|
-
const {
|
|
34
|
+
const { isStudio, blockData } = useBlockContext();
|
|
35
35
|
|
|
36
36
|
const handleNext = () => setQuery({ page: (query?.page || 0) + 1 });
|
|
37
37
|
const handlePrevious = () => setQuery({ page: (query?.page || 0) - 1 });
|
|
@@ -63,14 +63,14 @@ const BlogListing3: React.FC<ILevoBlockBaseProps<IBlogListing3Content>> = ({ con
|
|
|
63
63
|
data-levo_group_item
|
|
64
64
|
elementKey={`blogs.${index}.blog`}
|
|
65
65
|
config={
|
|
66
|
-
(
|
|
66
|
+
(isStudio && studioConfig?.preview_url) || (!isStudio && studioConfig?.live_url)
|
|
67
67
|
? {
|
|
68
68
|
action: {
|
|
69
69
|
type: "external_link",
|
|
70
70
|
value:
|
|
71
|
-
|
|
71
|
+
isStudio && studioConfig.preview_url
|
|
72
72
|
? studioConfig.preview_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
73
|
-
: !
|
|
73
|
+
: !isStudio && studioConfig.live_url
|
|
74
74
|
? studioConfig.live_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
75
75
|
: "",
|
|
76
76
|
options: {},
|
|
@@ -103,7 +103,7 @@ const Community1: React.FC<ILevoBlockBaseProps<ICommunity1Content>> = ({ content
|
|
|
103
103
|
// Join request state
|
|
104
104
|
const [joinRequest, setJoinRequest] = useState<IForumJoinRequest | null>(null);
|
|
105
105
|
|
|
106
|
-
const { parsedBlockData,
|
|
106
|
+
const { parsedBlockData, isStudio } = useBlockContext();
|
|
107
107
|
const forumKey = useMemo(() => {
|
|
108
108
|
return (
|
|
109
109
|
parsedBlockData?.source?.find((s) => s.module === "community")?.identifier ||
|
|
@@ -129,7 +129,7 @@ const Community1: React.FC<ILevoBlockBaseProps<ICommunity1Content>> = ({ content
|
|
|
129
129
|
.json<IResponseSingle<IForum>>();
|
|
130
130
|
|
|
131
131
|
if (response?.content?.data) {
|
|
132
|
-
if (
|
|
132
|
+
if (isStudio) {
|
|
133
133
|
setForumData({
|
|
134
134
|
...response.content.data,
|
|
135
135
|
settings: {
|
|
@@ -147,7 +147,7 @@ const Community1: React.FC<ILevoBlockBaseProps<ICommunity1Content>> = ({ content
|
|
|
147
147
|
levoClient?.logger?.error("Error fetching single forum data:", error);
|
|
148
148
|
return null;
|
|
149
149
|
}
|
|
150
|
-
}, [forumKey,
|
|
150
|
+
}, [forumKey, isStudio]);
|
|
151
151
|
|
|
152
152
|
const checkMembership = useCallback(async () => {
|
|
153
153
|
if (!forumData?.settings?.invite_only || !isLoggedIn) {
|
|
@@ -158,7 +158,7 @@ const Community1: React.FC<ILevoBlockBaseProps<ICommunity1Content>> = ({ content
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
// In builder mode, bypass API call and use sample data
|
|
161
|
-
if (
|
|
161
|
+
if (isStudio) {
|
|
162
162
|
const data = SAMPLE_GET_MEMBER_RESPONSE.content.data;
|
|
163
163
|
setIsMember(!!data?.member);
|
|
164
164
|
setJoinRequest(data?.join_request || null);
|
|
@@ -186,7 +186,7 @@ const Community1: React.FC<ILevoBlockBaseProps<ICommunity1Content>> = ({ content
|
|
|
186
186
|
setIsLoadingMembership(false);
|
|
187
187
|
hasFetchedMembershipRef.current = true;
|
|
188
188
|
}
|
|
189
|
-
}, [forumKey, forumData?.settings?.invite_only, isLoggedIn,
|
|
189
|
+
}, [forumKey, forumData?.settings?.invite_only, isLoggedIn, isStudio, levoClient]);
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
192
|
* Submit a join request for the current user
|
|
@@ -368,29 +368,29 @@ const Community1: React.FC<ILevoBlockBaseProps<ICommunity1Content>> = ({ content
|
|
|
368
368
|
|
|
369
369
|
const postDetailPageURLPattern = useMemo(() => {
|
|
370
370
|
if (
|
|
371
|
-
(
|
|
372
|
-
(!
|
|
371
|
+
(isStudio && detailPageStudioConfig?.preview_url) ||
|
|
372
|
+
(!isStudio && detailPageStudioConfig?.live_url)
|
|
373
373
|
) {
|
|
374
|
-
return
|
|
374
|
+
return isStudio && detailPageStudioConfig.preview_url
|
|
375
375
|
? detailPageStudioConfig.preview_url
|
|
376
|
-
: !
|
|
376
|
+
: !isStudio && detailPageStudioConfig.live_url
|
|
377
377
|
? detailPageStudioConfig.live_url
|
|
378
378
|
: "";
|
|
379
379
|
}
|
|
380
|
-
}, [
|
|
380
|
+
}, [isStudio, detailPageStudioConfig]);
|
|
381
381
|
|
|
382
382
|
const postListingPageURL = useMemo(() => {
|
|
383
383
|
if (
|
|
384
|
-
(
|
|
385
|
-
(!
|
|
384
|
+
(isStudio && listingPageStudioConfig?.preview_url) ||
|
|
385
|
+
(!isStudio && listingPageStudioConfig?.live_url)
|
|
386
386
|
) {
|
|
387
|
-
return
|
|
387
|
+
return isStudio && listingPageStudioConfig.preview_url
|
|
388
388
|
? listingPageStudioConfig.preview_url
|
|
389
|
-
: !
|
|
389
|
+
: !isStudio && listingPageStudioConfig.live_url
|
|
390
390
|
? listingPageStudioConfig.live_url
|
|
391
391
|
: "";
|
|
392
392
|
}
|
|
393
|
-
}, [
|
|
393
|
+
}, [isStudio, listingPageStudioConfig]);
|
|
394
394
|
|
|
395
395
|
const isInviteOnly = forumData?.settings?.invite_only ?? false;
|
|
396
396
|
const allowJoinRequests = forumData?.settings?.allow_join_requests ?? false;
|
|
@@ -91,7 +91,7 @@ const PostDetailSkeleton: React.FC = () => (
|
|
|
91
91
|
const CommunityPost1: React.FC<ILevoBlockBaseProps<ICommunityPost1Content>> = ({ content }) => {
|
|
92
92
|
const { fetch, logger } = useLevo();
|
|
93
93
|
const { isLoggedIn } = useAuth();
|
|
94
|
-
const {
|
|
94
|
+
const { isStudio } = useBlockContext();
|
|
95
95
|
const pagePost = usePageContext("community");
|
|
96
96
|
|
|
97
97
|
const postSource = pagePost && Object.keys(pagePost).length > 0 ? pagePost : content?.post;
|
|
@@ -123,7 +123,7 @@ const CommunityPost1: React.FC<ILevoBlockBaseProps<ICommunityPost1Content>> = ({
|
|
|
123
123
|
.json<IResponseSingle<IForum>>();
|
|
124
124
|
|
|
125
125
|
if (response?.content?.data) {
|
|
126
|
-
if (
|
|
126
|
+
if (isStudio) {
|
|
127
127
|
setForumData({
|
|
128
128
|
...response.content.data,
|
|
129
129
|
settings: {
|
|
@@ -142,7 +142,7 @@ const CommunityPost1: React.FC<ILevoBlockBaseProps<ICommunityPost1Content>> = ({
|
|
|
142
142
|
logger?.error("Failed to fetch forum data", levoError);
|
|
143
143
|
failedForumAttemptsRef.current += 1;
|
|
144
144
|
}
|
|
145
|
-
}, [forumKey, fetch, logger,
|
|
145
|
+
}, [forumKey, fetch, logger, isStudio]);
|
|
146
146
|
|
|
147
147
|
const checkMembership = useCallback(async () => {
|
|
148
148
|
if (!forumData?.settings?.invite_only || !isLoggedIn) {
|
|
@@ -153,7 +153,7 @@ const CommunityPost1: React.FC<ILevoBlockBaseProps<ICommunityPost1Content>> = ({
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
// In builder mode, bypass API call and use sample data
|
|
156
|
-
if (
|
|
156
|
+
if (isStudio) {
|
|
157
157
|
const data = SAMPLE_GET_MEMBER_RESPONSE.content.data;
|
|
158
158
|
setIsMember(!!data?.member);
|
|
159
159
|
setJoinRequest(data?.join_request || null);
|
|
@@ -186,7 +186,7 @@ const CommunityPost1: React.FC<ILevoBlockBaseProps<ICommunityPost1Content>> = ({
|
|
|
186
186
|
} finally {
|
|
187
187
|
setIsLoadingMembership(false);
|
|
188
188
|
}
|
|
189
|
-
}, [forumKey, forumData?.settings?.invite_only, isLoggedIn,
|
|
189
|
+
}, [forumKey, forumData?.settings?.invite_only, isLoggedIn, isStudio, fetch, logger]);
|
|
190
190
|
|
|
191
191
|
/** Submit a join request for the current user */
|
|
192
192
|
const handleSubmitJoinRequest = useCallback(
|
|
@@ -239,29 +239,29 @@ const CommunityPost1: React.FC<ILevoBlockBaseProps<ICommunityPost1Content>> = ({
|
|
|
239
239
|
|
|
240
240
|
const postDetailPageURLPattern = useMemo(() => {
|
|
241
241
|
if (
|
|
242
|
-
(
|
|
243
|
-
(!
|
|
242
|
+
(isStudio && detailPageStudioConfig?.preview_url) ||
|
|
243
|
+
(!isStudio && detailPageStudioConfig?.live_url)
|
|
244
244
|
) {
|
|
245
|
-
return
|
|
245
|
+
return isStudio && detailPageStudioConfig.preview_url
|
|
246
246
|
? detailPageStudioConfig.preview_url
|
|
247
|
-
: !
|
|
247
|
+
: !isStudio && detailPageStudioConfig.live_url
|
|
248
248
|
? detailPageStudioConfig.live_url
|
|
249
249
|
: "";
|
|
250
250
|
}
|
|
251
|
-
}, [
|
|
251
|
+
}, [isStudio, detailPageStudioConfig]);
|
|
252
252
|
|
|
253
253
|
const postListingPageURL = useMemo(() => {
|
|
254
254
|
if (
|
|
255
|
-
(
|
|
256
|
-
(!
|
|
255
|
+
(isStudio && listingPageStudioConfig?.preview_url) ||
|
|
256
|
+
(!isStudio && listingPageStudioConfig?.live_url)
|
|
257
257
|
) {
|
|
258
|
-
return
|
|
258
|
+
return isStudio && listingPageStudioConfig.preview_url
|
|
259
259
|
? listingPageStudioConfig.preview_url
|
|
260
|
-
: !
|
|
260
|
+
: !isStudio && listingPageStudioConfig.live_url
|
|
261
261
|
? listingPageStudioConfig.live_url
|
|
262
262
|
: "";
|
|
263
263
|
}
|
|
264
|
-
}, [
|
|
264
|
+
}, [isStudio, listingPageStudioConfig]);
|
|
265
265
|
|
|
266
266
|
// Reset fetch state when the post changes
|
|
267
267
|
const postCommentsCount = (postSource as unknown as IForumPost)?.comments_count ?? 0;
|
|
@@ -245,7 +245,7 @@ export const Content10: IBlock = {
|
|
|
245
245
|
{
|
|
246
246
|
key: "content",
|
|
247
247
|
label: "Content",
|
|
248
|
-
field_interface: "
|
|
248
|
+
field_interface: "BlogContentWidget",
|
|
249
249
|
hint: {
|
|
250
250
|
prompt_description:
|
|
251
251
|
"Full blog article body. Use formal, professional tone suitable for financial topics. Include headings, paragraphs, and clear explanations. Length should be 800–2000 words for a comprehensive post.",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ILevoBlockBaseProps } from "@levo-so/studio";
|
|
2
|
-
import { Box, Container, Heading, Icon, Media, Section, Typography } from "@levo-so/studio";
|
|
2
|
+
import { BlogContent, Box, Container, Heading, Icon, Media, Section, Typography } from "@levo-so/studio";
|
|
3
3
|
import type React from "react";
|
|
4
4
|
|
|
5
5
|
import type { IContent10Content } from "./content-10.schema";
|
|
@@ -32,7 +32,7 @@ const Content10: React.FC<ILevoBlockBaseProps<IContent10Content>> = ({ content }
|
|
|
32
32
|
</Box>
|
|
33
33
|
<Box elementKey="content-wrapper">
|
|
34
34
|
<Box elementKey="content-section">
|
|
35
|
-
<
|
|
35
|
+
<BlogContent elementKey="content" />
|
|
36
36
|
</Box>
|
|
37
37
|
</Box>
|
|
38
38
|
</Container>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { IBlock } from "@levo-so/studio";
|
|
2
|
+
|
|
3
|
+
const DEFAULT_CONTENT = {
|
|
4
|
+
html: '<div style="padding:40px;text-align:center;background:#f3f4f6;border-radius:12px;font-family:system-ui,sans-serif;">\n <h2 style="margin:0 0 8px;font-size:24px;">Custom HTML</h2>\n <p style="margin:0;color:#6b7280;">Paste any HTML here — it renders as-is.</p>\n</div>',
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type IEmbed2Content = typeof DEFAULT_CONTENT;
|
|
8
|
+
|
|
9
|
+
export const Embed2: IBlock = {
|
|
10
|
+
category_id: "embed",
|
|
11
|
+
title: "Custom HTML",
|
|
12
|
+
key: "embed-2",
|
|
13
|
+
version: "v1",
|
|
14
|
+
prompt_description:
|
|
15
|
+
"A transparent block for embedding custom HTML. The wrapper is invisible to layout so the pasted HTML renders as if no wrapper exists.",
|
|
16
|
+
content_schema: [
|
|
17
|
+
{
|
|
18
|
+
key: "html",
|
|
19
|
+
label: "HTML",
|
|
20
|
+
field_interface: "IframeWidget",
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
layouts: [
|
|
24
|
+
{
|
|
25
|
+
key: "default",
|
|
26
|
+
title: "Default",
|
|
27
|
+
styles: {
|
|
28
|
+
html: {
|
|
29
|
+
display: "contents",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
content: DEFAULT_CONTENT,
|
|
33
|
+
config: {},
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ILevoBlockBaseProps } from "@levo-so/studio";
|
|
2
|
+
import { Iframe } from "@levo-so/studio";
|
|
3
|
+
|
|
4
|
+
import type { IEmbed2Content } from "./embed-2.schema";
|
|
5
|
+
|
|
6
|
+
const Embed2: React.FC<ILevoBlockBaseProps<IEmbed2Content>> = () => (
|
|
7
|
+
<Iframe elementKey="html" />
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
export default Embed2;
|
|
@@ -62,9 +62,9 @@ const EventDetails: React.FC<ILevoBlockBaseProps<IEventDetailsContent>> = () =>
|
|
|
62
62
|
|
|
63
63
|
<Box elementKey="content-section">
|
|
64
64
|
<Box elementKey="main-content">
|
|
65
|
-
{data?.
|
|
65
|
+
{data?._id ? (
|
|
66
66
|
<RegisterModal
|
|
67
|
-
eventID={data?.
|
|
67
|
+
eventID={data?._id as string}
|
|
68
68
|
title={data?.title}
|
|
69
69
|
external={data?.external_ticketing}
|
|
70
70
|
/>
|
|
@@ -28,7 +28,7 @@ interface IEventMeta {
|
|
|
28
28
|
|
|
29
29
|
const EventListing2: React.FC<ILevoBlockBaseProps<IEventListing2Content>> = ({ content }) => {
|
|
30
30
|
const { response, query, setQuery } = useContextEngine<LevoEvent.Root, IEventMeta>("events");
|
|
31
|
-
const {
|
|
31
|
+
const { isStudio } = useBlockContext();
|
|
32
32
|
|
|
33
33
|
const handleNext = () => setQuery({ page: (query?.page || 0) + 1 });
|
|
34
34
|
const handlePrevious = () => setQuery({ page: (query?.page || 0) - 1 });
|
|
@@ -59,14 +59,14 @@ const EventListing2: React.FC<ILevoBlockBaseProps<IEventListing2Content>> = ({ c
|
|
|
59
59
|
data-levo_group_item
|
|
60
60
|
elementKey={`events.${index}.eventWrapper`}
|
|
61
61
|
config={
|
|
62
|
-
(
|
|
62
|
+
(isStudio && studioConfig?.preview_url) || (!isStudio && studioConfig?.live_url)
|
|
63
63
|
? {
|
|
64
64
|
action: {
|
|
65
65
|
type: "external_link",
|
|
66
66
|
value:
|
|
67
|
-
|
|
67
|
+
isStudio && studioConfig.preview_url
|
|
68
68
|
? studioConfig.preview_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
69
|
-
: !
|
|
69
|
+
: !isStudio && studioConfig.live_url
|
|
70
70
|
? studioConfig.live_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
71
71
|
: "",
|
|
72
72
|
options: {},
|
|
@@ -28,7 +28,7 @@ interface IEventMeta {
|
|
|
28
28
|
|
|
29
29
|
const EventListing3: React.FC<ILevoBlockBaseProps<IEventListing3>> = ({ content }) => {
|
|
30
30
|
const { response, query, setQuery } = useContextEngine<LevoEvent.Root, IEventMeta>("events");
|
|
31
|
-
const {
|
|
31
|
+
const { isStudio } = useBlockContext();
|
|
32
32
|
|
|
33
33
|
const handleNext = () => setQuery({ page: (query?.page || 0) + 1 });
|
|
34
34
|
const handlePrevious = () => setQuery({ page: (query?.page || 0) - 1 });
|
|
@@ -59,14 +59,14 @@ const EventListing3: React.FC<ILevoBlockBaseProps<IEventListing3>> = ({ content
|
|
|
59
59
|
data-levo_group_item
|
|
60
60
|
elementKey={`events.${index}.eventWrapper`}
|
|
61
61
|
config={
|
|
62
|
-
(
|
|
62
|
+
(isStudio && studioConfig?.preview_url) || (!isStudio && studioConfig?.live_url)
|
|
63
63
|
? {
|
|
64
64
|
action: {
|
|
65
65
|
type: "external_link",
|
|
66
66
|
value:
|
|
67
|
-
|
|
67
|
+
isStudio && studioConfig.preview_url
|
|
68
68
|
? studioConfig.preview_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
69
|
-
: !
|
|
69
|
+
: !isStudio && studioConfig.live_url
|
|
70
70
|
? studioConfig.live_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
71
71
|
: "",
|
|
72
72
|
options: {},
|
|
@@ -28,7 +28,7 @@ interface IEventMeta {
|
|
|
28
28
|
|
|
29
29
|
const EventListing4: React.FC<ILevoBlockBaseProps<IEventListing4>> = ({ content }) => {
|
|
30
30
|
const { response, query, setQuery } = useContextEngine<LevoEvent.Root, IEventMeta>("events");
|
|
31
|
-
const {
|
|
31
|
+
const { isStudio } = useBlockContext();
|
|
32
32
|
|
|
33
33
|
const handleNext = () => setQuery({ page: (query?.page || 0) + 1 });
|
|
34
34
|
const handlePrevious = () => setQuery({ page: (query?.page || 0) - 1 });
|
|
@@ -58,14 +58,14 @@ const EventListing4: React.FC<ILevoBlockBaseProps<IEventListing4>> = ({ content
|
|
|
58
58
|
data-levo_group_item
|
|
59
59
|
elementKey={`events.${index}.eventWrapper`}
|
|
60
60
|
config={
|
|
61
|
-
(
|
|
61
|
+
(isStudio && studioConfig?.preview_url) || (!isStudio && studioConfig?.live_url)
|
|
62
62
|
? {
|
|
63
63
|
action: {
|
|
64
64
|
type: "external_link",
|
|
65
65
|
value:
|
|
66
|
-
|
|
66
|
+
isStudio && studioConfig.preview_url
|
|
67
67
|
? studioConfig.preview_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
68
|
-
: !
|
|
68
|
+
: !isStudio && studioConfig.live_url
|
|
69
69
|
? studioConfig.live_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
70
70
|
: "",
|
|
71
71
|
options: {},
|
|
@@ -28,7 +28,7 @@ interface IEventMeta {
|
|
|
28
28
|
|
|
29
29
|
const EventListing: React.FC<ILevoBlockBaseProps<IEventListing>> = ({ content }) => {
|
|
30
30
|
const { response, query, setQuery } = useContextEngine<LevoEvent.Root, IEventMeta>("events");
|
|
31
|
-
const {
|
|
31
|
+
const { isStudio } = useBlockContext();
|
|
32
32
|
|
|
33
33
|
const handleNext = () => setQuery({ page: (query?.page || 0) + 1 });
|
|
34
34
|
const handlePrevious = () => setQuery({ page: (query?.page || 0) - 1 });
|
|
@@ -58,14 +58,14 @@ const EventListing: React.FC<ILevoBlockBaseProps<IEventListing>> = ({ content })
|
|
|
58
58
|
data-levo_group_item
|
|
59
59
|
elementKey={`events.${index}.eventWrapper`}
|
|
60
60
|
config={
|
|
61
|
-
(
|
|
61
|
+
(isStudio && studioConfig?.preview_url) || (!isStudio && studioConfig?.live_url)
|
|
62
62
|
? {
|
|
63
63
|
action: {
|
|
64
64
|
type: "external_link",
|
|
65
65
|
value:
|
|
66
|
-
|
|
66
|
+
isStudio && studioConfig.preview_url
|
|
67
67
|
? studioConfig.preview_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
68
|
-
: !
|
|
68
|
+
: !isStudio && studioConfig.live_url
|
|
69
69
|
? studioConfig.live_url.replace(/\{[^}]+\}/g, item?.slug)
|
|
70
70
|
: "",
|
|
71
71
|
options: {},
|
package/src/blocks/index.ts
CHANGED
|
@@ -48,6 +48,7 @@ const Cta1 = lazy(() => import("./cta/cta-1"));
|
|
|
48
48
|
const Cta2 = lazy(() => import("./cta/cta-2"));
|
|
49
49
|
const Cta3 = lazy(() => import("./cta/cta-3"));
|
|
50
50
|
const Embed1 = lazy(() => import("./embed/embed-1"));
|
|
51
|
+
const Embed2 = lazy(() => import("./embed/embed-2"));
|
|
51
52
|
const EventListing = lazy(() => import("./event/event-listing"));
|
|
52
53
|
const EventListing2 = lazy(() => import("./event/event-listing-2"));
|
|
53
54
|
const EventListing3 = lazy(() => import("./event/event-listing-3"));
|
|
@@ -175,6 +176,7 @@ export const blocks: Record<string, React.LazyExoticComponent<React.ComponentTyp
|
|
|
175
176
|
"cta-2:v1": Cta2,
|
|
176
177
|
"cta-3:v1": Cta3,
|
|
177
178
|
"embed-1:v1": Embed1,
|
|
179
|
+
"embed-2:v1": Embed2,
|
|
178
180
|
"event-listing:v1": EventListing,
|
|
179
181
|
"event-listing-2:v1": EventListing2,
|
|
180
182
|
"event-listing-3:v1": EventListing3,
|
|
@@ -572,7 +572,7 @@ export const Jobs1: IBlock = {
|
|
|
572
572
|
{
|
|
573
573
|
key: "description_content",
|
|
574
574
|
label: "Job Description",
|
|
575
|
-
field_interface: "
|
|
575
|
+
field_interface: "BlogContentWidget",
|
|
576
576
|
hint: {
|
|
577
577
|
prompt_description:
|
|
578
578
|
"Full job description including responsibilities, requirements, and benefits.",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ILevoBlockBaseProps } from "@levo-so/studio";
|
|
2
2
|
import {
|
|
3
|
+
BlogContent,
|
|
3
4
|
Box,
|
|
4
5
|
Button,
|
|
5
6
|
Container,
|
|
@@ -132,7 +133,7 @@ const Jobs1: React.FC<ILevoBlockBaseProps<IJobs1Content>> = ({ content }) => (
|
|
|
132
133
|
{/* Job Description Content */}
|
|
133
134
|
<Box elementKey="description_section">
|
|
134
135
|
<Heading elementKey="description_title" />
|
|
135
|
-
<
|
|
136
|
+
<BlogContent elementKey="description_content" />
|
|
136
137
|
</Box>
|
|
137
138
|
</Box>
|
|
138
139
|
<Form elementKey="application_form" />
|
|
@@ -158,7 +158,7 @@ const PollOption: React.FC<{
|
|
|
158
158
|
fetchPolls?: () => Promise<void>;
|
|
159
159
|
}> = ({ option, totalVotes, selectedOption, pollId, fetchPolls }) => {
|
|
160
160
|
const levoClient = useLevo();
|
|
161
|
-
const {
|
|
161
|
+
const { isStudio } = useBlockContext();
|
|
162
162
|
|
|
163
163
|
const [isUserOnOption, setIsUserOnOption] = useState(false);
|
|
164
164
|
const [isVoting, setIsVoting] = useState(false);
|
|
@@ -183,7 +183,7 @@ const PollOption: React.FC<{
|
|
|
183
183
|
}, [percentage]);
|
|
184
184
|
|
|
185
185
|
const handleOptionClick = async () => {
|
|
186
|
-
if (
|
|
186
|
+
if (isStudio || isVoting || isCurrentOptionSelected) return;
|
|
187
187
|
|
|
188
188
|
try {
|
|
189
189
|
setIsVoting(true);
|
|
@@ -368,7 +368,7 @@ const Poll: React.FC<{
|
|
|
368
368
|
|
|
369
369
|
const Polling1: React.FC<ILevoBlockBaseProps<IPolling1Content>> = ({ content }) => {
|
|
370
370
|
const levoClient = useLevo();
|
|
371
|
-
const {
|
|
371
|
+
const { isStudio } = useBlockContext();
|
|
372
372
|
|
|
373
373
|
const { account, isAuthLoaded } = useAuth();
|
|
374
374
|
|
|
@@ -395,7 +395,7 @@ const Polling1: React.FC<ILevoBlockBaseProps<IPolling1Content>> = ({ content })
|
|
|
395
395
|
}, []);
|
|
396
396
|
|
|
397
397
|
useEffect(() => {
|
|
398
|
-
if (
|
|
398
|
+
if (isStudio) return;
|
|
399
399
|
fetchPolls();
|
|
400
400
|
}, []);
|
|
401
401
|
|
|
@@ -407,7 +407,7 @@ const Polling1: React.FC<ILevoBlockBaseProps<IPolling1Content>> = ({ content })
|
|
|
407
407
|
<Typography elementKey="description" />
|
|
408
408
|
</Box>
|
|
409
409
|
<Box elementKey="polls">
|
|
410
|
-
{
|
|
410
|
+
{isStudio ? (
|
|
411
411
|
<>
|
|
412
412
|
{POLLS_RESPONSE_SAMPLE?.content?.data?.map((item: any, index: number) => {
|
|
413
413
|
return (
|
|
@@ -471,7 +471,7 @@ export const Profile4: IBlock = {
|
|
|
471
471
|
{
|
|
472
472
|
key: "content",
|
|
473
473
|
label: "Content",
|
|
474
|
-
field_interface: "
|
|
474
|
+
field_interface: "BlogContentWidget",
|
|
475
475
|
hint: {
|
|
476
476
|
prompt_description:
|
|
477
477
|
"Full profile article content. Should be comprehensive and informative.",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ILevoBlockBaseProps } from "@levo-so/studio";
|
|
2
|
-
import { Box, Button, Container, Form, Heading, Icon, Section, Typography } from "@levo-so/studio";
|
|
2
|
+
import { BlogContent, Box, Button, Container, Form, Heading, Icon, Section, Typography } from "@levo-so/studio";
|
|
3
3
|
import dayjs from "dayjs";
|
|
4
4
|
import type React from "react";
|
|
5
5
|
|
|
@@ -84,7 +84,7 @@ const Profile4: React.FC<ILevoBlockBaseProps<IProfile4Content>> = ({ content })
|
|
|
84
84
|
{/* Blog Content */}
|
|
85
85
|
<Box elementKey="content-section">
|
|
86
86
|
<Typography elementKey="content_title" />
|
|
87
|
-
<
|
|
87
|
+
<BlogContent elementKey="content" />
|
|
88
88
|
</Box>
|
|
89
89
|
</Box>
|
|
90
90
|
<Form elementKey="contact_form" />
|
|
@@ -180,7 +180,7 @@ export const Profile5: IBlock = {
|
|
|
180
180
|
{
|
|
181
181
|
key: "content_description",
|
|
182
182
|
label: "Content Description",
|
|
183
|
-
field_interface: "
|
|
183
|
+
field_interface: "BlogContentWidget",
|
|
184
184
|
hint: {
|
|
185
185
|
prompt_description:
|
|
186
186
|
"Main content paragraph providing comprehensive information about the team, services, or offerings. Should be engaging and informative.",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BlogContent,
|
|
2
3
|
Box,
|
|
3
4
|
Button,
|
|
4
5
|
Container,
|
|
@@ -45,7 +46,7 @@ const Profile5: React.FC<ILevoBlockBaseProps<IProfile5Content>> = ({ content })
|
|
|
45
46
|
</Box>
|
|
46
47
|
</Box>
|
|
47
48
|
<Box elementKey="content_container">
|
|
48
|
-
<
|
|
49
|
+
<BlogContent elementKey="content_description" />
|
|
49
50
|
</Box>
|
|
50
51
|
</Box>
|
|
51
52
|
</Box>
|
|
@@ -17,7 +17,7 @@ import type { IService2Content } from "./service-2.schema";
|
|
|
17
17
|
|
|
18
18
|
const Service2: React.FC<ILevoBlockBaseProps<IService2Content>> = ({ content, config }) => {
|
|
19
19
|
const [zipcode, setZipcode] = useState("");
|
|
20
|
-
const {
|
|
20
|
+
const { isStudio } = useBlockContext();
|
|
21
21
|
return (
|
|
22
22
|
<Section elementKey="layout">
|
|
23
23
|
<Container elementKey="container">
|
|
@@ -73,7 +73,7 @@ const Service2: React.FC<ILevoBlockBaseProps<IService2Content>> = ({ content, co
|
|
|
73
73
|
elementKey="search_button"
|
|
74
74
|
onClick={() => {
|
|
75
75
|
if (
|
|
76
|
-
!
|
|
76
|
+
!isStudio &&
|
|
77
77
|
zipcode &&
|
|
78
78
|
zipcode.length === 6 &&
|
|
79
79
|
config?.search_button?.custom_fields?.redirect_url
|
|
@@ -17,7 +17,7 @@ import type { IService3Content } from "./service-3.schema";
|
|
|
17
17
|
|
|
18
18
|
const Service3: React.FC<ILevoBlockBaseProps<IService3Content>> = ({ content, config }) => {
|
|
19
19
|
const [zipcode, setZipcode] = useState("");
|
|
20
|
-
const {
|
|
20
|
+
const { isStudio } = useBlockContext();
|
|
21
21
|
return (
|
|
22
22
|
<Section elementKey="layout">
|
|
23
23
|
<Container elementKey="container">
|
|
@@ -106,7 +106,7 @@ const Service3: React.FC<ILevoBlockBaseProps<IService3Content>> = ({ content, co
|
|
|
106
106
|
elementKey="search_button"
|
|
107
107
|
onClick={() => {
|
|
108
108
|
if (
|
|
109
|
-
!
|
|
109
|
+
!isStudio &&
|
|
110
110
|
zipcode &&
|
|
111
111
|
zipcode.length === 6 &&
|
|
112
112
|
config?.search_button?.custom_fields?.redirect_url
|
|
@@ -82,7 +82,7 @@ export const TermsAndConditions1: IBlock = {
|
|
|
82
82
|
{
|
|
83
83
|
key: "content",
|
|
84
84
|
label: "Content",
|
|
85
|
-
field_interface: "
|
|
85
|
+
field_interface: "BlogContentWidget",
|
|
86
86
|
hint: {
|
|
87
87
|
prompt_description:
|
|
88
88
|
"Main legal document content with structured sections, headings, and paragraphs. Should include comprehensive terms covering service usage, responsibilities, privacy, and legal compliance. Tone: formal, clear, legally compliant.",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BlogContent,
|
|
2
3
|
Box,
|
|
3
4
|
Container,
|
|
4
5
|
Heading,
|
|
@@ -18,7 +19,7 @@ const TermsAndConditions1: React.FC<ILevoBlockBaseProps<ITermsAndConditions1Cont
|
|
|
18
19
|
<Typography elementKey="subtitle" />
|
|
19
20
|
</Box>
|
|
20
21
|
<Box elementKey="content_wrapper">
|
|
21
|
-
<
|
|
22
|
+
<BlogContent elementKey="content" />
|
|
22
23
|
</Box>
|
|
23
24
|
</Container>
|
|
24
25
|
</Section>
|
package/src/schemas/blocks.ts
CHANGED
|
@@ -49,6 +49,7 @@ import { Cta1 } from "../blocks/cta/cta-1.schema";
|
|
|
49
49
|
import { Cta2 } from "../blocks/cta/cta-2.schema";
|
|
50
50
|
import { Cta3 } from "../blocks/cta/cta-3.schema";
|
|
51
51
|
import { Embed1 } from "../blocks/embed/embed-1.schema";
|
|
52
|
+
import { Embed2 } from "../blocks/embed/embed-2.schema";
|
|
52
53
|
import { EventDetails } from "../blocks/event/event-details.schema";
|
|
53
54
|
import { EventListing } from "../blocks/event/event-listing.schema";
|
|
54
55
|
import { EventListing2 } from "../blocks/event/event-listing-2.schema";
|
|
@@ -176,6 +177,7 @@ export const BlockList: IBlock[] = [
|
|
|
176
177
|
Cta3,
|
|
177
178
|
EditProfile,
|
|
178
179
|
Embed1,
|
|
180
|
+
Embed2,
|
|
179
181
|
EventDetails,
|
|
180
182
|
EventListing,
|
|
181
183
|
EventListing2,
|