@salesforcedevs/dx-components 0.53.1 → 0.53.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lwc.config.json CHANGED
@@ -29,7 +29,6 @@
29
29
  "dx/emptyState",
30
30
  "dx/feature",
31
31
  "dx/featuredContentHeader",
32
- "dx/featureGrid",
33
32
  "dx/featuresList",
34
33
  "dx/filterMenu",
35
34
  "dx/banner",
@@ -37,13 +36,11 @@
37
36
  "dx/newsletterForm",
38
37
  "dx/formattedDateTime",
39
38
  "dx/grid",
40
- "dx/groupBio",
41
39
  "dx/groupText",
42
40
  "dx/header",
43
41
  "dx/headerMobileNavMenu",
44
42
  "dx/headerNav",
45
43
  "dx/headerSearch",
46
- "dx/headTags",
47
44
  "dx/helmet",
48
45
  "dx/hr",
49
46
  "dx/icon",
@@ -51,8 +48,6 @@
51
48
  "dx/imageAndLabel",
52
49
  "dx/input",
53
50
  "dx/instrumentation",
54
- "dx/interactiveImage",
55
- "dx/lazy",
56
51
  "dx/logo",
57
52
  "dx/modalDrawer",
58
53
  "dx/pagination",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/dx-components",
3
- "version": "0.53.1",
3
+ "version": "0.53.2",
4
4
  "description": "DX Lightning web components",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -28,5 +28,5 @@
28
28
  "@types/lodash.get": "^4.4.6",
29
29
  "@types/vimeo__player": "^2.16.2"
30
30
  },
31
- "gitHead": "d0ec69fdb1483f7061ef4deeddc583c0ec3a11d5"
31
+ "gitHead": "37bfd27f1580498841761daaeb7da20f5a539d3e"
32
32
  }
@@ -306,6 +306,7 @@ export default class ContentArchive extends LightningElement {
306
306
 
307
307
  this.updateCheckedStatus();
308
308
  this.fetchPostsByCardType();
309
+ QueryCoordinator.setUrlParamValue(QUERY_SITE_FILTER, null);
309
310
  }
310
311
 
