@salesforcedevs/arch-components 1.20.17-alpha14 → 1.20.17-alpha16

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.
Files changed (147) hide show
  1. package/lwc.config.json +38 -1
  2. package/package.json +1 -1
  3. package/src/assets/css/arch-variables.css +512 -0
  4. package/src/modules/arch/badge/badge.css +22 -0
  5. package/src/modules/arch/badge/badge.html +5 -0
  6. package/src/modules/arch/badge/badge.ts +9 -0
  7. package/src/modules/arch/button/button.css +1 -0
  8. package/src/modules/arch/button/button.html +20 -0
  9. package/src/modules/arch/button/button.ts +67 -0
  10. package/src/modules/arch/buttonLink/buttonLink.css +1 -0
  11. package/src/modules/arch/buttonLink/buttonLink.html +19 -0
  12. package/src/modules/arch/buttonLink/buttonLink.stories.js +34 -0
  13. package/src/modules/arch/buttonLink/buttonLink.ts +8 -0
  14. package/src/modules/arch/buttonStyles/buttonStyles.css +220 -0
  15. package/src/modules/arch/card/card.css +128 -0
  16. package/src/modules/arch/card/card.html +85 -0
  17. package/src/modules/arch/card/card.ts +277 -0
  18. package/src/modules/arch/cardBase/cardBase.css +11 -0
  19. package/src/modules/arch/cardBase/cardBase.html +2 -0
  20. package/src/modules/arch/cardGridA/cardGridA.css +11 -0
  21. package/src/modules/arch/cardGridA/cardGridA.html +21 -0
  22. package/src/modules/arch/cardGridA/cardGridA.stories.js +118 -0
  23. package/src/modules/arch/cardGridA/cardGridA.ts +24 -0
  24. package/src/modules/arch/cardGridC/cardGridC.css +24 -0
  25. package/src/modules/arch/cardGridC/cardGridC.html +22 -0
  26. package/src/modules/arch/cardGridC/cardGridC.stories.js +51 -0
  27. package/src/modules/arch/cardGridC/cardGridC.ts +11 -0
  28. package/src/modules/arch/cardGridD/cardGridD.css +17 -0
  29. package/src/modules/arch/cardGridD/cardGridD.html +20 -0
  30. package/src/modules/arch/cardGridD/cardGridD.stories.js +43 -0
  31. package/src/modules/arch/cardGridD/cardGridD.ts +7 -0
  32. package/src/modules/arch/cardNew/cardNew.css +31 -0
  33. package/src/modules/arch/cardNew/cardNew.html +32 -0
  34. package/src/modules/arch/cardNew/cardNew.ts +66 -0
  35. package/src/modules/arch/children/children.html +2 -0
  36. package/src/modules/arch/children/children.ts +31 -0
  37. package/src/modules/arch/color/color.ts +59 -0
  38. package/src/modules/arch/content/__fixtures__/index.ts +884 -0
  39. package/src/modules/arch/content/content.css +643 -0
  40. package/src/modules/arch/content/content.html +65 -0
  41. package/src/modules/arch/content/content.stories.js +21 -0
  42. package/src/modules/arch/content/content.ts +169 -0
  43. package/src/modules/arch/contentIcon/contentIcon.css +48 -0
  44. package/src/modules/arch/contentIcon/contentIcon.html +15 -0
  45. package/src/modules/arch/contentIcon/contentIcon.stories.js +130 -0
  46. package/src/modules/arch/contentIcon/contentIcon.ts +68 -0
  47. package/src/modules/arch/context/context.ts +1 -1
  48. package/src/modules/arch/contextAdapter/constants.ts +1 -0
  49. package/src/modules/arch/contextAdapter/contextAdapter.html +1 -0
  50. package/src/modules/arch/contextAdapter/contextAdapter.ts +54 -0
  51. package/src/modules/arch/debounce/debounce.ts +32 -0
  52. package/src/modules/arch/dialog/dialog.ts +154 -0
  53. package/src/modules/arch/dialogStyles/dialogStyles.css +90 -0
  54. package/src/modules/arch/effectAdapter/effectAdapter.ts +2 -0
  55. package/src/modules/arch/explorer/explorer.css +301 -0
  56. package/src/modules/arch/explorer/explorer.html +418 -0
  57. package/src/modules/arch/explorer/explorer.ts +718 -0
  58. package/src/modules/arch/explorer/types.d.ts +60 -0
  59. package/src/modules/arch/fetch/fetch.ts +55 -0
  60. package/src/modules/arch/footerMfe/footerMfe.html +3 -0
  61. package/src/modules/arch/footerMfe/footerMfe.ts +19 -0
  62. package/src/modules/arch/gallery/gallery.css +365 -0
  63. package/src/modules/arch/gallery/gallery.html +71 -0
  64. package/src/modules/arch/gallery/gallery.ts +366 -0
  65. package/src/modules/arch/gallery/types.d.ts +35 -0
  66. package/src/modules/arch/heading/heading.css +1 -0
  67. package/src/modules/arch/heading/heading.html +9 -0
  68. package/src/modules/arch/heading/heading.ts +36 -0
  69. package/src/modules/arch/helpers/helpers.ts +141 -0
  70. package/src/modules/arch/heroA/heroA.css +116 -0
  71. package/src/modules/arch/heroA/heroA.html +28 -0
  72. package/src/modules/arch/heroA/heroA.stories.js +60 -0
  73. package/src/modules/arch/heroA/heroA.ts +53 -0
  74. package/src/modules/arch/heroB/heroB.css +79 -0
  75. package/src/modules/arch/heroB/heroB.html +27 -0
  76. package/src/modules/arch/heroB/heroB.stories.js +55 -0
  77. package/src/modules/arch/heroB/heroB.ts +26 -0
  78. package/src/modules/arch/i18n/i18n.ts +78 -0
  79. package/src/modules/arch/icon/icon.css +28 -0
  80. package/src/modules/arch/icon/icon.html +17 -0
  81. package/src/modules/arch/icon/icon.stories.js +26 -0
  82. package/src/modules/arch/icon/icon.ts +92 -0
  83. package/src/modules/arch/instrumentation/instrumentation.css +1 -0
  84. package/src/modules/arch/instrumentation/instrumentation.html +1 -0
  85. package/src/modules/arch/instrumentation/instrumentation.ts +113 -0
  86. package/src/modules/arch/labels/helpers.ts +25 -0
  87. package/src/modules/arch/labels/pointHelpers.ts +47 -0
  88. package/src/modules/arch/labels/timeHelpers.ts +182 -0
  89. package/src/modules/arch/labels/types.d.ts +5 -0
  90. package/src/modules/arch/logger/logger.ts +33 -0
  91. package/src/modules/arch/menu/menu.ts +260 -0
  92. package/src/modules/arch/overflow/overflow.ts +71 -0
  93. package/src/modules/arch/page/page.css +3 -0
  94. package/src/modules/arch/page/page.html +3 -0
  95. package/src/modules/arch/page/page.stories.js +19 -0
  96. package/src/modules/arch/page/page.ts +3 -0
  97. package/src/modules/arch/pageHeaderA/pageHeaderA.css +82 -0
  98. package/src/modules/arch/pageHeaderA/pageHeaderA.html +24 -0
  99. package/src/modules/arch/pageHeaderA/pageHeaderA.stories.js +25 -0
  100. package/src/modules/arch/pageHeaderA/pageHeaderA.ts +51 -0
  101. package/src/modules/arch/pill/pill.css +70 -0
  102. package/src/modules/arch/pill/pill.html +17 -0
  103. package/src/modules/arch/pill/pill.ts +34 -0
  104. package/src/modules/arch/polling-request.ts +97 -0
  105. package/src/modules/arch/reflectedElement/reflectedElement.html +2 -0
  106. package/src/modules/arch/reflectedElement/reflectedElement.ts +2 -0
  107. package/src/modules/arch/reset/reset.css +39 -0
  108. package/src/modules/arch/searchList/searchList.css +120 -0
  109. package/src/modules/arch/searchList/searchList.html +46 -0
  110. package/src/modules/arch/searchList/searchList.ts +53 -0
  111. package/src/modules/arch/sectionA/sectionA.css +64 -0
  112. package/src/modules/arch/sectionA/sectionA.html +21 -0
  113. package/src/modules/arch/sectionA/sectionA.stories.js +25 -0
  114. package/src/modules/arch/sectionA/sectionA.ts +27 -0
  115. package/src/modules/arch/select/select.css +40 -0
  116. package/src/modules/arch/select/select.html +24 -0
  117. package/src/modules/arch/select/select.ts +64 -0
  118. package/src/modules/arch/socialShare/socialShare.css +50 -0
  119. package/src/modules/arch/socialShare/socialShare.html +56 -0
  120. package/src/modules/arch/socialShare/socialShare.ts +29 -0
  121. package/src/modules/arch/spinner/spinner.css +195 -0
  122. package/src/modules/arch/spinner/spinner.html +9 -0
  123. package/src/modules/arch/spinner/spinner.ts +15 -0
  124. package/src/modules/arch/styles/styles.css +24 -0
  125. package/src/modules/arch/summary/summary.css +134 -0
  126. package/src/modules/arch/summary/summary.html +71 -0
  127. package/src/modules/arch/summary/summary.stories.js +163 -0
  128. package/src/modules/arch/summary/summary.ts +96 -0
  129. package/src/modules/arch/tab/tab.css +3 -0
  130. package/src/modules/arch/tab/tab.html +5 -0
  131. package/src/modules/arch/tab/tab.ts +46 -0
  132. package/src/modules/arch/tabset/tabset.css +112 -0
  133. package/src/modules/arch/tabset/tabset.html +62 -0
  134. package/src/modules/arch/tabset/tabset.ts +244 -0
  135. package/src/modules/arch/testutils.ts +118 -0
  136. package/src/modules/arch/threeCardGrid/threeCardGrid.css +6 -0
  137. package/src/modules/arch/threeCardGrid/threeCardGrid.html +5 -0
  138. package/src/modules/arch/threeCardGrid/threeCardGrid.ts +3 -0
  139. package/src/modules/arch/track/track.ts +23 -0
  140. package/src/modules/arch/trailhead.ts +120 -0
  141. package/src/modules/arch/types.d.ts +1 -0
  142. package/src/modules/arch/useEffectAttr.ts +16 -0
  143. package/src/modules/arch/utils/utils.ts +20 -0
  144. package/src/modules/arch/withState.ts +21 -0
  145. package/src/modules/arch/xsfMfeEvents/xsfMfeEvents.html +1 -0
  146. package/src/modules/arch/xsfMfeEvents/xsfMfeEvents.ts +47 -0
  147. package/src/modules/arch/slot/slot.ts +0 -21
