@nativescript-community/ui-pager
Version:
A NativeScript Pager / Carousel component that allows the user to swipe left and right through pages of data.
138 lines • 6.1 kB
JavaScript
import { profile } from '@nativescript/core/profiling';
import { ContentView } from '@nativescript/core/ui';
import { NativeViewElementNode, TemplateElement, createElement, registerElement, registerNativeViewElement } from 'svelte-native/dom';
//@ts-ignore
import { flush } from 'svelte/internal';
import { Pager, PagerItem } from '..';
class SvelteKeyedTemplate {
constructor(key, templateEl) {
this._key = key;
this._templateEl = templateEl;
}
get component() {
return this._templateEl.component;
}
get key() {
return this._key;
}
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') as NativeViewElementNode<View>;
const nativeEl = new ContentView();
// 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) => {
profile('__SvelteComponentBuilder__', () => {
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);
this.nativeView.on(Pager.itemDisposingEvent, this.disposeListItem, this);
}
loadView(viewType) {
if (Array.isArray(this.nativeElement.itemTemplates)) {
const keyedTemplate = this.nativeElement.itemTemplates.find((t) => t.key === 'default');
if (keyedTemplate) {
return keyedTemplate.createView();
}
}
const componentClass = this.getComponentForView(viewType);
if (!componentClass)
return null;
const nativeEl = new ContentView();
const builder = (parentView, props) => {
nativeEl.__SvelteComponent__ = new componentClass({
target: parentView,
props
});
};
// in svelte we want to add the wrapper as a child of the pager 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);
}
}
}
disposeListItem(args) {
const _view = args.view;
if (_view.__SvelteComponent__) {
_view.__SvelteComponent__.$destroy();
_view.__SvelteComponent__ = null;
}
}
updateListItem(args) {
const _view = args.view;
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.content = nativeEl;
}
}
else {
// ensure we dont do unnecessary tasks if index did not change
// console.log('updateListItem', args.index, _view.__CollectionViewCurrentIndex__);
_view.__CollectionViewCurrentIndex__ = args.index;
_view._batchUpdate(() => {
componentInstance.$set(props);
flush(); // we need to flush to make sure update is applied right away
});
}
}
static register() {
registerElement('pager', () => new PagerViewElement());
registerNativeViewElement('pageritem', () => PagerItem);
}
}
//# sourceMappingURL=index.js.map