UNPKG

@nativescript-community/svelte-native-nativescript-ui

Version:
153 lines (150 loc) 7.12 kB
import { NativeViewElementNode, logger, createElement, TemplateElement, SvelteKeyedTemplate, registerElement, NativeElementNode } from 'svelte-native/dom'; import { RadListView, ListViewViewType, ListViewLinearLayout, ListViewGridLayout, ListViewStaggeredLayout, ReorderHandle } from 'nativescript-ui-listview'; class RadListViewElement extends NativeViewElementNode { constructor() { super('radlistview', RadListView); let nativeView = this.nativeView; nativeView.itemViewLoader = (viewType) => this.loadView(viewType); this.nativeView.on(RadListView.itemLoadingEvent, (args) => { this.updateListItem(args); }); this.nativeView.on(RadListView.itemSwipeProgressStartedEvent, (args) => { this.updateSwipeItem(args); }); } loadView(viewType) { if (viewType.toLowerCase() == ListViewViewType.ItemView.toLowerCase() && typeof this.nativeElement.itemTemplates == "object") { let keyedTemplate = this.nativeElement.itemTemplates.find(t => t.key == "default"); if (keyedTemplate) { return keyedTemplate.createView(); } } let componentClass = this.getComponentForView(viewType); if (!componentClass) return null; logger.debug(() => "creating view for " + viewType); let wrapper = createElement('StackLayout', this.ownerDocument); wrapper.setStyle("padding", 0); wrapper.setStyle("margin", 0); let nativeEl = wrapper.nativeView; let builder = (props) => { let componentInstance = new componentClass({ target: wrapper, props: props }); nativeEl.__SvelteComponent__ = componentInstance; }; //for certain view types we like to delay until we have the data if (viewType.toLowerCase() == ListViewViewType.ItemView.toLowerCase() || viewType.toLowerCase() == ListViewViewType.GroupView.toLowerCase() // || viewType.toLowerCase() == ListViewViewType.ItemSwipeView.toLowerCase() doesn't work at the moment ) { nativeEl.__SvelteComponentBuilder__ = builder; } else { //otherwise, do it now 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(); let 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) { let type = childNode.getAttribute('type') || ListViewViewType.ItemView; if (type.toLowerCase() != ListViewViewType.ItemView.toLowerCase()) return; let key = childNode.getAttribute('key') || "default"; logger.debug(() => `Adding template for key ${key}`); if (!this.nativeView.itemTemplates || typeof this.nativeView.itemTemplates == "string") { this.nativeView.itemTemplates = []; } this.nativeView.itemTemplates = this.nativeView.itemTemplates.concat(new SvelteKeyedTemplate(key, childNode)); } } onRemovedChild(childNode) { super.onRemovedChild(childNode); if (childNode instanceof TemplateElement) { let type = childNode.getAttribute('type') || ListViewViewType.ItemView; if (type != ListViewViewType) return; let key = childNode.getAttribute('key') || "default"; if (this.nativeView.itemTemplates && typeof this.nativeView.itemTemplates != "string") { this.nativeView.itemTemplates = this.nativeView.itemTemplates.filter(t => t.key != key); } } } updateSwipeItem(args) { let item; let items = this.nativeElement.items; if (items.getItem) { item = items.getItem(args.index); } else { item = items[args.index]; } // logger.debug(`updating with swiped item idx: ${args.index} ${args.swipeView.bindingContext}`) this.updateViewWithProps(args.swipeView, { item }); } updateViewWithProps(view, props) { let componentInstance; let _view = view; if (!_view.__SvelteComponent__) { if (_view.__SvelteComponentBuilder__) { logger.debug(() => "mounting to view " + view + " with props " + Object.keys(props).join(",")); _view.__SvelteComponentBuilder__(props); _view.__SvelteComponentBuilder__ = null; return; } } if (_view.__SvelteComponent__) { componentInstance = _view.__SvelteComponent__; } if (componentInstance) { logger.debug(() => "updating view " + view + " with props " + Object.keys(props).join(",")); componentInstance.$set(props); } else { console.error("Couldn't find component for ", view); } } updateListItem(args) { let item; let listView = this.nativeView; let items = listView.items; if (args.index >= items.length) { logger.warn(() => "Got request for item at index that didn't exist"); return; } //groups have index less than zero if (args.index < 0) { this.updateViewWithProps(args.view, { item: args.view.bindingContext.category }); return; } if (items.getItem) { item = items.getItem(args.index); } else { item = items[args.index]; } this.updateViewWithProps(args.view, { item }); } static register() { registerElement('listViewLinearLayout', () => new NativeElementNode('listViewLinearLayout', ListViewLinearLayout)); registerElement('listViewGridLayout', () => new NativeElementNode('listViewGridLayout', ListViewGridLayout)); registerElement('listViewStaggeredLayout', () => new NativeElementNode('listViewStaggeredLayout', ListViewStaggeredLayout)); registerElement('reorderHandle', () => new NativeViewElementNode('reorderHandle', ReorderHandle)); registerElement('radlistview', () => new RadListViewElement()); } } export { RadListViewElement as default };