lib-pixelbuild 0.1.4 → 0.2.0

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 (63) hide show
  1. package/README.md +102 -127
  2. package/dist/builders/PageBuilder.d.ts +3 -2
  3. package/dist/builders/PageBuilder.js +41 -33
  4. package/dist/components/CardComponent.d.ts +3 -3
  5. package/dist/components/CardComponent.js +65 -41
  6. package/dist/components/FormComponent.d.ts +3 -3
  7. package/dist/components/FormComponent.js +8 -14
  8. package/dist/components/ListComponent.d.ts +3 -2
  9. package/dist/components/ListComponent.js +20 -15
  10. package/dist/components/LoadingComponent.js +1 -1
  11. package/dist/components/MapComponent.js +18 -4
  12. package/dist/components/SliderComponent.js +59 -15
  13. package/dist/components/SocialIconsComponent.js +1 -1
  14. package/dist/components/TextComponent.d.ts +3 -3
  15. package/dist/components/TextComponent.js +6 -7
  16. package/dist/elements/AlertElement.js +4 -3
  17. package/dist/elements/ButtonElement.js +19 -17
  18. package/dist/elements/IconElement.d.ts +1 -2
  19. package/dist/elements/IconElement.js +8 -9
  20. package/dist/elements/IconMap.d.ts +2 -0
  21. package/dist/elements/IconMap.js +30 -0
  22. package/dist/elements/InputElement.js +16 -16
  23. package/dist/factories/ButtonActionFactory.d.ts +6 -1
  24. package/dist/factories/ButtonActionFactory.js +14 -4
  25. package/dist/index.d.ts +2 -6
  26. package/dist/index.js +1 -4
  27. package/dist/layouts/Header.d.ts +2 -1
  28. package/dist/layouts/Header.js +33 -5
  29. package/dist/layouts/SiteLayout.d.ts +2 -1
  30. package/dist/layouts/SiteLayout.js +2 -2
  31. package/dist/renderers/SectionRenderer.d.ts +3 -3
  32. package/dist/renderers/SectionRenderer.js +45 -29
  33. package/dist/services/EmailService.d.ts +10 -2
  34. package/dist/services/EmailService.js +25 -25
  35. package/dist/types/RawWebsiteType.d.ts +8 -184
  36. package/dist/utils/InputValidators.js +11 -11
  37. package/dist/utils/propertyUtils.d.ts +3 -0
  38. package/dist/utils/propertyUtils.js +28 -0
  39. package/package.json +32 -19
  40. package/dist/elements/FileElement.d.ts +0 -4
  41. package/dist/elements/FileElement.js +0 -6
  42. package/dist/services/ApiService.d.ts +0 -5
  43. package/dist/services/ApiService.js +0 -17
  44. package/dist/services/CacheService.d.ts +0 -5
  45. package/dist/services/CacheService.js +0 -16
  46. package/dist/services/ConstructorService.d.ts +0 -12
  47. package/dist/services/ConstructorService.js +0 -33
  48. package/dist/types/AuthenticateResponseType.d.ts +0 -5
  49. package/dist/types/AuthenticateResponseType.js +0 -1
  50. package/dist/types/ButtonPropertiesType.d.ts +0 -11
  51. package/dist/types/ButtonPropertiesType.js +0 -1
  52. package/dist/types/FilePropertiesType.d.ts +0 -4
  53. package/dist/types/FilePropertiesType.js +0 -1
  54. package/dist/types/ImagePropertiesType.d.ts +0 -4
  55. package/dist/types/ImagePropertiesType.js +0 -1
  56. package/dist/types/InputPropertiesType.d.ts +0 -7
  57. package/dist/types/InputPropertiesType.js +0 -1
  58. package/dist/types/LinkPropertiesType.d.ts +0 -4
  59. package/dist/types/LinkPropertiesType.js +0 -1
  60. package/dist/types/PlanWebsiteType.d.ts +0 -9
  61. package/dist/types/PlanWebsiteType.js +0 -1
  62. package/dist/types/UserType.d.ts +0 -10
  63. package/dist/types/UserType.js +0 -1
@@ -1,14 +1,3 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
2
  import { useEffect, useState } from 'react';
14
3
  import { useKeenSlider } from 'keen-slider/react.js';
@@ -17,8 +6,8 @@ import { orderBySort } from '../utils/orderBySort.js';
17
6
  import 'keen-slider/keen-slider.min.css';
18
7
  const elementFactory = new ElementFactory();
19
8
  function cleanComponentStyles(styles) {
20
- const { minHeight: _m, display: _d, alignItems: _a, justifyContent: _j, flexDirection: _f } = styles, rest = __rest(styles, ["minHeight", "display", "alignItems", "justifyContent", "flexDirection"]);
21
- return rest;
9
+ const exclude = new Set(['minHeight', 'display', 'alignItems', 'justifyContent', 'flexDirection']);
10
+ return Object.fromEntries(Object.entries(styles).filter(([key]) => !exclude.has(key)));
22
11
  }
