mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-25 13:57:21 +00:00
Merge pull request #9324 from home-assistant/dev
This commit is contained in:
commit
3d788d6056
@ -104,5 +104,6 @@
|
||||
"lit/attribute-value-entities": 0
|
||||
},
|
||||
"plugins": ["disable", "import", "lit", "prettier", "@typescript-eslint"],
|
||||
"processor": "disable/disable"
|
||||
"processor": "disable/disable",
|
||||
"ignorePatterns": ["src/resources/lit-virtualizer/*"]
|
||||
}
|
||||
|
21
.gitignore
vendored
21
.gitignore
vendored
@ -1,10 +1,17 @@
|
||||
.DS_Store
|
||||
.reify-cache
|
||||
|
||||
# build
|
||||
build
|
||||
build-translations/*
|
||||
hass_frontend/*
|
||||
dist
|
||||
|
||||
# yarn
|
||||
.yarn
|
||||
yarn-error.log
|
||||
node_modules/*
|
||||
npm-debug.log
|
||||
.DS_Store
|
||||
hass_frontend/*
|
||||
.reify-cache
|
||||
|
||||
# Python stuff
|
||||
*.py[cod]
|
||||
@ -14,11 +21,8 @@ hass_frontend/*
|
||||
# venv stuff
|
||||
pyvenv.cfg
|
||||
pip-selfcheck.json
|
||||
venv
|
||||
venv/*
|
||||
.venv
|
||||
lib
|
||||
bin
|
||||
dist
|
||||
|
||||
# vscode
|
||||
.vscode/*
|
||||
@ -31,9 +35,8 @@ src/cast/dev_const.ts
|
||||
|
||||
# Secrets
|
||||
.lokalise_token
|
||||
yarn-error.log
|
||||
|
||||
#asdf
|
||||
# asdf
|
||||
.tool-versions
|
||||
|
||||
# Home Assistant config
|
||||
|
@ -116,8 +116,9 @@ const createWebpackConfig = ({
|
||||
// We need to change the import of the polyfill for EventTarget, so we replace the polyfill file with our customized one
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
new RegExp(
|
||||
require.resolve(
|
||||
"@lit-labs/virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js"
|
||||
path.resolve(
|
||||
paths.polymer_dir,
|
||||
"src/resources/lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js"
|
||||
)
|
||||
),
|
||||
path.resolve(paths.polymer_dir, "src/resources/EventTarget-ponyfill.js")
|
||||
|
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="home-assistant-frontend",
|
||||
version="20210531.1",
|
||||
version="20210601.0",
|
||||
description="The Home Assistant frontend",
|
||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||
author="The Home Assistant Authors",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Layout1d, scroll } from "@lit-labs/virtualizer";
|
||||
import { Layout1d, scroll } from "../../resources/lit-virtualizer";
|
||||
import deepClone from "deep-clone-simple";
|
||||
import {
|
||||
css,
|
||||
@ -340,11 +340,10 @@ export class HaDataTable extends LitElement {
|
||||
${scroll({
|
||||
items: this._items,
|
||||
layout: Layout1d,
|
||||
// @ts-expect-error
|
||||
renderItem: (row: DataTableRowData, index) => {
|
||||
// not sure how this happens...
|
||||
if (!row) {
|
||||
return "";
|
||||
return html``;
|
||||
}
|
||||
if (row.append) {
|
||||
return html`
|
||||
|
@ -108,7 +108,7 @@ class MoreInfoWeather extends LitElement {
|
||||
this.stateObj.attributes.pressure,
|
||||
this.hass.locale
|
||||
)}
|
||||
${getWeatherUnit(this.hass, "air_pressure")}
|
||||
${getWeatherUnit(this.hass, "pressure")}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Layout1d, scroll } from "@lit-labs/virtualizer";
|
||||
import { Layout1d, scroll } from "../../resources/lit-virtualizer";
|
||||
import "@material/mwc-list/mwc-list";
|
||||
import type { List } from "@material/mwc-list/mwc-list";
|
||||
import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation";
|
||||
@ -188,7 +188,6 @@ export class QuickBar extends LitElement {
|
||||
${scroll({
|
||||
items,
|
||||
layout: Layout1d,
|
||||
// @ts-expect-error
|
||||
renderItem: (item: QuickBarItem, index) =>
|
||||
this._renderItem(item, index),
|
||||
})}
|
||||
@ -224,7 +223,7 @@ export class QuickBar extends LitElement {
|
||||
|
||||
private _renderItem(item: QuickBarItem, index?: number) {
|
||||
if (!item) {
|
||||
return undefined;
|
||||
return html``;
|
||||
}
|
||||
return isCommandItem(item)
|
||||
? this._renderCommandItem(item, index)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Layout1d, scroll } from "@lit-labs/virtualizer";
|
||||
import { Layout1d, scroll } from "../../resources/lit-virtualizer";
|
||||
import {
|
||||
css,
|
||||
CSSResultGroup,
|
||||
@ -100,7 +100,6 @@ class HaLogbook extends LitElement {
|
||||
? scroll({
|
||||
items: this.entries,
|
||||
layout: Layout1d,
|
||||
// @ts-expect-error
|
||||
renderItem: (item: LogbookEntry, index) =>
|
||||
this._renderLogbookItem(item, index),
|
||||
})
|
||||
|
39
src/resources/lit-virtualizer/lib/lit-virtualizer.d.ts
vendored
Normal file
39
src/resources/lit-virtualizer/lib/lit-virtualizer.d.ts
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
import { LitElement, TemplateResult } from "lit";
|
||||
import {
|
||||
LayoutSpecifier,
|
||||
Layout,
|
||||
LayoutConstructor,
|
||||
} from "./uni-virtualizer/lib/layouts/Layout.js";
|
||||
/**
|
||||
* A LitElement wrapper of the scroll directive.
|
||||
*
|
||||
* Import this module to declare the lit-virtualizer custom element.
|
||||
* Pass an items array, renderItem method, and scroll target as properties
|
||||
* to the <lit-virtualizer> element.
|
||||
*/
|
||||
export declare class LitVirtualizer extends LitElement {
|
||||
renderItem?: (item: any, index?: number) => TemplateResult;
|
||||
items: Array<unknown>;
|
||||
scrollTarget: Element | Window;
|
||||
keyFunction: ((item: unknown) => unknown) | undefined;
|
||||
private _layout;
|
||||
private _scrollToIndex;
|
||||
createRenderRoot(): this;
|
||||
/**
|
||||
* The method used for rendering each item.
|
||||
*/
|
||||
set layout(layout: Layout | LayoutConstructor | LayoutSpecifier | null);
|
||||
get layout(): Layout | LayoutConstructor | LayoutSpecifier | null;
|
||||
/**
|
||||
* Scroll to the specified index, placing that item at the given position
|
||||
* in the scroll view.
|
||||
*/
|
||||
scrollToIndex(index: number, position?: string): Promise<void>;
|
||||
render(): TemplateResult;
|
||||
}
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"lit-virtualizer": LitVirtualizer;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=lit-virtualizer.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"lit-virtualizer.d.ts","sourceRoot":"","sources":["../src/lib/lit-virtualizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AAKvD,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAErG;;;;;;GAMG;AACH,qBACa,cAAe,SAAQ,UAAU;IAE1C,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,cAAc,CAAC,CAAC;IAG7D,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAM;IAG3B,YAAY,EAAE,OAAO,GAAG,MAAM,CAAQ;IAGtC,WAAW,EAAE,CAAC,CAAC,IAAI,EAAC,OAAO,KAAK,OAAO,CAAC,GAAG,SAAS,CAAa;IAEjE,OAAO,CAAC,OAAO,CAA6D;IAE5E,OAAO,CAAC,cAAc,CAAkD;IAExE,gBAAgB;IAahB;;OAEG;IAWH,IACI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,eAAe,GAAG,IAAI,EAIrE;IAED,IAAI,MAAM,IAAI,MAAM,GAAG,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAEhE;IAGD;;;OAGG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAgB;IAO7D,MAAM,IAAI,cAAc;CAO3B;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,iBAAiB,EAAE,cAAc,CAAC;KACrC;CACJ"}
|
118
src/resources/lit-virtualizer/lib/lit-virtualizer.js
Normal file
118
src/resources/lit-virtualizer/lib/lit-virtualizer.js
Normal file
@ -0,0 +1,118 @@
|
||||
var __decorate =
|
||||
(this && this.__decorate) ||
|
||||
function (decorators, target, key, desc) {
|
||||
var c = arguments.length,
|
||||
r =
|
||||
c < 3
|
||||
? target
|
||||
: desc === null
|
||||
? (desc = Object.getOwnPropertyDescriptor(target, key))
|
||||
: desc,
|
||||
d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
||||
r = Reflect.decorate(decorators, target, key, desc);
|
||||
else
|
||||
for (var i = decorators.length - 1; i >= 0; i--)
|
||||
if ((d = decorators[i]))
|
||||
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
import { html, LitElement } from "lit";
|
||||
import { customElement } from "lit/decorators/custom-element.js";
|
||||
import { property } from "lit/decorators/property.js";
|
||||
import { scroll } from "./scroll.js";
|
||||
import { scrollerRef } from "./uni-virtualizer/lib/VirtualScroller.js";
|
||||
/**
|
||||
* A LitElement wrapper of the scroll directive.
|
||||
*
|
||||
* Import this module to declare the lit-virtualizer custom element.
|
||||
* Pass an items array, renderItem method, and scroll target as properties
|
||||
* to the <lit-virtualizer> element.
|
||||
*/
|
||||
let LitVirtualizer = class LitVirtualizer extends LitElement {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.items = [];
|
||||
this.scrollTarget = this;
|
||||
this.keyFunction = undefined;
|
||||
this._layout = null;
|
||||
this._scrollToIndex = null;
|
||||
}
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
}
|
||||
// get items() {
|
||||
// return this._items;
|
||||
// }
|
||||
// set items(items) {
|
||||
// this._items = items;
|
||||
// this._scroller.totalItems = items.length;
|
||||
// }
|
||||
/**
|
||||
* The method used for rendering each item.
|
||||
*/
|
||||
// get renderItem() {
|
||||
// return this._renderItem;
|
||||
// }
|
||||
// set renderItem(renderItem) {
|
||||
// if (renderItem !== this.renderItem) {
|
||||
// this._renderItem = renderItem;
|
||||
// this.requestUpdate();
|
||||
// }
|
||||
// }
|
||||
set layout(layout) {
|
||||
// TODO (graynorton): Shouldn't have to set this here
|
||||
this._layout = layout;
|
||||
this.requestUpdate();
|
||||
}
|
||||
get layout() {
|
||||
return this[scrollerRef].layout;
|
||||
}
|
||||
/**
|
||||
* Scroll to the specified index, placing that item at the given position
|
||||
* in the scroll view.
|
||||
*/
|
||||
async scrollToIndex(index, position = "start") {
|
||||
this._scrollToIndex = { index, position };
|
||||
this.requestUpdate();
|
||||
await this.updateComplete;
|
||||
this._scrollToIndex = null;
|
||||
}
|
||||
render() {
|
||||
const { items, renderItem, keyFunction, scrollTarget } = this;
|
||||
const layout = this._layout;
|
||||
return html`
|
||||
${scroll({
|
||||
items,
|
||||
renderItem,
|
||||
layout,
|
||||
keyFunction,
|
||||
scrollTarget,
|
||||
scrollToIndex: this._scrollToIndex,
|
||||
})}
|
||||
`;
|
||||
}
|
||||
};
|
||||
__decorate([property()], LitVirtualizer.prototype, "renderItem", void 0);
|
||||
__decorate(
|
||||
[property({ attribute: false })],
|
||||
LitVirtualizer.prototype,
|
||||
"items",
|
||||
void 0
|
||||
);
|
||||
__decorate(
|
||||
[property({ attribute: false })],
|
||||
LitVirtualizer.prototype,
|
||||
"scrollTarget",
|
||||
void 0
|
||||
);
|
||||
__decorate([property()], LitVirtualizer.prototype, "keyFunction", void 0);
|
||||
__decorate(
|
||||
[property({ attribute: false })],
|
||||
LitVirtualizer.prototype,
|
||||
"layout",
|
||||
null
|
||||
);
|
||||
LitVirtualizer = __decorate([customElement("lit-virtualizer")], LitVirtualizer);
|
||||
export { LitVirtualizer };
|
||||
//# sourceMappingURL=lit-virtualizer.js.map
|
1
src/resources/lit-virtualizer/lib/lit-virtualizer.js.map
Normal file
1
src/resources/lit-virtualizer/lib/lit-virtualizer.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"lit-virtualizer.js","sourceRoot":"","sources":["../src/lib/lit-virtualizer.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAkB,MAAM,KAAK,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAoB,MAAM,0CAA0C,CAAC;AAGzF;;;;;;GAMG;AAEH,IAAa,cAAc,GAA3B,MAAa,cAAe,SAAQ,UAAU;IAA9C;;QAKI,UAAK,GAAmB,EAAE,CAAC;QAG3B,iBAAY,GAAqB,IAAI,CAAC;QAGtC,gBAAW,GAA4C,SAAS,CAAC;QAEzD,YAAO,GAAwD,IAAI,CAAC;QAEpE,mBAAc,GAA6C,IAAI,CAAC;IA0D5E,CAAC;IAxDG,gBAAgB;QACZ,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,gBAAgB;IAChB,0BAA0B;IAC1B,IAAI;IAEJ,qBAAqB;IACrB,2BAA2B;IAC3B,gDAAgD;IAChD,IAAI;IAEJ;;OAEG;IACH,qBAAqB;IACrB,+BAA+B;IAC/B,IAAI;IACJ,+BAA+B;IAC/B,4CAA4C;IAC5C,yCAAyC;IACzC,gCAAgC;IAChC,QAAQ;IACR,IAAI;IAGJ,IAAI,MAAM,CAAC,MAA2D;QAClE,qDAAqD;QACrD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,IAAI,MAAM;QACN,OAAQ,IAAyB,CAAC,WAAW,CAAE,CAAC,MAAM,CAAC;IAC3D,CAAC;IAGD;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,WAAmB,OAAO;QACzD,IAAI,CAAC,cAAc,GAAG,EAAC,KAAK,EAAE,QAAQ,EAAC,CAAC;QACxC,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,IAAI,CAAC,cAAc,CAAC;QAC1B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;IAC/B,CAAC;IAED,MAAM;QACF,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;QAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAA;cACL,MAAM,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC;SACzG,CAAC;IACN,CAAC;CACJ,CAAA;AAvEG;IADC,QAAQ,EAAE;kDACkD;AAG7D;IADC,QAAQ,CAAC,EAAC,SAAS,EAAE,KAAK,EAAC,CAAC;6CACF;AAG3B;IADC,QAAQ,CAAC,EAAC,SAAS,EAAE,KAAK,EAAC,CAAC;oDACS;AAGtC;IADC,QAAQ,EAAE;mDACsD;AAiCjE;IADC,QAAQ,CAAC,EAAC,SAAS,EAAC,KAAK,EAAC,CAAC;4CAK3B;AAhDQ,cAAc;IAD1B,aAAa,CAAC,iBAAiB,CAAC;GACpB,cAAc,CAyE1B;SAzEY,cAAc","sourcesContent":["import { html, LitElement, TemplateResult } from 'lit';\nimport { customElement } from 'lit/decorators/custom-element.js';\nimport { property } from 'lit/decorators/property.js';\nimport { scroll } from './scroll.js';\nimport { scrollerRef, ContainerElement } from './uni-virtualizer/lib/VirtualScroller.js';\nimport { LayoutSpecifier, Layout, LayoutConstructor } from './uni-virtualizer/lib/layouts/Layout.js';\n\n/**\n * A LitElement wrapper of the scroll directive.\n *\n * Import this module to declare the lit-virtualizer custom element.\n * Pass an items array, renderItem method, and scroll target as properties\n * to the <lit-virtualizer> element.\n */\n@customElement('lit-virtualizer')\nexport class LitVirtualizer extends LitElement {\n @property()\n renderItem?: ((item: any, index?: number) => TemplateResult);\n\n @property({attribute: false})\n items: Array<unknown> = [];\n\n @property({attribute: false})\n scrollTarget: Element | Window = this;\n\n @property()\n keyFunction: ((item:unknown) => unknown) | undefined = undefined;\n\n private _layout: Layout | LayoutConstructor | LayoutSpecifier | null = null;\n\n private _scrollToIndex: {index: number, position: string} | null = null;\n \n createRenderRoot() {\n return this;\n }\n\n // get items() {\n // return this._items;\n // }\n\n // set items(items) {\n // this._items = items;\n // this._scroller.totalItems = items.length;\n // }\n\n /**\n * The method used for rendering each item.\n */\n // get renderItem() {\n // return this._renderItem;\n // }\n // set renderItem(renderItem) {\n // if (renderItem !== this.renderItem) {\n // this._renderItem = renderItem;\n // this.requestUpdate();\n // }\n // }\n\n @property({attribute:false})\n set layout(layout: Layout | LayoutConstructor | LayoutSpecifier | null) {\n // TODO (graynorton): Shouldn't have to set this here\n this._layout = layout;\n this.requestUpdate();\n }\n\n get layout(): Layout | LayoutConstructor | LayoutSpecifier | null {\n return (this as ContainerElement)[scrollerRef]!.layout;\n }\n \n \n /**\n * Scroll to the specified index, placing that item at the given position\n * in the scroll view.\n */\n async scrollToIndex(index: number, position: string = 'start') {\n this._scrollToIndex = {index, position};\n this.requestUpdate();\n await this.updateComplete;\n this._scrollToIndex = null;\n }\n\n render(): TemplateResult {\n const { items, renderItem, keyFunction, scrollTarget } = this;\n const layout = this._layout;\n return html`\n ${scroll({ items, renderItem, layout, keyFunction, scrollTarget, scrollToIndex: this._scrollToIndex })}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'lit-virtualizer': LitVirtualizer;\n }\n}"]}
|
61
src/resources/lit-virtualizer/lib/scroll.d.ts
vendored
Normal file
61
src/resources/lit-virtualizer/lib/scroll.d.ts
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
import { TemplateResult, ChildPart } from "lit";
|
||||
import { PartInfo } from "lit/directive.js";
|
||||
import { AsyncDirective } from "lit/async-directive.js";
|
||||
import {
|
||||
Layout,
|
||||
LayoutConstructor,
|
||||
LayoutSpecifier,
|
||||
} from "./uni-virtualizer/lib/layouts/Layout.js";
|
||||
import {
|
||||
VirtualScroller,
|
||||
ScrollToIndexValue,
|
||||
} from "./uni-virtualizer/lib/VirtualScroller.js";
|
||||
/**
|
||||
* Configuration options for the scroll directive.
|
||||
*/
|
||||
interface ScrollConfig {
|
||||
/**
|
||||
* A function that returns a lit-html TemplateResult. It will be used
|
||||
* to generate the DOM for each item in the virtual list.
|
||||
*/
|
||||
renderItem?: (item: any, index?: number) => TemplateResult;
|
||||
keyFunction?: (item: any) => unknown;
|
||||
layout?: Layout | LayoutConstructor | LayoutSpecifier | null;
|
||||
/**
|
||||
* An element that receives scroll events for the virtual scroller.
|
||||
*/
|
||||
scrollTarget?: Element | Window;
|
||||
/**
|
||||
* The list of items to display via the renderItem function.
|
||||
*/
|
||||
items?: Array<any>;
|
||||
/**
|
||||
* Limit for the number of items to display. Defaults to the length of the
|
||||
* items array.
|
||||
*/
|
||||
totalItems?: number;
|
||||
/**
|
||||
* Index and position of the item to scroll to.
|
||||
*/
|
||||
scrollToIndex?: ScrollToIndexValue;
|
||||
}
|
||||
export declare const defaultKeyFunction: (item: any) => any;
|
||||
export declare const defaultRenderItem: (item: any) => TemplateResult<1>;
|
||||
declare class ScrollDirective extends AsyncDirective {
|
||||
container: HTMLElement | null;
|
||||
scroller: VirtualScroller | null;
|
||||
first: number;
|
||||
last: number;
|
||||
renderItem: (item: any, index?: number) => TemplateResult;
|
||||
keyFunction: (item: any) => unknown;
|
||||
items: Array<unknown>;
|
||||
constructor(part: PartInfo);
|
||||
render(config?: ScrollConfig): unknown;
|
||||
update(part: ChildPart, [config]: [ScrollConfig]): unknown;
|
||||
private _initialize;
|
||||
}
|
||||
export declare const scroll: (
|
||||
config?: ScrollConfig | undefined
|
||||
) => import("lit-html/directive").DirectiveResult<typeof ScrollDirective>;
|
||||
export {};
|
||||
//# sourceMappingURL=scroll.d.ts.map
|
1
src/resources/lit-virtualizer/lib/scroll.d.ts.map
Normal file
1
src/resources/lit-virtualizer/lib/scroll.d.ts.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../src/lib/scroll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAW,SAAS,EAAQ,MAAM,KAAK,CAAC;AAC/D,OAAO,EAAa,QAAQ,EAAY,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AACrG,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAE/F;;GAEG;AACH,UAAU,YAAY;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,cAAc,CAAC;IAE3D,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;IAGrC,MAAM,CAAC,EAAE,MAAM,GAAG,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAC;IAE7D;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAEhC;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAEnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;CACpC;AAEH,eAAO,MAAM,kBAAkB,SAAU,GAAG,QAAS,CAAC;AACtD,eAAO,MAAM,iBAAiB,SAAU,GAAG,sBAA2C,CAAC;AAEvF,cAAM,eAAgB,SAAQ,cAAc;IACxC,SAAS,EAAE,WAAW,GAAG,IAAI,CAAO;IACpC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAO;IACvC,KAAK,SAAI;IACT,IAAI,SAAK;IACT,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,cAAc,CAAqB;IAC9E,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAsB;IACzD,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAK;gBAEd,IAAI,EAAE,QAAQ;IAO1B,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY;IAc5B,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC;IAehD,OAAO,CAAC,WAAW;CAiBtB;AAED,eAAO,MAAM,MAAM,6GAA6B,CAAC"}
|
79
src/resources/lit-virtualizer/lib/scroll.js
Normal file
79
src/resources/lit-virtualizer/lib/scroll.js
Normal file
@ -0,0 +1,79 @@
|
||||
import { nothing, html } from "lit";
|
||||
import { directive, PartType } from "lit/directive.js";
|
||||
import { AsyncDirective } from "lit/async-directive.js";
|
||||
import { repeat } from "lit/directives/repeat.js";
|
||||
import { VirtualScroller } from "./uni-virtualizer/lib/VirtualScroller.js";
|
||||
export const defaultKeyFunction = (item) => item;
|
||||
export const defaultRenderItem = (item) =>
|
||||
html`${JSON.stringify(item, null, 2)}`;
|
||||
class ScrollDirective extends AsyncDirective {
|
||||
constructor(part) {
|
||||
super(part);
|
||||
this.container = null;
|
||||
this.scroller = null;
|
||||
this.first = 0;
|
||||
this.last = -1;
|
||||
this.renderItem = defaultRenderItem;
|
||||
this.keyFunction = defaultKeyFunction;
|
||||
this.items = [];
|
||||
if (part.type !== PartType.CHILD) {
|
||||
throw new Error(
|
||||
"The scroll directive can only be used in child expressions"
|
||||
);
|
||||
}
|
||||
}
|
||||
render(config) {
|
||||
if (config) {
|
||||
this.renderItem = config.renderItem || this.renderItem;
|
||||
this.keyFunction = config.keyFunction || this.keyFunction;
|
||||
}
|
||||
const itemsToRender = [];
|
||||
if (this.first >= 0 && this.last >= this.first) {
|
||||
for (let i = this.first; i < this.last + 1; i++) {
|
||||
itemsToRender.push(this.items[i]);
|
||||
}
|
||||
}
|
||||
return repeat(
|
||||
itemsToRender,
|
||||
this.keyFunction || defaultKeyFunction,
|
||||
this.renderItem
|
||||
);
|
||||
}
|
||||
update(part, [config]) {
|
||||
var _a;
|
||||
if (this.scroller || this._initialize(part, config)) {
|
||||
const { scroller } = this;
|
||||
this.items = scroller.items = config.items || [];
|
||||
scroller.totalItems =
|
||||
config.totalItems ||
|
||||
((_a = config.items) === null || _a === void 0 ? void 0 : _a.length) ||
|
||||
0;
|
||||
scroller.layout = config.layout || null;
|
||||
scroller.scrollTarget = config.scrollTarget || this.container;
|
||||
if (config.scrollToIndex) {
|
||||
scroller.scrollToIndex = config.scrollToIndex;
|
||||
}
|
||||
return this.render(config);
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
_initialize(part, config) {
|
||||
const container = (this.container = part.parentNode);
|
||||
if (container && container.nodeType === 1) {
|
||||
this.scroller = new VirtualScroller({ container });
|
||||
container.addEventListener("rangeChanged", (e) => {
|
||||
this.first = e.detail.first;
|
||||
this.last = e.detail.last;
|
||||
this.setValue(this.render());
|
||||
});
|
||||
return true;
|
||||
}
|
||||
// TODO (GN): This seems to be needed in the case where the `scroll`
|
||||
// directive is used within the `LitVirtualizer` element. Figure out why
|
||||
// and see if there's a cleaner solution.
|
||||
Promise.resolve().then(() => this.update(part, [config]));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const scroll = directive(ScrollDirective);
|
||||
//# sourceMappingURL=scroll.js.map
|
1
src/resources/lit-virtualizer/lib/scroll.js.map
Normal file
1
src/resources/lit-virtualizer/lib/scroll.js.map
Normal file
File diff suppressed because one or more lines are too long
230
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/VirtualScroller.d.ts
vendored
Normal file
230
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/VirtualScroller.d.ts
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
import {
|
||||
ItemBox,
|
||||
Layout,
|
||||
LayoutConstructor,
|
||||
LayoutSpecifier,
|
||||
} from "./layouts/Layout.js";
|
||||
export declare const scrollerRef: unique symbol;
|
||||
export declare type RangeChangeEvent = {
|
||||
first: number;
|
||||
last: number;
|
||||
firstVisible: number;
|
||||
lastVisible: number;
|
||||
};
|
||||
interface ElementWithOptionalScrollerRef extends Element {
|
||||
[scrollerRef]?: VirtualScroller;
|
||||
}
|
||||
interface ShadowRootWithOptionalScrollerRef extends ShadowRoot {
|
||||
[scrollerRef]?: VirtualScroller;
|
||||
}
|
||||
declare type Container =
|
||||
| ElementWithOptionalScrollerRef
|
||||
| ShadowRootWithOptionalScrollerRef;
|
||||
export declare type ContainerElement = ElementWithOptionalScrollerRef;
|
||||
declare type ChildMeasurements = {
|
||||
[key: number]: ItemBox;
|
||||
};
|
||||
export declare type ScrollToIndexValue = {
|
||||
index: number;
|
||||
position?: string;
|
||||
} | null;
|
||||
export interface VirtualScrollerConfig {
|
||||
layout?: Layout | LayoutConstructor | LayoutSpecifier;
|
||||
/**
|
||||
* An element that receives scroll events for the virtual scroller.
|
||||
*/
|
||||
scrollTarget?: Element | Window;
|
||||
/**
|
||||
* The parent of all child nodes to be rendered.
|
||||
*/
|
||||
container: Element | ShadowRoot;
|
||||
}
|
||||
/**
|
||||
* Provides virtual scrolling boilerplate.
|
||||
*
|
||||
* Extensions of this class must set container, layout, and scrollTarget.
|
||||
*
|
||||
* Extensions of this class must also override VirtualRepeater's DOM
|
||||
* manipulation methods.
|
||||
*/
|
||||
export declare class VirtualScroller {
|
||||
private _benchmarkStart;
|
||||
/**
|
||||
* Whether the layout should receive an updated viewport size on the next
|
||||
* render.
|
||||
*/
|
||||
private _layout;
|
||||
/**
|
||||
* The element that generates scroll events and defines the container
|
||||
* viewport. Set by scrollTarget.
|
||||
*/
|
||||
private _scrollTarget;
|
||||
/**
|
||||
* A sentinel element that sizes the container when it is a scrolling
|
||||
* element. This ensures the scroll bar accurately reflects the total
|
||||
* size of the list.
|
||||
*/
|
||||
private _sizer;
|
||||
/**
|
||||
* Layout provides these values, we set them on _render().
|
||||
* TODO @straversi: Can we find an XOR type, usable for the key here?
|
||||
*/
|
||||
private _scrollSize;
|
||||
/**
|
||||
* Difference between scroll target's current and required scroll offsets.
|
||||
* Provided by layout.
|
||||
*/
|
||||
private _scrollErr;
|
||||
/**
|
||||
* A list of the positions (top, left) of the children in the current range.
|
||||
*/
|
||||
private _childrenPos;
|
||||
private _childMeasurements;
|
||||
private _toBeMeasured;
|
||||
private _rangeChanged;
|
||||
private _itemsChanged;
|
||||
private _visibilityChanged;
|
||||
/**
|
||||
* Containing element. Set by container.
|
||||
*/
|
||||
protected _container: Container | null;
|
||||
/**
|
||||
* The parent of all child nodes to be rendered. Set by container.
|
||||
*/
|
||||
private _containerElement;
|
||||
/**
|
||||
* Keep track of original inline style of the container, so it can be
|
||||
* restored when container is changed.
|
||||
*/
|
||||
private _containerInlineStyle;
|
||||
/**
|
||||
* Size of the container.
|
||||
*/
|
||||
private _containerSize;
|
||||
/**
|
||||
* Resize observer attached to container.
|
||||
*/
|
||||
private _containerRO;
|
||||
/**
|
||||
* Resize observer attached to children.
|
||||
*/
|
||||
private _childrenRO;
|
||||
private _mutationObserver;
|
||||
private _mutationPromise;
|
||||
private _mutationPromiseResolver;
|
||||
private _mutationsObserved;
|
||||
private _loadListener;
|
||||
/**
|
||||
* Index and position of item to scroll to.
|
||||
*/
|
||||
private _scrollToIndex;
|
||||
/**
|
||||
* Items to render. Set by items.
|
||||
*/
|
||||
private _items;
|
||||
/**
|
||||
* Total number of items to render. Set by totalItems.
|
||||
*/
|
||||
private _totalItems;
|
||||
/**
|
||||
* Index of the first child in the range, not necessarily the first visible child.
|
||||
* TODO @straversi: Consider renaming these.
|
||||
*/
|
||||
protected _first: number;
|
||||
/**
|
||||
* Index of the last child in the range.
|
||||
*/
|
||||
protected _last: number;
|
||||
/**
|
||||
* Index of the first item intersecting the container element.
|
||||
*/
|
||||
private _firstVisible;
|
||||
/**
|
||||
* Index of the last item intersecting the container element.
|
||||
*/
|
||||
private _lastVisible;
|
||||
protected _scheduled: WeakSet<object>;
|
||||
/**
|
||||
* Invoked at the end of each render cycle: children in the range are
|
||||
* measured, and their dimensions passed to this callback. Use it to layout
|
||||
* children as needed.
|
||||
*/
|
||||
protected _measureCallback: ((sizes: ChildMeasurements) => void) | null;
|
||||
protected _measureChildOverride:
|
||||
| ((element: Element, item: unknown) => ItemBox)
|
||||
| null;
|
||||
constructor(config?: VirtualScrollerConfig);
|
||||
set items(items: Array<unknown> | undefined);
|
||||
/**
|
||||
* The total number of items, regardless of the range, that can be rendered
|
||||
* as child nodes.
|
||||
*/
|
||||
get totalItems(): number;
|
||||
set totalItems(num: number);
|
||||
/**
|
||||
* The parent of all child nodes to be rendered.
|
||||
*/
|
||||
get container(): Container | null;
|
||||
set container(container: Container | null);
|
||||
get layout(): Layout | LayoutConstructor | LayoutSpecifier | null;
|
||||
set layout(layout: Layout | LayoutConstructor | LayoutSpecifier | null);
|
||||
startBenchmarking(): void;
|
||||
stopBenchmarking(): {
|
||||
timeElapsed: number;
|
||||
virtualizationTime: number;
|
||||
} | null;
|
||||
private _measureChildren;
|
||||
/**
|
||||
* Returns the width, height, and margins of the given child.
|
||||
*/
|
||||
_measureChild(element: Element): ItemBox;
|
||||
/**
|
||||
* The element that generates scroll events and defines the container
|
||||
* viewport. The value `null` (default) corresponds to `window` as scroll
|
||||
* target.
|
||||
*/
|
||||
get scrollTarget(): Element | Window | null;
|
||||
set scrollTarget(target: Element | Window | null);
|
||||
/**
|
||||
* Index and position of item to scroll to. The scroller will fix to that point
|
||||
* until the user scrolls.
|
||||
*/
|
||||
set scrollToIndex(newValue: ScrollToIndexValue);
|
||||
protected _schedule(method: Function): Promise<void>;
|
||||
_updateDOM(): Promise<void>;
|
||||
_updateLayout(): void;
|
||||
private _handleScrollEvent;
|
||||
handleEvent(event: CustomEvent): void;
|
||||
private _initResizeObservers;
|
||||
private _createContainerSizer;
|
||||
get _children(): Array<HTMLElement>;
|
||||
private _updateView;
|
||||
/**
|
||||
* Styles the _sizer element or the container so that its size reflects the
|
||||
* total size of all items.
|
||||
*/
|
||||
private _sizeContainer;
|
||||
/**
|
||||
* Sets the top and left transform style of the children from the values in
|
||||
* pos.
|
||||
*/
|
||||
private _positionChildren;
|
||||
private _adjustRange;
|
||||
private _correctScrollError;
|
||||
/**
|
||||
* Emits a rangechange event with the current first, last, firstVisible, and
|
||||
* lastVisible.
|
||||
*/
|
||||
private _notifyRange;
|
||||
private _notifyVisibility;
|
||||
/**
|
||||
* Render and update the view at the next opportunity with the given
|
||||
* container size.
|
||||
*/
|
||||
private _containerSizeChanged;
|
||||
private _observeMutations;
|
||||
private _childLoaded;
|
||||
private _childrenSizeChanged;
|
||||
}
|
||||
export {};
|
||||
//# sourceMappingURL=VirtualScroller.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"VirtualScroller.d.ts","sourceRoot":"","sources":["../../../src/lib/uni-virtualizer/lib/VirtualScroller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAW,MAAM,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEnG,eAAO,MAAM,WAAW,eAAwB,CAAC;AAYjD,oBAAY,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,UAAU,8BAA+B,SAAQ,OAAO;IACtD,CAAC,WAAW,CAAC,CAAC,EAAE,eAAe,CAAA;CAChC;AAED,UAAU,iCAAkC,SAAQ,UAAU;IAC5D,CAAC,WAAW,CAAC,CAAC,EAAE,eAAe,CAAA;CAChC;AAED,aAAK,SAAS,GAAG,8BAA8B,GAAG,iCAAiC,CAAC;AACpF,oBAAY,gBAAgB,GAAG,8BAA8B,CAAC;AAM9D,aAAK,iBAAiB,GAAG;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAC,CAAC;AAElD,oBAAY,kBAAkB,GAAG;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAC,GAAG,IAAI,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,GAAG,iBAAiB,GAAG,eAAe,CAAC;IAEtD;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAEhC;;OAEG;IACH,SAAS,EAAE,OAAO,GAAG,UAAU,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,eAAe,CAAuB;IAC9C;;;OAGG;IAGH,OAAO,CAAC,OAAO,CAAuB;IAEtC;;;OAGG;IACH,OAAO,CAAC,aAAa,CAAwB;IAE7C;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAA4B;IAE1C;;;OAGG;IACH,OAAO,CAAC,WAAW,CAA2B;IAE9C;;;OAGG;IACH,OAAO,CAAC,UAAU,CAA4C;IAE9D;;OAEG;IACH,OAAO,CAAC,YAAY,CAAmD;IAGvE,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,aAAa,CAAwC;IAE7D,OAAO,CAAC,aAAa,CAAQ;IAE7B,OAAO,CAAC,aAAa,CAAQ;IAE7B,OAAO,CAAC,kBAAkB,CAAQ;IAElC;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,SAAS,GAAG,IAAI,CAAQ;IAE9C;;OAEG;IACH,OAAO,CAAC,iBAAiB,CAAiC;IAE1D;;;OAGG;IACH,OAAO,CAAC,qBAAqB,CAAuB;IAEpD;;OAEG;IACH,OAAO,CAAC,cAAc,CAAgD;IAEtE;;OAEG;IACH,OAAO,CAAC,YAAY,CAA+B;IAEnD;;OAEG;IACH,OAAO,CAAC,WAAW,CAA+B;IAElD,OAAO,CAAC,iBAAiB,CAAiC;IAC1D,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,wBAAwB,CAAyB;IACzD,OAAO,CAAC,kBAAkB,CAAS;IAInC,OAAO,CAAC,aAAa,CAAgC;IAErD;;OAEG;IACH,OAAO,CAAC,cAAc,CAA4B;IAElD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAsB;IAEpC;;OAEG;IACH,OAAO,CAAC,WAAW,CAAuB;IAE1C;;;OAGG;IACH,SAAS,CAAC,MAAM,SAAK;IAErB;;OAEG;IACH,SAAS,CAAC,KAAK,SAAK;IAEpB;;OAEG;IACH,OAAO,CAAC,aAAa,CAAK;IAE1B;;OAEG;IACH,OAAO,CAAC,YAAY,CAAK;IAEzB,SAAS,CAAC,UAAU,kBAAiB;IAErC;;;;OAIG;IACF,SAAS,CAAC,gBAAgB,EAAE,CAAC,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAE/E,SAAS,CAAC,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,IAAI,CAAQ;gBAEnF,MAAM,CAAC,EAAE,qBAAqB;IAS1C,IAAI,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,SAAS,EAM1C;IAED;;;OAGG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,UAAU,CAAC,GAAG,EAAE,MAAM,EAWzB;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,CAEhC;IAED,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,EA6ExC;IAID,IAAI,MAAM,IAAI,MAAM,GAAG,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAEhE;IAED,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,eAAe,GAAG,IAAI,EAiErE;IAID,iBAAiB;IAMjB,gBAAgB;;;;IAchB,OAAO,CAAC,gBAAgB;IAgBxB;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAQxC;;;;OAIG;IACH,IAAI,YAAY,IAAI,OAAO,GAAG,MAAM,GAAG,IAAI,CAE1C;IACD,IAAI,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,EAyB/C;IAED;;;OAGG;IACH,IAAI,aAAa,CAAC,QAAQ,EAAE,kBAAkB,EAG7C;cAEe,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IASpD,UAAU;IA0BhB,aAAa;IAoBb,OAAO,CAAC,kBAAkB;IAgB1B,WAAW,CAAC,KAAK,EAAE,WAAW;YA4BhB,oBAAoB;IAWlC,OAAO,CAAC,qBAAqB;IAgB7B,IAAI,SAAS,IAAI,KAAK,CAAC,WAAW,CAAC,CAWlC;IAED,OAAO,CAAC,WAAW;IAiDnB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAgBtB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;YAsBX,YAAY;IAkB1B,OAAO,CAAC,mBAAmB;IAS3B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,iBAAiB;IAWzB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;YAMf,iBAAiB;IAc/B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,oBAAoB;CAO7B"}
|
@ -0,0 +1,725 @@
|
||||
import getResizeObserver from "./polyfillLoaders/ResizeObserver.js";
|
||||
export const scrollerRef = Symbol("scrollerRef");
|
||||
/**
|
||||
* Provides virtual scrolling boilerplate.
|
||||
*
|
||||
* Extensions of this class must set container, layout, and scrollTarget.
|
||||
*
|
||||
* Extensions of this class must also override VirtualRepeater's DOM
|
||||
* manipulation methods.
|
||||
*/
|
||||
export class VirtualScroller {
|
||||
constructor(config) {
|
||||
this._benchmarkStart = null;
|
||||
/**
|
||||
* Whether the layout should receive an updated viewport size on the next
|
||||
* render.
|
||||
*/
|
||||
// private _needsUpdateView: boolean = false;
|
||||
this._layout = null;
|
||||
/**
|
||||
* The element that generates scroll events and defines the container
|
||||
* viewport. Set by scrollTarget.
|
||||
*/
|
||||
this._scrollTarget = null;
|
||||
/**
|
||||
* A sentinel element that sizes the container when it is a scrolling
|
||||
* element. This ensures the scroll bar accurately reflects the total
|
||||
* size of the list.
|
||||
*/
|
||||
this._sizer = null;
|
||||
/**
|
||||
* Layout provides these values, we set them on _render().
|
||||
* TODO @straversi: Can we find an XOR type, usable for the key here?
|
||||
*/
|
||||
this._scrollSize = null;
|
||||
/**
|
||||
* Difference between scroll target's current and required scroll offsets.
|
||||
* Provided by layout.
|
||||
*/
|
||||
this._scrollErr = null;
|
||||
/**
|
||||
* A list of the positions (top, left) of the children in the current range.
|
||||
*/
|
||||
this._childrenPos = null;
|
||||
// TODO: (graynorton): type
|
||||
this._childMeasurements = null;
|
||||
this._toBeMeasured = new Map();
|
||||
this._rangeChanged = true;
|
||||
this._itemsChanged = true;
|
||||
this._visibilityChanged = true;
|
||||
/**
|
||||
* Containing element. Set by container.
|
||||
*/
|
||||
this._container = null;
|
||||
/**
|
||||
* The parent of all child nodes to be rendered. Set by container.
|
||||
*/
|
||||
this._containerElement = null;
|
||||
/**
|
||||
* Keep track of original inline style of the container, so it can be
|
||||
* restored when container is changed.
|
||||
*/
|
||||
this._containerInlineStyle = null;
|
||||
/**
|
||||
* Size of the container.
|
||||
*/
|
||||
this._containerSize = null;
|
||||
/**
|
||||
* Resize observer attached to container.
|
||||
*/
|
||||
this._containerRO = null;
|
||||
/**
|
||||
* Resize observer attached to children.
|
||||
*/
|
||||
this._childrenRO = null;
|
||||
this._mutationObserver = null;
|
||||
this._mutationPromise = null;
|
||||
this._mutationPromiseResolver = null;
|
||||
this._mutationsObserved = false;
|
||||
// TODO (graynorton): Rethink, per longer comment below
|
||||
this._loadListener = this._childLoaded.bind(this);
|
||||
/**
|
||||
* Index and position of item to scroll to.
|
||||
*/
|
||||
this._scrollToIndex = null;
|
||||
/**
|
||||
* Items to render. Set by items.
|
||||
*/
|
||||
this._items = [];
|
||||
/**
|
||||
* Total number of items to render. Set by totalItems.
|
||||
*/
|
||||
this._totalItems = null;
|
||||
/**
|
||||
* Index of the first child in the range, not necessarily the first visible child.
|
||||
* TODO @straversi: Consider renaming these.
|
||||
*/
|
||||
this._first = 0;
|
||||
/**
|
||||
* Index of the last child in the range.
|
||||
*/
|
||||
this._last = 0;
|
||||
/**
|
||||
* Index of the first item intersecting the container element.
|
||||
*/
|
||||
this._firstVisible = 0;
|
||||
/**
|
||||
* Index of the last item intersecting the container element.
|
||||
*/
|
||||
this._lastVisible = 0;
|
||||
this._scheduled = new WeakSet();
|
||||
/**
|
||||
* Invoked at the end of each render cycle: children in the range are
|
||||
* measured, and their dimensions passed to this callback. Use it to layout
|
||||
* children as needed.
|
||||
*/
|
||||
this._measureCallback = null;
|
||||
this._measureChildOverride = null;
|
||||
this._first = -1;
|
||||
this._last = -1;
|
||||
if (config) {
|
||||
Object.assign(this, config);
|
||||
}
|
||||
}
|
||||
set items(items) {
|
||||
if (Array.isArray(items) && items !== this._items) {
|
||||
this._itemsChanged = true;
|
||||
this._items = items;
|
||||
this._schedule(this._updateLayout);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The total number of items, regardless of the range, that can be rendered
|
||||
* as child nodes.
|
||||
*/
|
||||
get totalItems() {
|
||||
return this._totalItems === null ? this._items.length : this._totalItems;
|
||||
}
|
||||
set totalItems(num) {
|
||||
if (typeof num !== "number" && num !== null) {
|
||||
throw new Error("New value must be a number.");
|
||||
}
|
||||
// TODO(valdrin) should we check if it is a finite number?
|
||||
// Technically, Infinity would break Layout, not VirtualRepeater.
|
||||
if (num !== this._totalItems) {
|
||||
this._totalItems = num;
|
||||
this._schedule(this._updateLayout);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The parent of all child nodes to be rendered.
|
||||
*/
|
||||
get container() {
|
||||
return this._container;
|
||||
}
|
||||
set container(container) {
|
||||
if (container === this._container) {
|
||||
return;
|
||||
}
|
||||
if (this._container) {
|
||||
// Remove children from old container.
|
||||
// TODO (graynorton): Decide whether we'd rather fire an event to clear
|
||||
// the range and let the renderer take care of removing the DOM children
|
||||
this._children.forEach((child) => child.parentNode.removeChild(child));
|
||||
}
|
||||
this._container = container;
|
||||
this._schedule(this._updateLayout);
|
||||
this._initResizeObservers().then(() => {
|
||||
const oldEl = this._containerElement;
|
||||
// Consider document fragments as shadowRoots.
|
||||
const newEl =
|
||||
container && container.nodeType === Node.DOCUMENT_FRAGMENT_NODE
|
||||
? container.host
|
||||
: container;
|
||||
if (oldEl === newEl) {
|
||||
return;
|
||||
}
|
||||
this._containerRO.disconnect();
|
||||
this._containerSize = null;
|
||||
if (oldEl) {
|
||||
if (this._containerInlineStyle) {
|
||||
oldEl.setAttribute("style", this._containerInlineStyle);
|
||||
} else {
|
||||
oldEl.removeAttribute("style");
|
||||
}
|
||||
this._containerInlineStyle = null;
|
||||
if (oldEl === this._scrollTarget) {
|
||||
oldEl.removeEventListener("scroll", this, { passive: true });
|
||||
this._sizer && this._sizer.remove();
|
||||
}
|
||||
oldEl.removeEventListener("load", this._loadListener, true);
|
||||
this._mutationObserver.disconnect();
|
||||
} else {
|
||||
// First time container was setup, add listeners only now.
|
||||
addEventListener("scroll", this, { passive: true });
|
||||
}
|
||||
this._containerElement = newEl;
|
||||
if (newEl) {
|
||||
this._containerInlineStyle = newEl.getAttribute("style") || null;
|
||||
// https://github.com/PolymerLabs/uni-virtualizer/issues/104
|
||||
// Would rather set these CSS properties on the host using Shadow Root
|
||||
// style scoping (and fall back to a global stylesheet where native
|
||||
// Shadow DOM is not available), but this Mobile Safari bug is preventing
|
||||
// that from working: https://bugs.webkit.org/show_bug.cgi?id=226195
|
||||
const style = newEl.style;
|
||||
style.display = style.display || "block";
|
||||
style.position = style.position || "relative";
|
||||
style.overflow = style.overflow || "auto";
|
||||
style.contain = style.contain || "strict";
|
||||
if (newEl === this._scrollTarget) {
|
||||
this._sizer = this._sizer || this._createContainerSizer();
|
||||
this._container.insertBefore(this._sizer, this._container.firstChild);
|
||||
}
|
||||
this._schedule(this._updateLayout);
|
||||
this._containerRO.observe(newEl);
|
||||
this._mutationObserver.observe(newEl, { childList: true });
|
||||
this._mutationPromise = new Promise(
|
||||
(resolve) => (this._mutationPromiseResolver = resolve)
|
||||
);
|
||||
if (this._layout && this._layout.listenForChildLoadEvents) {
|
||||
newEl.addEventListener("load", this._loadListener, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// This will always actually return a layout instance,
|
||||
// but TypeScript wants the getter and setter types to be the same
|
||||
get layout() {
|
||||
return this._layout;
|
||||
}
|
||||
set layout(layout) {
|
||||
if (this._layout === layout) {
|
||||
return;
|
||||
}
|
||||
let _layout = null;
|
||||
let _config = {};
|
||||
if (typeof layout === "object") {
|
||||
if (layout.type !== undefined) {
|
||||
_layout = layout.type;
|
||||
// delete (layout as LayoutSpecifier).type;
|
||||
}
|
||||
_config = layout;
|
||||
} else {
|
||||
_layout = layout;
|
||||
}
|
||||
if (typeof _layout === "function") {
|
||||
if (this._layout instanceof _layout) {
|
||||
if (_config) {
|
||||
this._layout.config = _config;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
_layout = new _layout(_config);
|
||||
}
|
||||
}
|
||||
if (this._layout) {
|
||||
this._measureCallback = null;
|
||||
this._measureChildOverride = null;
|
||||
this._layout.removeEventListener("scrollsizechange", this);
|
||||
this._layout.removeEventListener("scrollerrorchange", this);
|
||||
this._layout.removeEventListener("itempositionchange", this);
|
||||
this._layout.removeEventListener("rangechange", this);
|
||||
delete this.container[scrollerRef];
|
||||
this.container.removeEventListener("load", this._loadListener, true);
|
||||
// Reset container size so layout can get correct viewport size.
|
||||
if (this._containerElement) {
|
||||
this._sizeContainer(undefined);
|
||||
}
|
||||
}
|
||||
this._layout = _layout;
|
||||
if (this._layout) {
|
||||
if (
|
||||
this._layout.measureChildren &&
|
||||
typeof this._layout.updateItemSizes === "function"
|
||||
) {
|
||||
if (typeof this._layout.measureChildren === "function") {
|
||||
this._measureChildOverride = this._layout.measureChildren;
|
||||
}
|
||||
this._measureCallback = this._layout.updateItemSizes.bind(this._layout);
|
||||
}
|
||||
this._layout.addEventListener("scrollsizechange", this);
|
||||
this._layout.addEventListener("scrollerrorchange", this);
|
||||
this._layout.addEventListener("itempositionchange", this);
|
||||
this._layout.addEventListener("rangechange", this);
|
||||
this._container[scrollerRef] = this;
|
||||
if (this._layout.listenForChildLoadEvents) {
|
||||
this._container.addEventListener("load", this._loadListener, true);
|
||||
}
|
||||
this._schedule(this._updateLayout);
|
||||
}
|
||||
}
|
||||
// TODO (graynorton): Rework benchmarking so that it has no API and
|
||||
// instead is always on except in production builds
|
||||
startBenchmarking() {
|
||||
if (this._benchmarkStart === null) {
|
||||
this._benchmarkStart = window.performance.now();
|
||||
}
|
||||
}
|
||||
stopBenchmarking() {
|
||||
if (this._benchmarkStart !== null) {
|
||||
const now = window.performance.now();
|
||||
const timeElapsed = now - this._benchmarkStart;
|
||||
const entries = performance.getEntriesByName(
|
||||
"uv-virtualizing",
|
||||
"measure"
|
||||
);
|
||||
const virtualizationTime = entries
|
||||
.filter((e) => e.startTime >= this._benchmarkStart && e.startTime < now)
|
||||
.reduce((t, m) => t + m.duration, 0);
|
||||
this._benchmarkStart = null;
|
||||
return { timeElapsed, virtualizationTime };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
_measureChildren() {
|
||||
const mm = {};
|
||||
const children = this._children;
|
||||
const fn = this._measureChildOverride || this._measureChild;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i];
|
||||
const idx = this._first + i;
|
||||
if (this._itemsChanged || this._toBeMeasured.has(child)) {
|
||||
mm[idx] = fn.call(
|
||||
this,
|
||||
child,
|
||||
this._items[idx] /*as unknown as object*/
|
||||
);
|
||||
}
|
||||
}
|
||||
this._childMeasurements = mm;
|
||||
this._schedule(this._updateLayout);
|
||||
this._toBeMeasured.clear();
|
||||
}
|
||||
/**
|
||||
* Returns the width, height, and margins of the given child.
|
||||
*/
|
||||
_measureChild(element) {
|
||||
// offsetWidth doesn't take transforms in consideration, so we use
|
||||
// getBoundingClientRect which does.
|
||||
const { width, height } = element.getBoundingClientRect();
|
||||
return Object.assign({ width, height }, getMargins(element));
|
||||
}
|
||||
/**
|
||||
* The element that generates scroll events and defines the container
|
||||
* viewport. The value `null` (default) corresponds to `window` as scroll
|
||||
* target.
|
||||
*/
|
||||
get scrollTarget() {
|
||||
return this._scrollTarget;
|
||||
}
|
||||
set scrollTarget(target) {
|
||||
// Consider window as null.
|
||||
if (target === window) {
|
||||
target = null;
|
||||
}
|
||||
if (this._scrollTarget === target) {
|
||||
return;
|
||||
}
|
||||
this._sizeContainer(undefined);
|
||||
if (this._scrollTarget) {
|
||||
this._scrollTarget.removeEventListener("scroll", this, { passive: true });
|
||||
if (this._sizer && this._scrollTarget === this._containerElement) {
|
||||
this._sizer.remove();
|
||||
}
|
||||
}
|
||||
this._scrollTarget = target;
|
||||
if (target) {
|
||||
target.addEventListener("scroll", this, { passive: true });
|
||||
if (target === this._containerElement) {
|
||||
this._sizer = this._sizer || this._createContainerSizer();
|
||||
this._container.insertBefore(this._sizer, this._container.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Index and position of item to scroll to. The scroller will fix to that point
|
||||
* until the user scrolls.
|
||||
*/
|
||||
set scrollToIndex(newValue) {
|
||||
this._scrollToIndex = newValue;
|
||||
this._schedule(this._updateLayout);
|
||||
}
|
||||
async _schedule(method) {
|
||||
if (!this._scheduled.has(method)) {
|
||||
this._scheduled.add(method);
|
||||
await Promise.resolve();
|
||||
this._scheduled.delete(method);
|
||||
method.call(this);
|
||||
}
|
||||
}
|
||||
async _updateDOM() {
|
||||
const { _rangeChanged, _itemsChanged } = this;
|
||||
if (this._visibilityChanged) {
|
||||
this._notifyVisibility();
|
||||
this._visibilityChanged = false;
|
||||
}
|
||||
if (_rangeChanged || _itemsChanged) {
|
||||
this._notifyRange();
|
||||
this._rangeChanged = false;
|
||||
this._itemsChanged = false;
|
||||
await this._mutationPromise;
|
||||
}
|
||||
if (this._layout.measureChildren) {
|
||||
this._children.forEach((child) => this._childrenRO.observe(child));
|
||||
}
|
||||
this._positionChildren(this._childrenPos);
|
||||
this._sizeContainer(this._scrollSize);
|
||||
if (this._scrollErr) {
|
||||
this._correctScrollError(this._scrollErr);
|
||||
this._scrollErr = null;
|
||||
}
|
||||
if (this._benchmarkStart && "mark" in window.performance) {
|
||||
window.performance.mark("uv-end");
|
||||
}
|
||||
}
|
||||
_updateLayout() {
|
||||
this._layout.totalItems = this._totalItems;
|
||||
if (this._scrollToIndex !== null) {
|
||||
this._layout.scrollToIndex(
|
||||
this._scrollToIndex.index,
|
||||
this._scrollToIndex.position
|
||||
);
|
||||
this._scrollToIndex = null;
|
||||
}
|
||||
this._updateView();
|
||||
if (this._childMeasurements !== null) {
|
||||
// If the layout has been changed, we may have measurements but no callback
|
||||
if (this._measureCallback) {
|
||||
this._measureCallback(this._childMeasurements);
|
||||
}
|
||||
this._childMeasurements = null;
|
||||
}
|
||||
this._layout.reflowIfNeeded(this._itemsChanged);
|
||||
if (this._benchmarkStart && "mark" in window.performance) {
|
||||
window.performance.mark("uv-end");
|
||||
}
|
||||
}
|
||||
_handleScrollEvent() {
|
||||
if (this._benchmarkStart && "mark" in window.performance) {
|
||||
try {
|
||||
window.performance.measure("uv-virtualizing", "uv-start", "uv-end");
|
||||
} catch (e) {
|
||||
console.warn("Error measuring performance data: ", e);
|
||||
}
|
||||
window.performance.mark("uv-start");
|
||||
}
|
||||
this._schedule(this._updateLayout);
|
||||
}
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "scroll":
|
||||
if (!this._scrollTarget || event.target === this._scrollTarget) {
|
||||
this._handleScrollEvent();
|
||||
}
|
||||
break;
|
||||
case "scrollsizechange":
|
||||
this._scrollSize = event.detail;
|
||||
this._schedule(this._updateDOM);
|
||||
break;
|
||||
case "scrollerrorchange":
|
||||
this._scrollErr = event.detail;
|
||||
this._schedule(this._updateDOM);
|
||||
break;
|
||||
case "itempositionchange":
|
||||
this._childrenPos = event.detail;
|
||||
this._schedule(this._updateDOM);
|
||||
break;
|
||||
case "rangechange":
|
||||
this._adjustRange(event.detail);
|
||||
this._schedule(this._updateDOM);
|
||||
break;
|
||||
default:
|
||||
console.warn("event not handled", event);
|
||||
}
|
||||
}
|
||||
async _initResizeObservers() {
|
||||
if (this._containerRO === null) {
|
||||
const ResizeObserver = await getResizeObserver();
|
||||
this._containerRO = new ResizeObserver((entries) =>
|
||||
this._containerSizeChanged(entries[0].contentRect)
|
||||
);
|
||||
this._childrenRO = new ResizeObserver(
|
||||
this._childrenSizeChanged.bind(this)
|
||||
);
|
||||
this._mutationObserver = new MutationObserver(
|
||||
this._observeMutations.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
_createContainerSizer() {
|
||||
const sizer = document.createElement("div");
|
||||
// When the scrollHeight is large, the height of this element might be
|
||||
// ignored. Setting content and font-size ensures the element has a size.
|
||||
Object.assign(sizer.style, {
|
||||
position: "absolute",
|
||||
margin: "-2px 0 0 0",
|
||||
padding: 0,
|
||||
visibility: "hidden",
|
||||
fontSize: "2px",
|
||||
});
|
||||
sizer.innerHTML = " ";
|
||||
sizer.id = "uni-virtualizer-spacer";
|
||||
return sizer;
|
||||
}
|
||||
get _children() {
|
||||
const arr = [];
|
||||
let next = this.container.firstElementChild;
|
||||
while (next) {
|
||||
// Skip our spacer. TODO (graynorton): Feels a bit hacky. Anything better?
|
||||
if (next.id !== "uni-virtualizer-spacer") {
|
||||
arr.push(next);
|
||||
}
|
||||
next = next.nextElementSibling;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
_updateView() {
|
||||
if (!this.container || !this._containerElement || !this._layout) {
|
||||
return;
|
||||
}
|
||||
let width, height, top, left;
|
||||
if (
|
||||
this._scrollTarget === this._containerElement &&
|
||||
this._containerSize !== null
|
||||
) {
|
||||
width = this._containerSize.width;
|
||||
height = this._containerSize.height;
|
||||
left = this._containerElement.scrollLeft;
|
||||
top = this._containerElement.scrollTop;
|
||||
} else {
|
||||
const containerBounds = this._containerElement.getBoundingClientRect();
|
||||
const scrollBounds = this._scrollTarget
|
||||
? this._scrollTarget.getBoundingClientRect()
|
||||
: {
|
||||
top: containerBounds.top + window.pageYOffset,
|
||||
left: containerBounds.left + window.pageXOffset,
|
||||
width: innerWidth,
|
||||
height: innerHeight,
|
||||
};
|
||||
const scrollerWidth = scrollBounds.width;
|
||||
const scrollerHeight = scrollBounds.height;
|
||||
const xMin = Math.max(
|
||||
0,
|
||||
Math.min(scrollerWidth, containerBounds.left - scrollBounds.left)
|
||||
);
|
||||
const yMin = Math.max(
|
||||
0,
|
||||
Math.min(scrollerHeight, containerBounds.top - scrollBounds.top)
|
||||
);
|
||||
// TODO (graynorton): Direction is intended to be a layout-level concept, not a scroller-level concept,
|
||||
// so this feels like a factoring problem
|
||||
const xMax =
|
||||
this._layout.direction === "vertical"
|
||||
? Math.max(
|
||||
0,
|
||||
Math.min(scrollerWidth, containerBounds.right - scrollBounds.left)
|
||||
)
|
||||
: scrollerWidth;
|
||||
const yMax =
|
||||
this._layout.direction === "vertical"
|
||||
? scrollerHeight
|
||||
: Math.max(
|
||||
0,
|
||||
Math.min(
|
||||
scrollerHeight,
|
||||
containerBounds.bottom - scrollBounds.top
|
||||
)
|
||||
);
|
||||
width = xMax - xMin;
|
||||
height = yMax - yMin;
|
||||
left = Math.max(0, -(containerBounds.left - scrollBounds.left));
|
||||
top = Math.max(0, -(containerBounds.top - scrollBounds.top));
|
||||
}
|
||||
this._layout.viewportSize = { width, height };
|
||||
this._layout.viewportScroll = { top, left };
|
||||
}
|
||||
/**
|
||||
* Styles the _sizer element or the container so that its size reflects the
|
||||
* total size of all items.
|
||||
*/
|
||||
_sizeContainer(size) {
|
||||
if (this._scrollTarget === this._containerElement) {
|
||||
const left = size && size.width ? size.width - 1 : 0;
|
||||
const top = size && size.height ? size.height - 1 : 0;
|
||||
if (this._sizer) {
|
||||
this._sizer.style.transform = `translate(${left}px, ${top}px)`;
|
||||
}
|
||||
} else {
|
||||
if (this._containerElement) {
|
||||
const style = this._containerElement.style;
|
||||
style.minWidth = size && size.width ? size.width + "px" : null;
|
||||
style.minHeight = size && size.height ? size.height + "px" : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the top and left transform style of the children from the values in
|
||||
* pos.
|
||||
*/
|
||||
_positionChildren(pos) {
|
||||
if (pos) {
|
||||
const children = this._children;
|
||||
Object.keys(pos).forEach((key) => {
|
||||
const idx = key - this._first;
|
||||
const child = children[idx];
|
||||
if (child) {
|
||||
const { top, left, width, height } = pos[key];
|
||||
child.style.position = "absolute";
|
||||
child.style.boxSizing = "border-box";
|
||||
child.style.transform = `translate(${left}px, ${top}px)`;
|
||||
if (width !== undefined) {
|
||||
child.style.width = width + "px";
|
||||
}
|
||||
if (height !== undefined) {
|
||||
child.style.height = height + "px";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
async _adjustRange(range) {
|
||||
const { _first, _last, _firstVisible, _lastVisible } = this;
|
||||
this._first = range.first;
|
||||
this._last = range.last;
|
||||
this._firstVisible = range.firstVisible;
|
||||
this._lastVisible = range.lastVisible;
|
||||
this._rangeChanged =
|
||||
this._rangeChanged || this._first !== _first || this._last !== _last;
|
||||
this._visibilityChanged =
|
||||
this._visibilityChanged ||
|
||||
this._firstVisible !== _firstVisible ||
|
||||
this._lastVisible !== _lastVisible;
|
||||
}
|
||||
_correctScrollError(err) {
|
||||
if (this._scrollTarget) {
|
||||
this._scrollTarget.scrollTop -= err.top;
|
||||
this._scrollTarget.scrollLeft -= err.left;
|
||||
} else {
|
||||
window.scroll(
|
||||
window.pageXOffset - err.left,
|
||||
window.pageYOffset - err.top
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Emits a rangechange event with the current first, last, firstVisible, and
|
||||
* lastVisible.
|
||||
*/
|
||||
_notifyRange() {
|
||||
// TODO (graynorton): Including visibility here for backward compat, but
|
||||
// may decide to remove at some point. The rationale for separating is that
|
||||
// range change events are mainly intended for "internal" consumption by the
|
||||
// renderer, whereas visibility change events are mainly intended for "external"
|
||||
// consumption by application code.
|
||||
this._container.dispatchEvent(
|
||||
new CustomEvent("rangeChanged", {
|
||||
detail: {
|
||||
first: this._first,
|
||||
last: this._last,
|
||||
firstVisible: this._firstVisible,
|
||||
lastVisible: this._lastVisible,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
_notifyVisibility() {
|
||||
this._container.dispatchEvent(
|
||||
new CustomEvent("visibilityChanged", {
|
||||
detail: {
|
||||
first: this._first,
|
||||
last: this._last,
|
||||
firstVisible: this._firstVisible,
|
||||
lastVisible: this._lastVisible,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Render and update the view at the next opportunity with the given
|
||||
* container size.
|
||||
*/
|
||||
_containerSizeChanged(size) {
|
||||
const { width, height } = size;
|
||||
this._containerSize = { width, height };
|
||||
this._schedule(this._updateLayout);
|
||||
}
|
||||
async _observeMutations() {
|
||||
if (!this._mutationsObserved) {
|
||||
this._mutationsObserved = true;
|
||||
this._mutationPromiseResolver();
|
||||
this._mutationPromise = new Promise(
|
||||
(resolve) => (this._mutationPromiseResolver = resolve)
|
||||
);
|
||||
this._mutationsObserved = false;
|
||||
}
|
||||
}
|
||||
// TODO (graynorton): Rethink how this works. Probably child loading is too specific
|
||||
// to have dedicated support for; might want some more generic lifecycle hooks for
|
||||
// layouts to use. Possibly handle measurement this way, too, or maybe that remains
|
||||
// a first-class feature?
|
||||
_childLoaded() {
|
||||
// this.requestRemeasure();
|
||||
}
|
||||
_childrenSizeChanged(changes) {
|
||||
for (const change of changes) {
|
||||
this._toBeMeasured.set(change.target, change.contentRect);
|
||||
}
|
||||
this._measureChildren();
|
||||
this._schedule(this._updateLayout);
|
||||
}
|
||||
}
|
||||
function getMargins(el) {
|
||||
const style = window.getComputedStyle(el);
|
||||
return {
|
||||
marginTop: getMarginValue(style.marginTop),
|
||||
marginRight: getMarginValue(style.marginRight),
|
||||
marginBottom: getMarginValue(style.marginBottom),
|
||||
marginLeft: getMarginValue(style.marginLeft),
|
||||
};
|
||||
}
|
||||
function getMarginValue(value) {
|
||||
const float = value ? parseFloat(value) : NaN;
|
||||
return Number.isNaN(float) ? 0 : float;
|
||||
}
|
||||
//# sourceMappingURL=VirtualScroller.js.map
|
File diff suppressed because one or more lines are too long
90
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout.d.ts
vendored
Normal file
90
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout.d.ts
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
export declare type dimension = "height" | "width";
|
||||
export declare type Size = {
|
||||
[key in dimension]: number;
|
||||
};
|
||||
export declare type Margins = {
|
||||
marginTop: number;
|
||||
marginRight: number;
|
||||
marginBottom: number;
|
||||
marginLeft: number;
|
||||
};
|
||||
export declare type ItemBox = Size | (Size & Margins);
|
||||
export declare type position = "left" | "top";
|
||||
export declare type Positions = {
|
||||
left: number;
|
||||
top: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
};
|
||||
export declare type LayoutConstructor = new (config?: object) => Layout;
|
||||
export interface LayoutSpecifier {
|
||||
type: LayoutConstructor;
|
||||
}
|
||||
export declare type LayoutSpecifierFactory = (
|
||||
config?: object
|
||||
) => LayoutSpecifier;
|
||||
export declare type ScrollDirection = "vertical" | "horizontal";
|
||||
/**
|
||||
* Interface for layouts consumed by VirtualScroller or VirtualRepeater.
|
||||
*/
|
||||
export interface Layout {
|
||||
config?: object;
|
||||
totalItems: number;
|
||||
direction: ScrollDirection;
|
||||
viewportSize: Size;
|
||||
viewportScroll: Positions;
|
||||
readonly measureChildren?: boolean | ((e: Element, i: unknown) => ItemBox);
|
||||
readonly listenForChildLoadEvents?: boolean;
|
||||
updateItemSizes?: (sizes: { [key: number]: ItemBox }) => void;
|
||||
addEventListener: Function;
|
||||
removeEventListener: Function;
|
||||
scrollToIndex: (index: number, position: string) => void;
|
||||
/**
|
||||
* Called by a VirtualRepeater or VirtualScroller when an update that
|
||||
* potentially affects layout has occurred. For example, a viewport size
|
||||
* change.
|
||||
*
|
||||
* The layout is in turn responsible for dispatching events, as necessary,
|
||||
* to the VirtualRepeater or VirtualScroller. Each of the following events
|
||||
* represents an update that should be determined during a reflow. Dispatch
|
||||
* each event at maximum once during a single reflow.
|
||||
*
|
||||
* Events that should be dispatched:
|
||||
* - scrollsizechange
|
||||
* Dispatch when the total length of all items in the scrolling direction,
|
||||
* including spacing, changes.
|
||||
* detail: {
|
||||
* 'height' | 'width': number
|
||||
* }
|
||||
* - rangechange
|
||||
* Dispatch when the range of children that should be displayed changes
|
||||
* (based on layout calculations and the size of the container) or when
|
||||
* the first or last item to intersect the container changes.
|
||||
* detail: {
|
||||
* first: number,
|
||||
* last: number,
|
||||
* num: number,
|
||||
* stable: boolean,
|
||||
* remeasure: boolean,
|
||||
* firstVisible: number,
|
||||
* lastVisible: number,
|
||||
* }
|
||||
* - itempositionchange
|
||||
* Dispatch when the child positions change, for example due to a range
|
||||
* change.
|
||||
* detail {
|
||||
* [number]: {
|
||||
* left: number,
|
||||
* top: number
|
||||
* }
|
||||
* }
|
||||
* - scrollerrorchange
|
||||
* Dispatch when the set viewportScroll offset is not what it should be.
|
||||
* detail {
|
||||
* height: number,
|
||||
* width: number,
|
||||
* }
|
||||
*/
|
||||
reflowIfNeeded: (force: boolean) => void;
|
||||
}
|
||||
//# sourceMappingURL=Layout.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC3C,oBAAY,IAAI,GAAG;KAChB,GAAG,IAAI,SAAS,GAAG,MAAM;CAC3B,CAAC;AAEF,oBAAY,OAAO,GAAG;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAC;AAEF,oBAAY,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;AAE9C,oBAAY,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AACtC,oBAAY,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAC;AAGF,oBAAY,iBAAiB,GAAG,KAAI,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,iBAAiB,CAAA;CACxB;AAED,oBAAY,sBAAsB,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,eAAe,CAAC;AAG1E,oBAAY,eAAe,GAAG,UAAU,GAAG,YAAY,CAAC;AAExD;;GAEG;AACF,MAAM,WAAW,MAAM;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,EAAE,eAAe,CAAC;IAE3B,YAAY,EAAE,IAAI,CAAC;IAEnB,cAAc,EAAE,SAAS,CAAC;IAE1B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC;IAE3E,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAE5C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,KAAK,IAAI,CAAC;IAEX,gBAAgB,EAAE,QAAQ,CAAC;IAE3B,mBAAmB,EAAE,QAAQ,CAAC;IAE9B,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6CG;IACH,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C"}
|
@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=Layout.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout.js","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout.ts"],"names":[],"mappings":"","sourcesContent":["export type dimension = 'height' | 'width';\nexport type Size = {\n [key in dimension]: number\n};\n\nexport type Margins = {\n marginTop: number,\n marginRight: number,\n marginBottom: number,\n marginLeft: number\n};\n\nexport type ItemBox = Size | (Size & Margins);\n\nexport type position = 'left' | 'top';\nexport type Positions = {\n left: number,\n top: number,\n width?: number,\n height?: number\n};\n\n\nexport type LayoutConstructor = new(config?: object) => Layout;\n\nexport interface LayoutSpecifier {\n type: LayoutConstructor\n}\n\nexport type LayoutSpecifierFactory = (config?: object) => LayoutSpecifier;\n\n\nexport type ScrollDirection = 'vertical' | 'horizontal';\n\n/**\n * Interface for layouts consumed by VirtualScroller or VirtualRepeater.\n */\n export interface Layout {\n config?: object;\n \n totalItems: number;\n\n direction: ScrollDirection;\n\n viewportSize: Size;\n\n viewportScroll: Positions;\n\n readonly measureChildren?: boolean | ((e: Element, i: unknown) => ItemBox);\n\n readonly listenForChildLoadEvents?: boolean;\n\n updateItemSizes?: (sizes: {\n [key: number]: ItemBox\n }) => void;\n\n addEventListener: Function;\n\n removeEventListener: Function;\n\n scrollToIndex: (index: number, position: string) => void;\n\n /**\n * Called by a VirtualRepeater or VirtualScroller when an update that\n * potentially affects layout has occurred. For example, a viewport size\n * change.\n *\n * The layout is in turn responsible for dispatching events, as necessary,\n * to the VirtualRepeater or VirtualScroller. Each of the following events\n * represents an update that should be determined during a reflow. Dispatch\n * each event at maximum once during a single reflow.\n *\n * Events that should be dispatched:\n * - scrollsizechange\n * Dispatch when the total length of all items in the scrolling direction,\n * including spacing, changes.\n * detail: {\n * 'height' | 'width': number\n * }\n * - rangechange\n * Dispatch when the range of children that should be displayed changes\n * (based on layout calculations and the size of the container) or when\n * the first or last item to intersect the container changes.\n * detail: {\n * first: number,\n * last: number,\n * num: number,\n * stable: boolean,\n * remeasure: boolean,\n * firstVisible: number,\n * lastVisible: number,\n * }\n * - itempositionchange\n * Dispatch when the child positions change, for example due to a range\n * change.\n * detail {\n * [number]: {\n * left: number,\n * top: number\n * }\n * }\n * - scrollerrorchange\n * Dispatch when the set viewportScroll offset is not what it should be.\n * detail {\n * height: number,\n * width: number,\n * }\n */\n reflowIfNeeded: (force: boolean) => void;\n}"]}
|
108
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1d.d.ts
vendored
Normal file
108
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1d.d.ts
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
import { Layout1dBase, Layout1dBaseConfig } from "./Layout1dBase.js";
|
||||
import { ItemBox, Positions, Size } from "./Layout.js";
|
||||
declare type ItemBounds = {
|
||||
pos: number;
|
||||
size: number;
|
||||
};
|
||||
declare type Layout1dConstructor = {
|
||||
prototype: Layout1d;
|
||||
new (config?: Layout1dBaseConfig): Layout1d;
|
||||
};
|
||||
declare type Layout1dSpecifier = Layout1dBaseConfig & {
|
||||
type: Layout1dConstructor;
|
||||
};
|
||||
declare type Layout1dSpecifierFactory = (
|
||||
config?: Layout1dBaseConfig
|
||||
) => Layout1dSpecifier;
|
||||
export declare const layout1d: Layout1dSpecifierFactory;
|
||||
export declare class Layout1d extends Layout1dBase<Layout1dBaseConfig> {
|
||||
/**
|
||||
* Indices of children mapped to their (position and length) in the scrolling
|
||||
* direction. Used to keep track of children that are in range.
|
||||
*/
|
||||
_physicalItems: Map<number, ItemBounds>;
|
||||
/**
|
||||
* Used in tandem with _physicalItems to track children in range across
|
||||
* reflows.
|
||||
*/
|
||||
_newPhysicalItems: Map<number, ItemBounds>;
|
||||
/**
|
||||
* Width and height of children by their index.
|
||||
*/
|
||||
_metrics: Map<number, Size>;
|
||||
/**
|
||||
* anchorIdx is the anchor around which we reflow. It is designed to allow
|
||||
* jumping to any point of the scroll size. We choose it once and stick with
|
||||
* it until stable. _first and _last are deduced around it.
|
||||
*/
|
||||
_anchorIdx: number | null;
|
||||
/**
|
||||
* Position in the scrolling direction of the anchor child.
|
||||
*/
|
||||
_anchorPos: number | null;
|
||||
/**
|
||||
* Whether all children in range were in range during the previous reflow.
|
||||
*/
|
||||
_stable: boolean;
|
||||
/**
|
||||
* Whether to remeasure children during the next reflow.
|
||||
*/
|
||||
_needsRemeasure: boolean;
|
||||
/**
|
||||
* Number of children to lay out.
|
||||
*/
|
||||
private _nMeasured;
|
||||
/**
|
||||
* Total length in the scrolling direction of the laid out children.
|
||||
*/
|
||||
private _tMeasured;
|
||||
private _measureChildren;
|
||||
_estimate: boolean;
|
||||
get measureChildren(): boolean;
|
||||
/**
|
||||
* Determine the average size of all children represented in the sizes
|
||||
* argument.
|
||||
*/
|
||||
updateItemSizes(sizes: { [key: number]: ItemBox }): void;
|
||||
/**
|
||||
* Set the average item size based on the total length and number of children
|
||||
* in range.
|
||||
*/
|
||||
_updateItemSize(): void;
|
||||
_getMetrics(idx: number): ItemBox;
|
||||
_getPhysicalItem(idx: number): ItemBounds | undefined;
|
||||
_getSize(idx: number): number | undefined;
|
||||
/**
|
||||
* Returns the position in the scrolling direction of the item at idx.
|
||||
* Estimates it if the item at idx is not in the DOM.
|
||||
*/
|
||||
_getPosition(idx: number): number;
|
||||
_calculateAnchor(lower: number, upper: number): number;
|
||||
_getAnchor(lower: number, upper: number): number;
|
||||
/**
|
||||
* Updates _first and _last based on items that should be in the current
|
||||
* viewed range.
|
||||
*/
|
||||
_getActiveItems(): void;
|
||||
/**
|
||||
* Sets the range to empty.
|
||||
*/
|
||||
_clearItems(): void;
|
||||
_getItems(): void;
|
||||
_calculateError(): number;
|
||||
_updateScrollSize(): void;
|
||||
_reflow(): void;
|
||||
_resetReflowState(): void;
|
||||
/**
|
||||
* Returns the top and left positioning of the item at idx.
|
||||
*/
|
||||
_getItemPosition(idx: number): Positions;
|
||||
/**
|
||||
* Returns the height and width of the item at idx.
|
||||
*/
|
||||
_getItemSize(idx: number): Size;
|
||||
_viewDim2Changed(): void;
|
||||
_emitRange(): void;
|
||||
}
|
||||
export {};
|
||||
//# sourceMappingURL=Layout1d.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1d.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1d.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAU,MAAM,aAAa,CAAC;AAE9D,aAAK,UAAU,GAAG;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAC;AAEF,aAAK,mBAAmB,GAAG;IACzB,SAAS,EAAE,QAAQ,CAAC;IACpB,KAAI,MAAM,CAAC,EAAE,kBAAkB,GAAG,QAAQ,CAAA;CAC3C,CAAA;AAED,aAAK,iBAAiB,GAAG,kBAAkB,GAAG;IAC5C,IAAI,EAAE,mBAAmB,CAAA;CAC1B,CAAA;AAED,aAAK,wBAAwB,GAAG,CAAC,MAAM,CAAC,EAAE,kBAAkB,KAAK,iBAAiB,CAAC;AAEnF,eAAO,MAAM,QAAQ,EAAE,wBAEb,CAAC;AAGX,qBAAa,QAAS,SAAQ,YAAY,CAAC,kBAAkB,CAAC;IAC5D;;;OAGG;IACH,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAa;IAEpD;;;OAGG;IACH,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAa;IAEvD;;OAEG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAa;IAExC;;;;OAIG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC;;OAEG;IACH,OAAO,UAAQ;IAEf;;OAEG;IACH,eAAe,UAAS;IAExB;;OAEG;IACH,OAAO,CAAC,UAAU,CAAK;IAEvB;;OAEG;IACH,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,gBAAgB,CAAQ;IAEhC,SAAS,UAAQ;IAUjB,IAAI,eAAe,YAElB;IAED;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAC;IAmC/C;;;OAGG;IACH,eAAe;IAMf,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IASjC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAIrD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKzC;;;OAGG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAKjC,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IActD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAqDhD;;;OAGG;IACH,eAAe;IAQf;;OAEG;IACH,WAAW;IAeX,SAAS;IA+GT,eAAe,IAAI,MAAM;IAezB,iBAAiB;IAQjB,OAAO;IA0BP,iBAAiB;IAMjB;;OAEG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAOxC;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO/B,gBAAgB;IAKhB,UAAU;CAMX"}
|
@ -0,0 +1,406 @@
|
||||
import { Layout1dBase } from "./Layout1dBase.js";
|
||||
export const layout1d = (config) =>
|
||||
Object.assign(
|
||||
{
|
||||
type: Layout1d,
|
||||
},
|
||||
config
|
||||
);
|
||||
export class Layout1d extends Layout1dBase {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
/**
|
||||
* Indices of children mapped to their (position and length) in the scrolling
|
||||
* direction. Used to keep track of children that are in range.
|
||||
*/
|
||||
this._physicalItems = new Map();
|
||||
/**
|
||||
* Used in tandem with _physicalItems to track children in range across
|
||||
* reflows.
|
||||
*/
|
||||
this._newPhysicalItems = new Map();
|
||||
/**
|
||||
* Width and height of children by their index.
|
||||
*/
|
||||
this._metrics = new Map();
|
||||
/**
|
||||
* anchorIdx is the anchor around which we reflow. It is designed to allow
|
||||
* jumping to any point of the scroll size. We choose it once and stick with
|
||||
* it until stable. _first and _last are deduced around it.
|
||||
*/
|
||||
this._anchorIdx = null;
|
||||
/**
|
||||
* Position in the scrolling direction of the anchor child.
|
||||
*/
|
||||
this._anchorPos = null;
|
||||
/**
|
||||
* Whether all children in range were in range during the previous reflow.
|
||||
*/
|
||||
this._stable = true;
|
||||
/**
|
||||
* Whether to remeasure children during the next reflow.
|
||||
*/
|
||||
this._needsRemeasure = false;
|
||||
/**
|
||||
* Number of children to lay out.
|
||||
*/
|
||||
this._nMeasured = 0;
|
||||
/**
|
||||
* Total length in the scrolling direction of the laid out children.
|
||||
*/
|
||||
this._tMeasured = 0;
|
||||
this._measureChildren = true;
|
||||
this._estimate = true;
|
||||
}
|
||||
// protected _defaultConfig: Layout1dBaseConfig = Object.assign({}, super._defaultConfig, {
|
||||
// })
|
||||
// constructor(config: Layout1dConfig) {
|
||||
// super(config);
|
||||
// }
|
||||
get measureChildren() {
|
||||
return this._measureChildren;
|
||||
}
|
||||
/**
|
||||
* Determine the average size of all children represented in the sizes
|
||||
* argument.
|
||||
*/
|
||||
updateItemSizes(sizes) {
|
||||
Object.keys(sizes).forEach((key) => {
|
||||
const metrics = sizes[Number(key)],
|
||||
mi = this._getMetrics(Number(key)),
|
||||
prevSize = mi[this._sizeDim];
|
||||
// TODO(valdrin) Handle margin collapsing.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
|
||||
mi.width =
|
||||
metrics.width + (metrics.marginLeft || 0) + (metrics.marginRight || 0);
|
||||
mi.height =
|
||||
metrics.height + (metrics.marginTop || 0) + (metrics.marginBottom || 0);
|
||||
const size = mi[this._sizeDim];
|
||||
const item = this._getPhysicalItem(Number(key));
|
||||
if (item) {
|
||||
let delta = 0;
|
||||
if (size !== undefined) {
|
||||
item.size = size;
|
||||
if (prevSize === -1) {
|
||||
delta = size;
|
||||
this._nMeasured++;
|
||||
} else {
|
||||
delta = size - prevSize;
|
||||
}
|
||||
}
|
||||
this._tMeasured = this._tMeasured + delta;
|
||||
}
|
||||
});
|
||||
if (this._nMeasured) {
|
||||
this._updateItemSize();
|
||||
this._scheduleReflow();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set the average item size based on the total length and number of children
|
||||
* in range.
|
||||
*/
|
||||
_updateItemSize() {
|
||||
// Keep integer values.
|
||||
this._itemSize[this._sizeDim] = Math.round(
|
||||
this._tMeasured / this._nMeasured
|
||||
);
|
||||
}
|
||||
_getMetrics(idx) {
|
||||
let metrics = this._metrics.get(idx);
|
||||
if (metrics === undefined) {
|
||||
metrics = { height: -1, width: -1 };
|
||||
this._metrics.set(idx, metrics);
|
||||
}
|
||||
return metrics;
|
||||
}
|
||||
_getPhysicalItem(idx) {
|
||||
return this._newPhysicalItems.get(idx) || this._physicalItems.get(idx);
|
||||
}
|
||||
_getSize(idx) {
|
||||
const item = this._getPhysicalItem(idx);
|
||||
return item && item.size;
|
||||
}
|
||||
/**
|
||||
* Returns the position in the scrolling direction of the item at idx.
|
||||
* Estimates it if the item at idx is not in the DOM.
|
||||
*/
|
||||
_getPosition(idx) {
|
||||
const item = this._getPhysicalItem(idx);
|
||||
return item ? item.pos : idx * this._delta + this._spacing;
|
||||
}
|
||||
_calculateAnchor(lower, upper) {
|
||||
if (lower === 0) {
|
||||
return 0;
|
||||
}
|
||||
if (upper > this._scrollSize - this._viewDim1) {
|
||||
return this._totalItems - 1;
|
||||
}
|
||||
return Math.max(
|
||||
0,
|
||||
Math.min(
|
||||
this._totalItems - 1,
|
||||
Math.floor((lower + upper) / 2 / this._delta)
|
||||
)
|
||||
);
|
||||
}
|
||||
_getAnchor(lower, upper) {
|
||||
if (this._physicalItems.size === 0) {
|
||||
return this._calculateAnchor(lower, upper);
|
||||
}
|
||||
if (this._first < 0) {
|
||||
console.error("_getAnchor: negative _first");
|
||||
return this._calculateAnchor(lower, upper);
|
||||
}
|
||||
if (this._last < 0) {
|
||||
console.error("_getAnchor: negative _last");
|
||||
return this._calculateAnchor(lower, upper);
|
||||
}
|
||||
const firstItem = this._getPhysicalItem(this._first),
|
||||
lastItem = this._getPhysicalItem(this._last),
|
||||
firstMin = firstItem.pos,
|
||||
firstMax = firstMin + firstItem.size,
|
||||
lastMin = lastItem.pos,
|
||||
lastMax = lastMin + lastItem.size;
|
||||
if (lastMax < lower) {
|
||||
// Window is entirely past physical items, calculate new anchor
|
||||
return this._calculateAnchor(lower, upper);
|
||||
}
|
||||
if (firstMin > upper) {
|
||||
// Window is entirely before physical items, calculate new anchor
|
||||
return this._calculateAnchor(lower, upper);
|
||||
}
|
||||
if (firstMin >= lower || firstMax >= lower) {
|
||||
// First physical item overlaps window, choose it
|
||||
return this._first;
|
||||
}
|
||||
if (lastMax <= upper || lastMin <= upper) {
|
||||
// Last physical overlaps window, choose it
|
||||
return this._last;
|
||||
}
|
||||
// Window contains a physical item, but not the first or last
|
||||
let maxIdx = this._last,
|
||||
minIdx = this._first;
|
||||
while (true) {
|
||||
const candidateIdx = Math.round((maxIdx + minIdx) / 2),
|
||||
candidate = this._physicalItems.get(candidateIdx),
|
||||
cMin = candidate.pos,
|
||||
cMax = cMin + candidate.size;
|
||||
if (
|
||||
(cMin >= lower && cMin <= upper) ||
|
||||
(cMax >= lower && cMax <= upper)
|
||||
) {
|
||||
return candidateIdx;
|
||||
} else if (cMax < lower) {
|
||||
minIdx = candidateIdx + 1;
|
||||
} else if (cMin > upper) {
|
||||
maxIdx = candidateIdx - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Updates _first and _last based on items that should be in the current
|
||||
* viewed range.
|
||||
*/
|
||||
_getActiveItems() {
|
||||
if (this._viewDim1 === 0 || this._totalItems === 0) {
|
||||
this._clearItems();
|
||||
} else {
|
||||
this._getItems();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the range to empty.
|
||||
*/
|
||||
_clearItems() {
|
||||
this._first = -1;
|
||||
this._last = -1;
|
||||
this._physicalMin = 0;
|
||||
this._physicalMax = 0;
|
||||
const items = this._newPhysicalItems;
|
||||
this._newPhysicalItems = this._physicalItems;
|
||||
this._newPhysicalItems.clear();
|
||||
this._physicalItems = items;
|
||||
this._stable = true;
|
||||
}
|
||||
/*
|
||||
* Updates _first and _last based on items that should be in the given range.
|
||||
*/
|
||||
_getItems() {
|
||||
const items = this._newPhysicalItems;
|
||||
let lower, upper;
|
||||
// The anchorIdx is the anchor around which we reflow. It is designed to
|
||||
// allow jumping to any point of the scroll size. We choose it once and
|
||||
// stick with it until stable. first and last are deduced around it.
|
||||
if (this._scrollToIndex >= 0) {
|
||||
// If we have a scrollToIndex, we anchor on the given
|
||||
// index and set the scroll position accordingly
|
||||
this._anchorIdx = this._scrollToIndex;
|
||||
this._anchorPos = this._getPosition(this._anchorIdx);
|
||||
this._scrollIfNeeded();
|
||||
lower = Math.max(0, this._scrollPosition - this._overhang);
|
||||
upper = Math.min(
|
||||
this._scrollSize,
|
||||
this._scrollPosition + this._viewDim1 + this._overhang
|
||||
);
|
||||
} else {
|
||||
// Otherwise, we find an appropriate index to anchor on
|
||||
// given the current scroll position
|
||||
upper = Math.min(
|
||||
this._scrollSize,
|
||||
this._scrollPosition + this._viewDim1 + this._overhang
|
||||
);
|
||||
lower = Math.max(0, upper - this._viewDim1 - 2 * this._overhang);
|
||||
if (this._anchorIdx === null || this._anchorPos === null) {
|
||||
this._anchorIdx = this._getAnchor(lower, upper);
|
||||
this._anchorPos = this._getPosition(this._anchorIdx);
|
||||
}
|
||||
}
|
||||
let anchorSize = this._getSize(this._anchorIdx);
|
||||
if (anchorSize === undefined) {
|
||||
anchorSize = this._itemDim1;
|
||||
}
|
||||
// Anchor might be outside bounds, so prefer correcting the error and keep
|
||||
// that anchorIdx.
|
||||
let anchorErr = 0;
|
||||
if (this._anchorPos + anchorSize + this._spacing < lower) {
|
||||
anchorErr = lower - (this._anchorPos + anchorSize + this._spacing);
|
||||
}
|
||||
if (this._anchorPos > upper) {
|
||||
anchorErr = upper - this._anchorPos;
|
||||
}
|
||||
if (anchorErr) {
|
||||
this._scrollPosition -= anchorErr;
|
||||
lower -= anchorErr;
|
||||
upper -= anchorErr;
|
||||
this._scrollError += anchorErr;
|
||||
}
|
||||
// TODO @straversi: If size is always itemDim1, then why keep track of it?
|
||||
items.set(this._anchorIdx, { pos: this._anchorPos, size: anchorSize });
|
||||
this._first = this._last = this._anchorIdx;
|
||||
this._physicalMin = this._physicalMax = this._anchorPos;
|
||||
this._stable = true;
|
||||
while (this._physicalMin > lower && this._first > 0) {
|
||||
let size = this._getSize(--this._first);
|
||||
if (size === undefined) {
|
||||
this._stable = false;
|
||||
size = this._itemDim1;
|
||||
}
|
||||
const pos = (this._physicalMin -= size + this._spacing);
|
||||
items.set(this._first, { pos, size });
|
||||
if (this._stable === false && this._estimate === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (this._physicalMax < upper && this._last < this._totalItems) {
|
||||
let size = this._getSize(this._last);
|
||||
if (size === undefined) {
|
||||
this._stable = false;
|
||||
size = this._itemDim1;
|
||||
}
|
||||
items.set(this._last++, { pos: this._physicalMax, size });
|
||||
if (this._stable === false && this._estimate === false) {
|
||||
break;
|
||||
} else {
|
||||
this._physicalMax += size + this._spacing;
|
||||
}
|
||||
}
|
||||
this._last--;
|
||||
// This handles the cases where we were relying on estimated sizes.
|
||||
const extentErr = this._calculateError();
|
||||
if (extentErr) {
|
||||
this._physicalMin -= extentErr;
|
||||
this._physicalMax -= extentErr;
|
||||
this._anchorPos -= extentErr;
|
||||
this._scrollPosition -= extentErr;
|
||||
items.forEach((item) => (item.pos -= extentErr));
|
||||
this._scrollError += extentErr;
|
||||
}
|
||||
if (this._stable) {
|
||||
this._newPhysicalItems = this._physicalItems;
|
||||
this._newPhysicalItems.clear();
|
||||
this._physicalItems = items;
|
||||
}
|
||||
}
|
||||
_calculateError() {
|
||||
if (this._first === 0) {
|
||||
return this._physicalMin;
|
||||
} else if (this._physicalMin <= 0) {
|
||||
return this._physicalMin - this._first * this._delta;
|
||||
} else if (this._last === this._totalItems - 1) {
|
||||
return this._physicalMax - this._scrollSize;
|
||||
} else if (this._physicalMax >= this._scrollSize) {
|
||||
return (
|
||||
this._physicalMax -
|
||||
this._scrollSize +
|
||||
(this._totalItems - 1 - this._last) * this._delta
|
||||
);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_updateScrollSize() {
|
||||
// Reuse previously calculated physical max, as it might be higher than the
|
||||
// estimated size.
|
||||
super._updateScrollSize();
|
||||
this._scrollSize = Math.max(this._physicalMax, this._scrollSize);
|
||||
}
|
||||
// TODO: Can this be made to inherit from base, with proper hooks?
|
||||
_reflow() {
|
||||
const { _first, _last, _scrollSize } = this;
|
||||
this._updateScrollSize();
|
||||
this._getActiveItems();
|
||||
if (this._scrollSize !== _scrollSize) {
|
||||
this._emitScrollSize();
|
||||
}
|
||||
this._updateVisibleIndices();
|
||||
this._emitRange();
|
||||
if (this._first === -1 && this._last === -1) {
|
||||
this._resetReflowState();
|
||||
} else if (
|
||||
this._first !== _first ||
|
||||
this._last !== _last ||
|
||||
this._needsRemeasure
|
||||
) {
|
||||
this._emitChildPositions();
|
||||
this._emitScrollError();
|
||||
} else {
|
||||
this._emitChildPositions();
|
||||
this._emitScrollError();
|
||||
this._resetReflowState();
|
||||
}
|
||||
}
|
||||
_resetReflowState() {
|
||||
this._anchorIdx = null;
|
||||
this._anchorPos = null;
|
||||
this._stable = true;
|
||||
}
|
||||
/**
|
||||
* Returns the top and left positioning of the item at idx.
|
||||
*/
|
||||
_getItemPosition(idx) {
|
||||
return {
|
||||
[this._positionDim]: this._getPosition(idx),
|
||||
[this._secondaryPositionDim]: 0,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Returns the height and width of the item at idx.
|
||||
*/
|
||||
_getItemSize(idx) {
|
||||
return {
|
||||
[this._sizeDim]: this._getSize(idx) || this._itemDim1,
|
||||
[this._secondarySizeDim]: this._itemDim2,
|
||||
};
|
||||
}
|
||||
_viewDim2Changed() {
|
||||
this._needsRemeasure = true;
|
||||
this._scheduleReflow();
|
||||
}
|
||||
_emitRange() {
|
||||
const remeasure = this._needsRemeasure;
|
||||
const stable = this._stable;
|
||||
this._needsRemeasure = false;
|
||||
super._emitRange({ remeasure, stable });
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Layout1d.js.map
|
File diff suppressed because one or more lines are too long
236
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dBase.d.ts
vendored
Normal file
236
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dBase.d.ts
vendored
Normal file
@ -0,0 +1,236 @@
|
||||
import {
|
||||
Layout,
|
||||
Positions,
|
||||
ScrollDirection,
|
||||
Size,
|
||||
dimension,
|
||||
position,
|
||||
} from "./Layout.js";
|
||||
declare type UpdateVisibleIndicesOptions = {
|
||||
emit?: boolean;
|
||||
};
|
||||
export interface Layout1dBaseConfig {
|
||||
direction?: ScrollDirection;
|
||||
totalItems?: number;
|
||||
}
|
||||
export declare abstract class Layout1dBase<C extends Layout1dBaseConfig>
|
||||
implements Layout {
|
||||
/**
|
||||
* The last set viewport scroll position.
|
||||
*/
|
||||
private _latestCoords;
|
||||
/**
|
||||
* Scrolling direction.
|
||||
*/
|
||||
private _direction;
|
||||
/**
|
||||
* Dimensions of the viewport.
|
||||
*/
|
||||
private _viewportSize;
|
||||
/**
|
||||
* Flag for debouncing asynchnronous reflow requests.
|
||||
*/
|
||||
private _pendingReflow;
|
||||
private _pendingLayoutUpdate;
|
||||
/**
|
||||
* Index of the item that has been scrolled to via the public API. When the
|
||||
* container is otherwise scrolled, this value is set back to -1.
|
||||
*/
|
||||
protected _scrollToIndex: number;
|
||||
/**
|
||||
* When a child is scrolled to, the offset from the top of the child and the
|
||||
* top of the viewport. Value is a proportion of the item size.
|
||||
*/
|
||||
private _scrollToAnchor;
|
||||
/**
|
||||
* The index of the first item intersecting the viewport.
|
||||
*/
|
||||
private _firstVisible;
|
||||
/**
|
||||
* The index of the last item intersecting the viewport.
|
||||
*/
|
||||
private _lastVisible;
|
||||
private _eventTargetPromise;
|
||||
/**
|
||||
* Pixel offset in the scroll direction of the first child.
|
||||
*/
|
||||
protected _physicalMin: number;
|
||||
/**
|
||||
* Pixel offset in the scroll direction of the last child.
|
||||
*/
|
||||
protected _physicalMax: number;
|
||||
/**
|
||||
* Index of the first child.
|
||||
*/
|
||||
protected _first: number;
|
||||
/**
|
||||
* Index of the last child.
|
||||
*/
|
||||
protected _last: number;
|
||||
/**
|
||||
* The _estimated_ size of a child.
|
||||
*/
|
||||
protected _itemSize: Size;
|
||||
/**
|
||||
* Space in pixels between children.
|
||||
*/
|
||||
protected _spacing: number;
|
||||
/**
|
||||
* Length in the scrolling direction.
|
||||
*/
|
||||
protected _sizeDim: dimension;
|
||||
/**
|
||||
* Length in the non-scrolling direction.
|
||||
*/
|
||||
protected _secondarySizeDim: dimension;
|
||||
/**
|
||||
* Position in the scrolling direction.
|
||||
*/
|
||||
protected _positionDim: position;
|
||||
/**
|
||||
* Position in the non-scrolling direction.
|
||||
*/
|
||||
protected _secondaryPositionDim: position;
|
||||
/**
|
||||
* Current scroll offset in pixels.
|
||||
*/
|
||||
protected _scrollPosition: number;
|
||||
/**
|
||||
* Difference between current scroll offset and scroll offset calculated due
|
||||
* to a reflow.
|
||||
*/
|
||||
protected _scrollError: number;
|
||||
/**
|
||||
* Total number of items that could possibly be displayed. Used to help
|
||||
* calculate the scroll size.
|
||||
*/
|
||||
protected _totalItems: number;
|
||||
/**
|
||||
* The total (estimated) length of all items in the scrolling direction.
|
||||
*/
|
||||
protected _scrollSize: number;
|
||||
/**
|
||||
* Number of pixels beyond the visible size of the container to still include
|
||||
* in the active range of items.
|
||||
*/
|
||||
protected _overhang: number;
|
||||
private _eventTarget;
|
||||
protected _spacingChanged: boolean;
|
||||
protected _defaultConfig: C;
|
||||
constructor(config?: C);
|
||||
set config(config: C);
|
||||
get config(): C;
|
||||
/**
|
||||
* Maximum index of children + 1, to help estimate total height of the scroll
|
||||
* space.
|
||||
*/
|
||||
get totalItems(): number;
|
||||
set totalItems(num: number);
|
||||
/**
|
||||
* Primary scrolling direction.
|
||||
*/
|
||||
get direction(): ScrollDirection;
|
||||
set direction(dir: ScrollDirection);
|
||||
/**
|
||||
* Estimate of the dimensions of a single child.
|
||||
*/
|
||||
get itemSize(): Size;
|
||||
set itemSize(dims: Size);
|
||||
/**
|
||||
* Amount of space in between items.
|
||||
*/
|
||||
get spacing(): number;
|
||||
set spacing(px: number);
|
||||
/**
|
||||
* Height and width of the viewport.
|
||||
*/
|
||||
get viewportSize(): Size;
|
||||
set viewportSize(dims: Size);
|
||||
/**
|
||||
* Scroll offset of the viewport.
|
||||
*/
|
||||
get viewportScroll(): Positions;
|
||||
set viewportScroll(coords: Positions);
|
||||
/**
|
||||
* Perform a reflow if one has been scheduled.
|
||||
*/
|
||||
reflowIfNeeded(force: boolean): void;
|
||||
/**
|
||||
* Scroll to the child at the given index, and the given position within that
|
||||
* child.
|
||||
*/
|
||||
scrollToIndex(index: number, position?: string): void;
|
||||
dispatchEvent(evt: Event): Promise<void>;
|
||||
addEventListener(
|
||||
type: string,
|
||||
listener: EventListener | EventListenerObject | null,
|
||||
options?: boolean | AddEventListenerOptions | undefined
|
||||
): Promise<void>;
|
||||
removeEventListener(
|
||||
type: string,
|
||||
callback: EventListener | EventListenerObject | null,
|
||||
options?: boolean | EventListenerOptions | undefined
|
||||
): Promise<void>;
|
||||
/**
|
||||
* Get the top and left positioning of the item at idx.
|
||||
*/
|
||||
abstract _getItemPosition(idx: number): Positions;
|
||||
/**
|
||||
* Update _first and _last based on items that should be in the current
|
||||
* range.
|
||||
*/
|
||||
abstract _getActiveItems(): void;
|
||||
protected _itemDim2Changed(): void;
|
||||
protected _viewDim2Changed(): void;
|
||||
protected _updateLayout(): void;
|
||||
protected _getItemSize(_idx: number): Size;
|
||||
/**
|
||||
* The size of an item in the scrolling direction + space between items.
|
||||
*/
|
||||
protected get _delta(): number;
|
||||
/**
|
||||
* The height or width of an item, whichever corresponds to the scrolling direction.
|
||||
*/
|
||||
protected get _itemDim1(): number;
|
||||
/**
|
||||
* The height or width of an item, whichever does NOT correspond to the scrolling direction.
|
||||
*/
|
||||
protected get _itemDim2(): number;
|
||||
/**
|
||||
* The height or width of the viewport, whichever corresponds to the scrolling direction.
|
||||
*/
|
||||
protected get _viewDim1(): number;
|
||||
/**
|
||||
* The height or width of the viewport, whichever does NOT correspond to the scrolling direction.
|
||||
*/
|
||||
protected get _viewDim2(): number;
|
||||
protected _scheduleReflow(): void;
|
||||
protected _scheduleLayoutUpdate(): void;
|
||||
protected _reflow(): void;
|
||||
/**
|
||||
* Estimates the total length of all items in the scrolling direction, including spacing.
|
||||
*/
|
||||
protected _updateScrollSize(): void;
|
||||
protected _scrollIfNeeded(): void;
|
||||
protected _emitRange(inProps?: unknown): void;
|
||||
protected _emitScrollSize(): void;
|
||||
protected _emitScrollError(): void;
|
||||
/**
|
||||
* Get or estimate the top and left positions of items in the current range.
|
||||
* Emit an itempositionchange event with these positions.
|
||||
*/
|
||||
protected _emitChildPositions(): void;
|
||||
/**
|
||||
* Number of items to display.
|
||||
*/
|
||||
private get _num();
|
||||
private _checkThresholds;
|
||||
/**
|
||||
* Find the indices of the first and last items to intersect the viewport.
|
||||
* Emit a visibleindiceschange event when either index changes.
|
||||
*/
|
||||
protected _updateVisibleIndices(options?: UpdateVisibleIndicesOptions): void;
|
||||
private _scrollPositionChanged;
|
||||
}
|
||||
export {};
|
||||
//# sourceMappingURL=Layout1dBase.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1dBase.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1dBase.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAE1F,aAAK,2BAA2B,GAAG;IACjC,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,8BAAsB,YAAY,CAAC,CAAC,SAAS,kBAAkB,CAAE,YAAW,MAAM;IAChF;;OAEG;IACH,OAAO,CAAC,aAAa,CAAgC;IAErD;;OAEG;IACH,OAAO,CAAC,UAAU,CAA+B;IAEjD;;OAEG;IACH,OAAO,CAAC,aAAa,CAA+B;IAEpD;;OAEG;IACH,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,oBAAoB,CAAS;IAErC;;;OAGG;IACH,SAAS,CAAC,cAAc,SAAM;IAE9B;;;OAGG;IACH,OAAO,CAAC,eAAe,CAAK;IAE5B;;OAEG;IACH,OAAO,CAAC,aAAa,CAAK;IAE1B;;OAEG;IACH,OAAO,CAAC,YAAY,CAAK;IAEzB,OAAO,CAAC,mBAAmB,CAEvB;IAEJ;;OAEG;IACH,SAAS,CAAC,YAAY,SAAK;IAE3B;;OAEG;IACH,SAAS,CAAC,YAAY,SAAK;IAE3B;;OAEG;IACH,SAAS,CAAC,MAAM,SAAM;IAEtB;;OAEG;IACH,SAAS,CAAC,KAAK,SAAM;IAErB;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,IAAI,CAA6B;IAEtD;;OAEG;IACH,SAAS,CAAC,QAAQ,SAAK;IAEvB;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAY;IAEzC;;OAEG;IACH,SAAS,CAAC,iBAAiB,EAAE,SAAS,CAAW;IAEjD;;OAEG;IACH,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAS;IAEzC;;OAEG;IACH,SAAS,CAAC,qBAAqB,EAAE,QAAQ,CAAU;IAEnD;;OAEG;IACH,SAAS,CAAC,eAAe,SAAK;IAE9B;;;OAGG;IACH,SAAS,CAAC,YAAY,SAAK;IAE3B;;;OAGG;IACH,SAAS,CAAC,WAAW,SAAK;IAE1B;;OAEG;IACH,SAAS,CAAC,WAAW,SAAK;IAE1B;;;OAGG;IAGH,SAAS,CAAC,SAAS,SAAQ;IAE3B,OAAO,CAAC,YAAY,CAA4B;IAChD,SAAS,CAAC,eAAe,UAAS;IAElC,SAAS,CAAC,cAAc,EAAE,CAAC,CAErB;gBAEM,MAAM,CAAC,EAAE,CAAC;IAItB,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,EAEnB;IAED,IAAI,MAAM,IAAI,CAAC,CAId;IAED;;;OAGG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,GAAG,EAHA,MAGA,EAMjB;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,eAAe,CAE/B;IACD,IAAI,SAAS,CAAC,GAAG,EAHA,eAGA,EAWhB;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,IAAI,CAEnB;IACD,IAAI,QAAQ,CAAC,IAAI,EAHD,IAGC,EAUhB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IACD,IAAI,OAAO,CAAC,EAAE,EAHC,MAGD,EAMb;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,IAAI,CAEvB;IACD,IAAI,YAAY,CAAC,IAAI,EAHD,IAGC,EAQpB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,SAAS,CAE9B;IACD,IAAI,cAAc,CAAC,MAAM,EAHH,SAGG,EASxB;IAED;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,OAAO;IAO7B;;;OAGG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAU;IAyBzC,aAAa,CAAC,GAAG,EAAE,KAAK;IAKxB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,mBAAmB,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAAG,SAAS;IAK5I,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,mBAAmB,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GAAG,SAAS;IAKlJ;;OAEG;IACH,QAAQ,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAEjD;;;OAGG;IACH,QAAQ,CAAC,eAAe,IAAI,IAAI;IAEhC,SAAS,CAAC,gBAAgB;IAI1B,SAAS,CAAC,gBAAgB;IAI1B,SAAS,CAAC,aAAa;IAIvB,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO1C;;OAEG;IACH,SAAS,KAAK,MAAM,IAAI,MAAM,CAE7B;IAED;;OAEG;IACH,SAAS,KAAK,SAAS,IAAI,MAAM,CAEhC;IAED;;OAEG;IACH,SAAS,KAAK,SAAS,IAAI,MAAM,CAEhC;IAED;;OAEG;IACH,SAAS,KAAK,SAAS,IAAI,MAAM,CAEhC;IAED;;OAEG;IACH,SAAS,KAAK,SAAS,IAAI,MAAM,CAEhC;IAED,SAAS,CAAC,eAAe;IAIzB,SAAS,CAAC,qBAAqB;IAK/B,SAAS,CAAC,OAAO;IA6BjB;;OAEG;IACH,SAAS,CAAC,iBAAiB;IAM3B,SAAS,CAAC,eAAe;IAmBzB,SAAS,CAAC,UAAU,CAAC,OAAO,GAAE,OAAmB;IAcjD,SAAS,CAAC,eAAe;IAOzB,SAAS,CAAC,gBAAgB;IAW1B;;;OAGG;IACH,SAAS,CAAC,mBAAmB;IAQ7B;;OAEG;IACH,OAAO,KAAK,IAAI,GAKf;IAED,OAAO,CAAC,gBAAgB;IAcxB;;;OAGG;IACF,SAAS,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,2BAA2B;IAiCtE,OAAO,CAAC,sBAAsB;CAQ/B"}
|
@ -0,0 +1,477 @@
|
||||
import EventTarget from "../polyfillLoaders/EventTarget.js";
|
||||
export class Layout1dBase {
|
||||
constructor(config) {
|
||||
/**
|
||||
* The last set viewport scroll position.
|
||||
*/
|
||||
this._latestCoords = { left: 0, top: 0 };
|
||||
/**
|
||||
* Scrolling direction.
|
||||
*/
|
||||
this._direction = "vertical";
|
||||
/**
|
||||
* Dimensions of the viewport.
|
||||
*/
|
||||
this._viewportSize = { width: 0, height: 0 };
|
||||
/**
|
||||
* Flag for debouncing asynchnronous reflow requests.
|
||||
*/
|
||||
this._pendingReflow = false;
|
||||
this._pendingLayoutUpdate = false;
|
||||
/**
|
||||
* Index of the item that has been scrolled to via the public API. When the
|
||||
* container is otherwise scrolled, this value is set back to -1.
|
||||
*/
|
||||
this._scrollToIndex = -1;
|
||||
/**
|
||||
* When a child is scrolled to, the offset from the top of the child and the
|
||||
* top of the viewport. Value is a proportion of the item size.
|
||||
*/
|
||||
this._scrollToAnchor = 0;
|
||||
/**
|
||||
* The index of the first item intersecting the viewport.
|
||||
*/
|
||||
this._firstVisible = 0;
|
||||
/**
|
||||
* The index of the last item intersecting the viewport.
|
||||
*/
|
||||
this._lastVisible = 0;
|
||||
this._eventTargetPromise = EventTarget().then((Ctor) => {
|
||||
this._eventTarget = new Ctor();
|
||||
});
|
||||
/**
|
||||
* Pixel offset in the scroll direction of the first child.
|
||||
*/
|
||||
this._physicalMin = 0;
|
||||
/**
|
||||
* Pixel offset in the scroll direction of the last child.
|
||||
*/
|
||||
this._physicalMax = 0;
|
||||
/**
|
||||
* Index of the first child.
|
||||
*/
|
||||
this._first = -1;
|
||||
/**
|
||||
* Index of the last child.
|
||||
*/
|
||||
this._last = -1;
|
||||
/**
|
||||
* The _estimated_ size of a child.
|
||||
*/
|
||||
this._itemSize = { width: 100, height: 100 };
|
||||
/**
|
||||
* Space in pixels between children.
|
||||
*/
|
||||
this._spacing = 0;
|
||||
/**
|
||||
* Length in the scrolling direction.
|
||||
*/
|
||||
this._sizeDim = "height";
|
||||
/**
|
||||
* Length in the non-scrolling direction.
|
||||
*/
|
||||
this._secondarySizeDim = "width";
|
||||
/**
|
||||
* Position in the scrolling direction.
|
||||
*/
|
||||
this._positionDim = "top";
|
||||
/**
|
||||
* Position in the non-scrolling direction.
|
||||
*/
|
||||
this._secondaryPositionDim = "left";
|
||||
/**
|
||||
* Current scroll offset in pixels.
|
||||
*/
|
||||
this._scrollPosition = 0;
|
||||
/**
|
||||
* Difference between current scroll offset and scroll offset calculated due
|
||||
* to a reflow.
|
||||
*/
|
||||
this._scrollError = 0;
|
||||
/**
|
||||
* Total number of items that could possibly be displayed. Used to help
|
||||
* calculate the scroll size.
|
||||
*/
|
||||
this._totalItems = 0;
|
||||
/**
|
||||
* The total (estimated) length of all items in the scrolling direction.
|
||||
*/
|
||||
this._scrollSize = 1;
|
||||
/**
|
||||
* Number of pixels beyond the visible size of the container to still include
|
||||
* in the active range of items.
|
||||
*/
|
||||
// TODO (graynorton): Probably want to make this something we calculate based
|
||||
// on viewport size, item size, other factors, possibly still with a dial of some kind
|
||||
this._overhang = 1000;
|
||||
this._eventTarget = null;
|
||||
this._spacingChanged = false;
|
||||
this._defaultConfig = {
|
||||
direction: "vertical",
|
||||
};
|
||||
this.config = config || this._defaultConfig;
|
||||
}
|
||||
set config(config) {
|
||||
Object.assign(this, Object.assign({}, this._defaultConfig, config));
|
||||
}
|
||||
get config() {
|
||||
return {
|
||||
direction: this.direction,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Maximum index of children + 1, to help estimate total height of the scroll
|
||||
* space.
|
||||
*/
|
||||
get totalItems() {
|
||||
return this._totalItems;
|
||||
}
|
||||
set totalItems(num) {
|
||||
const _num = Number(num);
|
||||
if (_num !== this._totalItems) {
|
||||
this._totalItems = _num;
|
||||
this._scheduleReflow();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Primary scrolling direction.
|
||||
*/
|
||||
get direction() {
|
||||
return this._direction;
|
||||
}
|
||||
set direction(dir) {
|
||||
// Force it to be either horizontal or vertical.
|
||||
dir = dir === "horizontal" ? dir : "vertical";
|
||||
if (dir !== this._direction) {
|
||||
this._direction = dir;
|
||||
this._sizeDim = dir === "horizontal" ? "width" : "height";
|
||||
this._secondarySizeDim = dir === "horizontal" ? "height" : "width";
|
||||
this._positionDim = dir === "horizontal" ? "left" : "top";
|
||||
this._secondaryPositionDim = dir === "horizontal" ? "top" : "left";
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Estimate of the dimensions of a single child.
|
||||
*/
|
||||
get itemSize() {
|
||||
return this._itemSize;
|
||||
}
|
||||
set itemSize(dims) {
|
||||
const { _itemDim1, _itemDim2 } = this;
|
||||
Object.assign(this._itemSize, dims);
|
||||
if (_itemDim1 !== this._itemDim1 || _itemDim2 !== this._itemDim2) {
|
||||
if (_itemDim2 !== this._itemDim2) {
|
||||
this._itemDim2Changed();
|
||||
} else {
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Amount of space in between items.
|
||||
*/
|
||||
get spacing() {
|
||||
return this._spacing;
|
||||
}
|
||||
set spacing(px) {
|
||||
const _px = Number(px);
|
||||
if (_px !== this._spacing) {
|
||||
this._spacing = _px;
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Height and width of the viewport.
|
||||
*/
|
||||
get viewportSize() {
|
||||
return this._viewportSize;
|
||||
}
|
||||
set viewportSize(dims) {
|
||||
const { _viewDim1, _viewDim2 } = this;
|
||||
Object.assign(this._viewportSize, dims);
|
||||
if (_viewDim2 !== this._viewDim2) {
|
||||
this._viewDim2Changed();
|
||||
} else if (_viewDim1 !== this._viewDim1) {
|
||||
this._checkThresholds();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Scroll offset of the viewport.
|
||||
*/
|
||||
get viewportScroll() {
|
||||
return this._latestCoords;
|
||||
}
|
||||
set viewportScroll(coords) {
|
||||
Object.assign(this._latestCoords, coords);
|
||||
const oldPos = this._scrollPosition;
|
||||
this._scrollPosition = this._latestCoords[this._positionDim];
|
||||
if (oldPos !== this._scrollPosition) {
|
||||
this._scrollPositionChanged(oldPos, this._scrollPosition);
|
||||
this._updateVisibleIndices({ emit: true });
|
||||
}
|
||||
this._checkThresholds();
|
||||
}
|
||||
/**
|
||||
* Perform a reflow if one has been scheduled.
|
||||
*/
|
||||
reflowIfNeeded(force) {
|
||||
if (force || this._pendingReflow) {
|
||||
this._pendingReflow = false;
|
||||
this._reflow();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Scroll to the child at the given index, and the given position within that
|
||||
* child.
|
||||
*/
|
||||
scrollToIndex(index, position = "start") {
|
||||
if (!Number.isFinite(index)) return;
|
||||
index = Math.min(this.totalItems, Math.max(0, index));
|
||||
this._scrollToIndex = index;
|
||||
if (position === "nearest") {
|
||||
position = index > this._first + this._num / 2 ? "end" : "start";
|
||||
}
|
||||
switch (position) {
|
||||
case "start":
|
||||
this._scrollToAnchor = 0;
|
||||
break;
|
||||
case "center":
|
||||
this._scrollToAnchor = 0.5;
|
||||
break;
|
||||
case "end":
|
||||
this._scrollToAnchor = 1;
|
||||
break;
|
||||
default:
|
||||
throw new TypeError(
|
||||
"position must be one of: start, center, end, nearest"
|
||||
);
|
||||
}
|
||||
this._scheduleReflow();
|
||||
}
|
||||
async dispatchEvent(evt) {
|
||||
await this._eventTargetPromise;
|
||||
this._eventTarget.dispatchEvent(evt);
|
||||
}
|
||||
async addEventListener(type, listener, options) {
|
||||
await this._eventTargetPromise;
|
||||
this._eventTarget.addEventListener(type, listener, options);
|
||||
}
|
||||
async removeEventListener(type, callback, options) {
|
||||
await this._eventTargetPromise;
|
||||
this._eventTarget.removeEventListener(type, callback, options);
|
||||
}
|
||||
_itemDim2Changed() {
|
||||
// Override
|
||||
}
|
||||
_viewDim2Changed() {
|
||||
// Override
|
||||
}
|
||||
_updateLayout() {
|
||||
// Override
|
||||
}
|
||||
_getItemSize(_idx) {
|
||||
return {
|
||||
[this._sizeDim]: this._itemDim1,
|
||||
[this._secondarySizeDim]: this._itemDim2,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* The size of an item in the scrolling direction + space between items.
|
||||
*/
|
||||
get _delta() {
|
||||
return this._itemDim1 + this._spacing;
|
||||
}
|
||||
/**
|
||||
* The height or width of an item, whichever corresponds to the scrolling direction.
|
||||
*/
|
||||
get _itemDim1() {
|
||||
return this._itemSize[this._sizeDim];
|
||||
}
|
||||
/**
|
||||
* The height or width of an item, whichever does NOT correspond to the scrolling direction.
|
||||
*/
|
||||
get _itemDim2() {
|
||||
return this._itemSize[this._secondarySizeDim];
|
||||
}
|
||||
/**
|
||||
* The height or width of the viewport, whichever corresponds to the scrolling direction.
|
||||
*/
|
||||
get _viewDim1() {
|
||||
return this._viewportSize[this._sizeDim];
|
||||
}
|
||||
/**
|
||||
* The height or width of the viewport, whichever does NOT correspond to the scrolling direction.
|
||||
*/
|
||||
get _viewDim2() {
|
||||
return this._viewportSize[this._secondarySizeDim];
|
||||
}
|
||||
_scheduleReflow() {
|
||||
this._pendingReflow = true;
|
||||
}
|
||||
_scheduleLayoutUpdate() {
|
||||
this._pendingLayoutUpdate = true;
|
||||
this._scheduleReflow();
|
||||
}
|
||||
_reflow() {
|
||||
const { _first, _last, _scrollSize } = this;
|
||||
if (this._pendingLayoutUpdate) {
|
||||
this._updateLayout();
|
||||
this._pendingLayoutUpdate = false;
|
||||
}
|
||||
this._updateScrollSize();
|
||||
this._getActiveItems();
|
||||
this._scrollIfNeeded();
|
||||
this._updateVisibleIndices();
|
||||
if (this._scrollSize !== _scrollSize) {
|
||||
this._emitScrollSize();
|
||||
}
|
||||
if (this._first === -1 && this._last === -1) {
|
||||
// TODO: have default empty object for emitRange instead
|
||||
this._emitRange();
|
||||
} else if (
|
||||
this._first !== _first ||
|
||||
this._last !== _last ||
|
||||
this._spacingChanged
|
||||
) {
|
||||
// TODO: have default empty object for emitRange instead
|
||||
this._emitRange();
|
||||
this._emitChildPositions();
|
||||
}
|
||||
this._emitScrollError();
|
||||
}
|
||||
/**
|
||||
* Estimates the total length of all items in the scrolling direction, including spacing.
|
||||
*/
|
||||
_updateScrollSize() {
|
||||
// Ensure we have at least 1px - this allows getting at least 1 item to be
|
||||
// rendered.
|
||||
this._scrollSize = Math.max(1, this._totalItems * this._delta);
|
||||
}
|
||||
_scrollIfNeeded() {
|
||||
if (this._scrollToIndex === -1) {
|
||||
return;
|
||||
}
|
||||
const index = this._scrollToIndex;
|
||||
const anchor = this._scrollToAnchor;
|
||||
const pos = this._getItemPosition(index)[this._positionDim];
|
||||
const size = this._getItemSize(index)[this._sizeDim];
|
||||
const curAnchorPos = this._scrollPosition + this._viewDim1 * anchor;
|
||||
const newAnchorPos = pos + size * anchor;
|
||||
// Ensure scroll position is an integer within scroll bounds.
|
||||
const scrollPosition = Math.floor(
|
||||
Math.min(
|
||||
this._scrollSize - this._viewDim1,
|
||||
Math.max(0, this._scrollPosition - curAnchorPos + newAnchorPos)
|
||||
)
|
||||
);
|
||||
this._scrollError += this._scrollPosition - scrollPosition;
|
||||
this._scrollPosition = scrollPosition;
|
||||
}
|
||||
_emitRange(inProps = undefined) {
|
||||
const detail = Object.assign(
|
||||
{
|
||||
first: this._first,
|
||||
last: this._last,
|
||||
num: this._num,
|
||||
stable: true,
|
||||
firstVisible: this._firstVisible,
|
||||
lastVisible: this._lastVisible,
|
||||
},
|
||||
inProps
|
||||
);
|
||||
this.dispatchEvent(new CustomEvent("rangechange", { detail }));
|
||||
}
|
||||
_emitScrollSize() {
|
||||
const detail = {
|
||||
[this._sizeDim]: this._scrollSize,
|
||||
};
|
||||
this.dispatchEvent(new CustomEvent("scrollsizechange", { detail }));
|
||||
}
|
||||
_emitScrollError() {
|
||||
if (this._scrollError) {
|
||||
const detail = {
|
||||
[this._positionDim]: this._scrollError,
|
||||
[this._secondaryPositionDim]: 0,
|
||||
};
|
||||
this.dispatchEvent(new CustomEvent("scrollerrorchange", { detail }));
|
||||
this._scrollError = 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get or estimate the top and left positions of items in the current range.
|
||||
* Emit an itempositionchange event with these positions.
|
||||
*/
|
||||
_emitChildPositions() {
|
||||
const detail = {};
|
||||
for (let idx = this._first; idx <= this._last; idx++) {
|
||||
detail[idx] = this._getItemPosition(idx);
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent("itempositionchange", { detail }));
|
||||
}
|
||||
/**
|
||||
* Number of items to display.
|
||||
*/
|
||||
get _num() {
|
||||
if (this._first === -1 || this._last === -1) {
|
||||
return 0;
|
||||
}
|
||||
return this._last - this._first + 1;
|
||||
}
|
||||
_checkThresholds() {
|
||||
if (this._viewDim1 === 0 && this._num > 0) {
|
||||
this._scheduleReflow();
|
||||
} else {
|
||||
const min = Math.max(0, this._scrollPosition - this._overhang);
|
||||
const max = Math.min(
|
||||
this._scrollSize,
|
||||
this._scrollPosition + this._viewDim1 + this._overhang
|
||||
);
|
||||
if (this._physicalMin > min || this._physicalMax < max) {
|
||||
this._scheduleReflow();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Find the indices of the first and last items to intersect the viewport.
|
||||
* Emit a visibleindiceschange event when either index changes.
|
||||
*/
|
||||
_updateVisibleIndices(options) {
|
||||
if (this._first === -1 || this._last === -1) return;
|
||||
let firstVisible = this._first;
|
||||
while (
|
||||
Math.round(
|
||||
this._getItemPosition(firstVisible)[this._positionDim] +
|
||||
this._getItemSize(firstVisible)[this._sizeDim]
|
||||
) <= Math.round(this._scrollPosition)
|
||||
) {
|
||||
firstVisible++;
|
||||
}
|
||||
let lastVisible = this._last;
|
||||
while (
|
||||
Math.round(this._getItemPosition(lastVisible)[this._positionDim]) >=
|
||||
Math.round(this._scrollPosition + this._viewDim1)
|
||||
) {
|
||||
lastVisible--;
|
||||
}
|
||||
if (
|
||||
firstVisible !== this._firstVisible ||
|
||||
lastVisible !== this._lastVisible
|
||||
) {
|
||||
this._firstVisible = firstVisible;
|
||||
this._lastVisible = lastVisible;
|
||||
if (options && options.emit) {
|
||||
this._emitRange();
|
||||
}
|
||||
}
|
||||
}
|
||||
_scrollPositionChanged(oldPos, newPos) {
|
||||
// When both values are bigger than the max scroll position, keep the
|
||||
// current _scrollToIndex, otherwise invalidate it.
|
||||
const maxPos = this._scrollSize - this._viewDim1;
|
||||
if (oldPos < maxPos || newPos < maxPos) {
|
||||
this._scrollToIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Layout1dBase.js.map
|
File diff suppressed because one or more lines are too long
65
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dFlex.d.ts
vendored
Normal file
65
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dFlex.d.ts
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
import { Layout1dBase, Layout1dBaseConfig } from "./Layout1dBase";
|
||||
import { ItemBox, Positions, Size } from "./Layout";
|
||||
interface Layout1dFlexConfig extends Layout1dBaseConfig {
|
||||
spacing?: number;
|
||||
idealSize?: number;
|
||||
}
|
||||
declare type Layout1dFlexSpecifier = Layout1dFlexConfig & {
|
||||
type: new (config?: Layout1dFlexConfig) => Layout1dFlex;
|
||||
};
|
||||
declare type Layout1dFlexSpecifierFactory = (
|
||||
config?: Layout1dFlexConfig
|
||||
) => Layout1dFlexSpecifier;
|
||||
export declare const layout1dFlex: Layout1dFlexSpecifierFactory;
|
||||
interface Rolumn {
|
||||
_startIdx: number;
|
||||
_endIdx: number;
|
||||
_startPos: number;
|
||||
_size: number;
|
||||
}
|
||||
interface Chunk {
|
||||
_itemPositions: Array<Positions>;
|
||||
_rolumns: Array<Rolumn>;
|
||||
_size: number;
|
||||
_dirty: boolean;
|
||||
}
|
||||
/**
|
||||
* TODO @straversi: document and test this Layout.
|
||||
*/
|
||||
export declare class Layout1dFlex extends Layout1dBase<Layout1dFlexConfig> {
|
||||
private _itemSizes;
|
||||
private _chunkSize;
|
||||
private _chunks;
|
||||
private _aspectRatios;
|
||||
private _numberOfAspectRatiosMeasured;
|
||||
protected _idealSize: number | null;
|
||||
protected _config: Layout1dFlexConfig;
|
||||
protected _defaultConfig: Layout1dFlexConfig;
|
||||
listenForChildLoadEvents: boolean;
|
||||
/**
|
||||
* TODO graynorton@ Don't hard-code Flickr - probably need a config option
|
||||
*/
|
||||
measureChildren: (e: Element, i: unknown) => ItemBox;
|
||||
set idealSize(px: number | null);
|
||||
get idealSize(): number | null;
|
||||
updateItemSizes(sizes: { [key: number]: ItemBox }): void;
|
||||
_newChunk(): {
|
||||
_rolumns: never[];
|
||||
_itemPositions: never[];
|
||||
_size: number;
|
||||
_dirty: boolean;
|
||||
};
|
||||
_getChunk(idx: number | string): Chunk;
|
||||
_recordAspectRatio(dims: ItemBox): void;
|
||||
_getRandomAspectRatio(): Size;
|
||||
_viewDim2Changed(): void;
|
||||
_getActiveItems(): void;
|
||||
_getItemPosition(idx: number): Positions;
|
||||
_getItemSize(idx: number): Size;
|
||||
_getNaturalItemDims(idx: number): Size;
|
||||
_layOutChunk(startIdx: number): Chunk;
|
||||
_updateLayout(): void;
|
||||
_updateScrollSize(): void;
|
||||
}
|
||||
export {};
|
||||
//# sourceMappingURL=Layout1dFlex.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1dFlex.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1dFlex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAC,MAAM,UAAU,CAAC;AAElD,UAAU,kBAAmB,SAAQ,kBAAkB;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,aAAK,qBAAqB,GAAG,kBAAkB,GAAG;IAChD,IAAI,EAAE,KAAI,MAAM,CAAC,EAAE,kBAAkB,KAAK,YAAY,CAAA;CACvD,CAAA;AAED,aAAK,4BAA4B,GAAG,CAAC,MAAM,CAAC,EAAE,kBAAkB,KAAK,qBAAqB,CAAC;AAE3F,eAAO,MAAM,YAAY,EAAE,4BAEjB,CAAC;AAEX,UAAU,MAAM;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,KAAK;IACb,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAeD;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAY,CAAC,kBAAkB,CAAC;IAChE,OAAO,CAAC,UAAU,CAAmB;IAIrC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,6BAA6B,CAAa;IAClD,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3C,SAAS,CAAC,OAAO,EAAE,kBAAkB,CAAM;IAC3C,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAGzC;IAEH,wBAAwB,UAAQ;IAElC;;OAEG;IACD,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAUvD;IAED,IAAI,SAAS,CAAC,EAAE,eAAA,EAMf;IAED,IAAI,SAAS,kBAEZ;IAED,eAAe,CAAC,KAAK,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAC;IAqB/C,SAAS;;;;;;IAST,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAI9B,kBAAkB,CAAC,IAAI,EAAE,OAAO;IAahC,qBAAqB,IAAI,IAAI;IAa7B,gBAAgB;IAIhB,eAAe;IA2Bf,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAKxC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAM/B,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAStC,YAAY,CAAC,QAAQ,EAAE,MAAM;IA+D7B,aAAa,IAAI,IAAI;IAYrB,iBAAiB;CAOlB"}
|
@ -0,0 +1,264 @@
|
||||
import { Layout1dBase } from "./Layout1dBase";
|
||||
export const layout1dFlex = (config) =>
|
||||
Object.assign(
|
||||
{
|
||||
type: Layout1dFlex,
|
||||
},
|
||||
config
|
||||
);
|
||||
/**
|
||||
* TODO @straversi: document and test this Layout.
|
||||
*/
|
||||
export class Layout1dFlex extends Layout1dBase {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this._itemSizes = [];
|
||||
// private _itemPositions: Array<Positions> = [];
|
||||
// private _rolumnStartIdx: Array<number> = [];
|
||||
// private _rolumnStartPos: Array<number> = [];
|
||||
this._chunkSize = null;
|
||||
this._chunks = [];
|
||||
this._aspectRatios = {};
|
||||
this._numberOfAspectRatiosMeasured = 0;
|
||||
this._idealSize = null;
|
||||
this._config = {};
|
||||
this._defaultConfig = Object.assign({}, super._defaultConfig, {
|
||||
spacing: 0,
|
||||
idealSize: 200,
|
||||
});
|
||||
this.listenForChildLoadEvents = true;
|
||||
/**
|
||||
* TODO graynorton@ Don't hard-code Flickr - probably need a config option
|
||||
*/
|
||||
this.measureChildren = function (e, i) {
|
||||
const { naturalWidth, naturalHeight } = e;
|
||||
if (naturalWidth !== undefined && naturalHeight != undefined) {
|
||||
return { width: naturalWidth, height: naturalHeight };
|
||||
}
|
||||
const { o_width, o_height } = i;
|
||||
if (o_width !== undefined && o_height !== undefined) {
|
||||
return { width: o_width, height: o_height };
|
||||
}
|
||||
return { width: -1, height: -1 };
|
||||
};
|
||||
}
|
||||
set idealSize(px) {
|
||||
const _px = Number(px);
|
||||
if (_px !== this._idealSize) {
|
||||
this._idealSize = _px;
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
}
|
||||
get idealSize() {
|
||||
return this._idealSize;
|
||||
}
|
||||
updateItemSizes(sizes) {
|
||||
let dirty;
|
||||
Object.keys(sizes).forEach((key) => {
|
||||
const n = Number(key);
|
||||
const chunk = this._getChunk(n);
|
||||
const dims = sizes[n];
|
||||
const prevDims = this._itemSizes[n];
|
||||
if (dims.width && dims.height) {
|
||||
if (
|
||||
!prevDims ||
|
||||
prevDims.width !== dims.width ||
|
||||
prevDims.height !== dims.height
|
||||
) {
|
||||
chunk._dirty = true;
|
||||
dirty = true;
|
||||
this._itemSizes[n] = sizes[n];
|
||||
this._recordAspectRatio(sizes[n]);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (dirty) {
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
}
|
||||
_newChunk() {
|
||||
return {
|
||||
["_rolumns"]: [],
|
||||
_itemPositions: [],
|
||||
_size: 0,
|
||||
_dirty: false,
|
||||
};
|
||||
}
|
||||
_getChunk(idx) {
|
||||
return (
|
||||
this._chunks[Math.floor(Number(idx) / this._chunkSize)] ||
|
||||
this._newChunk()
|
||||
);
|
||||
}
|
||||
_recordAspectRatio(dims) {
|
||||
if (dims.width && dims.height) {
|
||||
const bucket = Math.round((dims.width / dims.height) * 10) / 10;
|
||||
if (this._aspectRatios[bucket]) {
|
||||
this._aspectRatios[bucket]++;
|
||||
} else {
|
||||
this._aspectRatios[bucket] = 1;
|
||||
}
|
||||
this._numberOfAspectRatiosMeasured++;
|
||||
}
|
||||
}
|
||||
_getRandomAspectRatio() {
|
||||
if (this._numberOfAspectRatiosMeasured === 0) {
|
||||
return { width: 1, height: 1 };
|
||||
}
|
||||
const n = Math.random() * this._numberOfAspectRatiosMeasured;
|
||||
const buckets = Object.keys(this._aspectRatios);
|
||||
let i = -1,
|
||||
m = 0;
|
||||
while (m < n && i < buckets.length) {
|
||||
m += this._aspectRatios[buckets[++i]];
|
||||
}
|
||||
return { width: Number(buckets[i]), height: 1 };
|
||||
}
|
||||
_viewDim2Changed() {
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
_getActiveItems() {
|
||||
const chunk = this._getChunk(0);
|
||||
if (chunk._rolumns.length === 0) return;
|
||||
const scrollPos = Math.max(
|
||||
0,
|
||||
Math.min(this._scrollPosition, this._scrollSize - this._viewDim1)
|
||||
);
|
||||
const min = Math.max(0, scrollPos - this._overhang);
|
||||
const max = Math.min(
|
||||
this._scrollSize,
|
||||
scrollPos + this._viewDim1 + this._overhang
|
||||
);
|
||||
const mid = (min + max) / 2;
|
||||
const estMidRolumn = Math.round(
|
||||
(mid / this._scrollSize) * chunk._rolumns.length
|
||||
);
|
||||
let idx = estMidRolumn;
|
||||
while (chunk._rolumns[idx]._startPos < min) {
|
||||
idx++;
|
||||
}
|
||||
while (chunk._rolumns[idx]._startPos > min) {
|
||||
idx--;
|
||||
}
|
||||
this._first = chunk._rolumns[idx]._startIdx;
|
||||
this._physicalMin = chunk._rolumns[idx]._startPos;
|
||||
let rolumnMax;
|
||||
while (
|
||||
(rolumnMax =
|
||||
chunk._rolumns[idx]._startPos +
|
||||
chunk._rolumns[idx]._size +
|
||||
this._spacing * 2) < max
|
||||
) {
|
||||
idx++;
|
||||
}
|
||||
this._last = chunk._rolumns[idx]._endIdx;
|
||||
this._physicalMax = rolumnMax;
|
||||
}
|
||||
_getItemPosition(idx) {
|
||||
const chunk = this._getChunk(0);
|
||||
return chunk._itemPositions[idx];
|
||||
}
|
||||
_getItemSize(idx) {
|
||||
const chunk = this._getChunk(0);
|
||||
const { width, height } = chunk._itemPositions[idx];
|
||||
return { width, height };
|
||||
}
|
||||
_getNaturalItemDims(idx) {
|
||||
let itemDims = this._itemSizes[idx];
|
||||
if (
|
||||
itemDims === undefined ||
|
||||
itemDims.width === -1 ||
|
||||
itemDims.height === -1
|
||||
) {
|
||||
itemDims = this._getRandomAspectRatio();
|
||||
}
|
||||
return itemDims;
|
||||
}
|
||||
_layOutChunk(startIdx) {
|
||||
const chunk = this._newChunk();
|
||||
let startPos = this._spacing;
|
||||
let idx = 0;
|
||||
let rolumnSize2 = 0;
|
||||
let lastRatio = Infinity;
|
||||
const finishRolumn = (lastIdx) => {
|
||||
const rolumn = {
|
||||
_startIdx: startIdx,
|
||||
_endIdx: lastIdx,
|
||||
_startPos: startPos - this._spacing,
|
||||
_size: 0,
|
||||
};
|
||||
chunk._rolumns.push(rolumn);
|
||||
let itemStartPos = this._spacing;
|
||||
for (let i = startIdx; i <= lastIdx; i++) {
|
||||
const pos = chunk._itemPositions[i];
|
||||
pos.width = pos.width * lastRatio;
|
||||
pos.height = pos.height * lastRatio;
|
||||
pos.left = this._positionDim === "left" ? startPos : itemStartPos;
|
||||
pos.top = this._positionDim === "top" ? startPos : itemStartPos;
|
||||
itemStartPos += pos[this._secondarySizeDim] + this._spacing;
|
||||
}
|
||||
rolumn._size = chunk._itemPositions[lastIdx][this._sizeDim];
|
||||
};
|
||||
while (idx < this._chunkSize) {
|
||||
const itemDims = this._getNaturalItemDims(idx);
|
||||
const availableSpace =
|
||||
this._viewDim2 - this._spacing * (idx - startIdx + 2);
|
||||
const itemSize = itemDims[this._sizeDim];
|
||||
const itemSize2 = itemDims[this._secondarySizeDim];
|
||||
const idealScaleFactor = this._idealSize / itemSize;
|
||||
const adjItemSize = idealScaleFactor * itemSize;
|
||||
const adjItemSize2 = idealScaleFactor * itemSize2;
|
||||
chunk._itemPositions[idx] = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: this._sizeDim === "width" ? adjItemSize : adjItemSize2,
|
||||
height: this._sizeDim === "height" ? adjItemSize : adjItemSize2,
|
||||
};
|
||||
const ratio = availableSpace / (rolumnSize2 + adjItemSize2);
|
||||
if (Math.abs(1 - ratio) > Math.abs(1 - lastRatio)) {
|
||||
// rolumn is better without adding this item
|
||||
finishRolumn(idx - 1);
|
||||
startIdx = idx;
|
||||
startPos += this._idealSize * lastRatio + this._spacing;
|
||||
lastRatio = (this._viewDim2 - 2 * this._spacing) / adjItemSize2;
|
||||
rolumnSize2 = adjItemSize2;
|
||||
} else {
|
||||
// add this item and continue
|
||||
rolumnSize2 += adjItemSize2;
|
||||
lastRatio = ratio;
|
||||
}
|
||||
if (idx === this._chunkSize - 1) {
|
||||
finishRolumn(idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
const lastRolumn = chunk._rolumns[chunk._rolumns.length - 1];
|
||||
chunk._size = lastRolumn._startPos + lastRolumn._size;
|
||||
return chunk;
|
||||
}
|
||||
_updateLayout() {
|
||||
if (/*this._rolumnStartIdx === undefined ||*/ this._viewDim2 === 0) return;
|
||||
this._chunkSize = Math.ceil(
|
||||
(2 * (this._viewDim1 * this._viewDim2)) /
|
||||
(this._idealSize * this._idealSize)
|
||||
);
|
||||
console.log("chunkSize", this._chunkSize);
|
||||
// TODO: An odd place to do this, need to think through the logistics of getting size info to the layout
|
||||
// in all cases
|
||||
// this._itemSizes.length = 100;//this._totalItems;
|
||||
this._chunks[0] = this._layOutChunk(0);
|
||||
// TODO (graynorton): This is a hack to force reflow
|
||||
this._spacingChanged = true;
|
||||
}
|
||||
_updateScrollSize() {
|
||||
const chunk = this._chunks[0];
|
||||
this._scrollSize =
|
||||
!chunk || chunk._rolumns.length === 0
|
||||
? 1
|
||||
: chunk._size + 2 * this._spacing;
|
||||
// chunk._rolumns[chunk._rolumns.length - 1]._startPos +
|
||||
// chunk._itemPositions[chunk._rolumns.length - 1][this._sizeDim] +
|
||||
// (this._spacing * 2);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Layout1dFlex.js.map
|
File diff suppressed because one or more lines are too long
20
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dGrid.d.ts
vendored
Normal file
20
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dGrid.d.ts
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
import { Layout1dBase } from "./Layout1dBase.js";
|
||||
/**
|
||||
* TODO @straversi: document and test this Layout.
|
||||
*/
|
||||
export declare abstract class Layout1dGrid<
|
||||
Config
|
||||
> extends Layout1dBase<Config> {
|
||||
protected _rolumns: number;
|
||||
_viewDim2Changed(): void;
|
||||
_itemDim2Changed(): void;
|
||||
_getActiveItems(): void;
|
||||
_getItemPosition(
|
||||
idx: number
|
||||
): {
|
||||
top: number;
|
||||
left: number;
|
||||
};
|
||||
_updateScrollSize(): void;
|
||||
}
|
||||
//# sourceMappingURL=Layout1dGrid.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1dGrid.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1dGrid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAE/C;;GAEG;AACH,8BAAsB,YAAY,CAAC,MAAM,CAAE,SAAQ,YAAY,CAAC,MAAM,CAAC;IACrE,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAK;IAO/B,gBAAgB;IAIhB,gBAAgB;IAIhB,eAAe;IAef,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC;IAQ1D,iBAAiB;CAIlB"}
|
@ -0,0 +1,52 @@
|
||||
import { Layout1dBase } from "./Layout1dBase.js";
|
||||
/**
|
||||
* TODO @straversi: document and test this Layout.
|
||||
*/
|
||||
export class Layout1dGrid extends Layout1dBase {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this._rolumns = 1;
|
||||
}
|
||||
// constructor(config) {
|
||||
// super(config);
|
||||
// this._rolumns = 1;
|
||||
// }
|
||||
_viewDim2Changed() {
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
_itemDim2Changed() {
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
_getActiveItems() {
|
||||
const min = Math.max(0, this._scrollPosition - this._overhang);
|
||||
const max = Math.min(
|
||||
this._scrollSize,
|
||||
this._scrollPosition + this._viewDim1 + this._overhang
|
||||
);
|
||||
const firstCow = Math.floor(min / this._delta);
|
||||
const lastCow = Math.ceil(max / this._delta) - 1;
|
||||
this._first = firstCow * this._rolumns;
|
||||
this._last = Math.min(
|
||||
(lastCow + 1) * this._rolumns - 1,
|
||||
this._totalItems - 1
|
||||
);
|
||||
this._physicalMin = this._delta * firstCow;
|
||||
this._physicalMax = this._delta * (lastCow + 1);
|
||||
}
|
||||
_getItemPosition(idx) {
|
||||
return {
|
||||
[this._positionDim]:
|
||||
this._spacing + Math.floor(idx / this._rolumns) * this._delta,
|
||||
[this._secondaryPositionDim]:
|
||||
this._spacing +
|
||||
(idx % this._rolumns) * (this._spacing + this._itemDim2),
|
||||
};
|
||||
}
|
||||
_updateScrollSize() {
|
||||
this._scrollSize = Math.max(
|
||||
1,
|
||||
Math.ceil(this._totalItems / this._rolumns) * this._delta + this._spacing
|
||||
);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Layout1dGrid.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1dGrid.js","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1dGrid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAE/C;;GAEG;AACH,MAAM,OAAgB,YAAqB,SAAQ,YAAoB;IAAvE;;QACY,aAAQ,GAAW,CAAC,CAAC;IA0CjC,CAAC;IAxCC,wBAAwB;IACxB,mBAAmB;IACnB,uBAAuB;IACvB,IAAI;IAEJ,gBAAgB;QACd,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC/B,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC/B,CAAC;IAED,eAAe;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAChB,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QACvC,IAAI,CAAC,KAAK;YACN,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;QAC3C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,gBAAgB,CAAC,GAAW;QAC1B,OAAO;YACL,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM;YAC9E,CAAC,IAAI,CAAC,qBAAqB,CAAC,EAAE,IAAI,CAAC,QAAQ;gBAC3C,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;SACrB,CAAC;IAC9C,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,WAAW;YACZ,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7F,CAAC;CACF","sourcesContent":["import {Layout1dBase} from './Layout1dBase.js';\n\n/**\n * TODO @straversi: document and test this Layout.\n */\nexport abstract class Layout1dGrid<Config> extends Layout1dBase<Config> {\n protected _rolumns: number = 1;\n\n // constructor(config) {\n // super(config);\n // this._rolumns = 1;\n // }\n\n _viewDim2Changed() {\n this._scheduleLayoutUpdate();\n }\n\n _itemDim2Changed() {\n this._scheduleLayoutUpdate();\n }\n\n _getActiveItems() {\n const min = Math.max(0, this._scrollPosition - this._overhang);\n const max = Math.min(\n this._scrollSize,\n this._scrollPosition + this._viewDim1 + this._overhang);\n const firstCow = Math.floor(min / this._delta);\n const lastCow = Math.ceil(max / this._delta) - 1;\n\n this._first = firstCow * this._rolumns;\n this._last =\n Math.min(((lastCow + 1) * this._rolumns) - 1, this._totalItems - 1);\n this._physicalMin = this._delta * firstCow;\n this._physicalMax = this._delta * (lastCow + 1);\n }\n\n _getItemPosition(idx: number): {top: number, left: number} {\n return {\n [this._positionDim]: this._spacing + Math.floor(idx / this._rolumns) * this._delta,\n [this._secondaryPositionDim]: this._spacing +\n ((idx % this._rolumns) * (this._spacing + this._itemDim2))\n } as unknown as {top: number, left: number};\n }\n\n _updateScrollSize() {\n this._scrollSize =\n Math.max(1, Math.ceil(this._totalItems / this._rolumns) * this._delta + this._spacing);\n }\n}\n"]}
|
8
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dNaturalSizeGrid.d.ts
vendored
Normal file
8
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dNaturalSizeGrid.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import { Layout1dGrid } from "./Layout1dGrid.js";
|
||||
import { Layout1dBaseConfig } from "./Layout1dBase.js";
|
||||
import { ItemBox } from "./Layout";
|
||||
export declare class Layout1dNaturalSizeGrid extends Layout1dGrid<Layout1dBaseConfig> {
|
||||
updateItemSizes(sizes: { [key: number]: ItemBox }): void;
|
||||
_updateLayout(): void;
|
||||
}
|
||||
//# sourceMappingURL=Layout1dNaturalSizeGrid.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1dNaturalSizeGrid.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1dNaturalSizeGrid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAC,OAAO,EAAC,MAAM,UAAU,CAAC;AAEjC,qBAAa,uBAAwB,SAAQ,YAAY,CAAC,kBAAkB,CAAC;IACzE,eAAe,CAAC,KAAK,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAC;IAQ7C,aAAa;CAYlB"}
|
@ -0,0 +1,23 @@
|
||||
import { Layout1dGrid } from "./Layout1dGrid.js";
|
||||
export class Layout1dNaturalSizeGrid extends Layout1dGrid {
|
||||
updateItemSizes(sizes) {
|
||||
// Assume all items have the same size.
|
||||
const size = Object.values(sizes)[0];
|
||||
if (size) {
|
||||
this.itemSize = size;
|
||||
}
|
||||
}
|
||||
_updateLayout() {
|
||||
const { _spacing } = this;
|
||||
this._rolumns = Math.max(1, Math.floor(this._viewDim2 / this._itemDim2));
|
||||
if (this._rolumns > 1) {
|
||||
this._spacing =
|
||||
(this._viewDim2 % (this._rolumns * this._itemDim2)) /
|
||||
(this._rolumns + 1);
|
||||
} else {
|
||||
this._spacing = 0;
|
||||
}
|
||||
this._spacingChanged = !(_spacing === this._spacing);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Layout1dNaturalSizeGrid.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1dNaturalSizeGrid.js","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1dNaturalSizeGrid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAI/C,MAAM,OAAO,uBAAwB,SAAQ,YAAgC;IACzE,eAAe,CAAC,KAA+B;QAC3C,uCAAuC;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;SACtB;IACH,CAAC;IAED,aAAa;QACX,MAAM,EAAC,QAAQ,EAAC,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QACzE,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE;YACrB,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC/D,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;SACzB;aACI;YACH,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;SACnB;QACD,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvD,CAAC;CACN","sourcesContent":["import {Layout1dGrid} from './Layout1dGrid.js';\nimport {Layout1dBaseConfig} from './Layout1dBase.js';\nimport {ItemBox} from './Layout';\n\nexport class Layout1dNaturalSizeGrid extends Layout1dGrid<Layout1dBaseConfig> {\n updateItemSizes(sizes: {[key: number]: ItemBox}) {\n // Assume all items have the same size.\n const size = Object.values(sizes)[0];\n if (size) {\n this.itemSize = size;\n }\n }\n \n _updateLayout() {\n const {_spacing} = this;\n this._rolumns = Math.max(1, Math.floor(this._viewDim2 / this._itemDim2));\n if (this._rolumns > 1) {\n this._spacing = (this._viewDim2 % (this._rolumns * this._itemDim2)) /\n (this._rolumns + 1);\n }\n else {\n this._spacing = 0;\n }\n this._spacingChanged = !(_spacing === this._spacing);\n } \n}"]}
|
22
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dSquareGrid.d.ts
vendored
Normal file
22
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/layouts/Layout1dSquareGrid.d.ts
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
import { Layout1dBaseConfig } from "./Layout1dBase.js";
|
||||
import { Layout1dGrid } from "./Layout1dGrid.js";
|
||||
import { Positions } from "./Layout.js";
|
||||
interface Layout1dSquareGridConfig extends Layout1dBaseConfig {
|
||||
spacing?: number;
|
||||
idealSize?: number;
|
||||
}
|
||||
declare type Layout1dSquareGridSpecifier = Layout1dSquareGridConfig & {
|
||||
type: new (config?: Layout1dSquareGridConfig) => Layout1dSquareGrid;
|
||||
};
|
||||
declare type Layout1dSquareGridSpecifierFactory = (
|
||||
config?: Layout1dSquareGridConfig
|
||||
) => Layout1dSquareGridSpecifier;
|
||||
export declare const layout1dSquareGrid: Layout1dSquareGridSpecifierFactory;
|
||||
export declare class Layout1dSquareGrid extends Layout1dGrid<Layout1dSquareGridConfig> {
|
||||
protected _idealSize: number;
|
||||
set idealSize(px: number);
|
||||
_getItemPosition(idx: number): Positions;
|
||||
_updateLayout(): void;
|
||||
}
|
||||
export {};
|
||||
//# sourceMappingURL=Layout1dSquareGrid.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1dSquareGrid.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1dSquareGrid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtC,UAAU,wBAAyB,SAAQ,kBAAkB;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,aAAK,2BAA2B,GAAG,wBAAwB,GAAG;IAC5D,IAAI,EAAE,KAAI,MAAM,CAAC,EAAE,wBAAwB,KAAK,kBAAkB,CAAA;CACnE,CAAA;AAED,aAAK,kCAAkC,GAAG,CAAC,MAAM,CAAC,EAAE,wBAAwB,KAAK,2BAA2B,CAAC;AAE7G,eAAO,MAAM,kBAAkB,EAAE,kCAEvB,CAAC;AAEX,qBAAa,kBAAmB,SAAQ,YAAY,CAAC,wBAAwB,CAAC;IAC5E,SAAS,CAAC,UAAU,EAAE,MAAM,CAAO;IASnC,IAAI,SAAS,CAAC,EAAE,EAAE,MAAM,EAKvB;IAED,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAIxC,aAAa;CASd"}
|
@ -0,0 +1,41 @@
|
||||
import { Layout1dGrid } from "./Layout1dGrid.js";
|
||||
export const layout1dSquareGrid = (config) =>
|
||||
Object.assign(
|
||||
{
|
||||
type: Layout1dSquareGrid,
|
||||
},
|
||||
config
|
||||
);
|
||||
export class Layout1dSquareGrid extends Layout1dGrid {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this._idealSize = 200;
|
||||
}
|
||||
// constructor(config) {
|
||||
// super(config);
|
||||
// if (config.idealSize === undefined) {
|
||||
// this._idealSize = 200;
|
||||
// }
|
||||
// }
|
||||
set idealSize(px) {
|
||||
if (px !== this._idealSize) {
|
||||
this._idealSize = px;
|
||||
this._scheduleLayoutUpdate();
|
||||
}
|
||||
}
|
||||
_getItemPosition(idx) {
|
||||
return Object.assign(super._getItemPosition(idx), this._itemSize);
|
||||
}
|
||||
_updateLayout() {
|
||||
const frolumns = this._viewDim2 / this._idealSize;
|
||||
this._rolumns =
|
||||
frolumns % 1 < 0.5 ? Math.floor(frolumns) : Math.ceil(frolumns);
|
||||
const adjSize =
|
||||
(this._viewDim2 - (this._rolumns + 1) * this._spacing) / this._rolumns;
|
||||
if (adjSize !== this._itemSize.width) {
|
||||
this._itemSize = { width: adjSize, height: adjSize };
|
||||
this._spacingChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Layout1dSquareGrid.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Layout1dSquareGrid.js","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/layouts/Layout1dSquareGrid.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAc/C,MAAM,CAAC,MAAM,kBAAkB,GAAuC,CAAC,MAAiC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;IACzH,IAAI,EAAE,kBAAkB;CACzB,EAAE,MAAM,CAAC,CAAC;AAEX,MAAM,OAAO,kBAAmB,SAAQ,YAAsC;IAA9E;;QACY,eAAU,GAAW,GAAG,CAAC;IA6BrC,CAAC;IA3BC,wBAAwB;IACxB,mBAAmB;IACnB,0CAA0C;IAC1C,+BAA+B;IAC/B,MAAM;IACN,IAAI;IAEJ,IAAI,SAAS,CAAC,EAAU;QACtB,IAAI,EAAE,KAAK,IAAI,CAAC,UAAU,EAAE;YAC1B,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,qBAAqB,EAAE,CAAC;SAC9B;IACH,CAAC;IAED,gBAAgB,CAAC,GAAW;QAC1B,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACpE,CAAC;IAED,aAAa;QACX,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;QAClD,IAAI,CAAC,QAAQ,GAAG,QAAQ,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChF,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;QACzF,IAAI,OAAO,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE;YACpC,IAAI,CAAC,SAAS,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YACrD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;SAC7B;IACH,CAAC;CACF","sourcesContent":["import {Layout1dBaseConfig} from './Layout1dBase.js';\nimport {Layout1dGrid} from './Layout1dGrid.js';\nimport {Positions} from './Layout.js';\n\ninterface Layout1dSquareGridConfig extends Layout1dBaseConfig {\n spacing?: number,\n idealSize?: number\n}\n\ntype Layout1dSquareGridSpecifier = Layout1dSquareGridConfig & {\n type: new(config?: Layout1dSquareGridConfig) => Layout1dSquareGrid\n}\n\ntype Layout1dSquareGridSpecifierFactory = (config?: Layout1dSquareGridConfig) => Layout1dSquareGridSpecifier;\n\nexport const layout1dSquareGrid: Layout1dSquareGridSpecifierFactory = (config?: Layout1dSquareGridConfig) => Object.assign({\n type: Layout1dSquareGrid\n}, config);\n\nexport class Layout1dSquareGrid extends Layout1dGrid<Layout1dSquareGridConfig> {\n protected _idealSize: number = 200;\n\n // constructor(config) {\n // super(config);\n // if (config.idealSize === undefined) {\n // this._idealSize = 200;\n // }\n // }\n\n set idealSize(px: number) {\n if (px !== this._idealSize) {\n this._idealSize = px;\n this._scheduleLayoutUpdate();\n }\n }\n\n _getItemPosition(idx: number): Positions {\n return Object.assign(super._getItemPosition(idx), this._itemSize);\n }\n\n _updateLayout() {\n const frolumns = this._viewDim2 / this._idealSize;\n this._rolumns = frolumns % 1 < 0.5 ? Math.floor(frolumns) : Math.ceil(frolumns);\n const adjSize = (this._viewDim2 - ((this._rolumns + 1) * this._spacing)) / this._rolumns;\n if (adjSize !== this._itemSize.width) {\n this._itemSize = { width: adjSize, height: adjSize };\n this._spacingChanged = true;\n }\n } \n}"]}
|
6
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.d.ts
vendored
Normal file
6
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
interface EventTargetConstructor {
|
||||
new (): EventTarget;
|
||||
}
|
||||
export default function EventTarget(): Promise<EventTargetConstructor>;
|
||||
export {};
|
||||
//# sourceMappingURL=EventTarget.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"EventTarget.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.ts"],"names":[],"mappings":"AAEA,UAAU,sBAAsB;IAC5B,QAAO,WAAW,CAAA;CACrB;AAKD,wBAA8B,WAAW,oCAExC"}
|
@ -0,0 +1,15 @@
|
||||
let _ET;
|
||||
let ET;
|
||||
export default async function EventTarget() {
|
||||
return ET || init();
|
||||
}
|
||||
async function init() {
|
||||
_ET = window.EventTarget;
|
||||
try {
|
||||
new _ET();
|
||||
} catch (_a) {
|
||||
_ET = (await import("event-target-shim")).EventTarget;
|
||||
}
|
||||
return (ET = _ET);
|
||||
}
|
||||
//# sourceMappingURL=EventTarget.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"EventTarget.js","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.ts"],"names":[],"mappings":"AAMA,IAAI,GAA+C,CAAC;AACpD,IAAI,EAA0B,CAAC;AAE/B,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW;IACrC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,IAAI;IACf,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC;IACzB,IAAI;QACA,IAAI,GAAG,EAAE,CAAC;KACb;IACD,WAAM;QACF,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,WAAW,CAAC;KACzD;IACD,OAAO,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC;AACtB,CAAC","sourcesContent":["type EventTargetModule = typeof import('event-target-shim');\n\ninterface EventTargetConstructor {\n new(): EventTarget\n}\n\nlet _ET: EventTargetModule | EventTargetConstructor;\nlet ET: EventTargetConstructor;\n\nexport default async function EventTarget() {\n return ET || init();\n}\n\nasync function init() {\n _ET = window.EventTarget;\n try {\n new _ET();\n }\n catch {\n _ET = (await import('event-target-shim')).EventTarget;\n }\n return (ET = _ET);\n}"]}
|
3
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/ResizeObserver.d.ts
vendored
Normal file
3
src/resources/lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/ResizeObserver.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { ResizeObserverConstructor } from "../polyfills/resize-observer-polyfill/ResizeObserver.js";
|
||||
export default function ResizeObserver(): Promise<ResizeObserverConstructor>;
|
||||
//# sourceMappingURL=ResizeObserver.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"ResizeObserver.d.ts","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/polyfillLoaders/ResizeObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,yDAAyD,CAAC;AAMpG,wBAA8B,cAAc,uCAE3C"}
|
@ -0,0 +1,20 @@
|
||||
let _RO;
|
||||
let RO;
|
||||
export default async function ResizeObserver() {
|
||||
return RO || init();
|
||||
}
|
||||
async function init() {
|
||||
if (_RO) {
|
||||
return (await _RO).default;
|
||||
} else {
|
||||
_RO = window.ResizeObserver;
|
||||
try {
|
||||
new _RO(function () {});
|
||||
} catch (e) {
|
||||
_RO = import("../polyfills/resize-observer-polyfill/ResizeObserver.js");
|
||||
_RO = (await _RO).default;
|
||||
}
|
||||
return (RO = _RO);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=ResizeObserver.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"ResizeObserver.js","sourceRoot":"","sources":["../../../../src/lib/uni-virtualizer/lib/polyfillLoaders/ResizeObserver.ts"],"names":[],"mappings":"AAGA,IAAI,GAAqD,CAAC;AAC1D,IAAI,EAA6B,CAAC;AAElC,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,cAAc;IACxC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,IAAI;IACf,IAAI,GAAG,EAAE;QACL,OAAO,CAAC,MAAM,GAA4B,CAAA,CAAC,OAAO,CAAC;KACtD;SACI;QACD,GAAG,GAAG,MAAM,CAAC,cAAc,CAAC;QAC5B,IAAI;YACA,IAAI,GAAG,CAAC,cAAY,CAAC,CAAC,CAAC;SAC1B;QACD,OAAO,CAAC,EAAE;YACN,GAAG,GAAG,MAAM,CAAC,yDAAyD,CAAoC,CAAC;YAC3G,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC;SAC7B;QACD,OAAO,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC;KACrB;AACL,CAAC","sourcesContent":["import { ResizeObserverConstructor } from '../polyfills/resize-observer-polyfill/ResizeObserver.js';\ntype ResizeObserverModule = typeof import('../polyfills/resize-observer-polyfill/ResizeObserver.js');\n\nlet _RO: ResizeObserverModule | ResizeObserverConstructor;\nlet RO: ResizeObserverConstructor;\n\nexport default async function ResizeObserver() {\n return RO || init();\n}\n\nasync function init() {\n if (_RO) {\n return (await _RO as ResizeObserverModule).default;\n }\n else {\n _RO = window.ResizeObserver;\n try {\n new _RO(function() {});\n }\n catch (e) {\n _RO = import('../polyfills/resize-observer-polyfill/ResizeObserver.js') as unknown as ResizeObserverModule;\n _RO = (await _RO).default;\n }\n return (RO = _RO); \n }\n}"]}
|
@ -0,0 +1,960 @@
|
||||
/**
|
||||
* Detects whether window and document objects are available in current environment.
|
||||
*/
|
||||
var isBrowser =
|
||||
typeof window !== "undefined" &&
|
||||
typeof document !== "undefined" &&
|
||||
window.document === document;
|
||||
|
||||
// Returns global object of a current environment.
|
||||
var global$1 = (function () {
|
||||
if (typeof global !== "undefined" && global.Math === Math) {
|
||||
return global;
|
||||
}
|
||||
if (typeof self !== "undefined" && self.Math === Math) {
|
||||
return self;
|
||||
}
|
||||
if (typeof window !== "undefined" && window.Math === Math) {
|
||||
return window;
|
||||
}
|
||||
// eslint-disable-next-line no-new-func
|
||||
return Function("return this")();
|
||||
})();
|
||||
|
||||
/**
|
||||
* A shim for the requestAnimationFrame which falls back to the setTimeout if
|
||||
* first one is not supported.
|
||||
*
|
||||
* @returns {number} Requests' identifier.
|
||||
*/
|
||||
var requestAnimationFrame$1 = (function () {
|
||||
if (typeof requestAnimationFrame === "function") {
|
||||
// It's required to use a bounded function because IE sometimes throws
|
||||
// an "Invalid calling object" error if rAF is invoked without the global
|
||||
// object on the left hand side.
|
||||
return requestAnimationFrame.bind(global$1);
|
||||
}
|
||||
var result = function (callback) {
|
||||
return setTimeout(function () {
|
||||
callback(+Date.now());
|
||||
}, 1000 / 60);
|
||||
};
|
||||
return result;
|
||||
})();
|
||||
|
||||
// Defines minimum timeout before adding a trailing call.
|
||||
var trailingTimeout = 2;
|
||||
/**
|
||||
* Creates a wrapper function which ensures that provided callback will be
|
||||
* invoked only once during the specified delay period.
|
||||
*
|
||||
* @param callback - Function to be invoked after the delay period.
|
||||
* @param delay - Delay after which to invoke callback.
|
||||
*/
|
||||
function throttle(callback, delay) {
|
||||
var leadingCall = false,
|
||||
trailingCall = false,
|
||||
lastCallTime = 0;
|
||||
/**
|
||||
* Invokes the original callback function and schedules new invocation if
|
||||
* the "proxy" was called during current request.
|
||||
*/
|
||||
function resolvePending() {
|
||||
if (leadingCall) {
|
||||
leadingCall = false;
|
||||
callback();
|
||||
}
|
||||
if (trailingCall) {
|
||||
proxy();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Callback invoked after the specified delay. It will further postpone
|
||||
* invocation of the original function delegating it to the
|
||||
* requestAnimationFrame.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
function timeoutCallback() {
|
||||
requestAnimationFrame$1(resolvePending);
|
||||
}
|
||||
/**
|
||||
* Schedules invocation of the original function.
|
||||
*/
|
||||
function proxy() {
|
||||
var timeStamp = Date.now();
|
||||
if (leadingCall) {
|
||||
// Reject immediately following calls.
|
||||
if (timeStamp - lastCallTime < trailingTimeout) {
|
||||
return;
|
||||
}
|
||||
// Schedule new call to be in invoked when the pending one is resolved.
|
||||
// This is important for "transitions" which never actually start
|
||||
// immediately so there is a chance that we might miss one if change
|
||||
// happens amids the pending invocation.
|
||||
trailingCall = true;
|
||||
} else {
|
||||
leadingCall = true;
|
||||
trailingCall = false;
|
||||
setTimeout(timeoutCallback, delay);
|
||||
}
|
||||
lastCallTime = timeStamp;
|
||||
}
|
||||
return proxy;
|
||||
}
|
||||
|
||||
// Minimum delay before invoking the update of observers.
|
||||
var REFRESH_DELAY = 20;
|
||||
// A list of substrings of CSS properties used to find transition events that
|
||||
// might affect dimensions of observed elements.
|
||||
var transitionKeys = [
|
||||
"top",
|
||||
"right",
|
||||
"bottom",
|
||||
"left",
|
||||
"width",
|
||||
"height",
|
||||
"size",
|
||||
"weight",
|
||||
];
|
||||
// Check if MutationObserver is available.
|
||||
var mutationObserverSupported = typeof MutationObserver !== "undefined";
|
||||
// Get the native implementation of HTMLElement.attachShadow
|
||||
var origAttachShadow =
|
||||
isBrowser &&
|
||||
HTMLElement.prototype.attachShadow &&
|
||||
HTMLElement.prototype.attachShadow.toString().indexOf("[native code]") !== -1
|
||||
? HTMLElement.prototype.attachShadow
|
||||
: null;
|
||||
/**
|
||||
* Singleton controller class which handles updates of ResizeObserver instances.
|
||||
*/
|
||||
var ResizeObserverController = /** @class */ (function () {
|
||||
/**
|
||||
* Creates a new instance of ResizeObserverController.
|
||||
*/
|
||||
function ResizeObserverController() {
|
||||
/**
|
||||
* Indicates whether DOM listeners have been added.
|
||||
*/
|
||||
this.connected_ = false;
|
||||
/**
|
||||
* Tells that controller has subscribed for Mutation Events.
|
||||
*/
|
||||
this.mutationEventsAdded_ = false;
|
||||
/**
|
||||
* Keeps reference to the instance of MutationObserver.
|
||||
*/
|
||||
this.mutationsObserver_ = null;
|
||||
/**
|
||||
* A list of connected observers.
|
||||
*/
|
||||
this.observers_ = [];
|
||||
this.onTransitionEnd_ = this.onTransitionEnd_.bind(this);
|
||||
this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY);
|
||||
}
|
||||
/**
|
||||
* Adds observer to observers list.
|
||||
*
|
||||
* @param observer Observer to be added.
|
||||
*/
|
||||
ResizeObserverController.prototype.addObserver = function (observer) {
|
||||
if (!~this.observers_.indexOf(observer)) {
|
||||
this.observers_.push(observer);
|
||||
}
|
||||
// Add listeners if they haven't been added yet.
|
||||
if (!this.connected_) {
|
||||
this.connect_();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Removes observer from observers list.
|
||||
*
|
||||
* @param observer Observer to be removed.
|
||||
*/
|
||||
ResizeObserverController.prototype.removeObserver = function (observer) {
|
||||
var observers = this.observers_;
|
||||
var index = observers.indexOf(observer);
|
||||
// Remove observer if it's present in registry.
|
||||
if (~index) {
|
||||
observers.splice(index, 1);
|
||||
}
|
||||
// Remove listeners if controller has no connected observers.
|
||||
if (!observers.length && this.connected_) {
|
||||
this.disconnect_();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Invokes the update of observers. It will continue running updates insofar
|
||||
* it detects changes.
|
||||
*/
|
||||
ResizeObserverController.prototype.refresh = function () {
|
||||
var changesDetected = this.updateObservers_();
|
||||
// Continue running updates if changes have been detected as there might
|
||||
// be future ones caused by CSS transitions.
|
||||
if (changesDetected) {
|
||||
this.refresh();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Updates every observer from observers list and notifies them of queued
|
||||
* entries.
|
||||
*
|
||||
* @returns Returns "true" if any observer has detected changes in
|
||||
* dimensions of it's elements.
|
||||
*/
|
||||
ResizeObserverController.prototype.updateObservers_ = function () {
|
||||
// Collect observers that have active observations.
|
||||
var activeObservers = this.observers_.filter(function (observer) {
|
||||
return observer.gatherActive(), observer.hasActive();
|
||||
});
|
||||
// Deliver notifications in a separate cycle in order to avoid any
|
||||
// collisions between observers, e.g. when multiple instances of
|
||||
// ResizeObserver are tracking the same element and the callback of one
|
||||
// of them changes content dimensions of the observed target. Sometimes
|
||||
// this may result in notifications being blocked for the rest of observers.
|
||||
activeObservers.forEach(function (observer) {
|
||||
return observer.broadcastActive();
|
||||
});
|
||||
return activeObservers.length > 0;
|
||||
};
|
||||
/**
|
||||
* Initializes DOM listeners.
|
||||
*/
|
||||
ResizeObserverController.prototype.connect_ = function () {
|
||||
// Do nothing if running in a non-browser environment or if listeners
|
||||
// have been already added.
|
||||
if (!isBrowser || this.connected_) {
|
||||
return;
|
||||
}
|
||||
// Subscription to the "Transitionend" event is used as a workaround for
|
||||
// delayed transitions. This way it's possible to capture at least the
|
||||
// final state of an element.
|
||||
document.addEventListener("transitionend", this.onTransitionEnd_);
|
||||
window.addEventListener("resize", this.refresh);
|
||||
if (mutationObserverSupported) {
|
||||
this.mutationsObserver_ = new MutationObserver(this.refresh);
|
||||
var options_1 = {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true,
|
||||
};
|
||||
this.mutationsObserver_.observe(document, options_1);
|
||||
if (origAttachShadow) {
|
||||
var controller_1 = this;
|
||||
(function observeExistingShadowRoots(node) {
|
||||
var shadowRoot = node.shadowRoot;
|
||||
if (shadowRoot) {
|
||||
controller_1.mutationsObserver_.observe(shadowRoot, options_1);
|
||||
observeExistingShadowRoots(shadowRoot);
|
||||
}
|
||||
var child = node.firstElementChild;
|
||||
while (child) {
|
||||
observeExistingShadowRoots(child);
|
||||
child = child.nextElementSibling;
|
||||
}
|
||||
})(document);
|
||||
HTMLElement.prototype.attachShadow = function () {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
var shadowRoot = origAttachShadow.apply(this, args);
|
||||
controller_1.mutationsObserver_.observe(shadowRoot, options_1);
|
||||
return shadowRoot;
|
||||
};
|
||||
}
|
||||
} else {
|
||||
document.addEventListener("DOMSubtreeModified", this.refresh);
|
||||
this.mutationEventsAdded_ = true;
|
||||
}
|
||||
this.connected_ = true;
|
||||
};
|
||||
/**
|
||||
* Removes DOM listeners.
|
||||
*/
|
||||
ResizeObserverController.prototype.disconnect_ = function () {
|
||||
// Do nothing if running in a non-browser environment or if listeners
|
||||
// have been already removed.
|
||||
if (!isBrowser || !this.connected_) {
|
||||
return;
|
||||
}
|
||||
document.removeEventListener("transitionend", this.onTransitionEnd_);
|
||||
window.removeEventListener("resize", this.refresh);
|
||||
if (this.mutationsObserver_) {
|
||||
this.mutationsObserver_.disconnect();
|
||||
if (origAttachShadow) {
|
||||
HTMLElement.prototype.attachShadow = origAttachShadow;
|
||||
}
|
||||
}
|
||||
if (this.mutationEventsAdded_) {
|
||||
document.removeEventListener("DOMSubtreeModified", this.refresh);
|
||||
}
|
||||
this.mutationsObserver_ = null;
|
||||
this.mutationEventsAdded_ = false;
|
||||
this.connected_ = false;
|
||||
};
|
||||
/**
|
||||
* "Transitionend" event handler.
|
||||
*/
|
||||
ResizeObserverController.prototype.onTransitionEnd_ = function (_a) {
|
||||
var _b = _a.propertyName,
|
||||
propertyName = _b === void 0 ? "" : _b;
|
||||
// Detect whether transition may affect dimensions of an element.
|
||||
var isReflowProperty = transitionKeys.some(function (key) {
|
||||
return !!~propertyName.indexOf(key);
|
||||
});
|
||||
if (isReflowProperty) {
|
||||
this.refresh();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Returns instance of the ResizeObserverController.
|
||||
*/
|
||||
ResizeObserverController.getInstance = function () {
|
||||
if (!ResizeObserverController.instance_) {
|
||||
ResizeObserverController.instance_ = new ResizeObserverController();
|
||||
}
|
||||
return ResizeObserverController.instance_;
|
||||
};
|
||||
/**
|
||||
* Holds reference to the controller's instance.
|
||||
*/
|
||||
ResizeObserverController.instance_ = null;
|
||||
return ResizeObserverController;
|
||||
})();
|
||||
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
function __values(o) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator],
|
||||
i = 0;
|
||||
if (m) return m.call(o);
|
||||
return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines non-writable/enumerable properties of the provided target object.
|
||||
*
|
||||
* @param target Object for which to define properties.
|
||||
* @param props Properties to be defined.
|
||||
* @returns Target object.
|
||||
*/
|
||||
var defineConfigurable = function (target, props) {
|
||||
var e_1, _a;
|
||||
try {
|
||||
for (
|
||||
var _b = __values(Object.keys(props)), _c = _b.next();
|
||||
!_c.done;
|
||||
_c = _b.next()
|
||||
) {
|
||||
var key = _c.value;
|
||||
Object.defineProperty(target, key, {
|
||||
value: props[key],
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
} catch (e_1_1) {
|
||||
e_1 = { error: e_1_1 };
|
||||
} finally {
|
||||
try {
|
||||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
||||
} finally {
|
||||
if (e_1) throw e_1.error;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the global object associated with provided element.
|
||||
*
|
||||
* @param {EventT} target
|
||||
* @returns {Object}
|
||||
*/
|
||||
var getWindowOf = function (target) {
|
||||
var _a;
|
||||
// Assume that the element is an instance of Node, which means that it
|
||||
// has the "ownerDocument" property from which we can retrieve a
|
||||
// corresponding global object.
|
||||
// Return the local global object if it's not possible extract one from
|
||||
// provided element.
|
||||
return (
|
||||
((_a =
|
||||
target === null || target === void 0 ? void 0 : target.ownerDocument) ===
|
||||
null || _a === void 0
|
||||
? void 0
|
||||
: _a.defaultView) || global$1
|
||||
);
|
||||
};
|
||||
|
||||
// Placeholder of an empty content rectangle.
|
||||
var emptyRect = createRectInit(0, 0, 0, 0);
|
||||
/**
|
||||
* Converts provided string to a number.
|
||||
*/
|
||||
function toFloat(value) {
|
||||
if (typeof value === "number") {
|
||||
return value;
|
||||
}
|
||||
return parseFloat(value) || 0;
|
||||
}
|
||||
/**
|
||||
* Extracts borders size from provided styles.
|
||||
*/
|
||||
function getBordersSize(styles) {
|
||||
var positions = [];
|
||||
for (var _i = 1; _i < arguments.length; _i++) {
|
||||
positions[_i - 1] = arguments[_i];
|
||||
}
|
||||
return positions.reduce(function (size, position) {
|
||||
var value = styles["border-" + position + "-width"];
|
||||
return size + toFloat(value);
|
||||
}, 0);
|
||||
}
|
||||
/**
|
||||
* Extracts paddings sizes from provided styles.
|
||||
*/
|
||||
function getPaddings(styles) {
|
||||
var st = styles;
|
||||
return {
|
||||
top: toFloat(st["padding-top"]),
|
||||
right: toFloat(st["padding-right"]),
|
||||
bottom: toFloat(st["padding-bottom"]),
|
||||
left: toFloat(st["padding-left"]),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Calculates content rectangle of provided SVG element.
|
||||
*
|
||||
* @param target Element content rectangle of which needs to be calculated.
|
||||
*/
|
||||
function getSVGContentRect(target) {
|
||||
var bbox = target.getBBox();
|
||||
return createRectInit(0, 0, bbox.width, bbox.height);
|
||||
}
|
||||
/**
|
||||
* Calculates content rectangle of provided HTMLElement.
|
||||
*
|
||||
* @param target Element for which to calculate the content rectangle.
|
||||
*/
|
||||
function getHTMLElementContentRect(target) {
|
||||
// Client width & height properties can't be
|
||||
// used exclusively as they provide rounded values.
|
||||
var clientWidth = target.clientWidth,
|
||||
clientHeight = target.clientHeight;
|
||||
// By this condition we can catch all non-replaced inline, hidden and
|
||||
// detached elements. Though elements with width & height properties less
|
||||
// than 0.5 will be discarded as well.
|
||||
//
|
||||
// Without it we would need to implement separate methods for each of
|
||||
// those cases and it's not possible to perform a precise and performance
|
||||
// effective test for hidden elements. E.g. even jQuery's ':visible' filter
|
||||
// gives wrong results for elements with width & height less than 0.5.
|
||||
if (!clientWidth && !clientHeight) {
|
||||
return emptyRect;
|
||||
}
|
||||
var styles = getWindowOf(target).getComputedStyle(target);
|
||||
var paddings = getPaddings(styles);
|
||||
var horizPad = paddings.left + paddings.right;
|
||||
var vertPad = paddings.top + paddings.bottom;
|
||||
// Computed styles of width & height are being used because they are the
|
||||
// only dimensions available to JS that contain non-rounded values. It could
|
||||
// be possible to utilize the getBoundingClientRect if only it's data wasn't
|
||||
// affected by CSS transformations let alone paddings, borders and scroll
|
||||
// bars.
|
||||
var width = toFloat(styles.width),
|
||||
height = toFloat(styles.height);
|
||||
// Width & height include paddings and borders when the 'border-box' box
|
||||
// model is applied (except for IE).
|
||||
if (styles.boxSizing === "border-box") {
|
||||
// Following conditions are required to handle Internet Explorer which
|
||||
// doesn't include paddings and borders to computed CSS dimensions.
|
||||
//
|
||||
// We can say that if CSS dimensions + paddings are equal to the "client"
|
||||
// properties then it's either IE, and thus we don't need to subtract
|
||||
// anything, or an element merely doesn't have paddings/borders styles.
|
||||
if (Math.round(width + horizPad) !== clientWidth) {
|
||||
width -= getBordersSize(styles, "left", "right") + horizPad;
|
||||
}
|
||||
if (Math.round(height + vertPad) !== clientHeight) {
|
||||
height -= getBordersSize(styles, "top", "bottom") + vertPad;
|
||||
}
|
||||
}
|
||||
// Following steps can't be applied to the document's root element as its
|
||||
// client[Width/Height] properties represent viewport area of the window.
|
||||
// Besides, it's as well not necessary as the <html> itself neither has
|
||||
// rendered scroll bars nor it can be clipped.
|
||||
if (!isDocumentElement(target)) {
|
||||
// In some browsers (only in Firefox, actually) CSS width & height
|
||||
// include scroll bars size which can be removed at this step as scroll
|
||||
// bars are the only difference between rounded dimensions + paddings
|
||||
// and "client" properties, though that is not always true in Chrome.
|
||||
var vertScrollbar = Math.round(width + horizPad) - clientWidth;
|
||||
var horizScrollbar = Math.round(height + vertPad) - clientHeight;
|
||||
// Chrome has a rather weird rounding of "client" properties.
|
||||
// E.g. for an element with content width of 314.2px it sometimes gives
|
||||
// the client width of 315px and for the width of 314.7px it may give
|
||||
// 314px. And it doesn't happen all the time. So just ignore this delta
|
||||
// as a non-relevant.
|
||||
if (Math.abs(vertScrollbar) !== 1) {
|
||||
width -= vertScrollbar;
|
||||
}
|
||||
if (Math.abs(horizScrollbar) !== 1) {
|
||||
height -= horizScrollbar;
|
||||
}
|
||||
}
|
||||
return createRectInit(paddings.left, paddings.top, width, height);
|
||||
}
|
||||
/**
|
||||
* Checks whether provided element is an instance of the SVGGraphicsElement.
|
||||
*
|
||||
* @param target Element to be checked.
|
||||
*/
|
||||
var isSVGGraphicsElement = (function () {
|
||||
// Some browsers, namely IE and Edge, don't have the SVGGraphicsElement
|
||||
// interface.
|
||||
if (typeof SVGGraphicsElement !== "undefined") {
|
||||
return function (target) {
|
||||
return target instanceof getWindowOf(target).SVGGraphicsElement;
|
||||
};
|
||||
}
|
||||
// If it's so, then check that element is at least an instance of the
|
||||
// SVGElement and that it has the "getBBox" method.
|
||||
// eslint-disable-next-line no-extra-parens
|
||||
return function (target) {
|
||||
return (
|
||||
target instanceof getWindowOf(target).SVGElement &&
|
||||
typeof target.getBBox === "function"
|
||||
);
|
||||
};
|
||||
})();
|
||||
/**
|
||||
* Checks whether provided element is a document element (<html>).
|
||||
*
|
||||
* @param target Element to be checked.
|
||||
*/
|
||||
function isDocumentElement(target) {
|
||||
return target === getWindowOf(target).document.documentElement;
|
||||
}
|
||||
/**
|
||||
* Calculates an appropriate content rectangle for provided html or svg element.
|
||||
*
|
||||
* @param target Element content rectangle of which needs to be calculated.
|
||||
*/
|
||||
function getContentRect(target) {
|
||||
if (!isBrowser) {
|
||||
return emptyRect;
|
||||
}
|
||||
if (isSVGGraphicsElement(target)) {
|
||||
return getSVGContentRect(target);
|
||||
}
|
||||
return getHTMLElementContentRect(target);
|
||||
}
|
||||
/**
|
||||
* Creates rectangle with an interface of the DOMRectReadOnly.
|
||||
* Spec: https://drafts.fxtf.org/geometry/#domrectreadonly
|
||||
*
|
||||
* @param rectInit Object with rectangle's x/y coordinates and
|
||||
* dimensions.
|
||||
*/
|
||||
function createReadOnlyRect(_a) {
|
||||
var x = _a.x,
|
||||
y = _a.y,
|
||||
width = _a.width,
|
||||
height = _a.height;
|
||||
// If DOMRectReadOnly is available use it as a prototype for the rectangle.
|
||||
var Constr =
|
||||
typeof DOMRectReadOnly !== "undefined" ? DOMRectReadOnly : Object;
|
||||
var rect = Object.create(Constr.prototype);
|
||||
// Rectangle's properties are not writable and non-enumerable.
|
||||
defineConfigurable(rect, {
|
||||
x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
height: height,
|
||||
top: y,
|
||||
right: x + width,
|
||||
bottom: height + y,
|
||||
left: x,
|
||||
});
|
||||
return rect;
|
||||
}
|
||||
/**
|
||||
* Creates DOMRectInit object based on the provided dimensions and the x/y
|
||||
* coordinates. Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit
|
||||
*
|
||||
* @param x X coordinate.
|
||||
* @param y Y coordinate.
|
||||
* @param width Rectangle's width.
|
||||
* @param height Rectangle's height.
|
||||
*/
|
||||
function createRectInit(x, y, width, height) {
|
||||
return { x: x, y: y, width: width, height: height };
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that is responsible for computations of the content rectangle of
|
||||
* provided DOM element and for keeping track of it's changes.
|
||||
*/
|
||||
var ResizeObservation = /** @class */ (function () {
|
||||
/**
|
||||
* Creates an instance of ResizeObservation.
|
||||
*
|
||||
* @param target Element to be observed.
|
||||
*/
|
||||
function ResizeObservation(target) {
|
||||
/**
|
||||
* Broadcasted width of content rectangle.
|
||||
*/
|
||||
this.broadcastWidth = 0;
|
||||
/**
|
||||
* Broadcasted height of content rectangle.
|
||||
*/
|
||||
this.broadcastHeight = 0;
|
||||
/**
|
||||
* Reference to the last observed content rectangle.
|
||||
*/
|
||||
this.contentRect_ = createRectInit(0, 0, 0, 0);
|
||||
this.target = target;
|
||||
}
|
||||
/**
|
||||
* Updates content rectangle and tells whether it's width or height properties
|
||||
* have changed since the last broadcast.
|
||||
*/
|
||||
ResizeObservation.prototype.isActive = function () {
|
||||
var rect = getContentRect(this.target);
|
||||
this.contentRect_ = rect;
|
||||
return (
|
||||
rect.width !== this.broadcastWidth || rect.height !== this.broadcastHeight
|
||||
);
|
||||
};
|
||||
/**
|
||||
* Updates 'broadcastWidth' and 'broadcastHeight' properties with a data
|
||||
* from the corresponding properties of the last observed content rectangle.
|
||||
*
|
||||
* @returns Last observed content rectangle.
|
||||
*/
|
||||
ResizeObservation.prototype.broadcastRect = function () {
|
||||
var rect = this.contentRect_;
|
||||
this.broadcastWidth = rect.width;
|
||||
this.broadcastHeight = rect.height;
|
||||
return rect;
|
||||
};
|
||||
return ResizeObservation;
|
||||
})();
|
||||
|
||||
var ResizeObserverEntry = /** @class */ (function () {
|
||||
/**
|
||||
* Creates an instance of ResizeObserverEntry.
|
||||
*
|
||||
* @param target Element that is being observed.
|
||||
* @param rectInit Data of the element's content rectangle.
|
||||
*/
|
||||
function ResizeObserverEntry(target, rectInit) {
|
||||
var contentRect = createReadOnlyRect(rectInit);
|
||||
// According to the specification following properties are not writable
|
||||
// and are also not enumerable in the native implementation.
|
||||
//
|
||||
// Property accessors are not being used as they'd require to define a
|
||||
// private WeakMap storage which may cause memory leaks in browsers that
|
||||
// don't support this type of collections.
|
||||
defineConfigurable(this, { target: target, contentRect: contentRect });
|
||||
}
|
||||
return ResizeObserverEntry;
|
||||
})();
|
||||
|
||||
/**
|
||||
* A collection of shims that provide minimal functionality of the ES6
|
||||
* collections.
|
||||
*
|
||||
* These implementations are not meant to be used outside of the ResizeObserver
|
||||
* modules as they cover only a limited range of use cases.
|
||||
*/
|
||||
/* eslint-disable require-jsdoc, valid-jsdoc */
|
||||
var MapShim = (function () {
|
||||
if (typeof Map !== "undefined") {
|
||||
return Map;
|
||||
}
|
||||
/**
|
||||
* Returns index in provided array that matches the specified key.
|
||||
*/
|
||||
function getIndex(arr, key) {
|
||||
var result = -1;
|
||||
arr.some(function (entry, index) {
|
||||
if (entry[0] === key) {
|
||||
result = index;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
return /** @class */ (function () {
|
||||
function class_1() {
|
||||
this.__entries__ = [];
|
||||
}
|
||||
Object.defineProperty(class_1.prototype, "size", {
|
||||
get: function () {
|
||||
return this.__entries__.length;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
});
|
||||
class_1.prototype.get = function (key) {
|
||||
var _a;
|
||||
var index = getIndex(this.__entries__, key);
|
||||
return (_a = this.__entries__[index]) === null || _a === void 0
|
||||
? void 0
|
||||
: _a[1];
|
||||
};
|
||||
class_1.prototype.set = function (key, value) {
|
||||
var index = getIndex(this.__entries__, key);
|
||||
if (~index) {
|
||||
this.__entries__[index][1] = value;
|
||||
} else {
|
||||
this.__entries__.push([key, value]);
|
||||
}
|
||||
};
|
||||
class_1.prototype.delete = function (key) {
|
||||
var entries = this.__entries__;
|
||||
var index = getIndex(entries, key);
|
||||
if (~index) {
|
||||
entries.splice(index, 1);
|
||||
}
|
||||
};
|
||||
class_1.prototype.has = function (key) {
|
||||
return !!~getIndex(this.__entries__, key);
|
||||
};
|
||||
class_1.prototype.clear = function () {
|
||||
this.__entries__.splice(0);
|
||||
};
|
||||
class_1.prototype.forEach = function (callback, ctx) {
|
||||
var e_1, _a;
|
||||
if (ctx === void 0) {
|
||||
ctx = null;
|
||||
}
|
||||
try {
|
||||
for (
|
||||
var _b = __values(this.__entries__), _c = _b.next();
|
||||
!_c.done;
|
||||
_c = _b.next()
|
||||
) {
|
||||
var entry = _c.value;
|
||||
callback.call(ctx, entry[1], entry[0]);
|
||||
}
|
||||
} catch (e_1_1) {
|
||||
e_1 = { error: e_1_1 };
|
||||
} finally {
|
||||
try {
|
||||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
||||
} finally {
|
||||
if (e_1) throw e_1.error;
|
||||
}
|
||||
}
|
||||
};
|
||||
return class_1;
|
||||
})();
|
||||
})();
|
||||
|
||||
var ResizeObserverSPI = /** @class */ (function () {
|
||||
/**
|
||||
* Creates a new instance of ResizeObserver.
|
||||
*
|
||||
* @param callback Callback function that is invoked when one of the observed
|
||||
* elements changes it's content dimensions.
|
||||
* @param controller Controller instance which is responsible for the updates
|
||||
* of observer.
|
||||
* @param callbackCtx Reference to the public ResizeObserver instance which
|
||||
* will be passed to callback function.
|
||||
*/
|
||||
function ResizeObserverSPI(callback, controller, callbackCtx) {
|
||||
/**
|
||||
* Collection of resize observations that have detected changes in dimensions
|
||||
* of elements.
|
||||
*/
|
||||
this.activeObservations_ = [];
|
||||
/**
|
||||
* Registry of the ResizeObservation instances.
|
||||
*/
|
||||
this.observations_ = new MapShim();
|
||||
if (typeof callback !== "function") {
|
||||
throw new TypeError(
|
||||
"The callback provided as parameter 1 is not a function."
|
||||
);
|
||||
}
|
||||
this.callback_ = callback;
|
||||
this.controller_ = controller;
|
||||
this.callbackCtx_ = callbackCtx;
|
||||
}
|
||||
/**
|
||||
* Starts observing provided element.
|
||||
*
|
||||
* @param target Element to be observed.
|
||||
*/
|
||||
ResizeObserverSPI.prototype.observe = function (target) {
|
||||
if (target === undefined) {
|
||||
throw new TypeError("1 argument required, but only 0 present.");
|
||||
}
|
||||
// Do nothing if current environment doesn't have the Element interface.
|
||||
if (typeof Element === "undefined" || !(Element instanceof Object)) {
|
||||
return;
|
||||
}
|
||||
if (!(target instanceof getWindowOf(target).Element)) {
|
||||
throw new TypeError('parameter 1 is not of type "Element".');
|
||||
}
|
||||
var observations = this.observations_;
|
||||
// Do nothing if element is already being observed.
|
||||
if (observations.has(target)) {
|
||||
return;
|
||||
}
|
||||
observations.set(target, new ResizeObservation(target));
|
||||
this.controller_.addObserver(this);
|
||||
// Force the update of observations.
|
||||
this.controller_.refresh();
|
||||
};
|
||||
/**
|
||||
* Stops observing provided element.
|
||||
*
|
||||
* @param target Element to stop observing.
|
||||
*/
|
||||
ResizeObserverSPI.prototype.unobserve = function (target) {
|
||||
if (target === undefined) {
|
||||
throw new TypeError("1 argument required, but only 0 present.");
|
||||
}
|
||||
// Do nothing if current environment doesn't have the Element interface.
|
||||
if (typeof Element === "undefined" || !(Element instanceof Object)) {
|
||||
return;
|
||||
}
|
||||
if (!(target instanceof getWindowOf(target).Element)) {
|
||||
throw new TypeError('parameter 1 is not of type "Element".');
|
||||
}
|
||||
var observations = this.observations_;
|
||||
// Do nothing if element is not being observed.
|
||||
if (!observations.has(target)) {
|
||||
return;
|
||||
}
|
||||
observations.delete(target);
|
||||
if (!observations.size) {
|
||||
this.controller_.removeObserver(this);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Stops observing all elements.
|
||||
*/
|
||||
ResizeObserverSPI.prototype.disconnect = function () {
|
||||
this.clearActive();
|
||||
this.observations_.clear();
|
||||
this.controller_.removeObserver(this);
|
||||
};
|
||||
/**
|
||||
* Collects observation instances the associated element of which has changed
|
||||
* it's content rectangle.
|
||||
*/
|
||||
ResizeObserverSPI.prototype.gatherActive = function () {
|
||||
var _this = this;
|
||||
this.clearActive();
|
||||
this.observations_.forEach(function (observation) {
|
||||
if (observation.isActive()) {
|
||||
_this.activeObservations_.push(observation);
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Invokes initial callback function with a list of ResizeObserverEntry
|
||||
* instances collected from active resize observations.
|
||||
*/
|
||||
ResizeObserverSPI.prototype.broadcastActive = function () {
|
||||
// Do nothing if observer doesn't have active observations.
|
||||
if (!this.hasActive()) {
|
||||
return;
|
||||
}
|
||||
var ctx = this.callbackCtx_;
|
||||
// Create ResizeObserverEntry instance for every active observation.
|
||||
var entries = this.activeObservations_.map(function (observation) {
|
||||
return new ResizeObserverEntry(
|
||||
observation.target,
|
||||
observation.broadcastRect()
|
||||
);
|
||||
});
|
||||
this.callback_.call(ctx, entries, ctx);
|
||||
this.clearActive();
|
||||
};
|
||||
/**
|
||||
* Clears the collection of active observations.
|
||||
*/
|
||||
ResizeObserverSPI.prototype.clearActive = function () {
|
||||
this.activeObservations_.splice(0);
|
||||
};
|
||||
/**
|
||||
* Tells whether observer has active observations.
|
||||
*/
|
||||
ResizeObserverSPI.prototype.hasActive = function () {
|
||||
return this.activeObservations_.length > 0;
|
||||
};
|
||||
return ResizeObserverSPI;
|
||||
})();
|
||||
|
||||
/**
|
||||
* ResizeObserver API. Encapsulates the ResizeObserver SPI implementation
|
||||
* exposing only those methods and properties that are defined in the spec.
|
||||
*/
|
||||
var ResizeObserver = /** @class */ (function () {
|
||||
/**
|
||||
* Creates a new instance of ResizeObserver.
|
||||
*
|
||||
* @param callback Callback that is invoked when dimensions of the observed
|
||||
* elements change.
|
||||
*/
|
||||
function ResizeObserver(callback) {
|
||||
if (!(this instanceof ResizeObserver)) {
|
||||
throw new TypeError("Cannot call a class as a function.");
|
||||
}
|
||||
if (!arguments.length) {
|
||||
throw new TypeError("1 argument required, but only 0 present.");
|
||||
}
|
||||
var controller = ResizeObserverController.getInstance();
|
||||
this.observer_ = new ResizeObserverSPI(callback, controller, this);
|
||||
}
|
||||
ResizeObserver.prototype.observe = function (target) {
|
||||
this.observer_.observe(target);
|
||||
};
|
||||
ResizeObserver.prototype.unobserve = function (target) {
|
||||
this.observer_.unobserve(target);
|
||||
};
|
||||
ResizeObserver.prototype.disconnect = function () {
|
||||
this.observer_.disconnect();
|
||||
};
|
||||
return ResizeObserver;
|
||||
})();
|
||||
|
||||
var index = (function () {
|
||||
// Export existing implementation if available.
|
||||
if (typeof global$1.ResizeObserver !== "undefined") {
|
||||
return global$1.ResizeObserver;
|
||||
}
|
||||
return ResizeObserver;
|
||||
})();
|
||||
|
||||
export default index;
|
8
src/resources/lit-virtualizer/lib/uni-virtualizer/uni-virtualizer.d.ts
vendored
Normal file
8
src/resources/lit-virtualizer/lib/uni-virtualizer/uni-virtualizer.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
export {
|
||||
VirtualScroller,
|
||||
RangeChangeEvent,
|
||||
scrollerRef,
|
||||
} from "./lib/VirtualScroller.js";
|
||||
export { Layout1d, layout1d } from "./lib/layouts/Layout1d.js";
|
||||
export { Layout1dGrid } from "./lib/layouts/Layout1dGrid.js";
|
||||
//# sourceMappingURL=uni-virtualizer.d.ts.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"uni-virtualizer.d.ts","sourceRoot":"","sources":["../../src/lib/uni-virtualizer/uni-virtualizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE1F,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC"}
|
@ -0,0 +1,4 @@
|
||||
export { VirtualScroller, scrollerRef } from "./lib/VirtualScroller.js";
|
||||
export { Layout1d, layout1d } from "./lib/layouts/Layout1d.js";
|
||||
export { Layout1dGrid } from "./lib/layouts/Layout1dGrid.js";
|
||||
//# sourceMappingURL=uni-virtualizer.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"uni-virtualizer.js","sourceRoot":"","sources":["../../src/lib/uni-virtualizer/uni-virtualizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAoB,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE1F,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC","sourcesContent":["export { VirtualScroller, RangeChangeEvent, scrollerRef } from './lib/VirtualScroller.js';\n\nexport { Layout1d, layout1d } from './lib/layouts/Layout1d.js';\nexport { Layout1dGrid } from './lib/layouts/Layout1dGrid.js';\n"]}
|
10
src/resources/lit-virtualizer/lit-virtualizer.d.ts
vendored
Normal file
10
src/resources/lit-virtualizer/lit-virtualizer.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
export { scroll } from "./lib/scroll.js";
|
||||
export {
|
||||
Layout1d,
|
||||
layout1d,
|
||||
Layout1dGrid,
|
||||
RangeChangeEvent,
|
||||
scrollerRef,
|
||||
} from "./lib/uni-virtualizer/uni-virtualizer.js";
|
||||
export { LitVirtualizer } from "./lib/lit-virtualizer.js";
|
||||
//# sourceMappingURL=lit-virtualizer.d.ts.map
|
1
src/resources/lit-virtualizer/lit-virtualizer.d.ts.map
Normal file
1
src/resources/lit-virtualizer/lit-virtualizer.d.ts.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"lit-virtualizer.d.ts","sourceRoot":"","sources":["src/lit-virtualizer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC3H,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC"}
|
10
src/resources/lit-virtualizer/lit-virtualizer.js
Normal file
10
src/resources/lit-virtualizer/lit-virtualizer.js
Normal file
@ -0,0 +1,10 @@
|
||||
// export { repeat } from './lib/repeat.js';
|
||||
export { scroll } from "./lib/scroll.js";
|
||||
export {
|
||||
Layout1d,
|
||||
layout1d,
|
||||
Layout1dGrid,
|
||||
scrollerRef,
|
||||
} from "./lib/uni-virtualizer/uni-virtualizer.js";
|
||||
export { LitVirtualizer } from "./lib/lit-virtualizer.js";
|
||||
//# sourceMappingURL=lit-virtualizer.js.map
|
1
src/resources/lit-virtualizer/lit-virtualizer.js.map
Normal file
1
src/resources/lit-virtualizer/lit-virtualizer.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"lit-virtualizer.js","sourceRoot":"","sources":["src/lit-virtualizer.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAoB,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC3H,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC","sourcesContent":["// export { repeat } from './lib/repeat.js';\nexport { scroll } from './lib/scroll.js';\nexport { Layout1d, layout1d, Layout1dGrid, RangeChangeEvent, scrollerRef } from './lib/uni-virtualizer/uni-virtualizer.js';\nexport { LitVirtualizer } from './lib/lit-virtualizer.js';\n"]}
|
55
src/resources/lit-virtualizer/package.json
Normal file
55
src/resources/lit-virtualizer/package.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "@lit-labs/virtualizer",
|
||||
"version": "0.7.0",
|
||||
"description": "Virtual scrolling for Lit",
|
||||
"license": "BSD-3-Clause",
|
||||
"main": "lit-virtualizer.js",
|
||||
"files": [
|
||||
"/lit-virtualizer.js",
|
||||
"/lit-virtualizer.d.ts",
|
||||
"/lit-virtualizer.d.ts.map",
|
||||
"/lib/"
|
||||
],
|
||||
"module": "lit-virtualizer.js",
|
||||
"scripts": {
|
||||
"bench": "tach --root=../.. --browser=chrome-headless test/benchmarks/${BENCH:-basic}.html --measure=fcp",
|
||||
"bench:debug": "tach --root=../.. test/benchmarks/${BENCH:-basic}.html --measure=fcp",
|
||||
"bench:scroll": "tach --force-clean-npm-install --config=test/benchmarks/scrollingBenchmarks.json",
|
||||
"build": "tsc & copyfiles -u 2 src/lib/uni-virtualizer/lib/polyfills/resize-observer-polyfill/ResizeObserver.js lib",
|
||||
"checksize": "rollup -c; rm lit-virtualizer.bundled.js lit-virtualizer-with-polyfills.bundled.js",
|
||||
"clean": "rm -r node_modules/",
|
||||
"lint": "tslint --project ./",
|
||||
"prepare": "npm run build",
|
||||
"test": "karma start karma.conf.js",
|
||||
"test:debug": "karma start karma.conf.js --single-run=false --debug",
|
||||
"test:screenshot": "cd test/screenshot && rollup -c && mocha screenshot.js",
|
||||
"generate-screenshots": "cd test/screenshot && rollup -c && mocha screenshot.js --generate-screenshots"
|
||||
},
|
||||
"author": "Google LLC",
|
||||
"devDependencies": {
|
||||
"chai": "^4.2.0",
|
||||
"copyfiles": "^2.4.1",
|
||||
"http-server": "^0.11.1",
|
||||
"karma": "^4.1.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-rollup-preprocessor": "^7.0.0",
|
||||
"mocha": "^6.1.4",
|
||||
"pixelmatch": "^4.0.2",
|
||||
"pngjs": "^3.4.0",
|
||||
"puppeteer": "^1.17.0",
|
||||
"rollup": "^1.11.2",
|
||||
"rollup-plugin-filesize": "^6.1.1",
|
||||
"rollup-plugin-node-resolve": "^4.2.3",
|
||||
"rollup-plugin-terser": "^5.0.0",
|
||||
"tachometer": "^0.4.7",
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"event-target-shim": "^5.0.1",
|
||||
"lit": "^2.0.0-rc.1",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
}
|
@ -931,6 +931,9 @@
|
||||
"config_entry_system_options": {
|
||||
"enable_new_entities_description": "비활성화한 경우 새로 발견된 {integration} 구성요소는 Home Assistant에 자동으로 추가되지 않습니다.",
|
||||
"enable_new_entities_label": "새로 추가된 구성요소를 활성화합니다.",
|
||||
"enable_polling_description": "Home Assistant가 업데이트를 위해 {integration} 구성요소를 자동으로 폴링해야하는 경우.",
|
||||
"enable_polling_label": "업데이트를 위해 폴링을 활성화합니다.",
|
||||
"restart_home_assistant": "변경 사항을 적용하려면 Home Assistant를 다시 시작해야합니다.",
|
||||
"title": "{integration} 시스템 옵션",
|
||||
"update": "업데이트"
|
||||
},
|
||||
@ -2217,6 +2220,7 @@
|
||||
},
|
||||
"disabled_cause": "{cause}에 의해 비활성화되었습니다"
|
||||
},
|
||||
"disabled_polling": "데이터 업데이트를 위한 자동 폴링 비활성화",
|
||||
"documentation": "관련 문서",
|
||||
"enable_restart_confirm": "이 통합 구성요소를 활성화하려면 Home Assistant를 다시 시작해주세요",
|
||||
"entities": "{count} {count, plural,\none{개의 구성요소}\nother{개의 구성요소}\n}",
|
||||
|
Loading…
x
Reference in New Issue
Block a user