@mindfiredigital/page-builder
Version:
764 lines (763 loc) • 26.8 kB
JavaScript
var __awaiter =
(this && this.__awaiter) ||
function (thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P
? value
: new P(function (resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator['throw'](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done
? resolve(result.value)
: adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Canvas } from '../canvas/Canvas.js';
import { debounce } from '../utils/utilityFunctions.js';
import LayersViewController from './LayerViewController.js';
import { TableComponent } from '../components/TableComponent.js';
import { svgs } from '../icons/svgs.js';
import { TextComponent } from '../components/TextComponent.js';
import { HeaderComponent } from '../components/HeaderComponent.js';
import { SidebarUtils } from '../utils/customizationSidebarHelper.js';
export class CustomizationSidebar {
static init(
customComponentsConfig,
editable,
BasicComponent,
showAttributeTab
) {
this.sidebarElement = document.getElementById('customization');
this.controlsContainer = document.getElementById('controls');
this.componentNameHeader = document.getElementById('component-name');
this.customComponentsConfig = customComponentsConfig;
this.basicComponentsConfig = BasicComponent;
this.editable = editable;
this.showAttributeTab = showAttributeTab;
if (!this.sidebarElement || !this.controlsContainer) {
console.error('CustomizationSidebar: Required elements not found.');
return;
}
this.layersViewController = new LayersViewController();
this.functionsPanel = document.createElement('div');
this.functionsPanel.id = 'functions-panel';
this.functionsPanel.className = 'dropdown-panel';
this.functionsPanel.style.display = 'none';
this.layersModeToggle = document.createElement('div');
this.layersModeToggle.className = 'layers-mode-toggle';
this.layersModeToggle.innerHTML = `
<button id="customize-tab" title="Customize" class="active">${svgs.settings}</button>
<button id="attribute-tab" title="Attribute" >${svgs.attribute}</button>
<button id="layers-tab" title="Layers"> ${svgs.menu} </button>
`;
this.sidebarElement.insertBefore(
this.layersModeToggle,
this.componentNameHeader
);
this.sidebarElement.appendChild(this.controlsContainer);
this.sidebarElement.appendChild(this.functionsPanel);
this.controlsContainer.style.display = 'block';
this.layersView = document.createElement('div');
this.layersView.id = 'layers-view';
this.layersView.className = 'layers-view hidden';
this.sidebarElement.appendChild(this.layersView);
const customizeTab = this.layersModeToggle.querySelector('#customize-tab');
const attributeTab = this.layersModeToggle.querySelector('#attribute-tab');
const layersTab = this.layersModeToggle.querySelector('#layers-tab');
if (this.editable === false && showAttributeTab === true) {
customizeTab.style.display = 'none';
layersTab.style.display = 'none';
attributeTab.classList.add('active');
customizeTab.classList.remove('active');
layersTab.classList.remove('active');
this.switchToAttributeMode();
} else {
customizeTab.addEventListener('click', () =>
this.switchToCustomizeMode()
);
attributeTab.addEventListener('click', () => {
this.switchToAttributeMode();
});
layersTab.addEventListener('click', () => this.switchToLayersMode());
}
}
static switchToCustomizeMode() {
const customizeTab = document.getElementById('customize-tab');
const attributeTab = document.getElementById('attribute-tab');
const layersTab = document.getElementById('layers-tab');
const layersView = document.getElementById('layers-view');
const componentName = document.getElementById('component-name');
customizeTab.classList.add('active');
attributeTab.classList.remove('active');
layersTab.classList.remove('active');
layersView.style.display = 'none';
this.controlsContainer.style.display = 'block';
this.functionsPanel.style.display = 'none';
componentName.style.display = 'block';
if (this.selectedComponent) {
this.populateCssControls(this.selectedComponent);
}
}
static switchToAttributeMode() {
const customizeTab = document.getElementById('customize-tab');
const attributeTab = document.getElementById('attribute-tab');
const layersTab = document.getElementById('layers-tab');
const layersView = document.getElementById('layers-view');
const componentName = document.getElementById('component-name');
attributeTab.classList.add('active');
customizeTab.classList.remove('active');
layersTab.classList.remove('active');
layersView.style.display = 'none';
this.functionsPanel.style.display = 'block';
this.controlsContainer.style.display = 'none';
componentName.style.display = 'block';
if (this.selectedComponent) {
this.populateFunctionalityControls(this.selectedComponent);
}
}
static switchToLayersMode() {
const customizeTab = document.getElementById('customize-tab');
const attributeTab = document.getElementById('attribute-tab');
const layersTab = document.getElementById('layers-tab');
const layersView = document.getElementById('layers-view');
const componentName = document.getElementById('component-name');
layersTab.classList.add('active');
attributeTab.classList.remove('active');
customizeTab.classList.remove('active');
this.controlsContainer.style.display = 'none';
this.functionsPanel.style.display = 'none';
layersView.style.display = 'block';
componentName.style.display = 'none';
LayersViewController.updateLayersView();
}
static showSidebar(componentId) {
const component = document.getElementById(componentId);
if (!component) {
console.error(`Component with ID "${componentId}" not found.`);
return;
}
if (this.editable === false && this.showAttributeTab !== true) {
return;
}
this.selectedComponent = component;
this.sidebarElement.style.display = 'block';
this.sidebarElement.classList.add('visible');
const menuButton = document.getElementById('menu-btn');
if (menuButton) {
menuButton.style.backgroundColor = '#e2e8f0';
menuButton.style.borderColor = '#cbd5e1';
}
this.componentNameHeader.textContent = `Component: ${componentId}`;
if (this.editable === false && this.showAttributeTab === true) {
this.switchToAttributeMode();
return;
}
this.switchToCustomizeMode();
}
static populateCssControls(component) {
this.controlsContainer.innerHTML = '';
const styles = getComputedStyle(component);
const isCanvas = component.id.toLowerCase() === 'canvas';
SidebarUtils.createSelectControl(
'Display',
'display',
styles.display || 'block',
['block', 'inline', 'inline-block', 'flex', 'grid', 'none'],
this.controlsContainer
);
if (styles.display === 'flex' || component.style.display === 'flex') {
SidebarUtils.createSelectControl(
'Flex Direction',
'flex-direction',
styles.flexDirection || 'row',
['row', 'row-reverse', 'column', 'column-reverse'],
this.controlsContainer
);
SidebarUtils.createSelectControl(
'Align Items',
'align-items',
styles.alignItems || 'stretch',
['stretch', 'flex-start', 'flex-end', 'center', 'baseline'],
this.controlsContainer
);
SidebarUtils.createSelectControl(
'Justify Content',
'justify-content',
styles.justifyContent || 'flex-start',
[
'flex-start',
'flex-end',
'center',
'space-between',
'space-around',
'space-evenly',
],
this.controlsContainer
);
}
if (isCanvas) {
SidebarUtils.createPageSizeSelect(this.controlsContainer, component);
SidebarUtils.createControl(
'Width',
'width', // Use 'width' property for dynamic sizing
'number',
component.offsetWidth,
this.controlsContainer,
{ min: 300, max: 2000, unit: 'px' } // Increased max for custom large sizes
);
SidebarUtils.createControl(
'Min Height',
'min-height',
'number',
parseInt(styles.minHeight) || 100,
this.controlsContainer,
{ min: 0, max: 2000, unit: 'px' }
);
SidebarUtils.createControl(
'Margin',
'margin',
'number',
parseInt(styles.margin) || 0,
this.controlsContainer,
{ min: 0, max: 100, unit: 'px' }
);
}
if (!isCanvas) {
SidebarUtils.createControl(
'Width',
'width',
'number',
component.offsetWidth,
this.controlsContainer,
{ min: 0, max: 1000, unit: 'px' }
);
SidebarUtils.createControl(
'Height',
'height',
'number',
component.offsetHeight,
this.controlsContainer,
{ min: 0, max: 1000, unit: 'px' }
);
SidebarUtils.createControl(
'Margin',
'margin',
'number',
parseInt(styles.margin) || 0,
this.controlsContainer,
{ min: 0, max: 1000, unit: 'px' }
);
SidebarUtils.createControl(
'Padding',
'padding',
'number',
parseInt(styles.padding) || 0,
this.controlsContainer,
{ min: 0, max: 1000, unit: 'px' }
);
}
SidebarUtils.createControl(
'Background Color',
'background-color',
'color',
styles.backgroundColor,
this.controlsContainer
);
SidebarUtils.createSelectControl(
'Text Alignment',
'alignment',
styles.textAlign,
['left', 'center', 'right'],
this.controlsContainer
);
SidebarUtils.createSelectControl(
'Font Family',
'font-family',
styles.fontFamily,
[
'Arial',
'Verdana',
'Helvetica',
'Times New Roman',
'Georgia',
'Courier New',
'sans-serif',
'serif',
],
this.controlsContainer
);
SidebarUtils.createControl(
'Font Size',
'font-size',
'number',
parseInt(styles.fontSize) || 16,
this.controlsContainer,
{ min: 0, max: 100, unit: 'px' }
);
SidebarUtils.createSelectControl(
'Font Weight',
'font-weight',
styles.fontWeight,
[
'normal',
'bold',
'bolder',
'lighter',
'100',
'200',
'300',
'400',
'500',
'600',
'700',
'800',
'900',
],
this.controlsContainer
);
SidebarUtils.createControl(
'Text Color',
'text-color',
'color',
styles.color || '#000000',
this.controlsContainer
);
SidebarUtils.createControl(
'Border Width',
'border-width',
'number',
parseInt(styles.borderWidth) || 0,
this.controlsContainer,
{ min: 0, max: 20, unit: 'px' }
);
SidebarUtils.createSelectControl(
'Border Style',
'border-style',
styles.borderStyle || 'none',
[
'none',
'solid',
'dashed',
'dotted',
'double',
'groove',
'ridge',
'inset',
'outset',
],
this.controlsContainer
);
SidebarUtils.createControl(
'Border Color',
'border-color',
'color',
styles.borderColor || '#000000',
this.controlsContainer
);
const bgColorInput = document.getElementById('background-color');
if (bgColorInput) {
bgColorInput.value = SidebarUtils.rgbToHex(styles.backgroundColor);
}
const textColorInput = document.getElementById('text-color');
if (textColorInput) {
textColorInput.value = SidebarUtils.rgbToHex(styles.color);
}
const borderColorInput = document.getElementById('border-color');
if (borderColorInput) {
borderColorInput.value = SidebarUtils.rgbToHex(styles.borderColor);
}
this.addListeners(component);
}
static handleInputTrigger(event) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c;
const component = CustomizationSidebar.selectedComponent;
if (!component) return;
let componentConfig;
if (component.classList.contains('table-component')) {
componentConfig =
(_a = CustomizationSidebar.basicComponentsConfig) === null ||
_a === void 0
? void 0
: _a.find(comp => comp.name === 'table');
} else if (component.classList.contains('text-component')) {
componentConfig =
(_b = CustomizationSidebar.basicComponentsConfig) === null ||
_b === void 0
? void 0
: _b.find(comp => comp.name === 'text');
} else if (component.classList.contains('header-component')) {
componentConfig =
(_c = CustomizationSidebar.basicComponentsConfig) === null ||
_c === void 0
? void 0
: _c.find(comp => comp.name === 'header');
}
if (componentConfig && componentConfig.globalExecuteFunction) {
const inputValues = {};
const allInputs =
CustomizationSidebar.functionsPanel.querySelectorAll(
'.attribute-input'
);
allInputs.forEach(input => {
const inputEl = input;
// Check the input type and get the correct value
if (inputEl.type === 'checkbox') {
inputValues[inputEl.id] = inputEl.checked ? 'true' : 'false';
} else {
inputValues[inputEl.id] = inputEl.value;
}
});
const result = yield componentConfig.globalExecuteFunction(inputValues);
const tableInstance = new TableComponent();
const textInstance = new TextComponent();
const headerInstance = new HeaderComponent();
if (result) {
textInstance.seedFormulaValues(result);
tableInstance.seedFormulaValues(result);
headerInstance.seedFormulaValues(result);
Canvas.historyManager.captureState();
}
textInstance.updateInputValues(inputValues);
tableInstance.updateInputValues(inputValues);
headerInstance.updateInputValues(inputValues);
tableInstance.evaluateRowVisibility(inputValues);
Canvas.historyManager.captureState();
}
});
}
static ShoModal(componentAttributes) {
if (componentAttributes && componentAttributes.length > 0) {
return true;
}
return false;
}
static populateFunctionalityControls(component) {
var _a, _b, _c, _d, _e;
this.functionsPanel.innerHTML = '';
let componentConfig;
let showModalButton = false;
const tableConfig =
(_a = this.basicComponentsConfig) === null || _a === void 0
? void 0
: _a.find(comp => comp.name === 'table');
if (component.classList.contains('table-component')) {
componentConfig = tableConfig;
this.ShoModal(
componentConfig === null || componentConfig === void 0
? void 0
: componentConfig.attributes
);
} else if (component.classList.contains('text-component')) {
componentConfig =
(_b = this.basicComponentsConfig) === null || _b === void 0
? void 0
: _b.find(comp => comp.name === 'text');
showModalButton = this.ShoModal(
componentConfig === null || componentConfig === void 0
? void 0
: componentConfig.attributes
);
} else if (component.classList.contains('header-component')) {
componentConfig =
(_c = this.basicComponentsConfig) === null || _c === void 0
? void 0
: _c.find(comp => comp.name === 'header');
showModalButton = this.ShoModal(
componentConfig === null || componentConfig === void 0
? void 0
: componentConfig.attributes
);
} else if (component.classList.contains('table-cell-content')) {
showModalButton = this.ShoModal(
tableConfig === null || tableConfig === void 0
? void 0
: tableConfig.attributes
);
} else if (component.classList.contains('table-row')) {
const tableInputAttr =
(_d =
tableConfig === null || tableConfig === void 0
? void 0
: tableConfig.attributes) === null || _d === void 0
? void 0
: _d.filter(input => input.type === 'Input');
if (
tableInputAttr &&
tableInputAttr.length > 0 &&
this.basicComponentsConfig &&
this.editable !== false
) {
SidebarUtils.populateRowVisibilityControls(component, tableInputAttr);
}
return;
} else if (component.classList.contains('custom-component')) {
const componentType =
(_e = Array.from(component.classList).find(cls =>
cls.endsWith('-component')
)) === null || _e === void 0
? void 0
: _e.replace('-component', '');
const customComponentsConfig =
CustomizationSidebar.customComponentsConfig;
if (
componentType &&
customComponentsConfig &&
customComponentsConfig[componentType] &&
customComponentsConfig[componentType].settingsComponentTagName
) {
const settingsComponentTagName =
customComponentsConfig[componentType].settingsComponentTagName;
let settingsElement = this.functionsPanel.querySelector(
settingsComponentTagName
);
if (!settingsElement) {
settingsElement = document.createElement(settingsComponentTagName);
this.functionsPanel.appendChild(settingsElement);
}
settingsElement.setAttribute(
'data-settings',
JSON.stringify({ targetComponentId: component.id })
);
}
}
if (
componentConfig &&
componentConfig.attributes &&
componentConfig.attributes.length > 0
) {
componentConfig.attributes.forEach(attribute => {
if (attribute.type === 'Input') {
SidebarUtils.createAttributeControls(
attribute,
this.functionsPanel,
this.handleInputTrigger
);
}
});
}
if (showModalButton) {
SidebarUtils.populateModalButton(
component,
this.functionsPanel,
this.editable
);
} else if (!componentConfig) {
this.functionsPanel.innerHTML =
'<p>No specific settings for this component.</p>';
}
}
static addListeners(component) {
var _a,
_b,
_c,
_d,
_e,
_f,
_g,
_h,
_j,
_k,
_l,
_m,
_o,
_p,
_q,
_r,
_s,
_t,
_u,
_v;
const controls = {
width: document.getElementById('width'),
height: document.getElementById('height'),
backgroundColor: document.getElementById('background-color'),
margin: document.getElementById('margin'),
padding: document.getElementById('padding'),
alignment: document.getElementById('alignment'),
fontSize: document.getElementById('font-size'),
fontWeight: document.getElementById('font-weight'),
textColor: document.getElementById('text-color'),
borderWidth: document.getElementById('border-width'),
borderStyle: document.getElementById('border-style'),
borderColor: document.getElementById('border-color'),
display: document.getElementById('display'),
fontFamily: document.getElementById('font-family'),
flexDirection: document.getElementById('flex-direction'),
alignItems: document.getElementById('align-items'),
justifyContent: document.getElementById('justify-content'),
};
const captureStateDebounced = debounce(() => {
Canvas.dispatchDesignChange();
Canvas.historyManager.captureState();
}, 300);
// Attach listeners only if the element exists
(_a = controls.width) === null || _a === void 0
? void 0
: _a.addEventListener('input', () => {
const unit = document.getElementById('width-unit').value;
component.style.width = `${controls.width.value}${unit}`;
captureStateDebounced();
});
(_b = controls.height) === null || _b === void 0
? void 0
: _b.addEventListener('input', () => {
const unit = document.getElementById('height-unit').value;
component.style.height = `${controls.height.value}${unit}`;
captureStateDebounced();
});
(_c = controls.backgroundColor) === null || _c === void 0
? void 0
: _c.addEventListener('input', () => {
component.style.backgroundColor = controls.backgroundColor.value;
document.getElementById('background-color-value').value =
controls.backgroundColor.value;
captureStateDebounced();
});
(_d = document.getElementById('background-color-value')) === null ||
_d === void 0
? void 0
: _d.addEventListener('input', e => {
const target = e.target;
component.style.backgroundColor = target.value;
document.getElementById('background-color').value = target.value;
captureStateDebounced();
});
(_e = controls.margin) === null || _e === void 0
? void 0
: _e.addEventListener('input', () => {
const unit = document.getElementById('margin-unit').value;
component.style.margin = `${controls.margin.value}${unit}`;
captureStateDebounced();
});
(_f = controls.padding) === null || _f === void 0
? void 0
: _f.addEventListener('input', () => {
const unit = document.getElementById('padding-unit').value;
component.style.padding = `${controls.padding.value}${unit}`;
captureStateDebounced();
});
(_g = controls.alignment) === null || _g === void 0
? void 0
: _g.addEventListener('change', () => {
component.style.textAlign = controls.alignment.value;
captureStateDebounced();
});
(_h = controls.fontSize) === null || _h === void 0
? void 0
: _h.addEventListener('input', () => {
const unit = document.getElementById('font-size-unit').value;
component.style.fontSize = `${controls.fontSize.value}${unit}`;
captureStateDebounced();
});
(_j = controls.fontWeight) === null || _j === void 0
? void 0
: _j.addEventListener('change', () => {
component.style.fontWeight = controls.fontWeight.value;
captureStateDebounced();
});
(_k = controls.textColor) === null || _k === void 0
? void 0
: _k.addEventListener('input', () => {
component.style.color = controls.textColor.value;
document.getElementById('text-color-value').value =
controls.textColor.value;
captureStateDebounced();
});
(_l = document.getElementById('text-color-value')) === null || _l === void 0
? void 0
: _l.addEventListener('input', e => {
const target = e.target;
component.style.color = target.value;
document.getElementById('text-color').value = target.value;
captureStateDebounced();
});
(_m = controls.borderWidth) === null || _m === void 0
? void 0
: _m.addEventListener('input', () => {
const unit = document.getElementById('border-width-unit').value;
component.style.borderWidth = `${controls.borderWidth.value}${unit}`;
captureStateDebounced();
});
(_o = controls.borderStyle) === null || _o === void 0
? void 0
: _o.addEventListener('change', () => {
component.style.borderStyle = controls.borderStyle.value;
captureStateDebounced();
});
(_p = controls.borderColor) === null || _p === void 0
? void 0
: _p.addEventListener('input', () => {
component.style.borderColor = controls.borderColor.value;
document.getElementById('border-color-value').value =
controls.borderColor.value;
captureStateDebounced();
});
(_q = document.getElementById('border-color-value')) === null ||
_q === void 0
? void 0
: _q.addEventListener('input', e => {
const target = e.target;
component.style.borderColor = target.value;
document.getElementById('border-color').value = target.value;
captureStateDebounced();
});
(_r = controls.display) === null || _r === void 0
? void 0
: _r.addEventListener('change', () => {
component.style.display = controls.display.value;
captureStateDebounced();
this.populateCssControls(component);
});
(_s = controls.flexDirection) === null || _s === void 0
? void 0
: _s.addEventListener('change', () => {
component.style.flexDirection = controls.flexDirection.value;
captureStateDebounced();
});
(_t = controls.alignItems) === null || _t === void 0
? void 0
: _t.addEventListener('change', () => {
component.style.alignItems = controls.alignItems.value;
captureStateDebounced();
});
(_u = controls.fontFamily) === null || _u === void 0
? void 0
: _u.addEventListener('change', () => {
component.style.fontFamily = controls.fontFamily.value;
captureStateDebounced();
});
(_v = controls.justifyContent) === null || _v === void 0
? void 0
: _v.addEventListener('change', () => {
component.style.justifyContent = controls.justifyContent.value;
captureStateDebounced();
});
}
static getLayersViewController() {
return this.layersViewController;
}
}
CustomizationSidebar.selectedComponent = null;
CustomizationSidebar.customComponentsConfig = null;
CustomizationSidebar.basicComponentsConfig = null;
CustomizationSidebar.showAttributeTab = undefined;