23
12
  function StaticSliderComponent({ component }) {
24
13
  const firstSlide = orderBySort(component.elements)[0];
@@ -46,7 +35,7 @@ function InteractiveSliderComponent({ component }) {
46
35
  if (!properties.autoplay || slides.length < 2)
47
36
  return;
48
37
  const interval = Number(properties.interval) > 0 ? Number(properties.interval) : 5000;
49
- const timer = window.setInterval(() => { var _b; return (_b = instanceRef.current) === null || _b === void 0 ? void 0 : _b.moveToIdx(instanceRef.current.track.details.rel + 1); }, interval);
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);
50
39
  return () => window.clearInterval(timer);
51
40
  }, [instanceRef, properties.autoplay, properties.interval, slides.length]);
52
41
  const fixedHeight = Number(properties.height) > 0 ? Number(properties.height) : 0;
@@ -56,7 +45,62 @@ function InteractiveSliderComponent({ component }) {
56
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'
57
46
  ? fixedHeight
58
47
  ? Object.assign({ width: '100%', height: '100%', objectFit: 'cover' }, element.styles) : Object.assign({ width: '100%' }, element.styles)
59
- : element.styles })) }, element.id))) }), showArrows && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "aria-label": "Slide anterior", onClick: () => { var _b; return (_b = instanceRef.current) === null || _b === void 0 ? void 0 : _b.moveToIdx(instanceRef.current.track.details.rel - 1); }, style: { position: 'absolute', left: 0, top: '50%', transform: 'translateY(-50%)' }, children: '<' }), _jsx("button", { type: "button", "aria-label": "Proximo slide", onClick: () => { var _b; return (_b = instanceRef.current) === null || _b === void 0 ? void 0 : _b.moveToIdx(instanceRef.current.track.details.rel + 1); }, style: { position: 'absolute', right: 0, top: '50%', transform: 'translateY(-50%)' }, children: '>' })] })), showDots && (_jsx("div", { "aria-label": "Navegacao do slider", style: { display: 'flex', justifyContent: 'center', gap: 4 }, 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 _b; return (_b = instanceRef.current) === null || _b === void 0 ? void 0 : _b.moveToIdx(index); }, children: index + 1 }, element.id))) }))] }));
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',
99
+ display: 'flex',
100
+ alignItems: 'center',
101
+ justifyContent: 'center',
102
+ transition: 'all 0.2s',
103
+ }, children: index + 1 }, element.id))) }))] }));
60
104
  }
61
105
  export function SliderComponent({ component, editionMode = false }) {
62
106
  if (editionMode)
@@ -15,5 +15,5 @@ export function SocialIconsComponent({ social }) {
15
15
  }
16
16
  if (all.length === 0)
17
17
  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: "noreferrer", "aria-label": element.description, children: _jsx(element.icon, {}) }) }, element.id))) }));
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))) }));
19
19
  }
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
1
  import type { ComponentType } from '../types/ComponentType.js';
3
- export declare function TextComponent({ component }: {
2
+ declare const TextComponent: import("react").NamedExoticComponent<{
4
3
  readonly component: ComponentType;
5
- }): React.JSX.Element;
4
+ }>;
5
+ export { TextComponent };
@@ -1,12 +1,11 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from 'react';
2
+ import { memo, useMemo } from 'react';
3
3
  import { Row, Container } from 'react-bootstrap';
4
4
  import { ElementFactory } from '../factories/ElementFactory.js';
5
5
  import { orderBySort } from '../utils/orderBySort.js';
6
6
  const elementFactory = new ElementFactory();
7
- export function TextComponent({ component }) {
8
- return (_jsx(Container, { style: component.styles, children: _jsx(Row, { id: "element-row", children: orderBySort(component.elements).map((element) => {
9
- const e = elementFactory.build(element);
10
- return React.cloneElement(e, { key: element.id });
11
- }) }) }));
12
- }
7
+ 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
+ });
11
+ export { TextComponent };
@@ -3,20 +3,21 @@ import { useEffect } from 'react';
3
3
  import { Alert } from 'react-bootstrap';
4
4
  import { UseFormStore } from '../stores/UseFormStore.js';
5
5
  import { ElementColWrapper } from './ElementColWrapper.js';
6
+ import { getString, getNumber, getBoolean } from '../utils/propertyUtils.js';
6
7
  export function AlertElement({ element, formId }) {
7
8
  const properties = element.properties;
8
- const resolvedFormId = formId !== null && formId !== void 0 ? formId : properties.componentId;
9
+ const resolvedFormId = formId !== null && formId !== void 0 ? formId : getNumber(properties, 'componentId');
9
10
  const hidden = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.hidden; });
