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,11 @@
class DynamicImportSwiperModule {
constructor(getFiles) {
this.getFiles = getFiles;
}
getModule() {
return Promise.all(this.getFiles());
}
}
export default DynamicImportSwiperModule;

View File

@ -0,0 +1,83 @@
import SwiperSlider from '@js/theme/components/sliders/SwiperSlider';
class PageSlider {
constructor() {
this.observeElementClass = 'js-slider-observed';
this.selfInitializedSlidersSelector = '.swiper:not(.swiper-custom)';
}
init() {
const self = this;
this.observer = new IntersectionObserver((entries) => {
entries.forEach(({ intersectionRatio, target }) => {
if (intersectionRatio > 0) {
self.observer.unobserve(target);
PageSlider.initSlider(target);
}
});
});
this.observerElements();
}
static initSlider(target) {
const swiper = new SwiperSlider(target, PageSlider.getConfigForSliderElement(target));
swiper.initSlider();
}
static getConfigForSliderElement(target) {
let elConfig = target.dataset.swiper || {};
if (typeof elConfig === 'string') {
elConfig = JSON.parse(elConfig);
}
const parent = target.parentElement;
const nextEl = parent.querySelector('.swiper-button-next');
const prevEl = parent.querySelector('.swiper-button-prev');
const pagination = parent.querySelector('.swiper-pagination');
if (nextEl && prevEl && typeof elConfig.navigation === 'undefined') {
elConfig = {
...elConfig,
navigation: {
nextEl,
prevEl,
},
};
}
if (pagination && typeof elConfig.pagination === 'undefined') {
elConfig = {
...elConfig,
pagination: {
el: pagination,
type: 'bullets',
clickable: true,
},
};
}
return elConfig;
}
observerElements() {
const elms = document.querySelectorAll(this.selfInitializedSlidersSelector);
for (let i = 0; i < elms.length; i += 1) {
const elem = elms[i];
if (!elem.classList.contains(this.observeElementClass)) {
this.observer.observe(elem);
elem.classList.add(this.observeElementClass);
}
}
}
refresh() {
this.observerElements();
}
}
export default PageSlider;

View File

@ -0,0 +1,124 @@
import Swiper, {
Navigation, Pagination, Autoplay,
} from 'swiper';
import DynamicImportSwiperModule from '@js/theme/components/sliders/DynamicImportSwiperModule';
/* eslint-disable */
const dynamicModulesMap = {
thumbs: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/thumbs/thumbs.js'),
],
),
virtual: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/virtual/virtual.js'),
import('@node_modules/swiper/modules/virtual/virtual.scss'),
],
),
keyboard: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/keyboard/keyboard.js'),
],
),
mousewheel: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/mousewheel/mousewheel.js'),
],
),
scrollbar: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/scrollbar/scrollbar.js'),
import('@node_modules/swiper/modules/scrollbar/scrollbar.scss'),
],
),
parallax: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/parallax/parallax.js'),
],
),
zoom: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/zoom/zoom.js'),
import('@node_modules/swiper/modules/zoom/zoom.scss'),
],
),
freeMode: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/free-mode/free-mode.js'),
import('@node_modules/swiper/modules/free-mode/free-mode.scss'),
],
),
controller: new DynamicImportSwiperModule(
() => [
import('@node_modules/swiper/modules/controller/controller.js'),
import('@node_modules/swiper/modules/controller/controller.scss'),
],
),
};
/* eslint-enable */
const defaultModules = [Navigation, Pagination, Autoplay];
class SwiperSlider {
constructor(target, options) {
this.target = target;
this.options = options;
this.modules = defaultModules;
this._modulesToFetch = [];
this.SwiperInstance = null;
}
async initSlider() {
this.findNeededModulesToFetch();
await this.fetchNeededModules();
await this.initSwiper();
return this.SwiperInstance;
}
initSwiper() {
this.SwiperInstance = new Swiper(this.target, {
...this.options,
modules: this.modules,
});
}
async fetchNeededModules() {
if (this._modulesToFetch.length > 0) {
const modulesPromisesArray = [];
for (const module of this._modulesToFetch) {
modulesPromisesArray.push(module.getFiles());
}
const allPromises = Promise.all(
modulesPromisesArray.map((innerModulesPromisesArray) => Promise.all(innerModulesPromisesArray)),
);
return allPromises.then((arrayOfModules) => {
for (const moduleImported of arrayOfModules) {
for (const module of moduleImported) {
if (typeof module.default !== 'undefined') {
this.modules = [...this.modules, module.default];
}
}
}
});
}
return Promise.resolve();
}
findNeededModulesToFetch() {
for (const dynamicModuleProp in dynamicModulesMap) {
if (Object.prototype.hasOwnProperty.call(dynamicModulesMap, dynamicModuleProp)
&& typeof this.options[dynamicModuleProp] !== 'undefined') {
this._modulesToFetch.push(dynamicModulesMap[dynamicModuleProp]);
}
}
}
}
export default SwiperSlider;