@hashicorp/react-components 1.1.8 → 1.1.11
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/package.json +4 -8
- package/src/components/nav-panel/components/flight-icon/index.tsx +51 -0
- package/src/components/nav-panel/components/flight-icon/style.module.css +3 -0
- package/src/components/nav-panel/components/link-list/index.tsx +15 -9
- package/src/components/nav-panel/components/link-list/style.module.css +10 -10
- package/src/components/nav-panel/components/panel/column/style.module.css +3 -3
- package/src/components/nav-panel/components/panel/root/style.module.css +6 -6
- package/src/components/nav-panel/components/promo/index.tsx +15 -9
- package/src/components/nav-panel/components/promo/style.module.css +27 -13
- package/src/components/nav-panel/components/text/index.tsx +34 -0
- package/src/components/nav-panel/product-panel/index.tsx +39 -14
- package/src/components/nav-panel/product-panel/style.module.css +78 -37
- package/src/components/nav-panel/standard-panel/index.tsx +3 -0
- package/src/components/nav-panel/standard-panel/style.module.css +2 -2
- package/src/lib/get-localized-link-props/index.test.ts +30 -0
- package/src/lib/get-localized-link-props/index.ts +45 -0
- package/src/lib/parse-url/index.test.ts +40 -1
- package/src/lib/parse-url/index.ts +75 -9
- package/src/lib/send-posthog-event/index.ts +22 -0
- package/src/lib/supported-locales/index.ts +1 -0
- package/src/lib/track-nav-click-event/index.ts +4 -4
- package/src/lib/v/index.ts +4 -5
- package/src/components/actions/index.tsx +0 -107
- package/src/components/actions/style.module.css +0 -28
- package/src/components/actions/types.ts +0 -73
- package/src/components/call-to-action/index.tsx +0 -205
- package/src/components/call-to-action/styles/variant-centered.module.css +0 -93
- package/src/components/call-to-action/styles/variant-compact-grid.module.css +0 -88
- package/src/components/call-to-action/styles/variant-compact.module.css +0 -91
- package/src/components/call-to-action/styles/variant-links.module.css +0 -85
- package/src/components/card/README.md +0 -11
- package/src/components/card/card.tsx +0 -45
- package/src/components/card/index.test.tsx +0 -69
- package/src/components/card/index.tsx +0 -14
- package/src/components/card/newsroom-card/index.test.tsx +0 -39
- package/src/components/card/newsroom-card/index.tsx +0 -37
- package/src/components/card/newsroom-card/style.module.css +0 -12
- package/src/components/card/partner-card/index.test.tsx +0 -57
- package/src/components/card/partner-card/index.tsx +0 -69
- package/src/components/card/partner-card/style.module.css +0 -24
- package/src/components/card/person-card/index.test.tsx +0 -71
- package/src/components/card/person-card/index.tsx +0 -93
- package/src/components/card/person-card/style.module.css +0 -33
- package/src/components/card/primitives.tsx +0 -176
- package/src/components/card/promo-card/index.tsx +0 -51
- package/src/components/card/resource-card/index.test.tsx +0 -48
- package/src/components/card/resource-card/index.tsx +0 -37
- package/src/components/card/style.module.css +0 -145
- package/src/components/card/types.ts +0 -66
- package/src/components/card/unified-card/index.tsx +0 -64
- package/src/components/consent-manager/README.md +0 -73
- package/src/components/consent-manager/components/banner/banner.module.css +0 -23
- package/src/components/consent-manager/components/banner/banner.test.tsx +0 -31
- package/src/components/consent-manager/components/banner/banner.tsx +0 -73
- package/src/components/consent-manager/components/dialog/dialog.module.css +0 -145
- package/src/components/consent-manager/components/dialog/dialog.test.tsx +0 -194
- package/src/components/consent-manager/components/dialog/dialog.tsx +0 -339
- package/src/components/consent-manager/img/icn_close.tsx +0 -19
- package/src/components/consent-manager/index.test.tsx +0 -334
- package/src/components/consent-manager/index.tsx +0 -186
- package/src/components/consent-manager/loader/README.md +0 -29
- package/src/components/consent-manager/loader/categories.ts +0 -22
- package/src/components/consent-manager/loader/index.tsx +0 -94
- package/src/components/consent-manager/loader/presets/enterprise.ts +0 -12
- package/src/components/consent-manager/loader/presets/oss.ts +0 -10
- package/src/components/consent-manager/loader/services.ts +0 -45
- package/src/components/consent-manager/scripts/custom.tsx +0 -59
- package/src/components/consent-manager/scripts/segment.tsx +0 -87
- package/src/components/consent-manager/style.module.css +0 -9
- package/src/components/consent-manager/types.ts +0 -55
- package/src/components/consent-manager/util/cookies.test.ts +0 -75
- package/src/components/consent-manager/util/cookies.ts +0 -70
- package/src/components/consent-manager/util/integrations.test.ts +0 -115
- package/src/components/consent-manager/util/integrations.ts +0 -110
- package/src/components/intro/index.tsx +0 -82
- package/src/components/intro/style.module.css +0 -67
- package/src/components/intro/types.ts +0 -44
- package/src/components/marketo-form/CHANGELOG.md +0 -122
- package/src/components/marketo-form/README.md +0 -1
- package/src/components/marketo-form/contexts/FormMetadata.ts +0 -11
- package/src/components/marketo-form/docs.mdx +0 -197
- package/src/components/marketo-form/fixtures/index.ts +0 -185
- package/src/components/marketo-form/form/index.tsx +0 -369
- package/src/components/marketo-form/index.test.tsx +0 -320
- package/src/components/marketo-form/index.ts +0 -11
- package/src/components/marketo-form/package.original.json +0 -30
- package/src/components/marketo-form/partials/error-message/index.tsx +0 -12
- package/src/components/marketo-form/partials/error-message/style.module.css +0 -13
- package/src/components/marketo-form/partials/field/index.tsx +0 -90
- package/src/components/marketo-form/partials/field-wrapper/index.tsx +0 -26
- package/src/components/marketo-form/partials/fields/checkbox-field/index.tsx +0 -32
- package/src/components/marketo-form/partials/fields/email-field/index.tsx +0 -35
- package/src/components/marketo-form/partials/fields/form-page-url-field/index.tsx +0 -21
- package/src/components/marketo-form/partials/fields/hidden-field/index.tsx +0 -37
- package/src/components/marketo-form/partials/fields/htmltext-field/index.tsx +0 -21
- package/src/components/marketo-form/partials/fields/htmltext-field/style.module.css +0 -18
- package/src/components/marketo-form/partials/fields/name-field/index.tsx +0 -19
- package/src/components/marketo-form/partials/fields/name-field/style.module.css +0 -13
- package/src/components/marketo-form/partials/fields/radio-buttons-field/index.tsx +0 -48
- package/src/components/marketo-form/partials/fields/select-field/index.tsx +0 -39
- package/src/components/marketo-form/partials/fields/select-field/style.module.css +0 -5
- package/src/components/marketo-form/partials/fields/telephone-field/index.tsx +0 -30
- package/src/components/marketo-form/partials/fields/text-field/index.tsx +0 -30
- package/src/components/marketo-form/partials/fields/textarea-field/index.tsx +0 -29
- package/src/components/marketo-form/partials/label/index.tsx +0 -24
- package/src/components/marketo-form/partials/label/style.module.css +0 -12
- package/src/components/marketo-form/partials/visibility-rule/index.tsx +0 -84
- package/src/components/marketo-form/props.js +0 -66
- package/src/components/marketo-form/server/api-routes.ts +0 -109
- package/src/components/marketo-form/server/client.ts +0 -98
- package/src/components/marketo-form/server/index.ts +0 -8
- package/src/components/marketo-form/types.ts +0 -268
- package/src/components/marketo-form/utils.test.tsx +0 -103
- package/src/components/marketo-form/utils.ts +0 -449
- package/src/components/next-steps/index.tsx +0 -137
- package/src/components/next-steps/style.module.css +0 -270
- package/src/components/next-steps/types.ts +0 -63
- package/src/components/product-badge/index.test.tsx +0 -11
- package/src/components/product-badge/index.tsx +0 -42
- package/src/components/product-badge/style.module.css +0 -76
- package/src/components/products-used/index.tsx +0 -84
- package/src/components/products-used/style.module.css +0 -87
- package/src/components/products-used/types.ts +0 -31
- package/src/components/related-content/index.test.tsx +0 -74
- package/src/components/related-content/index.tsx +0 -56
- package/src/components/related-content/style.module.css +0 -89
- package/src/components/related-content/types.ts +0 -21
- package/src/components/subnav/helpers/areBasePathsMatching.ts +0 -13
- package/src/components/subnav/helpers/traverse/index.ts +0 -42
- package/src/components/subnav/helpers/useHeightRef.ts +0 -42
- package/src/components/subnav/helpers/useNavRef.ts +0 -30
- package/src/components/subnav/helpers/useOverflowRef.ts +0 -85
- package/src/components/subnav/helpers/useStuckRef.ts +0 -51
- package/src/components/subnav/index.tsx +0 -199
- package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.test.ts +0 -26
- package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.ts +0 -22
- package/src/components/subnav/partials/CtaLinks/github-stars-link/index.tsx +0 -87
- package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.test.ts +0 -29
- package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.ts +0 -32
- package/src/components/subnav/partials/CtaLinks/github-stars-link/style.module.css +0 -85
- package/src/components/subnav/partials/CtaLinks/icons/github-logo.js +0 -20
- package/src/components/subnav/partials/CtaLinks/icons/github.svg.js +0 -7
- package/src/components/subnav/partials/CtaLinks/icons/star.js +0 -20
- package/src/components/subnav/partials/CtaLinks/index.tsx +0 -130
- package/src/components/subnav/partials/CtaLinks/style.module.css +0 -45
- package/src/components/subnav/partials/DropdownTrigger/index.tsx +0 -35
- package/src/components/subnav/partials/DropdownTrigger/style.module.css +0 -36
- package/src/components/subnav/partials/MenuItemsDefault/index.tsx +0 -151
- package/src/components/subnav/partials/MenuItemsDefault/style.module.css +0 -91
- package/src/components/subnav/partials/MenuItemsOverflow/index.tsx +0 -139
- package/src/components/subnav/partials/MenuItemsOverflow/style.module.css +0 -82
- package/src/components/subnav/partials/TitleLink/index.tsx +0 -113
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-dark.ts +0 -9
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-light.ts +0 -9
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-dark.ts +0 -23
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-light.ts +0 -23
- package/src/components/subnav/partials/TitleLink/style.module.css +0 -43
- package/src/components/subnav/partials/nav-item-text/index.tsx +0 -37
- package/src/components/subnav/partials/nav-item-text/style.module.css +0 -15
- package/src/components/subnav/style.module.css +0 -68
- package/src/components/subnav/subnav-consts.ts +0 -1
- package/src/components/subnav/theme.module.css +0 -50
|
@@ -1,8 +1,31 @@
|
|
|
1
|
-
@custom-media --dev-dot-viewport (min-width:
|
|
1
|
+
@custom-media --dev-dot-viewport (min-width: 924px);
|
|
2
2
|
|
|
3
3
|
.productPanel {
|
|
4
4
|
height: 100%;
|
|
5
5
|
|
|
6
|
+
/* Temporarily included for devdot compatability
|
|
7
|
+
https://app.asana.com/1/90955849329269/project/1209320521286316/task/1210514680913728?focus=true */
|
|
8
|
+
--mds-spacing-01: 0.25rem;
|
|
9
|
+
--mds-spacing-02: 0.375rem;
|
|
10
|
+
--mds-spacing-03: 0.5rem;
|
|
11
|
+
--mds-spacing-04: 0.75rem;
|
|
12
|
+
--mds-spacing-05: 1rem;
|
|
13
|
+
--mds-spacing-06: 1.25rem;
|
|
14
|
+
--mds-spacing-07: 1.5rem;
|
|
15
|
+
--mds-spacing-08: 2rem;
|
|
16
|
+
--mds-spacing-09: 2.5rem;
|
|
17
|
+
--mds-spacing-10: 3rem;
|
|
18
|
+
--mds-spacing-11: 3.5rem;
|
|
19
|
+
--mds-spacing-12: 4rem;
|
|
20
|
+
--mds-spacing-13: 4.5rem;
|
|
21
|
+
--mds-spacing-14: 5.5rem;
|
|
22
|
+
--mds-spacing-15: 6rem;
|
|
23
|
+
--mds-spacing-16: 8rem;
|
|
24
|
+
--mds-spacing-17: 8.5rem;
|
|
25
|
+
--mds-typography-body-200-font-size: 0.875rem;
|
|
26
|
+
--mds-typography-font-weight-regular: 400;
|
|
27
|
+
--mds-typography-font-weight-semibold: 600;
|
|
28
|
+
|
|
6
29
|
@media (--large) {
|
|
7
30
|
&.noSide {
|
|
8
31
|
display: grid;
|
|
@@ -26,7 +49,11 @@
|
|
|
26
49
|
list-style: none;
|
|
27
50
|
padding: 0;
|
|
28
51
|
display: grid;
|
|
29
|
-
margin: var(--
|
|
52
|
+
margin: var(--mds-spacing-07) 0 0;
|
|
53
|
+
|
|
54
|
+
@nest .topPromo & {
|
|
55
|
+
margin-bottom: var(--mds-spacing-07);
|
|
56
|
+
}
|
|
30
57
|
|
|
31
58
|
@media (--large) {
|
|
32
59
|
@nest .noSide & {
|
|
@@ -48,27 +75,27 @@
|
|
|
48
75
|
|
|
49
76
|
&:first-child {
|
|
50
77
|
border-bottom: 1px solid var(--token-color-border-primary);
|
|
51
|
-
margin-bottom: var(--
|
|
52
|
-
padding-bottom: var(--
|
|
78
|
+
margin-bottom: var(--mds-spacing-05);
|
|
79
|
+
padding-bottom: var(--mds-spacing-05);
|
|
53
80
|
}
|
|
54
81
|
}
|
|
55
82
|
|
|
56
83
|
.eyebrow {
|
|
57
|
-
padding-bottom: var(--
|
|
84
|
+
padding-bottom: var(--mds-spacing-04);
|
|
58
85
|
color: var(--token-color-foreground-strong);
|
|
59
|
-
font-weight: var(--font-weight-
|
|
86
|
+
font-weight: var(--mds-typography-font-weight-semibold);
|
|
60
87
|
|
|
61
88
|
@media (--large) {
|
|
62
89
|
@nest .noSide & {
|
|
63
90
|
padding-bottom: 0;
|
|
64
|
-
padding-left: var(--
|
|
91
|
+
padding-left: var(--mds-spacing-06);
|
|
65
92
|
}
|
|
66
93
|
}
|
|
67
94
|
|
|
68
95
|
@media (--dev-dot-viewport) {
|
|
69
96
|
@nest .hasSide & {
|
|
70
97
|
padding-bottom: 0;
|
|
71
|
-
padding-left: var(--
|
|
98
|
+
padding-left: var(--mds-spacing-06);
|
|
72
99
|
}
|
|
73
100
|
}
|
|
74
101
|
}
|
|
@@ -82,8 +109,7 @@
|
|
|
82
109
|
|
|
83
110
|
@media (--large) {
|
|
84
111
|
@nest .noSide & {
|
|
85
|
-
padding: var(--
|
|
86
|
-
var(--hdsplus-spacing-04);
|
|
112
|
+
padding: var(--mds-spacing-06) var(--mds-spacing-05) var(--mds-spacing-04);
|
|
87
113
|
grid-auto-flow: row;
|
|
88
114
|
grid-template-columns: repeat(2, 300px);
|
|
89
115
|
grid-template-rows: repeat(2, max-content);
|
|
@@ -93,8 +119,7 @@
|
|
|
93
119
|
|
|
94
120
|
@media (--dev-dot-viewport) {
|
|
95
121
|
@nest .hasSide & {
|
|
96
|
-
padding: var(--
|
|
97
|
-
var(--hdsplus-spacing-04);
|
|
122
|
+
padding: var(--mds-spacing-06) var(--mds-spacing-05) var(--mds-spacing-04);
|
|
98
123
|
grid-auto-flow: row;
|
|
99
124
|
grid-template-columns: repeat(2, 300px);
|
|
100
125
|
grid-template-rows: repeat(2, max-content);
|
|
@@ -113,29 +138,29 @@
|
|
|
113
138
|
|
|
114
139
|
.productWrapper {
|
|
115
140
|
display: flex;
|
|
116
|
-
margin-bottom: var(--
|
|
117
|
-
gap: var(--
|
|
141
|
+
margin-bottom: var(--mds-spacing-05);
|
|
142
|
+
gap: var(--mds-spacing-05);
|
|
118
143
|
|
|
119
144
|
@media (--large) {
|
|
120
145
|
@nest .noSide & {
|
|
121
|
-
padding: var(--
|
|
146
|
+
padding: var(--mds-spacing-03) var(--mds-spacing-05);
|
|
122
147
|
margin-bottom: 0;
|
|
123
148
|
|
|
124
149
|
&:hover {
|
|
125
150
|
background-color: var(--token-color-surface-interactive-hover);
|
|
126
|
-
border-radius: var(--
|
|
151
|
+
border-radius: var(--mds-spacing-01);
|
|
127
152
|
}
|
|
128
153
|
}
|
|
129
154
|
}
|
|
130
155
|
|
|
131
156
|
@media (--dev-dot-viewport) {
|
|
132
157
|
@nest .hasSide & {
|
|
133
|
-
padding: var(--
|
|
158
|
+
padding: var(--mds-spacing-03) var(--mds-spacing-05);
|
|
134
159
|
margin-bottom: 0;
|
|
135
160
|
|
|
136
161
|
&:hover {
|
|
137
162
|
background-color: var(--token-color-surface-interactive-hover);
|
|
138
|
-
border-radius: var(--
|
|
163
|
+
border-radius: var(--mds-spacing-01);
|
|
139
164
|
}
|
|
140
165
|
}
|
|
141
166
|
}
|
|
@@ -152,8 +177,8 @@
|
|
|
152
177
|
@nest .noSide & {
|
|
153
178
|
& svg {
|
|
154
179
|
@media (--large) {
|
|
155
|
-
height: var(--
|
|
156
|
-
width: var(--
|
|
180
|
+
height: var(--mds-spacing-08);
|
|
181
|
+
width: var(--mds-spacing-08);
|
|
157
182
|
}
|
|
158
183
|
}
|
|
159
184
|
}
|
|
@@ -161,8 +186,8 @@
|
|
|
161
186
|
@nest .hasSide & {
|
|
162
187
|
& svg {
|
|
163
188
|
@media (--dev-dot-viewport) {
|
|
164
|
-
height: var(--
|
|
165
|
-
width: var(--
|
|
189
|
+
height: var(--mds-spacing-08);
|
|
190
|
+
width: var(--mds-spacing-08);
|
|
166
191
|
}
|
|
167
192
|
}
|
|
168
193
|
}
|
|
@@ -195,17 +220,29 @@
|
|
|
195
220
|
justify-content: space-between;
|
|
196
221
|
flex-direction: column;
|
|
197
222
|
|
|
223
|
+
@nest .topPromo & {
|
|
224
|
+
justify-content: flex-start;
|
|
225
|
+
}
|
|
226
|
+
|
|
198
227
|
@media (--large) {
|
|
199
228
|
@nest .noSide & {
|
|
200
|
-
padding: var(--
|
|
201
|
-
var(--
|
|
229
|
+
padding: var(--mds-spacing-07) 0 var(--mds-spacing-09)
|
|
230
|
+
var(--mds-spacing-04);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@nest .topPromo & {
|
|
234
|
+
padding-bottom: var(--mds-spacing-04);
|
|
202
235
|
}
|
|
203
236
|
}
|
|
204
237
|
|
|
205
238
|
@media (--dev-dot-viewport) {
|
|
206
239
|
@nest .hasSide & {
|
|
207
|
-
padding: var(--
|
|
208
|
-
var(--
|
|
240
|
+
padding: var(--mds-spacing-07) 0 var(--mds-spacing-09)
|
|
241
|
+
var(--mds-spacing-04);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@nest .topPromo & {
|
|
245
|
+
padding-bottom: var(--mds-spacing-04);
|
|
209
246
|
}
|
|
210
247
|
}
|
|
211
248
|
}
|
|
@@ -215,10 +252,10 @@
|
|
|
215
252
|
background: var(--token-color-surface-faint);
|
|
216
253
|
display: flex;
|
|
217
254
|
flex-direction: column;
|
|
218
|
-
gap: var(--
|
|
255
|
+
gap: var(--mds-spacing-05);
|
|
219
256
|
margin: 0;
|
|
220
|
-
padding: var(--
|
|
221
|
-
var(--
|
|
257
|
+
padding: var(--mds-spacing-07) var(--mds-spacing-04) var(--mds-spacing-09)
|
|
258
|
+
var(--mds-spacing-07);
|
|
222
259
|
}
|
|
223
260
|
|
|
224
261
|
.sidePanelItems {
|
|
@@ -227,24 +264,24 @@
|
|
|
227
264
|
padding: 0;
|
|
228
265
|
display: grid;
|
|
229
266
|
grid-template-columns: 1fr;
|
|
230
|
-
gap: var(--
|
|
267
|
+
gap: var(--mds-spacing-07);
|
|
231
268
|
|
|
232
269
|
@media (--dev-dot-viewport) {
|
|
233
|
-
gap: var(--
|
|
270
|
+
gap: var(--mds-spacing-05);
|
|
234
271
|
}
|
|
235
272
|
}
|
|
236
273
|
|
|
237
274
|
/* Lifted from .productWrapper */
|
|
238
275
|
.sidePanelItem {
|
|
239
276
|
display: flex;
|
|
240
|
-
gap: var(--
|
|
277
|
+
gap: var(--mds-spacing-05);
|
|
241
278
|
|
|
242
279
|
@media (--dev-dot-viewport) {
|
|
243
|
-
padding: var(--
|
|
280
|
+
padding: var(--mds-spacing-03) var(--mds-spacing-05);
|
|
244
281
|
|
|
245
282
|
&:hover {
|
|
246
283
|
background-color: var(--token-color-surface-interactive-hover);
|
|
247
|
-
border-radius: var(--
|
|
284
|
+
border-radius: var(--mds-spacing-01);
|
|
248
285
|
}
|
|
249
286
|
}
|
|
250
287
|
}
|
|
@@ -253,8 +290,8 @@
|
|
|
253
290
|
packages/react-components/src/components/nav-panel/components/link-list/style.module.css */
|
|
254
291
|
.iconBackground {
|
|
255
292
|
background: var(--token-color-foreground-high-contrast);
|
|
256
|
-
height: var(--
|
|
257
|
-
width: var(--
|
|
293
|
+
height: var(--mds-spacing-08);
|
|
294
|
+
width: var(--mds-spacing-08);
|
|
258
295
|
display: flex;
|
|
259
296
|
align-items: center;
|
|
260
297
|
justify-content: center;
|
|
@@ -301,7 +338,7 @@ packages/react-components/src/components/nav-panel/components/link-list/style.mo
|
|
|
301
338
|
*/
|
|
302
339
|
.hcpVaultSecrets,
|
|
303
340
|
.hcpVaultRadar {
|
|
304
|
-
padding: var(--
|
|
341
|
+
padding: var(--mds-spacing-01);
|
|
305
342
|
border: 2px solid var(--token-color-vault-brand);
|
|
306
343
|
border-radius: 3px;
|
|
307
344
|
|
|
@@ -313,3 +350,7 @@ packages/react-components/src/components/nav-panel/components/link-list/style.mo
|
|
|
313
350
|
fill: inherit;
|
|
314
351
|
}
|
|
315
352
|
}
|
|
353
|
+
|
|
354
|
+
.sidePanelText {
|
|
355
|
+
font-weight: var(--mds-typography-font-weight-semibold);
|
|
356
|
+
}
|
|
@@ -12,12 +12,14 @@ interface StandardPanelProps {
|
|
|
12
12
|
navData: NavItem[]
|
|
13
13
|
promo?: PromoProps
|
|
14
14
|
sectionName?: string
|
|
15
|
+
locale?: any
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
const StandardPanel = ({
|
|
18
19
|
navData,
|
|
19
20
|
promo,
|
|
20
21
|
sectionName = '',
|
|
22
|
+
locale,
|
|
21
23
|
}: StandardPanelProps) => {
|
|
22
24
|
return (
|
|
23
25
|
<NavPanel.Root>
|
|
@@ -26,6 +28,7 @@ const StandardPanel = ({
|
|
|
26
28
|
return (
|
|
27
29
|
<NavPanel.Column key={stableIdx}>
|
|
28
30
|
<LinkList
|
|
31
|
+
locale={locale}
|
|
29
32
|
links={navItems}
|
|
30
33
|
linkClickHandler={(text, href) => {
|
|
31
34
|
trackNavClickEvent(text, href, sectionName)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getLocalizedLinkProps } from '.'
|
|
2
|
+
|
|
3
|
+
describe('getLocalizedLinkProps', () => {
|
|
4
|
+
it('does not format localized homepage', () => {
|
|
5
|
+
const localizedLinkProps = getLocalizedLinkProps('/en', 'ja')
|
|
6
|
+
expect(localizedLinkProps.href).toBe('/en')
|
|
7
|
+
expect(localizedLinkProps.hrefLang).toBe('en')
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it('does not format localized path hrefs', () => {
|
|
11
|
+
const localizedLinkProps = getLocalizedLinkProps('/ja/solutions', 'de')
|
|
12
|
+
expect(localizedLinkProps.href).toBe('/ja/solutions')
|
|
13
|
+
expect(localizedLinkProps.hrefLang).toBe('ja')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('does format paths that start with a locale string', () => {
|
|
17
|
+
const localizedLinkProps = getLocalizedLinkProps(
|
|
18
|
+
'/deconstructing-cloud',
|
|
19
|
+
'en'
|
|
20
|
+
)
|
|
21
|
+
expect(localizedLinkProps.href).toBe('/en/deconstructing-cloud')
|
|
22
|
+
expect(localizedLinkProps.hrefLang).toBe('en')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('does not format external paths', () => {
|
|
26
|
+
const localizedLinkProps = getLocalizedLinkProps('https://google.com', 'ja')
|
|
27
|
+
expect(localizedLinkProps.href).toBe('https://google.com')
|
|
28
|
+
expect(localizedLinkProps.hrefLang).toBe(undefined)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { parseUrl } from '../parse-url'
|
|
2
|
+
import { allSupportedLocales } from '../supported-locales'
|
|
3
|
+
|
|
4
|
+
export const getLocalizedLinkProps = (
|
|
5
|
+
url: string,
|
|
6
|
+
locale?: string
|
|
7
|
+
): {
|
|
8
|
+
href: string
|
|
9
|
+
hrefLang: string | undefined
|
|
10
|
+
} => {
|
|
11
|
+
const parsedHref = parseUrl(url).href
|
|
12
|
+
|
|
13
|
+
// example: /en
|
|
14
|
+
const hrefIsLocalizedHomepage = allSupportedLocales.includes(
|
|
15
|
+
parsedHref.substring(1)
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
// true example: /en/solutions
|
|
19
|
+
// false example: /entry-point
|
|
20
|
+
const hrefIsLocalized =
|
|
21
|
+
allSupportedLocales.includes(parsedHref.substring(1, 3)) &&
|
|
22
|
+
parsedHref[3] === '/'
|
|
23
|
+
|
|
24
|
+
// If the href is already localized:
|
|
25
|
+
// - do not format the href
|
|
26
|
+
// - use the locale from the href for the hrefLang
|
|
27
|
+
if (hrefIsLocalizedHomepage || hrefIsLocalized) {
|
|
28
|
+
return {
|
|
29
|
+
href: parsedHref,
|
|
30
|
+
hrefLang: parsedHref.substring(1, 3),
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (parsedHref.startsWith('/') && locale) {
|
|
35
|
+
return {
|
|
36
|
+
href: `/${locale}${parsedHref}`,
|
|
37
|
+
hrefLang: locale,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
href: parsedHref,
|
|
43
|
+
hrefLang: undefined,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseUrl } from '.'
|
|
1
|
+
import { parseUrl, hasHashiCorpDestination } from '.'
|
|
2
2
|
|
|
3
3
|
describe('parseUrl', () => {
|
|
4
4
|
it('detects hashicorp.com URLs as internal', () => {
|
|
@@ -7,6 +7,12 @@ describe('parseUrl', () => {
|
|
|
7
7
|
expect(url.linkType).toBe('inbound')
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
+
it('detects www.hashicorp.com URLs as internal', () => {
|
|
11
|
+
const url = parseUrl('https://hashicorp.com/foo')
|
|
12
|
+
expect(url.href).toBe('/foo')
|
|
13
|
+
expect(url.linkType).toBe('inbound')
|
|
14
|
+
})
|
|
15
|
+
|
|
10
16
|
it('detects URLs not containing hashicorp.com as external', () => {
|
|
11
17
|
const externalUrl = 'https://google.com/example'
|
|
12
18
|
const url = parseUrl(externalUrl)
|
|
@@ -27,4 +33,37 @@ describe('parseUrl', () => {
|
|
|
27
33
|
)
|
|
28
34
|
expect(url.href).toBe('/resources?type=case-study&products=terraform')
|
|
29
35
|
})
|
|
36
|
+
|
|
37
|
+
it('leaves URL hash intact', () => {
|
|
38
|
+
const url = parseUrl('https://hashicorp.com/about#leadership')
|
|
39
|
+
expect(url.href).toBe('/about#leadership')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('leaves HashiCorp subdomain URLs intact', () => {
|
|
43
|
+
const url = parseUrl('https://developer.hashicorp.com/terraform')
|
|
44
|
+
expect(url.href).toBe('https://developer.hashicorp.com/terraform')
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
describe('hasHashiCorpDestination', () => {
|
|
49
|
+
it('returns true for supported hashicorp domains', () => {
|
|
50
|
+
const isHashiCorpDestination = hasHashiCorpDestination(
|
|
51
|
+
'https://portal.cloud.hashicorp.com/foo'
|
|
52
|
+
)
|
|
53
|
+
expect(isHashiCorpDestination).toBe(true)
|
|
54
|
+
})
|
|
55
|
+
it('returns false for external domains', () => {
|
|
56
|
+
const isHashiCorpDestination = hasHashiCorpDestination(
|
|
57
|
+
'https://foo.com/bar'
|
|
58
|
+
)
|
|
59
|
+
expect(isHashiCorpDestination).toBe(false)
|
|
60
|
+
})
|
|
61
|
+
it('returns true for relative links', () => {
|
|
62
|
+
const isHashiCorpDestination = hasHashiCorpDestination('/bar')
|
|
63
|
+
expect(isHashiCorpDestination).toBe(true)
|
|
64
|
+
})
|
|
65
|
+
it('returns true for hashes', () => {
|
|
66
|
+
const isHashiCorpDestination = hasHashiCorpDestination('#someHash')
|
|
67
|
+
expect(isHashiCorpDestination).toBe(true)
|
|
68
|
+
})
|
|
30
69
|
})
|
|
@@ -1,9 +1,46 @@
|
|
|
1
|
+
export const hashicorpDestinations: string[] = [
|
|
2
|
+
'app.terraform.io',
|
|
3
|
+
'boundaryproject.io',
|
|
4
|
+
'cloud.hashicorp.com',
|
|
5
|
+
'consul.io',
|
|
6
|
+
'developer.hashicorp.com',
|
|
7
|
+
'hashicorp.com',
|
|
8
|
+
'nomadproject.io',
|
|
9
|
+
'packer.io',
|
|
10
|
+
'portal.cloud.hashicorp.com',
|
|
11
|
+
'registry.terraform.io',
|
|
12
|
+
'terraform.io',
|
|
13
|
+
'vagrantup.com',
|
|
14
|
+
'vaultproject.io',
|
|
15
|
+
'waypointproject.io',
|
|
16
|
+
] as const
|
|
17
|
+
|
|
18
|
+
const containsHashiCorpDestination = (str: string): boolean =>
|
|
19
|
+
hashicorpDestinations.some(function (destination) {
|
|
20
|
+
return str.indexOf(destination) >= 0
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* This function determines if a `url` is a HashiCorp link (relative URLs, hashes,
|
|
25
|
+
* or a url with a HashiCorp domain) or a non-HashiCorp link.
|
|
26
|
+
*
|
|
27
|
+
* @param {string | undefined} url - The URL to be parsed. It may be a relative URL, an anchor, or a full external/internal URL.
|
|
28
|
+
*
|
|
29
|
+
* @returns {{ linkType: 'inbound' | 'outbound', href: string }}
|
|
30
|
+
* An object with two properties:
|
|
31
|
+
* - `linkType`: Indicates whether the URL is 'inbound' or 'outbound'. Can be used to conditionally
|
|
32
|
+
* render the value of the target attribute.
|
|
33
|
+
* - `href`: The parsed href (may include pathname, search, and hash for internal URLs).
|
|
34
|
+
*
|
|
35
|
+
* @throws {Error} Throws an error if the URL is undefined or invalid.
|
|
36
|
+
*/
|
|
1
37
|
export function parseUrl(url: string | undefined): {
|
|
2
|
-
linkType: 'inbound' | 'outbound'
|
|
38
|
+
linkType: 'inbound' | 'outbound' | ''
|
|
3
39
|
href: string
|
|
4
40
|
} {
|
|
5
41
|
if (!url) {
|
|
6
|
-
|
|
42
|
+
console.log('No url to parse, returning empty string')
|
|
43
|
+
return { linkType: '', href: '' }
|
|
7
44
|
}
|
|
8
45
|
|
|
9
46
|
if (isRelative(url) || isAnchor(url)) {
|
|
@@ -12,21 +49,50 @@ export function parseUrl(url: string | undefined): {
|
|
|
12
49
|
|
|
13
50
|
if (isInternal(url)) {
|
|
14
51
|
try {
|
|
15
|
-
const { pathname, search } = new URL(url)
|
|
16
|
-
const href = pathname + search
|
|
52
|
+
const { pathname, search, hash } = new URL(url)
|
|
53
|
+
const href = pathname + search + hash
|
|
17
54
|
return { linkType: 'inbound', href }
|
|
18
55
|
} catch (error) {
|
|
19
|
-
|
|
56
|
+
console.log(`Invalid href: ${url}`)
|
|
57
|
+
return { linkType: '', href: '' }
|
|
20
58
|
}
|
|
21
59
|
}
|
|
22
60
|
|
|
23
61
|
return { linkType: 'outbound', href: url }
|
|
24
62
|
}
|
|
25
63
|
|
|
26
|
-
const isRelative = (url) => url.startsWith('/')
|
|
27
|
-
const isAnchor = (url) => url.startsWith('#')
|
|
64
|
+
const isRelative = (url: string) => url.startsWith('/')
|
|
65
|
+
const isAnchor = (url: string) => url.startsWith('#')
|
|
28
66
|
|
|
29
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Determines whether the provided url uses hashicorp.com or www.hashicorp.com as the hostname.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} url - The URL to check.
|
|
71
|
+
* @returns {boolean} - Returns true if the link uses a HashiCorp domain, otherwise false.
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
export const isInternal = (url: string): boolean => {
|
|
30
75
|
const hostname = new URL(url).hostname
|
|
31
|
-
return hostname === 'hashicorp.com'
|
|
76
|
+
return hostname === 'hashicorp.com' || hostname === 'www.hashicorp.com'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Determines whether the provided url uses a HashiCorp hostname. This is used in several
|
|
81
|
+
* components to open a new tab for non-HashiCorp links.
|
|
82
|
+
*
|
|
83
|
+
* @param {string} url - The URL to check.
|
|
84
|
+
* @returns {boolean} - Returns true if the link uses a HashiCorp domain, otherwise false.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
export const hasHashiCorpDestination = (url: string): boolean => {
|
|
88
|
+
// Fast return in case a relative URL or anchor is passed in
|
|
89
|
+
if (isRelative(url) || isAnchor(url)) return true
|
|
90
|
+
try {
|
|
91
|
+
const hostname = new URL(url).hostname
|
|
92
|
+
const isHashiCorpDestination = containsHashiCorpDestination(hostname)
|
|
93
|
+
return isHashiCorpDestination
|
|
94
|
+
} catch (e) {
|
|
95
|
+
console.error('Error: `url` is not a valid URL', e)
|
|
96
|
+
return false
|
|
97
|
+
}
|
|
32
98
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import posthog from 'posthog-js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A custom hook to send a custom event to PostHog.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} eventName - The name of the custom event to be tracked in PostHog.
|
|
7
|
+
* @param {Record<string, any>} properties - A key-value object containing properties associated with the event.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const MyComponent = () => {
|
|
11
|
+
* sendPosthogEvent('button_click', { buttonId: 'submit', action: 'clicked' });
|
|
12
|
+
* return <button id="submit">Submit</button>;
|
|
13
|
+
* };
|
|
14
|
+
*/
|
|
15
|
+
const sendPosthogEvent = (
|
|
16
|
+
eventName: string,
|
|
17
|
+
properties: Record<string, any>
|
|
18
|
+
) => {
|
|
19
|
+
posthog.capture(eventName, properties)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default sendPosthogEvent
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const allSupportedLocales = ['en', 'de', 'es', 'fr', 'ja', 'ko', 'pt']
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import sendPosthogEvent from '../send-posthog-event'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Pushes a 'Nav link click' custom event to
|
|
5
|
-
* A wrapper around the
|
|
4
|
+
* Pushes a 'Nav link click' custom event to PostHog.
|
|
5
|
+
* A wrapper around the PostHog custom event method.
|
|
6
6
|
*
|
|
7
7
|
* @param {string} name - The name of the nav link
|
|
8
8
|
* @param {string} href - The href for the nav link
|
|
@@ -14,7 +14,7 @@ export const trackNavClickEvent = (
|
|
|
14
14
|
href: string,
|
|
15
15
|
section: string
|
|
16
16
|
) => {
|
|
17
|
-
|
|
17
|
+
sendPosthogEvent('Nav link click', {
|
|
18
18
|
name,
|
|
19
19
|
href,
|
|
20
20
|
section,
|
package/src/lib/v/index.ts
CHANGED
|
@@ -3,9 +3,8 @@ import { vercelStegaSplit } from '@vercel/stega'
|
|
|
3
3
|
/**
|
|
4
4
|
* Takes in a Vercel Visual Editing string and returns the string without
|
|
5
5
|
* hidden data.
|
|
6
|
+
*
|
|
6
7
|
*/
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
):
|
|
10
|
-
return vercelStegaSplit(s).cleaned as VercelVEString
|
|
11
|
-
}
|
|
8
|
+
export const vercelSplit = <VercelString>(
|
|
9
|
+
original: VercelString
|
|
10
|
+
): VercelString => vercelStegaSplit(original as string).cleaned as VercelString
|