10
11
  const registerElement = UseFormStore((state) => state.registerElement);
11
12
  const unregisterElement = UseFormStore((state) => state.unregisterElement);
12
13
  useEffect(() => {
13
14
  registerElement(element.id, resolvedFormId, {
14
15
  type: 'alert',
15
- hidden: Boolean(properties.startHidden)
16
+ hidden: getBoolean(properties, 'startHidden')
16
17
  });
17
18
  return () => unregisterElement(element.id);
18
19
  }, [element.id, properties.startHidden, registerElement, resolvedFormId, unregisterElement]);
19
20
  if (hidden)
20
21
  return null;
21
- return (_jsx(ElementColWrapper, { element: element, children: _jsxs(Alert, { hidden: hidden, variant: String(properties.type || 'info'), style: element.styles, children: [_jsx(Alert.Heading, { children: String(properties.title || '') }), _jsx("p", { className: "mb-0", children: String(properties.message || '') })] }) }));
22
+ return (_jsx(ElementColWrapper, { element: element, children: _jsxs(Alert, { variant: getString(properties, 'type', 'info'), style: element.styles, children: [_jsx(Alert.Heading, { children: getString(properties, 'title') }), _jsx("p", { className: "mb-0", children: getString(properties, 'message') })] }) }));
22
23
  }
@@ -3,11 +3,11 @@ import { useEffect } from 'react';
3
3
  import { Button, Spinner } from 'react-bootstrap';
4
4
  import { ElementColWrapper } from './ElementColWrapper.js';
5
5
  import { UseFormStore } from '../stores/UseFormStore.js';
6
- import { ButtonActionFactory } from '../factories/ButtonActionFactory.js';
6
+ import { buttonActionFactory } from '../factories/ButtonActionFactory.js';
7
+ import { getString, getNumber, getBoolean } from '../utils/propertyUtils.js';
7
8
  export function ButtonElement({ element, formId }) {
8
- var _a;
9
9
  const properties = element.properties;
10
- const resolvedFormId = formId !== null && formId !== void 0 ? formId : properties.componentId;
10
+ const resolvedFormId = formId !== null && formId !== void 0 ? formId : getNumber(properties, 'componentId');
11
11
  const hidden = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.hidden; });
12
12
  const loading = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.loading; });
13
13
  const showElement = UseFormStore((state) => state.showElement);
@@ -17,7 +17,7 @@ export function ButtonElement({ element, formId }) {
17
17
  useEffect(() => {
18
18
  registerElement(element.id, resolvedFormId, {
19
19
  type: 'button',
20
- hidden: Boolean(properties.startHidden)
20
+ hidden: getBoolean(properties, 'startHidden')
21
21
  });
22
22
  return () => unregisterElement(element.id);
23
23
  }, [element.id, properties.startHidden, registerElement, resolvedFormId, unregisterElement]);
@@ -35,25 +35,27 @@ export function ButtonElement({ element, formId }) {
35
35
  if (hasErrors)
36
36
  return false;
37
37
  UseFormStore.getState().setElementState(element.id, { loading: true });
38
- if (properties.actionId) {
39
- const buttonActionFactory = new ButtonActionFactory();
40
- await buttonActionFactory.build(properties.actionId, formData);
38
+ const actionId = getNumber(properties, 'actionId');
39
+ if (actionId) {
40
+ await buttonActionFactory.build(actionId, formData);
41
41
  }
42
+ const loadingTime = (_a = getNumber(properties, 'loadingTime')) !== null && _a !== void 0 ? _a : 0;
42
43
  setTimeout(() => {
43
- if (properties.hideOnClick)
44
+ if (getBoolean(properties, 'hideOnClick'))
44
45
  hideElement(element.id);
45
- if (properties.successMessageId)
46
- showElement(properties.successMessageId);
47
- if (properties.successActionId)
48
- showElement(properties.successActionId);
46
+ const successMessageId = getNumber(properties, 'successMessageId');
47
+ const successActionId = getNumber(properties, 'successActionId');
48
+ if (successMessageId)
49
+ showElement(successMessageId);
50
+ if (successActionId)
51
+ showElement(successActionId);
49
52
  UseFormStore.getState().setElementState(element.id, { loading: false });
50
- }, (_a = properties.loadingTime) !== null && _a !== void 0 ? _a : 0);
53
+ }, loadingTime);
51
54
  }
52
55
  }
53
56
  if (hidden)
54
57
  return null;