311
312
  private goToPage(e: CustomEvent) {
@@ -1,89 +0,0 @@
1
- @import "helpers/reset";
2
- @import "helpers/text";
3
-
4
- .docs-action-bar {
5
- display: flex;
6
- justify-content: space-between;
7
- align-items: flex-end;
8
- padding: var(--dx-g-spacing-md) 0 var(--dx-g-spacing-lg);
9
- }
10
-
11
- .docs-action-bar > .records-container {
12
- margin-right: auto;
13
- }
14
-
15
- .docs-action-bar .filters-container {
16
- display: flex;
17
- }
18
-
19
- .filter-checkbox-group,
20
- .filter-button::part(container) {
21
- --dx-c-checkbox-text-transform: capitalize;
22
-
23
- text-transform: var(--dx-c-checkbox-text-transform);
24
- }
25
-
26
- .docs-action-bar .filters-container > *:not(:first-child),
27
- .docs-search-input {
28
- margin-left: var(--dx-g-spacing-sm);
29
- }
30
-
31
- .docs-search-input {
32
- --dx-c-input-width: 285px;
33
- }
34
-
35
- .docs-card {
36
- --dx-c-body-max-lines: 4;
37
- --dx-c-heading-max-lines: 2;
38
- }
39
-
40
- .pagination-container {
41
- max-width: fit-content;
42
- max-width: -moz-fit-content;
43
- margin: var(--dx-g-spacing-lg) auto;
44
- }
45
-
46
- @media screen and (max-width: 1024px) {
47
- .docs-card {
48
- --dx-c-body-max-lines: 3;
49
- }
50
- }
51
-
52
- @media screen and (max-width: 768px) {
53
- .docs-action-bar {
54
- flex-direction: column-reverse;
55
- width: 100%;
56
- padding: 0;
57
- }
58
-
59
- .docs-search-input {
60
- --dx-c-input-width: 100%;
61
-
62
- width: 100%;
63
- margin-bottom: var(--dx-g-spacing-md);
64
- }
65
-
66
- .docs-action-bar .records-container {
67
- transform: translateY(-100%);
68
- }
69
- }
70
-
71
- @media screen and (max-width: 600px) {
72
- .pagination-container {
73
- width: 100%;
74
- overflow: hidden;
75
- }
76
-
77
- .pagination-container > * {
78
- position: absolute;
79
- left: 50%;
80
- transform: translateX(-50%);
81
- }
82
- }
83
-
84
- @media screen and (max-width: 460px) {
85
- .docs-action-bar .records-container {
86
- transform: initial;
87
- padding: var(--dx-g-spacing-md) 0;
88
- }
89
- }
@@ -1,46 +0,0 @@
1
- <template>
2
- <div class="card-grid">
3
- <div class="docs-action-bar">
4
- <div class="records-container">
5
- <span if:true={endingRecord}>
6
- Showing { startingRecord } to { endingRecord } of {
7
- cards.length }
8
- </span>
9
- </div>
10
- <div class="filters-container">
11
- <slot name="filters"></slot>
12
- </div>
13
- <dx-input
14
- size="small"
15
- placeholder="Search..."
16
- icon-symbol="search"
17
- shortcut-key="j"
18
- class="docs-search-input"
19
- onchange={handleSearchChange}
20
- value={searchTerm}
21
- ></dx-input>
22
- </div>
23
- <dx-grid
24
- columns={tileColumns}
25
- if:false={showEmptyState}
26
- class="card-container"
27
- ></dx-grid>
28
- <div style="display: none">
29
- <slot name="cards" onslotchange={onSlotChange}></slot>
30
- </div>
31
- <div class="pagination-container" if:false={showEmptyState}>
32
- <dx-pagination
33
- current-page={page}
34
- total-pages={totalPages}
35
- pages-to-show={pagesToShow}
36
- onpagechange={goToPage}
37
- if:false={hidePagination}
38
- ></dx-pagination>
39
- </div>
40
- </div>
41
- <dx-empty-state
42
- title="Beep boop. That did not compute."
43
- subtitle={emptyStateSubtitle}
44
- if:true={showEmptyState}
45
- ></dx-empty-state>
46
- </template>
@@ -1,140 +0,0 @@
1
- import { LightningElement, api } from "lwc";
2
-
3
- export default class CardGrid extends LightningElement {
4
- @api pageSize = 24;
5
- @api searchDebounce = 500;
6
- page = 1;
7
-
8
- private searchTerm = "";
9
- private matchDesktop!: MediaQueryList;
10
- private matchMobile!: MediaQueryList;
11
- private matchMobileSmall!: MediaQueryList;
12
- private deviceType: "desktop" | "mobile" | "mobile-small" = "desktop";
13
- private searchTimeout?: number;
14
- private cards: any[] = [];
15
-
16
- private get startingRecord() {
17
- return this.page === 1
18
- ? this.page
19
- : (this.page - 1) * this.pageSize + 1;
20
- }
21
-
22
- private get endingRecord() {
23
- const defaultEndingRecord = this.pageSize * this.page;
24
- return defaultEndingRecord > this.cards.length
25
- ? this.cards.length
26
- : defaultEndingRecord;
27
- }
28
-
29
- private get totalPages() {
30
- return Math.ceil(this.cards.length / this.pageSize);
31
- }
32
-
33
- private get hidePagination() {
34
- return this.totalPages < 2;
35
- }
36
-
37
- private get emptyStateSubtitle() {
38
- return (
39
- "No results" +
40
- (this.searchTerm !== "" ? ` for "${this.searchTerm}"` : "")
41
- );
42
- }
43
-
44
- private get showEmptyState() {
45
- return !this.cards.length;
46
- }
47
-
48
- private get tileColumns() {
49
- return this.deviceType === "desktop" ? "three" : "two";
50
- }
51
-
52
- private get pagesToShow() {
53
- return this.deviceType === "mobile-small" ? 3 : 5;
54
- }
55
-
56
- connectedCallback(): void {
57
- this.matchDesktop = window.matchMedia("(min-width: 1024px)");
58
- this.matchDesktop.addEventListener("change", this.handleDesktopView);
59
-
60
- this.matchMobile = window.matchMedia(
61
- "(min-width: 401px) and (max-width: 1023px)"
62
- );
63
- this.matchMobile.addEventListener("change", this.handleMobileView);
64
-
65
- this.matchMobileSmall = window.matchMedia("(max-width: 340px)");
66
- this.matchMobileSmall.addEventListener(
67
- "change",
68
- this.handleMobileSmallView
69
- );
70
-
71
- if (this.matchMobile.matches) {
72
- this.deviceType = "mobile";
73
- }
74
- if (this.matchMobileSmall.matches) {
75
- this.deviceType = "mobile-small";
76
- }
77
- }
78
-
79
- disconnectedCallback(): void {
80
- this.matchDesktop.removeEventListener("change", this.handleDesktopView);
81
- this.matchMobile.removeEventListener("change", this.handleMobileView);
82
- this.matchMobileSmall.removeEventListener(
83
- "change",
84
- this.handleMobileSmallView
85
- );
86
- }
87
-
88
- renderedCallback(): void {
89
- this.displayCurrentPage();
90
- }
91
-
92
- onSlotChange() {
93
- const slots = Array.from(
94
- this.template.querySelectorAll("slot")
95
- ) as HTMLSlotElement[];
96
- this.cards = Array.from(slots[1].assignedElements()[0].children);
97
- }
98
-
99
- handleDesktopView = (e: MediaQueryListEvent | MediaQueryList) => {
100
- if (e.matches) {
101
- this.deviceType = "desktop";
102
- }
103
- };
104
-
105
- handleMobileView = (e: MediaQueryListEvent | MediaQueryList) => {
106
- if (e.matches) {
107
- this.deviceType = "mobile";
108
- }
109
- };
110
-
111
- handleMobileSmallView = (e: MediaQueryListEvent | MediaQueryList) => {
112
- if (e.matches) {
113
- this.deviceType = "mobile-small";
114
- }
115
- };
116
-
117
- handleSearchChange(event: InputEvent): void {
118
- window.clearTimeout(this.searchTimeout);
119
- this.searchTimeout = window.setTimeout(() => {
120
- this.dispatchEvent(
121
- new CustomEvent("searchchange", { detail: event.detail })
122
- );
123
- }, this.searchDebounce);
124
- }
125
-
126
- goToPage(e: CustomEvent) {
127
- this.page = e.detail;
128
- this.displayCurrentPage();
129
- }
130
-
131
- displayCurrentPage() {
132
- const cardContainer = this.template.querySelector(".card-container");
133
- if (cardContainer) {
134
- cardContainer.innerHTML = "";
135
- this.cards
136
- .slice(this.startingRecord - 1, this.endingRecord)
137
- .map((node) => cardContainer?.appendChild(node));
138
- }
139
- }
140
- }
@@ -1,3 +0,0 @@
1
- <template>
2
- <slot onslotchange={onSlotChange}></slot>
3
- </template>
@@ -1,15 +0,0 @@
1
- import { LightningElement } from "lwc";
2
- import { LightningSlotElement } from "typings/custom";
3
-
4
- export default class FeatureGrid extends LightningElement {
5
- private onSlotChange(e: LightningSlotElement) {
6
- // @ts-ignore
7
- const slot = e.target;
8
- slot.assignedElements().forEach(
9
- (featureElement: any, index: number) => {
10
- featureElement.descriptionPosition =
11
- index % 2 === 0 ? "left" : "right";
12
- }
13
- );
14
- }
15
- }
@@ -1,49 +0,0 @@
1
- @import "helpers/reset";
2
- @import "helpers/text";
3
-
4
- .container {
5
- display: flex;
6
- flex-direction: column;
7
- align-items: center;
8
- }
9
-
10
- .avatar {
11
- border-radius: 9999px;
12
- margin-bottom: var(--dx-g-spacing-md);
13
- }
14
-
15
- .name {
16
- margin-bottom: var(--dx-g-spacing-sm);
17
- }
18
-
19
- .avatar.size-small {
20
- width: 50px;
21
- }
22
-
23
- .avatar.size-medium {
24
- width: 100px;
25
- }
26
-
27
- .avatar.size-large {
28
- width: 200px;
29
- }
30
-
31
- .body {
32
- text-align: center;
33
- }
34
-
35
- .position {
36
- color: var(--dx-g-blue-vibrant-50);
37
- }
38
-
39
- .position.condensed {
40
- color: inherit;
41
- }
42
-
43
- .descriptors {
44
- margin-top: var(--dx-g-spacing-sm);
45
- }
46
-
47
- .descriptors > *:not(:last-child) {
48
- margin-bottom: var(--dx-g-spacing-xs);
49
- }
@@ -1,29 +0,0 @@
1
- <template>
2
- <div class="container">
3
- <div if:true={imgSrc}>
4
- <img class={imgClass} src={imgSrc} alt={imgAlt} />
5
- </div>
6
- <div class="body">
7
- <p if:true={name} class={nameClass}>{name}</p>
8
- <p if:true={position} class={positionClass}>{position}</p>
9
- <div
10
- if:false={isCondensedVariant}
11
- class="descriptors dx-text-body-2"
12
- >
13
- <p if:true={descriptor1}>{descriptor1}</p>
14
- <p if:true={descriptor2}>{descriptor2}</p>
15
- <p if:true={descriptor3}>{descriptor3}</p>
16
- <p if:true={profileHref}>
17
- <dx-button
18
- href={profileHref}
19
- target={profileTarget}
20
- rel={profileRel}
21
- variant="inline-inherit"
22
- >
23
- {profileText}
24
- </dx-button>
25
- </p>
26
- </div>
27
- </div>
28
- </div>
29
- </template>
@@ -1,41 +0,0 @@
1
- import { LightningElement, api } from "lwc";
2
-
3
- export default class GroupBio extends LightningElement {
4
- @api imgSrc: string = "";
5
- @api imgAlt: string = "";
6
- @api imgSize: "small" | "medium" | "large" = "large";
7
- @api variant: "condensed" | "default" = "default";
8
- @api name: string = "";
9
- @api position: string = "";
10
- @api descriptor1: string = "";
11
- @api descriptor2: string = "";
12
- @api descriptor3: string = "";
13
- @api profileHref: string = "";
14
- @api profileText: string = "";
15
- @api profileTarget: string = "_blank";
16
- @api profileRel: string = "noopener";
17
-
18
- private get imgClass(): string {
19
- return `avatar size-${this.imgSize}`;
20
- }
21
-
22
- private get nameClass(): string {
23
- return `name ${
24
- this.variant === "condensed"
25
- ? "condensed dx-text-label-1"
26
- : "dx-text-heading-4"
27
- }`;
28
- }
29
-
30
- private get positionClass(): string {
31
- return `position ${
32
- this.variant === "condensed"
33
- ? "condensed dx-text-body-3"
34
- : "dx-text-heading-5"
35
- }`;
36
- }
37
-
38
- private get isCondensedVariant(): boolean {
39
- return this.variant === "condensed";
40
- }
41
- }
@@ -1,3 +0,0 @@
1
- <template>
2
- <slot></slot>
3
- </template>
@@ -1,39 +0,0 @@
1
- import { LightningElement } from "lwc";
2
-
3
- const syncElementAttributes = (elementA: Element, elementB: Element) => {
4
- if (elementB.textContent) {
5
- elementA.textContent = elementB.textContent;
6
- }
7
- const names = elementB.getAttributeNames();
8
- names.forEach((name: string) => {
9
- const val = elementB.getAttribute(name);
10
- if (val) {
11
- elementA.setAttribute(name, val);
12
- }
13
- });
14
- };
15
-
16
- export default class HeadTags extends LightningElement {
17
- connectedCallback() {
18
- const innerElements = this.querySelectorAll("*");
19
- if (innerElements) {
20
- Array.from(innerElements).forEach((innerElement) => {
21
- const elementName = innerElement.getAttribute("name");
22
- let existingElement = null;
23
- if (elementName) {
24
- existingElement = document.head.querySelector(
25
- `meta[name="${elementName}"]`
26
- );
27
- }
28
- if (innerElement.tagName === "TITLE") {
29
- existingElement = document.head.querySelector("title");
30
- }
31
- if (existingElement) {
32
- syncElementAttributes(existingElement, innerElement);
33
- return;
34
- }
35
- document.head.appendChild(innerElement);
36
- });
37
- }
38
- }
39
- }
@@ -1,59 +0,0 @@
1
- @import "helpers/reset";
2
- @import "helpers/text";
3
-
4
- article {
5
- border: 1px solid var(--dx-g-gray-90);
6
- border-radius: 0.3125rem;
7
- }
8
-
9
- header {
10
- display: flex;
11
- align-items: flex-start;
12
- justify-content: space-between;
13
- border-radius: 0.3125rem 0.3125rem 0 0;
14
- background-color: var(--dx-g-gray-95);
15
- font-family: var(--dx-g-font-sans);
16
- color: var(--dx-g-gray-10);
17
- padding: var(--dx-g-spacing-sm);
18
- }
19
-
20
- header span {
21
- padding: var(--dx-g-spacing-sm) var(--dx-g-spacing-md);
22
- font-size: var(--dx-g-text-sm);
23
- }
24
-
25
- footer {
26
- border-radius: 0 0 0.3125rem 0.3125rem;
27
- }
28
-
29
- .body {
30
- margin: var(--dx-g-spacing-md);
31
- overflow-x: auto;
32
- }
33
-
34
- .body img {
35
- min-width: 650px;
36
- }
37
-
38
- .controls {
39
- display: flex;
40
- align-items: center;
41
- justify-content: flex-end;
42
- }
43
-
44
- /* Breakpoints for mobile */
45
-
46
- @media screen and (max-width: 640px) {
47
- header {
48
- flex-direction: column;
49
- align-items: flex-end;
50
- }
51
- }
52
-
53
- @media screen and (max-width: 320px) {
54
- .controls,
55
- .controls dx-dropdown,
56
- .controls dx-button {
57
- width: 100%;
58
- }
59
- }
@@ -1,32 +0,0 @@
1
- <template>
2
- <article>
3
- <header>
4
- <span>{title}</span>
5
- <div class="controls">
6
- <template if:true={isSingleDownload}>
7
- <dx-button
8
- icon-symbol="download"
9
- href={singleDownloadHref}
10
- download={singleDownloadFilename}
11
- >
12
- {downloadButtonLabel}
13
- </dx-button>
14
- </template>
15
- <template if:false={isSingleDownload}>
16
- <dx-dropdown
17
- options={urls}
18
- onchange={handleDownloadOptionChange}
19
- placement="bottom-end"
20
- >
21
- <dx-button variant="primary" icon-symbol="chevrondown">
22
- {downloadButtonLabel}
23
- </dx-button>
24
- </dx-dropdown>
25
- </template>
26
- </div>
27
- </header>
28
- <div class="body">
29
- <img src={featuredSrc} alt={title} />
30
- </div>
31
- </article>
32
- </template>
@@ -1,71 +0,0 @@
1
- import { LightningElement, api } from "lwc";
2
-
3
- // Extracts filename and extension from a file URL
4
- const FILENAME_FROM_URL_REGEX = /(?=\w+\.\w{3,4}$).+/;
5
- const EXTENSION_FROM_URL_REGEX = /\.([^.]*)$/;
6
-
7
- export default class InteractiveImage extends LightningElement {
8
- @api title!: string;
9
- @api featuredSrc!: string;
10
-
11
- @api
12
- set downloadUrls(values: any) {
13
- // Normalize input values
14
- let urls;
15
- if (typeof values === "string") {
16
- if (values.startsWith("[")) {
17
- urls = JSON.parse(values);
18
- } else {
19
- urls = [values];
20
- }
21
- } else {
22
- urls = values;
23
- }
24
- // Ensure that we have some URLs
25
- if (!urls || urls.length === 0) {
26
- throw new Error(
27
- `No download url found for interactive image with title "${this.title}"`
28
- );
29
- }
30
- // Prepare download options with labels
31
- this.urls = urls.map((url: string) => {
32
- return {
33
- label: this.getDownloadLabelFromUrl(url),
34
- id: url
35
- };
36
- });
37
- }
38
- get downloadUrls() {
39
- return this.urls;
40
- }
41
-
42
- private urls: { label: string; id: string }[] = [];
43
-
44
- private get isSingleDownload() {
45
- return this.urls.length === 1;
46
- }
47
-
48
- private get singleDownloadHref() {
49
- return this.urls[0].id;
50
- }
51
-
52
- private get singleDownloadFilename() {
53
- const pathParts = this.urls[0].id.match(FILENAME_FROM_URL_REGEX);
54
- return pathParts ? pathParts[0] : "";
55
- }
56
-
57
- private get downloadButtonLabel() {
58
- return this.isSingleDownload ? this.urls[0].label : "Download as...";
59
- }
60
-
61
- private handleDownloadOptionChange(event: CustomEvent) {
62
- window.open(event.detail, "_blank");
63
- }
64
-
65
- private getDownloadLabelFromUrl(url: string): string {
66
- const urlParts = url.match(EXTENSION_FROM_URL_REGEX);
67
- return urlParts
68
- ? `Download as ${urlParts[1].toUpperCase()}`
69
- : "Download";
70
- }
71
- }
@@ -1,5 +0,0 @@
1
- <template>
2
- <template if:true={renderSlot}>
3
- <slot></slot>
4
- </template>
5
- </template>
@@ -1,163 +0,0 @@
1
- import { LightningElement, api } from "lwc";
2
-
3
- import { LazyMode } from "typings/custom";
4
-
5
- /**
6
- * Defines a fallback for BackgroundTasksAPI for browsers that doesn't support it.
7
- * Currently BackgroundTasksAPI is supported by all major browsers
8
- * except in Safari where it can be enabled in Experimental (WebKit) Features.
9
- * See also: https://developer.mozilla.org/en-US/docs/Web/API/Background_Tasks_API
10
- */
11
- function defineBackgroundTasksAPI() {
12
- // Fallback to using setTimeout
13
- window.requestIdleCallback =
14
- window.requestIdleCallback ||
15
- function (handler: any) {
16
- const startTime = Date.now();
17
-
18
- return setTimeout(function () {
19
- handler({
20
- didTimeout: false,
21
- timeRemaining: function () {
22
- return Math.max(0, 50.0 - (Date.now() - startTime));
23
- }
24
- });
25
- }, 1);
26
- };
27
- window.cancelIdleCallback =
28
- window.cancelIdleCallback ||
29
- function (id: any) {
30
- clearTimeout(id);
31
- };
32
- }
33
-
34
- export default class Lazy extends LightningElement {
35
- @api mode: LazyMode = "idle";
36
-
37
- // intersection mode api
38
- @api rootId: string | undefined;
39
- @api rootMargin: string = "0px";
40
- @api threshold: number = 0;
41
-
42
- @api
43
- get placeholderSize() {
44
- return this._placeholderSize;
45
- }
46
-
47
- set placeholderSize(value) {
48
- this._placeholderSize = value;
49
- }
50
-
51
- /**
52
- * 'rendered' marks the first call made to renderedCallback()
53
- */
54
- private rendered: boolean = false;
55
- /**
56
- * 'renderSlot' controls whether the dx-lazy slot contents get rendered
57
- */
58
- private renderSlot: boolean = false;
59
- /**
60
- * 'connectedCallbackCalled' marks the first call made to connectedCallback()
61
- */
62
- private connectedCallbackCalled: boolean = false;
63
- /**
64
- * The handle as returned by calling window.requestIdleCallback()
65
- */
66
- private idleCallbackHandle: any;
67
- /**
68
- * The Intersection Observer if instantiated, else undefined
69
- */
70
- private observer: IntersectionObserver | undefined;
71
- /**
72
- * The size of the placeholder for the lazy container in pixels
73
- */
74
- private _placeholderSize: number = 200;
75
-
76
- constructor() {
77
- super();
78
- this.updateHostStyle();
79
- }
80
-
81
- connectedCallback() {
82
- if (!this.connectedCallbackCalled) {
83
- this.connectedCallbackCalled = true;
84
- if (this.mode === "idle") {
85
- defineBackgroundTasksAPI();
86
- this.waitForIdle();
87
- }
88
- }
89
- }
90
-
91
- renderedCallback() {
92
- if (!this.rendered) {
93
- this.rendered = true;
94
- if (this.mode === "intersection") {
95
- this.observeIntersection();
96
- }
97
- }
98
- }
99
-
100
- disconnectedCallback() {
101
- if (this.observer) {
102
- this.observer.disconnect();
103
- }
104
- if (this.idleCallbackHandle) {
105
- window.cancelIdleCallback(this.idleCallbackHandle);
106
- }
107
- }
108
-
109
- private waitForIdle() {
110
- this.idleCallbackHandle = window.requestIdleCallback(
111
- this.idleCallback.bind(this),
112
- { timeout: 1000 }
113
- );
114
- }
115
-
116
- private idleCallback() {
117
- this.doRender();
118
- window.cancelIdleCallback(this.idleCallbackHandle);
119
- }
120
-
121
- private observeIntersection() {
122
- let root = null; // root with a value of null means to use the viewport
123
- if (this.rootId && typeof this.rootId === "string") {
124
- root = document.querySelector(`#${this.rootId}`);
125
- }
126
- this.observer = new IntersectionObserver(
127
- this.intersectionCallback.bind(this),
128
- {
129
- root,
130
- rootMargin: this.rootMargin,
131
- threshold: this.threshold
132
- }
133
- );
134
- this.observer.observe(this.template.host);
135
- }
136
-
137
- private intersectionCallback(
138
- entries: IntersectionObserverEntry[],
139
- observer: IntersectionObserver
140
- ) {
141
- entries.forEach((entry: IntersectionObserverEntry) => {
142
- if (entry.isIntersecting) {
143
- this.doRender();
144
- observer.disconnect();
145
- }
146
- });
147
- }
148
-
149
- private updateHostStyle() {
150
- if (this.renderSlot) {
151
- this.template.host.style.display = "";
152
- this.template.host.style.minHeight = "";
153
- } else {
154
- this.template.host.style.display = "block";
155
- this.template.host.style.minHeight = `${this._placeholderSize}px`;
156
- }
157
- }
158
-
159
- private doRender() {
160
- this.renderSlot = true;
161
- this.updateHostStyle();
162
- }
163
- }