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.
Files changed (98) hide show
  1. package/dist/builders/PageBuilder.js +42 -26
  2. package/dist/components/ButtonsComponent.d.ts +5 -0
  3. package/dist/components/ButtonsComponent.js +45 -0
  4. package/dist/components/CardComponent.js +31 -6
  5. package/dist/components/FormComponent.js +9 -4
  6. package/dist/components/{CarouselComponent.d.ts → IconComponent.d.ts} +3 -2
  7. package/dist/components/IconComponent.js +12 -0
  8. package/dist/components/ImageComponent.d.ts +5 -0
  9. package/dist/components/ImageComponent.js +18 -0
  10. package/dist/components/ListComponent.js +5 -2
  11. package/dist/components/LoadingComponent.js +2 -2
  12. package/dist/components/MapComponent.js +11 -12
  13. package/dist/components/SliderComponent.d.ts +0 -1
  14. package/dist/components/SliderComponent.js +173 -93
  15. package/dist/components/SocialIconsComponent.d.ts +3 -2
  16. package/dist/components/SocialIconsComponent.js +20 -16
  17. package/dist/components/TextComponent.js +5 -3
  18. package/dist/constants/ComponentEnum.d.ts +2 -0
  19. package/dist/constants/ComponentEnum.js +2 -0
  20. package/dist/designSystem/baseCss.d.ts +8 -0
  21. package/dist/designSystem/baseCss.js +406 -0
  22. package/dist/designSystem/buildSiteCss.d.ts +8 -0
  23. package/dist/designSystem/buildSiteCss.js +11 -0
  24. package/dist/designSystem/index.d.ts +6 -0
  25. package/dist/designSystem/index.js +5 -0
  26. package/dist/designSystem/theme.d.ts +9 -0
  27. package/dist/designSystem/theme.js +11 -0
  28. package/dist/designSystem/themeVars.d.ts +8 -0
  29. package/dist/designSystem/themeVars.js +9 -0
  30. package/dist/designSystem/tokens.d.ts +82 -0
  31. package/dist/designSystem/tokens.js +144 -0
  32. package/dist/elements/AlertElement.js +4 -4
  33. package/dist/elements/ButtonElement.js +21 -7
  34. package/dist/elements/ElementColWrapper.js +11 -2
  35. package/dist/elements/IconElement.js +5 -5
  36. package/dist/elements/IconMap.js +101 -28
  37. package/dist/elements/InputElement.js +10 -9
  38. package/dist/elements/TextElement.js +5 -1
  39. package/dist/factories/ButtonActionFactory.d.ts +3 -4
  40. package/dist/factories/ButtonActionFactory.js +2 -2
  41. package/dist/factories/ComponentFactory.d.ts +2 -1
  42. package/dist/factories/ComponentFactory.js +29 -12
  43. package/dist/index.d.ts +20 -5
  44. package/dist/index.js +15 -1
  45. package/dist/layouts/Footer.js +13 -2
  46. package/dist/layouts/Header.js +43 -16
  47. package/dist/layouts/SiteLayout.d.ts +8 -1
  48. package/dist/layouts/SiteLayout.js +36 -3
  49. package/dist/renderers/BlockRenderer.d.ts +8 -0
  50. package/dist/renderers/BlockRenderer.js +68 -0
  51. package/dist/services/EmailService.d.ts +14 -5
  52. package/dist/services/EmailService.js +21 -24
  53. package/dist/stores/UseFormStore.d.ts +7 -2
  54. package/dist/stores/UseFormStore.js +8 -3
  55. package/dist/types/{SectionColumnType.d.ts → BlockType.d.ts} +2 -6
  56. package/dist/types/ComponentType.d.ts +3 -0
  57. package/dist/types/ElementType.d.ts +1 -0
  58. package/dist/types/EmailSettingsType.d.ts +5 -0
  59. package/dist/types/HeaderPropertiesType.d.ts +1 -0
  60. package/dist/types/MailBodyType.d.ts +2 -0
  61. package/dist/types/PageType.d.ts +2 -2
  62. package/dist/types/SocialPropertiesType.d.ts +3 -11
  63. package/dist/types/StylesType.d.ts +12 -0
  64. package/dist/types/WebsitePropertiesType.d.ts +2 -0
  65. package/dist/types/WebsiteType.d.ts +6 -0
  66. package/dist/ui/PbAlert.d.ts +10 -0
  67. package/dist/ui/PbAlert.js +8 -0
  68. package/dist/ui/PbButton.d.ts +20 -0
  69. package/dist/ui/PbButton.js +20 -0
  70. package/dist/ui/PbCol.d.ts +14 -0
  71. package/dist/ui/PbCol.js +43 -0
  72. package/dist/ui/PbContainer.d.ts +7 -0
  73. package/dist/ui/PbContainer.js +17 -0
  74. package/dist/ui/PbRow.d.ts +7 -0
  75. package/dist/ui/PbRow.js +17 -0
  76. package/dist/ui/PbSpinner.d.ts +3 -0
  77. package/dist/ui/PbSpinner.js +5 -0
  78. package/dist/ui/index.d.ts +6 -0
  79. package/dist/ui/index.js +6 -0
  80. package/dist/utils/emailTemplate.d.ts +7 -0
  81. package/dist/utils/emailTemplate.js +66 -0
  82. package/dist/utils/fonts.d.ts +2 -0
  83. package/dist/utils/fonts.js +10 -0
  84. package/dist/utils/imageCustomization.d.ts +3 -0
  85. package/dist/utils/imageCustomization.js +9 -0
  86. package/dist/utils/responsiveProperties.d.ts +2 -0
  87. package/dist/utils/responsiveProperties.js +28 -0
  88. package/dist/utils/responsiveStyles.d.ts +6 -0
  89. package/dist/utils/responsiveStyles.js +73 -0
  90. package/package.json +1 -8
  91. package/dist/components/CarouselComponent.js +0 -6
  92. package/dist/layouts/Menu.d.ts +0 -5
  93. package/dist/layouts/Menu.js +0 -34
  94. package/dist/renderers/SectionRenderer.d.ts +0 -6
  95. package/dist/renderers/SectionRenderer.js +0 -73
  96. package/dist/types/SectionType.d.ts +0 -10
  97. /package/dist/types/{SectionColumnType.js → BlockType.js} +0 -0
  98. /package/dist/types/{SectionType.js → EmailSettingsType.js} +0 -0