55
- return (_jsx(ElementColWrapper, { element: element, children: _jsx(Button, { as: properties.path ? 'a' : 'button', type: properties.type === 'button' || properties.type === 'submit' || properties.type === 'reset'
56
- ? properties.type : undefined, variant: String(properties.variant || (properties.type === 'button' || properties.type === 'submit' || properties.type === 'reset'
57
- ? 'primary'
58
- : properties.type || 'primary')), href: String(properties.path || ''), target: properties.path ? '_blank' : undefined, rel: properties.path ? 'noopener noreferrer' : undefined, disabled: loading, onClick: handleClick, style: element.styles, children: loading ? (_jsxs(_Fragment, { children: [_jsx("output", { "aria-busy": "true", children: _jsx(Spinner, { as: "span", animation: "border", size: "sm", "aria-hidden": "true" }) }), ' ' + (String((_a = properties.message) !== null && _a !== void 0 ? _a : ''))] })) : (String(properties.text || properties.title || '')) }) }));
58
+ const buttonType = properties.type === 'button' || properties.type === 'submit' || properties.type === 'reset'
59
+ ? properties.type : undefined;
60
+ return (_jsx(ElementColWrapper, { element: element, children: _jsx(Button, { as: properties.path ? 'a' : 'button', type: buttonType, variant: getString(properties, 'variant', buttonType ? 'primary' : getString(properties, 'type', 'primary')), href: getString(properties, 'path'), target: properties.path ? '_blank' : undefined, rel: properties.path ? 'noopener noreferrer' : undefined, disabled: loading, onClick: handleClick, style: element.styles, children: loading ? (_jsxs(_Fragment, { children: [_jsx("output", { "aria-busy": "true", children: _jsx(Spinner, { as: "span", animation: "border", size: "sm", "aria-hidden": "true" }) }), ' ' + getString(properties, 'message')] })) : (getString(properties, 'text') || getString(properties, 'title')) }) }));
59
61
  }
@@ -1,5 +1,4 @@
1
- import React from 'react';
2
1
  import type { ElementType } from '../types/ElementType.js';
3
2
  export declare function IconElement({ element }: {
4
3
  readonly element: ElementType;
5
- }): React.JSX.Element;
4
+ }): import("react").JSX.Element;
@@ -1,16 +1,15 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { FaArrowRight, FaBars, FaCalendar, FaCheck, FaChevronLeft, FaChevronRight, FaClock, FaEnvelope, FaFacebookF, FaGlobe, FaHeart, FaHome, FaInfoCircle, FaInstagram, FaLink, FaMapMarkerAlt, FaPhone, FaQuestionCircle, FaQuoteLeft, FaSearch, FaShoppingCart, FaStar, FaTimes, FaTwitter, FaUser, FaWhatsapp, FaYoutube, } from 'react-icons/fa';
2
+ import { Suspense, useMemo } from 'react';
3
+ import { iconMap } from './IconMap.js';
3
4
  import { ElementColWrapper } from './ElementColWrapper.js';
4
- const icons = {
5
- FaArrowRight, FaBars, FaCalendar, FaCheck, FaChevronLeft, FaChevronRight, FaClock,
6
- FaEnvelope, FaFacebookF, FaGlobe, FaHeart, FaHome, FaInfoCircle, FaInstagram, FaLink,
7
- FaMapMarkerAlt, FaPhone, FaQuoteLeft, FaSearch, FaShoppingCart, FaStar, FaTimes,
8
- FaTwitter, FaUser, FaWhatsapp, FaYoutube,
9
- };
5
+ function FallbackIcon({ name }) {
6
+ const Icon = iconMap[name] || iconMap.FaQuestionCircle;
7
+ return _jsx(Icon, { size: "1em", "aria-label": name || 'Icon' });
8
+ }
10
9
  export function IconElement({ element }) {
11
10
  var _a;
12
11
  const name = String(element.properties.name || '');
13
- const Icon = icons[name] || FaQuestionCircle;
14
12
  const iconSize = ((_a = element.styles) === null || _a === void 0 ? void 0 : _a.fontSize) || '1.25rem';
15
- return (_jsx(ElementColWrapper, { element: element, children: _jsx("span", { style: { fontSize: iconSize, display: 'inline-flex' }, children: _jsx(Icon, { size: "1em", style: element.styles, "aria-label": name || 'Ícone' }) }) }));
13
+ const Icon = useMemo(() => iconMap[name] || iconMap.FaQuestionCircle, [name]);
14
+ return (_jsx(ElementColWrapper, { element: element, children: _jsx("span", { style: { fontSize: iconSize, display: 'inline-flex' }, children: _jsx(Suspense, { fallback: _jsx(FallbackIcon, { name: name }), children: _jsx(Icon, { size: "1em", style: element.styles, "aria-label": name || 'Icon' }) }) }) }));
16
15
  }
