feat(main): Add base theme: This is the falcon theme out of the box.

This is falcon v3.1.2
This commit is contained in:
2025-11-18 14:04:01 +01:00
parent 3a7f2db331
commit 6849b8eefd
605 changed files with 49820 additions and 0 deletions

View File

@ -0,0 +1,42 @@
import $ from 'jquery';
class DynamicImportDOMEvents {
constructor({
importer,
events,
eventSelector,
preventDefault,
} = {}) {
this.eventSelector = eventSelector;
this.events = events;
this.eventsArray = events.split(' ');
this.preventDefault = preventDefault;
this.importer = importer;
this.fetchFiles = this.fetchFiles.bind(this);
this.bindEvents();
}
fetchFiles(e = false) {
if (e && this.preventDefault) {
e.preventDefault();
}
this.importer.loadFiles(() => {
if (e && this.eventsArray.includes(e.type)) {
$(e.target).trigger(e.type);
this.unbindEvents();
}
});
}
bindEvents() {
$(document).on(this.events, this.eventSelector, this.fetchFiles);
}
unbindEvents() {
$(document).off(this.events, this.eventSelector, this.fetchFiles);
}
}
export default DynamicImportDOMEvents;

View File

@ -0,0 +1,51 @@
import DynamicImportJqueryPlugin from '@js/theme/utils/DynamicImportJqueryPlugin';
import DynamicImportDOMEvents from '@js/theme/utils/DynamicImportDOMEvents';
export default class DynamicImportHandler {
constructor({
files,
jqueryPluginCover = null,
enableObserve = false,
observeOptions = false,
DOMEvents = false,
DOMEventsSelector = false,
DOMEventsPreventDefault = false,
onLoadFiles = () => {},
} = {}) {
this.files = files;
this.jqueryPluginCover = jqueryPluginCover;
this.enableObserve = enableObserve;
this.observeOptions = observeOptions;
this.onLoadFiles = onLoadFiles;
this.jqueryDynamicImport = false;
this.dynamicDOMEvents = false;
this.filesLoaded = false;
if (jqueryPluginCover) {
this.jqueryDynamicImport = new DynamicImportJqueryPlugin({
jqueryPluginCover,
importer: this,
});
}
if (DOMEvents && DOMEventsSelector) {
this.dynamicDOMEvents = new DynamicImportDOMEvents({
events: DOMEvents,
eventSelector: DOMEventsSelector,
preventDefault: DOMEventsPreventDefault,
importer: this,
});
}
}
loadFiles(callback = () => {}) {
if (!this.filesLoaded) {
Promise.all(this.files()).then((res) => {
callback();
this.onLoadFiles(res);
});
this.filesLoaded = true;
}
}
}

View File

@ -0,0 +1,41 @@
import $ from 'jquery';
class DynamicImportJqueryPlugin {
constructor({
jqueryPluginCover,
importer,
} = {}) {
this.jqueryPluginCover = jqueryPluginCover;
this.importer = importer;
this.jqueryFuncCalled = [];
this.setJqueryPlugin();
}
callJqueryAction() {
for (const fncCall of this.jqueryFuncCalled) {
fncCall.elem[this.jqueryPluginCover](fncCall.args);
}
}
fetchFiles() {
this.importer.loadFiles(() => this.callJqueryAction());
}
setJqueryPlugin() {
const self = this;
/* eslint-disable func-names */
$.fn[this.jqueryPluginCover] = function (args) {
self.jqueryFuncCalled.push({
elem: this,
args,
});
self.fetchFiles();
return this;
};
}
}
export default DynamicImportJqueryPlugin;

View File

@ -0,0 +1,8 @@
export default function debounce(func, timeout = 300) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => { func.apply(this, args); }, timeout);
};
}

View File

@ -0,0 +1,13 @@
/**
* Convert a template string into HTML DOM nodes
* @param {String} str The template string
* @return {Node} The template HTML
*/
const parseToHtml = (str) => {
const parser = new DOMParser();
const doc = parser.parseFromString(str, 'text/html');
return doc.body.children[0];
};
export default parseToHtml;