UNPKG

uicore-ts

Version:

UICore is a library to build native-like user interfaces using pure Typescript. No HTML is needed at all. Components are described as TS classes and all user interactions are handled explicitly. This library is strongly inspired by the UIKit framework tha

384 lines (383 loc) 14.1 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var UITableView_exports = {}; __export(UITableView_exports, { UITableView: () => UITableView }); module.exports = __toCommonJS(UITableView_exports); var import_UIButton = require("./UIButton"); var import_UINativeScrollView = require("./UINativeScrollView"); var import_UIObject = require("./UIObject"); var import_UIView = require("./UIView"); class UITableView extends import_UINativeScrollView.UINativeScrollView { constructor(elementID) { super(elementID); this.allRowsHaveEqualHeight = import_UIObject.NO; this._visibleRows = []; this._firstLayoutVisibleRows = []; this._rowPositions = []; this._highestValidRowPositionIndex = 0; this._reusableViews = {}; this._removedReusableViews = {}; this._rowIDIndex = 0; this.reloadsOnLanguageChange = import_UIObject.YES; this.sidePadding = 0; this._persistedData = []; this._needsDrawingOfVisibleRowsBeforeLayout = import_UIObject.NO; this._isDrawVisibleRowsScheduled = import_UIObject.NO; this.animationDuration = 0.25; this._fullHeightView = new import_UIView.UIView(); this._fullHeightView.hidden = import_UIObject.YES; this._fullHeightView.userInteractionEnabled = import_UIObject.NO; this.addSubview(this._fullHeightView); this.scrollsX = import_UIObject.NO; } loadData() { this._persistedData = []; this._calculatePositionsUntilIndex(this.numberOfRows() - 1); this._needsDrawingOfVisibleRowsBeforeLayout = import_UIObject.YES; this.setNeedsLayout(); } reloadData() { this._removeVisibleRows(); this._removeAllReusableRows(); this._rowPositions = []; this._highestValidRowPositionIndex = 0; this.loadData(); } highlightChanges(previousData, newData) { previousData = previousData.map((dataPoint) => JSON.stringify(dataPoint)); newData = newData.map((dataPoint) => JSON.stringify(dataPoint)); const newIndexes = []; newData.forEach((value, index) => { if (!previousData.contains(value)) { newIndexes.push(index); } }); newIndexes.forEach((index) => { if (this.isRowWithIndexVisible(index)) { this.highlightRowAsNew(this.visibleRowWithIndex(index)); } }); } highlightRowAsNew(row) { } invalidateSizeOfRowWithIndex(index, animateChange = import_UIObject.NO) { if (this._rowPositions[index]) { this._rowPositions[index].isValid = import_UIObject.NO; } this._highestValidRowPositionIndex = Math.min(this._highestValidRowPositionIndex, index - 1); this._needsDrawingOfVisibleRowsBeforeLayout = import_UIObject.YES; this._shouldAnimateNextLayout = animateChange; } _calculateAllPositions() { this._calculatePositionsUntilIndex(this.numberOfRows() - 1); } _calculatePositionsUntilIndex(maxIndex) { var validPositionObject = this._rowPositions[this._highestValidRowPositionIndex]; if (!(0, import_UIObject.IS)(validPositionObject)) { validPositionObject = { bottomY: 0, topY: 0, isValid: import_UIObject.YES }; } var previousBottomY = validPositionObject.bottomY; if (!this._rowPositions.length) { this._highestValidRowPositionIndex = -1; } for (var i = this._highestValidRowPositionIndex + 1; i <= maxIndex; i++) { var height; const rowPositionObject = this._rowPositions[i]; if ((0, import_UIObject.IS)((rowPositionObject || import_UIObject.nil).isValid)) { height = rowPositionObject.bottomY - rowPositionObject.topY; } else { height = this.heightForRowWithIndex(i); } const positionObject = { bottomY: previousBottomY + height, topY: previousBottomY, isValid: import_UIObject.YES }; if (i < this._rowPositions.length) { this._rowPositions[i] = positionObject; } else { this._rowPositions.push(positionObject); } this._highestValidRowPositionIndex = i; previousBottomY = previousBottomY + height; } } indexesForVisibleRows(paddingRatio = 0.5) { const firstVisibleY = this.contentOffset.y - this.bounds.height * paddingRatio; const lastVisibleY = firstVisibleY + this.bounds.height * (1 + paddingRatio); const numberOfRows = this.numberOfRows(); if (this.allRowsHaveEqualHeight) { const rowHeight = this.heightForRowWithIndex(0); var firstIndex = firstVisibleY / rowHeight; var lastIndex = lastVisibleY / rowHeight; firstIndex = Math.trunc(firstIndex); lastIndex = Math.trunc(lastIndex) + 1; firstIndex = Math.max(firstIndex, 0); lastIndex = Math.min(lastIndex, numberOfRows - 1); var result = []; for (var i = firstIndex; i < lastIndex + 1; i++) { result.push(i); } return result; } var accumulatedHeight = 0; var result = []; this._calculateAllPositions(); const rowPositions = this._rowPositions; for (var i = 0; i < numberOfRows; i++) { const height = rowPositions[i].bottomY - rowPositions[i].topY; accumulatedHeight = accumulatedHeight + height; if (accumulatedHeight >= firstVisibleY) { result.push(i); } if (accumulatedHeight >= lastVisibleY) { break; } } return result; } _removeVisibleRows() { const visibleRows = []; this._visibleRows.forEach((row) => { var _a; this._persistedData[row._UITableViewRowIndex] = this.persistenceDataItemForRowWithIndex( row._UITableViewRowIndex, row ); row.removeFromSuperview(); (_a = this._removedReusableViews[row == null ? void 0 : row._UITableViewReusabilityIdentifier]) == null ? void 0 : _a.push(row); }); this._visibleRows = visibleRows; } _removeAllReusableRows() { this._reusableViews.forEach( (rows) => rows.forEach((row) => { this._persistedData[row._UITableViewRowIndex] = this.persistenceDataItemForRowWithIndex( row._UITableViewRowIndex, row ); row.removeFromSuperview(); this._markReusableViewAsUnused(row); }) ); } _markReusableViewAsUnused(row) { if (!this._removedReusableViews[row._UITableViewReusabilityIdentifier].contains(row)) { this._removedReusableViews[row._UITableViewReusabilityIdentifier].push(row); } } _drawVisibleRows() { if (!this.isMemberOfViewTree) { return; } const visibleIndexes = this.indexesForVisibleRows(); const minIndex = visibleIndexes[0]; const maxIndex = visibleIndexes[visibleIndexes.length - 1]; const removedViews = []; const visibleRows = []; this._visibleRows.forEach((row) => { if ((0, import_UIObject.IS_DEFINED)(row._UITableViewRowIndex) && (row._UITableViewRowIndex < minIndex || row._UITableViewRowIndex > maxIndex)) { this._persistedData[row._UITableViewRowIndex] = this.persistenceDataItemForRowWithIndex( row._UITableViewRowIndex, row ); this._removedReusableViews[row._UITableViewReusabilityIdentifier].push(row); removedViews.push(row); } else { visibleRows.push(row); } }); this._visibleRows = visibleRows; visibleIndexes.forEach((rowIndex) => { if (this.isRowWithIndexVisible(rowIndex)) { return; } const view = this.viewForRowWithIndex(rowIndex); this._firstLayoutVisibleRows.push(view); this._visibleRows.push(view); this.addSubview(view); }); for (let i = 0; i < removedViews.length; i++) { const view = removedViews[i]; if (this._visibleRows.indexOf(view) == -1) { view.removeFromSuperview(); } } } visibleRowWithIndex(rowIndex) { for (var i = 0; i < this._visibleRows.length; i++) { const row = this._visibleRows[i]; if (row._UITableViewRowIndex == rowIndex) { return row; } } return import_UIObject.nil; } isRowWithIndexVisible(rowIndex) { return (0, import_UIObject.IS)(this.visibleRowWithIndex(rowIndex)); } reusableViewForIdentifier(identifier, rowIndex) { if (!this._removedReusableViews[identifier]) { this._removedReusableViews[identifier] = []; } if (this._removedReusableViews[identifier] && this._removedReusableViews[identifier].length) { const view = this._removedReusableViews[identifier].pop(); view._UITableViewRowIndex = rowIndex; Object.assign(view, this._persistedData[rowIndex] || this.defaultRowPersistenceDataItem()); return view; } if (!this._reusableViews[identifier]) { this._reusableViews[identifier] = []; } const newView = this.newReusableViewForIdentifier(identifier, this._rowIDIndex); this._rowIDIndex = this._rowIDIndex + 1; newView._UITableViewReusabilityIdentifier = identifier; newView._UITableViewRowIndex = rowIndex; Object.assign(newView, this._persistedData[rowIndex] || this.defaultRowPersistenceDataItem()); this._reusableViews[identifier].push(newView); return newView; } newReusableViewForIdentifier(identifier, rowIDIndex) { const view = new import_UIButton.UIButton(this.elementID + "Row" + rowIDIndex); view.stopsPointerEventPropagation = import_UIObject.NO; view.pausesPointerEvents = import_UIObject.NO; return view; } heightForRowWithIndex(index) { return 50; } numberOfRows() { return 1e4; } defaultRowPersistenceDataItem() { } persistenceDataItemForRowWithIndex(rowIndex, row) { } viewForRowWithIndex(rowIndex) { const row = this.reusableViewForIdentifier("Row", rowIndex); row._UITableViewRowIndex = rowIndex; (0, import_UIObject.FIRST_OR_NIL)(row.titleLabel).text = "Row " + rowIndex; return row; } didScrollToPosition(offsetPosition) { super.didScrollToPosition(offsetPosition); this.forEachViewInSubtree(function(view) { view._isPointerValid = import_UIObject.NO; }); if (!this._isDrawVisibleRowsScheduled) { this._isDrawVisibleRowsScheduled = import_UIObject.YES; import_UIView.UIView.runFunctionBeforeNextFrame(function() { this._calculateAllPositions(); this._drawVisibleRows(); this.setNeedsLayout(); this._isDrawVisibleRowsScheduled = import_UIObject.NO; }.bind(this)); } } wasAddedToViewTree() { this.loadData(); } setFrame(rectangle, zIndex, performUncheckedLayout) { const frame = this.frame; super.setFrame(rectangle, zIndex, performUncheckedLayout); if (frame.isEqualTo(rectangle) && !performUncheckedLayout) { return; } this._needsDrawingOfVisibleRowsBeforeLayout = import_UIObject.YES; } didReceiveBroadcastEvent(event) { super.didReceiveBroadcastEvent(event); if (event.name == import_UIView.UIView.broadcastEventName.LanguageChanged && this.reloadsOnLanguageChange) { this.reloadData(); } } _layoutAllRows(positions = this._rowPositions) { const bounds = this.bounds; this._visibleRows.sort((rowA, rowB) => rowA._UITableViewRowIndex - rowB._UITableViewRowIndex).forEach((row) => { const frame = bounds.copy(); const positionObject = positions[row._UITableViewRowIndex]; frame.min.y = positionObject.topY; frame.max.y = positionObject.bottomY; row.frame = frame; row.style.width = "" + (bounds.width - this.sidePadding * 2).integerValue + "px"; row.style.left = "" + this.sidePadding.integerValue + "px"; this.viewHTMLElement.appendChild(row.viewHTMLElement); }); this._fullHeightView.frame = bounds.rectangleWithHeight((positions.lastElement || import_UIObject.nil).bottomY).rectangleWithWidth(bounds.width * 0.5); this._firstLayoutVisibleRows = []; } _animateLayoutAllRows() { import_UIView.UIView.animateViewOrViewsWithDurationDelayAndFunction( this._visibleRows, this.animationDuration, 0, void 0, function() { this._layoutAllRows(); }.bind(this), function() { }.bind(this) ); } layoutSubviews() { const previousPositions = JSON.parse(JSON.stringify(this._rowPositions)); const previousVisibleRowsLength = this._visibleRows.length; if (this._needsDrawingOfVisibleRowsBeforeLayout) { this._drawVisibleRows(); this._needsDrawingOfVisibleRowsBeforeLayout = import_UIObject.NO; } super.layoutSubviews(); if (!this.numberOfRows() || !this.isMemberOfViewTree) { return; } if (this._shouldAnimateNextLayout) { this._layoutAllRows(previousPositions); if (previousVisibleRowsLength < this._visibleRows.length) { import_UIView.UIView.runFunctionBeforeNextFrame(function() { this._animateLayoutAllRows(); }.bind(this)); } else { this._animateLayoutAllRows(); } this._shouldAnimateNextLayout = import_UIObject.NO; } else { this._calculateAllPositions(); this._layoutAllRows(); } } intrinsicContentHeight(constrainingWidth = 0) { var result = 0; this._calculateAllPositions(); if (this._rowPositions.length) { result = this._rowPositions[this._rowPositions.length - 1].bottomY; } return result; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { UITableView }); //# sourceMappingURL=UITableView.js.map