@@ -0,0 +1,2 @@
1
+ import type { IconType } from 'react-icons';
2
+ export declare const iconMap: Record<string, IconType>;
@@ -0,0 +1,30 @@
1
+ import { FaArrowRight, FaBars, FaCalendar, FaCheck, FaChevronLeft, FaChevronRight, FaClock, FaEnvelope, FaFacebookF, FaGlobe, FaHeart, FaHome, FaInfoCircle, FaInstagram, FaLink, FaMapMarkerAlt, FaPhone, FaQuestionCircle, FaQuoteLeft, FaSearch, FaShoppingCart, FaStar, FaTimes, FaTwitter, FaUser, FaWhatsapp, FaYoutube, } from 'react-icons/fa';
2
+ export const iconMap = {
3
+ FaArrowRight,
4
+ FaBars,
5
+ FaCalendar,
6
+ FaCheck,
7
+ FaChevronLeft,
8
+ FaChevronRight,
9
+ FaClock,
10
+ FaEnvelope,
11
+ FaFacebookF,
12
+ FaGlobe,
13
+ FaHeart,
14
+ FaHome,
15
+ FaInfoCircle,
16
+ FaInstagram,
17
+ FaLink,
18
+ FaMapMarkerAlt,
19
+ FaPhone,
20
+ FaQuestionCircle,
21
+ FaQuoteLeft,
22
+ FaSearch,
23
+ FaShoppingCart,
24
+ FaStar,
25
+ FaTimes,
26
+ FaTwitter,
27
+ FaUser,
28
+ FaWhatsapp,
29
+ FaYoutube,
30
+ };
@@ -5,9 +5,10 @@ import { IMaskInput } from 'react-imask';
5
5
  import { ElementColWrapper } from './ElementColWrapper.js';
6
6
  import { UseFormStore } from '../stores/UseFormStore.js';
7
7
  import { ElementTypeEnum } from '../constants/ElementEnum.js';
8
+ import { getString, getNumber, getBoolean } from '../utils/propertyUtils.js';
8
9
  export function InputElement({ element, formId }) {
9
10
  const properties = element.properties;
10
- const resolvedFormId = formId !== null && formId !== void 0 ? formId : properties.componentId;
11
+ const resolvedFormId = formId !== null && formId !== void 0 ? formId : getNumber(properties, 'componentId');
11
12
  const hidden = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.hidden; });
12
13
  const error = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.error; });
13
14
  const errorMessage = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.errorMessage; });