@@ -1,109 +1,189 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useState } from 'react';
3
- import { useKeenSlider } from 'keen-slider/react.js';
2
+ import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
4
3
  import { ElementFactory } from '../factories/ElementFactory.js';
5
4
  import { orderBySort } from '../utils/orderBySort.js';
6
- import 'keen-slider/keen-slider.min.css';
5
+ import { resolveResponsiveProperties, breakpointFromWidth } from '../utils/responsiveProperties.js';
7
6
  const elementFactory = new ElementFactory();
8
7
  function cleanComponentStyles(styles) {
9
8
  const exclude = new Set(['minHeight', 'display', 'alignItems', 'justifyContent', 'flexDirection']);
10
9
  return Object.fromEntries(Object.entries(styles).filter(([key]) => !exclude.has(key)));
11
10
  }
12
- function StaticSliderComponent({ component }) {
13
- const firstSlide = orderBySort(component.elements)[0];
14
- if (!firstSlide)
15
- return null;
16
- return (_jsx("div", { style: Object.assign({ position: 'relative', overflow: 'hidden' }, cleanComponentStyles(component.styles)), children: elementFactory.build(firstSlide) }));
11
+ function buildSlide(element, fixedHeight, sharedImageStyles, useSharedImages) {
12
+ const isImage = element.elementType === 'image' || element.elementType === 'video';
13
+ if (isImage) {
14
+ const base = fixedHeight ? { width: '100%', height: '100%', objectFit: 'cover' } : { width: '100%' };
15
+ const override = useSharedImages ? sharedImageStyles || {} : element.styles;
16
+ return elementFactory.build(Object.assign(Object.assign({}, element), { styles: Object.assign(Object.assign({}, base), override) }));
17
+ }
18
+ return elementFactory.build(Object.assign(Object.assign({}, element), { styles: element.styles }));
17
19
  }
18
- function InteractiveSliderComponent({ component }) {
20
+ function resolveChromeColors(properties) {
21
+ return {
22
+ arrowBackground: String(properties.arrowBackground || 'rgba(0,0,0,0.45)'),
23
+ arrowColor: String(properties.arrowColor || '#fff'),
24
+ arrowSize: Number(properties.arrowSize) || 40,
25
+ dotActiveBackground: String(properties.dotActiveBackground || '#333'),
26
+ dotBackground: String(properties.dotBackground || 'rgba(0,0,0,0.15)'),
27
+ dotActiveColor: String(properties.dotActiveColor || '#fff'),
28
+ dotColor: String(properties.dotColor || '#666'),
29
+ dotSize: Number(properties.dotSize) || 28
30
+ };
31
+ }
32
+ const ARROW_BASE_STYLE = {
33
+ position: 'absolute',
34
+ top: '50%',
35
+ transform: 'translateY(-50%)',
36
+ zIndex: 10,
37
+ borderRadius: '50%',
38
+ border: 'none',
39
+ fontSize: 18,
40
+ fontWeight: 700,
41
+ lineHeight: 1,
42
+ cursor: 'pointer',
43
+ display: 'flex',
44
+ alignItems: 'center',
45
+ justifyContent: 'center',
46
+ transition: 'background 0.2s'
47
+ };
48
+ function ArrowButton({ side, size, background, color, onClick }) {
49
+ return (_jsx("button", { type: "button", "aria-label": side === 'left' ? 'Slide anterior' : 'Próximo slide', onClick: onClick, style: Object.assign(Object.assign({}, ARROW_BASE_STYLE), { [side]: 8, width: size, height: size, background, color }), children: _jsx("svg", { width: "10", height: "16", viewBox: "0 0 10 16", fill: "none", children: _jsx("path", { d: side === 'left' ? 'M8.5 1L1.5 8L8.5 15' : 'M1.5 1L8.5 8L1.5 15', stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
50
+ }
51
+ function Dots({ count, current, size, activeBackground, background, activeColor, color, onGoTo }) {
52
+ return (_jsx("div", { "aria-label": "Navega\u00E7\u00E3o do slider", style: { display: 'flex', justifyContent: 'center', gap: 6, marginTop: 12 }, children: Array.from({ length: count }).map((_, index) => (_jsx("button", { type: "button", "aria-label": `Ir para o slide ${index + 1}`, "aria-current": current === index ? 'true' : undefined, onClick: () => onGoTo(index), style: {
53
+ width: size,
54
+ height: size,
55
+ borderRadius: '50%',
56
+ border: 'none',
57
+ background: current === index ? activeBackground : background,
58
+ color: current === index ? activeColor : color,
59
+ fontSize: 12,
60
+ fontWeight: 600,
61
+ lineHeight: 1,
62
+ cursor: 'pointer',
63
+ display: 'flex',
64
+ alignItems: 'center',
65
+ justifyContent: 'center',
66
+ transition: 'all 0.2s'
67
+ }, children: index + 1 }, index))) }));
68
+ }
69
+ function useSliderWidth(ref) {
70
+ const [width, setWidth] = useState(0);
71
+ useLayoutEffect(() => {
72
+ const el = ref.current;
73
+ if (!el)
74
+ return;
75
+ const measure = () => setWidth(el.getBoundingClientRect().width);
76
+ measure();
77
+ const observer = new ResizeObserver(measure);
78
+ observer.observe(el);
79
+ return () => observer.disconnect();
80
+ }, [ref]);
81
+ return width;
82
+ }
83
+ export function SliderComponent({ component, editionMode = false }) {
19
84
  const properties = component.properties || {};
20
85
  const slides = orderBySort(component.elements);
21
- const [currentSlide, setCurrentSlide] = useState(0);
22
- const [loaded, setLoaded] = useState(false);
23
- const [ref, instanceRef] = useKeenSlider({
24
- loop: slides.length > 1,
25
- mode: 'snap',
26
- slides: { perView: Number(properties.perView) || 1, spacing: 10 },
27
- created() {
28
- setLoaded(true);
29
- },
30
- slideChanged(slider) {
31
- setCurrentSlide(slider.track.details.rel);
32
- }
33
- });
86
+ const n = slides.length;
87
+ const containerRef = useRef(null);
88
+ const width = useSliderWidth(containerRef);
89
+ const breakpoint = breakpointFromWidth(width);
90
+ const resolved = useMemo(() => resolveResponsiveProperties(properties, breakpoint), [properties, breakpoint]);
91
+ const perView = Math.max(1, Number(resolved.perView) || 1);
92
+ const spacing = Number(resolved.spacing) > 0 ? Number(resolved.spacing) : 10;
93
+ const fixedHeight = Number(resolved.height) > 0 ? Number(resolved.height) : 0;
94
+ const loop = resolved.loop === undefined ? n > 1 : Boolean(resolved.loop);
95
+ const slideWidth = width > 0 ? (width - spacing * (perView - 1)) / perView : 0;
96
+ const slideStep = slideWidth + spacing;
97
+ const maxIndex = Math.max(0, n - perView);
98
+ const [index, setIndex] = useState(loop ? n : 0);
99
+ const [animate, setAnimate] = useState(false);
100
+ const [dragging, setDragging] = useState(false);
101
+ const dragRef = useRef(null);
102
+ const currentIndex = loop ? ((Math.round(index) % n) + n) % n : Math.min(Math.max(0, Math.round(index)), maxIndex);
34
103
  useEffect(() => {
35
- if (!properties.autoplay || slides.length < 2)
104
+ if (editionMode || !resolved.autoplay || n <= 1)
36
105
  return;
37
- const interval = Number(properties.interval) > 0 ? Number(properties.interval) : 5000;
38
- const timer = window.setInterval(() => { var _a; return (_a = instanceRef.current) === null || _a === void 0 ? void 0 : _a.moveToIdx(instanceRef.current.track.details.rel + 1); }, interval);
106
+ const interval = Number(resolved.interval) > 0 ? Number(resolved.interval) : 5000;
107
+ const timer = window.setInterval(() => {
108
+ setAnimate(true);
109
+ setIndex((prev) => prev + 1);
110
+ }, interval);
39
111
  return () => window.clearInterval(timer);
40
- }, [instanceRef, properties.autoplay, properties.interval, slides.length]);
41
- const fixedHeight = Number(properties.height) > 0 ? Number(properties.height) : 0;
42
- const perView = Number(properties.perView) || 1;
43
- const showArrows = Boolean(properties.showArrows) && loaded && slides.length > perView;
44
- const showDots = Boolean(properties.showDots) && loaded && slides.length > 1;
45
- return (_jsxs("div", { style: Object.assign({ position: 'relative' }, cleanComponentStyles(component.styles)), children: [_jsx("div", { ref: ref, className: "keen-slider", style: fixedHeight ? { height: fixedHeight } : undefined, children: slides.map((element) => (_jsx("div", { className: "keen-slider__slide", style: { overflow: 'hidden' }, children: elementFactory.build(Object.assign(Object.assign({}, element), { styles: element.elementType === 'image' || element.elementType === 'video'
46
- ? fixedHeight
47
- ? Object.assign({ width: '100%', height: '100%', objectFit: 'cover' }, element.styles) : Object.assign({ width: '100%' }, element.styles)
48
- : element.styles })) }, element.id))) }), showArrows && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "aria-label": "Slide anterior", onClick: () => { var _a; return (_a = instanceRef.current) === null || _a === void 0 ? void 0 : _a.moveToIdx(instanceRef.current.track.details.rel - 1); }, style: {
49
- position: 'absolute',
50
- left: 8,
51
- top: '50%',
52
- transform: 'translateY(-50%)',
53
- zIndex: 10,
54
- width: 40,
55
- height: 40,
56
- borderRadius: '50%',
57
- border: 'none',
58
- background: 'rgba(0,0,0,0.45)',
59
- color: '#fff',
60
- fontSize: 18,
61
- fontWeight: 700,
62
- lineHeight: 1,
63
- cursor: 'pointer',
64
- display: 'flex',
65
- alignItems: 'center',
66
- justifyContent: 'center',
67
- transition: 'background 0.2s'
68
- }, children: _jsx("svg", { width: "10", height: "16", viewBox: "0 0 10 16", fill: "none", children: _jsx("path", { d: "M8.5 1L1.5 8L8.5 15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsx("button", { type: "button", "aria-label": "Proximo slide", onClick: () => { var _a; return (_a = instanceRef.current) === null || _a === void 0 ? void 0 : _a.moveToIdx(instanceRef.current.track.details.rel + 1); }, style: {
69
- position: 'absolute',
70
- right: 8,
71
- top: '50%',
72
- transform: 'translateY(-50%)',
73
- zIndex: 10,
74
- width: 40,
75
- height: 40,
76
- borderRadius: '50%',
77
- border: 'none',
78
- background: 'rgba(0,0,0,0.45)',
79
- color: '#fff',
80
- fontSize: 18,
81
- fontWeight: 700,
82
- lineHeight: 1,
83
- cursor: 'pointer',
84
- display: 'flex',
85
- alignItems: 'center',
86
- justifyContent: 'center',
87
- transition: 'background 0.2s'
88
- }, children: _jsx("svg", { width: "10", height: "16", viewBox: "0 0 10 16", fill: "none", children: _jsx("path", { d: "M1.5 1L8.5 8L1.5 15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })), showDots && (_jsx("div", { "aria-label": "Navegacao do slider", style: { display: 'flex', justifyContent: 'center', gap: 6, marginTop: 12 }, children: slides.map((element, index) => (_jsx("button", { type: "button", "aria-label": `Ir para o slide ${index + 1}`, "aria-current": currentSlide === index ? 'true' : undefined, onClick: () => { var _a; return (_a = instanceRef.current) === null || _a === void 0 ? void 0 : _a.moveToIdx(index); }, style: {
89
- width: 28,
90
- height: 28,
91
- borderRadius: '50%',
92
- border: 'none',
93
- background: currentSlide === index ? '#333' : 'rgba(0,0,0,0.15)',
94
- color: currentSlide === index ? '#fff' : '#666',
95
- fontSize: 12,
96
- fontWeight: 600,
97
- lineHeight: 1,
98
- cursor: 'pointer',
112
+ }, [editionMode, resolved.autoplay, resolved.interval, n]);
113
+ const snapToRange = (value) => {
114
+ if (!loop)
115
+ return value;
116
+ if (value >= 2 * n)
117
+ return value - n;
118
+ if (value < n)
119
+ return value + n;
120
+ return value;
121
+ };
122
+ const handleTransitionEnd = () => {
123
+ if (!loop || dragging)
124
+ return;
125
+ const snapped = snapToRange(index);
126
+ if (snapped !== index) {
127
+ setAnimate(false);
128
+ setIndex(snapped);
129
+ }
130
+ };
131
+ const goTo = (i) => {
132
+ const target = loop ? i : Math.min(Math.max(0, i), maxIndex);
133
+ setAnimate(true);
134
+ setIndex(target);
135
+ };
136
+ const goToDot = (i) => {
137
+ const target = loop ? n + i : Math.min(Math.max(0, i), maxIndex);
138
+ let delta = target - index;
139
+ if (loop) {
140
+ if (delta > n / 2)
141
+ delta -= n;
142
+ else if (delta < -n / 2)
143
+ delta += n;
144
+ }
145
+ setAnimate(true);
146
+ setIndex(index + delta);
147
+ };
148
+ const onPointerDown = (e) => {
149
+ if (n <= 1)
150
+ return;
151
+ dragRef.current = { startX: e.clientX, startIndex: index };
152
+ e.currentTarget.setPointerCapture(e.pointerId);
153
+ setDragging(true);
154
+ setAnimate(false);
155
+ };
156
+ const onPointerMove = (e) => {
157
+ const drag = dragRef.current;
158
+ if (!drag || slideStep <= 0)
159
+ return;
160
+ setIndex(drag.startIndex - (e.clientX - drag.startX) / slideStep);
161
+ };
162
+ const endDrag = () => {
163
+ if (!dragRef.current)
164
+ return;
165
+ dragRef.current = null;
166
+ setDragging(false);
167
+ setIndex((prev) => {
168
+ const rounded = Math.round(prev);
169
+ return loop ? snapToRange(rounded) : Math.min(Math.max(0, rounded), maxIndex);
170
+ });
171
+ setAnimate(true);
172
+ };
173
+ const translateX = -(index * slideStep);
174
+ const trackSlides = loop ? [...slides, ...slides, ...slides] : slides;
175
+ const showArrows = Boolean(resolved.showArrows) && n > perView;
176
+ const showDots = Boolean(resolved.showDots) && n > 1;
177
+ const chrome = resolveChromeColors(resolved);
178
+ const useSharedImages = resolved.imageCustomization !== 'separate';
179
+ const sharedImageStyles = resolved.imageStyles || {};
180
+ return (_jsxs("div", { ref: containerRef, "data-pb-component": component.id, style: Object.assign({ position: 'relative' }, cleanComponentStyles(component.styles)), children: [_jsx("div", { style: Object.assign({ overflow: 'hidden' }, (fixedHeight ? { height: fixedHeight } : {})), children: _jsx("div", { style: {
99
181
  display: 'flex',
100
- alignItems: 'center',
101
- justifyContent: 'center',
102
- transition: 'all 0.2s'
103
- }, children: index + 1 }, element.id))) }))] }));
104
- }
105
- export function SliderComponent({ component, editionMode = false }) {
106
- if (editionMode)
107
- return _jsx(StaticSliderComponent, { component: component });
108
- return _jsx(InteractiveSliderComponent, { component: component });
182
+ columnGap: spacing,
183
+ transform: `translateX(${translateX}px)`,
184
+ transition: animate && !dragging ? 'transform 0.3s ease' : 'none',
185
+ cursor: dragging ? 'grabbing' : n > 1 ? 'grab' : 'default',
186
+ touchAction: 'pan-y',
187
+ userSelect: 'none'
188
+ }, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: endDrag, onPointerCancel: endDrag, onTransitionEnd: handleTransitionEnd, children: trackSlides.map((element, i) => (_jsx("div", { style: { width: slideWidth, flexShrink: 0, overflow: 'hidden' }, children: buildSlide(element, fixedHeight, sharedImageStyles, useSharedImages) }, `${element.id}-${i}`))) }) }), showArrows && (_jsxs(_Fragment, { children: [_jsx(ArrowButton, { side: "left", size: chrome.arrowSize, background: chrome.arrowBackground, color: chrome.arrowColor, onClick: () => goTo(index - 1) }), _jsx(ArrowButton, { side: "right", size: chrome.arrowSize, background: chrome.arrowBackground, color: chrome.arrowColor, onClick: () => goTo(index + 1) })] })), showDots && (_jsx(Dots, { count: n, current: currentIndex, size: chrome.dotSize, activeBackground: chrome.dotActiveBackground, background: chrome.dotBackground, activeColor: chrome.dotActiveColor, color: chrome.dotColor, onGoTo: goToDot }))] }));
109
189
  }
@@ -1,4 +1,5 @@
1
1
  import type { SocialPropertiesType } from '../types/SocialPropertiesType.js';
2
- export declare function SocialIconsComponent({ social }: {
3
- readonly social: SocialPropertiesType;
2
+ export declare function SocialIconsComponent({ social, color }: {
3
+ readonly social?: SocialPropertiesType;
4
+ readonly color?: string;
4
5
  }): import("react").JSX.Element;
@@ -1,19 +1,23 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Row, Col } from 'react-bootstrap';
3
- import { FaFacebookF, FaInstagram, FaLink } from 'react-icons/fa';
4
- export function SocialIconsComponent({ social }) {
5
- var _a, _b, _c;
6
- const all = [];
7
- if ((_a = social.facebook) === null || _a === void 0 ? void 0 : _a.path) {
8
- all.push({ id: 'facebook', url: social.facebook.path, icon: FaFacebookF, description: 'Logo do Facebook' });
9
- }
10
- if ((_b = social.instagram) === null || _b === void 0 ? void 0 : _b.path) {
11
- all.push({ id: 'instagram', url: social.instagram.path, icon: FaInstagram, description: 'Logo do Instagram' });
12
- }
13
- if ((_c = social.linktree) === null || _c === void 0 ? void 0 : _c.path) {
14
- all.push({ id: 'linktree', url: social.linktree.path, icon: FaLink, description: 'Logo do Linktree' });
15
- }
16
- if (all.length === 0)
2
+ import { FaFacebookF, FaInstagram, FaTiktok, FaWhatsapp, FaYoutube, FaXTwitter, FaLinkedin, FaThreads, FaLink } from 'react-icons/fa6';
3
+ const SOCIAL_ICONS = {
4
+ facebook: FaFacebookF,
5
+ instagram: FaInstagram,
6
+ tiktok: FaTiktok,
7
+ whatsapp: FaWhatsapp,
8
+ youtube: FaYoutube,
9
+ x: FaXTwitter,
10
+ twitter: FaXTwitter,
11
+ linkedin: FaLinkedin,
12
+ threads: FaThreads,
13
+ linktree: FaLink,
14
+ kwai: FaLink
15
+ };
16
+ export function SocialIconsComponent({ social, color }) {
17
+ const entries = Object.entries(social || {})
18
+ .filter(([, value]) => Boolean(value === null || value === void 0 ? void 0 : value.path))
19
+ .map(([id, value]) => ({ id, url: (value === null || value === void 0 ? void 0 : value.path) || '', Icon: SOCIAL_ICONS[id] || FaLink }));
20
+ if (entries.length === 0)
17
21
  return null;
18
- return (_jsx(Row, { children: all.map((element) => (_jsx(Col, { className: "text-center social-icons", style: { color: '#FFCC00' }, children: _jsx("a", { href: element.url, target: "_blank", rel: "noopener noreferrer", "aria-label": element.description, children: _jsx(element.icon, {}) }) }, element.id))) }));
22
+ return (_jsx("div", { className: "pb-social-icons", style: { color }, children: entries.map(({ id, url, Icon }) => (_jsx("a", { className: "pb-social-icon", href: url, target: "_blank", rel: "noopener noreferrer", "aria-label": id, children: _jsx(Icon, {}) }, id))) }));
19
23
  }
@@ -1,11 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { memo, useMemo } from 'react';
3
- import { Row, Container } from 'react-bootstrap';
3
+ import { PbContainer } from '../ui/PbContainer.js';
4
+ import { PbRow } from '../ui/PbRow.js';
4
5
  import { ElementFactory } from '../factories/ElementFactory.js';
5
6
  import { orderBySort } from '../utils/orderBySort.js';
7
+ import { resolveImageElement } from '../utils/imageCustomization.js';
6
8
  const elementFactory = new ElementFactory();
7
9
  const TextComponent = memo(function TextComponent({ component }) {
8
- const elements = useMemo(() => orderBySort(component.elements), [component.elements]);
9
- return (_jsx(Container, { style: component.styles, children: _jsx(Row, { id: "element-row", children: elements.map((element) => elementFactory.build(element)) }) }));
10
+ const elements = useMemo(() => orderBySort(component.elements).map((element) => resolveImageElement(component, element)), [component.elements, component.properties]);
11
+ return (_jsx(PbContainer, { "data-pb-component": component.id, style: component.styles, children: _jsx(PbRow, { id: "element-row", children: elements.map((element) => elementFactory.build(element)) }) }));
10
12
  });
11
13
  export { TextComponent };
@@ -13,5 +13,7 @@ export declare const ComponentTypeEnum: {
13
13
  readonly SocialIcons: "social-icons";
14
14
  readonly Map: "map";
15
15
  readonly List: "list";
16
+ readonly Buttons: "buttons";
17
+ readonly Icon: "icon";
16
18
  };
17
19
  export type ComponentTypeSlug = (typeof ComponentTypeEnum)[keyof typeof ComponentTypeEnum];
@@ -13,4 +13,6 @@ export const ComponentTypeEnum = {
13
13
  SocialIcons: 'social-icons',
14
14
  Map: 'map',
15
15
  List: 'list',
16
+ Buttons: 'buttons',
17
+ Icon: 'icon'
16
18
  };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * CSS base do site público (sem Bootstrap).
3
+ *
4
+ * Classes utilitárias e de componentes usadas pelo `lib-pixelbuild`. Todos os
5
+ * valores de destaque usam `var(--pb-*)` com fallback, então o design system
6
+ * (Etapa 1) sobrescreve os tokens sem tocar nestes estilos.
7
+ */
8
+ export declare const baseCss = "\n/* \u2500\u2500\u2500 Reset e tipografia base \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-root, .pb-root *, .pb-root *::before, .pb-root *::after {\n box-sizing: border-box;\n}\n.pb-root {\n margin: 0;\n font-family: var(--pb-font-family, 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif);\n font-size: var(--pb-font-size-base, 16px);\n line-height: var(--pb-line-height, 1.6);\n color: var(--pb-color-text, #1f2937);\n background-color: var(--pb-color-background, #ffffff);\n -webkit-font-smoothing: antialiased;\n text-rendering: optimizeLegibility;\n}\n.pb-root h1, .pb-root h2, .pb-root h3, .pb-root h4, .pb-root h5, .pb-root h6 {\n margin: 0 0 0.5em;\n font-weight: var(--pb-font-weight-bold, 700);\n line-height: 1.2;\n color: var(--pb-color-heading, #111827);\n}\n.pb-root img {\n max-width: 100%;\n height: auto;\n}\n.pb-root a {\n color: var(--pb-color-primary, #f58220);\n text-decoration: none;\n}\n.pb-root a:hover {\n text-decoration: underline;\n}\n\n/* \u2500\u2500\u2500 Layout: container / grade \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-container {\n width: 100%;\n margin-inline: auto;\n padding-inline: var(--pb-gutter, 1.5rem);\n}\n.pb-container-fluid {\n max-width: none !important;\n padding-inline: var(--pb-gutter, 1.5rem);\n}\n@media (min-width: 576px) {\n .pb-container { max-width: 540px; }\n}\n@media (min-width: 768px) {\n .pb-container { max-width: 720px; }\n}\n@media (min-width: 992px) {\n .pb-container { max-width: 960px; }\n}\n@media (min-width: 1200px) {\n .pb-container { max-width: 1140px; }\n}\n@media (min-width: 1400px) {\n .pb-container { max-width: 1320px; }\n}\n\n.pb-row {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--pb-gutter, 1.5rem);\n}\n.pb-col {\n min-width: 0;\n}\n\n/* \u2500\u2500\u2500 Bot\u00F5es \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5em;\n padding: 0.5em 1.25em;\n font-family: inherit;\n font-size: 1rem;\n font-weight: var(--pb-font-weight-bold, 700);\n line-height: 1.5;\n text-align: center;\n text-decoration: none;\n border: 1px solid transparent;\n border-radius: var(--pb-radius-md, 8px);\n cursor: pointer;\n transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;\n}\n.pb-button:hover { text-decoration: none; }\n.pb-button:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.pb-button-primary {\n background-color: var(--pb-color-primary, #f58220);\n border-color: var(--pb-color-primary, #f58220);\n color: #ffffff;\n}\n.pb-button-primary:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--pb-color-primary, #f58220) 88%, #000);\n border-color: color-mix(in srgb, var(--pb-color-primary, #f58220) 88%, #000);\n}\n.pb-button-secondary {\n background-color: var(--pb-color-secondary, #64748b);\n border-color: var(--pb-color-secondary, #64748b);\n color: #ffffff;\n}\n.pb-button-success {\n background-color: var(--pb-color-success, #16a34a);\n border-color: var(--pb-color-success, #16a34a);\n color: #ffffff;\n}\n.pb-button-danger {\n background-color: var(--pb-color-danger, #dc2626);\n border-color: var(--pb-color-danger, #dc2626);\n color: #ffffff;\n}\n.pb-button-warning {\n background-color: var(--pb-color-warning, #f59e0b);\n border-color: var(--pb-color-warning, #f59e0b);\n color: #1f2937;\n}\n.pb-button-info {\n background-color: var(--pb-color-info, #0ea5e9);\n border-color: var(--pb-color-info, #0ea5e9);\n color: #ffffff;\n}\n.pb-button-light {\n background-color: var(--pb-color-light, #f8fafc);\n border-color: var(--pb-color-border, #e5e7eb);\n color: var(--pb-color-text, #1f2937);\n}\n.pb-button-dark {\n background-color: var(--pb-color-dark, #0f172a);\n border-color: var(--pb-color-dark, #0f172a);\n color: #ffffff;\n}\n.pb-button-outline-primary {\n background-color: transparent;\n border-color: var(--pb-color-primary, #f58220);\n color: var(--pb-color-primary, #f58220);\n}\n.pb-button-outline-primary:hover:not(:disabled) {\n background-color: var(--pb-color-primary, #f58220);\n color: #ffffff;\n}\n.pb-button-outline-secondary {\n background-color: transparent;\n border-color: var(--pb-color-secondary, #64748b);\n color: var(--pb-color-secondary, #64748b);\n}\n.pb-button-outline-secondary:hover:not(:disabled) {\n background-color: var(--pb-color-secondary, #64748b);\n color: #ffffff;\n}\n.pb-button-link {\n background-color: transparent;\n border-color: transparent;\n color: var(--pb-color-primary, #f58220);\n padding-inline: 0.5em;\n}\n.pb-button-sm {\n padding: 0.375em 0.875em;\n font-size: 0.875rem;\n border-radius: var(--pb-radius-sm, 4px);\n}\n.pb-button-lg {\n padding: 0.625em 1.5em;\n font-size: 1.125rem;\n border-radius: var(--pb-radius-lg, 12px);\n}\n\n/* \u2500\u2500\u2500 Spinner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-spinner {\n display: inline-block;\n width: 1.5rem;\n height: 1.5rem;\n border: 0.2em solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: pb-spin 0.75s linear infinite;\n vertical-align: -0.25em;\n}\n.pb-spinner-sm {\n width: 1rem;\n height: 1rem;\n border-width: 0.18em;\n}\n@keyframes pb-spin {\n to { transform: rotate(360deg); }\n}\n\n/* \u2500\u2500\u2500 Alertas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-alert {\n padding: var(--pb-space-md, 16px) var(--pb-space-lg, 24px);\n border: 1px solid;\n border-radius: var(--pb-radius-md, 8px);\n margin-bottom: var(--pb-space-md, 16px);\n}\n.pb-alert-title {\n font-weight: var(--pb-font-weight-bold, 700);\n margin-bottom: 0.25em;\n}\n.pb-alert-primary {\n background-color: color-mix(in srgb, var(--pb-color-primary, #f58220) 10%, #fff);\n border-color: color-mix(in srgb, var(--pb-color-primary, #f58220) 35%, #fff);\n color: var(--pb-color-text, #1f2937);\n}\n.pb-alert-info {\n background-color: color-mix(in srgb, var(--pb-color-info, #0ea5e9) 10%, #fff);\n border-color: color-mix(in srgb, var(--pb-color-info, #0ea5e9) 35%, #fff);\n color: var(--pb-color-text, #1f2937);\n}\n.pb-alert-success {\n background-color: color-mix(in srgb, var(--pb-color-success, #16a34a) 10%, #fff);\n border-color: color-mix(in srgb, var(--pb-color-success, #16a34a) 35%, #fff);\n color: var(--pb-color-text, #1f2937);\n}\n.pb-alert-warning {\n background-color: color-mix(in srgb, var(--pb-color-warning, #f59e0b) 12%, #fff);\n border-color: color-mix(in srgb, var(--pb-color-warning, #f59e0b) 35%, #fff);\n color: var(--pb-color-text, #1f2937);\n}\n.pb-alert-danger {\n background-color: color-mix(in srgb, var(--pb-color-danger, #dc2626) 10%, #fff);\n border-color: color-mix(in srgb, var(--pb-color-danger, #dc2626) 35%, #fff);\n color: var(--pb-color-text, #1f2937);\n}\n.pb-alert-secondary {\n background-color: var(--pb-color-light, #f8fafc);\n border-color: var(--pb-color-border, #e5e7eb);\n color: var(--pb-color-text, #1f2937);\n}\n\n/* \u2500\u2500\u2500 Formul\u00E1rios \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-form-group {\n margin-bottom: var(--pb-space-md, 16px);\n}\n.pb-form-label {\n display: block;\n margin-bottom: 0.375rem;\n font-weight: var(--pb-font-weight-bold, 700);\n color: var(--pb-color-text, #1f2937);\n}\n.pb-form-control,\n.pb-form-select,\n.pb-form-textarea {\n display: block;\n width: 100%;\n padding: 0.5em 0.75em;\n font-family: inherit;\n font-size: 1rem;\n line-height: 1.5;\n color: var(--pb-color-text, #1f2937);\n background-color: var(--pb-color-surface, #ffffff);\n border: 1px solid var(--pb-color-border, #e5e7eb);\n border-radius: var(--pb-radius-sm, 4px);\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n}\n.pb-form-control:focus,\n.pb-form-select:focus,\n.pb-form-textarea:focus {\n outline: none;\n border-color: var(--pb-color-primary, #f58220);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--pb-color-primary, #f58220) 20%, transparent);\n}\n.pb-form-control-invalid,\n.pb-form-select-invalid,\n.pb-form-textarea-invalid {\n border-color: var(--pb-color-danger, #dc2626);\n}\n.pb-invalid-feedback {\n display: block;\n margin-top: 0.375rem;\n font-size: 0.875rem;\n color: var(--pb-color-danger, #dc2626);\n}\n.pb-form-check {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 0.5rem;\n}\n.pb-form-check-input {\n width: 1.1em;\n height: 1.1em;\n accent-color: var(--pb-color-primary, #f58220);\n flex-shrink: 0;\n}\n.pb-form-check-label {\n font-weight: normal;\n margin-bottom: 0;\n}\n\n/* \u2500\u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-header {\n width: 100%;\n}\n.pb-header-inner {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--pb-space-md, 16px);\n flex-wrap: wrap;\n padding-block: var(--pb-space-sm, 8px);\n}\n.pb-brand {\n display: inline-flex;\n align-items: center;\n text-decoration: none;\n}\n.pb-brand img {\n max-height: 56px;\n width: auto;\n}\n.pb-nav {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n.pb-nav-link {\n display: inline-block;\n padding: 0.5rem 0.75rem;\n color: inherit;\n text-decoration: none;\n font-weight: 500;\n border-bottom: 2px solid transparent;\n transition: color 0.2s ease, border-color 0.2s ease;\n}\n.pb-nav-link:hover {\n text-decoration: none;\n opacity: 0.85;\n}\n.pb-nav-link-active {\n border-bottom-color: currentColor;\n}\n.pb-nav-toggle {\n display: none;\n padding: 0.375rem 0.625rem;\n font-size: 1.25rem;\n line-height: 1;\n background: transparent;\n border: 1px solid var(--pb-color-border, #e5e7eb);\n border-radius: var(--pb-radius-sm, 4px);\n cursor: pointer;\n color: inherit;\n}\n@media (max-width: 991.98px) {\n .pb-nav-toggle { display: inline-flex; align-items: center; }\n .pb-nav { display: none; }\n .pb-nav-open { display: flex; flex-direction: column; width: 100%; }\n}\n\n/* \u2500\u2500\u2500 Footer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-footer {\n width: 100%;\n padding-block: var(--pb-space-xl, 32px);\n color: var(--pb-color-text, #1f2937);\n}\n.pb-footer-divider {\n border: none;\n border-top: 1px solid var(--pb-color-border, #e5e7eb);\n margin: var(--pb-space-lg, 24px) 0;\n}\n.pb-social-icons {\n display: flex;\n justify-content: center;\n gap: var(--pb-space-sm, 8px);\n flex-wrap: wrap;\n}\n.pb-social-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n color: inherit;\n text-decoration: none;\n}\n.pb-social-icon:hover {\n text-decoration: none;\n opacity: 0.8;\n}\n\n/* \u2500\u2500\u2500 Loading \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-loading {\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--pb-space-sm, 8px);\n font-weight: 600;\n letter-spacing: 0.08em;\n}\n\n/* \u2500\u2500\u2500 Utilit\u00E1rios de alinhamento \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.pb-text-center { text-align: center; }\n.pb-mb-0 { margin-bottom: 0; }\n";