@salesforcedevs/arch-components 1.20.17-alpha8 → 1.25.0

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 (158) hide show
  1. package/LICENSE +12 -0
  2. package/lwc.config.json +42 -3
  3. package/package.json +36 -46
  4. package/src/assets/css/arch-variables.css +512 -0
  5. package/src/modules/arch/badge/badge.css +22 -0
  6. package/src/modules/arch/badge/badge.html +5 -0
  7. package/src/modules/arch/badge/badge.ts +9 -0
  8. package/src/modules/arch/button/button.css +1 -0
  9. package/src/modules/arch/button/button.html +20 -0
  10. package/src/modules/arch/button/button.ts +67 -0
  11. package/src/modules/arch/buttonLink/buttonLink.css +1 -0
  12. package/src/modules/arch/buttonLink/buttonLink.html +19 -0
  13. package/src/modules/arch/buttonLink/buttonLink.stories.js +34 -0
  14. package/src/modules/arch/buttonLink/buttonLink.ts +8 -0
  15. package/src/modules/arch/buttonStyles/buttonStyles.css +220 -0
  16. package/src/modules/arch/card/card.css +128 -0
  17. package/src/modules/arch/card/card.html +85 -0
  18. package/src/modules/arch/card/card.ts +277 -0
  19. package/src/modules/arch/cardBase/cardBase.css +11 -0
  20. package/src/modules/arch/cardBase/cardBase.html +2 -0
  21. package/src/modules/arch/cardGridA/cardGridA.css +11 -0
  22. package/src/modules/arch/cardGridA/cardGridA.html +21 -0
  23. package/src/modules/arch/cardGridA/cardGridA.stories.js +118 -0
  24. package/src/modules/arch/cardGridA/cardGridA.ts +24 -0
  25. package/src/modules/arch/cardGridC/cardGridC.css +24 -0
  26. package/src/modules/arch/cardGridC/cardGridC.html +22 -0
  27. package/src/modules/arch/cardGridC/cardGridC.stories.js +51 -0
  28. package/src/modules/arch/cardGridC/cardGridC.ts +11 -0
  29. package/src/modules/arch/cardGridD/cardGridD.css +17 -0
  30. package/src/modules/arch/cardGridD/cardGridD.html +20 -0
  31. package/src/modules/arch/cardGridD/cardGridD.stories.js +43 -0
  32. package/src/modules/arch/cardGridD/cardGridD.ts +7 -0
  33. package/src/modules/arch/cardNew/cardNew.css +31 -0
  34. package/src/modules/arch/cardNew/cardNew.html +32 -0
  35. package/src/modules/arch/cardNew/cardNew.ts +66 -0
  36. package/src/modules/arch/children/children.html +2 -0
  37. package/src/modules/arch/children/children.ts +31 -0
  38. package/src/modules/arch/color/color.ts +59 -0
  39. package/src/modules/arch/content/__fixtures__/index.ts +884 -0
  40. package/src/modules/arch/content/content.css +643 -0
  41. package/src/modules/arch/content/content.html +65 -0
  42. package/src/modules/arch/content/content.stories.js +21 -0
  43. package/src/modules/arch/content/content.ts +169 -0
  44. package/src/modules/arch/contentIcon/contentIcon.css +48 -0
  45. package/src/modules/arch/contentIcon/contentIcon.html +15 -0
  46. package/src/modules/arch/contentIcon/contentIcon.stories.js +130 -0
  47. package/src/modules/arch/contentIcon/contentIcon.ts +68 -0
  48. package/src/{common → modules/arch}/context/context.ts +21 -19
  49. package/src/modules/arch/contextAdapter/constants.ts +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.html +1 -0
  55. package/src/modules/arch/effectAdapter/effectAdapter.ts +28 -0
  56. package/src/modules/arch/explorer/explorer.css +301 -0
  57. package/src/modules/arch/explorer/explorer.html +418 -0
  58. package/src/modules/arch/explorer/explorer.ts +718 -0
  59. package/src/modules/arch/explorer/types.d.ts +60 -0
  60. package/src/modules/arch/fetch/fetch.ts +55 -0
  61. package/src/modules/arch/footerMfe/footerMfe.html +3 -0
  62. package/src/modules/arch/footerMfe/footerMfe.ts +19 -0
  63. package/src/modules/arch/gallery/gallery.css +365 -0
  64. package/src/modules/arch/gallery/gallery.html +71 -0
  65. package/src/modules/arch/gallery/gallery.ts +366 -0
  66. package/src/modules/arch/gallery/types.d.ts +35 -0
  67. package/src/modules/arch/heading/heading.css +1 -0
  68. package/src/modules/arch/heading/heading.html +9 -0
  69. package/src/modules/arch/heading/heading.ts +36 -0
  70. package/src/modules/arch/helpers/helpers.ts +141 -0
  71. package/src/modules/arch/heroA/heroA.css +116 -0
  72. package/src/modules/arch/heroA/heroA.html +28 -0
  73. package/src/modules/arch/heroA/heroA.stories.js +60 -0
  74. package/src/modules/arch/heroA/heroA.ts +53 -0
  75. package/src/modules/arch/heroB/heroB.css +79 -0
  76. package/src/modules/arch/heroB/heroB.html +27 -0
  77. package/src/modules/arch/heroB/heroB.stories.js +55 -0
  78. package/src/modules/arch/heroB/heroB.ts +26 -0
  79. package/src/modules/arch/i18n/i18n.ts +78 -0
  80. package/src/modules/arch/icon/icon.css +28 -0
  81. package/src/modules/arch/icon/icon.html +17 -0
  82. package/src/modules/arch/icon/icon.stories.js +26 -0
  83. package/src/modules/arch/icon/icon.ts +92 -0
  84. package/src/modules/arch/instrumentation/instrumentation.css +1 -0
  85. package/src/modules/arch/instrumentation/instrumentation.html +1 -0
  86. package/src/modules/arch/instrumentation/instrumentation.ts +113 -0
  87. package/src/modules/arch/labels/helpers.ts +25 -0
  88. package/src/modules/arch/labels/pointHelpers.ts +47 -0
  89. package/src/modules/arch/labels/timeHelpers.ts +182 -0
  90. package/src/modules/arch/labels/types.d.ts +5 -0
  91. package/src/modules/arch/logger/logger.ts +33 -0
  92. package/src/modules/arch/menu/menu.ts +260 -0
  93. package/src/modules/arch/overflow/overflow.ts +71 -0
  94. package/src/modules/arch/page/page.css +3 -0
  95. package/src/modules/arch/page/page.html +3 -0
  96. package/src/modules/arch/page/page.stories.js +19 -0
  97. package/src/modules/arch/page/page.ts +3 -0
  98. package/src/modules/arch/pageHeaderA/pageHeaderA.css +82 -0
  99. package/src/modules/arch/pageHeaderA/pageHeaderA.html +24 -0
  100. package/src/modules/arch/pageHeaderA/pageHeaderA.stories.js +25 -0
  101. package/src/modules/arch/pageHeaderA/pageHeaderA.ts +51 -0
  102. package/src/modules/arch/pill/pill.css +70 -0
  103. package/src/modules/arch/pill/pill.html +17 -0
  104. package/src/modules/arch/pill/pill.ts +34 -0
  105. package/src/modules/arch/polling-request.ts +97 -0
  106. package/src/modules/arch/reflectedElement/reflectedElement.html +2 -0
  107. package/src/{common → modules/arch}/reflectedElement/reflectedElement.ts +5 -3
  108. package/src/modules/arch/reset/reset.css +39 -0
  109. package/src/modules/arch/searchList/searchList.css +120 -0
  110. package/src/modules/arch/searchList/searchList.html +46 -0
  111. package/src/modules/arch/searchList/searchList.ts +53 -0
  112. package/src/modules/arch/sectionA/sectionA.css +64 -0
  113. package/src/modules/arch/sectionA/sectionA.html +21 -0
  114. package/src/modules/arch/sectionA/sectionA.stories.js +25 -0
  115. package/src/modules/arch/sectionA/sectionA.ts +27 -0
  116. package/src/modules/arch/select/select.css +40 -0
  117. package/src/modules/arch/select/select.html +24 -0
  118. package/src/modules/arch/select/select.ts +64 -0
  119. package/src/modules/arch/socialShare/socialShare.css +50 -0
  120. package/src/modules/arch/socialShare/socialShare.html +56 -0
  121. package/src/modules/arch/socialShare/socialShare.ts +29 -0
  122. package/src/modules/arch/spinner/spinner.css +195 -0
  123. package/src/modules/arch/spinner/spinner.html +9 -0
  124. package/src/modules/arch/spinner/spinner.ts +15 -0
  125. package/src/modules/arch/styles/styles.css +24 -0
  126. package/src/modules/arch/summary/summary.css +134 -0
  127. package/src/modules/arch/summary/summary.html +71 -0
  128. package/src/modules/arch/summary/summary.stories.js +163 -0
  129. package/src/modules/arch/summary/summary.ts +96 -0
  130. package/src/modules/arch/tab/tab.css +3 -0
  131. package/src/modules/arch/tab/tab.html +5 -0
  132. package/src/modules/arch/tab/tab.ts +46 -0
  133. package/src/modules/arch/tabset/tabset.css +112 -0
  134. package/src/modules/arch/tabset/tabset.html +62 -0
  135. package/src/modules/arch/tabset/tabset.ts +244 -0
  136. package/src/modules/arch/testutils.ts +118 -0
  137. package/src/modules/arch/threeCardGrid/threeCardGrid.css +6 -0
  138. package/src/modules/arch/threeCardGrid/threeCardGrid.html +5 -0
  139. package/src/modules/arch/threeCardGrid/threeCardGrid.ts +3 -0
  140. package/src/modules/arch/track/track.ts +23 -0
  141. package/src/modules/arch/trailhead.ts +120 -0
  142. package/src/modules/arch/types.d.ts +1 -0
  143. package/src/modules/arch/useEffectAttr.ts +16 -0
  144. package/src/modules/arch/utils/utils.ts +20 -0
  145. package/src/modules/arch/withState.ts +21 -0
  146. package/src/modules/arch/xsfMfeEvents/xsfMfeEvents.html +1 -0
  147. package/src/modules/arch/xsfMfeEvents/xsfMfeEvents.ts +47 -0
  148. package/src/common/effectAdapter/__tests__/effectAdapter.test.ts +0 -12
  149. package/src/common/effectAdapter/effectAdapter.ts +0 -18
  150. package/src/common/reflectedElement/__tests__/modules/test/select/select.html +0 -3
  151. package/src/common/reflectedElement/__tests__/modules/test/select/select.ts +0 -7
  152. package/src/common/reflectedElement/__tests__/modules/test/selectTransform/selectTransform.html +0 -3
  153. package/src/common/reflectedElement/__tests__/modules/test/selectTransform/selectTransform.ts +0 -18
  154. package/src/common/reflectedElement/__tests__/reflectedElement.test.ts +0 -75
  155. package/src/common/slot/__tests__/slot.test.ts +0 -96
  156. package/src/common/slot/slot.ts +0 -20
  157. /package/src/{common → modules/arch}/context/context.html +0 -0
  158. /package/src/{common/effectAdapter/effectAdapter.html → modules/arch/contextAdapter/contextAdapter.html} +0 -0