@@ -15,12 +16,12 @@ export function InputElement({ element, formId }) {
15
16
  const unregisterElement = UseFormStore((state) => state.unregisterElement);
16
17
  const validateFormData = UseFormStore((state) => state.validateFormData);
17
18
  useEffect(() => {
18
- var _a, _b, _c;
19
+ var _a;
19
20
  registerElement(element.id, resolvedFormId, {
20
- name: String(properties.name || ''),
21
+ name: getString(properties, 'name'),
21
22
  type: element.elementType,
22
- value: properties.checked ? String((_a = properties.value) !== null && _a !== void 0 ? _a : 'on') : String((_b = properties.value) !== null && _b !== void 0 ? _b : ''),
23
- inputValidateId: (_c = properties.inputValidateId) !== null && _c !== void 0 ? _c : null
23
+ value: getBoolean(properties, 'checked') ? getString(properties, 'value', 'on') : getString(properties, 'value'),
24
+ inputValidateId: (_a = getNumber(properties, 'inputValidateId')) !== null && _a !== void 0 ? _a : null
24
25
  });
25
26
  return () => unregisterElement(element.id);
26
27
  }, [
@@ -37,10 +38,10 @@ export function InputElement({ element, formId }) {
37
38
  if (hidden)
38
39
  return null;
39
40
  const hasMask = element.elementType === ElementTypeEnum.Input && Boolean(properties.mask);
40
- const label = String(properties.label || properties.title || '');
41
- const name = String(properties.name || '');
41
+ const label = getString(properties, 'label') || getString(properties, 'title');
42
+ const name = getString(properties, 'name');
42
43
  const controlId = name || `element-${element.id}`;
43
- const inputValidateId = properties.inputValidateId;
44
+ const inputValidateId = getNumber(properties, 'inputValidateId');
44
45
  const options = Array.isArray(properties.options) ? properties.options : [];
45
46
  const handleAccept = (value) => {
46
47
  UseFormStore.getState().setElementState(element.id, { value });
@@ -65,12 +66,11 @@ export function InputElement({ element, formId }) {
65
66
  store.setElementState(element.id, { value: checked ? value : '' });
66
67
  };
67
68
  const renderControl = () => {
68
- var _a, _b, _c, _d, _e;
69
69
  if (element.elementType === ElementTypeEnum.Textarea) {
70
- return (_jsx("textarea", { defaultValue: String((_a = properties.value) !== null && _a !== void 0 ? _a : ''), rows: Number(properties.rows) || 4, onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: Boolean(properties.required), name: name, placeholder: String(properties.placeholder || ''), className: `form-control${error ? ' is-invalid' : ''}`, style: element.styles }));
70
+ 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-control${error ? ' is-invalid' : ''}`, style: element.styles }));
71
71
  }
72
72
  if (element.elementType === ElementTypeEnum.Select) {
73
- return (_jsx("select", { defaultValue: String((_b = properties.value) !== null && _b !== void 0 ? _b : ''), onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: Boolean(properties.required), name: name, className: `form-select${error ? ' is-invalid' : ''}`, style: element.styles, children: options.map((option, index) => {
73
+ return (_jsx("select", { defaultValue: getString(properties, 'value'), onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: getBoolean(properties, 'required'), name: name, className: `form-select${error ? ' is-invalid' : ''}`, style: element.styles, children: options.map((option, index) => {
74
74
  var _a, _b, _c, _d;
75
75
  const data = typeof option === 'object' && option !== null ? option : null;
76
76
  const value = String((_a = data === null || data === void 0 ? void 0 : data.value) !== null && _a !== void 0 ? _a : option);
@@ -79,16 +79,16 @@ export function InputElement({ element, formId }) {
79
79
  }) }));
80
80
  }
81
81
  if (element.elementType === ElementTypeEnum.Checkbox || element.elementType === ElementTypeEnum.Radio) {
82
- const value = String((_c = properties.value) !== null && _c !== void 0 ? _c : 'on');
83
- return (_jsxs("div", { className: "form-check", children: [_jsx("input", { id: controlId, type: element.elementType, defaultChecked: Boolean(properties.checked), value: value, onChange: (e) => setCheckedValue(e.target.checked, value), onBlur: handleBlur, required: Boolean(properties.required), name: name, className: `form-check-input${error ? ' is-invalid' : ''}`, style: element.styles }), label && _jsx("label", { className: "form-check-label", htmlFor: controlId, children: label })] }));
82
+ const value = getString(properties, 'value', 'on');
83
+ 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 ? ' is-invalid' : ''}`, style: element.styles }), label && _jsx("label", { className: "form-check-label", htmlFor: controlId, children: label })] }));
84
84
  }
85
85
  if (element.elementType === ElementTypeEnum.File) {
86
- return (_jsx("div", { className: "alert alert-secondary", role: "status", style: element.styles, children: "Upload de arquivos n\u00E3o dispon\u00EDvel neste formul\u00E1rio." }));
86
+ return (_jsx("div", { className: "alert alert-secondary", role: "status", style: element.styles, children: "File upload not available in this form." }));
87
87
  }
88
88
  if (hasMask) {
89
- return (_jsx(IMaskInput, { mask: String(properties.mask), defaultValue: String((_d = properties.value) !== null && _d !== void 0 ? _d : ''), onAccept: handleAccept, onBlur: handleBlur, required: Boolean(properties.required), name: name, placeholder: String(properties.placeholder || ''), className: `form-control${error ? ' is-invalid' : ''}`, style: element.styles }));
89
+ 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${error ? ' is-invalid' : ''}`, style: element.styles }));
90
90
  }
91
- return (_jsx("input", { type: String(properties.type || 'text'), defaultValue: String((_e = properties.value) !== null && _e !== void 0 ? _e : ''), onChange: (e) => setValue(e.target.value), onBlur: handleBlur, required: Boolean(properties.required), name: name, placeholder: String(properties.placeholder || ''), className: `form-control${error ? ' is-invalid' : ''}`, style: element.styles }));
91
+ 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${error ? ' is-invalid' : ''}`, style: element.styles }));
92
92
  };
93
93
  return (_jsx(ElementColWrapper, { element: element, children: _jsxs(Form.Group, { className: "mb-3", controlId: controlId, children: [label && element.elementType !== ElementTypeEnum.Checkbox && element.elementType !== ElementTypeEnum.Radio && (_jsx(Form.Label, { children: label })), renderControl(), error && (_jsx("div", { className: "invalid-feedback", style: { display: 'block' }, children: errorMessage }))] }) }));
94
94
  }
@@ -1,5 +1,10 @@
1
+ import { type EmailServiceConfig } from '../services/EmailService.js';
1
2
  import type { FormFieldsType } from '../types/FormFieldsType.js';
2
3
  import type { MailBodyType } from '../types/MailBodyType.js';
