lib-pixelbuild 0.2.1 → 0.2.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/builders/PageBuilder.js +42 -26
- package/dist/components/ButtonsComponent.d.ts +5 -0
- package/dist/components/ButtonsComponent.js +45 -0
- package/dist/components/CardComponent.js +31 -6
- package/dist/components/FormComponent.js +9 -4
- package/dist/components/{CarouselComponent.d.ts → IconComponent.d.ts} +3 -2
- package/dist/components/IconComponent.js +12 -0
- package/dist/components/ImageComponent.d.ts +5 -0
- package/dist/components/ImageComponent.js +18 -0
- package/dist/components/ListComponent.js +5 -2
- package/dist/components/LoadingComponent.js +2 -2
- package/dist/components/MapComponent.js +11 -12
- package/dist/components/SliderComponent.d.ts +0 -1
- package/dist/components/SliderComponent.js +173 -93
- package/dist/components/SocialIconsComponent.d.ts +3 -2
- package/dist/components/SocialIconsComponent.js +20 -16
- package/dist/components/TextComponent.js +5 -3
- package/dist/constants/ComponentEnum.d.ts +2 -0
- package/dist/constants/ComponentEnum.js +2 -0
- package/dist/designSystem/baseCss.d.ts +8 -0
- package/dist/designSystem/baseCss.js +406 -0
- package/dist/designSystem/buildSiteCss.d.ts +8 -0
- package/dist/designSystem/buildSiteCss.js +11 -0
- package/dist/designSystem/index.d.ts +6 -0
- package/dist/designSystem/index.js +5 -0
- package/dist/designSystem/theme.d.ts +9 -0
- package/dist/designSystem/theme.js +11 -0
- package/dist/designSystem/themeVars.d.ts +8 -0
- package/dist/designSystem/themeVars.js +9 -0
- package/dist/designSystem/tokens.d.ts +82 -0
- package/dist/designSystem/tokens.js +144 -0
- package/dist/elements/AlertElement.js +4 -4
- package/dist/elements/ButtonElement.js +21 -7
- package/dist/elements/ElementColWrapper.js +11 -2
- package/dist/elements/IconElement.js +5 -5
- package/dist/elements/IconMap.js +101 -28
- package/dist/elements/InputElement.js +10 -9
- package/dist/elements/TextElement.js +5 -1
- package/dist/factories/ButtonActionFactory.d.ts +3 -4
- package/dist/factories/ButtonActionFactory.js +2 -2
- package/dist/factories/ComponentFactory.d.ts +2 -1
- package/dist/factories/ComponentFactory.js +29 -12
- package/dist/index.d.ts +20 -5
- package/dist/index.js +15 -1
- package/dist/layouts/Footer.js +13 -2
- package/dist/layouts/Header.js +43 -16
- package/dist/layouts/SiteLayout.d.ts +8 -1
- package/dist/layouts/SiteLayout.js +36 -3
- package/dist/renderers/BlockRenderer.d.ts +8 -0
- package/dist/renderers/BlockRenderer.js +68 -0
- package/dist/services/EmailService.d.ts +14 -5
- package/dist/services/EmailService.js +21 -24
- package/dist/stores/UseFormStore.d.ts +7 -2
- package/dist/stores/UseFormStore.js +8 -3
- package/dist/types/{SectionColumnType.d.ts → BlockType.d.ts} +2 -6
- package/dist/types/ComponentType.d.ts +3 -0
- package/dist/types/ElementType.d.ts +1 -0
- package/dist/types/EmailSettingsType.d.ts +5 -0
- package/dist/types/HeaderPropertiesType.d.ts +1 -0
- package/dist/types/MailBodyType.d.ts +2 -0
- package/dist/types/PageType.d.ts +2 -2
- package/dist/types/SocialPropertiesType.d.ts +3 -11
- package/dist/types/StylesType.d.ts +12 -0
- package/dist/types/WebsitePropertiesType.d.ts +2 -0
- package/dist/types/WebsiteType.d.ts +6 -0
- package/dist/ui/PbAlert.d.ts +10 -0
- package/dist/ui/PbAlert.js +8 -0
- package/dist/ui/PbButton.d.ts +20 -0
- package/dist/ui/PbButton.js +20 -0
- package/dist/ui/PbCol.d.ts +14 -0
- package/dist/ui/PbCol.js +43 -0
- package/dist/ui/PbContainer.d.ts +7 -0
- package/dist/ui/PbContainer.js +17 -0
- package/dist/ui/PbRow.d.ts +7 -0
- package/dist/ui/PbRow.js +17 -0
- package/dist/ui/PbSpinner.d.ts +3 -0
- package/dist/ui/PbSpinner.js +5 -0
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/index.js +6 -0
- package/dist/utils/emailTemplate.d.ts +7 -0
- package/dist/utils/emailTemplate.js +66 -0
- package/dist/utils/fonts.d.ts +2 -0
- package/dist/utils/fonts.js +10 -0
- package/dist/utils/imageCustomization.d.ts +3 -0
- package/dist/utils/imageCustomization.js +9 -0
- package/dist/utils/responsiveProperties.d.ts +2 -0
- package/dist/utils/responsiveProperties.js +28 -0
- package/dist/utils/responsiveStyles.d.ts +6 -0
- package/dist/utils/responsiveStyles.js +73 -0
- package/package.json +1 -8
- package/dist/components/CarouselComponent.js +0 -6
- package/dist/layouts/Menu.d.ts +0 -5
- package/dist/layouts/Menu.js +0 -34
- package/dist/renderers/SectionRenderer.d.ts +0 -6
- package/dist/renderers/SectionRenderer.js +0 -73
- package/dist/types/SectionType.d.ts +0 -10
- /package/dist/types/{SectionColumnType.js → BlockType.js} +0 -0
- /package/dist/types/{SectionType.js → EmailSettingsType.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -2,11 +2,25 @@ export { Header } from './layouts/Header.js';
|
|
|
2
2
|
export { Footer } from './layouts/Footer.js';
|
|
3
3
|
export { SiteLayout } from './layouts/SiteLayout.js';
|
|
4
4
|
export { PageBuilder } from './builders/PageBuilder.js';
|
|
5
|
-
export {
|
|
5
|
+
export { BlockRenderer } from './renderers/BlockRenderer.js';
|
|
6
|
+
export { IconComponent } from './components/IconComponent.js';
|
|
6
7
|
export { LoadingComponent } from './components/LoadingComponent.js';
|
|
7
8
|
export { ComponentFactory } from './factories/ComponentFactory.js';
|
|
8
9
|
export { ElementFactory } from './factories/ElementFactory.js';
|
|
10
|
+
export { iconMap } from './elements/IconMap.js';
|
|
9
11
|
export { ComponentTypeEnum } from './constants/ComponentEnum.js';
|
|
10
12
|
export { ElementTypeEnum } from './constants/ElementEnum.js';
|
|
13
|
+
export { ButtonActionEnum } from './constants/ButtonActionEnum.js';
|
|
11
14
|
export { analyticsService } from './services/AnalyticsService.js';
|
|
12
15
|
export { buttonActionFactory } from './factories/ButtonActionFactory.js';
|
|
16
|
+
export { defaultTokens, mergeTokens, tokenToCssVars, buildTokenCss, buildThemeVars } from './designSystem/tokens.js';
|
|
17
|
+
export { baseCss } from './designSystem/baseCss.js';
|
|
18
|
+
export { buildSiteCss } from './designSystem/buildSiteCss.js';
|
|
19
|
+
export { themeVarsStyle } from './designSystem/themeVars.js';
|
|
20
|
+
export { ThemeStyle } from './designSystem/theme.js';
|
|
21
|
+
export { PbContainer } from './ui/PbContainer.js';
|
|
22
|
+
export { PbRow } from './ui/PbRow.js';
|
|
23
|
+
export { PbCol } from './ui/PbCol.js';
|
|
24
|
+
export { PbButton } from './ui/PbButton.js';
|
|
25
|
+
export { PbSpinner } from './ui/PbSpinner.js';
|
|
26
|
+
export { PbAlert } from './ui/PbAlert.js';
|
package/dist/layouts/Footer.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import DOMPurify from 'dompurify';
|
|
3
|
-
import {
|
|
3
|
+
import { PbContainer } from '../ui/PbContainer.js';
|
|
4
|
+
import { PbRow } from '../ui/PbRow.js';
|
|
5
|
+
import { PbCol } from '../ui/PbCol.js';
|
|
4
6
|
import { SocialIconsComponent } from '../components/SocialIconsComponent.js';
|
|
5
7
|
export function Footer({ website }) {
|
|
6
8
|
var _a;
|
|
7
9
|
const social = (_a = website.properties) === null || _a === void 0 ? void 0 : _a.social;
|
|
8
10
|
const footer = website.footer.properties;
|
|
9
11
|
const styles = website.footer.styles;
|
|
10
|
-
|
|
12
|
+
const fluid = styles.fluid || undefined;
|
|
13
|
+
const baseStyle = Object.assign({}, styles);
|
|
14
|
+
delete baseStyle.fluid;
|
|
15
|
+
delete baseStyle.responsive;
|
|
16
|
+
const textStyle = {
|
|
17
|
+
display: 'flex',
|
|
18
|
+
flexDirection: 'column',
|
|
19
|
+
alignItems: 'center'
|
|
20
|
+
};
|
|
21
|
+
return (_jsx(PbContainer, { fluid: fluid || undefined, children: _jsx("footer", { id: "footer", className: "pb-footer", style: { backgroundColor: styles.backgroundColor }, children: _jsxs(PbRow, { children: [_jsx(PbCol, { width: { xs: 12 }, style: { marginBottom: '30px' }, children: social && _jsx(SocialIconsComponent, { social: social, color: styles.socialIconColor || styles.color }) }), _jsx(PbCol, { width: { xs: 12 }, style: textStyle, children: _jsx("div", { dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(footer.text1) } }) }), _jsx(PbCol, { width: { xs: 12 }, style: textStyle, children: _jsx("div", { dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(footer.text2) } }) }), _jsx(PbCol, { width: { xs: 12 }, style: { display: 'flex', justifyContent: 'center' }, children: _jsx("div", { dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(footer.text3) } }) }), _jsxs(PbCol, { width: { xs: 12 }, children: [_jsx("hr", { className: "pb-footer-divider" }), _jsxs("p", { className: "pb-text-center pb-mb-0", style: baseStyle, children: ["\u00A9 ", new Date().getFullYear(), " ", website.name] })] })] }) }) }));
|
|
11
22
|
}
|
package/dist/layouts/Header.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useMemo, useCallback } from 'react';
|
|
2
|
+
import { useMemo, useCallback, useState } from 'react';
|
|
3
3
|
import { useLocation } from 'react-router-dom';
|
|
4
|
-
import {
|
|
4
|
+
import { PbContainer } from '../ui/PbContainer.js';
|
|
5
5
|
export function Header({ website, imageBaseUrl }) {
|
|
6
6
|
const headerProperties = website.header.properties;
|
|
7
7
|
const headerStyles = website.header.styles;
|
|
8
|
-
const domain = (website.domain || '').replaceAll('.', '');
|
|
9
8
|
const location = useLocation();
|
|
9
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
10
10
|
const menuPages = useMemo(() => (website.pages || []).filter((p) => p.menu === true).sort((a, b) => (a.menuOrder || 0) - (b.menuOrder || 0)), [website.pages]);
|
|
11
11
|
const isActive = useCallback((path) => {
|
|
12
12
|
const currentPath = location.pathname;
|
|
@@ -15,20 +15,47 @@ export function Header({ website, imageBaseUrl }) {
|
|
|
15
15
|
return currentPath === path || currentPath.startsWith(path + '/');
|
|
16
16
|
}, [location.pathname]);
|
|
17
17
|
const showMenu = headerProperties.showMenu !== false && menuPages.length > 0;
|
|
18
|
-
const logoUrl = useMemo(() => imageBaseUrl
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const logoUrl = useMemo(() => (imageBaseUrl && website.logo ? `${imageBaseUrl.replace(/\/+$/, '')}/${website.logo}` : undefined), [imageBaseUrl, website.logo]);
|
|
19
|
+
const logoAlign = headerProperties.logoAlign || 'center';
|
|
20
|
+
const menuLinkColor = headerStyles.menuLinkColor || headerStyles.color || undefined;
|
|
21
|
+
const menuActiveLinkColor = headerStyles.menuActiveLinkColor || headerStyles.menuLinkColor || headerStyles.color || undefined;
|
|
22
|
+
const textAlign = headerStyles.textAlign || 'left';
|
|
23
|
+
const brandStyle = { padding: 0 };
|
|
24
|
+
if (showMenu) {
|
|
25
|
+
if (logoAlign === 'right')
|
|
26
|
+
brandStyle.marginLeft = 'auto';
|
|
27
|
+
else if (logoAlign === 'center') {
|
|
28
|
+
brandStyle.marginRight = 'auto';
|
|
29
|
+
brandStyle.marginLeft = 'auto';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
brandStyle.marginRight = 'auto';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (logoAlign === 'center') {
|
|
36
|
+
brandStyle.margin = '0 auto';
|
|
37
|
+
}
|
|
38
|
+
else if (logoAlign === 'right') {
|
|
39
|
+
brandStyle.marginLeft = 'auto';
|
|
40
|
+
}
|
|
41
|
+
const innerStyle = { textAlign };
|
|
42
|
+
if (textAlign === 'center')
|
|
43
|
+
innerStyle.justifyContent = 'center';
|
|
44
|
+
else if (textAlign === 'right')
|
|
45
|
+
innerStyle.justifyContent = 'flex-end';
|
|
46
|
+
const closeMenu = useCallback(() => setMenuOpen(false), []);
|
|
47
|
+
return (_jsx("header", { className: "pb-header", style: {
|
|
48
|
+
backgroundColor: headerStyles.backgroundColor || undefined,
|
|
49
|
+
color: headerStyles.color || undefined
|
|
50
|
+
}, children: _jsx(PbContainer, { fluid: headerStyles.fluid || undefined, children: _jsxs("div", { className: "pb-header-inner", style: innerStyle, children: [headerProperties.showLogo && logoUrl && (_jsx("a", { className: "pb-brand", href: "/", style: brandStyle, "aria-label": "P\u00E1gina inicial", children: _jsx("img", { src: logoUrl, width: Number(headerProperties.logoWidth) || 200, alt: "Logo" }) })), showMenu && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "pb-nav-toggle", "aria-label": menuOpen ? 'Fechar menu' : 'Abrir menu', "aria-expanded": menuOpen, onClick: () => setMenuOpen((open) => !open), children: "\u2630" }), _jsx("nav", { className: `pb-nav${menuOpen ? ' pb-nav-open' : ''}`, "aria-label": "Menu principal", children: menuPages.map((p) => {
|
|
22
51
|
const active = isActive(p.path);
|
|
23
|
-
return (_jsx(
|
|
24
|
-
color: active ?
|
|
25
|
-
fontSize:
|
|
26
|
-
letterSpacing:
|
|
27
|
-
textTransform:
|
|
52
|
+
return (_jsx("a", { href: p.path, onClick: closeMenu, className: `pb-nav-link${active ? ' pb-nav-link-active' : ''}`, style: {
|
|
53
|
+
color: active ? menuActiveLinkColor : menuLinkColor,
|
|
54
|
+
fontSize: headerStyles.menuFontSize || undefined,
|
|
55
|
+
letterSpacing: headerStyles.menuLetterSpacing || undefined,
|
|
56
|
+
textTransform: headerStyles.menuTextTransform || undefined,
|
|
28
57
|
margin: '0 12px',
|
|
29
|
-
paddingBottom: '4px'
|
|
30
|
-
borderBottom: active ? '2px solid #c0ad5b' : '2px solid transparent',
|
|
31
|
-
transition: 'color 0.3s, border-color 0.3s'
|
|
58
|
+
paddingBottom: '4px'
|
|
32
59
|
}, children: p.title }, p.id));
|
|
33
|
-
}) }) })] })
|
|
60
|
+
}) })] }))] }) }) }));
|
|
34
61
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { WebsiteType } from '../types/WebsiteType.js';
|
|
2
|
-
export
|
|
2
|
+
export interface EmailApiConfig {
|
|
3
|
+
apiUrl?: string;
|
|
4
|
+
authToken?: string;
|
|
5
|
+
sender?: string;
|
|
6
|
+
senderName?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function SiteLayout({ website, imageBaseUrl, emailApi }: {
|
|
3
9
|
readonly website: WebsiteType;
|
|
4
10
|
readonly imageBaseUrl?: string;
|
|
11
|
+
readonly emailApi?: EmailApiConfig;
|
|
5
12
|
}): import("react").JSX.Element;
|
|
@@ -1,7 +1,40 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
2
3
|
import { Outlet } from 'react-router-dom';
|
|
4
|
+
import { Helmet } from 'react-helmet-async';
|
|
3
5
|
import { Header } from './Header.js';
|
|
4
6
|
import { Footer } from './Footer.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
import { ThemeStyle } from '../designSystem/theme.js';
|
|
8
|
+
import { buildFontFamily, buildGoogleFontsHref } from '../utils/fonts.js';
|
|
9
|
+
import { buttonActionFactory } from '../factories/ButtonActionFactory.js';
|
|
10
|
+
export function SiteLayout({ website, imageBaseUrl, emailApi }) {
|
|
11
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
12
|
+
const fontFamily = buildFontFamily((_a = website.styles) === null || _a === void 0 ? void 0 : _a.fontFamily);
|
|
13
|
+
const fontHref = buildGoogleFontsHref((_b = website.styles) === null || _b === void 0 ? void 0 : _b.fontFamily);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
var _a, _b, _c, _d, _e, _f;
|
|
16
|
+
if (!(emailApi === null || emailApi === void 0 ? void 0 : emailApi.apiUrl) || !emailApi.authToken)
|
|
17
|
+
return;
|
|
18
|
+
buttonActionFactory.configureEmail({
|
|
19
|
+
apiUrl: emailApi.apiUrl,
|
|
20
|
+
authToken: emailApi.authToken,
|
|
21
|
+
websiteId: website.id,
|
|
22
|
+
sender: emailApi.sender || 'contato@pixelbuild.com.br',
|
|
23
|
+
senderName: emailApi.senderName || website.name,
|
|
24
|
+
defaultRecipient: (_b = (_a = website.properties) === null || _a === void 0 ? void 0 : _a.email) === null || _b === void 0 ? void 0 : _b.recipient,
|
|
25
|
+
defaultRecipientName: (_d = (_c = website.properties) === null || _c === void 0 ? void 0 : _c.email) === null || _d === void 0 ? void 0 : _d.recipientName,
|
|
26
|
+
defaultSubject: (_f = (_e = website.properties) === null || _e === void 0 ? void 0 : _e.email) === null || _f === void 0 ? void 0 : _f.subject
|
|
27
|
+
});
|
|
28
|
+
}, [
|
|
29
|
+
emailApi === null || emailApi === void 0 ? void 0 : emailApi.apiUrl,
|
|
30
|
+
emailApi === null || emailApi === void 0 ? void 0 : emailApi.authToken,
|
|
31
|
+
emailApi === null || emailApi === void 0 ? void 0 : emailApi.sender,
|
|
32
|
+
emailApi === null || emailApi === void 0 ? void 0 : emailApi.senderName,
|
|
33
|
+
website.id,
|
|
34
|
+
website.name,
|
|
35
|
+
(_d = (_c = website.properties) === null || _c === void 0 ? void 0 : _c.email) === null || _d === void 0 ? void 0 : _d.recipient,
|
|
36
|
+
(_f = (_e = website.properties) === null || _e === void 0 ? void 0 : _e.email) === null || _f === void 0 ? void 0 : _f.recipientName,
|
|
37
|
+
(_h = (_g = website.properties) === null || _g === void 0 ? void 0 : _g.email) === null || _h === void 0 ? void 0 : _h.subject
|
|
38
|
+
]);
|
|
39
|
+
return (_jsxs(_Fragment, { children: [_jsx(ThemeStyle, { designSystem: website.designSystem }), fontHref && (_jsxs(Helmet, { children: [_jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" }), _jsx("link", { href: fontHref, rel: "stylesheet" })] })), _jsxs("div", { id: "site-layout", className: "pb-root", style: { backgroundColor: website.styles.backgroundColor, color: website.styles.color, fontFamily }, children: [_jsx(Header, { website: website, imageBaseUrl: imageBaseUrl }), _jsx(Outlet, {}), _jsx(Footer, { website: website })] })] }));
|
|
7
40
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BlockType } from '../types/BlockType.js';
|
|
2
|
+
import type { ComponentDefaults } from '../types/WebsiteType.js';
|
|
3
|
+
declare const BlockRenderer: import("react").NamedExoticComponent<{
|
|
4
|
+
readonly blocks: BlockType[];
|
|
5
|
+
readonly editionMode?: boolean;
|
|
6
|
+
readonly componentDefaults?: ComponentDefaults;
|
|
7
|
+
}>;
|
|
8
|
+
export { BlockRenderer };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useMemo } from 'react';
|
|
3
|
+
import { PbContainer } from '../ui/PbContainer.js';
|
|
4
|
+
import { ComponentFactory } from '../factories/ComponentFactory.js';
|
|
5
|
+
import { orderBySort } from '../utils/orderBySort.js';
|
|
6
|
+
import { buildResponsiveCss } from '../utils/responsiveStyles.js';
|
|
7
|
+
const componentFactory = new ComponentFactory();
|
|
8
|
+
function gridClass(id) {
|
|
9
|
+
return `pixelbuild-grid-${String(id).replace(/[^a-zA-Z0-9_-]/g, '_')}`;
|
|
10
|
+
}
|
|
11
|
+
const BlockGrid = memo(function BlockGrid({ block, editionMode, componentDefaults }) {
|
|
12
|
+
const grid = gridClass(block.id);
|
|
13
|
+
const components = orderBySort(block.components);
|
|
14
|
+
const css = useMemo(() => {
|
|
15
|
+
const rules = components
|
|
16
|
+
.map((component) => {
|
|
17
|
+
var _a, _b, _c;
|
|
18
|
+
const properties = component.properties || {};
|
|
19
|
+
const row = Math.max(0, Number(properties.row) || 0);
|
|
20
|
+
const rowSpan = Math.max(1, Number(properties.rowSpan) || 1);
|
|
21
|
+
const xs = ((_a = component.width) === null || _a === void 0 ? void 0 : _a.xs) || 12;
|
|
22
|
+
const sm = ((_b = component.width) === null || _b === void 0 ? void 0 : _b.sm) || xs;
|
|
23
|
+
const md = ((_c = component.width) === null || _c === void 0 ? void 0 : _c.md) || sm;
|
|
24
|
+
const cls = gridClass(component.id);
|
|
25
|
+
return [
|
|
26
|
+
`.${grid} .${cls}{grid-column:span ${xs};grid-row:auto;min-width:0}`,
|
|
27
|
+
`@media (min-width:576px){.${grid} .${cls}{grid-column:span ${sm}}}`,
|
|
28
|
+
`@media (min-width:768px){.${grid} .${cls}{grid-column:span ${md};grid-row:${row + 1}/span ${rowSpan}}}`
|
|
29
|
+
].join('');
|
|
30
|
+
})
|
|
31
|
+
.join('');
|
|
32
|
+
return `.${grid}{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pb-gutter,1rem)}${rules}`;
|
|
33
|
+
}, [grid, components]);
|
|
34
|
+
if (editionMode && components.length === 0) {
|
|
35
|
+
return (_jsxs("div", { "data-pixelbuild-empty-block": block.id, style: {
|
|
36
|
+
minHeight: 80,
|
|
37
|
+
display: 'flex',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
justifyContent: 'center',
|
|
40
|
+
gap: 6,
|
|
41
|
+
border: '1.5px dashed #c4d0dc',
|
|
42
|
+
color: '#94a3b8',
|
|
43
|
+
fontSize: 13,
|
|
44
|
+
cursor: 'pointer',
|
|
45
|
+
textAlign: 'center',
|
|
46
|
+
borderRadius: 8
|
|
47
|
+
}, children: [_jsx("span", { style: { fontSize: 18, lineHeight: 1 }, children: "+" }), "Adicionar componente"] }));
|
|
48
|
+
}
|
|
49
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { children: css }), _jsx("div", { className: grid, children: components.map((component) => (_jsx("div", { className: gridClass(component.id), children: componentFactory.build(component, editionMode, componentDefaults) }, component.id))) })] }));
|
|
50
|
+
});
|
|
51
|
+
const BlockContent = memo(function BlockContent({ block, editionMode, componentDefaults }) {
|
|
52
|
+
const content = useMemo(() => _jsx(BlockGrid, { block: block, editionMode: editionMode, componentDefaults: componentDefaults }), [block, editionMode, componentDefaults]);
|
|
53
|
+
if (block.sectionType === 'container-fluid') {
|
|
54
|
+
return (_jsx(PbContainer, { fluid: true, "data-pb-block": block.id, style: block.styles, children: content }));
|
|
55
|
+
}
|
|
56
|
+
if (block.sectionType === 'container') {
|
|
57
|
+
return (_jsx(PbContainer, { "data-pb-block": block.id, style: block.styles, children: content }));
|
|
58
|
+
}
|
|
59
|
+
return _jsx(PbContainer, { fluid: true, children: content });
|
|
60
|
+
});
|
|
61
|
+
const BlockRenderer = memo(function BlockRenderer({ blocks, editionMode = false, componentDefaults }) {
|
|
62
|
+
const sorted = useMemo(() => orderBySort(blocks || []), [blocks]);
|
|
63
|
+
if (sorted.length === 0) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { children: buildResponsiveCss(sorted) }), sorted.map((block) => (_jsx(BlockContent, { block: block, editionMode: editionMode, componentDefaults: componentDefaults }, block.id)))] }));
|
|
67
|
+
});
|
|
68
|
+
export { BlockRenderer };
|
|
@@ -3,15 +3,24 @@ import type { MailBodyType } from '../types/MailBodyType.js';
|
|
|
3
3
|
export interface EmailServiceConfig {
|
|
4
4
|
apiUrl: string;
|
|
5
5
|
authToken: string;
|
|
6
|
-
|
|
6
|
+
websiteId: number | string;
|
|
7
7
|
sender: string;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
senderName?: string;
|
|
9
|
+
defaultRecipient?: string;
|
|
10
|
+
defaultRecipientName?: string;
|
|
11
|
+
defaultSubject?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface EmailSendOptions {
|
|
14
|
+
recipient?: string;
|
|
15
|
+
recipientName?: string;
|
|
16
|
+
subject?: string;
|
|
17
|
+
formId?: number | string;
|
|
18
|
+
websiteName?: string;
|
|
10
19
|
}
|
|
11
20
|
declare class EmailService {
|
|
12
21
|
private readonly config;
|
|
13
22
|
constructor(config: EmailServiceConfig);
|
|
14
|
-
sendMail(params: FormFieldsType[]): Promise<boolean>;
|
|
15
|
-
createBody(params: FormFieldsType[]): MailBodyType;
|
|
23
|
+
sendMail(params: FormFieldsType[], options?: EmailSendOptions): Promise<boolean>;
|
|
24
|
+
createBody(params: FormFieldsType[], options?: EmailSendOptions): MailBodyType;
|
|
16
25
|
}
|
|
17
26
|
export { EmailService };
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import { buildFormEmailHtml } from '../utils/emailTemplate.js';
|
|
2
|
+
const DEFAULT_SUBJECT = 'Mensagem enviada pelo formulário do site';
|
|
3
|
+
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1
4
|
class EmailService {
|
|
2
5
|
constructor(config) {
|
|
3
6
|
this.config = config;
|
|
4
7
|
}
|
|
5
|
-
async sendMail(params) {
|
|
6
|
-
const body = this.createBody(params);
|
|
8
|
+
async sendMail(params, options = {}) {
|
|
9
|
+
const body = this.createBody(params, options);
|
|
7
10
|
const response = await fetch(`${this.config.apiUrl}/send-mail`, {
|
|
8
11
|
method: 'POST',
|
|
9
12
|
headers: {
|
|
10
13
|
'Content-Type': 'application/json',
|
|
11
|
-
Authorization: `Bearer ${this.config.authToken}
|
|
14
|
+
Authorization: `Bearer ${this.config.authToken}`,
|
|
15
|
+
'X-Website-Id': String(this.config.websiteId)
|
|
12
16
|
},
|
|
13
17
|
body: JSON.stringify(body)
|
|
14
18
|
});
|
|
@@ -17,29 +21,22 @@ class EmailService {
|
|
|
17
21
|
}
|
|
18
22
|
return true;
|
|
19
23
|
}
|
|
20
|
-
createBody(params) {
|
|
21
|
-
var _a
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const phone = params.find((e) => e.name === 'phoneField');
|
|
24
|
+
createBody(params, options = {}) {
|
|
25
|
+
var _a;
|
|
26
|
+
const rows = params
|
|
27
|
+
.filter((field) => { var _a; return field.name && String((_a = field.value) !== null && _a !== void 0 ? _a : '').trim() !== ''; })
|
|
28
|
+
.map((field) => { var _a; return ({ label: field.name, value: String((_a = field.value) !== null && _a !== void 0 ? _a : '') }); });
|
|
29
|
+
const emailField = params.find((field) => { var _a; return /email/i.test(field.name) || EMAIL_REGEX.test(String((_a = field.value) !== null && _a !== void 0 ? _a : '')); });
|
|
30
|
+
const subject = options.subject || this.config.defaultSubject || DEFAULT_SUBJECT;
|
|
28
31
|
return {
|
|
29
|
-
senderName: this.config.senderName,
|
|
32
|
+
senderName: this.config.senderName || options.websiteName || 'PixelBuild',
|
|
30
33
|
sender: this.config.sender,
|
|
31
|
-
recipientName: this.config.
|
|
32
|
-
recipient: this.config.
|
|
33
|
-
title:
|
|
34
|
-
message:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
`CPF: ${(_d = document === null || document === void 0 ? void 0 : document.value) !== null && _d !== void 0 ? _d : ''}`,
|
|
38
|
-
`E-mail: ${(_e = email === null || email === void 0 ? void 0 : email.value) !== null && _e !== void 0 ? _e : ''}`,
|
|
39
|
-
`Celular: ${(_f = phone === null || phone === void 0 ? void 0 : phone.value) !== null && _f !== void 0 ? _f : ''}`
|
|
40
|
-
]
|
|
41
|
-
.filter(Boolean)
|
|
42
|
-
.join('\n')
|
|
34
|
+
recipientName: options.recipientName || this.config.defaultRecipientName || 'Site',
|
|
35
|
+
recipient: options.recipient || this.config.defaultRecipient || '',
|
|
36
|
+
title: subject,
|
|
37
|
+
message: buildFormEmailHtml(subject, rows),
|
|
38
|
+
isHtml: true,
|
|
39
|
+
lead: Object.assign(Object.assign({ formId: (_a = options.formId) !== null && _a !== void 0 ? _a : null }, Object.fromEntries(rows.map((row) => [row.label, row.value]))), (emailField ? { email: emailField.value } : {}))
|
|
43
40
|
};
|
|
44
41
|
}
|
|
45
42
|
}
|
|
@@ -11,14 +11,19 @@ export interface FormElement {
|
|
|
11
11
|
inputValidateId: number | null;
|
|
12
12
|
[key: string]: string | number | boolean | null;
|
|
13
13
|
}
|
|
14
|
+
export interface FormEmailConfig {
|
|
15
|
+
recipient?: string;
|
|
16
|
+
subject?: string;
|
|
17
|
+
}
|
|
14
18
|
export interface FormEntry {
|
|
15
19
|
elements: string[];
|
|
16
|
-
|
|
20
|
+
email?: FormEmailConfig;
|
|
21
|
+
[key: string]: string[] | FormEmailConfig | null | undefined;
|
|
17
22
|
}
|
|
18
23
|
export interface FormStoreState {
|
|
19
24
|
forms: Record<string, FormEntry>;
|
|
20
25
|
elements: Record<string, FormElement>;
|
|
21
|
-
registerForm: (formId: number) => void;
|
|
26
|
+
registerForm: (formId: number, emailConfig?: FormEmailConfig) => void;
|
|
22
27
|
registerElement: (elementId: number, formId?: number | null, initialState?: Partial<FormElement>) => void;
|
|
23
28
|
unregisterElement: (elementId: number) => void;
|
|
24
29
|
validateFormData: (inputValidateId: number, elementId: number, value: string) => void;
|
|
@@ -3,9 +3,14 @@ import { InputValidateFactory } from '../factories/InputValidateFactory.js';
|
|
|
3
3
|
const UseFormStore = create((set, get) => ({
|
|
4
4
|
forms: {},
|
|
5
5
|
elements: {},
|
|
6
|
-
registerForm: (formId) => set((state) =>
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
registerForm: (formId, emailConfig) => set((state) => {
|
|
7
|
+
const existing = state.forms[formId];
|
|
8
|
+
const nextForm = existing
|
|
9
|
+
? Object.assign(Object.assign({}, existing), (emailConfig ? { email: emailConfig } : {})) : Object.assign({ elements: [] }, (emailConfig ? { email: emailConfig } : {}));
|
|
10
|
+
return {
|
|
11
|
+
forms: Object.assign(Object.assign({}, state.forms), { [formId]: nextForm })
|
|
12
|
+
};
|
|
13
|
+
}),
|
|
9
14
|
registerElement: (elementId, formId = null, initialState = {}) => set((state) => {
|
|
10
15
|
var _a, _b;
|
|
11
16
|
const existingElement = state.elements[elementId];
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import type { StylesType } from './StylesType.js';
|
|
2
|
-
import type { ColumnWidthType } from './ColumnWidthType.js';
|
|
3
2
|
import type { ComponentType } from './ComponentType.js';
|
|
4
|
-
|
|
5
|
-
export interface SectionColumnType {
|
|
3
|
+
export interface BlockType {
|
|
6
4
|
id: number;
|
|
7
|
-
|
|
8
|
-
offset: ColumnWidthType;
|
|
5
|
+
sectionType: 'container' | 'container-fluid';
|
|
9
6
|
sort: number;
|
|
10
7
|
properties: Record<string, unknown>;
|
|
11
8
|
styles: StylesType;
|
|
12
9
|
components: ComponentType[];
|
|
13
|
-
childSections: SectionType[];
|
|
14
10
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { StylesType } from './StylesType.js';
|
|
2
2
|
import type { ElementType } from './ElementType.js';
|
|
3
|
+
import type { ColumnWidthType } from './ColumnWidthType.js';
|
|
3
4
|
export interface ComponentType {
|
|
4
5
|
id: number;
|
|
5
6
|
componentType: string;
|
|
@@ -7,5 +8,7 @@ export interface ComponentType {
|
|
|
7
8
|
enabled: boolean;
|
|
8
9
|
properties: Record<string, unknown>;
|
|
9
10
|
styles: StylesType;
|
|
11
|
+
width: ColumnWidthType;
|
|
12
|
+
offset: ColumnWidthType;
|
|
10
13
|
elements: ElementType[];
|
|
11
14
|
}
|
package/dist/types/PageType.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { StylesType } from './StylesType.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { BlockType } from './BlockType.js';
|
|
3
3
|
export interface PageType {
|
|
4
4
|
id: number;
|
|
5
5
|
websiteId: number;
|
|
@@ -13,5 +13,5 @@ export interface PageType {
|
|
|
13
13
|
menuType: 'link' | 'dropdown';
|
|
14
14
|
properties: Record<string, unknown>;
|
|
15
15
|
styles: StylesType;
|
|
16
|
-
|
|
16
|
+
blocks: BlockType[];
|
|
17
17
|
}
|
|
@@ -2,7 +2,12 @@ export type Float = 'left' | 'right' | 'none' | 'inline-start' | 'inline-end';
|
|
|
2
2
|
export type TextAlign = 'left' | 'right' | 'center' | 'justify' | 'start' | 'end';
|
|
3
3
|
export type ObjectFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
|
|
4
4
|
export type FontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
|
|
5
|
+
export type BreakpointKey = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
6
|
+
export type ResponsiveStylesType = {
|
|
7
|
+
[key in BreakpointKey]?: Partial<Omit<StylesType, 'responsive'>>;
|
|
8
|
+
};
|
|
5
9
|
export interface StylesType {
|
|
10
|
+
responsive?: ResponsiveStylesType;
|
|
6
11
|
alignItems?: string;
|
|
7
12
|
backgroundColor?: string;
|
|
8
13
|
backgroundGradientColorStart?: string;
|
|
@@ -18,6 +23,7 @@ export interface StylesType {
|
|
|
18
23
|
display?: string;
|
|
19
24
|
float?: Float;
|
|
20
25
|
fluid?: boolean;
|
|
26
|
+
fontFamily?: string;
|
|
21
27
|
fontSize?: string;
|
|
22
28
|
fontWeight?: FontWeight;
|
|
23
29
|
height?: string;
|
|
@@ -25,6 +31,12 @@ export interface StylesType {
|
|
|
25
31
|
marginLeft?: string;
|
|
26
32
|
marginRight?: string;
|
|
27
33
|
marginBottom?: string;
|
|
34
|
+
menuLinkColor?: string;
|
|
35
|
+
menuActiveLinkColor?: string;
|
|
36
|
+
menuFontSize?: string;
|
|
37
|
+
menuLetterSpacing?: string;
|
|
38
|
+
menuTextTransform?: string;
|
|
39
|
+
socialIconColor?: string;
|
|
28
40
|
objectFit?: ObjectFit;
|
|
29
41
|
paddingTop?: string;
|
|
30
42
|
paddingLeft?: string;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { SocialPropertiesType } from './SocialPropertiesType.js';
|
|
2
|
+
import type { EmailSettingsType } from './EmailSettingsType.js';
|
|
2
3
|
export interface WebsitePropertiesType {
|
|
3
4
|
loadingMessage: string;
|
|
4
5
|
social: SocialPropertiesType;
|
|
6
|
+
email?: EmailSettingsType;
|
|
5
7
|
}
|
|
@@ -3,6 +3,9 @@ import type { StylesType } from './StylesType.js';
|
|
|
3
3
|
import type { HeaderType } from './HeaderType.js';
|
|
4
4
|
import type { FooterType } from './FooterType.js';
|
|
5
5
|
import type { WebsitePropertiesType } from './WebsitePropertiesType.js';
|
|
6
|
+
import type { PartialDesignTokens } from '../designSystem/tokens.js';
|
|
7
|
+
/** Estilos padrão por tipo de componente (ex.: todos os botões, títulos...). */
|
|
8
|
+
export type ComponentDefaults = Record<string, Partial<StylesType>>;
|
|
6
9
|
export interface WebsiteType {
|
|
7
10
|
id: number;
|
|
8
11
|
name: string;
|
|
@@ -13,7 +16,10 @@ export interface WebsiteType {
|
|
|
13
16
|
footer: FooterType;
|
|
14
17
|
properties: WebsitePropertiesType;
|
|
15
18
|
styles: StylesType;
|
|
19
|
+
designSystem?: PartialDesignTokens;
|
|
20
|
+
componentDefaults?: ComponentDefaults;
|
|
16
21
|
enabled: boolean;
|
|
22
|
+
maintenance?: boolean;
|
|
17
23
|
publishedAt: string | null;
|
|
18
24
|
createdAt: string;
|
|
19
25
|
updatedAt: string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Alerta próprio do design system. Substitui o `Alert` do react-bootstrap.
|
|
4
|
+
*/
|
|
5
|
+
export declare function PbAlert({ variant, title, style, children }: {
|
|
6
|
+
readonly variant?: string;
|
|
7
|
+
readonly title?: ReactNode;
|
|
8
|
+
readonly style?: CSSProperties;
|
|
9
|
+
readonly children?: ReactNode;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Alerta próprio do design system. Substitui o `Alert` do react-bootstrap.
|
|
4
|
+
*/
|
|
5
|
+
export function PbAlert({ variant = 'info', title, style, children }) {
|
|
6
|
+
const classes = ['pb-alert', variant ? `pb-alert-${variant}` : 'pb-alert-info'].filter(Boolean).join(' ');
|
|
7
|
+
return (_jsxs("div", { className: classes, role: "alert", style: style, children: [title && _jsx("div", { className: "pb-alert-title", children: title }), children] }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
export type PbButtonVariant = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark' | 'outline-primary' | 'outline-secondary' | 'link';
|
|
3
|
+
/**
|
|
4
|
+
* Botão próprio do design system. Substitui o `Button` do react-bootstrap,
|
|
5
|
+
* mantendo o comportamento de link (`href`) e botão de formulário.
|
|
6
|
+
*/
|
|
7
|
+
export declare function PbButton({ as, href, target, rel, type, variant, size, disabled, onClick, className, style, children }: {
|
|
8
|
+
readonly as?: string;
|
|
9
|
+
readonly href?: string;
|
|
10
|
+
readonly target?: string;
|
|
11
|
+
readonly rel?: string;
|
|
12
|
+
readonly type?: 'button' | 'submit' | 'reset';
|
|
13
|
+
readonly variant?: string;
|
|
14
|
+
readonly size?: 'sm' | 'lg';
|
|
15
|
+
readonly disabled?: boolean;
|
|
16
|
+
readonly onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
|
17
|
+
readonly className?: string;
|
|
18
|
+
readonly style?: CSSProperties;
|
|
19
|
+
readonly children?: ReactNode;
|
|
20
|
+
}): import("react").JSX.Element;
|