@@ -0,0 +1,366 @@
1
+ import { LightningElement, api } from "lwc";
2
+ import { Card } from "arch/card";
3
+ import { FilterOption } from "./types";
4
+ import { sendInteractionEvent, InteractionEventTypes } from "arch/helpers";
5
+ import { debounce } from "arch/debounce";
6
+
7
+ // function to get the cards array from the json payload
8
+ async function getGridCards(data, imageHash) {
9
+ const parsedData = JSON.parse(data);
10
+ // Sort the data based on the `sort` value
11
+ parsedData.sort((a, b) => a.sort - b.sort);
12
+ // load the gallery cards
13
+ return parsedData.map((item) => {
14
+ const card: Card = {
15
+ assistiveText: "Click here to go to this resource",
16
+ //ctaTitle: "Read More",
17
+ ctaTarget: null,
18
+ pretitleHref: null,
19
+ pretitleHrefText: null
20
+ };
21
+
22
+ // Dynamically set all other properties based on the data object
23
+ for (const prop in item) {
24
+ if (Object.prototype.hasOwnProperty.call(item, prop)) {
25
+ switch (prop) {
26
+ case "url":
27
+ card.ctaHref = item[prop];
28
+ break;
29
+ default:
30
+ card[prop] = item[prop];
31
+ }
32
+ }
33
+ }
34
+
35
+ // Set imgSrc to thumbnail if it exists, otherwise use image
36
+ if (item.thumbnail) {
37
+ // Use thumbnail as-is if it's a full URL (starts with http), otherwise prepend asset path
38
+ if (item.thumbnail.startsWith("http")) {
39
+ card.imgSrc = item.thumbnail;
40
+ } else {
41
+ card.imgSrc = `/1/asset/immutable/s/${imageHash}${item.thumbnail}`;
42
+ }
43
+ } else if (item.image) {
44
+ card.imgSrc = item.image;
45
+ }
46
+
47
+ return card;
48
+ });
49
+ }
50
+ export default class gallery extends LightningElement {
51
+ // get the inputs from the config
52
+ _content: string | null = null;
53
+ _filterData;
54
+ _filterProperty;
55
+ _filterLabel;
56
+ _searchTitle;
57
+ _imageHash: string | null = null;
58
+ @api containerId: string;
59
+
60
+ // second filter drop down is optional and pulled from the json data set
61
+ _showMetaFilter = false;
62
+ _metaFilterProperty;
63
+ _metaFilterLabel;
64
+
65
+ // get the inputs from the form
66
+ _selectFilter: string = "";
67
+ _keywordFilter: string = "";
68
+ _selectMetaFilter: string = "";
69
+
70
+ // set up the outputs
71
+ allCards: Card[] = [];
72
+ filteredCards: Card[] = [];
73
+ shareUrl = window.location.href;
74
+
75
+ // prep the filters options
76
+ filterOptions: FilterOption[] = [];
77
+ metaFilterOptions: FilterOption[] = [];
78
+
79
+ // populate the filter drop down
80
+ connectedCallback() {
81
+ // Check if we're on the data model gallery page
82
+ if (
83
+ this.containerId === "data-model-gallery" &&
84
+ window.location.hash === "#data-model-gallery"
85
+ ) {
86
+ window.location.href =
87
+ "https://developer.salesforce.com/docs/platform/data-models/guide/get-started.html";
88
+ }
89
+ }
90
+ get socialTitle() {
91
+ //Search title is plurar, removing last letter to make the title singular (should be a letter S)
92
+ return `${this._searchTitle.substring(
93
+ 0,
94
+ this._searchTitle.length - 1
95
+ )} Gallery`;
96
+ }
97
+
98
+ // fetch the filter data from a url
99
+ async fetchFilterData() {
100
+ try {
101
+ const response = await fetch(this._filterData);
102
+ const data = await response.json();
103
+ this.filterOptions = data as FilterOption[];
104
+ } catch (error) {
105
+ console.error(
106
+ "An error occurred getting the filter list:",
107
+ error.message
108
+ );
109
+ }
110
+ }
111
+
112
+ // handle the filter selection change
113
+ filterChange(evt: { detail: string }) {
114
+ this._selectFilter = evt.detail;
115
+ this.applyFilters();
116
+ }
117
+
118
+ private sendInteractionEvent = debounce((event, target) => {
119
+ sendInteractionEvent(
120
+ "Gallery Search",
121
+ InteractionEventTypes.INPUT_CHANGE,
122
+ event,
123
+ target
124
+ );
125
+ }, 1000);
126
+
127
+ // handle typing in the search box
128
+ keywordFilterChange(evt: InputEvent) {
129
+ const target = evt.currentTarget as HTMLInputElement;
130
+ this.sendInteractionEvent(evt, target);
131
+ this._keywordFilter = (evt.currentTarget as HTMLInputElement).value;
132
+ this.applyFilters();
133
+ }
134
+
135
+ // handle the filter selection change
136
+ metaFilterChange(evt: { detail: string }) {
137
+ this._selectMetaFilter = evt.detail;
138
+ this.applyFilters();
139
+ }
140
+
141
+ // update the gallery based on filtering
142
+ async applyFilters() {
143
+ this.filteredCards = this.allCards.filter((card) => {
144
+ const isFilterMatch =
145
+ this._selectFilter === "" ||
146
+ card[this._filterProperty]
147
+ ?.toLowerCase()
148
+ .includes(this._selectFilter.toLocaleLowerCase());
149
+ const isMetaMatch = this._showMetaFilter
150
+ ? this._selectMetaFilter === "" ||
151
+ card[this._metaFilterProperty]
152
+ ?.toLowerCase()
153
+ .includes(this._selectMetaFilter.toLocaleLowerCase())
154
+ : true;
155
+ const isKeywordMatch =
156
+ this._keywordFilter === "" ||
157
+ (card.pretitle &&
158
+ card.pretitle
159
+ .toLowerCase()
160
+ .includes(this._keywordFilter.toLowerCase())) ||
161
+ (card.title &&
162
+ card.title
163
+ .toLowerCase()
164
+ .includes(this._keywordFilter.toLowerCase())) ||
165
+ (card.description &&
166
+ card.description
167
+ .toLowerCase()
168
+ .includes(this._keywordFilter.toLowerCase()));
169
+
170
+ if (isFilterMatch && isMetaMatch && isKeywordMatch) {
171
+ return true;
172
+ }
173
+ return false;
174
+ });
175
+
176
+ // Update page state so that we track filters in URL params
177
+ const params = new URLSearchParams();
178
+
179
+ if (this._selectFilter !== "") {
180
+ params.set(this._filterLabel, this._selectFilter);
181
+ }
182
+ if (this._showMetaFilter && this._selectMetaFilter !== "") {
183
+ params.set(this._metaFilterLabel, this._selectMetaFilter);
184
+ }
185
+ if (this._keywordFilter !== "") {
186
+ params.set("keywords", this._keywordFilter);
187
+ }
188
+
189
+ const paramsString = params.toString();
190
+ let updatedUrl = window.location.pathname;
191
+
192
+ // Update the hash to the containerId if it's been filtered or from the URL on load
193
+ const urlHash = this.containerId
194
+ ? `#${this.containerId}`
195
+ : window.location.hash.split("?")[0];
196
+
197
+ if (urlHash) {
198
+ updatedUrl += urlHash;
199
+ }
200
+ if (paramsString) {
201
+ updatedUrl += `?${paramsString}`;
202
+ }
203
+
204
+ window.history.replaceState(
205
+ window.history.state,
206
+ document.title,
207
+ updatedUrl
208
+ );
209
+ this.shareUrl = `${window.location.protocol}//${window.location.hostname}${updatedUrl}`;
210
+
211
+ // Scrolls to container element to keep new data in focus.
212
+ if (urlHash) {
213
+ const targetElement = document.querySelector(
214
+ `#${this.containerId}`
215
+ );
216
+ // Scroll to the target element if it exists
217
+ if (targetElement) {
218
+ targetElement.scrollIntoView({ behavior: "smooth" });
219
+ }
220
+ }
221
+ }
222
+
223
+ checkURLParams() {
224
+ // Load filters from URL params
225
+ let requireFilterUpdate = false;
226
+ const url = new URL(window.location.href.replace("#", ""));
227
+ const params = url.searchParams;
228
+ for (const [key, value] of params.entries()) {
229
+ switch (key) {
230
+ case this._filterLabel:
231
+ this._selectFilter = value;
232
+ requireFilterUpdate = true;
233
+ break;
234
+ case this._metaFilterLabel:
235
+ this._selectMetaFilter = value;
236
+ requireFilterUpdate = true;
237
+ break;
238
+ case "keywords":
239
+ this._keywordFilter = value;
240
+ requireFilterUpdate = true;
241
+ break;
242
+ default:
243
+ break;
244
+ }
245
+ }
246
+
247
+ return requireFilterUpdate;
248
+ }
249
+
250
+ handleResetFiltersClick() {
251
+ this._selectFilter = "";
252
+ if (this._showMetaFilter) {
253
+ this._selectMetaFilter = "";
254
+ }
255
+ this._keywordFilter = "";
256
+ this.applyFilters();
257
+ }
258
+
259
+ private updateCards() {
260
+ if (this._content && this._imageHash) {
261
+ try {
262
+ getGridCards(this._content, this._imageHash).then((res) => {
263
+ this.allCards = this.filteredCards = res;
264
+ if (this._showMetaFilter) {
265
+ const typesArr = [
266
+ ...new Set(this.allCards.map((item) => item.type))
267
+ ];
268
+ typesArr.sort((a, b) => a.localeCompare(b));
269
+ this.metaFilterOptions = typesArr.map((type) => ({
270
+ label: type,
271
+ value: type
272
+ })) as FilterOption[];
273
+ }
274
+ if (this.checkURLParams()) {
275
+ this.applyFilters();
276
+ }
277
+ });
278
+ } catch (error) {
279
+ console.error(
280
+ "An error occurred getting the cards:",
281
+ error.message
282
+ );
283
+ }
284
+ }
285
+ }
286
+
287
+ // bind the config to the variables
288
+ @api
289
+ set searchtitle(value) {
290
+ if (this._searchTitle !== value) {
291
+ this._searchTitle = value;
292
+ }
293
+ }
294
+ get searchtitle() {
295
+ return this._searchTitle;
296
+ }
297
+
298
+ @api
299
+ set imageHash(value) {
300
+ this._imageHash = value;
301
+ this.updateCards();
302
+ }
303
+ get imageHash() {
304
+ return this._imageHash;
305
+ }
306
+
307
+ @api
308
+ set content(value) {
309
+ this._content = value;
310
+ this.updateCards();
311
+ }
312
+ get content() {
313
+ return this._content;
314
+ }
315
+
316
+ @api
317
+ set filter(value) {
318
+ if (this._filterData !== value) {
319
+ this._filterData = value;
320
+ if (!this._filterData.endsWith(".json")) {
321
+ this.filterOptions = JSON.parse(
322
+ this._filterData
323
+ ) as FilterOption[];
324
+ } else {
325
+ this.fetchFilterData();
326
+ }
327
+ }
328
+ }
329
+ get filter() {
330
+ return this._filterData;
331
+ }
332
+
333
+ @api
334
+ set property(value) {
335
+ if (this._filterProperty !== value) {
336
+ this._filterProperty = value;
337
+ }
338
+ }
339
+ get property() {
340
+ return this._filterProperty;
341
+ }
342
+
343
+ @api
344
+ set label(value) {
345
+ if (this._filterLabel !== value) {
346
+ this._filterLabel = value;
347
+ }
348
+ }
349
+ get label() {
350
+ return this._filterLabel;
351
+ }
352
+
353
+ // below is for getting and setting the optional second filter
354
+ @api
355
+ set metafilters(value) {
356
+ if (this._metaFilterProperty !== value) {
357
+ this._showMetaFilter = true;
358
+ this._metaFilterProperty = value;
359
+ this._metaFilterLabel =
360
+ value.charAt(0).toUpperCase() + value.slice(1);
361
+ }
362
+ }
363
+ get metafilters() {
364
+ return this._metaFilterProperty;
365
+ }
366
+ }
@@ -0,0 +1,35 @@
1
+ export type GalleryCard = {
2
+ id?: string;
3
+ pretitle: string | null;
4
+ title: string;
5
+ description: string;
6
+ image: string | null;
7
+ status?: string | null;
8
+ sort: number | null;
9
+ updated?: Date | null;
10
+ productAreas: string[];
11
+ url: string | null;
12
+ };
13
+
14
+ export type CardAttribute = string | null;
15
+ export type Card = {
16
+ assistiveText: CardAttribute;
17
+ ctaHref: CardAttribute;
18
+ ctaTarget: CardAttribute;
19
+ ctaTitle: CardAttribute;
20
+ description: CardAttribute;
21
+ imgSrc: CardAttribute;
22
+ pretitle: CardAttribute;
23
+ pretitleHref: CardAttribute;
24
+ pretitleHrefText: CardAttribute;
25
+ title: CardAttribute;
26
+ };
27
+
28
+ export type GalleryCards = {
29
+ items: Card[];
30
+ }
31
+
32
+ export type FilterOption = {
33
+ label: string;
34
+ value: string;
35
+ };
@@ -0,0 +1 @@
1
+ @import 'arch/reset';
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <h1 class="heading" if:true={isLevel1}><slot></slot></h1>
3
+ <h2 class="heading" if:true={isLevel2}><slot></slot></h2>
4
+ <h3 class="heading" if:true={isLevel3}><slot></slot></h3>
5
+ <h4 class="heading" if:true={isLevel4}><slot></slot></h4>
6
+ <h5 class="heading" if:true={isLevel5}><slot></slot></h5>
7
+ <h6 class="heading" if:true={isLevel6}><slot></slot></h6>
8
+ <template if:false={isHeading}><slot></slot></template>
9
+ </template>
@@ -0,0 +1,36 @@
1
+ import { api, LightningElement } from 'lwc';
2
+
3
+ export default class extends LightningElement {
4
+ // In the future, this could accept a value of "auto" which
5
+ // could traverse the DOM tree and figure out the appropriate level
6
+ @api level: '1' | '2' | '3' | '4' | '5' | '6' | null = null;
7
+
8
+ private get isHeading() {
9
+ // If "level" is null, we render a <slot> and with no heading
10
+ return this.level !== null;
11
+ }
12
+
13
+ private get isLevel1() {
14
+ return this.level === '1';
15
+ }
16
+
17
+ private get isLevel2() {
18
+ return this.level === '2';
19
+ }
20
+
21
+ private get isLevel3() {
22
+ return this.level === '3';
23
+ }
24
+
25
+ private get isLevel4() {
26
+ return this.level === '4';
27
+ }
28
+
29
+ private get isLevel5() {
30
+ return this.level === '5';
31
+ }
32
+
33
+ private get isLevel6() {
34
+ return this.level === '6';
35
+ }
36
+ }
@@ -0,0 +1,141 @@
1
+ export function attrToBool(attr: any) {
2
+ if (typeof attr === "boolean") {
3
+ return attr;
4
+ }
5
+ if (typeof attr === "string") {
6
+ return attr === "true" || attr === "";
7
+ }
8
+ return !!attr;
9
+ }
10
+
11
+ export function hash(value: string) {
12
+ let hashValue = 0;
13
+ for (let i = 0; i < value.length; i++) {
14
+ const char = value.charCodeAt(i);
15
+ hashValue = (hashValue << 5) - hashValue + char;
16
+ hashValue |= 0;
17
+ }
18
+ return hashValue;
19
+ }
20
+
21
+ export function createImageUrl(image: string, hashParam: string) {
22
+ if (image.startsWith("/assets")) {
23
+ const segments = image.split("/");
24
+ return `/1/asset/immutable/s/${hashParam}/$assetsDir/images/${
25
+ segments[segments.length - 1]
26
+ }`;
27
+ }
28
+ return image;
29
+ }
30
+
31
+ export const InteractionEventTypes = Object.freeze({
32
+ CLICK: "CLICK",
33
+ PAGE_VIEW: "PAGE_VIEW",
34
+ INPUT_CHANGE: "INPUT_CHANGE",
35
+ FILE_DOWNLOAD: "FILE_DOWNLOAD",
36
+ IMAGE_DOWNLOAD: "IMAGE_DOWNLOAD", //used with CDN
37
+ IMAGE_CLICK: "IMAGE_CLICK",
38
+ DROPDOWN_CHANGE: "DROPDOWN_CHANGE"
39
+ });
40
+ const channelActions = Object.freeze({
41
+ DOWNLOAD: "DOWNLOAD",
42
+ VIEW: "VIEW"
43
+ });
44
+ const channelActionsStatus = Object.freeze({
45
+ SUCCESS: "SUCCESS",
46
+ FAILURE: "FAILURE"
47
+ });
48
+ export function sendInteractionEvent(name, type, event, target?) {
49
+ const element = target || event.currentTarget;
50
+ let text: string = "";
51
+ let eventValue: string = "";
52
+ let channelAction: string = "";
53
+ const channelActionStatus: string = channelActionsStatus.SUCCESS;
54
+ const pageUrl = new URL(document.location.href);
55
+ const searchTitle = pageUrl.searchParams.get("keywords") || "";
56
+ if (
57
+ type === InteractionEventTypes.IMAGE_CLICK ||
58
+ type === InteractionEventTypes.FILE_DOWNLOAD
59
+ ) {
60
+ eventValue = element.href || element.src;
61
+ const url = new URL(
62
+ eventValue,
63
+ window.location.protocol + "//" + window.location.host
64
+ );
65
+ text = url.pathname.substr(url.pathname.lastIndexOf("/") + 1);
66
+ channelAction = channelActions.DOWNLOAD;
67
+ }
68
+ if (type === InteractionEventTypes.CLICK) {
69
+ eventValue = element.href || "";
70
+
71
+ let textNode = element;
72
+ if (element.firstChild.localName === "slot") {
73
+ textNode = element.firstChild
74
+ .assignedNodes()
75
+ .find((child) => child.textContent !== "");
76
+ }
77
+ text = element.ariaLabel || textNode.textContent || textNode.innerText;
78
+
79
+ if (eventValue.includes("/view/")) {
80
+ type = InteractionEventTypes.IMAGE_CLICK;
81
+ const imgSrc = target.getElementsByTagName("img")[0].src;
82
+ channelAction = channelActions.VIEW;
83
+
84
+ if (imgSrc) {
85
+ const url = new URL(
86
+ imgSrc,
87
+ window.location.protocol + "//" + window.location.host
88
+ );
89
+ text = url.pathname.substr(url.pathname.lastIndexOf("/") + 1);
90
+ }
91
+ }
92
+ if (eventValue.includes("/cms/delivery/media")) {
93
+ type = InteractionEventTypes.IMAGE_DOWNLOAD;
94
+ channelAction = channelActions.DOWNLOAD;
95
+ }
96
+ }
97
+ if (type === InteractionEventTypes.DROPDOWN_CHANGE) {
98
+ text = element.id;
99
+ eventValue = element.value;
100
+ }
101
+ if (type === InteractionEventTypes.INPUT_CHANGE) {
102
+ text = element.ariaLabel;
103
+ eventValue = element.value;
104
+ }
105
+ let env = "DEV";
106
+ if (window.location.host === "architect.salesforce.com") {
107
+ env = "PRD";
108
+ }
109
+ if (window.location.host.includes("site-staging")) {
110
+ env = "STG";
111
+ }
112
+ text = text.replace(/^\s+|\s+$/g, "");
113
+ const pathNameArray = window.location.pathname.split("/");
114
+ const interaction = {
115
+ name: name,
116
+ eventType: "websiteInteractionEvent",
117
+ topLevelLocation: pathNameArray[1] || "/",
118
+ secondLevelLocation: pathNameArray[2],
119
+ page: pathNameArray[3],
120
+ params: window.location.search || window.location.hash,
121
+ interactionType: type,
122
+ interactionElement: element
123
+ ? `${element.localName}/${element.name}/${text}`
124
+ : "",
125
+ eventValue: eventValue,
126
+ env: env,
127
+ gaClientId: localStorage.getItem("ga_client_id"),
128
+ elementId: element.id,
129
+ elementLabel: text,
130
+ channelAction: channelAction,
131
+ channelActionStatus: channelActionStatus,
132
+ testSend: env === "PRD" ? "false" : "true",
133
+ pageId: pathNameArray[pathNameArray.length - 1],
134
+ pageTitle: document.title,
135
+ searchTitle: pathNameArray[1] === "search" ? searchTitle : "",
136
+ domainName: window.location.hostname
137
+ };
138
+ (window as any).SalesforceInteractions?.sendEvent({
139
+ interaction: interaction
140
+ });
141
+ }
@@ -0,0 +1,116 @@
1
+ @import "arch/reset";
2
+
3
+ a {
4
+ text-decoration: none;
5
+ }
6
+
7
+ img {
8
+ display: block;
9
+ max-width: 100%;
10
+ max-height: 475px;
11
+ }
12
+
13
+ .hero {
14
+ padding: 0 var(--arch-spacing-6);
15
+ }
16
+
17
+ .hero-white {
18
+ background-color: var(--arch-color-white);
19
+ color: var(--arch-color-black);
20
+ }
21
+
22
+ .hero-dark {
23
+ background-color: var(--arch-color-theme-dark);
24
+ color: var(--arch-color-white);
25
+ }
26
+
27
+ .hero-blue {
28
+ background-color: var(--arch-color-blue-ninety-five);
29
+ color: var(--arch-color-black);
30
+ }
31
+
32
+ .hero-light {
33
+ background-color: var(--arch-color-theme-light);
34
+ color: var(--arch-color-black);
35
+ }
36
+
37
+ .hero-bright {
38
+ background-color: var(--arch-color-theme-bright);
39
+ color: var(--arch-color-black);
40
+ }
41
+
42
+ .content {
43
+ align-items: center;
44
+ display: flex;
45
+ justify-content: space-between;
46
+ margin: auto;
47
+ max-width: 1280px;
48
+ min-height: 500px;
49
+ }
50
+
51
+ .content-start {
52
+ display: flex;
53
+ flex-direction: column;
54
+ align-items: start;
55
+ padding-top: var(--arch-spacing-12);
56
+ padding-bottom: var(--arch-spacing-12);
57
+ padding-right: var(--arch-spacing-6);
58
+ width: 40%;
59
+ min-width: 400px;
60
+ }
61
+
62
+ .content-end-center {
63
+ margin-top: var(--arch-spacing-8);
64
+ margin-bottom: var(--arch-spacing-8);
65
+ }
66
+
67
+ .content-end-bottom {
68
+ align-self: flex-end;
69
+ margin-top: var(--arch-spacing-8);
70
+ }
71
+
72
+ .title {
73
+ font-family: Neutraface, sans-serif;
74
+ font-size: var(--arch-font-size-6xl);
75
+ line-height: 1;
76
+ white-space: pre-line;
77
+ }
78
+
79
+ .subtitle {
80
+ line-height: 1.5;
81
+ margin: var(--arch-spacing-2) 0;
82
+ font-size: var(--arch-font-size-xl);
83
+ }
84
+
85
+ .cta {
86
+ margin-top: var(--arch-spacing-2);
87
+ }
88
+
89
+ @media screen and (max-width: 1100px) {
90
+ .content {
91
+ flex-direction: column;
92
+ padding-top: var(--arch-spacing-8);
93
+ }
94
+
95
+ .content-start {
96
+ align-items: center;
97
+ margin: auto;
98
+ max-width: 400px;
99
+ min-width: auto;
100
+ padding: var(--arch-spacing-2) 0 var(--arch-spacing-3);
101
+ text-align: center;
102
+ width: 100%;
103
+ }
104
+
105
+ .content-end {
106
+ margin-left: auto;
107
+ margin-right: auto;
108
+ max-width: 450px;
109
+ max-height: 450px;
110
+ }
111
+
112
+ .title {
113
+ white-space: normal;
114
+ font-size: var(--arch-font-size-5xl);
115
+ }
116
+ }