3
- export declare class ButtonActionFactory {
4
+ declare class ButtonActionFactory {
5
+ private emailService;
6
+ configureEmail(config: EmailServiceConfig): void;
4
7
  build(actionId: number, data: FormFieldsType[]): Promise<MailBodyType | boolean>;
5
8
  }
9
+ export declare const buttonActionFactory: ButtonActionFactory;
10
+ export type { EmailServiceConfig } from '../services/EmailService.js';
@@ -1,13 +1,23 @@
1
1
  import { EmailService } from '../services/EmailService.js';
2
2
  import { ButtonActionEnum } from '../constants/ButtonActionEnum.js';
3
- export class ButtonActionFactory {
3
+ class ButtonActionFactory {
4
+ constructor() {
5
+ this.emailService = null;
6
+ }
7
+ configureEmail(config) {
8
+ this.emailService = new EmailService(config);
9
+ }
4
10
  async build(actionId, data) {
5
- const emailService = new EmailService('https://api.example.com');
6
11
  switch (actionId) {
7
- case ButtonActionEnum.SendMail:
8
- return emailService.sendMail(data);
12
+ case ButtonActionEnum.SendMail: {
13
+ if (!this.emailService) {
14
+ throw new Error('EmailService not configured. Call configureEmail() before using SendMail action.');
15
+ }
16
+ return this.emailService.sendMail(data);
17
+ }
9
18
  default:
10
19
  throw new Error('Invalid button action: ' + actionId);
11
20
  }
12
21
  }
13
22
  }
23
+ export const buttonActionFactory = new ButtonActionFactory();
package/dist/index.d.ts CHANGED
@@ -8,8 +8,6 @@ export type { ComponentType } from './types/ComponentType.js';
8
8
  export type { ElementType } from './types/ElementType.js';
9
9
  export type { PropertiesType } from './types/PropertiesType.js';
10
10
  export type { StylesType } from './types/StylesType.js';
11
- export type { UserType } from './types/UserType.js';
12
- export type { AuthenticateResponseType } from './types/AuthenticateResponseType.js';
13
11
  export { Header } from './layouts/Header.js';
14
12
  export { Footer } from './layouts/Footer.js';
15
13
  export { SiteLayout } from './layouts/SiteLayout.js';
@@ -20,8 +18,6 @@ export { ComponentFactory } from './factories/ComponentFactory.js';
20
18
  export { ElementFactory } from './factories/ElementFactory.js';
21
19
  export { ComponentTypeEnum } from './constants/ComponentEnum.js';
22
20
  export { ElementTypeEnum } from './constants/ElementEnum.js';
23
- export { ApiService } from './services/ApiService.js';
24
21
  export { analyticsService } from './services/AnalyticsService.js';
25
- export { CacheService } from './services/CacheService.js';
26
- export { ConstructorService } from './services/ConstructorService.js';
27
- export { EmailService } from './services/EmailService.js';
22
+ export { buttonActionFactory } from './factories/ButtonActionFactory.js';
23
+ export type { EmailServiceConfig } from './services/EmailService.js';
package/dist/index.js CHANGED
@@ -8,8 +8,5 @@ export { ComponentFactory } from './factories/ComponentFactory.js';
8
8
  export { ElementFactory } from './factories/ElementFactory.js';
9
9
  export { ComponentTypeEnum } from './constants/ComponentEnum.js';
10
10
  export { ElementTypeEnum } from './constants/ElementEnum.js';
11
- export { ApiService } from './services/ApiService.js';
12
11
  export { analyticsService } from './services/AnalyticsService.js';
13
- export { CacheService } from './services/CacheService.js';
14
- export { ConstructorService } from './services/ConstructorService.js';
15
- export { EmailService } from './services/EmailService.js';
12
+ export { buttonActionFactory } from './factories/ButtonActionFactory.js';
@@ -1,4 +1,5 @@
1
1
  import type { WebsiteType } from '../types/WebsiteType.js';
2
- export declare function Header({ website }: {
2
+ export declare function Header({ website, imageBaseUrl }: {
3
3
  readonly website: WebsiteType;
4
+ readonly imageBaseUrl?: string;
4
5
  }): import("react").JSX.Element;
@@ -1,8 +1,36 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Container, Row, Col } from 'react-bootstrap';
3
- export function Header({ website }) {
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useCallback } from 'react';
3
+ import { useLocation } from 'react-router-dom';
4
+ import { Container, Navbar, Nav } from 'react-bootstrap';
5
+ export function Header({ website, imageBaseUrl }) {
4
6
  const headerProperties = website.header.properties;
5
7
  const headerStyles = website.header.styles;
6
- const domain = website.domain.replaceAll('.', '');
7
- return (_jsx(Container, { fluid: headerStyles.fluid || undefined, style: { backgroundColor: headerStyles.backgroundColor }, children: _jsx(Row, { id: "header", children: _jsx(Col, { xs: 3, md: 3, lg: 3, style: Object.assign({ display: headerProperties.showLogo ? 'block' : 'none' }, headerStyles), children: _jsx("img", { src: `https://noisdev-website-images.s3.sa-east-1.amazonaws.com/${domain}/${website.logo}`, width: "200", className: "d-inline-block align-top", alt: "Logo", style: { textAlign: headerProperties.logoAlign } }) }) }) }));
8
+ const domain = (website.domain || '').replaceAll('.', '');
9
+ const location = useLocation();
10
+ const menuPages = useMemo(() => (website.pages || [])
11
+ .filter((p) => p.menu === true)
12
+ .sort((a, b) => (a.menuOrder || 0) - (b.menuOrder || 0)), [website.pages]);
13
+ const isActive = useCallback((path) => {
14
+ const currentPath = location.pathname;
15
+ if (path === '/')
16
+ return currentPath === '/' || currentPath === '';
17
+ return currentPath === path || currentPath.startsWith(path + '/');
18
+ }, [location.pathname]);
19
+ const showMenu = headerProperties.showMenu !== false && menuPages.length > 0;
20
+ const logoUrl = useMemo(() => imageBaseUrl
21
+ ? `${imageBaseUrl.replace(/\/+$/, '')}/${domain}/${website.logo}`
22
+ : `https://noisdev-website-images.s3.sa-east-1.amazonaws.com/${domain}/${website.logo}`, [imageBaseUrl, domain, website.logo]);
23
+ return (_jsx(Navbar, { expand: "lg", collapseOnSelect: true, className: "py-3", style: { backgroundColor: headerStyles.backgroundColor || undefined, width: '100%' }, children: _jsxs(Container, { fluid: headerStyles.fluid || undefined, children: [headerProperties.showLogo && (_jsx(Navbar.Brand, { style: { marginRight: showMenu ? 'auto' : 0, padding: 0 }, children: _jsx("img", { src: logoUrl, width: "200", className: "d-inline-block align-top", alt: "Logo" }) })), showMenu && (_jsxs(_Fragment, { children: [_jsx(Navbar.Toggle, { "aria-controls": "header-navbar-nav" }), _jsx(Navbar.Collapse, { id: "header-navbar-nav", children: _jsx(Nav, { className: `mx-auto ${headerProperties.showLogo ? '' : 'w-100 justify-content-center'}`, children: menuPages.map((p) => {
24
+ const active = isActive(p.path);
25
+ return (_jsx(Nav.Link, { href: p.path, style: {
26
+ color: active ? '#c0ad5b' : '#a4a4a4',
27
+ fontSize: '0.9rem',
28
+ letterSpacing: '0.05em',
29
+ textTransform: 'uppercase',
30
+ margin: '0 12px',
31
+ paddingBottom: '4px',
32
+ borderBottom: active ? '2px solid #c0ad5b' : '2px solid transparent',
33
+ transition: 'color 0.3s, border-color 0.3s',
34
+ }, children: p.title }, p.id));
35
+ }) }) })] }))] }) }));
8
36
  }
@@ -1,4 +1,5 @@
1
1
  import type { WebsiteType } from '../types/WebsiteType.js';
2
- export declare function SiteLayout({ website }: {
2
+ export declare function SiteLayout({ website, imageBaseUrl }: {
3
3
  readonly website: WebsiteType;
4
+ readonly imageBaseUrl?: string;
4
5
  }): import("react").JSX.Element;
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Outlet } from 'react-router-dom';
3
3
  import { Header } from './Header.js';
4
4
  import { Footer } from './Footer.js';
5
- export function SiteLayout({ website }) {
6
- return (_jsxs("div", { id: "site-layout", style: { backgroundColor: website.styles.backgroundColor, color: website.styles.color }, children: [_jsx(Header, { website: website }), _jsx(Outlet, {}), _jsx(Footer, { website: website })] }));
5
+ export function SiteLayout({ website, imageBaseUrl }) {
6
+ return (_jsxs("div", { id: "site-layout", style: { backgroundColor: website.styles.backgroundColor, color: website.styles.color }, children: [_jsx(Header, { website: website, imageBaseUrl: imageBaseUrl }), _jsx(Outlet, {}), _jsx(Footer, { website: website })] }));
7
7
  }
@@ -1,6 +1,6 @@
1
- import React from 'react';
2
1
  import type { SectionType } from '../types/SectionType.js';
3
- export declare function SectionRenderer({ sections, editionMode }: {
2
+ declare const SectionRenderer: import("react").NamedExoticComponent<{
4
3
  readonly sections: SectionType[];
5
4
  readonly editionMode?: boolean;
6
- }): React.JSX.Element;
5
+ }>;
6
+ export { SectionRenderer };