@salesforcedevs/arch-components 1.20.17-alpha13 → 1.20.17-alpha15

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 (146) hide show
  1. package/package.json +1 -1
  2. package/src/assets/css/arch-variables.css +512 -0
  3. package/src/modules/arch/badge/badge.css +22 -0
  4. package/src/modules/arch/badge/badge.html +5 -0
  5. package/src/modules/arch/badge/badge.ts +9 -0
  6. package/src/modules/arch/button/button.css +1 -0
  7. package/src/modules/arch/button/button.html +20 -0
  8. package/src/modules/arch/button/button.ts +67 -0
  9. package/src/modules/arch/buttonLink/buttonLink.css +1 -0
  10. package/src/modules/arch/buttonLink/buttonLink.html +19 -0
  11. package/src/modules/arch/buttonLink/buttonLink.stories.js +24 -0
  12. package/src/modules/arch/buttonLink/buttonLink.ts +8 -0
  13. package/src/modules/arch/buttonStyles/buttonStyles.css +220 -0
  14. package/src/modules/arch/card/card.css +128 -0
  15. package/src/modules/arch/card/card.html +85 -0
  16. package/src/modules/arch/card/card.ts +277 -0
  17. package/src/modules/arch/cardBase/cardBase.css +11 -0
  18. package/src/modules/arch/cardBase/cardBase.html +2 -0
  19. package/src/modules/arch/cardGridA/cardGridA.css +11 -0
  20. package/src/modules/arch/cardGridA/cardGridA.html +21 -0
  21. package/src/modules/arch/cardGridA/cardGridA.stories.js +107 -0
  22. package/src/modules/arch/cardGridA/cardGridA.ts +24 -0
  23. package/src/modules/arch/cardGridC/cardGridC.css +24 -0
  24. package/src/modules/arch/cardGridC/cardGridC.html +22 -0
  25. package/src/modules/arch/cardGridC/cardGridC.stories.js +42 -0
  26. package/src/modules/arch/cardGridC/cardGridC.ts +11 -0
  27. package/src/modules/arch/cardGridD/cardGridD.css +17 -0
  28. package/src/modules/arch/cardGridD/cardGridD.html +20 -0
  29. package/src/modules/arch/cardGridD/cardGridD.stories.js +34 -0
  30. package/src/modules/arch/cardGridD/cardGridD.ts +7 -0
  31. package/src/modules/arch/cardNew/cardNew.css +31 -0
  32. package/src/modules/arch/cardNew/cardNew.html +32 -0
  33. package/src/modules/arch/cardNew/cardNew.ts +66 -0
  34. package/src/modules/arch/children/children.html +2 -0
  35. package/src/modules/arch/children/children.ts +31 -0
  36. package/src/modules/arch/color/color.ts +59 -0
  37. package/src/modules/arch/content/__fixtures__/index.ts +884 -0
  38. package/src/modules/arch/content/content.css +643 -0
  39. package/src/modules/arch/content/content.html +65 -0
  40. package/src/modules/arch/content/content.stories.js +14 -0
  41. package/src/modules/arch/content/content.ts +169 -0
  42. package/src/modules/arch/contentIcon/contentIcon.css +48 -0
  43. package/src/modules/arch/contentIcon/contentIcon.html +15 -0
  44. package/src/modules/arch/contentIcon/contentIcon.stories.js +110 -0
  45. package/src/modules/arch/contentIcon/contentIcon.ts +68 -0
  46. package/src/modules/arch/context/context.ts +21 -19
  47. package/src/modules/arch/contextAdapter/constants.ts +1 -0
  48. package/src/modules/arch/contextAdapter/contextAdapter.html +1 -0
  49. package/src/modules/arch/contextAdapter/contextAdapter.ts +54 -0
  50. package/src/modules/arch/debounce/debounce.ts +32 -0
  51. package/src/modules/arch/dialog/dialog.ts +154 -0
  52. package/src/modules/arch/dialogStyles/dialogStyles.css +90 -0
  53. package/src/modules/arch/effectAdapter/effectAdapter.ts +19 -9
  54. package/src/modules/arch/explorer/explorer.css +301 -0
  55. package/src/modules/arch/explorer/explorer.html +418 -0
  56. package/src/modules/arch/explorer/explorer.ts +718 -0
  57. package/src/modules/arch/explorer/types.d.ts +60 -0
  58. package/src/modules/arch/fetch/fetch.ts +55 -0
  59. package/src/modules/arch/footerMfe/footerMfe.html +3 -0
  60. package/src/modules/arch/footerMfe/footerMfe.ts +19 -0
  61. package/src/modules/arch/gallery/gallery.css +365 -0
  62. package/src/modules/arch/gallery/gallery.html +71 -0
  63. package/src/modules/arch/gallery/gallery.ts +366 -0
  64. package/src/modules/arch/gallery/types.d.ts +35 -0
  65. package/src/modules/arch/heading/heading.css +1 -0
  66. package/src/modules/arch/heading/heading.html +9 -0
  67. package/src/modules/arch/heading/heading.ts +36 -0
  68. package/src/modules/arch/helpers/helpers.ts +141 -0
  69. package/src/modules/arch/heroA/heroA.css +116 -0
  70. package/src/modules/arch/heroA/heroA.html +28 -0
  71. package/src/modules/arch/heroA/heroA.stories.js +49 -0
  72. package/src/modules/arch/heroA/heroA.ts +53 -0
  73. package/src/modules/arch/heroB/heroB.css +79 -0
  74. package/src/modules/arch/heroB/heroB.html +27 -0
  75. package/src/modules/arch/heroB/heroB.stories.js +44 -0
  76. package/src/modules/arch/heroB/heroB.ts +26 -0
  77. package/src/modules/arch/i18n/i18n.ts +78 -0
  78. package/src/modules/arch/icon/icon.css +28 -0
  79. package/src/modules/arch/icon/icon.html +17 -0
  80. package/src/modules/arch/icon/icon.stories.js +18 -0
  81. package/src/modules/arch/icon/icon.ts +92 -0
  82. package/src/modules/arch/instrumentation/instrumentation.css +1 -0
  83. package/src/modules/arch/instrumentation/instrumentation.html +1 -0
  84. package/src/modules/arch/instrumentation/instrumentation.ts +113 -0
  85. package/src/modules/arch/labels/helpers.ts +25 -0
  86. package/src/modules/arch/labels/pointHelpers.ts +47 -0
  87. package/src/modules/arch/labels/timeHelpers.ts +182 -0
  88. package/src/modules/arch/labels/types.d.ts +5 -0
  89. package/src/modules/arch/logger/logger.ts +33 -0
  90. package/src/modules/arch/menu/menu.ts +260 -0
  91. package/src/modules/arch/overflow/overflow.ts +71 -0
  92. package/src/modules/arch/page/page.css +3 -0
  93. package/src/modules/arch/page/page.html +3 -0
  94. package/src/modules/arch/page/page.stories.js +10 -0
  95. package/src/modules/arch/page/page.ts +3 -0
  96. package/src/modules/arch/pageHeaderA/pageHeaderA.css +82 -0
  97. package/src/modules/arch/pageHeaderA/pageHeaderA.html +24 -0
  98. package/src/modules/arch/pageHeaderA/pageHeaderA.stories.js +18 -0
  99. package/src/modules/arch/pageHeaderA/pageHeaderA.ts +51 -0
  100. package/src/modules/arch/pill/pill.css +70 -0
  101. package/src/modules/arch/pill/pill.html +17 -0
  102. package/src/modules/arch/pill/pill.ts +34 -0
  103. package/src/modules/arch/polling-request.ts +97 -0
  104. package/src/modules/arch/reflectedElement/reflectedElement.html +2 -0
  105. package/src/modules/arch/reflectedElement/reflectedElement.ts +5 -3
  106. package/src/modules/arch/reset/reset.css +39 -0
  107. package/src/modules/arch/searchList/searchList.css +120 -0
  108. package/src/modules/arch/searchList/searchList.html +46 -0
  109. package/src/modules/arch/searchList/searchList.ts +53 -0
  110. package/src/modules/arch/sectionA/sectionA.css +64 -0
  111. package/src/modules/arch/sectionA/sectionA.html +21 -0
  112. package/src/modules/arch/sectionA/sectionA.stories.js +18 -0
  113. package/src/modules/arch/sectionA/sectionA.ts +27 -0
  114. package/src/modules/arch/select/select.css +40 -0
  115. package/src/modules/arch/select/select.html +24 -0
  116. package/src/modules/arch/select/select.ts +64 -0
  117. package/src/modules/arch/socialShare/socialShare.css +50 -0
  118. package/src/modules/arch/socialShare/socialShare.html +56 -0
  119. package/src/modules/arch/socialShare/socialShare.ts +29 -0
  120. package/src/modules/arch/spinner/spinner.css +195 -0
  121. package/src/modules/arch/spinner/spinner.html +9 -0
  122. package/src/modules/arch/spinner/spinner.ts +15 -0
  123. package/src/modules/arch/styles/styles.css +24 -0
  124. package/src/modules/arch/summary/summary.css +134 -0
  125. package/src/modules/arch/summary/summary.html +71 -0
  126. package/src/modules/arch/summary/summary.stories.js +148 -0
  127. package/src/modules/arch/summary/summary.ts +96 -0
  128. package/src/modules/arch/tab/tab.css +3 -0
  129. package/src/modules/arch/tab/tab.html +5 -0
  130. package/src/modules/arch/tab/tab.ts +46 -0
  131. package/src/modules/arch/tabset/tabset.css +112 -0
  132. package/src/modules/arch/tabset/tabset.html +62 -0
  133. package/src/modules/arch/tabset/tabset.ts +244 -0
  134. package/src/modules/arch/testutils.ts +118 -0
  135. package/src/modules/arch/threeCardGrid/threeCardGrid.css +6 -0
  136. package/src/modules/arch/threeCardGrid/threeCardGrid.html +5 -0
  137. package/src/modules/arch/threeCardGrid/threeCardGrid.ts +3 -0
  138. package/src/modules/arch/track/track.ts +23 -0
  139. package/src/modules/arch/trailhead.ts +120 -0
  140. package/src/modules/arch/types.d.ts +1 -0
  141. package/src/modules/arch/useEffectAttr.ts +16 -0
  142. package/src/modules/arch/utils/utils.ts +20 -0
  143. package/src/modules/arch/withState.ts +21 -0
  144. package/src/modules/arch/xsfMfeEvents/xsfMfeEvents.html +1 -0
  145. package/src/modules/arch/xsfMfeEvents/xsfMfeEvents.ts +47 -0
  146. package/src/modules/arch/slot/slot.ts +0 -20
