UNPKG

@triniwiz/nativescript-pager

Version:

A Carousel/Pager plugin for NativeScript

122 lines 5.39 kB
import { NativeViewElementNode, TemplateElement, createElement, registerElement, } from "svelte-native/dom"; import { flush } from "svelte/internal"; import { Pager } from "../"; class SvelteKeyedTemplate { constructor(key, templateEl) { this.key = key; this._templateEl = templateEl; } get component() { return this._templateEl.component; } createView() { // create a proxy element to eventually contain our item (once we have one to render) // TODO is StackLayout the best choice here? const wrapper = createElement("StackLayout"); const nativeEl = wrapper.nativeView; // because of the way {N} works we cant use that wrapper as the target for the component // it will trigger uncessary {N} component updates because the parent view is already attached nativeEl.__SvelteComponentBuilder__ = (parentView, props) => { nativeEl.__SvelteComponent__ = new this.component({ target: parentView, props, }); }; return nativeEl; } } export default class PagerViewElement extends NativeViewElementNode { constructor() { super("pager", Pager); const nativeView = this.nativeView; nativeView.itemViewLoader = (viewType) => this.loadView(viewType); this.nativeView.on(Pager.itemLoadingEvent, this.updateListItem, this); } loadView(viewType) { if (Array.isArray(this.nativeElement._itemTemplatesInternal)) { const keyedTemplate = this.nativeElement._itemTemplatesInternal.find((t) => t.key === "default"); if (keyedTemplate) { return keyedTemplate.createView(); } } const componentClass = this.getComponentForView(viewType); if (!componentClass) return null; const wrapper = createElement("StackLayout"); const nativeEl = wrapper.nativeView; const builder = (parentView, props) => { nativeEl.__SvelteComponent__ = new componentClass({ target: parentView, props, }); }; // in svelte we want to add the wrapper as a child of the collectionview ourselves nativeEl.__SvelteComponentBuilder__ = builder; return nativeEl; } // For some reason itemTemplateSelector isn't defined as a "property" on radListView, so when we set the property, it is lowercase (due to svelte's forced downcasing) // we intercept and fix the case here. setAttribute(fullkey, value) { if (fullkey.toLowerCase() === "itemtemplateselector") { fullkey = "itemTemplateSelector"; } super.setAttribute(fullkey, value); } getComponentForView(viewType) { const normalizedViewType = viewType.toLowerCase(); const templateEl = this.childNodes.find((n) => n.tagName === "template" && String(n.getAttribute("type")).toLowerCase() === normalizedViewType); if (!templateEl) return null; return templateEl.component; } onInsertedChild(childNode, index) { super.onInsertedChild(childNode, index); if (childNode instanceof TemplateElement) { const key = childNode.getAttribute("key") || "default"; const templateIndex = this.nativeView._itemTemplatesInternal.findIndex((t) => t.key === key); if (templateIndex >= 0) { this.nativeView._itemTemplatesInternal.splice(templateIndex, 1, new SvelteKeyedTemplate(key, childNode)); } else { this.nativeView._itemTemplatesInternal = this.nativeView._itemTemplatesInternal.concat(new SvelteKeyedTemplate(key, childNode)); } } } onRemovedChild(childNode) { super.onRemovedChild(childNode); if (childNode instanceof TemplateElement) { const key = childNode.getAttribute("key") || "default"; if (this.nativeView._itemTemplatesInternal && typeof this.nativeView._itemTemplatesInternal !== "string") { this.nativeView._itemTemplatesInternal = this.nativeView._itemTemplatesInternal.filter((t) => t.key !== key); } } } updateListItem(args) { const _view = args.view.getChildAt(0); const props = { item: args.bindingContext, index: args.index }; const componentInstance = _view.__SvelteComponent__; if (!componentInstance) { if (_view.__SvelteComponentBuilder__) { const dummy = createElement("fragment"); _view.__SvelteComponentBuilder__(dummy, props); _view.__SvelteComponentBuilder__ = null; _view.__CollectionViewCurrentIndex__ = args.index; const nativeEl = dummy.firstElement().nativeView; _view.addChild(nativeEl); } } else { // ensure we dont do unnecessary tasks if index did not change _view.__CollectionViewCurrentIndex__ = args.index; componentInstance.$set(props); flush(); // we need to flush to make sure update is applied right away } } static register() { registerElement("pager", () => new PagerViewElement()); } } //# sourceMappingURL=index.js.map