lib-pixelbuild 0.2.2 → 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 +40 -27
- package/dist/components/ButtonsComponent.js +6 -5
- package/dist/components/CardComponent.js +13 -7
- package/dist/components/FormComponent.js +3 -2
- package/dist/components/IconComponent.d.ts +5 -0
- package/dist/components/IconComponent.js +12 -0
- package/dist/components/ImageComponent.js +4 -3
- package/dist/components/ListComponent.js +1 -2
- package/dist/components/LoadingComponent.js +2 -2
- package/dist/components/MapComponent.js +10 -11
- package/dist/components/SliderComponent.d.ts +1 -1
- package/dist/components/SliderComponent.js +8 -10
- package/dist/components/SocialIconsComponent.js +3 -4
- package/dist/components/TextComponent.js +3 -2
- package/dist/constants/ComponentEnum.d.ts +1 -0
- package/dist/constants/ComponentEnum.js +1 -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 +5 -3
- package/dist/elements/ElementColWrapper.js +2 -2
- package/dist/elements/IconMap.js +2 -2
- package/dist/elements/InputElement.js +10 -9
- package/dist/elements/TextElement.js +4 -0
- package/dist/factories/ComponentFactory.d.ts +2 -1
- package/dist/factories/ComponentFactory.js +25 -11
- package/dist/index.d.ts +15 -3
- package/dist/index.js +13 -1
- package/dist/layouts/Footer.js +13 -2
- package/dist/layouts/Header.js +17 -8
- package/dist/layouts/SiteLayout.js +2 -1
- package/dist/renderers/BlockRenderer.d.ts +8 -0
- package/dist/renderers/BlockRenderer.js +68 -0
- package/dist/types/{SectionColumnType.d.ts → BlockType.d.ts} +2 -6
- package/dist/types/ComponentType.d.ts +3 -0
- package/dist/types/PageType.d.ts +2 -2
- package/dist/types/WebsiteType.d.ts +5 -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/imageCustomization.js +1 -3
- package/dist/utils/responsiveStyles.d.ts +2 -2
- package/dist/utils/responsiveStyles.js +10 -19
- package/package.json +1 -6
- package/dist/renderers/SectionRenderer.d.ts +0 -6
- package/dist/renderers/SectionRenderer.js +0 -88
- package/dist/types/SectionType.d.ts +0 -10
- package/dist/types/SectionType.js +0 -1
- /package/dist/types/{SectionColumnType.js → BlockType.js} +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design System tokens.
|
|
3
|
+
*
|
|
4
|
+
* Fontes de verdade para cores, tipografia, espaçamento, raio e sombra do site
|
|
5
|
+
* público. Cada token é exposto como uma variável CSS `--pb-*` e os componentes
|
|
6
|
+
* do `lib-pixelbuild` consomem via `var(--pb-*, <fallback>)`, de forma que um
|
|
7
|
+
* site sem design system configurado continua com aparência padrão.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Valores padrão. Mantidos neutros e modernos para que um site sem
|
|
11
|
+
* personalização não tenha cara de "framework genérico".
|
|
12
|
+
*/
|
|
13
|
+
export const defaultTokens = {
|
|
14
|
+
colors: {
|
|
15
|
+
primary: '#F58220',
|
|
16
|
+
secondary: '#64748B',
|
|
17
|
+
success: '#16A34A',
|
|
18
|
+
danger: '#DC2626',
|
|
19
|
+
warning: '#F59E0B',
|
|
20
|
+
info: '#0EA5E9',
|
|
21
|
+
light: '#F8FAFC',
|
|
22
|
+
dark: '#0F172A',
|
|
23
|
+
background: '#FFFFFF',
|
|
24
|
+
surface: '#FFFFFF',
|
|
25
|
+
text: '#1F2937',
|
|
26
|
+
heading: '#111827',
|
|
27
|
+
muted: '#6B7280',
|
|
28
|
+
border: '#E5E7EB'
|
|
29
|
+
},
|
|
30
|
+
typography: {
|
|
31
|
+
fontFamily: "'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
|
|
32
|
+
fontSizeBase: '16px',
|
|
33
|
+
fontWeightNormal: '400',
|
|
34
|
+
fontWeightBold: '700',
|
|
35
|
+
lineHeight: '1.6'
|
|
36
|
+
},
|
|
37
|
+
spacing: {
|
|
38
|
+
none: '0',
|
|
39
|
+
xs: '4px',
|
|
40
|
+
sm: '8px',
|
|
41
|
+
md: '16px',
|
|
42
|
+
lg: '24px',
|
|
43
|
+
xl: '32px',
|
|
44
|
+
xxl: '48px'
|
|
45
|
+
},
|
|
46
|
+
radius: {
|
|
47
|
+
none: '0',
|
|
48
|
+
sm: '4px',
|
|
49
|
+
md: '8px',
|
|
50
|
+
lg: '12px',
|
|
51
|
+
full: '9999px'
|
|
52
|
+
},
|
|
53
|
+
shadow: {
|
|
54
|
+
none: 'none',
|
|
55
|
+
sm: '0 1px 2px rgba(0,0,0,0.05)',
|
|
56
|
+
md: '0 4px 12px rgba(0,0,0,0.08)',
|
|
57
|
+
lg: '0 8px 24px rgba(0,0,0,0.12)'
|
|
58
|
+
},
|
|
59
|
+
gutter: '1.5rem'
|
|
60
|
+
};
|
|
61
|
+
function mergePartial(base, partial) {
|
|
62
|
+
if (!partial)
|
|
63
|
+
return base;
|
|
64
|
+
const result = Object.assign({}, base);
|
|
65
|
+
for (const key of Object.keys(partial)) {
|
|
66
|
+
const value = partial[key];
|
|
67
|
+
if (value === undefined)
|
|
68
|
+
continue;
|
|
69
|
+
const baseValue = base[key];
|
|
70
|
+
if (typeof baseValue === 'object' && baseValue !== null && typeof value === 'object' && value !== null) {
|
|
71
|
+
;
|
|
72
|
+
result[key] = Object.assign(Object.assign({}, baseValue), value);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
;
|
|
76
|
+
result[key] = value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
export function mergeTokens(base, partial) {
|
|
82
|
+
const merged = mergePartial(base, partial || {});
|
|
83
|
+
return merged;
|
|
84
|
+
}
|
|
85
|
+
/** Mapeia os tokens para pares `--pb-*` → valor. */
|
|
86
|
+
export function tokenToCssVars(tokens) {
|
|
87
|
+
const { colors, typography, spacing, radius, shadow } = tokens;
|
|
88
|
+
return {
|
|
89
|
+
'--pb-color-primary': colors.primary,
|
|
90
|
+
'--pb-color-secondary': colors.secondary,
|
|
91
|
+
'--pb-color-success': colors.success,
|
|
92
|
+
'--pb-color-danger': colors.danger,
|
|
93
|
+
'--pb-color-warning': colors.warning,
|
|
94
|
+
'--pb-color-info': colors.info,
|
|
95
|
+
'--pb-color-light': colors.light,
|
|
96
|
+
'--pb-color-dark': colors.dark,
|
|
97
|
+
'--pb-color-background': colors.background,
|
|
98
|
+
'--pb-color-surface': colors.surface,
|
|
99
|
+
'--pb-color-text': colors.text,
|
|
100
|
+
'--pb-color-heading': colors.heading,
|
|
101
|
+
'--pb-color-muted': colors.muted,
|
|
102
|
+
'--pb-color-border': colors.border,
|
|
103
|
+
'--pb-font-family': typography.fontFamily,
|
|
104
|
+
'--pb-font-size-base': typography.fontSizeBase,
|
|
105
|
+
'--pb-font-weight-normal': typography.fontWeightNormal,
|
|
106
|
+
'--pb-font-weight-bold': typography.fontWeightBold,
|
|
107
|
+
'--pb-line-height': typography.lineHeight,
|
|
108
|
+
'--pb-space-none': spacing.none,
|
|
109
|
+
'--pb-space-xs': spacing.xs,
|
|
110
|
+
'--pb-space-sm': spacing.sm,
|
|
111
|
+
'--pb-space-md': spacing.md,
|
|
112
|
+
'--pb-space-lg': spacing.lg,
|
|
113
|
+
'--pb-space-xl': spacing.xl,
|
|
114
|
+
'--pb-space-xxl': spacing.xxl,
|
|
115
|
+
'--pb-radius-none': radius.none,
|
|
116
|
+
'--pb-radius-sm': radius.sm,
|
|
117
|
+
'--pb-radius-md': radius.md,
|
|
118
|
+
'--pb-radius-lg': radius.lg,
|
|
119
|
+
'--pb-radius-full': radius.full,
|
|
120
|
+
'--pb-shadow-none': shadow.none,
|
|
121
|
+
'--pb-shadow-sm': shadow.sm,
|
|
122
|
+
'--pb-shadow-md': shadow.md,
|
|
123
|
+
'--pb-shadow-lg': shadow.lg,
|
|
124
|
+
'--pb-gutter': tokens.gutter
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/** Gera o bloco `:root { --pb-*: ... }` a partir dos tokens (com defaults). */
|
|
128
|
+
export function buildTokenCss(tokens) {
|
|
129
|
+
const merged = mergeTokens(defaultTokens, tokens);
|
|
130
|
+
const vars = tokenToCssVars(merged);
|
|
131
|
+
const lines = Object.entries(vars)
|
|
132
|
+
.map(([key, value]) => ` ${key}: ${value};`)
|
|
133
|
+
.join('\n');
|
|
134
|
+
return `:root {\n${lines}\n}`;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Retorna o mapa de variáveis `--pb-*` (com defaults mesclados) para aplicação
|
|
138
|
+
* inline em um elemento raiz — permite que a troca de token reflita em tempo
|
|
139
|
+
* real no preview sem reinjetar o `<head>`.
|
|
140
|
+
*/
|
|
141
|
+
export function buildThemeVars(designSystem) {
|
|
142
|
+
const merged = mergeTokens(defaultTokens, designSystem);
|
|
143
|
+
return tokenToCssVars(merged);
|
|
144
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { PbAlert } from '../ui/PbAlert.js';
|
|
4
4
|
import { UseFormStore } from '../stores/UseFormStore.js';
|
|
5
5
|
import { ElementColWrapper } from './ElementColWrapper.js';
|
|
6
6
|
import { getString, getNumber, getBoolean } from '../utils/propertyUtils.js';
|
|
@@ -16,8 +16,8 @@ export function AlertElement({ element, formId }) {
|
|
|
16
16
|
hidden: getBoolean(properties, 'startHidden')
|
|
17
17
|
});
|
|
18
18
|
return () => unregisterElement(element.id);
|
|
19
|
-
}, [element.id, properties.startHidden, registerElement,
|
|
19
|
+
}, [element.id, properties.startHidden, registerElement, unregisterElement, resolvedFormId]);
|
|
20
20
|
if (hidden)
|
|
21
21
|
return null;
|
|
22
|
-
return (_jsx(ElementColWrapper, { element: element, children:
|
|
22
|
+
return (_jsx(ElementColWrapper, { element: element, children: _jsx(PbAlert, { variant: getString(properties, 'type', 'info'), style: element.styles, title: getString(properties, 'title'), children: _jsx("p", { className: "pb-mb-0", children: getString(properties, 'message') }) }) }));
|
|
23
23
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
|
-
import { Button, Spinner } from 'react-bootstrap';
|
|
4
3
|
import { ElementColWrapper } from './ElementColWrapper.js';
|
|
4
|
+
import { PbButton } from '../ui/PbButton.js';
|
|
5
|
+
import { PbSpinner } from '../ui/PbSpinner.js';
|
|
5
6
|
import { UseFormStore } from '../stores/UseFormStore.js';
|
|
6
7
|
import { buttonActionFactory } from '../factories/ButtonActionFactory.js';
|
|
7
8
|
import { ButtonActionEnum } from '../constants/ButtonActionEnum.js';
|
|
@@ -21,7 +22,7 @@ export function ButtonElement({ element, formId }) {
|
|
|
21
22
|
hidden: getBoolean(properties, 'startHidden')
|
|
22
23
|
});
|
|
23
24
|
return () => unregisterElement(element.id);
|
|
24
|
-
}, [element.id, properties.startHidden, registerElement,
|
|
25
|
+
}, [element.id, properties.startHidden, registerElement, unregisterElement, resolvedFormId]);
|
|
25
26
|
async function handleClick(event) {
|
|
26
27
|
var _a, _b, _c;
|
|
27
28
|
if (!properties.path) {
|
|
@@ -70,5 +71,6 @@ export function ButtonElement({ element, formId }) {
|
|
|
70
71
|
? properties.type
|
|
71
72
|
: undefined;
|
|
72
73
|
const size = getString(properties, 'size');
|
|
73
|
-
|
|
74
|
+
const variant = getString(properties, 'variant', buttonType ? 'primary' : getString(properties, 'type', 'primary'));
|
|
75
|
+
return (_jsx(ElementColWrapper, { element: element, children: _jsx(PbButton, { href: getString(properties, 'path') || undefined, target: properties.path ? getString(properties, 'target', '_self') : undefined, type: buttonType, variant: variant, size: size === 'sm' || size === 'lg' ? size : undefined, disabled: loading, onClick: handleClick, style: element.styles, children: loading ? (_jsxs(_Fragment, { children: [_jsx("output", { "aria-busy": "true", children: _jsx(PbSpinner, { size: "sm" }) }), ' ' + getString(properties, 'message')] })) : (getString(properties, 'text') || getString(properties, 'title')) }) }));
|
|
74
76
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { PbCol } from '../ui/PbCol.js';
|
|
3
3
|
export function ElementColWrapper({ element, children }) {
|
|
4
4
|
var _a;
|
|
5
5
|
const style = {};
|
|
@@ -10,5 +10,5 @@ export function ElementColWrapper({ element, children }) {
|
|
|
10
10
|
if ((_a = element.styles) === null || _a === void 0 ? void 0 : _a.textAlign) {
|
|
11
11
|
style.textAlign = element.styles.textAlign;
|
|
12
12
|
}
|
|
13
|
-
return (_jsx(
|
|
13
|
+
return (_jsx(PbCol, { colId: element.id, width: element.width, offset: element.offset, style: style, "data-pb-element": element.id, children: children }));
|
|
14
14
|
}
|
package/dist/elements/IconMap.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FaArrowRight, FaArrowLeft, FaArrowUp, FaArrowDown, FaChevronRight, FaChevronLeft, FaChevronUp, FaChevronDown, FaLongArrowAltRight, FaLongArrowAltLeft, FaBars, FaTimes, FaCheck, FaPlus, FaMinus, FaSearch, FaHome, FaUser, FaUsers, FaCog, FaInfoCircle, FaQuestionCircle, FaExclamationTriangle, FaCheckCircle, FaTimesCircle, FaExternalLinkAlt, FaDownload, FaUpload, FaSync, FaLock, FaUnlock, FaEye, FaEyeSlash, FaBell, FaStar, FaHeart, FaList, FaTh, FaThLarge, FaFilter, FaPhone, FaEnvelope, FaEnvelopeOpen, FaComment, FaComments, FaQuoteLeft, FaQuoteRight, FaPaperPlane, FaFacebookF, FaInstagram, FaWhatsapp, FaYoutube, FaTwitter, FaLinkedinIn, FaPinterestP, FaShoppingCart, FaShoppingBag, FaCreditCard, FaMoneyBillWave, FaTag, FaTags, FaGift, FaTruck, FaMapMarkerAlt, FaMap, FaMapPin, FaGlobe, FaCompass, FaLocationArrow, FaClock, FaCalendar, FaCalendarAlt, FaHourglassHalf, FaImage, FaImages, FaCamera, FaVideo, FaFilm, FaMusic, FaHeadphones, FaPlay, FaBriefcase, FaBuilding, FaChartBar, FaChartLine, FaChartPie, FaRocket, FaLightbulb, FaTrophy, FaMedal, FaFlag, FaFile, FaFolder, FaLink, FaPencilAlt, FaTrashAlt, FaCopy, FaCloud, FaWifi, FaMobileAlt
|
|
1
|
+
import { FaArrowRight, FaArrowLeft, FaArrowUp, FaArrowDown, FaChevronRight, FaChevronLeft, FaChevronUp, FaChevronDown, FaLongArrowAltRight, FaLongArrowAltLeft, FaBars, FaTimes, FaCheck, FaPlus, FaMinus, FaSearch, FaHome, FaUser, FaUsers, FaCog, FaInfoCircle, FaQuestionCircle, FaExclamationTriangle, FaCheckCircle, FaTimesCircle, FaExternalLinkAlt, FaDownload, FaUpload, FaSync, FaLock, FaUnlock, FaEye, FaEyeSlash, FaBell, FaStar, FaHeart, FaList, FaTh, FaThLarge, FaFilter, FaPhone, FaEnvelope, FaEnvelopeOpen, FaComment, FaComments, FaQuoteLeft, FaQuoteRight, FaPaperPlane, FaFacebookF, FaInstagram, FaWhatsapp, FaYoutube, FaTwitter, FaLinkedinIn, FaPinterestP, FaShoppingCart, FaShoppingBag, FaCreditCard, FaMoneyBillWave, FaTag, FaTags, FaGift, FaTruck, FaMapMarkerAlt, FaMap, FaMapPin, FaGlobe, FaCompass, FaLocationArrow, FaClock, FaCalendar, FaCalendarAlt, FaHourglassHalf, FaImage, FaImages, FaCamera, FaVideo, FaFilm, FaMusic, FaHeadphones, FaPlay, FaBriefcase, FaBuilding, FaChartBar, FaChartLine, FaChartPie, FaRocket, FaLightbulb, FaTrophy, FaMedal, FaFlag, FaFile, FaFolder, FaLink, FaPencilAlt, FaTrashAlt, FaCopy, FaCloud, FaWifi, FaMobileAlt } from 'react-icons/fa';
|
|
2
2
|
export const iconMap = {
|
|
3
3
|
'arrow-right': FaArrowRight,
|
|
4
4
|
'arrow-left': FaArrowLeft,
|
|
@@ -99,5 +99,5 @@ export const iconMap = {
|
|
|
99
99
|
copy: FaCopy,
|
|
100
100
|
cloud: FaCloud,
|
|
101
101
|
wifi: FaWifi,
|
|
102
|
-
mobile: FaMobileAlt
|
|
102
|
+
mobile: FaMobileAlt
|
|
103
103
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
|
-
import { Form } from 'react-bootstrap';
|
|
4
3
|
import { IMaskInput } from 'react-imask';
|
|
5
4
|
import { ElementColWrapper } from './ElementColWrapper.js';
|
|
6
5
|
import { UseFormStore } from '../stores/UseFormStore.js';
|
|
@@ -66,12 +65,14 @@ export function InputElement({ element, formId }) {
|
|
|
66
65
|
}
|
|
67
66
|
store.setElementState(element.id, { value: checked ? value : '' });
|
|
68
67
|
};
|
|
68
|
+
const isCheck = element.elementType === ElementTypeEnum.Checkbox || element.elementType === ElementTypeEnum.Radio;
|
|
69
69
|
const renderControl = () => {
|
|
70
|
+
const baseClass = error ? 'pb-form-control-invalid' : '';
|
|
70
71
|
if (element.elementType === ElementTypeEnum.Textarea) {
|
|
71
|
-
return (_jsx("textarea", { defaultValue: getString(properties, 'value'), rows: getNumber(properties, 'rows') || 4, onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, placeholder: getString(properties, 'placeholder'), className: `form-
|
|
72
|
+
return (_jsx("textarea", { defaultValue: getString(properties, 'value'), rows: getNumber(properties, 'rows') || 4, onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, placeholder: getString(properties, 'placeholder'), className: `pb-form-textarea ${baseClass}`.trim(), style: element.styles }));
|
|
72
73
|
}
|
|
73
74
|
if (element.elementType === ElementTypeEnum.Select) {
|
|
74
|
-
return (_jsx("select", { defaultValue: getString(properties, 'value'), onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, className: `form-select${
|
|
75
|
+
return (_jsx("select", { defaultValue: getString(properties, 'value'), onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, className: `pb-form-select ${baseClass}`.trim(), style: element.styles, children: options.map((option, index) => {
|
|
75
76
|
var _a, _b, _c, _d;
|
|
76
77
|
const data = typeof option === 'object' && option !== null ? option : null;
|
|
77
78
|
const value = String((_a = data === null || data === void 0 ? void 0 : data.value) !== null && _a !== void 0 ? _a : option);
|
|
@@ -79,17 +80,17 @@ export function InputElement({ element, formId }) {
|
|
|
79
80
|
return (_jsx("option", { value: value, children: text }, `${value}-${index}`));
|
|
80
81
|
}) }));
|
|
81
82
|
}
|
|
82
|
-
if (
|
|
83
|
+
if (isCheck) {
|
|
83
84
|
const value = getString(properties, 'value', 'on');
|
|
84
|
-
return (_jsxs("div", { className: "form-check", children: [_jsx("input", { id: controlId, type: element.elementType, defaultChecked: getBoolean(properties, 'checked'), value: value, onChange: (e) => setCheckedValue(e.target.checked, value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, className: `form-check-input${error ? '
|
|
85
|
+
return (_jsxs("div", { className: "pb-form-check", children: [_jsx("input", { id: controlId, type: element.elementType, defaultChecked: getBoolean(properties, 'checked'), value: value, onChange: (e) => setCheckedValue(e.target.checked, value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, className: `pb-form-check-input${error ? ' pb-form-check-invalid' : ''}`, style: element.styles }), label && (_jsx("label", { className: "pb-form-check-label", htmlFor: controlId, children: label }))] }));
|
|
85
86
|
}
|
|
86
87
|
if (element.elementType === ElementTypeEnum.File) {
|
|
87
|
-
return (_jsx("div", { className: "alert alert-secondary", role: "status", style: element.styles, children: "File upload not available in this form." }));
|
|
88
|
+
return (_jsx("div", { className: "pb-alert pb-alert-secondary", role: "status", style: element.styles, children: "File upload not available in this form." }));
|
|
88
89
|
}
|
|
89
90
|
if (hasMask) {
|
|
90
|
-
return (_jsx(IMaskInput, { mask: getString(properties, 'mask'), defaultValue: getString(properties, 'value'), onAccept: handleAccept, onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, placeholder: getString(properties, 'placeholder'), className: `form-control${
|
|
91
|
+
return (_jsx(IMaskInput, { mask: getString(properties, 'mask'), defaultValue: getString(properties, 'value'), onAccept: handleAccept, onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, placeholder: getString(properties, 'placeholder'), className: `pb-form-control ${baseClass}`.trim(), style: element.styles }));
|
|
91
92
|
}
|
|
92
|
-
return (_jsx("input", { type: getString(properties, 'type', 'text'), defaultValue: getString(properties, 'value'), onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, placeholder: getString(properties, 'placeholder'), className: `form-control${
|
|
93
|
+
return (_jsx("input", { type: getString(properties, 'type', 'text'), defaultValue: getString(properties, 'value'), onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, placeholder: getString(properties, 'placeholder'), className: `pb-form-control ${baseClass}`.trim(), style: element.styles }));
|
|
93
94
|
};
|
|
94
|
-
return (_jsx(ElementColWrapper, { element: element, children: _jsxs(
|
|
95
|
+
return (_jsx(ElementColWrapper, { element: element, children: _jsxs("div", { className: "pb-form-group", id: controlId, children: [label && !isCheck && (_jsx("label", { className: "pb-form-label", htmlFor: controlId, children: label })), renderControl(), error && (_jsx("div", { className: "pb-invalid-feedback", role: "alert", children: errorMessage }))] }) }));
|
|
95
96
|
}
|
|
@@ -4,10 +4,14 @@ import { ElementColWrapper } from './ElementColWrapper.js';
|
|
|
4
4
|
export function TextElement({ element }) {
|
|
5
5
|
const properties = element.properties;
|
|
6
6
|
const text = String(properties.text || properties.title || properties.message || '');
|
|
7
|
+
const isSimple = properties.editorType === 'simple';
|
|
7
8
|
if (element.elementType === 'title') {
|
|
8
9
|
const tag = String(properties.tag || 'h2');
|
|
9
10
|
const TitleTag = tag;
|
|
10
11
|
return (_jsx(ElementColWrapper, { element: element, children: _jsx(TitleTag, { style: Object.assign({ margin: 0 }, element.styles), children: text }) }));
|
|
11
12
|
}
|
|
13
|
+
if (isSimple) {
|
|
14
|
+
return (_jsx(ElementColWrapper, { element: element, children: _jsx("div", { style: Object.assign({ whiteSpace: 'pre-wrap' }, element.styles), children: text }) }));
|
|
15
|
+
}
|
|
12
16
|
return (_jsx(ElementColWrapper, { element: element, children: _jsx("div", { dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(text) }, style: element.styles }) }));
|
|
13
17
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ComponentType } from '../types/ComponentType.js';
|
|
3
|
+
import type { ComponentDefaults } from '../types/WebsiteType.js';
|
|
3
4
|
export declare class ComponentFactory {
|
|
4
|
-
build(component: ComponentType, editionMode?: boolean): React.ReactElement | null;
|
|
5
|
+
build(component: ComponentType, editionMode?: boolean, defaults?: ComponentDefaults): React.ReactElement | null;
|
|
5
6
|
}
|
|
@@ -8,32 +8,46 @@ import { SliderComponent } from '../components/SliderComponent.js';
|
|
|
8
8
|
import { CardComponent } from '../components/CardComponent.js';
|
|
9
9
|
import { MapComponent } from '../components/MapComponent.js';
|
|
10
10
|
import { ButtonsComponent } from '../components/ButtonsComponent.js';
|
|
11
|
+
import { IconComponent } from '../components/IconComponent.js';
|
|
12
|
+
/**
|
|
13
|
+
* Aplica os estilos padrão do design system (`componentDefaults`) antes dos
|
|
14
|
+
* estilos da instância — o override da instância prevalece.
|
|
15
|
+
*/
|
|
16
|
+
function applyDefaults(component, defaults) {
|
|
17
|
+
const typeDefaults = defaults === null || defaults === void 0 ? void 0 : defaults[component.componentType];
|
|
18
|
+
if (!typeDefaults || Object.keys(typeDefaults).length === 0)
|
|
19
|
+
return component;
|
|
20
|
+
return Object.assign(Object.assign({}, component), { styles: Object.assign(Object.assign({}, typeDefaults), component.styles) });
|
|
21
|
+
}
|
|
11
22
|
export class ComponentFactory {
|
|
12
|
-
build(component, editionMode = false) {
|
|
13
|
-
|
|
23
|
+
build(component, editionMode = false, defaults) {
|
|
24
|
+
const resolved = applyDefaults(component, defaults);
|
|
25
|
+
switch (resolved.componentType) {
|
|
14
26
|
case ComponentTypeEnum.Text:
|
|
15
27
|
case ComponentTypeEnum.TextWithImage:
|
|
16
28
|
case ComponentTypeEnum.HeroBanner:
|
|
17
|
-
return _jsx(TextComponent, { component:
|
|
29
|
+
return _jsx(TextComponent, { component: resolved }, resolved.id);
|
|
18
30
|
case ComponentTypeEnum.Image:
|
|
19
|
-
return _jsx(ImageComponent, { component:
|
|
31
|
+
return _jsx(ImageComponent, { component: resolved }, resolved.id);
|
|
20
32
|
case ComponentTypeEnum.List:
|
|
21
|
-
return _jsx(ListComponent, { component:
|
|
33
|
+
return _jsx(ListComponent, { component: resolved }, resolved.id);
|
|
22
34
|
case ComponentTypeEnum.Slider:
|
|
23
35
|
case ComponentTypeEnum.Gallery:
|
|
24
36
|
case ComponentTypeEnum.Testimonials:
|
|
25
|
-
return _jsx(SliderComponent, { component:
|
|
37
|
+
return _jsx(SliderComponent, { component: resolved, editionMode: editionMode }, resolved.id);
|
|
26
38
|
case ComponentTypeEnum.Form:
|
|
27
|
-
return _jsx(FormComponent, { component:
|
|
39
|
+
return _jsx(FormComponent, { component: resolved }, resolved.id);
|
|
28
40
|
case ComponentTypeEnum.Card:
|
|
29
41
|
case ComponentTypeEnum.Faq:
|
|
30
|
-
return _jsx(CardComponent, { component:
|
|
42
|
+
return _jsx(CardComponent, { component: resolved }, resolved.id);
|
|
31
43
|
case ComponentTypeEnum.Map:
|
|
32
|
-
return _jsx(MapComponent, { component:
|
|
44
|
+
return _jsx(MapComponent, { component: resolved }, resolved.id);
|
|
33
45
|
case ComponentTypeEnum.Buttons:
|
|
34
|
-
return _jsx(ButtonsComponent, { component:
|
|
46
|
+
return _jsx(ButtonsComponent, { component: resolved }, resolved.id);
|
|
47
|
+
case ComponentTypeEnum.Icon:
|
|
48
|
+
return _jsx(IconComponent, { component: resolved }, resolved.id);
|
|
35
49
|
default:
|
|
36
|
-
throw new Error('Invalid component type: ' +
|
|
50
|
+
throw new Error('Invalid component type: ' + resolved.componentType);
|
|
37
51
|
}
|
|
38
52
|
}
|
|
39
53
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export type { RawWebsiteType } from './types/RawWebsiteType.js';
|
|
2
2
|
export type { WebsiteType } from './types/WebsiteType.js';
|
|
3
3
|
export type { PageType } from './types/PageType.js';
|
|
4
|
-
export type {
|
|
5
|
-
export type { SectionColumnType } from './types/SectionColumnType.js';
|
|
4
|
+
export type { BlockType } from './types/BlockType.js';
|
|
6
5
|
export type { ColumnWidthType } from './types/ColumnWidthType.js';
|
|
7
6
|
export type { ComponentType } from './types/ComponentType.js';
|
|
8
7
|
export type { ElementType } from './types/ElementType.js';
|
|
@@ -12,7 +11,8 @@ export { Header } from './layouts/Header.js';
|
|
|
12
11
|
export { Footer } from './layouts/Footer.js';
|
|
13
12
|
export { SiteLayout, type EmailApiConfig } from './layouts/SiteLayout.js';
|
|
14
13
|
export { PageBuilder } from './builders/PageBuilder.js';
|
|
15
|
-
export {
|
|
14
|
+
export { BlockRenderer } from './renderers/BlockRenderer.js';
|
|
15
|
+
export { IconComponent } from './components/IconComponent.js';
|
|
16
16
|
export { LoadingComponent } from './components/LoadingComponent.js';
|
|
17
17
|
export { ComponentFactory } from './factories/ComponentFactory.js';
|
|
18
18
|
export { ElementFactory } from './factories/ElementFactory.js';
|
|
@@ -24,3 +24,15 @@ export { analyticsService } from './services/AnalyticsService.js';
|
|
|
24
24
|
export { buttonActionFactory } from './factories/ButtonActionFactory.js';
|
|
25
25
|
export type { EmailServiceConfig, EmailSendOptions } from './services/EmailService.js';
|
|
26
26
|
export type { EmailSettingsType } from './types/EmailSettingsType.js';
|
|
27
|
+
export type { DesignTokens, DesignColors, DesignTypography, DesignSpacing, DesignRadius, DesignShadow, PartialDesignTokens, DeepPartial } from './designSystem/tokens.js';
|
|
28
|
+
export { defaultTokens, mergeTokens, tokenToCssVars, buildTokenCss, buildThemeVars } from './designSystem/tokens.js';
|
|
29
|
+
export { baseCss } from './designSystem/baseCss.js';
|
|
30
|
+
export { buildSiteCss } from './designSystem/buildSiteCss.js';
|
|
31
|
+
export { themeVarsStyle } from './designSystem/themeVars.js';
|
|
32
|
+
export { ThemeStyle } from './designSystem/theme.js';
|
|
33
|
+
export { PbContainer } from './ui/PbContainer.js';
|
|
34
|
+
export { PbRow } from './ui/PbRow.js';
|
|
35
|
+
export { PbCol } from './ui/PbCol.js';
|
|
36
|
+
export { PbButton } from './ui/PbButton.js';
|
|
37
|
+
export { PbSpinner } from './ui/PbSpinner.js';
|
|
38
|
+
export { PbAlert } from './ui/PbAlert.js';
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,8 @@ 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';
|
|
@@ -12,3 +13,14 @@ export { ElementTypeEnum } from './constants/ElementEnum.js';
|
|
|
12
13
|
export { ButtonActionEnum } from './constants/ButtonActionEnum.js';
|
|
13
14
|
export { analyticsService } from './services/AnalyticsService.js';
|
|
14
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,11 +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
8
|
const location = useLocation();
|
|
9
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
9
10
|
const menuPages = useMemo(() => (website.pages || []).filter((p) => p.menu === true).sort((a, b) => (a.menuOrder || 0) - (b.menuOrder || 0)), [website.pages]);
|
|
10
11
|
const isActive = useCallback((path) => {
|
|
11
12
|
const currentPath = location.pathname;
|
|
@@ -18,6 +19,7 @@ export function Header({ website, imageBaseUrl }) {
|
|
|
18
19
|
const logoAlign = headerProperties.logoAlign || 'center';
|
|
19
20
|
const menuLinkColor = headerStyles.menuLinkColor || headerStyles.color || undefined;
|
|
20
21
|
const menuActiveLinkColor = headerStyles.menuActiveLinkColor || headerStyles.menuLinkColor || headerStyles.color || undefined;
|
|
22
|
+
const textAlign = headerStyles.textAlign || 'left';
|
|
21
23
|
const brandStyle = { padding: 0 };
|
|
22
24
|
if (showMenu) {
|
|
23
25
|
if (logoAlign === 'right')
|
|
@@ -36,17 +38,24 @@ export function Header({ website, imageBaseUrl }) {
|
|
|
36
38
|
else if (logoAlign === 'right') {
|
|
37
39
|
brandStyle.marginLeft = 'auto';
|
|
38
40
|
}
|
|
39
|
-
|
|
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) => {
|
|
40
51
|
const active = isActive(p.path);
|
|
41
|
-
return (_jsx(
|
|
52
|
+
return (_jsx("a", { href: p.path, onClick: closeMenu, className: `pb-nav-link${active ? ' pb-nav-link-active' : ''}`, style: {
|
|
42
53
|
color: active ? menuActiveLinkColor : menuLinkColor,
|
|
43
54
|
fontSize: headerStyles.menuFontSize || undefined,
|
|
44
55
|
letterSpacing: headerStyles.menuLetterSpacing || undefined,
|
|
45
56
|
textTransform: headerStyles.menuTextTransform || undefined,
|
|
46
57
|
margin: '0 12px',
|
|
47
|
-
paddingBottom: '4px'
|
|
48
|
-
borderBottom: active && menuActiveLinkColor ? `2px solid ${menuActiveLinkColor}` : '2px solid transparent',
|
|
49
|
-
transition: 'color 0.3s, border-color 0.3s',
|
|
58
|
+
paddingBottom: '4px'
|
|
50
59
|
}, children: p.title }, p.id));
|
|
51
|
-
}) }) })] })
|
|
60
|
+
}) })] }))] }) }) }));
|
|
52
61
|
}
|
|
@@ -4,6 +4,7 @@ import { Outlet } from 'react-router-dom';
|
|
|
4
4
|
import { Helmet } from 'react-helmet-async';
|
|
5
5
|
import { Header } from './Header.js';
|
|
6
6
|
import { Footer } from './Footer.js';
|
|
7
|
+
import { ThemeStyle } from '../designSystem/theme.js';
|
|
7
8
|
import { buildFontFamily, buildGoogleFontsHref } from '../utils/fonts.js';
|
|
8
9
|
import { buttonActionFactory } from '../factories/ButtonActionFactory.js';
|
|
9
10
|
export function SiteLayout({ website, imageBaseUrl, emailApi }) {
|
|
@@ -35,5 +36,5 @@ export function SiteLayout({ website, imageBaseUrl, emailApi }) {
|
|
|
35
36
|
(_f = (_e = website.properties) === null || _e === void 0 ? void 0 : _e.email) === null || _f === void 0 ? void 0 : _f.recipientName,
|
|
36
37
|
(_h = (_g = website.properties) === null || _g === void 0 ? void 0 : _g.email) === null || _h === void 0 ? void 0 : _h.subject
|
|
37
38
|
]);
|
|
38
|
-
return (_jsxs(_Fragment, { children: [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", style: { backgroundColor: website.styles.backgroundColor, color: website.styles.color, fontFamily }, children: [_jsx(Header, { website: website, imageBaseUrl: imageBaseUrl }), _jsx(Outlet, {}), _jsx(Footer, { website: website })] })] }));
|
|
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 })] })] }));
|
|
39
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 };
|
|
@@ -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
|
}
|