@@ -0,0 +1,8 @@
1
+ import { api } from 'lwc';
2
+ import Button from 'arch/button';
3
+
4
+ export default class extends Button {
5
+ @api href: string | null = null;
6
+ @api rel: string | null = null;
7
+ @api target: '_self' | '_blank' | '_parent' | '_top' | null = null;
8
+ }
@@ -0,0 +1,220 @@
1
+ @import "arch/reset";
2
+
3
+ :host {
4
+ display: inline-flex;
5
+
6
+ --dark-1: 5%;
7
+ --dark-2: 15%;
8
+
9
+ color: var(--arch-color-meteorite);
10
+ }
11
+
12
+ .button {
13
+ align-items: center;
14
+ appearance: none;
15
+ border: 1px solid transparent;
16
+ background-color: transparent;
17
+ border-radius: var(--arch-spacing-1);
18
+ color: inherit;
19
+ cursor: pointer;
20
+ display: flex;
21
+ width: 100%;
22
+ justify-content: center;
23
+ font-weight: bold;
24
+ line-height: 1.25;
25
+ font-size: var(--arch-font-size-sm);
26
+ padding: calc(var(--arch-spacing-3) * 0.8333) var(--arch-spacing-4);
27
+ text-decoration: none;
28
+ user-select: none;
29
+ white-space: nowrap;
30
+ }
31
+
32
+ .button-variant {
33
+ background-color: hsl(
34
+ var(--color-bg-h) var(--color-bg-s) var(--color-bg-l)
35
+ );
36
+ border: 1px solid hsl(var(--color-bg-h) var(--color-bg-s) var(--color-bg-l));
37
+ box-shadow: 0 1px 0
38
+ hsl(
39
+ var(--color-bg-h) var(--color-bg-s)
40
+ calc(var(--color-bg-l) - var(--dark-2))
41
+ );
42
+ color: var(--color);
43
+ }
44
+
45
+ .button-variant:hover:not(.button-disabled),
46
+ .button-variant:focus:not(.button-disabled),
47
+ .button-variant:active:not(.button-disabled) {
48
+ color: var(--color);
49
+ }
50
+
51
+ .button-variant:hover:not(.button-disabled),
52
+ .button-variant:focus:not(.button-disabled) {
53
+ background-color: hsl(
54
+ var(--color-bg-h) var(--color-bg-s)
55
+ calc(var(--color-bg-l) - var(--dark-1))
56
+ );
57
+ border-color: hsl(
58
+ var(--color-bg-h) var(--color-bg-s)
59
+ calc(var(--color-bg-l) - var(--dark-1))
60
+ );
61
+ }
62
+
63
+ .button-variant:active:not(.button-disabled) {
64
+ background-color: hsl(
65
+ var(--color-bg-h) var(--color-bg-s)
66
+ calc(var(--color-bg-l) - var(--dark-2))
67
+ );
68
+ border-color: hsl(
69
+ var(--color-bg-h) var(--color-bg-s)
70
+ calc(var(--color-bg-l) - var(--dark-2))
71
+ );
72
+ box-shadow: 0 1px 0
73
+ hsl(
74
+ var(--color-bg-h) var(--color-bg-s)
75
+ calc(var(--color-bg-l) - var(--dark-2))
76
+ ),
77
+ 0 0 4px hsl(var(--color-bg-h) var(--color-bg-s) var(--color-bg-l));
78
+ }
79
+
80
+ .button-neutral {
81
+ color: var(--arch-color-brand);
82
+ background-color: var(--arch-color-white);
83
+ box-shadow: 0 0 0 1px hsl(0deg 0% 0% / 5%), 0 2px 0 hsl(0deg 0% 0% / 5%);
84
+ }
85
+
86
+ .button-neutral:hover:not(.button-disabled),
87
+ .button-neutral:focus:not(.button-disabled) {
88
+ background-color: var(--arch-color-sand);
89
+ }
90
+
91
+ .button-neutral:active:not(.button-disabled) {
92
+ background-color: var(--arch-color-fog);
93
+ color: var(--arch-color-meteorite);
94
+ }
95
+
96
+ .button-bare:hover:not(.button-disabled),
97
+ .button-bare:focus:not(.button-disabled) {
98
+ background-color: var(--arch-color-sand);
99
+ color: hsl(
100
+ var(--arch-color-meteorite-h) var(--arch-color-meteorite-s)
101
+ calc(var(--arch-color-meteorite-l) - var(--dark-1))
102
+ );
103
+ }
104
+
105
+ .button-border-filled {
106
+ background-color: var(--arch-color-white);
107
+ border-color: var(--arch-color-fog);
108
+ box-shadow: 0 1px 0 0 hsl(0deg 0% 0% / 10%);
109
+ }
110
+
111
+ .button-border-filled:hover:not(.button-disabled),
112
+ .button-border-filled:focus:not(.button-disabled) {
113
+ background-color: var(--arch-color-sand);
114
+ color: hsl(
115
+ var(--arch-color-meteorite-h) var(--arch-color-meteorite-s)
116
+ calc(var(--arch-color-meteorite-l) - var(--dark-1))
117
+ );
118
+ }
119
+
120
+ .button-bare:active:not(.button-disabled),
121
+ .button-border-filled:active:not(.button-disabled) {
122
+ background-color: var(--arch-color-fog);
123
+ color: hsl(
124
+ var(--arch-color-meteorite-h) var(--arch-color-meteorite-s)
125
+ calc(var(--arch-color-meteorite-l) - var(--dark-1))
126
+ );
127
+ }
128
+
129
+ .button-brand {
130
+ --color: var(--arch-color-white);
131
+ --color-bg-h: var(--arch-color-brand-h);
132
+ --color-bg-s: var(--arch-color-brand-s);
133
+ --color-bg-l: var(--arch-color-brand-l);
134
+ }
135
+
136
+ .button-success {
137
+ --color: var(--arch-color-white);
138
+ --color-bg-h: var(--arch-color-success-h);
139
+ --color-bg-s: var(--arch-color-success-s);
140
+ --color-bg-l: var(--arch-color-success-l);
141
+ }
142
+
143
+ .button-destructive {
144
+ --color: var(--arch-color-white);
145
+ --color-bg-h: var(--arch-color-destructive-h);
146
+ --color-bg-s: var(--arch-color-destructive-s);
147
+ --color-bg-l: var(--arch-color-destructive-l);
148
+ }
149
+
150
+ .button-destructive-inverse {
151
+ color: var(--arch-color-destructive);
152
+ background-color: var(--arch-color-white);
153
+ border-color: transparent;
154
+ box-shadow: 0 0 0 1px hsl(0deg 0% 0% / 5%), 0 2px 0 hsl(0deg 0% 0% / 5%);
155
+ }
156
+
157
+ .button-destructive-inverse:hover:not(.button-disabled),
158
+ .button-destructive-inverse:focus:not(.button-disabled) {
159
+ color: var(--arch-color-destructive);
160
+ background-color: var(--arch-color-sand);
161
+ border-color: transparent;
162
+ }
163
+
164
+ .button-destructive-inverse:active:not(.button-disabled) {
165
+ color: var(--arch-color-meteorite);
166
+ background-color: var(--arch-color-fog);
167
+ border-color: transparent;
168
+ }
169
+
170
+ .button-disabled {
171
+ background: var(--arch-color-fog);
172
+ border-color: var(--arch-color-fog);
173
+ box-shadow: 0 1px 0 var(--arch-color-fog);
174
+ color: var(--arch-color-granite);
175
+ cursor: not-allowed;
176
+ pointer-events: none;
177
+ outline: none;
178
+ }
179
+
180
+ .button-small {
181
+ font-size: var(--arch-font-size-sm);
182
+ padding: var(--arch-spacing-2) var(--arch-spacing-4);
183
+ }
184
+
185
+ .button-large {
186
+ font-size: var(--arch-font-size-md);
187
+ padding: var(--arch-spacing-3) var(--arch-spacing-5);
188
+ }
189
+
190
+ .button[data-icon-size] {
191
+ padding: 0;
192
+ }
193
+
194
+ .button[data-icon-size="small"] {
195
+ padding: calc(var(--arch-spacing-2) + 0.75px);
196
+ }
197
+
198
+ .button[data-icon-size="medium"] {
199
+ padding: calc(var(--arch-spacing-2) + 1px);
200
+ }
201
+
202
+ .button[data-icon-size="large"] {
203
+ padding: calc(var(--arch-spacing-2) + 2px);
204
+ }
205
+
206
+ .spinner {
207
+ margin-right: var(--arch-spacing-2);
208
+ margin-left: calc(var(--arch-spacing-1) * -1);
209
+ animation: rotation 2s infinite linear;
210
+ }
211
+
212
+ @keyframes rotation {
213
+ from {
214
+ transform: rotate(0deg);
215
+ }
216
+
217
+ to {
218
+ transform: rotate(359deg);
219
+ }
220
+ }
@@ -0,0 +1,128 @@
1
+ @import "arch/reset";
2
+ @import "arch/cardBase";
3
+
4
+ :host {
5
+ height: 100%;
6
+ }
7
+
8
+ a {
9
+ color: var(--arch-color-brand);
10
+ text-decoration: none;
11
+ }
12
+
13
+ a:hover {
14
+ text-decoration: underline;
15
+ }
16
+
17
+ .card {
18
+ display: flex;
19
+ }
20
+
21
+ .content {
22
+ display: flex;
23
+ flex: 1;
24
+ flex-direction: column;
25
+ color: var(--arch-color-black);
26
+ }
27
+
28
+ .content-inner {
29
+ flex: 1;
30
+ }
31
+
32
+ .pretitle {
33
+ font-size: var(--arch-font-size-sm);
34
+ color: var(--arch-color-meteorite);
35
+ padding-bottom: var(--arch-spacing-1);
36
+ }
37
+
38
+ .title {
39
+ font-size: var(--arch-font-size-lg);
40
+ font-weight: bold;
41
+ }
42
+
43
+ .description {
44
+ margin-top: var(--arch-spacing-3);
45
+ line-height: var(--arch-line-height-normal);
46
+ }
47
+
48
+ .cta {
49
+ font-weight: bold;
50
+ margin-top: var(--arch-spacing-3);
51
+ display: block;
52
+ }
53
+
54
+ div.image {
55
+ background-size: cover;
56
+ background-repeat: no-repeat;
57
+ background-position: center center;
58
+ }
59
+
60
+ img.image {
61
+ max-width: 90%;
62
+ max-height: 100px;
63
+ }
64
+
65
+ .card[data-href] .image {
66
+ cursor: pointer;
67
+ }
68
+
69
+ .card:not([data-image]),
70
+ .card[data-image=""] {
71
+ padding: var(--arch-spacing-6);
72
+ }
73
+
74
+ .card[data-image^="top"] {
75
+ flex-direction: column-reverse;
76
+ }
77
+
78
+ .card[data-image^="top"] .content {
79
+ padding: var(--arch-spacing-6);
80
+ }
81
+
82
+ .card[data-image="top-cover"] .image {
83
+ height: 0;
84
+ border-top-left-radius: var(--arch-radius-lg);
85
+ border-top-right-radius: var(--arch-radius-lg);
86
+ }
87
+
88
+ .card[data-image="top-small"] .image {
89
+ align-self: flex-start;
90
+ margin: var(--arch-spacing-6) var(--arch-spacing-6) 0 var(--arch-spacing-6);
91
+ max-height: 75px;
92
+ }
93
+
94
+ .card[data-image="right-cover"] {
95
+ align-items: stretch;
96
+ padding: var(--arch-spacing-6);
97
+ }
98
+
99
+ .card[data-image="right-cover"] .image {
100
+ flex: 1;
101
+ align-self: stretch;
102
+ border-radius: var(--arch-radius-lg);
103
+ margin-left: var(--arch-spacing-6);
104
+ }
105
+
106
+ .card[data-image="left-cover"] {
107
+ align-items: top;
108
+ flex-direction: row-reverse;
109
+ padding: var(--arch-spacing-6);
110
+ }
111
+
112
+ .card[data-image="left-cover"] .image {
113
+ align-self: stretch;
114
+ border-radius: var(--arch-radius-lg);
115
+ flex: 1;
116
+ margin-right: var(--arch-spacing-6);
117
+ }
118
+
119
+ .card[data-image="left-small"] {
120
+ align-items: flex-start;
121
+ flex-direction: row-reverse;
122
+ padding: var(--arch-spacing-6);
123
+ }
124
+
125
+ .card[data-image="left-small"] .image {
126
+ width: 50px;
127
+ margin-right: var(--arch-spacing-6);
128
+ }
@@ -0,0 +1,85 @@
1
+ <template>
2
+ <article
3
+ class="card card-base"
4
+ data-href={ctaHref}
5
+ data-image={imgVariantResponsive}
6
+ role="article"
7
+ aria-labelledby={cardTitleId}
8
+ tabindex="0"
9
+ onkeydown={handleCardKeydown}
10
+ >
11
+ <div class="content">
12
+ <div class="content-inner">
13
+ <template if:true={pretitle}>
14
+ <p class="pretitle">{pretitle}</p>
15
+ </template>
16
+ <template if:true={pretitleHref}>
17
+ <p><a href={pretitleHref}>{pretitleHrefText}</a></p>
18
+ </template>
19
+ <h3 class="title" id={cardTitleId}>{title}</h3>
20
+ <p if:true={description} class="description">{description}</p>
21
+ </div>
22
+ <a
23
+ if:true={ctaTitle}
24
+ class="cta"
25
+ name={ctaTitleId}
26
+ id={ctaTitleId}
27
+ href={ctaHref}
28
+ target={ctaTarget}
29
+ aria-label={assistiveText}
30
+ onclick={trackLinkClick}
31
+ rel={rel}
32
+ >
33
+ {ctaTitle}
34
+ <img
35
+ if:true={isExternalHref}
36
+ src="https://a.sfdcstatic.com/developer-website/images/architect/new_window.svg"
37
+ style="display: inline; height: 1rem; margin: 0 0 0 5px"
38
+ alt="Open link in new window"
39
+ aria-label="Open link in new window"
40
+ />
41
+ </a>
42
+ </div>
43
+ <template if:true={imgSrc}>
44
+ <div
45
+ name={ctaHref}
46
+ id={imageDivId}
47
+ class="image"
48
+ if:false={imgTag}
49
+ onclick={onImageClick}
50
+ style={imgStyle}
51
+ data-href={ctaHref}
52
+ ></div>
53
+ <picture if:true={imgTagNoSvg}>
54
+ <template if:false={isRemoteImage}>
55
+ <source srcset={imgSrcSetWebP} />
56
+ <source srcset={imgSrcSetJpg} />
57
+ </template>
58
+ <img
59
+ name={ctaHref}
60
+ id={imageImgId}
61
+ class="image"
62
+ if:true={imgTag}
63
+ onclick={onImageClick}
64
+ style={imgStyle}
65
+ src={imgSrc}
66
+ alt={imageAltText}
67
+ loading="lazy"
68
+ decoding="async"
69
+ />
70
+ </picture>
71
+ <img
72
+ name={ctaHref}
73
+ id={imageSvgId}
74
+ class="image"
75
+ if:true={imgTagSvg}
76
+ onclick={onImageClick}
77
+ style={imgStyle}
78
+ src={imgSrc}
79
+ alt={description}
80
+ loading="lazy"
81
+ decoding="async"
82
+ />
83
+ </template>
84
+ </article>
85
+ </template>
@@ -0,0 +1,277 @@
1
+ import { api, track, LightningElement } from "lwc";
2
+
3
+ import { track as analyticsTrack } from "arch/instrumentation";
4
+ import { sendInteractionEvent, InteractionEventTypes } from "arch/helpers";
5
+
6
+ export type CardAttribute = string | null;
7
+
8
+ export type CardImageVariant =
9
+ | "top-cover"
10
+ | "top-small"
11
+ | "left-small"
12
+ | "left-cover"
13
+ | "right-cover";
14
+
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
+ productArea: CardAttribute;
27
+ date: CardAttribute;
28
+ level: CardAttribute;
29
+ };
30
+
31
+ const widths = [820, 640, 320, 75];
32
+
33
+ const homepageCtaTitles = ["design", "deliver", "govern", "roadmap"];
34
+
35
+ // arch-card-grid taks care of adjusting the grid to the correct number
36
+ // of columns at smaller view ports
37
+ export const mediaQuerySnapToTop = window.matchMedia(`(max-width: 500px)`);
38
+
39
+ export default class extends LightningElement {
40
+ @api assistiveText: CardAttribute = null;
41
+ @api ctaHref: CardAttribute = null;
42
+ @api ctaTarget: CardAttribute = null;
43
+ @api ctaTitle: CardAttribute = null;
44
+ @api description: CardAttribute = null;
45
+ @api imgAspect: CardAttribute = null;
46
+ @api imgSrc: CardAttribute = null;
47
+ @api imgVariant: CardImageVariant = "top-cover";
48
+ @api pretitle: CardAttribute = null;
49
+ @api pretitleHref: CardAttribute = null;
50
+ @api pretitleHrefText: CardAttribute = null;
51
+ @api title: string = "";
52
+ @api productArea: string = "";
53
+ @api date: string = "";
54
+ @api level: string = "";
55
+
56
+ @track private snapToTop = mediaQuerySnapToTop.matches;
57
+ private cardId: string = "";
58
+
59
+ private get imgStyle() {
60
+ if (!this.imgSrc) {
61
+ return "";
62
+ }
63
+ const style: string[] = [];
64
+ const { imgVariantResponsive: variant, imgSrc } = this;
65
+
66
+ if (variant.includes("cover")) {
67
+ const image = imgSrc;
68
+
69
+ // Use the original image if it's a remote image or WebP
70
+ /* if (!this.isRemoteImage && !imgSrc.includes('webp')) {
71
+ const imgType = imgSrc.split('.').pop();
72
+ image = imgSrc.replace(`.${imgType}`, '-820w.webp');
73
+ } */
74
+
75
+ style.push(`background-image: url(${image})`);
76
+ }
77
+ if (variant === "top-cover") {
78
+ style.push(`padding-top: ${this.imgAspect || "40%"}`);
79
+ }
80
+ return style.join(";");
81
+ }
82
+
83
+ private get imgTag() {
84
+ return this.imgVariant.includes("small");
85
+ }
86
+
87
+ private get isRemoteImage() {
88
+ return /^(https?:\/\/|\/\/)/i.test(this.imgSrc);
89
+ }
90
+
91
+ private get imgSrcSetWebP() {
92
+ if (this.isRemoteImage) {
93
+ return this.imgSrc;
94
+ }
95
+ const imgType = this.imgSrc?.split(".").pop();
96
+ const imgName = this.imgSrc?.replace(`.${imgType}`, "");
97
+ const srcSet: string[] = [];
98
+ widths.forEach((width) => {
99
+ srcSet.push(`${imgName}-${width}w.webp ${width}w`);
100
+ });
101
+ return srcSet.join(",");
102
+ }
103
+
104
+ private get imgSrcSetJpg() {
105
+ if (this.isRemoteImage) {
106
+ return this.imgSrc;
107
+ }
108
+ const imgType = this.imgSrc?.split(".").pop();
109
+ const imgName = this.imgSrc?.replace(`.${imgType}`, "");
110
+ const srcSet: string[] = [];
111
+ widths.forEach((width) => {
112
+ srcSet.push(`${imgName}-${width}w.jpg ${width}w`);
113
+ });
114
+ return srcSet.join(",");
115
+ }
116
+
117
+ private get imgTagNoSvg() {
118
+ return this.imgTag && !this.imgSrc?.toLowerCase().endsWith("svg");
119
+ }
120
+
121
+ private get imgTagSvg() {
122
+ return this.imgTag && this.imgSrc?.toLowerCase().endsWith("svg");
123
+ }
124
+
125
+ private get rel() {
126
+ return this.ctaTarget === "_blank" ? "noopener" : "";
127
+ }
128
+
129
+ get isExternalHref() {
130
+ return this.ctaTarget === "_blank" && this.ctaTitle;
131
+ }
132
+
133
+ private get imgVariantResponsive() {
134
+ if (!this.snapToTop) {
135
+ return this.imgVariant;
136
+ }
137
+ return String(this.imgVariant).replace(/left|right/, "top");
138
+ }
139
+
140
+ // Accessibility getters
141
+ get cardTitleId() {
142
+ return `${this.cardId}-title`;
143
+ }
144
+
145
+ get ctaTitleId() {
146
+ return `${this.cardId}-cta`;
147
+ }
148
+
149
+ get imageDivId() {
150
+ return `${this.cardId}-image-div`;
151
+ }
152
+
153
+ get imageImgId() {
154
+ return `${this.cardId}-image-img`;
155
+ }
156
+
157
+ get imageSvgId() {
158
+ return `${this.cardId}-image-svg`;
159
+ }
160
+
161
+ get imageAriaLabel() {
162
+ const title = this.title || "Card";
163
+ const description = this.description || "";
164
+ return `View ${title}${description ? `: ${description}` : ""}`;
165
+ }
166
+
167
+ get imageAltText() {
168
+ return this.description || this.title || "Card image";
169
+ }
170
+
171
+ connectedCallback() {
172
+ mediaQuerySnapToTop.addListener(this.onMediaQuerySnapToTop);
173
+ // Generate unique ID for this card instance
174
+ const title = this.title || "Card";
175
+ this.cardId = `${title}-${Math.random().toString(36).substring(2, 11)}`;
176
+ }
177
+
178
+ disconnectedCallback() {
179
+ mediaQuerySnapToTop.removeListener(this.onMediaQuerySnapToTop);
180
+ }
181
+
182
+ private onImageClick(e: MouseEvent) {
183
+ const element = e.target as HTMLElement;
184
+ sendInteractionEvent(
185
+ "Card Image Click",
186
+ InteractionEventTypes.IMAGE_CLICK,
187
+ e,
188
+ element
189
+ );
190
+
191
+ const { ctaHref, ctaTarget } = this;
192
+ if (ctaHref) {
193
+ if (ctaTarget) {
194
+ window.open(ctaHref, ctaTarget);
195
+ } else {
196
+ window.location.href = ctaHref;
197
+ }
198
+ }
199
+ this.trackLinkClick(e, true);
200
+ }
201
+
202
+ private trackLinkClick(e: MouseEvent, imgClick: boolean) {
203
+ const element = e.currentTarget as HTMLAnchorElement;
204
+ const linkText = this.ctaTitle;
205
+ const title = typeof this.title === "string" ? this.title : "";
206
+ let event: string = "";
207
+ let payload: Record<string, string> = {};
208
+ if (!imgClick) {
209
+ sendInteractionEvent(
210
+ "Card Link Click",
211
+ InteractionEventTypes.CLICK,
212
+ e,
213
+ element
214
+ );
215
+ }
216
+
217
+ if (
218
+ window.location.pathname === "/" &&
219
+ homepageCtaTitles.includes(this.title.toLowerCase())
220
+ ) {
221
+ event = "homepage_cta";
222
+ payload = {
223
+ linkText: `home: ${linkText}`,
224
+ headingText: title,
225
+ itemLocation: "card"
226
+ };
227
+ } else {
228
+ event = "select_content";
229
+ payload = {
230
+ contentType: "card grid",
231
+ itemTitle: !title || title === "" ? undefined : title,
232
+ itemLocation: "card"
233
+ };
234
+ }
235
+ if (element.target) {
236
+ const parsedLink = new URL(element.href);
237
+ analyticsTrack(this.template.host, "custEv_outboundClick", {
238
+ clickText: title,
239
+ clickUrl: parsedLink.href
240
+ });
241
+ }
242
+ analyticsTrack(this.template.host, event, payload);
243
+ }
244
+
245
+ private onMediaQuerySnapToTop = (e: MediaQueryListEvent) => {
246
+ this.snapToTop = e.matches;
247
+ };
248
+
249
+ // Accessibility keyboard handlers
250
+ handleCardKeydown(e: KeyboardEvent) {
251
+ if (e.key === "Enter" || e.key === " ") {
252
+ this.trackLinkClick(e as unknown as MouseEvent, false);
253
+ e.preventDefault();
254
+ if (this.ctaHref) {
255
+ if (this.ctaTarget) {
256
+ window.open(this.ctaHref, this.ctaTarget);
257
+ } else {
258
+ window.location.href = this.ctaHref;
259
+ }
260
+ }
261
+ }
262
+ }
263
+ }
264
+
265
+ export function extractCardAttributes(element: Element) {
266
+ return {
267
+ ctaHref: element.getAttribute("cta-href")!,
268
+ ctaTarget: element.getAttribute("cta-target")!,
269
+ ctaTitle: element.getAttribute("cta-title")!,
270
+ description: element.getAttribute("description"),
271
+ imgSrc: element.getAttribute("img-src"),
272
+ pretitle: element.getAttribute("pretitle"),
273
+ pretitleHref: element.getAttribute("pretitle-href"),
274
+ pretitleHrefText: element.getAttribute("pretitle-href-text"),
275
+ title: element.getAttribute("title")
276
+ } as Card;
277
+ }