uicore-ts 1.1.336 → 1.1.338
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiledScripts/UICore.js +1 -0
- package/compiledScripts/UICore.js.map +2 -2
- package/compiledScripts/UITableView.js +11 -2
- package/compiledScripts/UITableView.js.map +2 -2
- package/compiledScripts/UIView.d.ts +40 -0
- package/compiledScripts/UIView.js +22 -9
- package/compiledScripts/UIView.js.map +2 -2
- package/package.json +1 -1
- package/scripts/UICore.ts +2 -0
- package/scripts/UITableView.ts +17 -3
- package/scripts/UIView.ts +71 -10
|
@@ -58,6 +58,7 @@ const _UICore = class extends import_UIObject.UIObject {
|
|
|
58
58
|
}
|
|
59
59
|
);
|
|
60
60
|
const windowDidResize = () => {
|
|
61
|
+
import_UIView.UIView.resetLayoutCycleTrackingForAllViews();
|
|
61
62
|
this.rootViewController.view.forEachViewInSubtree((view) => {
|
|
62
63
|
view._frameCache = void 0;
|
|
63
64
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../scripts/UICore.ts"],
|
|
4
|
-
"sourcesContent": ["import \"./UICoreExtensions\"\nimport { UILanguageService } from \"./UIInterfaces\"\nimport { nil, NO, UIObject } from \"./UIObject\"\nimport { UIRoute } from \"./UIRoute\"\nimport { UIView } from \"./UIView\"\nimport { UIViewController } from \"./UIViewController\"\n\n\nexport class UICore extends UIObject {\n \n rootViewController: UIViewController\n \n \n \n static RootViewControllerClass: typeof UIViewController\n static main: UICore\n \n static languageService: UILanguageService = nil\n \n static readonly broadcastEventName = {\n \n \"RouteDidChange\": \"RouteDidChange\",\n \"WindowDidResize\": \"WindowDidResize\"\n \n }\n \n constructor(rootDivElementID: string, rootViewControllerClass: typeof UIViewController, public paddingLength = 20) {\n \n super()\n \n UICore.RootViewControllerClass = rootViewControllerClass\n UICore.main = UICore.main || this\n \n const rootViewElement = document.getElementById(rootDivElementID)\n const rootView = new UIView(rootDivElementID, rootViewElement)\n rootView.pausesPointerEvents = NO //YES;\n rootView.core = this\n \n if (UICore.RootViewControllerClass) {\n \n if (!(UICore.RootViewControllerClass.prototype instanceof UIViewController) ||\n (UICore.RootViewControllerClass as any) === UIViewController) {\n \n console.log(\n \"Error, UICore.RootViewControllerClass must be UIViewController or a subclass of UIViewController, \" +\n \"falling back to UIViewController.\"\n )\n \n UICore.RootViewControllerClass = UIViewController\n \n }\n \n this.rootViewController = new UICore.RootViewControllerClass(rootView)\n \n }\n else {\n \n this.rootViewController = new UIViewController(rootView)\n \n }\n \n this.rootViewController.viewWillAppear().then(() =>\n this.rootViewController.viewDidAppear()\n )\n \n \n this.rootViewController.view.addTargetForControlEvent(\n UIView.controlEvent.PointerUpInside,\n () => {\n \n (document.activeElement as HTMLElement)?.blur?.()\n \n }\n )\n \n \n const windowDidResize = () => {\n \n this.rootViewController.view.forEachViewInSubtree((view) => {\n \n view._frameCache = undefined\n \n })\n // Doing layout two times to prevent page scrollbars from confusing the layout\n this.rootViewController.view.setNeedsLayout()\n this.rootViewController._triggerLayoutViewSubviews()\n UIView.layoutViewsIfNeeded()\n \n this.rootViewController._triggerLayoutViewSubviews()\n UIView.layoutViewsIfNeeded()\n \n this.rootViewController.view.broadcastEventInSubtree({\n \n name: UICore.broadcastEventName.WindowDidResize,\n parameters: nil\n \n })\n \n }\n \n window.addEventListener(\"resize\", windowDidResize)\n \n const didScroll = () => {\n \n //code\n \n this.rootViewController.view.broadcastEventInSubtree({\n \n name: UIView.broadcastEventName.PageDidScroll,\n parameters: nil\n \n })\n \n \n }\n \n window.addEventListener(\"scroll\", didScroll, false)\n \n const hashDidChange = () => {\n \n //code\n \n this.rootViewController.handleRouteRecursively(UIRoute.currentRoute)\n \n this.rootViewController.view.broadcastEventInSubtree({\n \n name: UICore.broadcastEventName.RouteDidChange,\n parameters: nil\n \n })\n \n \n }\n \n window.addEventListener(\"hashchange\", hashDidChange, false)\n \n hashDidChange()\n \n \n }\n \n \n}\n\n\nArray.prototype.indexOf || (Array.prototype.indexOf = function (d, e) {\n let a\n if (null == this) {\n throw new TypeError(\"\\\"this\\\" is null or not defined\")\n }\n const c = Object(this),\n b = c.length >>> 0\n if (0 === b) {\n return -1\n }\n // @ts-ignore\n a = +e || 0\n Infinity === Math.abs(a) && (a = 0)\n if (a >= b) {\n return -1\n }\n for (a = Math.max(0 <= a ? a : b - Math.abs(a), 0); a < b;) {\n if (a in c && c[a] === d) {\n return a\n }\n a++\n }\n return -1\n})\n\n\n\n\n\n\n\n\n\n\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAO;AAEP,sBAAkC;AAClC,qBAAwB;AACxB,oBAAuB;AACvB,8BAAiC;AAG1B,MAAM,UAAN,cAAqB,yBAAS;AAAA,EAkBjC,YAAY,kBAA0B,yBAAyD,gBAAgB,IAAI;AAE/G,UAAM;AAFqF;AAI3F,YAAO,0BAA0B;AACjC,YAAO,OAAO,QAAO,QAAQ;AAE7B,UAAM,kBAAkB,SAAS,eAAe,gBAAgB;AAChE,UAAM,WAAW,IAAI,qBAAO,kBAAkB,eAAe;AAC7D,aAAS,sBAAsB;AAC/B,aAAS,OAAO;AAEhB,QAAI,QAAO,yBAAyB;AAEhC,UAAI,EAAE,QAAO,wBAAwB,qBAAqB,6CACrD,QAAO,4BAAoC,0CAAkB;AAE9D,gBAAQ;AAAA,UACJ;AAAA,QAEJ;AAEA,gBAAO,0BAA0B;AAAA,MAErC;AAEA,WAAK,qBAAqB,IAAI,QAAO,wBAAwB,QAAQ;AAAA,IAEzE,OACK;AAED,WAAK,qBAAqB,IAAI,yCAAiB,QAAQ;AAAA,IAE3D;AAEA,SAAK,mBAAmB,eAAe,EAAE;AAAA,MAAK,MAC1C,KAAK,mBAAmB,cAAc;AAAA,IAC1C;AAGA,SAAK,mBAAmB,KAAK;AAAA,MACzB,qBAAO,aAAa;AAAA,MACpB,MAAM;AApElB;AAsEgB,SAAC,oBAAS,kBAAT,mBAAwC,SAAxC;AAAA,MAEL;AAAA,IACJ;AAGA,UAAM,kBAAkB,MAAM;AAE1B,WAAK,mBAAmB,KAAK,qBAAqB,CAAC,SAAS;AAExD,aAAK,cAAc;AAAA,MAEvB,CAAC;AAED,WAAK,mBAAmB,KAAK,eAAe;AAC5C,WAAK,mBAAmB,2BAA2B;AACnD,2BAAO,oBAAoB;AAE3B,WAAK,mBAAmB,2BAA2B;AACnD,2BAAO,oBAAoB;AAE3B,WAAK,mBAAmB,KAAK,wBAAwB;AAAA,QAEjD,MAAM,QAAO,mBAAmB;AAAA,QAChC,YAAY;AAAA,MAEhB,CAAC;AAAA,IAEL;AAEA,WAAO,iBAAiB,UAAU,eAAe;AAEjD,UAAM,YAAY,MAAM;AAIpB,WAAK,mBAAmB,KAAK,wBAAwB;AAAA,QAEjD,MAAM,qBAAO,mBAAmB;AAAA,QAChC,YAAY;AAAA,MAEhB,CAAC;AAAA,IAGL;AAEA,WAAO,iBAAiB,UAAU,WAAW,KAAK;AAElD,UAAM,gBAAgB,MAAM;AAIxB,WAAK,mBAAmB,uBAAuB,uBAAQ,YAAY;AAEnE,WAAK,mBAAmB,KAAK,wBAAwB;AAAA,QAEjD,MAAM,QAAO,mBAAmB;AAAA,QAChC,YAAY;AAAA,MAEhB,CAAC;AAAA,IAGL;AAEA,WAAO,iBAAiB,cAAc,eAAe,KAAK;AAE1D,kBAAc;AAAA,EAGlB;AAGJ;
|
|
4
|
+
"sourcesContent": ["import \"./UICoreExtensions\"\nimport { UILanguageService } from \"./UIInterfaces\"\nimport { nil, NO, UIObject } from \"./UIObject\"\nimport { UIRoute } from \"./UIRoute\"\nimport { UIView } from \"./UIView\"\nimport { UIViewController } from \"./UIViewController\"\n\n\nexport class UICore extends UIObject {\n \n rootViewController: UIViewController\n \n \n \n static RootViewControllerClass: typeof UIViewController\n static main: UICore\n \n static languageService: UILanguageService = nil\n \n static readonly broadcastEventName = {\n \n \"RouteDidChange\": \"RouteDidChange\",\n \"WindowDidResize\": \"WindowDidResize\"\n \n }\n \n constructor(rootDivElementID: string, rootViewControllerClass: typeof UIViewController, public paddingLength = 20) {\n \n super()\n \n UICore.RootViewControllerClass = rootViewControllerClass\n UICore.main = UICore.main || this\n \n const rootViewElement = document.getElementById(rootDivElementID)\n const rootView = new UIView(rootDivElementID, rootViewElement)\n rootView.pausesPointerEvents = NO //YES;\n rootView.core = this\n \n if (UICore.RootViewControllerClass) {\n \n if (!(UICore.RootViewControllerClass.prototype instanceof UIViewController) ||\n (UICore.RootViewControllerClass as any) === UIViewController) {\n \n console.log(\n \"Error, UICore.RootViewControllerClass must be UIViewController or a subclass of UIViewController, \" +\n \"falling back to UIViewController.\"\n )\n \n UICore.RootViewControllerClass = UIViewController\n \n }\n \n this.rootViewController = new UICore.RootViewControllerClass(rootView)\n \n }\n else {\n \n this.rootViewController = new UIViewController(rootView)\n \n }\n \n this.rootViewController.viewWillAppear().then(() =>\n this.rootViewController.viewDidAppear()\n )\n \n \n this.rootViewController.view.addTargetForControlEvent(\n UIView.controlEvent.PointerUpInside,\n () => {\n \n (document.activeElement as HTMLElement)?.blur?.()\n \n }\n )\n \n \n const windowDidResize = () => {\n \n UIView.resetLayoutCycleTrackingForAllViews()\n \n this.rootViewController.view.forEachViewInSubtree((view) => {\n \n view._frameCache = undefined\n \n })\n // Doing layout two times to prevent page scrollbars from confusing the layout\n this.rootViewController.view.setNeedsLayout()\n this.rootViewController._triggerLayoutViewSubviews()\n UIView.layoutViewsIfNeeded()\n \n this.rootViewController._triggerLayoutViewSubviews()\n UIView.layoutViewsIfNeeded()\n \n this.rootViewController.view.broadcastEventInSubtree({\n \n name: UICore.broadcastEventName.WindowDidResize,\n parameters: nil\n \n })\n \n }\n \n window.addEventListener(\"resize\", windowDidResize)\n \n const didScroll = () => {\n \n //code\n \n this.rootViewController.view.broadcastEventInSubtree({\n \n name: UIView.broadcastEventName.PageDidScroll,\n parameters: nil\n \n })\n \n \n }\n \n window.addEventListener(\"scroll\", didScroll, false)\n \n const hashDidChange = () => {\n \n //code\n \n this.rootViewController.handleRouteRecursively(UIRoute.currentRoute)\n \n this.rootViewController.view.broadcastEventInSubtree({\n \n name: UICore.broadcastEventName.RouteDidChange,\n parameters: nil\n \n })\n \n \n }\n \n window.addEventListener(\"hashchange\", hashDidChange, false)\n \n hashDidChange()\n \n \n }\n \n \n}\n\n\nArray.prototype.indexOf || (Array.prototype.indexOf = function (d, e) {\n let a\n if (null == this) {\n throw new TypeError(\"\\\"this\\\" is null or not defined\")\n }\n const c = Object(this),\n b = c.length >>> 0\n if (0 === b) {\n return -1\n }\n // @ts-ignore\n a = +e || 0\n Infinity === Math.abs(a) && (a = 0)\n if (a >= b) {\n return -1\n }\n for (a = Math.max(0 <= a ? a : b - Math.abs(a), 0); a < b;) {\n if (a in c && c[a] === d) {\n return a\n }\n a++\n }\n return -1\n})\n\n\n\n\n\n\n\n\n\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -601,8 +601,17 @@ class UITableView extends import_UINativeScrollView.UINativeScrollView {
|
|
|
601
601
|
} else {
|
|
602
602
|
view = this.newReusableViewForIdentifier(identifier, this._rowIDIndex);
|
|
603
603
|
this._rowIDIndex = this._rowIDIndex + 1;
|
|
604
|
-
view.
|
|
605
|
-
|
|
604
|
+
view.configureWithObject({
|
|
605
|
+
_UITableViewReusabilityIdentifier: identifier,
|
|
606
|
+
_UITableViewRowIndex: rowIndex,
|
|
607
|
+
clearIntrinsicSizeCache: (0, import_UIObject.EXTEND)(() => {
|
|
608
|
+
const currentRowIndex = view._UITableViewRowIndex;
|
|
609
|
+
if ((0, import_UIObject.IS_DEFINED)(currentRowIndex) && view.isMemberOfViewTree) {
|
|
610
|
+
this.invalidateSizeOfRowWithIndex(currentRowIndex);
|
|
611
|
+
this.setNeedsLayout();
|
|
612
|
+
}
|
|
613
|
+
})
|
|
614
|
+
});
|
|
606
615
|
Object.assign(view, this._persistedData[rowIndex] || this.defaultRowPersistenceDataItem());
|
|
607
616
|
}
|
|
608
617
|
if (this.allRowsHaveEqualHeight) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../scripts/UITableView.ts"],
|
|
4
|
-
"sourcesContent": ["import { UIButton } from \"./UIButton\"\nimport { UINativeScrollView } from \"./UINativeScrollView\"\nimport { FIRST_OR_NIL, IF, IS, IS_DEFINED, MAKE_ID, nil, NO, YES } from \"./UIObject\"\nimport { UIPoint } from \"./UIPoint\"\nimport { UIRectangle } from \"./UIRectangle\"\nimport { UIView, UIViewBroadcastEvent } from \"./UIView\"\n\n\ninterface UITableViewRowView extends UIView {\n \n _UITableViewRowIndex?: number;\n \n}\n\n\nexport interface UITableViewReusableViewsContainerObject {\n \n [key: string]: UIView[];\n \n}\n\n\nexport interface UITableViewReusableViewPositionObject {\n \n bottomY: number;\n topY: number;\n \n isValid: boolean;\n \n}\n\n\nexport class UITableView extends UINativeScrollView {\n \n \n allRowsHaveEqualHeight: boolean = NO\n _visibleRows: UITableViewRowView[] = []\n \n /** Shared intrinsic size cache identifier used for all row views when\n * allRowsHaveEqualHeight is YES. Stable for the lifetime of the table;\n * the shared cache bucket is invalidated on reloadData and\n * clearIntrinsicSizeCache so the height is re-measured after data changes. */\n _equalRowHeightCacheIdentifier: string\n \n _rowPositions: UITableViewReusableViewPositionObject[] = []\n \n _highestValidRowPositionIndex: number = 0\n \n _unusedReusableViews: UITableViewReusableViewsContainerObject = {}\n \n _fullHeightView: UIView\n _rowIDIndex: number = 0\n reloadsOnLanguageChange = YES\n sidePadding = 0\n \n cellWeights?: number[]\n \n _persistedData: any[] = []\n _needsDrawingOfVisibleRowsBeforeLayout = NO\n _isDrawVisibleRowsScheduled = NO\n _shouldAnimateNextLayout?: boolean\n \n override usesVirtualLayoutingForIntrinsicSizing = NO\n \n override animationDuration = 0.25\n \n // Viewport scrolling properties\n _intersectionObserver?: IntersectionObserver\n \n // -------------------------------------------------------------------------\n // Keyboard navigation state\n // -------------------------------------------------------------------------\n \n /** Row index with -1 meaning the header row. undefined means no focus. */\n _keyboardFocusedRowIndex: number | undefined = undefined\n /** Cell index within the focused row. */\n _keyboardFocusedCellIndex: number = 0\n /** Total number of data columns (excludes left/right side cells). Set by CBDataView. */\n _columnCount: number = 0\n /** Called by UITableView when the focused row/cell changes. CBDataView overrides this. */\n keyboardFocusDidChange?: (rowIndex: number | undefined, cellIndex: number) => void\n /** Fired when Enter is pressed on a focused cell. Passes rowIndex and cellIndex. */\n keyboardDidActivateCell?: (rowIndex: number, cellIndex: number) => void\n \n _keydownHandler?: (event: KeyboardEvent) => void\n _keyboardListenersAttached = false\n \n \n get _reusableViews(): UITableViewReusableViewsContainerObject {\n \n const result: UITableViewReusableViewsContainerObject = {}\n \n const addView = (view: UIView) => {\n const identifier = view._UITableViewReusabilityIdentifier\n if (!identifier) {\n return\n }\n if (!result[identifier]) {\n result[identifier] = []\n }\n result[identifier].push(view)\n }\n \n this._visibleRows.forEach(addView)\n \n this._unusedReusableViews.forEach((views: UIView[]) => views.forEach(addView))\n \n return result\n \n }\n \n \n constructor(elementID?: string) {\n \n super(elementID)\n \n this._equalRowHeightCacheIdentifier = (elementID ?? MAKE_ID()) + \"_rowHeight\"\n \n this._fullHeightView = new UIView()\n this._fullHeightView.hidden = YES\n this._fullHeightView.userInteractionEnabled = NO\n this.addSubview(this._fullHeightView)\n \n this.scrollsX = NO\n \n this._setupViewportScrollAndResizeHandlersIfNeeded()\n this._setupGridAccessibility()\n this._setupKeyboardNavigation()\n \n }\n \n \n // -------------------------------------------------------------------------\n // ARIA / Accessibility setup\n // -------------------------------------------------------------------------\n \n /**\n * The element that receives tabIndex, ARIA grid role, and all keyboard/pointer\n * listeners. Defaults to the table's own element. CBDataView overrides this\n * to a container that wraps both the header and the table, so the focus ring\n * encompasses both.\n */\n _keyboardListenerElement: HTMLElement = this.viewHTMLElement\n \n _setupGridAccessibility() {\n const el = this._keyboardListenerElement\n el.setAttribute(\"role\", \"grid\")\n el.setAttribute(\"aria-rowcount\", \"0\")\n el.setAttribute(\"aria-colcount\", \"0\")\n el.tabIndex = 0\n }\n \n /** Called by CBDataView after descriptors change. */\n setColumnCount(count: number) {\n this._columnCount = count\n this._keyboardListenerElement.setAttribute(\"aria-colcount\", String(count))\n }\n \n /** Called by CBDataView after data loads. */\n setRowCount(count: number) {\n this._keyboardListenerElement.setAttribute(\"aria-rowcount\", String(count))\n }\n \n \n // -------------------------------------------------------------------------\n // Keyboard navigation\n // -------------------------------------------------------------------------\n \n _setupKeyboardNavigation() {\n \n this._keydownHandler = (event: KeyboardEvent) => {\n \n if (!this.isMemberOfViewTree) {\n return\n }\n \n const target = event.target as HTMLElement\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\") {\n return\n }\n \n const rowCount = this.numberOfRows()\n const hasHeader = this._keyboardFocusedRowIndex !== undefined\n \n if (event.key === \"ArrowDown\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex === undefined) {\n this._setKeyboardFocus(0, this._keyboardFocusedCellIndex)\n }\n else if (event.metaKey || event.ctrlKey) {\n this._setKeyboardFocus(rowCount - 1, this._keyboardFocusedCellIndex)\n }\n else if (event.altKey) {\n const pageSize = Math.max(1, Math.floor(this.bounds.height / (this._heightForAnyRow() || 50)))\n const next = Math.min(\n (this._keyboardFocusedRowIndex < 0 ? 0 : this._keyboardFocusedRowIndex) + pageSize,\n rowCount - 1\n )\n this._setKeyboardFocus(next, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex === -1) {\n this._setKeyboardFocus(0, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex < rowCount - 1) {\n this._setKeyboardFocus(this._keyboardFocusedRowIndex + 1, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"ArrowUp\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex === undefined) {\n this._setKeyboardFocus(rowCount - 1, this._keyboardFocusedCellIndex)\n }\n else if (event.metaKey || event.ctrlKey) {\n this._setKeyboardFocus(-1, this._keyboardFocusedCellIndex)\n }\n else if (event.altKey) {\n const pageSize = Math.max(1, Math.floor(this.bounds.height / (this._heightForAnyRow() || 50)))\n const prev = Math.max(\n (this._keyboardFocusedRowIndex < 0 ? 0 : this._keyboardFocusedRowIndex) - pageSize, -1)\n this._setKeyboardFocus(prev, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex === 0) {\n this._setKeyboardFocus(-1, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex > 0) {\n this._setKeyboardFocus(this._keyboardFocusedRowIndex - 1, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"ArrowRight\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined && this._columnCount > 0) {\n const nextCell = event.metaKey || event.ctrlKey\n ? this._columnCount - 1\n : Math.min(this._keyboardFocusedCellIndex + 1, this._columnCount - 1)\n this._setKeyboardFocus(this._keyboardFocusedRowIndex, nextCell)\n }\n }\n else if (event.key === \"ArrowLeft\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined && this._columnCount > 0) {\n const prevCell = event.metaKey || event.ctrlKey\n ? 0\n : Math.max(this._keyboardFocusedCellIndex - 1, 0)\n this._setKeyboardFocus(this._keyboardFocusedRowIndex, prevCell)\n }\n }\n else if (event.key === \"Home\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined) {\n this._setKeyboardFocus(this._keyboardFocusedRowIndex, 0)\n }\n }\n else if (event.key === \"End\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined && this._columnCount > 0) {\n this._setKeyboardFocus(this._keyboardFocusedRowIndex, this._columnCount - 1)\n }\n }\n else if (event.key === \"PageDown\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined) {\n const pageSize = Math.max(1, Math.floor(this.bounds.height / (this._heightForAnyRow() || 50)))\n const next = Math.min(\n (this._keyboardFocusedRowIndex < 0 ? 0 : this._keyboardFocusedRowIndex) + pageSize,\n rowCount - 1\n )\n this._setKeyboardFocus(next, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"PageUp\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined) {\n const pageSize = Math.max(1, Math.floor(this.bounds.height / (this._heightForAnyRow() || 50)))\n const prev = Math.max(\n (this._keyboardFocusedRowIndex < 0 ? 0 : this._keyboardFocusedRowIndex) - pageSize, -1)\n this._setKeyboardFocus(prev, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"Enter\" || event.key === \" \") {\n if (this._keyboardFocusedRowIndex !== undefined && this._keyboardFocusedRowIndex >= 0) {\n event.preventDefault()\n this.keyboardDidActivateCell?.(this._keyboardFocusedRowIndex, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"Escape\") {\n // Release focus from the table \u2014 move to next focusable element\n this._clearKeyboardFocus()\n this._keyboardListenerElement.blur()\n }\n \n }\n \n // Listeners are attached in wasAddedToViewTree to guarantee they land\n // on the final stable viewHTMLElement after the framework has fully\n // initialised the view.\n \n }\n \n /**\n * Move keyboard focus to a specific row and cell.\n * rowIndex = -1 means the header row.\n */\n _setKeyboardFocus(rowIndex: number, cellIndex: number) {\n \n const previousRowIndex = this._keyboardFocusedRowIndex\n const previousCellIndex = this._keyboardFocusedCellIndex\n \n // When moving to a different data row, land on the first button cell by default\n if (rowIndex >= 0 && rowIndex !== previousRowIndex) {\n const row = this.visibleRowWithIndex(rowIndex) as any\n if (row && typeof row.firstButtonCellIndex === \"function\") {\n cellIndex = row.firstButtonCellIndex()\n }\n }\n \n this._keyboardFocusedRowIndex = rowIndex\n this._keyboardFocusedCellIndex = cellIndex\n \n // Clear highlight from old position\n if (previousRowIndex !== undefined && previousRowIndex !== rowIndex) {\n this._clearKeyboardFocusOnRow(previousRowIndex)\n }\n else if (previousRowIndex === rowIndex && previousCellIndex !== cellIndex) {\n this._clearKeyboardFocusOnRow(rowIndex)\n }\n \n // Scroll the focused row into view if it is a data row\n if (rowIndex >= 0) {\n this._scrollRowIntoView(rowIndex)\n }\n \n // Apply highlight to new position\n this._applyKeyboardFocusToVisibleRows()\n \n // Notify observers (CBDataView uses this to sync header highlight)\n this.keyboardFocusDidChange?.(rowIndex, cellIndex)\n \n }\n \n _clearKeyboardFocus() {\n const previous = this._keyboardFocusedRowIndex\n this._keyboardFocusedRowIndex = undefined\n if (previous !== undefined) {\n this._clearKeyboardFocusOnRow(previous)\n }\n this.keyboardFocusDidChange?.(undefined, this._keyboardFocusedCellIndex)\n }\n \n _clearKeyboardFocusOnRow(rowIndex: number) {\n if (rowIndex === -1) {\n // Header \u2014 notify via callback; CBDataView handles the header view\n this.keyboardFocusDidChange?.(-1, -1)\n return\n }\n const row = this.visibleRowWithIndex(rowIndex) as any\n if (row && typeof row.setKeyboardFocusedCellIndex === \"function\") {\n row.setKeyboardFocusedCellIndex(undefined)\n }\n }\n \n _applyKeyboardFocusToVisibleRows(clearAll = false) {\n this._visibleRows.forEach((row: any) => {\n if (typeof row.setKeyboardFocusedCellIndex !== \"function\") {\n return\n }\n if (clearAll || row._UITableViewRowIndex !== this._keyboardFocusedRowIndex) {\n row.setKeyboardFocusedCellIndex(undefined)\n }\n else {\n row.setKeyboardFocusedCellIndex(this._keyboardFocusedCellIndex)\n }\n })\n }\n \n _scrollRowIntoView(rowIndex: number) {\n const position = this._rowPositionWithIndex(rowIndex)\n if (!position) {\n return\n }\n const offsetY = this.contentOffset.y\n const visibleHeight = this.bounds.height\n if (position.topY < offsetY) {\n const duration = this.animationDuration\n this.animationDuration = 0\n this.contentOffset = this.contentOffset.pointWithY(position.topY)\n this.animationDuration = duration\n }\n else if (position.bottomY > offsetY + visibleHeight) {\n const duration = this.animationDuration\n this.animationDuration = 0\n this.contentOffset = this.contentOffset.pointWithY(position.bottomY - visibleHeight)\n this.animationDuration = duration\n }\n }\n \n /** Expose so CBDataView can call it after loading data. */\n focusRowAtIndex(rowIndex: number, cellIndex: number = 0) {\n this._setKeyboardFocus(rowIndex, cellIndex)\n this._keyboardListenerElement.focus({ preventScroll: true })\n }\n \n \n _windowScrollHandler = () => {\n if (!this.isMemberOfViewTree) {\n return\n }\n this._scheduleDrawVisibleRows()\n }\n \n _resizeHandler = () => {\n if (!this.isMemberOfViewTree) {\n return\n }\n // Invalidate all row positions on resize as widths may have changed\n this._rowPositions.everyElement.isValid = NO\n this._highestValidRowPositionIndex = -1\n this._scheduleDrawVisibleRows()\n }\n \n _setupViewportScrollAndResizeHandlersIfNeeded() {\n if (this._intersectionObserver) {\n return\n }\n \n window.addEventListener(\"scroll\", this._windowScrollHandler, { passive: true })\n window.addEventListener(\"resize\", this._resizeHandler, { passive: true })\n \n // Use IntersectionObserver to detect when table enters/exits viewport\n this._intersectionObserver = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && this.isMemberOfViewTree) {\n this._scheduleDrawVisibleRows()\n }\n })\n },\n {\n root: null,\n rootMargin: \"100% 0px\", // Load rows 100% viewport height before/after\n threshold: 0\n }\n )\n this._intersectionObserver.observe(this.viewHTMLElement)\n }\n \n \n _cleanupViewportScrollListeners() {\n window.removeEventListener(\"scroll\", this._windowScrollHandler)\n window.removeEventListener(\"resize\", this._resizeHandler)\n if (this._intersectionObserver) {\n this._intersectionObserver.disconnect()\n this._intersectionObserver = undefined\n }\n }\n \n override wasRemovedFromViewTree() {\n super.wasRemovedFromViewTree()\n this._cleanupViewportScrollListeners()\n if (this._keydownHandler) {\n this.viewHTMLElement.removeEventListener(\"keydown\", this._keydownHandler)\n }\n // Reset so listeners are re-attached if added back to the tree\n this._keyboardListenersAttached = false\n }\n \n \n loadData() {\n \n this._persistedData = []\n \n this._calculatePositionsUntilIndex(this.numberOfRows() - 1)\n this._needsDrawingOfVisibleRowsBeforeLayout = YES\n \n this.setNeedsLayout()\n \n }\n \n reloadData() {\n \n this._removeVisibleRows()\n this._removeAllReusableRows()\n \n this._rowPositions = []\n this._highestValidRowPositionIndex = -1\n \n if (this.allRowsHaveEqualHeight) {\n UIView.invalidateSharedIntrinsicSizeCache(this._equalRowHeightCacheIdentifier)\n }\n \n this.loadData()\n \n }\n \n \n highlightChanges(previousData: any[], newData: any[]) {\n \n previousData = previousData.map(dataPoint => JSON.stringify(dataPoint))\n newData = newData.map(dataPoint => JSON.stringify(dataPoint))\n \n const newIndexes: number[] = []\n \n newData.forEach((value, index) => {\n \n if (!previousData.contains(value)) {\n \n newIndexes.push(index)\n \n }\n \n })\n \n newIndexes.forEach(index => {\n \n if (this.isRowWithIndexVisible(index)) {\n this.highlightRowAsNew(\n this.visibleRowWithIndex(index) ?? this.viewForRowWithIndex(index)\n )\n }\n \n })\n \n }\n \n \n highlightRowAsNew(row: UIView) {\n \n \n }\n \n \n invalidateSizeOfRowWithIndex(index: number, animateChange = NO) {\n if (this._rowPositions?.[index]) {\n FIRST_OR_NIL(this._rowPositions[index]).isValid = NO\n this._rowPositions.slice(index).everyElement.isValid = NO\n }\n this._highestValidRowPositionIndex = Math.min(this._highestValidRowPositionIndex, index - 1)\n this._needsDrawingOfVisibleRowsBeforeLayout = YES\n this._shouldAnimateNextLayout = animateChange\n }\n \n \n _rowPositionWithIndex(index: number, positions = this._rowPositions) {\n if (this.allRowsHaveEqualHeight && index > 0) {\n const firstPositionObject = positions[0]\n const rowHeight = firstPositionObject.bottomY - firstPositionObject.topY\n const result = {\n bottomY: rowHeight * (index + 1),\n topY: rowHeight * index,\n isValid: firstPositionObject.isValid\n }\n return result\n }\n return positions[index]\n }\n \n _calculateAllPositions() {\n this._calculatePositionsUntilIndex(this.numberOfRows() - 1)\n }\n \n _calculatePositionsUntilIndex(maxIndex: number) {\n \n if (this.allRowsHaveEqualHeight) {\n const positionObject: UITableViewReusableViewPositionObject = {\n bottomY: this._heightForAnyRow(),\n topY: 0,\n isValid: YES\n }\n this._rowPositions = [positionObject]\n return\n }\n \n let validPositionObject = this._rowPositions[this._highestValidRowPositionIndex]\n if (!IS(validPositionObject)) {\n validPositionObject = {\n bottomY: 0,\n topY: 0,\n isValid: YES\n }\n }\n \n let previousBottomY = validPositionObject.bottomY\n if (!this._rowPositions.length) {\n this._highestValidRowPositionIndex = -1\n }\n \n for (let i = this._highestValidRowPositionIndex + 1; i <= maxIndex; i++) {\n \n let height: number\n \n const rowPositionObject = this._rowPositions[i]\n \n if (IS((rowPositionObject || nil).isValid)) {\n height = rowPositionObject.bottomY - rowPositionObject.topY\n }\n // Do not calculate heights if all rows have equal heights, and we already have a height\n else if (this.allRowsHaveEqualHeight && i > 0) {\n height = this._rowPositions[0].bottomY - this._rowPositions[0].topY\n }\n else {\n height = this.heightForRowWithIndex(i)\n }\n \n const positionObject: UITableViewReusableViewPositionObject = {\n bottomY: previousBottomY + height,\n topY: previousBottomY,\n isValid: YES\n }\n \n if (i < this._rowPositions.length) {\n this._rowPositions[i] = positionObject\n }\n else {\n this._rowPositions.push(positionObject)\n }\n this._highestValidRowPositionIndex = i\n previousBottomY = previousBottomY + height\n \n }\n \n }\n \n \n _heightForAnyRow(calculateVisibleRows = YES) {\n return this.heightForRowWithIndex(\n this._visibleRows.firstElement?._UITableViewRowIndex ??\n (calculateVisibleRows ? this.indexesForVisibleRows().firstElement : 0) ??\n 0\n )\n }\n \n indexesForVisibleRows(paddingRatio = 0.5): number[] {\n \n // 1. Calculate the visible frame relative to the Table's bounds (0,0 is top-left of the table view)\n // This accounts for the Window viewport clipping the table if it is partially off-screen.\n const tableRect = this.viewHTMLElement.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const pageScale = UIView.pageScale\n \n // The top of the visible window relative to the view's top edge.\n // If tableRect.top is negative, the table is scrolled up and clipped by the window top.\n const visibleFrameTop = Math.max(0, -tableRect.top / pageScale)\n \n // The bottom of the visible window relative to the view's top edge.\n // We clip it to the table's actual bounds height so we don't look past the table content.\n const visibleFrameBottom = Math.min(\n this.bounds.height,\n (viewportHeight - tableRect.top) / pageScale\n )\n \n // If the table is completely off-screen, return empty\n if (visibleFrameBottom <= visibleFrameTop) {\n return []\n }\n \n // 2. Convert to Content Coordinates (Scroll Offset)\n // contentOffset.y is the internal scroll position.\n // If using viewport scrolling (full height), contentOffset.y is typically 0.\n // If using internal scrolling, this shifts the visible frame to the correct content rows.\n let firstVisibleY = this.contentOffset.y + visibleFrameTop\n let lastVisibleY = this.contentOffset.y + visibleFrameBottom\n \n // 3. Apply Padding\n // We calculate padding based on the viewport height to ensure smooth scrolling\n const paddingPx = (viewportHeight / pageScale) * paddingRatio\n firstVisibleY = Math.max(0, firstVisibleY - paddingPx)\n lastVisibleY = lastVisibleY + paddingPx\n \n const numberOfRows = this.numberOfRows()\n \n // 4. Find Indexes\n if (this.allRowsHaveEqualHeight) {\n \n const rowHeight = this._heightForAnyRow(NO)\n \n let firstIndex = Math.floor(firstVisibleY / rowHeight)\n let lastIndex = Math.floor(lastVisibleY / rowHeight)\n \n // Clamp BOTH indexes to [0, numberOfRows-1].\n // Without the upper clamp on firstIndex, when the viewport extends below the\n // last row firstIndex can exceed numberOfRows-1 while lastIndex is already\n // clamped there. firstIndex > lastIndex \u2192 empty result \u2192 _removeVisibleRows \u2192\n // browser collapses scrollHeight \u2192 scrollTop resets to 0 \u2192 rows pile at top.\n firstIndex = Math.max(0, Math.min(firstIndex, numberOfRows - 1))\n lastIndex = Math.max(0, Math.min(lastIndex, numberOfRows - 1))\n \n const result = []\n for (let i = firstIndex; i <= lastIndex; i++) {\n result.push(i)\n }\n return result\n }\n \n // Variable Heights\n this._calculateAllPositions()\n const result = []\n \n // Clamp firstVisibleY to the actual content height so that when the viewport\n // extends below the last row the intersection check still matches the final rows\n // rather than producing an empty result.\n const totalContentHeight = IF(this._rowPositions.lastElement)(() =>\n this._rowPositions.lastElement.bottomY\n ).ELSE(() =>\n 0\n )\n firstVisibleY = Math.min(firstVisibleY, totalContentHeight)\n \n for (let i = 0; i < numberOfRows; i++) {\n \n const position = this._rowPositionWithIndex(i)\n if (!position) {\n break\n }\n \n const rowTop = position.topY\n const rowBottom = position.bottomY\n \n // Check intersection\n if (rowBottom >= firstVisibleY && rowTop <= lastVisibleY) {\n result.push(i)\n }\n \n if (rowTop > lastVisibleY) {\n break\n }\n \n }\n \n return result\n \n }\n \n \n // This is called when no rows are supposed to be visible as a performance shortcut\n _removeVisibleRows() {\n \n this._visibleRows.forEach((row: UIView) => {\n \n this._persistedData[row._UITableViewRowIndex as number] = this.persistenceDataItemForRowWithIndex(\n row._UITableViewRowIndex as number,\n row\n )\n row.removeFromSuperview()\n this._markReusableViewAsUnused(row)\n \n })\n this._visibleRows = []\n \n }\n \n \n _removeAllReusableRows() {\n this._unusedReusableViews.forEach((rows: UIView[]) =>\n rows.forEach((row: UIView) => {\n \n this._persistedData[row._UITableViewRowIndex as number] = this.persistenceDataItemForRowWithIndex(\n row._UITableViewRowIndex as number,\n row\n )\n row.removeFromSuperview()\n \n })\n )\n this._unusedReusableViews = {}\n }\n \n \n _markReusableViewAsUnused(row: UIView) {\n const identifier = row._UITableViewReusabilityIdentifier\n if (!this._unusedReusableViews[identifier]) {\n this._unusedReusableViews[identifier] = []\n }\n if (!this._unusedReusableViews[identifier].contains(row)) {\n this._unusedReusableViews[identifier].push(row)\n }\n }\n \n _scheduleDrawVisibleRows() {\n if (!this._isDrawVisibleRowsScheduled) {\n this._isDrawVisibleRowsScheduled = YES\n \n UIView.runFunctionBeforeNextFrame(() => {\n this._calculateAllPositions()\n this._drawVisibleRows()\n this.setNeedsLayout()\n this._isDrawVisibleRowsScheduled = NO\n })\n }\n }\n \n _drawVisibleRows() {\n \n if (!this.isMemberOfViewTree) {\n return\n }\n \n // Uses the unified method above\n const visibleIndexes = this.indexesForVisibleRows()\n \n // If no rows are visible, remove all current rows\n if (visibleIndexes.length === 0) {\n this._removeVisibleRows()\n return\n }\n \n const minIndex = visibleIndexes[0]\n const maxIndex = visibleIndexes[visibleIndexes.length - 1]\n \n const removedViews: UITableViewRowView[] = []\n const visibleRows: UITableViewRowView[] = []\n \n // 1. Identify rows that have moved off-screen\n this._visibleRows.forEach((row) => {\n if (IS_DEFINED(row._UITableViewRowIndex) &&\n (row._UITableViewRowIndex < minIndex || row._UITableViewRowIndex > maxIndex)) {\n \n // Persist state before removal\n this._persistedData[row._UITableViewRowIndex] = this.persistenceDataItemForRowWithIndex(\n row._UITableViewRowIndex,\n row\n )\n this._markReusableViewAsUnused(row)\n removedViews.push(row)\n }\n else {\n visibleRows.push(row)\n }\n })\n \n this._visibleRows = visibleRows\n \n // 2. Add new rows that have moved onto the screen\n visibleIndexes.forEach((rowIndex: number) => {\n // If the view is already in this._visibleRows, do nothing to it\n if (this.isRowWithIndexVisible(rowIndex)) {\n return\n }\n \n // Get view from reuse pool (marked as unused before) or make a new one\n const view: UITableViewRowView = this.viewForRowWithIndex(rowIndex)\n this._visibleRows.push(view)\n this.addSubview(view)\n \n // Ensure the row and all its children stay out of the natural tab order\n view.tabIndex = -1\n view.forEachViewInSubtree(subview => {\n subview.tabIndex = -1\n })\n })\n \n // 3. Clean up DOM\n removedViews.forEach(row => {\n // Check that the row has not been added back\n if (this._visibleRows.indexOf(row) == -1) {\n row.removeFromSuperview()\n }\n })\n \n // 4. Re-apply keyboard focus highlight after rows are re-rendered\n this._applyKeyboardFocusToVisibleRows()\n \n }\n \n \n visibleRowWithIndex(rowIndex: number | undefined): UIView | undefined {\n for (let i = 0; i < this._visibleRows.length; i++) {\n const row = this._visibleRows[i]\n if (row._UITableViewRowIndex == rowIndex) {\n return row\n }\n }\n }\n \n \n isRowWithIndexVisible(rowIndex: number) {\n return IS(this.visibleRowWithIndex(rowIndex))\n }\n \n \n reusableViewForIdentifier(identifier: string, rowIndex: number): UITableViewRowView {\n \n const visibleRowView = this.visibleRowWithIndex(rowIndex)\n if (visibleRowView?._UITableViewReusabilityIdentifier === identifier) {\n return visibleRowView\n }\n \n if (!this._unusedReusableViews[identifier]) {\n this._unusedReusableViews[identifier] = []\n }\n \n let view: UITableViewRowView\n \n if (this._unusedReusableViews[identifier]?.length) {\n \n view = this._unusedReusableViews[identifier].pop() as UITableViewRowView\n view._UITableViewRowIndex = rowIndex\n Object.assign(view, this._persistedData[rowIndex] || this.defaultRowPersistenceDataItem())\n \n }\n else {\n \n view = this.newReusableViewForIdentifier(identifier, this._rowIDIndex) as UITableViewRowView\n this._rowIDIndex = this._rowIDIndex + 1\n \n view._UITableViewReusabilityIdentifier = identifier\n view._UITableViewRowIndex = rowIndex\n \n Object.assign(view, this._persistedData[rowIndex] || this.defaultRowPersistenceDataItem())\n \n }\n \n // When all rows are uniform, opt the view into the shared height cache so\n // only the first measurement is ever computed for the whole table.\n if (this.allRowsHaveEqualHeight) {\n view.sharedIntrinsicSizeCacheIdentifier = this._equalRowHeightCacheIdentifier\n }\n else {\n view.sharedIntrinsicSizeCacheIdentifier = undefined\n }\n \n return view\n \n }\n \n \n // Functions that should be overridden to draw the correct content START\n newReusableViewForIdentifier(identifier: string, rowIDIndex: number): UIView {\n \n const view = new UIButton(this.elementID + \"Row\" + rowIDIndex)\n \n view.stopsPointerEventPropagation = NO\n view.pausesPointerEvents = NO\n \n return view\n \n }\n \n heightForRowWithIndex(index: number): number {\n return 50\n }\n \n numberOfRows() {\n return 10000\n }\n \n defaultRowPersistenceDataItem(): any {\n \n \n }\n \n persistenceDataItemForRowWithIndex(rowIndex: number, row: UIView): any {\n \n \n }\n \n viewForRowWithIndex(rowIndex: number): UITableViewRowView {\n const row = this.reusableViewForIdentifier(\"Row\", rowIndex)\n row._UITableViewRowIndex = rowIndex\n FIRST_OR_NIL((row as unknown as UIButton).titleLabel).text = \"Row \" + rowIndex\n return row\n }\n \n // Functions that should be overridden to draw the correct content END\n \n \n // Functions that trigger redrawing of the content\n override didScrollToPosition(offsetPosition: UIPoint) {\n \n super.didScrollToPosition(offsetPosition)\n \n this.forEachViewInSubtree((view: UIView) => {\n view._isPointerValid = NO\n })\n \n this._scheduleDrawVisibleRows()\n \n }\n \n override willMoveToSuperview(superview: UIView) {\n super.willMoveToSuperview(superview)\n \n if (IS(superview)) {\n // Set up viewport listeners when added to a superview\n this._setupViewportScrollAndResizeHandlersIfNeeded()\n }\n else {\n // Clean up when removed from superview\n this._cleanupViewportScrollListeners()\n }\n }\n \n override wasAddedToViewTree() {\n super.wasAddedToViewTree()\n this.loadData()\n \n // Ensure listeners are set up\n this._setupViewportScrollAndResizeHandlersIfNeeded()\n \n // Attach keyboard and pointer listeners now that the element is stable\n // in the DOM. Guarded so repeated wasAddedToViewTree calls (e.g. after\n // navigation returns) don't stack duplicate listeners.\n if (!this._keyboardListenersAttached) {\n this._keyboardListenersAttached = true\n const el = this._keyboardListenerElement\n \n el.addEventListener(\"keydown\", this._keydownHandler!)\n \n el.addEventListener(\"pointerdown\", (event: PointerEvent) => {\n const target = event.target as HTMLElement | null\n if (target?.tagName === \"INPUT\" || target?.tagName === \"TEXTAREA\") {\n return\n }\n let walkedTarget = target\n while (walkedTarget && walkedTarget !== el) {\n const viewObject = (walkedTarget as any).UIViewObject as UITableViewRowView | undefined\n if (viewObject?._UITableViewRowIndex !== undefined) {\n el.focus({ preventScroll: true })\n this._setKeyboardFocus(viewObject._UITableViewRowIndex, this._keyboardFocusedCellIndex)\n return\n }\n walkedTarget = walkedTarget.parentElement\n }\n el.focus({ preventScroll: true })\n })\n \n el.addEventListener(\"focus\", () => {\n if (this._keyboardFocusedRowIndex === undefined && this.numberOfRows() > 0) {\n this._setKeyboardFocus(0, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex !== undefined) {\n this._applyKeyboardFocusToVisibleRows()\n }\n })\n \n el.addEventListener(\"blur\", (event: FocusEvent) => {\n if (!el.contains(event.relatedTarget as Node)) {\n this._applyKeyboardFocusToVisibleRows(true)\n }\n })\n }\n \n // Remove all subviews from the browser's natural tab order.\n // The container (_keyboardListenerElement) is the single tab stop.\n // Internal navigation is handled exclusively via arrow keys.\n this.forEachViewInSubtree(view => {\n if (view !== this) {\n view.tabIndex = -1\n }\n })\n // Re-assert tabIndex=0 on the listener element \u2014 wasAddedToViewTree fires\n // on every tree insertion including navigation returns.\n this._keyboardListenerElement.tabIndex = 0\n \n }\n \n override setFrame(rectangle: UIRectangle, zIndex?: number, performUncheckedLayout?: boolean) {\n \n const frame = this.frame\n super.setFrame(rectangle, zIndex, performUncheckedLayout)\n if (frame.isEqualTo(rectangle) && !performUncheckedLayout) {\n return\n }\n \n this._needsDrawingOfVisibleRowsBeforeLayout = YES\n \n }\n \n \n override didReceiveBroadcastEvent(event: UIViewBroadcastEvent) {\n \n super.didReceiveBroadcastEvent(event)\n \n if (event.name == UIView.broadcastEventName.LanguageChanged && this.reloadsOnLanguageChange) {\n \n this.reloadData()\n \n }\n \n \n }\n \n \n override clearIntrinsicSizeCache() {\n super.clearIntrinsicSizeCache()\n if (this.allRowsHaveEqualHeight) {\n UIView.invalidateSharedIntrinsicSizeCache(this._equalRowHeightCacheIdentifier)\n }\n this.invalidateSizeOfRowWithIndex(0)\n }\n \n private _layoutAllRows(positions = this._rowPositions) {\n \n const bounds = this.bounds\n \n const sortedRows = this._visibleRows.sort(\n (rowA, rowB) => rowA._UITableViewRowIndex! - rowB._UITableViewRowIndex!\n )\n \n sortedRows.forEach((row, i) => {\n \n const frame = bounds.copy()\n \n const positionObject = this._rowPositionWithIndex(row._UITableViewRowIndex!, positions)\n frame.min.y = positionObject.topY\n frame.max.y = positionObject.bottomY\n row.frame = frame\n \n row.style.width = \"\" + (bounds.width - this.sidePadding * 2).integerValue + \"px\"\n row.style.left = \"\" + this.sidePadding.integerValue + \"px\"\n \n // Set aria-rowindex (1-based per ARIA spec)\n row.viewHTMLElement.setAttribute(\"aria-rowindex\", String((row._UITableViewRowIndex ?? 0) + 1))\n \n // Insert before the correct next sibling so DOM order always matches\n // row index order. The nextSibling check makes this a no-op when the\n // element is already in the right position, avoiding unnecessary DOM\n // mutations and the focus loss that appendChild causes.\n const nextSiblingElement = sortedRows[i + 1]?.viewHTMLElement\n ?? this._fullHeightView.viewHTMLElement\n if (row.viewHTMLElement.nextSibling !== nextSiblingElement) {\n this.viewHTMLElement.insertBefore(row.viewHTMLElement, nextSiblingElement)\n }\n \n })\n \n // Use _rowPositionWithIndex rather than positions.lastElement.\n // When allRowsHaveEqualHeight = YES, _rowPositions contains only a single\n // entry (row 0). positions.lastElement.bottomY would therefore equal just\n // ONE row's height (e.g. 50px) instead of the full content height.\n // _rowPositionWithIndex correctly uses the computed formula for equal-height\n // tables (numberOfRows \u00D7 rowHeight) and falls back to positions[N-1] otherwise.\n // This ensures _fullHeightView maintains the correct scroll height even when\n // all visible rows have been removed from the DOM (e.g. after crossing the\n // bottom edge), preventing the browser from clamping scrollTop to 0.\n const numberOfRows = this.numberOfRows()\n const fullContentHeight = numberOfRows\n ? this._rowPositionWithIndex(numberOfRows - 1, positions).bottomY\n : 0\n this._fullHeightView.frame = bounds.rectangleWithHeight(fullContentHeight)\n .rectangleWithWidth(bounds.width * 0.5)\n \n }\n \n private _animateLayoutAllRows() {\n \n UIView.animateViewOrViewsWithDurationDelayAndFunction(\n this._visibleRows,\n this.animationDuration,\n 0,\n undefined,\n () => {\n \n this._layoutAllRows()\n \n },\n () => {\n \n \n }\n )\n \n }\n \n // UITableView has usesVirtualLayoutingForIntrinsicSizing = NO and is always\n // given a fixed viewport frame by its parent \u2014 so frame.height never changes\n // between layout passes. The base didLayoutSubviews compares frame.height and\n // therefore never propagates upward, even when row positions have changed and\n // intrinsicContentHeight now returns a different value.\n // We override here to track the intrinsic content height instead, so that\n // parents (e.g. CBDataView) get their cache invalidated and re-layout whenever\n // the total row stack height changes.\n override didLayoutSubviews() {\n this.viewController?.viewDidLayoutSubviews()\n \n if (!this.isVirtualLayouting && IS(this.superview) && this.isMemberOfViewTree) {\n const currentContentHeight = this.intrinsicContentHeight()\n if (currentContentHeight !== this._lastReportedHeight) {\n this._lastReportedHeight = currentContentHeight\n this.clearIntrinsicSizeCache()\n this.superview.setNeedsLayout()\n }\n }\n }\n \n \n override layoutSubviews() {\n \n if (this.isVirtualLayouting) {\n console.error(\"layout subviews called during virtual layouting on UITableView, \" +\n \"indicating a possible error in the layout system.\")\n return\n }\n \n const previousPositions: UITableViewReusableViewPositionObject[] = JSON.parse(\n JSON.stringify(this._rowPositions))\n \n const previousVisibleRowsLength = this._visibleRows.length\n \n if (this._needsDrawingOfVisibleRowsBeforeLayout) {\n \n this._drawVisibleRows()\n \n this._needsDrawingOfVisibleRowsBeforeLayout = NO\n \n }\n \n \n super.layoutSubviews()\n \n \n if (!this.numberOfRows() || !this.isMemberOfViewTree) {\n \n return\n \n }\n \n \n if (this._shouldAnimateNextLayout) {\n \n \n // Need to do layout with the previous positions\n \n this._layoutAllRows(previousPositions)\n \n \n if (previousVisibleRowsLength < this._visibleRows.length) {\n \n \n UIView.runFunctionBeforeNextFrame(() => {\n \n this._animateLayoutAllRows()\n \n })\n \n }\n else {\n \n this._animateLayoutAllRows()\n \n }\n \n \n this._shouldAnimateNextLayout = NO\n \n }\n else {\n \n this._calculateAllPositions()\n \n this._layoutAllRows()\n \n \n }\n \n \n }\n \n \n override intrinsicContentHeight(constrainingWidth = 0) {\n \n let result = 0\n this._calculateAllPositions()\n \n const numberOfRows = this.numberOfRows()\n if (numberOfRows) {\n result = this._rowPositionWithIndex(numberOfRows - 1).bottomY\n }\n \n return result\n \n }\n \n \n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { UIButton } from \"./UIButton\"\nimport { UINativeScrollView } from \"./UINativeScrollView\"\nimport { EXTEND, FIRST_OR_NIL, IF, IS, IS_DEFINED, MAKE_ID, nil, NO, YES } from \"./UIObject\"\nimport { UIPoint } from \"./UIPoint\"\nimport { UIRectangle } from \"./UIRectangle\"\nimport { UIView, UIViewBroadcastEvent } from \"./UIView\"\n\n\ninterface UITableViewRowView extends UIView {\n \n _UITableViewRowIndex?: number;\n \n}\n\n\nexport interface UITableViewReusableViewsContainerObject {\n \n [key: string]: UIView[];\n \n}\n\n\nexport interface UITableViewReusableViewPositionObject {\n \n bottomY: number;\n topY: number;\n \n isValid: boolean;\n \n}\n\n\nexport class UITableView extends UINativeScrollView {\n \n \n allRowsHaveEqualHeight: boolean = NO\n _visibleRows: UITableViewRowView[] = []\n \n /** Shared intrinsic size cache identifier used for all row views when\n * allRowsHaveEqualHeight is YES. Stable for the lifetime of the table;\n * the shared cache bucket is invalidated on reloadData and\n * clearIntrinsicSizeCache so the height is re-measured after data changes. */\n _equalRowHeightCacheIdentifier: string\n \n _rowPositions: UITableViewReusableViewPositionObject[] = []\n \n _highestValidRowPositionIndex: number = 0\n \n _unusedReusableViews: UITableViewReusableViewsContainerObject = {}\n \n _fullHeightView: UIView\n _rowIDIndex: number = 0\n reloadsOnLanguageChange = YES\n sidePadding = 0\n \n cellWeights?: number[]\n \n _persistedData: any[] = []\n _needsDrawingOfVisibleRowsBeforeLayout = NO\n _isDrawVisibleRowsScheduled = NO\n _shouldAnimateNextLayout?: boolean\n \n override usesVirtualLayoutingForIntrinsicSizing = NO\n \n override animationDuration = 0.25\n \n // Viewport scrolling properties\n _intersectionObserver?: IntersectionObserver\n \n // -------------------------------------------------------------------------\n // Keyboard navigation state\n // -------------------------------------------------------------------------\n \n /** Row index with -1 meaning the header row. undefined means no focus. */\n _keyboardFocusedRowIndex: number | undefined = undefined\n /** Cell index within the focused row. */\n _keyboardFocusedCellIndex: number = 0\n /** Total number of data columns (excludes left/right side cells). Set by CBDataView. */\n _columnCount: number = 0\n /** Called by UITableView when the focused row/cell changes. CBDataView overrides this. */\n keyboardFocusDidChange?: (rowIndex: number | undefined, cellIndex: number) => void\n /** Fired when Enter is pressed on a focused cell. Passes rowIndex and cellIndex. */\n keyboardDidActivateCell?: (rowIndex: number, cellIndex: number) => void\n \n _keydownHandler?: (event: KeyboardEvent) => void\n _keyboardListenersAttached = false\n \n \n get _reusableViews(): UITableViewReusableViewsContainerObject {\n \n const result: UITableViewReusableViewsContainerObject = {}\n \n const addView = (view: UIView) => {\n const identifier = view._UITableViewReusabilityIdentifier\n if (!identifier) {\n return\n }\n if (!result[identifier]) {\n result[identifier] = []\n }\n result[identifier].push(view)\n }\n \n this._visibleRows.forEach(addView)\n \n this._unusedReusableViews.forEach((views: UIView[]) => views.forEach(addView))\n \n return result\n \n }\n \n \n constructor(elementID?: string) {\n \n super(elementID)\n \n this._equalRowHeightCacheIdentifier = (elementID ?? MAKE_ID()) + \"_rowHeight\"\n \n this._fullHeightView = new UIView()\n this._fullHeightView.hidden = YES\n this._fullHeightView.userInteractionEnabled = NO\n this.addSubview(this._fullHeightView)\n \n this.scrollsX = NO\n \n this._setupViewportScrollAndResizeHandlersIfNeeded()\n this._setupGridAccessibility()\n this._setupKeyboardNavigation()\n \n }\n \n \n // -------------------------------------------------------------------------\n // ARIA / Accessibility setup\n // -------------------------------------------------------------------------\n \n /**\n * The element that receives tabIndex, ARIA grid role, and all keyboard/pointer\n * listeners. Defaults to the table's own element. CBDataView overrides this\n * to a container that wraps both the header and the table, so the focus ring\n * encompasses both.\n */\n _keyboardListenerElement: HTMLElement = this.viewHTMLElement\n \n _setupGridAccessibility() {\n const el = this._keyboardListenerElement\n el.setAttribute(\"role\", \"grid\")\n el.setAttribute(\"aria-rowcount\", \"0\")\n el.setAttribute(\"aria-colcount\", \"0\")\n el.tabIndex = 0\n }\n \n /** Called by CBDataView after descriptors change. */\n setColumnCount(count: number) {\n this._columnCount = count\n this._keyboardListenerElement.setAttribute(\"aria-colcount\", String(count))\n }\n \n /** Called by CBDataView after data loads. */\n setRowCount(count: number) {\n this._keyboardListenerElement.setAttribute(\"aria-rowcount\", String(count))\n }\n \n \n // -------------------------------------------------------------------------\n // Keyboard navigation\n // -------------------------------------------------------------------------\n \n _setupKeyboardNavigation() {\n \n this._keydownHandler = (event: KeyboardEvent) => {\n \n if (!this.isMemberOfViewTree) {\n return\n }\n \n const target = event.target as HTMLElement\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\") {\n return\n }\n \n const rowCount = this.numberOfRows()\n const hasHeader = this._keyboardFocusedRowIndex !== undefined\n \n if (event.key === \"ArrowDown\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex === undefined) {\n this._setKeyboardFocus(0, this._keyboardFocusedCellIndex)\n }\n else if (event.metaKey || event.ctrlKey) {\n this._setKeyboardFocus(rowCount - 1, this._keyboardFocusedCellIndex)\n }\n else if (event.altKey) {\n const pageSize = Math.max(1, Math.floor(this.bounds.height / (this._heightForAnyRow() || 50)))\n const next = Math.min(\n (this._keyboardFocusedRowIndex < 0 ? 0 : this._keyboardFocusedRowIndex) + pageSize,\n rowCount - 1\n )\n this._setKeyboardFocus(next, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex === -1) {\n this._setKeyboardFocus(0, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex < rowCount - 1) {\n this._setKeyboardFocus(this._keyboardFocusedRowIndex + 1, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"ArrowUp\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex === undefined) {\n this._setKeyboardFocus(rowCount - 1, this._keyboardFocusedCellIndex)\n }\n else if (event.metaKey || event.ctrlKey) {\n this._setKeyboardFocus(-1, this._keyboardFocusedCellIndex)\n }\n else if (event.altKey) {\n const pageSize = Math.max(1, Math.floor(this.bounds.height / (this._heightForAnyRow() || 50)))\n const prev = Math.max(\n (this._keyboardFocusedRowIndex < 0 ? 0 : this._keyboardFocusedRowIndex) - pageSize, -1)\n this._setKeyboardFocus(prev, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex === 0) {\n this._setKeyboardFocus(-1, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex > 0) {\n this._setKeyboardFocus(this._keyboardFocusedRowIndex - 1, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"ArrowRight\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined && this._columnCount > 0) {\n const nextCell = event.metaKey || event.ctrlKey\n ? this._columnCount - 1\n : Math.min(this._keyboardFocusedCellIndex + 1, this._columnCount - 1)\n this._setKeyboardFocus(this._keyboardFocusedRowIndex, nextCell)\n }\n }\n else if (event.key === \"ArrowLeft\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined && this._columnCount > 0) {\n const prevCell = event.metaKey || event.ctrlKey\n ? 0\n : Math.max(this._keyboardFocusedCellIndex - 1, 0)\n this._setKeyboardFocus(this._keyboardFocusedRowIndex, prevCell)\n }\n }\n else if (event.key === \"Home\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined) {\n this._setKeyboardFocus(this._keyboardFocusedRowIndex, 0)\n }\n }\n else if (event.key === \"End\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined && this._columnCount > 0) {\n this._setKeyboardFocus(this._keyboardFocusedRowIndex, this._columnCount - 1)\n }\n }\n else if (event.key === \"PageDown\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined) {\n const pageSize = Math.max(1, Math.floor(this.bounds.height / (this._heightForAnyRow() || 50)))\n const next = Math.min(\n (this._keyboardFocusedRowIndex < 0 ? 0 : this._keyboardFocusedRowIndex) + pageSize,\n rowCount - 1\n )\n this._setKeyboardFocus(next, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"PageUp\") {\n event.preventDefault()\n if (this._keyboardFocusedRowIndex !== undefined) {\n const pageSize = Math.max(1, Math.floor(this.bounds.height / (this._heightForAnyRow() || 50)))\n const prev = Math.max(\n (this._keyboardFocusedRowIndex < 0 ? 0 : this._keyboardFocusedRowIndex) - pageSize, -1)\n this._setKeyboardFocus(prev, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"Enter\" || event.key === \" \") {\n if (this._keyboardFocusedRowIndex !== undefined && this._keyboardFocusedRowIndex >= 0) {\n event.preventDefault()\n this.keyboardDidActivateCell?.(this._keyboardFocusedRowIndex, this._keyboardFocusedCellIndex)\n }\n }\n else if (event.key === \"Escape\") {\n // Release focus from the table \u2014 move to next focusable element\n this._clearKeyboardFocus()\n this._keyboardListenerElement.blur()\n }\n \n }\n \n // Listeners are attached in wasAddedToViewTree to guarantee they land\n // on the final stable viewHTMLElement after the framework has fully\n // initialised the view.\n \n }\n \n /**\n * Move keyboard focus to a specific row and cell.\n * rowIndex = -1 means the header row.\n */\n _setKeyboardFocus(rowIndex: number, cellIndex: number) {\n \n const previousRowIndex = this._keyboardFocusedRowIndex\n const previousCellIndex = this._keyboardFocusedCellIndex\n \n // When moving to a different data row, land on the first button cell by default\n if (rowIndex >= 0 && rowIndex !== previousRowIndex) {\n const row = this.visibleRowWithIndex(rowIndex) as any\n if (row && typeof row.firstButtonCellIndex === \"function\") {\n cellIndex = row.firstButtonCellIndex()\n }\n }\n \n this._keyboardFocusedRowIndex = rowIndex\n this._keyboardFocusedCellIndex = cellIndex\n \n // Clear highlight from old position\n if (previousRowIndex !== undefined && previousRowIndex !== rowIndex) {\n this._clearKeyboardFocusOnRow(previousRowIndex)\n }\n else if (previousRowIndex === rowIndex && previousCellIndex !== cellIndex) {\n this._clearKeyboardFocusOnRow(rowIndex)\n }\n \n // Scroll the focused row into view if it is a data row\n if (rowIndex >= 0) {\n this._scrollRowIntoView(rowIndex)\n }\n \n // Apply highlight to new position\n this._applyKeyboardFocusToVisibleRows()\n \n // Notify observers (CBDataView uses this to sync header highlight)\n this.keyboardFocusDidChange?.(rowIndex, cellIndex)\n \n }\n \n _clearKeyboardFocus() {\n const previous = this._keyboardFocusedRowIndex\n this._keyboardFocusedRowIndex = undefined\n if (previous !== undefined) {\n this._clearKeyboardFocusOnRow(previous)\n }\n this.keyboardFocusDidChange?.(undefined, this._keyboardFocusedCellIndex)\n }\n \n _clearKeyboardFocusOnRow(rowIndex: number) {\n if (rowIndex === -1) {\n // Header \u2014 notify via callback; CBDataView handles the header view\n this.keyboardFocusDidChange?.(-1, -1)\n return\n }\n const row = this.visibleRowWithIndex(rowIndex) as any\n if (row && typeof row.setKeyboardFocusedCellIndex === \"function\") {\n row.setKeyboardFocusedCellIndex(undefined)\n }\n }\n \n _applyKeyboardFocusToVisibleRows(clearAll = false) {\n this._visibleRows.forEach((row: any) => {\n if (typeof row.setKeyboardFocusedCellIndex !== \"function\") {\n return\n }\n if (clearAll || row._UITableViewRowIndex !== this._keyboardFocusedRowIndex) {\n row.setKeyboardFocusedCellIndex(undefined)\n }\n else {\n row.setKeyboardFocusedCellIndex(this._keyboardFocusedCellIndex)\n }\n })\n }\n \n _scrollRowIntoView(rowIndex: number) {\n const position = this._rowPositionWithIndex(rowIndex)\n if (!position) {\n return\n }\n const offsetY = this.contentOffset.y\n const visibleHeight = this.bounds.height\n if (position.topY < offsetY) {\n const duration = this.animationDuration\n this.animationDuration = 0\n this.contentOffset = this.contentOffset.pointWithY(position.topY)\n this.animationDuration = duration\n }\n else if (position.bottomY > offsetY + visibleHeight) {\n const duration = this.animationDuration\n this.animationDuration = 0\n this.contentOffset = this.contentOffset.pointWithY(position.bottomY - visibleHeight)\n this.animationDuration = duration\n }\n }\n \n /** Expose so CBDataView can call it after loading data. */\n focusRowAtIndex(rowIndex: number, cellIndex: number = 0) {\n this._setKeyboardFocus(rowIndex, cellIndex)\n this._keyboardListenerElement.focus({ preventScroll: true })\n }\n \n \n _windowScrollHandler = () => {\n if (!this.isMemberOfViewTree) {\n return\n }\n this._scheduleDrawVisibleRows()\n }\n \n _resizeHandler = () => {\n if (!this.isMemberOfViewTree) {\n return\n }\n // Invalidate all row positions on resize as widths may have changed\n this._rowPositions.everyElement.isValid = NO\n this._highestValidRowPositionIndex = -1\n this._scheduleDrawVisibleRows()\n }\n \n _setupViewportScrollAndResizeHandlersIfNeeded() {\n if (this._intersectionObserver) {\n return\n }\n \n window.addEventListener(\"scroll\", this._windowScrollHandler, { passive: true })\n window.addEventListener(\"resize\", this._resizeHandler, { passive: true })\n \n // Use IntersectionObserver to detect when table enters/exits viewport\n this._intersectionObserver = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && this.isMemberOfViewTree) {\n this._scheduleDrawVisibleRows()\n }\n })\n },\n {\n root: null,\n rootMargin: \"100% 0px\", // Load rows 100% viewport height before/after\n threshold: 0\n }\n )\n this._intersectionObserver.observe(this.viewHTMLElement)\n }\n \n \n _cleanupViewportScrollListeners() {\n window.removeEventListener(\"scroll\", this._windowScrollHandler)\n window.removeEventListener(\"resize\", this._resizeHandler)\n if (this._intersectionObserver) {\n this._intersectionObserver.disconnect()\n this._intersectionObserver = undefined\n }\n }\n \n override wasRemovedFromViewTree() {\n super.wasRemovedFromViewTree()\n this._cleanupViewportScrollListeners()\n if (this._keydownHandler) {\n this.viewHTMLElement.removeEventListener(\"keydown\", this._keydownHandler)\n }\n // Reset so listeners are re-attached if added back to the tree\n this._keyboardListenersAttached = false\n }\n \n \n loadData() {\n \n this._persistedData = []\n \n this._calculatePositionsUntilIndex(this.numberOfRows() - 1)\n this._needsDrawingOfVisibleRowsBeforeLayout = YES\n \n this.setNeedsLayout()\n \n }\n \n reloadData() {\n \n this._removeVisibleRows()\n this._removeAllReusableRows()\n \n this._rowPositions = []\n this._highestValidRowPositionIndex = -1\n \n if (this.allRowsHaveEqualHeight) {\n UIView.invalidateSharedIntrinsicSizeCache(this._equalRowHeightCacheIdentifier)\n }\n \n this.loadData()\n \n }\n \n \n highlightChanges(previousData: any[], newData: any[]) {\n \n previousData = previousData.map(dataPoint => JSON.stringify(dataPoint))\n newData = newData.map(dataPoint => JSON.stringify(dataPoint))\n \n const newIndexes: number[] = []\n \n newData.forEach((value, index) => {\n \n if (!previousData.contains(value)) {\n \n newIndexes.push(index)\n \n }\n \n })\n \n newIndexes.forEach(index => {\n \n if (this.isRowWithIndexVisible(index)) {\n this.highlightRowAsNew(\n this.visibleRowWithIndex(index) ?? this.viewForRowWithIndex(index)\n )\n }\n \n })\n \n }\n \n \n highlightRowAsNew(row: UIView) {\n \n \n }\n \n \n invalidateSizeOfRowWithIndex(index: number, animateChange = NO) {\n if (this._rowPositions?.[index]) {\n FIRST_OR_NIL(this._rowPositions[index]).isValid = NO\n this._rowPositions.slice(index).everyElement.isValid = NO\n }\n this._highestValidRowPositionIndex = Math.min(this._highestValidRowPositionIndex, index - 1)\n this._needsDrawingOfVisibleRowsBeforeLayout = YES\n this._shouldAnimateNextLayout = animateChange\n }\n \n \n _rowPositionWithIndex(index: number, positions = this._rowPositions) {\n if (this.allRowsHaveEqualHeight && index > 0) {\n const firstPositionObject = positions[0]\n const rowHeight = firstPositionObject.bottomY - firstPositionObject.topY\n const result = {\n bottomY: rowHeight * (index + 1),\n topY: rowHeight * index,\n isValid: firstPositionObject.isValid\n }\n return result\n }\n return positions[index]\n }\n \n _calculateAllPositions() {\n this._calculatePositionsUntilIndex(this.numberOfRows() - 1)\n }\n \n _calculatePositionsUntilIndex(maxIndex: number) {\n \n if (this.allRowsHaveEqualHeight) {\n const positionObject: UITableViewReusableViewPositionObject = {\n bottomY: this._heightForAnyRow(),\n topY: 0,\n isValid: YES\n }\n this._rowPositions = [positionObject]\n return\n }\n \n let validPositionObject = this._rowPositions[this._highestValidRowPositionIndex]\n if (!IS(validPositionObject)) {\n validPositionObject = {\n bottomY: 0,\n topY: 0,\n isValid: YES\n }\n }\n \n let previousBottomY = validPositionObject.bottomY\n if (!this._rowPositions.length) {\n this._highestValidRowPositionIndex = -1\n }\n \n for (let i = this._highestValidRowPositionIndex + 1; i <= maxIndex; i++) {\n \n let height: number\n \n const rowPositionObject = this._rowPositions[i]\n \n if (IS((rowPositionObject || nil).isValid)) {\n height = rowPositionObject.bottomY - rowPositionObject.topY\n }\n // Do not calculate heights if all rows have equal heights, and we already have a height\n else if (this.allRowsHaveEqualHeight && i > 0) {\n height = this._rowPositions[0].bottomY - this._rowPositions[0].topY\n }\n else {\n height = this.heightForRowWithIndex(i)\n }\n \n const positionObject: UITableViewReusableViewPositionObject = {\n bottomY: previousBottomY + height,\n topY: previousBottomY,\n isValid: YES\n }\n \n if (i < this._rowPositions.length) {\n this._rowPositions[i] = positionObject\n }\n else {\n this._rowPositions.push(positionObject)\n }\n this._highestValidRowPositionIndex = i\n previousBottomY = previousBottomY + height\n \n }\n \n }\n \n \n _heightForAnyRow(calculateVisibleRows = YES) {\n return this.heightForRowWithIndex(\n this._visibleRows.firstElement?._UITableViewRowIndex ??\n (calculateVisibleRows ? this.indexesForVisibleRows().firstElement : 0) ??\n 0\n )\n }\n \n indexesForVisibleRows(paddingRatio = 0.5): number[] {\n \n // 1. Calculate the visible frame relative to the Table's bounds (0,0 is top-left of the table view)\n // This accounts for the Window viewport clipping the table if it is partially off-screen.\n const tableRect = this.viewHTMLElement.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const pageScale = UIView.pageScale\n \n // The top of the visible window relative to the view's top edge.\n // If tableRect.top is negative, the table is scrolled up and clipped by the window top.\n const visibleFrameTop = Math.max(0, -tableRect.top / pageScale)\n \n // The bottom of the visible window relative to the view's top edge.\n // We clip it to the table's actual bounds height so we don't look past the table content.\n const visibleFrameBottom = Math.min(\n this.bounds.height,\n (viewportHeight - tableRect.top) / pageScale\n )\n \n // If the table is completely off-screen, return empty\n if (visibleFrameBottom <= visibleFrameTop) {\n return []\n }\n \n // 2. Convert to Content Coordinates (Scroll Offset)\n // contentOffset.y is the internal scroll position.\n // If using viewport scrolling (full height), contentOffset.y is typically 0.\n // If using internal scrolling, this shifts the visible frame to the correct content rows.\n let firstVisibleY = this.contentOffset.y + visibleFrameTop\n let lastVisibleY = this.contentOffset.y + visibleFrameBottom\n \n // 3. Apply Padding\n // We calculate padding based on the viewport height to ensure smooth scrolling\n const paddingPx = (viewportHeight / pageScale) * paddingRatio\n firstVisibleY = Math.max(0, firstVisibleY - paddingPx)\n lastVisibleY = lastVisibleY + paddingPx\n \n const numberOfRows = this.numberOfRows()\n \n // 4. Find Indexes\n if (this.allRowsHaveEqualHeight) {\n \n const rowHeight = this._heightForAnyRow(NO)\n \n let firstIndex = Math.floor(firstVisibleY / rowHeight)\n let lastIndex = Math.floor(lastVisibleY / rowHeight)\n \n // Clamp BOTH indexes to [0, numberOfRows-1].\n // Without the upper clamp on firstIndex, when the viewport extends below the\n // last row firstIndex can exceed numberOfRows-1 while lastIndex is already\n // clamped there. firstIndex > lastIndex \u2192 empty result \u2192 _removeVisibleRows \u2192\n // browser collapses scrollHeight \u2192 scrollTop resets to 0 \u2192 rows pile at top.\n firstIndex = Math.max(0, Math.min(firstIndex, numberOfRows - 1))\n lastIndex = Math.max(0, Math.min(lastIndex, numberOfRows - 1))\n \n const result = []\n for (let i = firstIndex; i <= lastIndex; i++) {\n result.push(i)\n }\n return result\n }\n \n // Variable Heights\n this._calculateAllPositions()\n const result = []\n \n // Clamp firstVisibleY to the actual content height so that when the viewport\n // extends below the last row the intersection check still matches the final rows\n // rather than producing an empty result.\n const totalContentHeight = IF(this._rowPositions.lastElement)(() =>\n this._rowPositions.lastElement.bottomY\n ).ELSE(() =>\n 0\n )\n firstVisibleY = Math.min(firstVisibleY, totalContentHeight)\n \n for (let i = 0; i < numberOfRows; i++) {\n \n const position = this._rowPositionWithIndex(i)\n if (!position) {\n break\n }\n \n const rowTop = position.topY\n const rowBottom = position.bottomY\n \n // Check intersection\n if (rowBottom >= firstVisibleY && rowTop <= lastVisibleY) {\n result.push(i)\n }\n \n if (rowTop > lastVisibleY) {\n break\n }\n \n }\n \n return result\n \n }\n \n \n // This is called when no rows are supposed to be visible as a performance shortcut\n _removeVisibleRows() {\n \n this._visibleRows.forEach((row: UIView) => {\n \n this._persistedData[row._UITableViewRowIndex as number] = this.persistenceDataItemForRowWithIndex(\n row._UITableViewRowIndex as number,\n row\n )\n row.removeFromSuperview()\n this._markReusableViewAsUnused(row)\n \n })\n this._visibleRows = []\n \n }\n \n \n _removeAllReusableRows() {\n this._unusedReusableViews.forEach((rows: UIView[]) =>\n rows.forEach((row: UIView) => {\n \n this._persistedData[row._UITableViewRowIndex as number] = this.persistenceDataItemForRowWithIndex(\n row._UITableViewRowIndex as number,\n row\n )\n row.removeFromSuperview()\n \n })\n )\n this._unusedReusableViews = {}\n }\n \n \n _markReusableViewAsUnused(row: UIView) {\n const identifier = row._UITableViewReusabilityIdentifier\n if (!this._unusedReusableViews[identifier]) {\n this._unusedReusableViews[identifier] = []\n }\n if (!this._unusedReusableViews[identifier].contains(row)) {\n this._unusedReusableViews[identifier].push(row)\n }\n }\n \n _scheduleDrawVisibleRows() {\n if (!this._isDrawVisibleRowsScheduled) {\n this._isDrawVisibleRowsScheduled = YES\n \n UIView.runFunctionBeforeNextFrame(() => {\n this._calculateAllPositions()\n this._drawVisibleRows()\n this.setNeedsLayout()\n this._isDrawVisibleRowsScheduled = NO\n })\n }\n }\n \n _drawVisibleRows() {\n \n if (!this.isMemberOfViewTree) {\n return\n }\n \n // Uses the unified method above\n const visibleIndexes = this.indexesForVisibleRows()\n \n // If no rows are visible, remove all current rows\n if (visibleIndexes.length === 0) {\n this._removeVisibleRows()\n return\n }\n \n const minIndex = visibleIndexes[0]\n const maxIndex = visibleIndexes[visibleIndexes.length - 1]\n \n const removedViews: UITableViewRowView[] = []\n const visibleRows: UITableViewRowView[] = []\n \n // 1. Identify rows that have moved off-screen\n this._visibleRows.forEach((row) => {\n if (IS_DEFINED(row._UITableViewRowIndex) &&\n (row._UITableViewRowIndex < minIndex || row._UITableViewRowIndex > maxIndex)) {\n \n // Persist state before removal\n this._persistedData[row._UITableViewRowIndex] = this.persistenceDataItemForRowWithIndex(\n row._UITableViewRowIndex,\n row\n )\n this._markReusableViewAsUnused(row)\n removedViews.push(row)\n }\n else {\n visibleRows.push(row)\n }\n })\n \n this._visibleRows = visibleRows\n \n // 2. Add new rows that have moved onto the screen\n visibleIndexes.forEach((rowIndex: number) => {\n // If the view is already in this._visibleRows, do nothing to it\n if (this.isRowWithIndexVisible(rowIndex)) {\n return\n }\n \n // Get view from reuse pool (marked as unused before) or make a new one\n const view: UITableViewRowView = this.viewForRowWithIndex(rowIndex)\n this._visibleRows.push(view)\n this.addSubview(view)\n \n // Ensure the row and all its children stay out of the natural tab order\n view.tabIndex = -1\n view.forEachViewInSubtree(subview => {\n subview.tabIndex = -1\n })\n })\n \n // 3. Clean up DOM\n removedViews.forEach(row => {\n // Check that the row has not been added back\n if (this._visibleRows.indexOf(row) == -1) {\n row.removeFromSuperview()\n }\n })\n \n // 4. Re-apply keyboard focus highlight after rows are re-rendered\n this._applyKeyboardFocusToVisibleRows()\n \n }\n \n \n visibleRowWithIndex(rowIndex: number | undefined): UIView | undefined {\n for (let i = 0; i < this._visibleRows.length; i++) {\n const row = this._visibleRows[i]\n if (row._UITableViewRowIndex == rowIndex) {\n return row\n }\n }\n }\n \n \n isRowWithIndexVisible(rowIndex: number) {\n return IS(this.visibleRowWithIndex(rowIndex))\n }\n \n \n reusableViewForIdentifier(identifier: string, rowIndex: number): UITableViewRowView {\n \n const visibleRowView = this.visibleRowWithIndex(rowIndex)\n if (visibleRowView?._UITableViewReusabilityIdentifier === identifier) {\n return visibleRowView\n }\n \n if (!this._unusedReusableViews[identifier]) {\n this._unusedReusableViews[identifier] = []\n }\n \n let view: UITableViewRowView\n \n if (this._unusedReusableViews[identifier]?.length) {\n \n view = this._unusedReusableViews[identifier].pop() as UITableViewRowView\n view._UITableViewRowIndex = rowIndex\n Object.assign(view, this._persistedData[rowIndex] || this.defaultRowPersistenceDataItem())\n \n }\n else {\n \n view = this.newReusableViewForIdentifier(identifier, this._rowIDIndex) as UITableViewRowView\n this._rowIDIndex = this._rowIDIndex + 1\n \n view.configureWithObject({\n _UITableViewReusabilityIdentifier: identifier,\n _UITableViewRowIndex: rowIndex,\n \n // Extend clearIntrinsicSizeCache so that when the row (or any of its\n // subviews) invalidates its own size cache, the table is notified to\n // re-measure that specific row index. EXTEND preserves the original\n // implementation and appends this behaviour after it.\n clearIntrinsicSizeCache: EXTEND(() => {\n const currentRowIndex = view._UITableViewRowIndex\n if (IS_DEFINED(currentRowIndex) && view.isMemberOfViewTree) {\n this.invalidateSizeOfRowWithIndex(currentRowIndex)\n this.setNeedsLayout()\n }\n })\n })\n \n Object.assign(view, this._persistedData[rowIndex] || this.defaultRowPersistenceDataItem())\n \n }\n \n // When all rows are uniform, opt the view into the shared height cache so\n // only the first measurement is ever computed for the whole table.\n if (this.allRowsHaveEqualHeight) {\n view.sharedIntrinsicSizeCacheIdentifier = this._equalRowHeightCacheIdentifier\n }\n else {\n view.sharedIntrinsicSizeCacheIdentifier = undefined\n }\n \n return view\n \n }\n \n \n // Functions that should be overridden to draw the correct content START\n newReusableViewForIdentifier(identifier: string, rowIDIndex: number): UIView {\n \n const view = new UIButton(this.elementID + \"Row\" + rowIDIndex)\n \n view.stopsPointerEventPropagation = NO\n view.pausesPointerEvents = NO\n \n return view\n \n }\n \n heightForRowWithIndex(index: number): number {\n return 50\n }\n \n numberOfRows() {\n return 10000\n }\n \n defaultRowPersistenceDataItem(): any {\n \n \n }\n \n persistenceDataItemForRowWithIndex(rowIndex: number, row: UIView): any {\n \n \n }\n \n viewForRowWithIndex(rowIndex: number): UITableViewRowView {\n const row = this.reusableViewForIdentifier(\"Row\", rowIndex)\n row._UITableViewRowIndex = rowIndex\n FIRST_OR_NIL((row as unknown as UIButton).titleLabel).text = \"Row \" + rowIndex\n return row\n }\n \n // Functions that should be overridden to draw the correct content END\n \n \n // Functions that trigger redrawing of the content\n override didScrollToPosition(offsetPosition: UIPoint) {\n \n super.didScrollToPosition(offsetPosition)\n \n this.forEachViewInSubtree((view: UIView) => {\n view._isPointerValid = NO\n })\n \n this._scheduleDrawVisibleRows()\n \n }\n \n override willMoveToSuperview(superview: UIView) {\n super.willMoveToSuperview(superview)\n \n if (IS(superview)) {\n // Set up viewport listeners when added to a superview\n this._setupViewportScrollAndResizeHandlersIfNeeded()\n }\n else {\n // Clean up when removed from superview\n this._cleanupViewportScrollListeners()\n }\n }\n \n override wasAddedToViewTree() {\n super.wasAddedToViewTree()\n this.loadData()\n \n // Ensure listeners are set up\n this._setupViewportScrollAndResizeHandlersIfNeeded()\n \n // Attach keyboard and pointer listeners now that the element is stable\n // in the DOM. Guarded so repeated wasAddedToViewTree calls (e.g. after\n // navigation returns) don't stack duplicate listeners.\n if (!this._keyboardListenersAttached) {\n this._keyboardListenersAttached = true\n const el = this._keyboardListenerElement\n \n el.addEventListener(\"keydown\", this._keydownHandler!)\n \n el.addEventListener(\"pointerdown\", (event: PointerEvent) => {\n const target = event.target as HTMLElement | null\n if (target?.tagName === \"INPUT\" || target?.tagName === \"TEXTAREA\") {\n return\n }\n let walkedTarget = target\n while (walkedTarget && walkedTarget !== el) {\n const viewObject = (walkedTarget as any).UIViewObject as UITableViewRowView | undefined\n if (viewObject?._UITableViewRowIndex !== undefined) {\n el.focus({ preventScroll: true })\n this._setKeyboardFocus(viewObject._UITableViewRowIndex, this._keyboardFocusedCellIndex)\n return\n }\n walkedTarget = walkedTarget.parentElement\n }\n el.focus({ preventScroll: true })\n })\n \n el.addEventListener(\"focus\", () => {\n if (this._keyboardFocusedRowIndex === undefined && this.numberOfRows() > 0) {\n this._setKeyboardFocus(0, this._keyboardFocusedCellIndex)\n }\n else if (this._keyboardFocusedRowIndex !== undefined) {\n this._applyKeyboardFocusToVisibleRows()\n }\n })\n \n el.addEventListener(\"blur\", (event: FocusEvent) => {\n if (!el.contains(event.relatedTarget as Node)) {\n this._applyKeyboardFocusToVisibleRows(true)\n }\n })\n }\n \n // Remove all subviews from the browser's natural tab order.\n // The container (_keyboardListenerElement) is the single tab stop.\n // Internal navigation is handled exclusively via arrow keys.\n this.forEachViewInSubtree(view => {\n if (view !== this) {\n view.tabIndex = -1\n }\n })\n // Re-assert tabIndex=0 on the listener element \u2014 wasAddedToViewTree fires\n // on every tree insertion including navigation returns.\n this._keyboardListenerElement.tabIndex = 0\n \n }\n \n override setFrame(rectangle: UIRectangle, zIndex?: number, performUncheckedLayout?: boolean) {\n \n const frame = this.frame\n super.setFrame(rectangle, zIndex, performUncheckedLayout)\n if (frame.isEqualTo(rectangle) && !performUncheckedLayout) {\n return\n }\n \n this._needsDrawingOfVisibleRowsBeforeLayout = YES\n \n }\n \n \n override didReceiveBroadcastEvent(event: UIViewBroadcastEvent) {\n \n super.didReceiveBroadcastEvent(event)\n \n if (event.name == UIView.broadcastEventName.LanguageChanged && this.reloadsOnLanguageChange) {\n \n this.reloadData()\n \n }\n \n \n }\n \n \n override clearIntrinsicSizeCache() {\n super.clearIntrinsicSizeCache()\n if (this.allRowsHaveEqualHeight) {\n UIView.invalidateSharedIntrinsicSizeCache(this._equalRowHeightCacheIdentifier)\n }\n this.invalidateSizeOfRowWithIndex(0)\n }\n \n private _layoutAllRows(positions = this._rowPositions) {\n \n const bounds = this.bounds\n \n const sortedRows = this._visibleRows.sort(\n (rowA, rowB) => rowA._UITableViewRowIndex! - rowB._UITableViewRowIndex!\n )\n \n sortedRows.forEach((row, i) => {\n \n const frame = bounds.copy()\n \n const positionObject = this._rowPositionWithIndex(row._UITableViewRowIndex!, positions)\n frame.min.y = positionObject.topY\n frame.max.y = positionObject.bottomY\n row.frame = frame\n \n row.style.width = \"\" + (bounds.width - this.sidePadding * 2).integerValue + \"px\"\n row.style.left = \"\" + this.sidePadding.integerValue + \"px\"\n \n // Set aria-rowindex (1-based per ARIA spec)\n row.viewHTMLElement.setAttribute(\"aria-rowindex\", String((row._UITableViewRowIndex ?? 0) + 1))\n \n // Insert before the correct next sibling so DOM order always matches\n // row index order. The nextSibling check makes this a no-op when the\n // element is already in the right position, avoiding unnecessary DOM\n // mutations and the focus loss that appendChild causes.\n const nextSiblingElement = sortedRows[i + 1]?.viewHTMLElement\n ?? this._fullHeightView.viewHTMLElement\n if (row.viewHTMLElement.nextSibling !== nextSiblingElement) {\n this.viewHTMLElement.insertBefore(row.viewHTMLElement, nextSiblingElement)\n }\n \n })\n \n // Use _rowPositionWithIndex rather than positions.lastElement.\n // When allRowsHaveEqualHeight = YES, _rowPositions contains only a single\n // entry (row 0). positions.lastElement.bottomY would therefore equal just\n // ONE row's height (e.g. 50px) instead of the full content height.\n // _rowPositionWithIndex correctly uses the computed formula for equal-height\n // tables (numberOfRows \u00D7 rowHeight) and falls back to positions[N-1] otherwise.\n // This ensures _fullHeightView maintains the correct scroll height even when\n // all visible rows have been removed from the DOM (e.g. after crossing the\n // bottom edge), preventing the browser from clamping scrollTop to 0.\n const numberOfRows = this.numberOfRows()\n const fullContentHeight = numberOfRows\n ? this._rowPositionWithIndex(numberOfRows - 1, positions).bottomY\n : 0\n this._fullHeightView.frame = bounds.rectangleWithHeight(fullContentHeight)\n .rectangleWithWidth(bounds.width * 0.5)\n \n }\n \n private _animateLayoutAllRows() {\n \n UIView.animateViewOrViewsWithDurationDelayAndFunction(\n this._visibleRows,\n this.animationDuration,\n 0,\n undefined,\n () => {\n \n this._layoutAllRows()\n \n },\n () => {\n \n \n }\n )\n \n }\n \n // UITableView has usesVirtualLayoutingForIntrinsicSizing = NO and is always\n // given a fixed viewport frame by its parent \u2014 so frame.height never changes\n // between layout passes. The base didLayoutSubviews compares frame.height and\n // therefore never propagates upward, even when row positions have changed and\n // intrinsicContentHeight now returns a different value.\n // We override here to track the intrinsic content height instead, so that\n // parents (e.g. CBDataView) get their cache invalidated and re-layout whenever\n // the total row stack height changes.\n override didLayoutSubviews() {\n this.viewController?.viewDidLayoutSubviews()\n \n if (!this.isVirtualLayouting && IS(this.superview) && this.isMemberOfViewTree) {\n const currentContentHeight = this.intrinsicContentHeight()\n if (currentContentHeight !== this._lastReportedHeight) {\n this._lastReportedHeight = currentContentHeight\n this.clearIntrinsicSizeCache()\n this.superview.setNeedsLayout()\n }\n }\n }\n \n \n override layoutSubviews() {\n \n if (this.isVirtualLayouting) {\n console.error(\"layout subviews called during virtual layouting on UITableView, \" +\n \"indicating a possible error in the layout system.\")\n return\n }\n \n const previousPositions: UITableViewReusableViewPositionObject[] = JSON.parse(\n JSON.stringify(this._rowPositions))\n \n const previousVisibleRowsLength = this._visibleRows.length\n \n if (this._needsDrawingOfVisibleRowsBeforeLayout) {\n \n this._drawVisibleRows()\n \n this._needsDrawingOfVisibleRowsBeforeLayout = NO\n \n }\n \n \n super.layoutSubviews()\n \n \n if (!this.numberOfRows() || !this.isMemberOfViewTree) {\n \n return\n \n }\n \n \n if (this._shouldAnimateNextLayout) {\n \n \n // Need to do layout with the previous positions\n \n this._layoutAllRows(previousPositions)\n \n \n if (previousVisibleRowsLength < this._visibleRows.length) {\n \n \n UIView.runFunctionBeforeNextFrame(() => {\n \n this._animateLayoutAllRows()\n \n })\n \n }\n else {\n \n this._animateLayoutAllRows()\n \n }\n \n \n this._shouldAnimateNextLayout = NO\n \n }\n else {\n \n this._calculateAllPositions()\n \n this._layoutAllRows()\n \n \n }\n \n \n }\n \n \n override intrinsicContentHeight(constrainingWidth = 0) {\n \n let result = 0\n this._calculateAllPositions()\n \n const numberOfRows = this.numberOfRows()\n if (numberOfRows) {\n result = this._rowPositionWithIndex(numberOfRows - 1).bottomY\n }\n \n return result\n \n }\n \n \n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["result"]
|
|
7
7
|
}
|
|
@@ -344,6 +344,46 @@ export declare class UIView extends UIObject {
|
|
|
344
344
|
static runFunctionBeforeNextFrame(step: () => void): void;
|
|
345
345
|
static _isLayoutViewsIfNeededScheduled: boolean;
|
|
346
346
|
static scheduleLayoutViewsIfNeeded(): void;
|
|
347
|
+
/**
|
|
348
|
+
* Persistent layout-cycle tracking map, shared across all iterations within a
|
|
349
|
+
* single layout pass. Lifted out of the local scope so that
|
|
350
|
+
* `resetLayoutCycleTracking()` can clear it in response to intentional events
|
|
351
|
+
* (data changes, window resize) that would otherwise trip the cycle guard.
|
|
352
|
+
*/
|
|
353
|
+
static _layoutCounts: Map<UIView, number>;
|
|
354
|
+
/**
|
|
355
|
+
* Maximum number of while-loop iterations allowed in a single layout pass
|
|
356
|
+
* before the pass is forcibly terminated. Each iteration processes all views
|
|
357
|
+
* that were queued since the previous iteration. Raise this if deep view
|
|
358
|
+
* hierarchies with many cascading height changes legitimately need more rounds.
|
|
359
|
+
* Default: 10.
|
|
360
|
+
*/
|
|
361
|
+
static layoutPassMaxIterations: number;
|
|
362
|
+
/**
|
|
363
|
+
* Maximum number of times a single view may be laid out within one layout pass
|
|
364
|
+
* before it is considered a cycle and skipped with a warning. Raise this if a
|
|
365
|
+
* view legitimately re-queues itself many times due to cascading content changes.
|
|
366
|
+
* Default: 5.
|
|
367
|
+
*/
|
|
368
|
+
static layoutCycleThreshold: number;
|
|
369
|
+
/**
|
|
370
|
+
* Resets layout-cycle tracking for all views globally. Call this when an
|
|
371
|
+
* intentional external event (window resize, theme change, etc.) triggers a
|
|
372
|
+
* full re-layout so that no view is incorrectly blocked by the cycle detector.
|
|
373
|
+
*/
|
|
374
|
+
static resetLayoutCycleTrackingForAllViews(): void;
|
|
375
|
+
/**
|
|
376
|
+
* Resets layout-cycle tracking for this view, pardoning it from its
|
|
377
|
+
* accumulated layout count. Call this when this view's data changes
|
|
378
|
+
* and it legitimately needs to be laid out again within the current pass.
|
|
379
|
+
*/
|
|
380
|
+
resetLayoutCycleTracking(): void;
|
|
381
|
+
/**
|
|
382
|
+
* Resets layout-cycle tracking for this view and every view in its subtree.
|
|
383
|
+
* Call this when a container's contents change (e.g. rows reloaded, child
|
|
384
|
+
* views swapped) and the whole subtree legitimately needs re-layout.
|
|
385
|
+
*/
|
|
386
|
+
resetLayoutCycleTrackingForSubtree(): void;
|
|
347
387
|
static layoutViewsIfNeeded(): void;
|
|
348
388
|
_lastReportedHeight: number;
|
|
349
389
|
setNeedsLayout(): void;
|
|
@@ -1116,19 +1116,25 @@ const _UIView = class extends import_UIObject.UIObject {
|
|
|
1116
1116
|
_UIView.layoutViewsIfNeeded();
|
|
1117
1117
|
});
|
|
1118
1118
|
}
|
|
1119
|
+
static resetLayoutCycleTrackingForAllViews() {
|
|
1120
|
+
_UIView._layoutCounts.clear();
|
|
1121
|
+
}
|
|
1122
|
+
resetLayoutCycleTracking() {
|
|
1123
|
+
_UIView._layoutCounts.delete(this);
|
|
1124
|
+
}
|
|
1125
|
+
resetLayoutCycleTrackingForSubtree() {
|
|
1126
|
+
this.forEachViewInSubtree((subtreeView) => _UIView._layoutCounts.delete(subtreeView));
|
|
1127
|
+
}
|
|
1119
1128
|
static layoutViewsIfNeeded() {
|
|
1120
1129
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1121
|
-
if (!_UIView._isLayoutViewsIfNeededScheduled) {
|
|
1122
|
-
_UIView.scheduleLayoutViewsIfNeeded();
|
|
1123
|
-
}
|
|
1124
1130
|
if (!_UIView._viewsToLayout.length) {
|
|
1125
1131
|
return;
|
|
1126
1132
|
}
|
|
1127
1133
|
(_a = window.UILayoutCycleTracer) == null ? void 0 : _a.willBeginLayoutPass();
|
|
1128
1134
|
(_b = window.UILayoutDebugger) == null ? void 0 : _b.willBeginLayoutPass(_UIView._viewsToLayout);
|
|
1129
|
-
|
|
1135
|
+
_UIView._layoutCounts.clear();
|
|
1136
|
+
const maxIterations = _UIView.layoutPassMaxIterations;
|
|
1130
1137
|
let iteration = 0;
|
|
1131
|
-
const layoutCounts = /* @__PURE__ */ new Map();
|
|
1132
1138
|
while (_UIView._viewsToLayout.length > 0 && iteration < maxIterations) {
|
|
1133
1139
|
(_c = window.UILayoutCycleTracer) == null ? void 0 : _c.willBeginIteration(iteration);
|
|
1134
1140
|
(_d = window.UILayoutDebugger) == null ? void 0 : _d.willBeginIteration(iteration);
|
|
@@ -1137,8 +1143,8 @@ const _UIView = class extends import_UIObject.UIObject {
|
|
|
1137
1143
|
const viewDepthMap = /* @__PURE__ */ new Map();
|
|
1138
1144
|
for (let i = 0; i < viewsToProcess.length; i++) {
|
|
1139
1145
|
const view = viewsToProcess[i];
|
|
1140
|
-
const layoutCount =
|
|
1141
|
-
if (layoutCount >=
|
|
1146
|
+
const layoutCount = _UIView._layoutCounts.get(view) || 0;
|
|
1147
|
+
if (layoutCount >= _UIView.layoutCycleThreshold) {
|
|
1142
1148
|
console.warn("View layout cycle detected:", view);
|
|
1143
1149
|
import_UILayoutCycleTracer.UILayoutCycleTracer.printViewReport(view);
|
|
1144
1150
|
continue;
|
|
@@ -1157,7 +1163,7 @@ const _UIView = class extends import_UIObject.UIObject {
|
|
|
1157
1163
|
const breakpointOnThisLine = "Add a breakpoint on this line to step through layout.";
|
|
1158
1164
|
}
|
|
1159
1165
|
view.layoutIfNeeded();
|
|
1160
|
-
|
|
1166
|
+
_UIView._layoutCounts.set(view, (_UIView._layoutCounts.get(view) || 0) + 1);
|
|
1161
1167
|
(_g = window.UILayoutCycleTracer) == null ? void 0 : _g.didLayoutView(view);
|
|
1162
1168
|
(_h = window.UILayoutDebugger) == null ? void 0 : _h.didLayoutView(view);
|
|
1163
1169
|
}
|
|
@@ -1165,15 +1171,19 @@ const _UIView = class extends import_UIObject.UIObject {
|
|
|
1165
1171
|
}
|
|
1166
1172
|
(_i = window.UILayoutCycleTracer) == null ? void 0 : _i.didFinishLayoutPass(iteration);
|
|
1167
1173
|
(_j = window.UILayoutDebugger) == null ? void 0 : _j.didFinishLayoutPass(iteration);
|
|
1174
|
+
_UIView._layoutCounts.clear();
|
|
1168
1175
|
}
|
|
1169
1176
|
setNeedsLayout() {
|
|
1170
1177
|
var _a, _b;
|
|
1178
|
+
this.clearIntrinsicSizeCache();
|
|
1179
|
+
if (this.isVirtualLayouting) {
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1171
1182
|
if (this._shouldLayout && _UIView._viewsToLayout.contains(this)) {
|
|
1172
1183
|
return;
|
|
1173
1184
|
}
|
|
1174
1185
|
this._shouldLayout = import_UIObject.YES;
|
|
1175
1186
|
_UIView._viewsToLayout.push(this);
|
|
1176
|
-
this.clearIntrinsicSizeCache();
|
|
1177
1187
|
(_a = window.UILayoutCycleTracer) == null ? void 0 : _a.viewDidCallSetNeedsLayout(this);
|
|
1178
1188
|
(_b = window.UILayoutDebugger) == null ? void 0 : _b.viewDidCallSetNeedsLayout(this);
|
|
1179
1189
|
if (!_UIView._isLayoutViewsIfNeededScheduled) {
|
|
@@ -2812,6 +2822,9 @@ UIView._pageDimensionsCacheValid = false;
|
|
|
2812
2822
|
UIView._resizeObserverInitialized = false;
|
|
2813
2823
|
UIView._transformAttribute = ("transform" in document.documentElement.style ? "transform" : void 0) || ("-webkit-transform" in document.documentElement.style ? "-webkit-transform" : "undefined") || ("-moz-transform" in document.documentElement.style ? "-moz-transform" : "undefined") || ("-ms-transform" in document.documentElement.style ? "-ms-transform" : "undefined") || ("-o-transform" in document.documentElement.style ? "-o-transform" : "undefined");
|
|
2814
2824
|
UIView._isLayoutViewsIfNeededScheduled = import_UIObject.NO;
|
|
2825
|
+
UIView._layoutCounts = /* @__PURE__ */ new Map();
|
|
2826
|
+
UIView.layoutPassMaxIterations = 10;
|
|
2827
|
+
UIView.layoutCycleThreshold = 5;
|
|
2815
2828
|
UIView.constraintAttribute = {
|
|
2816
2829
|
"left": AutoLayout.Attribute.LEFT,
|
|
2817
2830
|
"right": AutoLayout.Attribute.RIGHT,
|