UNPKG

itmar-block-packages

Version:

Common React components for WordPress custom blocks, now fully TypeScript-ready.

292 lines (288 loc) 9.52 kB
'use strict'; var Swiper = require('swiper'); var modules = require('swiper/modules'); // 2. 外部変数の宣言(管理用のSetとMap) const linkedPairs = new Set(); const swiperRegistry = new Map(); function coerceDataValue(val) { if (val == null) return null; if (typeof val !== "string") return val; const t = val.trim(); if (t === "") return ""; if (t === "true") return true; if (t === "false") return false; if (t === "null") return null; // JSONっぽければJSONとして読む(swiper-info など) const looksJson = (t.startsWith("{") && t.endsWith("}")) || (t.startsWith("[") && t.endsWith("]")); if (looksJson) { try { return JSON.parse(t); } catch { // JSONとして壊れてたら文字列のまま return val; } } // 数値 const n = Number(t); if (!Number.isNaN(n) && t !== "") return n; return val; } function toDatasetKey(key) { // "swiper-id" -> "swiperId" のように変換 return key.replace(/-([a-z])/g, (_, c) => c.toUpperCase()); } function getData(el, key) { if (!el) return null; const dsKey = toDatasetKey(key); // dataset優先 if (el.dataset && dsKey in el.dataset) { return coerceDataValue(el.dataset[dsKey]); } // 念のため attribute も見ておく const attr = el.getAttribute?.(`data-${key}`); if (attr != null) return coerceDataValue(attr); return null; } /** * 二つのSwiperを連携させる */ function linkSwipers(a, b) { if (!a || !b) return; const pairKey = `${a.swiper_id}__${b.swiper_id}`; if (linkedPairs.has(pairKey)) return; linkedPairs.add(pairKey); // bがサムネならthumbs連携 if (b.is_thumbnail) { a.instance.thumbs.swiper = b.instance; a.instance.thumbs.init(); a.instance.thumbs.update(true); return; } // どちらもサムネじゃなければ相互同期 if (!a.is_thumbnail) { a.instance.on("slideChangeTransitionStart", (slider) => { b.instance.slideToLoop(slider.realIndex, undefined, false); }); b.instance.on("slideChangeTransitionStart", (slider) => { a.instance.slideToLoop(slider.realIndex, undefined, false); }); } } function tryLink(swiperObj) { // 自分が relate_id を持っていて、相手が既にいればリンク if (swiperObj.relate_id && swiperRegistry.has(swiperObj.relate_id)) { const target = swiperRegistry.get(swiperObj.relate_id); if (target) linkSwipers(swiperObj, target); } // 逆に「相手が自分を relate_id に指定していた」ケースも拾う for (const other of swiperRegistry.values()) { if (other.relate_id === swiperObj.swiper_id) { linkSwipers(other, swiperObj); } } } /** * スライダーブロックの初期化メイン関数 */ function slideBlockSwiperInit(swiperElement) { // セレクタ文字列でも、要素直接でも受け取れるようにする const el = typeof swiperElement === "string" ? document.querySelector(swiperElement) : swiperElement; if (!el) return null; const swiper_id = getData(el, "swiper-id"); const relate_id = getData(el, "relate-id"); const is_thumbnail = !!getData(el, "thumb-flg"); const swiper_info = getData(el, "swiper-info"); const parallax_obj = getData(el, "parallax-option"); const moduleArray = []; //モジュールのマッピング const effectModule = { fade_single_view: modules.EffectFade, coverflow: modules.EffectCoverflow, coverflow_2: modules.EffectCoverflow, cube: modules.EffectCube, flip: modules.EffectFlip, cards: modules.EffectCards, parallax: modules.Parallax, thumbs: modules.Thumbs, }; //エフェクトのセット if (swiper_info.effect) { if (effectModule[swiper_info.effect]) { moduleArray.push(effectModule[swiper_info.effect]); } } //モジュールを追加 moduleArray.push(effectModule["parallax"], effectModule["thumbs"]); if (!swiper_info || typeof swiper_info !== "object") { throw new Error("data-swiper-info が見つからないか、JSONとして解釈できません。"); } // パララックス設定 const parallax_option = parallax_obj != null ? { parallax: true } : {}; // オートプレイ設定 const autoplayOption = swiper_info.is_autoplay ? { freeMode: { enabled: true, momentum: false }, autoplay: { delay: swiper_info.autoplay || 3000, stopOnLastSlide: false, disableOnInteraction: false, }, } : {}; // 各エフェクトごとの詳細設定 const effectOption = { none: { centeredSlides: swiper_info.isActiveCenter, direction: swiper_info.singleDirection, speed: swiper_info.slideSpeed, slidesPerView: swiper_info.mobilePerView, spaceBetween: swiper_info.mobileBetween, breakpoints: { 768: { slidesPerView: swiper_info.defaultPerView, spaceBetween: swiper_info.defaultBetween, }, }, }, slide_single_view: { direction: swiper_info.singleDirection, loopAdditionalSlides: 1, speed: swiper_info.slideSpeed, allowTouchMove: false, ...parallax_option, }, fade_single_view: { speed: swiper_info.slideSpeed, effect: "fade", fadeEffect: { crossFade: true }, ...parallax_option, }, coverflow: { centeredSlides: true, slidesPerView: 3, spaceBetween: swiper_info.mobileBetween, effect: "coverflow", coverflowEffect: { rotate: 50, depth: 100, stretch: 0, modifier: 1, scale: 0.9, slideShadows: true, }, breakpoints: { 768: { spaceBetween: swiper_info.defaultBetween, coverflowEffect: { stretch: 0 }, }, }, }, coverflow_2: { centeredSlides: true, slidesPerView: "auto", effect: "coverflow", coverflowEffect: { rotate: 0, slideShadows: false, stretch: 100 }, breakpoints: { 768: { coverflowEffect: { stretch: 100 } } }, }, cube: { speed: 800, effect: "cube", cubeEffect: { slideShadows: true, shadow: true, shadowOffset: 40, shadowScale: 0.94, }, on: { slideChangeTransitionStart: function () { this.el.classList.remove("scale-in"); this.el.classList.add("scale-out"); }, slideChangeTransitionEnd: function () { this.el.classList.remove("scale-out"); this.el.classList.add("scale-in"); }, }, }, flip: { effect: "flip", flipEffect: { limitRotation: true, slideShadows: true }, }, cards: { effect: "cards", cardsEffect: { perSlideOffset: 8, perSlideRotate: 2, rotate: true, slideShadows: true, }, }, }; // 共通オプションの組み立て let swiperOptions = { loop: swiper_info.loop, ...autoplayOption, }; // サムネイル時の追加オプション if (is_thumbnail) { swiperOptions = { ...swiperOptions, watchSlidesProgress: true, freeMode: true, }; } // ナビゲーション等の設定 if (swiper_info.navigation?.disp) { moduleArray.push(modules.Navigation); swiperOptions.navigation = { nextEl: `.${swiper_id}-next`, prevEl: `.${swiper_id}-prev`, addIcons: false, }; } if (swiper_info.pagination?.disp) { moduleArray.push(modules.Pagination); swiperOptions.pagination = { el: `.${swiper_id}-pagination` }; } if (swiper_info.scrollbar?.disp) { moduleArray.push(modules.Scrollbar); swiperOptions.scrollbar = { el: `.${swiper_id}-scrollbar` }; } // エフェクトの適用 const currentEffect = swiper_info.effect || "none"; if (effectOption[currentEffect]) { swiperOptions = { ...swiperOptions, ...effectOption[currentEffect] }; } // ここが $swiperElement[0] -> el に変わる const instance = new Swiper(el, { ...swiperOptions, modules: moduleArray }); const swiperObj = { instance, swiper_id, relate_id, is_thumbnail, }; if (swiper_id) swiperRegistry.set(swiper_id, swiperObj); // 連携処理 tryLink(swiperObj); return swiperObj; } exports.slideBlockSwiperInit = slideBlockSwiperInit; //# sourceMappingURL=SwiperControl.js.map