@@ -0,0 +1,169 @@
1
+ import { api, LightningElement, track } from 'lwc';
2
+ import { createImageUrl, sendInteractionEvent, InteractionEventTypes } from 'arch/helpers';
3
+
4
+ const ARCHITECT_BASE_REGEX = /^https?:\/\/([\w-]*\.)?architect/; // matches roughly any subdomain of architect
5
+
6
+ export default class extends LightningElement {
7
+ private observer!: MutationObserver;
8
+ private didSetContent = false;
9
+
10
+ @api socialTitle: string | null = null;
11
+ @api lastUpdated: string | null = null;
12
+ @api readingTime: string | null = null;
13
+ @api navHidden: string | null = null;
14
+ @api imageHash: string | null = null;
15
+
16
+ @track private headings: {
17
+ href: string;
18
+ id: string;
19
+ label: string;
20
+ }[] = [];
21
+
22
+ private get showHeadingsNav() {
23
+ return this.navHidden === null && this.headings.length > 0;
24
+ }
25
+
26
+ private get rootClassName() {
27
+ return 'root';
28
+ }
29
+
30
+ connectedCallback() {
31
+ this.observer = new MutationObserver(() => {
32
+ this.setContent();
33
+ });
34
+ this.observer.observe(this.template.host, {
35
+ characterData: true,
36
+ childList: true,
37
+ subtree: true
38
+ });
39
+ this.setContent();
40
+ const that = this;
41
+ window.addEventListener('hashchange', function locationHashChanged() {
42
+ const heading: HTMLElement | null = that.template.querySelector(`[id="${window.location.hash.substring(1)}"]`);
43
+ if (heading) {
44
+ heading.style.scrollMarginTop = `var(--dx-g-global-header-height)`; // required adjustment for global nav
45
+ heading.scrollIntoView({
46
+ behavior: 'instant', // we can't use smooth here anymore, because the global nav MFE resizes itself and messes up scrolling
47
+ block: "start",
48
+ });
49
+ }
50
+ });
51
+ }
52
+
53
+ disconnectedCallback() {
54
+ this.observer.disconnect();
55
+ }
56
+
57
+ renderedCallback() {
58
+ if (!this.didSetContent) {
59
+ this.didSetContent = true;
60
+ this.setContent();
61
+ if (window.location.hash) {
62
+ this.scrollToHash(window.location.hash);
63
+ }
64
+ }
65
+ }
66
+
67
+ private onHeadingClick(e: MouseEvent) {
68
+ const anchor = e.currentTarget as HTMLAnchorElement;
69
+ this.scrollToHash(anchor.hash);
70
+ }
71
+
72
+ private onContentClick(e: MouseEvent) {
73
+ const element = e.target as HTMLElement;
74
+ const targetIsImage =
75
+ element instanceof HTMLImageElement &&
76
+ element.parentElement instanceof HTMLAnchorElement;
77
+
78
+ if (element instanceof HTMLAnchorElement || targetIsImage) {
79
+ const anchorEl = targetIsImage ? element.parentElement : element;
80
+ const url = new URL(
81
+ anchorEl.href || element.src,
82
+ window.location.protocol + '//' + window.location.host
83
+ );
84
+ const filename = url.pathname.substr(
85
+ url.pathname.lastIndexOf('/') + 1
86
+ );
87
+
88
+ if (anchorEl.hasAttribute('download') || filename.includes('.')) {
89
+ const regexImg = new RegExp(/[^\s]+(.*?).(jpg|jpeg|png|gif|JPG|JPEG|PNG|GIF|webp)$/);
90
+ if (regexImg.test(filename)) {
91
+ sendInteractionEvent('Image Click', InteractionEventTypes.IMAGE_CLICK, e, element)
92
+ } else {
93
+ sendInteractionEvent('File Download', InteractionEventTypes.FILE_DOWNLOAD, e, anchorEl)
94
+ }
95
+ } else if (anchorEl.target) {
96
+ sendInteractionEvent('Link Click', InteractionEventTypes.CLICK, e, anchorEl);
97
+ }
98
+ }
99
+ }
100
+
101
+ private scrollToHash(hash: string) {
102
+ const heading: HTMLElement | null = this.template.querySelector(`[id="${hash.split('?')[0].substring(1)}"]`);
103
+ if (heading) {
104
+ heading.style.scrollMarginTop = `var(--dx-g-global-header-height)`; // required adjustment for global nav
105
+ heading.scrollIntoView({
106
+ behavior: "instant",
107
+ block: "start",
108
+ });
109
+ }
110
+ }
111
+
112
+ private setContent() {
113
+ const main = this.template.querySelector('main');
114
+ if (main) {
115
+ main.innerHTML = this.template.host.innerHTML.replace(
116
+ /(<table>[\s\S]+?<\/table>)/g,
117
+ `<div class="table">$1</div>`
118
+ );
119
+ this.headings = Array.from(main.querySelectorAll('h2,h3')).map(
120
+ (n) => {
121
+ const label = n.innerText.trim();
122
+ const id = label.replace(/[^a-zA-Z0-9]/g, '_');
123
+ const href = `#${id}`;
124
+ const style =
125
+ n.tagName === 'H3' ? 'padding-left: 1.25rem' : '';
126
+ // Side effects in map ftw
127
+ n.id = id;
128
+ return { href, id, label, style };
129
+ }
130
+ );
131
+ Array.from(main.querySelectorAll('a')).forEach((el) => {
132
+ if (
133
+ !el.href.startsWith('/') &&
134
+ !ARCHITECT_BASE_REGEX.test(el.href) &&
135
+ !el.href.startsWith('about:blank#') &&
136
+ !el.href.startsWith('http://localhost') &&
137
+ !el.href.startsWith('https://sfdc.co') &&
138
+ !el.href.startsWith('https://sf-archs.cdn.salesforce-experience.com') &&
139
+ !el.href.includes('herokuapp.com')
140
+ ) {
141
+ const doc = el.ownerDocument;
142
+ const img = doc.createElement('img');
143
+ img.src = 'https://a.sfdcstatic.com/developer-website/images/architect/new_window.svg';
144
+ img.style =
145
+ 'display: inline;height: 1.2rem;margin:0 0 0 5px;';
146
+ img.alt = 'Open link in new window';
147
+ el.appendChild(img);
148
+ el.target = '_blank';
149
+ el.rel = 'noopener';
150
+ }
151
+ });
152
+ Array.from(main.querySelectorAll('img')).forEach((el) => {
153
+ el.src = createImageUrl(el.src, this.imageHash);
154
+ });
155
+ }
156
+ }
157
+
158
+ private get showScroll() {
159
+ return parseInt(this.readingTime, 10) > 4;
160
+ }
161
+
162
+ private onScrollClick() {
163
+ window.scroll({
164
+ top: 0,
165
+ left: 0,
166
+ behavior: 'smooth'
167
+ });
168
+ }
169
+ }
@@ -0,0 +1,48 @@
1
+ @import "arch/reset";
2
+
3
+ .image-container {
4
+ border-radius: var(--arch-radius-lg);
5
+ position: relative;
6
+ }
7
+
8
+ .image {
9
+ border-radius: var(--arch-radius-lg);
10
+ display: block;
11
+ height: 100%;
12
+ object-fit: cover;
13
+ width: 100%;
14
+ }
15
+
16
+ .icon {
17
+ align-self: center;
18
+ color: var(--arch-color-white);
19
+ display: flex;
20
+ background-color: var(--arch-color-evergreen);
21
+ border-radius: var(--arch-radius-full);
22
+ border: 3px solid var(--arch-color-white);
23
+ box-sizing: border-box;
24
+ justify-content: center;
25
+ height: var(--size);
26
+ position: absolute;
27
+ right: -10px;
28
+ top: -4px;
29
+ width: var(--size);
30
+ }
31
+
32
+ .icon-small,
33
+ .icon-medium {
34
+ --size: 30px;
35
+ }
36
+
37
+ .icon-large,
38
+ .icon-xlarge {
39
+ --size: 38px;
40
+ }
41
+
42
+ .icon-svg {
43
+ --icon-size: 100%;
44
+
45
+ height: 60%;
46
+ margin: auto;
47
+ width: 60%;
48
+ }
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <div class="image-container" style={imageContainerStyles}>
3
+ <img src={src} class="image" alt="" loading="lazy" decoding="async" />
4
+ <template if:true={checked}>
5
+ <div class={iconClassName}>
6
+ <arch-icon
7
+ class="icon-svg"
8
+ size="override"
9
+ sprite="action"
10
+ symbol="check"
11
+ ></arch-icon>
12
+ </div>
13
+ </template>
14
+ </div>
15
+ </template>
@@ -0,0 +1,130 @@
1
+ import { html } from "lit-html";
2
+
3
+ export default {
4
+ title: "arch/arch-content-icon",
5
+ component: "sb-arch-content-icon"
6
+ };
7
+
8
+ // prettier-ignore
9
+ const createStyles = () => html `
10
+ <style>
11
+ sb-arch-content-icon {
12
+ display: block;
13
+ }
14
+ </style>`;
15
+
16
+ // prettier-ignore
17
+ export const Base = () => html` ${createStyles()}
18
+ <sb-arch-content-icon src="/images/badge-1.png"></sb-arch-content-icon>
19
+ `;
20
+
21
+ // prettier-ignore
22
+ export const BaseChecked = () => html` ${createStyles()}
23
+ <sb-arch-content-icon
24
+ .checked=${true}
25
+ src="/images/badge-1.png"
26
+ ></sb-arch-content-icon>
27
+ `;
28
+
29
+ // prettier-ignore
30
+ export const BaseSmall = () => html` ${createStyles()}
31
+ <sb-arch-content-icon size="small" src="/images/badge-1.png"></sb-arch-content-icon>
32
+ `;
33
+
34
+ // prettier-ignore
35
+ export const BaseSmallChecked = () => html` ${createStyles()}
36
+ <sb-arch-content-icon
37
+ .checked=${true}
38
+ size="small"
39
+ src="/images/badge-1.png"
40
+ ></sb-arch-content-icon>
41
+ `;
42
+
43
+ // prettier-ignore
44
+ export const BaseLarge = () => html` ${createStyles()}
45
+ <sb-arch-content-icon size="large" src="/images/badge-1.png"></sb-arch-content-icon>
46
+ `;
47
+
48
+ // prettier-ignore
49
+ export const BaseLargeChecked = () => html` ${createStyles()}
50
+ <sb-arch-content-icon
51
+ .checked=${true}
52
+ size="large"
53
+ src="/images/badge-1.png"
54
+ ></sb-arch-content-icon>
55
+ `;
56
+
57
+ // prettier-ignore
58
+ export const BaseXLarge = () => html` ${createStyles()}
59
+ <sb-arch-content-icon
60
+ size="xlarge"
61
+ src="/images/badge-1.png"
62
+ ></sb-arch-content-icon>
63
+ `;
64
+
65
+ // prettier-ignore
66
+ export const BaseXLargeChecked = () => html` ${createStyles()}
67
+ <sb-arch-content-icon
68
+ .checked=${true}
69
+ size="xlarge"
70
+ src="/images/badge-1.png"
71
+ ></sb-arch-content-icon>
72
+ `;
73
+
74
+ // prettier-ignore
75
+ export const Trail = () => html` ${createStyles()}
76
+ <sb-arch-content-icon
77
+ .background=${true}
78
+ color="rgb(221, 49, 49)"
79
+ src="/images/badge-trail-1.png"
80
+ ></sb-arch-content-icon>
81
+ `;
82
+
83
+ // prettier-ignore
84
+ export const TrailChecked = () => html` ${createStyles()}
85
+ <sb-arch-content-icon
86
+ .background=${true}
87
+ color="rgb(221, 49, 49)"
88
+ .checked=${true}
89
+ src="/images/badge-trail-1.png"
90
+ ></sb-arch-content-icon>
91
+ `;
92
+
93
+ // prettier-ignore
94
+ export const TrailSmall = () => html` ${createStyles()}
95
+ <sb-arch-content-icon
96
+ .background=${true}
97
+ color="rgb(221, 49, 49)"
98
+ size="small"
99
+ src="/images/badge-trail-1.png"
100
+ ></sb-arch-content-icon>
101
+ `;
102
+
103
+ // prettier-ignore
104
+ export const TrailLarge = () => html` ${createStyles()}
105
+ <sb-arch-content-icon
106
+ .background=${true}
107
+ color="rgb(221, 49, 49)"
108
+ size="large"
109
+ src="/images/badge-trail-1.png"
110
+ ></sb-arch-content-icon>
111
+ `;
112
+
113
+ // prettier-ignore
114
+ export const Trailmix = () => html` ${createStyles()}
115
+ <sb-arch-content-icon
116
+ .background=${true}
117
+ size="large"
118
+ src="/images/trailblazer-1.png"
119
+ ></sb-arch-content-icon>
120
+ `;
121
+
122
+ // prettier-ignore
123
+ export const TrailmixComplete = () => html` ${createStyles()}
124
+ <sb-arch-content-icon
125
+ .background=${true}
126
+ size="large"
127
+ .checked=${true}
128
+ src="/images/trailblazer-1.png"
129
+ ></sb-arch-content-icon>
130
+ `;
@@ -0,0 +1,68 @@
1
+ import { api, LightningElement } from 'lwc';
2
+
3
+ export default class extends LightningElement {
4
+ @api background: boolean = false;
5
+ @api checked: boolean = false;
6
+ @api color: string | null = null;
7
+ @api size: 'small' | 'medium' | 'large' | 'xlarge' = 'medium';
8
+ _src: string;
9
+
10
+ @api
11
+ get src() {
12
+ return this._src;
13
+ }
14
+ set src(value) {
15
+ const cms = value?.indexOf('sf-archs');
16
+ if (cms !== -1) {
17
+ this._src = `https://${value.substring(value.indexOf('sf-archs'))}`;
18
+ } else {
19
+ this._src = value;
20
+ }
21
+ }
22
+ private get imageSize() {
23
+ switch (this.size) {
24
+ case 'small':
25
+ return 64;
26
+ case 'medium':
27
+ return 72;
28
+ case 'large':
29
+ return 96;
30
+ case 'xlarge':
31
+ return 128;
32
+ default:
33
+ return 72;
34
+ }
35
+ }
36
+
37
+ private get imageContainerStyles() {
38
+ const styles = `height: ${this.imageSize}px; width: ${this.imageSize}px;`;
39
+ if (this.background) {
40
+ return [styles, `background-color: ${this.color};`].join(' ');
41
+ }
42
+ return styles;
43
+ }
44
+
45
+ private get iconClassName() {
46
+ return `icon icon--${this.size}`;
47
+ }
48
+
49
+ private get imgSrcSetWebP() {
50
+ const imgType = this.src.split('.').pop();
51
+ const imgName = this.src.replace(`.${imgType}`, '');
52
+ return `${imgName}-search.webp 75w`;
53
+ }
54
+
55
+ private get imgSrcSetJpg() {
56
+ const imgType = this.src.split('.').pop();
57
+ const imgName = this.src.replace(`.${imgType}`, '');
58
+ return `${imgName}-search.jpg 75w`;
59
+ }
60
+
61
+ private get imgTagNoSvg() {
62
+ return !this.src.toLowerCase().endsWith('svg');
63
+ }
64
+
65
+ private get imgTagSvg() {
66
+ return this.src.toLowerCase().endsWith('svg');
67
+ }
68
+ }
@@ -11,7 +11,7 @@ import {
11
11
  import { EffectAdapter } from "arch/effectAdapter";
12
12
 
13
13
  export interface ContextWireAdapter<Value, Config, Context>
14
- extends WireAdapter<Value, Config, Context> {
14
+ extends WireAdapter<Config, Context> {
15
15
  value: Value;
16
16
  }
17
17
  export interface ContextWireAdapterConstructor<Value, Config, Context> {
@@ -0,0 +1 @@
1
+ export const DEFAULT_LOCALE = 'en';
@@ -0,0 +1 @@
1
+ <template></template>
@@ -0,0 +1,54 @@
1
+ import { Locale } from 'arch/i18n';
2
+ import { DEFAULT_LOCALE } from './constants';
3
+ import { createContextAdapter } from 'arch/context';
4
+
5
+ type Nullable<T> = T | null;
6
+
7
+ export type ContextAdapterValue = {
8
+ crossOriginAssets: boolean;
9
+ assetsUrl: string;
10
+ locale: Locale;
11
+ };
12
+
13
+ export type ContextAdapterConfig = {
14
+ crossOriginAssets?: Nullable<boolean>;
15
+ assetsUrl?: Nullable<string>;
16
+ locale?: Nullable<Locale>;
17
+ };
18
+
19
+ export type ContextAdapterContext = {
20
+ crossOriginAssets?: Nullable<boolean>;
21
+ assetsUrl?: Nullable<string>;
22
+ locale?: Nullable<Locale>;
23
+ };
24
+
25
+ export const ContextAdapter = createContextAdapter<
26
+ ContextAdapterValue,
27
+ ContextAdapterConfig,
28
+ ContextAdapterContext
29
+ >(
30
+ () => {
31
+ return {
32
+ crossOriginAssets: process.env.CROSS_ORIGIN_ASSETS === 'true',
33
+ // See `rollup.config.js` for more explanation of this variable
34
+ // If set, we trim everything after /modules to get the absolute assets url on `th-components`
35
+ // If not, we default to the relative assets url on `th-components`
36
+ assetsUrl: process.env.IMPORT_META_URL
37
+ ? String(process.env.IMPORT_META_URL).replace(/\/modules.*/, '')
38
+ : '/assets/images',
39
+ locale: getDefaultLocale()
40
+ };
41
+ },
42
+ {
43
+ assetsUrl: 'optional',
44
+ crossOriginAssets: 'optional',
45
+ locale: 'optional'
46
+ }
47
+ );
48
+
49
+ export const { setGlobalContext, setDefaultValue } = ContextAdapter;
50
+
51
+ function getDefaultLocale() {
52
+ // @ts-ignore
53
+ return window.locale || DEFAULT_LOCALE;
54
+ }
@@ -0,0 +1,32 @@
1
+ type Procedure = (...args: any[]) => void;
2
+
3
+ type Options = {
4
+ isImmediate: boolean;
5
+ };
6
+
7
+ export function debounce<F extends Procedure>(
8
+ func: F,
9
+ waitMilliseconds = 50,
10
+ options: Options = {
11
+ isImmediate: false
12
+ }
13
+ ): F {
14
+ let timeoutId: ReturnType<typeof setTimeout> | undefined;
15
+ return function (this: any, ...args: any[]) {
16
+ const context = this;
17
+ const doLater = function () {
18
+ timeoutId = undefined;
19
+ if (!options.isImmediate) {
20
+ func.apply(context, args);
21
+ }
22
+ };
23
+ const shouldCallNow = options.isImmediate && timeoutId === undefined;
24
+ if (timeoutId !== undefined) {
25
+ clearTimeout(timeoutId);
26
+ }
27
+ timeoutId = setTimeout(doLater, waitMilliseconds);
28
+ if (shouldCallNow) {
29
+ func.apply(context, args);
30
+ }
31
+ } as any;
32
+ }
@@ -0,0 +1,154 @@
1
+ import {
2
+ Instance as PopperInstance,
3
+ Placement as PopperPlacement
4
+ } from '@popperjs/core';
5
+
6
+ export type DialogState = {
7
+ isOpen?: boolean;
8
+ };
9
+
10
+ export type Placement =
11
+ | 'top'
12
+ | 'top left'
13
+ | 'top right'
14
+ | 'right'
15
+ | 'right top'
16
+ | 'right bottom'
17
+ | 'bottom'
18
+ | 'bottom left'
19
+ | 'bottom right'
20
+ | 'left'
21
+ | 'left top'
22
+ | 'left bottom';
23
+
24
+ const DEFAULT_PLACEMENT = 'top';
25
+ const NUBBIN_SIZE = 14;
26
+
27
+ export class Dialog {
28
+ constructor(
29
+ private trigger: HTMLElement,
30
+ private dialog: HTMLElement,
31
+ private options: {
32
+ placement?: Placement;
33
+ onChange?: (Partial: DialogState) => void;
34
+ } = {}
35
+ ) {
36
+ this.create();
37
+ }
38
+
39
+ popper: PopperInstance | null = null;
40
+
41
+ private _state: DialogState = { isOpen: false };
42
+
43
+ get state(): DialogState {
44
+ return this._state;
45
+ }
46
+
47
+ set state(nextState: DialogState) {
48
+ this._state = { ...this._state, ...nextState };
49
+
50
+ if (this.options.onChange) {
51
+ this.options.onChange(this.state);
52
+ }
53
+ }
54
+
55
+ private async create() {
56
+ const modifiers = [
57
+ {
58
+ name: 'flip',
59
+ options: {
60
+ padding: NUBBIN_SIZE
61
+ }
62
+ },
63
+ {
64
+ name: 'hide',
65
+ enabled: false
66
+ },
67
+ {
68
+ name: 'preventOverflow',
69
+ options: {
70
+ padding: {
71
+ top: 2,
72
+ bottom: 2,
73
+ left: 5,
74
+ right: 5
75
+ }
76
+ }
77
+ },
78
+ {
79
+ name: 'offset',
80
+ options: {
81
+ offset: ({ placement, reference }: any) => {
82
+ if (placement.match(/^(top|bottom)/)) {
83
+ return [0, NUBBIN_SIZE];
84
+ }
85
+
86
+ if (placement.match(/end?/)) {
87
+ return [(reference.height / 2) * 1, NUBBIN_SIZE];
88
+ }
89
+
90
+ if (placement.match(/start?/)) {
91
+ return [(reference.height / 2) * -1, NUBBIN_SIZE];
92
+ }
93
+
94
+ return [0, NUBBIN_SIZE];
95
+ }
96
+ }
97
+ }
98
+ ];
99
+ const { createPopper } = await import('@popperjs/core');
100
+
101
+ this.popper = createPopper(this.trigger, this.dialog, {
102
+ placement: this.getPlacement(this.options.placement),
103
+ modifiers
104
+ });
105
+
106
+ // Show
107
+ this.trigger.addEventListener('mouseenter', this.show.bind(this));
108
+ this.trigger.addEventListener('focusin', this.show.bind(this));
109
+
110
+ // Hide
111
+ this.trigger.addEventListener('mouseleave', this.hide.bind(this));
112
+ this.trigger.addEventListener('focusout', this.hide.bind(this));
113
+ }
114
+
115
+ destroy() {
116
+ this.popper!.destroy();
117
+ this.popper = null;
118
+ }
119
+
120
+ private async show() {
121
+ await this.popper!.update();
122
+ this.state = { isOpen: true };
123
+ }
124
+
125
+ private hide() {
126
+ this.state = { isOpen: false };
127
+ }
128
+
129
+ // Map the "placement" property used by SLDS to the correct Popper "placement"
130
+ private getPlacement(
131
+ placement: Placement = DEFAULT_PLACEMENT
132
+ ): PopperPlacement {
133
+ switch (placement) {
134
+ case 'top left':
135
+ return 'top-start';
136
+ case 'top right':
137
+ return 'top-end';
138
+ case 'right top':
139
+ return 'right-start';
140
+ case 'right bottom':
141
+ return 'right-end';
142
+ case 'bottom left':
143
+ return 'bottom-start';
144
+ case 'bottom right':
145
+ return 'bottom-end';
146
+ case 'left top':
147
+ return 'left-start';
148
+ case 'left bottom':
149
+ return 'left-end';
150
+ default:
151
+ return placement;
152
+ }
153
+ }
154
+ }