UNPKG

@agnos-ui/core

Version:

Framework-agnostic headless component library.

290 lines (289 loc) 10.4 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const utils_stores = require("../../utils/stores.cjs"); const utils_directive = require("../../dom-CuBx1JPZ.cjs"); const EmblaCarousel = require("embla-carousel"); const tansu = require("@amadeus-it-group/tansu"); const utils_writables = require("../../writables-Bn3uhKEG.cjs"); const services_navManager = require("../../services/navManager.cjs"); const utils_widget = require("../../utils/widget.cjs"); const defaultConfig = { align: "center", container: null, containScroll: "trimSnaps", direction: "ltr", dragFree: false, dragThreshold: 10, duration: 25, loop: false, skipSnaps: false, plugins: [], showNavigationArrows: true, showNavigationIndicators: true, ariaPrevLabel: "Select previous slide", ariaNextLabel: "Select next slide", ariaIndicatorLabel: (index) => `Select slide ${index + 1}` }; function getCarouselDefaultConfig() { return { ...defaultConfig }; } const configValidator = { dragFree: utils_writables.typeBoolean, plugins: utils_writables.typeArray, align: utils_writables.createTypeEnum(["start", "center", "end"]), container: utils_writables.typeStringOrNull, containScroll: utils_writables.createTypeEnum([false, "trimSnaps", "keepSnaps"]), direction: utils_writables.createTypeEnum(["ltr", "rtl"]), dragThreshold: utils_writables.typeNumber, duration: utils_writables.typeNumber, loop: utils_writables.typeBoolean, skipSnaps: utils_writables.typeBoolean, showNavigationArrows: utils_writables.typeBoolean, showNavigationIndicators: utils_writables.typeBoolean, ariaPrevLabel: utils_writables.typeString, ariaNextLabel: utils_writables.typeString, ariaIndicatorLabel: utils_writables.typeFunction }; function createEmblaCarousel(options$, plugins$) { let emblaApi; const scrolling$ = tansu.writable(false); const canScrollPrev$ = tansu.writable(false); const canScrollNext$ = tansu.writable(true); const selectedScrollSnap$ = tansu.writable(0); const initialized$ = tansu.writable(false); const slideNodes$ = tansu.writable([]); const directiveArgs$ = tansu.computed(() => ({ options: options$(), plugins: plugins$ ? plugins$() : [] })); return { directive: utils_directive.bindDirective( utils_directive.browserDirective((element, { options, plugins }) => { if (emblaApi) { throw new Error("Only one Embla directive can be attached per carousel widget !"); } emblaApi = EmblaCarousel(element, options, plugins); emblaApi.on("scroll", () => { scrolling$.set(true); }); emblaApi.on("settle", () => { scrolling$.set(false); }); emblaApi.on("select", (api) => { canScrollNext$.set(api.canScrollNext()); canScrollPrev$.set(api.canScrollPrev()); selectedScrollSnap$.set(api.selectedScrollSnap()); }); emblaApi.on("init", () => { initialized$.set(true); }); emblaApi.on("reInit", (api) => { canScrollNext$.set(api.canScrollNext()); canScrollPrev$.set(api.canScrollPrev()); scrolling$.set(false); selectedScrollSnap$.set(api.selectedScrollSnap()); }); emblaApi.on("slidesChanged", (api) => { slideNodes$.set(api.slideNodes()); }); canScrollNext$.set(emblaApi.canScrollNext()); canScrollPrev$.set(emblaApi.canScrollPrev()); slideNodes$.set(emblaApi.slideNodes()); return { update: ({ options: options2, plugins: plugins2 }) => { emblaApi.reInit(options2, plugins2); }, destroy: () => { emblaApi == null ? void 0 : emblaApi.destroy(); emblaApi = void 0; initialized$.set(false); scrolling$.set(false); canScrollPrev$.set(false); canScrollNext$.set(true); selectedScrollSnap$.set(0); slideNodes$.set([]); } }; }), directiveArgs$ ), stores: { scrolling$: tansu.asReadable(scrolling$), canScrollPrev$: tansu.asReadable(canScrollPrev$), canScrollNext$: tansu.asReadable(canScrollNext$), selectedScrollSnap$: tansu.asReadable(selectedScrollSnap$), initialized$: tansu.asReadable(initialized$), slideNodes$: tansu.asReadable(slideNodes$) }, get api() { return emblaApi; } }; } const createCarousel = utils_widget.createWidgetFactory("carousel", (config) => { const [ { align$, container$, containScroll$, direction$, dragFree$, dragThreshold$, duration$, loop$, skipSnaps$, plugins$, ariaPrevLabel$, ariaNextLabel$, ariaIndicatorLabel$, showNavigationIndicators$, ...stateProps }, patch ] = utils_stores.writablesForProps(defaultConfig, config, configValidator); const emblaOptions$ = tansu.computed(() => ({ align: align$(), container: container$(), containScroll: containScroll$(), direction: direction$(), dragFree: dragFree$(), dragThreshold: dragThreshold$(), duration: duration$(), loop: loop$(), skipSnaps: skipSnaps$() })); const emblaCarousel = createEmblaCarousel(emblaOptions$, plugins$); const { stores: { slideNodes$, ...emblaStores } } = emblaCarousel; const { directive: navDirective, refreshElements, focusLeft, focusRight, focusFirst, focusLast } = services_navManager.createNavManager(); const navManagerConfig = { keys: { ArrowLeft: focusLeft, ArrowRight: focusRight, Home: focusFirst, End: focusLast }, selector: (node) => node.querySelectorAll("[role='tab']") }; return { ...utils_stores.stateStores({ ...emblaStores, ...stateProps, direction$, showNavigationIndicators$ }), patch, api: { scrollPrev: (jump) => { var _a, _b; (_b = (_a = emblaCarousel.api) == null ? void 0 : _a.scrollPrev) == null ? void 0 : _b.call(_a, jump); }, scrollNext: (jump) => { var _a, _b; (_b = (_a = emblaCarousel.api) == null ? void 0 : _a.scrollNext) == null ? void 0 : _b.call(_a, jump); }, scrollTo: (index, jump) => { var _a, _b; (_b = (_a = emblaCarousel.api) == null ? void 0 : _a.scrollTo) == null ? void 0 : _b.call(_a, index, jump); }, plugins: () => { var _a, _b; return (_b = (_a = emblaCarousel.api) == null ? void 0 : _a.plugins) == null ? void 0 : _b.call(_a); }, emblaApi: () => emblaCarousel.api }, directives: { root: utils_directive.mergeDirectives( emblaCarousel.directive, utils_directive.createAttributesDirective(() => ({ classNames: { "au-carousel": utils_stores.true$ }, attributes: { role: tansu.readable("region"), "aria-roledescription": tansu.readable("carousel"), dir: direction$ } })) ), scrollPrev: utils_directive.createAttributesDirective(() => ({ attributes: { "aria-label": ariaPrevLabel$, disabled: tansu.computed(() => !emblaCarousel.stores.canScrollPrev$() || void 0) }, events: { click: () => { var _a; return (_a = emblaCarousel.api) == null ? void 0 : _a.scrollPrev(); }, pointerdown: (event) => event.preventDefault(), touchstart: (event) => event.stopPropagation() } })), scrollNext: utils_directive.createAttributesDirective(() => ({ attributes: { "aria-label": ariaNextLabel$, disabled: tansu.computed(() => !emblaCarousel.stores.canScrollNext$() || void 0) }, events: { click: () => { var _a; return (_a = emblaCarousel.api) == null ? void 0 : _a.scrollNext(); }, pointerdown: (event) => event.preventDefault(), touchstart: (event) => event.stopPropagation() } })), tabList: utils_directive.mergeDirectives( utils_directive.bindDirective(navDirective, tansu.readable(navManagerConfig)), utils_directive.browserDirective(() => { const unsubscribe = slideNodes$.subscribe(() => { refreshElements(); }); return { destroy: unsubscribe }; }), utils_directive.createAttributesDirective(() => ({ attributes: { role: tansu.readable("tablist") } })) ), tabIndicator: utils_directive.createAttributesDirective((slide$) => ({ events: { click: () => { var _a; (_a = emblaCarousel.api) == null ? void 0 : _a.scrollTo(slide$().index, slide$().jump ?? true); } }, attributes: { "aria-label": tansu.computed(() => ariaIndicatorLabel$()(slide$().index)), "aria-selected": tansu.computed(() => slide$().index === emblaCarousel.stores.selectedScrollSnap$() ? "true" : void 0), "aria-controls": tansu.computed(() => slide$().id), role: tansu.readable("tab"), tabindex: tansu.computed(() => slide$().index === emblaCarousel.stores.selectedScrollSnap$() ? "0" : "-1") } })), slide: utils_directive.createAttributesDirective((slide$) => { const selected$ = tansu.computed(() => slide$().index === emblaCarousel.stores.selectedScrollSnap$()); return { attributes: { id: tansu.computed(() => slide$().id), "aria-hidden": tansu.computed(() => selected$() ? void 0 : "true"), role: tansu.computed(() => showNavigationIndicators$() ? "tabpanel" : "group"), "aria-roledescription": tansu.computed(() => showNavigationIndicators$() ? void 0 : "slide"), tabindex: tansu.computed(() => showNavigationIndicators$() && selected$() ? "0" : void 0) }, classNames: { "au-carousel-slide": utils_stores.true$ } }; }) } }; }); exports.createCarousel = createCarousel; exports.createEmblaCarousel = createEmblaCarousel; exports.getCarouselDefaultConfig = getCarouselDefaultConfig;