@salesforcedevs/arch-components 1.28.5-node22-1 → 1.29.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.
- package/LICENSE +12 -0
- package/lwc.config.json +1 -1
- package/package.json +47 -46
- package/src/modules/arch/browserLocale/browserLocale.ts +104 -0
- package/src/modules/arch/localePreference/localePreference.ts +72 -0
- package/src/modules/arch/searchHybrid/searchHybrid.css +113 -0
- package/src/modules/arch/searchHybrid/searchHybrid.html +164 -0
- package/src/modules/arch/searchHybrid/searchHybrid.ts +299 -0
- package/src/modules/arch/searchList/searchList.css +6 -0
- package/src/modules/arch/searchList/searchList.html +18 -3
- package/src/modules/arch/searchList/searchList.ts +188 -41
- package/src/modules/arch/select/select.html +2 -1
- package/src/modules/arch/content/__fixtures__/index.ts +0 -884
- package/src/modules/arch/content/content.css +0 -643
- package/src/modules/arch/content/content.html +0 -65
- package/src/modules/arch/content/content.stories.js +0 -21
- package/src/modules/arch/content/content.ts +0 -169
package/LICENSE
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Copyright (c) 2020, Salesforce.com, Inc.
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
7
|
+
|
|
8
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
9
|
+
|
|
10
|
+
* Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
11
|
+
|
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/lwc.config.json
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"arch/cardGridD",
|
|
16
16
|
"arch/cardNew",
|
|
17
17
|
"arch/children",
|
|
18
|
-
"arch/content",
|
|
19
18
|
"arch/contentIcon",
|
|
20
19
|
"arch/context",
|
|
21
20
|
"arch/contextAdapter",
|
|
@@ -31,6 +30,7 @@
|
|
|
31
30
|
"arch/pageHeaderA",
|
|
32
31
|
"arch/pill",
|
|
33
32
|
"arch/reflectedElement",
|
|
33
|
+
"arch/searchHybrid",
|
|
34
34
|
"arch/searchList",
|
|
35
35
|
"arch/sectionA",
|
|
36
36
|
"arch/select",
|
package/package.json
CHANGED
|
@@ -1,47 +1,48 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
2
|
+
"name": "@salesforcedevs/arch-components",
|
|
3
|
+
"version": "1.29.0",
|
|
4
|
+
"description": "Architect Lightning web components",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": "22.x"
|
|
8
|
+
},
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@coveo/headless": "3.22.2",
|
|
14
|
+
"@floating-ui/dom": "1.5.1",
|
|
15
|
+
"@optimizely/optimizely-sdk": "5.3.0",
|
|
16
|
+
"@shikijs/colorized-brackets": "^3.12.2",
|
|
17
|
+
"@types/throttle-debounce": "5.0.2",
|
|
18
|
+
"@vimeo/player": "2.22.0",
|
|
19
|
+
"classnames": "2.5.1",
|
|
20
|
+
"composed-offset-position": "0.0.4",
|
|
21
|
+
"coveo-search-ui": "2.10113.0",
|
|
22
|
+
"debounce": "1.2.1",
|
|
23
|
+
"js-cookie": "3.0.5",
|
|
24
|
+
"jspdf": "^2.5.1",
|
|
25
|
+
"lodash.defaults": "4.2.0",
|
|
26
|
+
"lodash.get": "4.4.2",
|
|
27
|
+
"lodash.kebabcase": "4.1.1",
|
|
28
|
+
"memoize-one": "6.0.0",
|
|
29
|
+
"microtip": "0.2.2",
|
|
30
|
+
"shiki": "^3.12.2",
|
|
31
|
+
"throttle-debounce": "5.0.0",
|
|
32
|
+
"uuid": "9.0.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/classnames": "2.3.1",
|
|
36
|
+
"@types/debounce": "1.2.4",
|
|
37
|
+
"@types/js-cookie": "3.0.6",
|
|
38
|
+
"@types/lodash.defaults": "4.2.9",
|
|
39
|
+
"@types/lodash.get": "4.4.9",
|
|
40
|
+
"@types/lodash.kebabcase": "4.1.9",
|
|
41
|
+
"@types/luxon": "3.4.2",
|
|
42
|
+
"@types/uuid": "8.3.4",
|
|
43
|
+
"@types/vimeo__player": "2.18.3",
|
|
44
|
+
"eventsourcemock": "2.0.0",
|
|
45
|
+
"luxon": "3.4.4"
|
|
46
|
+
},
|
|
47
|
+
"gitHead": "5d072e2fa81d7eccadcbfb4134ee007ce2b0c7c4"
|
|
48
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Resolves a browser's preferred language (BCP-47 tags from
|
|
3
|
+
* navigator.languages) to one of the site's supported locale ids
|
|
4
|
+
* (e.g. "en-us", "ja-jp", "zh-tw"). Used to pick a sensible default language
|
|
5
|
+
* for search when the page itself carries no locale.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const DEFAULT_LOCALE = "en-us";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Region/script-aware overrides for cases a plain language-only match can't
|
|
12
|
+
* resolve. Keys are normalized lowercase BCP-47 tags (or language-only codes);
|
|
13
|
+
* values are site locale ids. Order of checks: exact id -> these rules ->
|
|
14
|
+
* language-only first match -> default.
|
|
15
|
+
*
|
|
16
|
+
* Product decisions baked in (see search locale design):
|
|
17
|
+
* - bare "es" -> es-mx (languages.yml lists es-mx as the generic Spanish)
|
|
18
|
+
* - any pt-* -> pt-br (only Brazilian Portuguese is published)
|
|
19
|
+
* - no/nb/nn -> nb-no (only Norwegian id)
|
|
20
|
+
* - Chinese is matched on script/region, never collapsed to language-only.
|
|
21
|
+
*/
|
|
22
|
+
const TAG_OVERRIDES: Record<string, string> = {
|
|
23
|
+
// Chinese — Traditional
|
|
24
|
+
"zh-tw": "zh-tw",
|
|
25
|
+
"zh-hant": "zh-tw",
|
|
26
|
+
"zh-hk": "zh-tw",
|
|
27
|
+
"zh-mo": "zh-tw",
|
|
28
|
+
// Chinese — Simplified (and bare "zh")
|
|
29
|
+
zh: "zh-cn",
|
|
30
|
+
"zh-cn": "zh-cn",
|
|
31
|
+
"zh-hans": "zh-cn",
|
|
32
|
+
"zh-sg": "zh-cn",
|
|
33
|
+
// Spanish
|
|
34
|
+
es: "es-mx",
|
|
35
|
+
"es-es": "es-es",
|
|
36
|
+
// Portuguese (only pt-br exists)
|
|
37
|
+
pt: "pt-br",
|
|
38
|
+
"pt-pt": "pt-br",
|
|
39
|
+
// Norwegian (only nb-no exists)
|
|
40
|
+
no: "nb-no",
|
|
41
|
+
nb: "nb-no",
|
|
42
|
+
nn: "nb-no"
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Map a single language-only code (e.g. "ja", "de") to its site locale id by
|
|
47
|
+
* finding the first supported id whose language subtag matches.
|
|
48
|
+
*/
|
|
49
|
+
function languageOnlyMatch(
|
|
50
|
+
language: string,
|
|
51
|
+
supportedIds: string[]
|
|
52
|
+
): string | undefined {
|
|
53
|
+
return supportedIds.find((id) => id.split("-")[0] === language);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the best site locale id for the given browser languages.
|
|
58
|
+
* The first browser language that maps to a supported id wins; earlier entries
|
|
59
|
+
* take precedence over later ones (matching navigator.languages ordering).
|
|
60
|
+
* @param navigatorLanguages Ordered list of BCP-47 tags (navigator.languages).
|
|
61
|
+
* @param supportedIds Site locale ids actually offered (e.g. from the dropdown).
|
|
62
|
+
* @returns A supported locale id, or "en-us" if nothing matches.
|
|
63
|
+
*/
|
|
64
|
+
export function resolveBrowserLocale(
|
|
65
|
+
navigatorLanguages: readonly string[] | undefined,
|
|
66
|
+
supportedIds: string[]
|
|
67
|
+
): string {
|
|
68
|
+
if (!navigatorLanguages || navigatorLanguages.length === 0) {
|
|
69
|
+
return DEFAULT_LOCALE;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const supported = new Set(supportedIds);
|
|
73
|
+
|
|
74
|
+
for (const raw of navigatorLanguages) {
|
|
75
|
+
if (!raw) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const tag = raw.toLowerCase();
|
|
79
|
+
|
|
80
|
+
// 1. Exact id match (e.g. "ja-jp" -> ja-jp).
|
|
81
|
+
if (supported.has(tag)) {
|
|
82
|
+
return tag;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 2. Region/script override (e.g. "zh-tw" -> zh-tw, "es" -> es-mx).
|
|
86
|
+
const overridden = TAG_OVERRIDES[tag];
|
|
87
|
+
if (overridden && supported.has(overridden)) {
|
|
88
|
+
return overridden;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 3. Language-only fall-through (e.g. "de-ch" -> de -> de-de).
|
|
92
|
+
const language = tag.split("-")[0];
|
|
93
|
+
const overriddenLang = TAG_OVERRIDES[language];
|
|
94
|
+
if (overriddenLang && supported.has(overriddenLang)) {
|
|
95
|
+
return overriddenLang;
|
|
96
|
+
}
|
|
97
|
+
const matched = languageOnlyMatch(language, supportedIds);
|
|
98
|
+
if (matched) {
|
|
99
|
+
return matched;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return DEFAULT_LOCALE;
|
|
104
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Per-device storage for the user's chosen search language, gated behind
|
|
3
|
+
* OneTrust functional-cookie consent.
|
|
4
|
+
*
|
|
5
|
+
* There is no shared consent util in the codebase; this mirrors the consent
|
|
6
|
+
* read used on the admin site (page-events-calendar.php's one_trust_notice),
|
|
7
|
+
* which parses the OptanonConsent cookie's `groups` field and inspects the
|
|
8
|
+
* functional category. OneTrust's standard functional group id is C0003;
|
|
9
|
+
* "C0003:1" means granted, "C0003:0" means denied.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const STORAGE_KEY = "arch-search-language";
|
|
13
|
+
const FUNCTIONAL_GROUP_ID = "C0003";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Read the OptanonConsent cookie and return whether the functional group is
|
|
17
|
+
* granted. Defensive: if OneTrust hasn't loaded or the cookie is absent
|
|
18
|
+
* (tests, pre-consent, non-prod), returns false so we never persist without
|
|
19
|
+
* an explicit grant.
|
|
20
|
+
*/
|
|
21
|
+
function hasFunctionalConsent(): boolean {
|
|
22
|
+
try {
|
|
23
|
+
const cookie = document.cookie
|
|
24
|
+
.split("; ")
|
|
25
|
+
.find((row) => row.startsWith("OptanonConsent="));
|
|
26
|
+
if (!cookie) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
// The cookie value is URL-encoded querystring-style, e.g.
|
|
30
|
+
// "...&groups=C0001:1,C0003:1,C0002:0&...".
|
|
31
|
+
const value = decodeURIComponent(cookie.split("=").slice(1).join("="));
|
|
32
|
+
const groups = new URLSearchParams(value).get("groups");
|
|
33
|
+
if (!groups) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return groups
|
|
37
|
+
.split(",")
|
|
38
|
+
.some((entry) => entry.trim() === `${FUNCTIONAL_GROUP_ID}:1`);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the stored language preference, or null if none / unavailable.
|
|
46
|
+
* Reading an already-stored preference is low-risk, so it is not consent-gated.
|
|
47
|
+
*/
|
|
48
|
+
export function getStoredLanguage(): string | null {
|
|
49
|
+
try {
|
|
50
|
+
return window.localStorage.getItem(STORAGE_KEY);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Persist the chosen language, but only if the user has granted functional
|
|
58
|
+
* consent. Returns true if the value was written, false if it was skipped
|
|
59
|
+
* (no consent) or failed. When skipped, the choice still applies for the
|
|
60
|
+
* current page/session via in-memory state and the ?lang= URL param.
|
|
61
|
+
*/
|
|
62
|
+
export function setStoredLanguage(language: string): boolean {
|
|
63
|
+
if (!language || !hasFunctionalConsent()) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
window.localStorage.setItem(STORAGE_KEY, language);
|
|
68
|
+
return true;
|
|
69
|
+
} catch (e) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
@import "arch/reset";
|
|
2
|
+
|
|
3
|
+
:host {
|
|
4
|
+
font-size: var(--arch-font-size-md);
|
|
5
|
+
position: relative;
|
|
6
|
+
width: 100%;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.search-toolbar {
|
|
10
|
+
display: flex;
|
|
11
|
+
gap: var(--arch-spacing-4);
|
|
12
|
+
justify-content: flex-end;
|
|
13
|
+
margin-bottom: var(--arch-spacing-4);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.search-language-selector,
|
|
17
|
+
.search-sort-selector {
|
|
18
|
+
display: flex;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.search-facets {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-wrap: wrap;
|
|
24
|
+
gap: var(--arch-spacing-2);
|
|
25
|
+
margin-bottom: var(--arch-spacing-4);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.search-facet-chip {
|
|
29
|
+
align-items: center;
|
|
30
|
+
background-color: white;
|
|
31
|
+
border: 1px solid var(--arch-color-fog);
|
|
32
|
+
border-radius: var(--arch-radius-lg);
|
|
33
|
+
color: var(--arch-color-black);
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
display: inline-flex;
|
|
36
|
+
font-family: inherit;
|
|
37
|
+
font-size: var(--arch-font-size-sm);
|
|
38
|
+
gap: var(--arch-spacing-2);
|
|
39
|
+
padding: var(--arch-spacing-1) var(--arch-spacing-3);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.search-facet-chip[aria-pressed="true"] {
|
|
43
|
+
background-color: var(--arch-color-meteorite);
|
|
44
|
+
border-color: var(--arch-color-meteorite);
|
|
45
|
+
color: white;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.search-facet-count {
|
|
49
|
+
font-size: var(--arch-font-size-xs);
|
|
50
|
+
opacity: 0.8;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.search-summary {
|
|
54
|
+
color: var(--arch-color-granite);
|
|
55
|
+
font-size: var(--arch-font-size-sm);
|
|
56
|
+
margin-bottom: var(--arch-spacing-4);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Semantic results list (WCAG 1.3.1) — reset the list chrome so the visual
|
|
60
|
+
is identical to the prior div-based markup. */
|
|
61
|
+
.search-result-list {
|
|
62
|
+
list-style: none;
|
|
63
|
+
margin: 0;
|
|
64
|
+
padding: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.search-result-type {
|
|
68
|
+
color: var(--arch-color-meteorite);
|
|
69
|
+
font-size: var(--arch-font-size-sm);
|
|
70
|
+
line-height: var(--arch-line-height-snug);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.search-state {
|
|
74
|
+
padding: var(--arch-spacing-6) 0;
|
|
75
|
+
text-align: center;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.search-state-error {
|
|
79
|
+
color: var(--arch-color-error, #c23934);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.search-pagination {
|
|
83
|
+
align-items: center;
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-wrap: wrap;
|
|
86
|
+
gap: var(--arch-spacing-2);
|
|
87
|
+
justify-content: center;
|
|
88
|
+
margin-top: var(--arch-spacing-6);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.search-pagination button {
|
|
92
|
+
background-color: white;
|
|
93
|
+
border: 1px solid var(--arch-color-fog);
|
|
94
|
+
border-radius: var(--arch-radius-md);
|
|
95
|
+
color: var(--arch-color-black);
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
font-family: inherit;
|
|
98
|
+
font-size: var(--arch-font-size-sm);
|
|
99
|
+
min-width: 2.5rem;
|
|
100
|
+
padding: var(--arch-spacing-1) var(--arch-spacing-3);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.search-pagination button[disabled] {
|
|
104
|
+
cursor: default;
|
|
105
|
+
opacity: 0.5;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.search-pagination button[aria-current="page"] {
|
|
109
|
+
background-color: var(--arch-color-meteorite);
|
|
110
|
+
border-color: var(--arch-color-meteorite);
|
|
111
|
+
color: white;
|
|
112
|
+
opacity: 1;
|
|
113
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<arch-section-a background="white" title="Search">
|
|
3
|
+
<div class="search-toolbar">
|
|
4
|
+
<template lwc:if={showLanguageSelector}>
|
|
5
|
+
<div class="search-language-selector">
|
|
6
|
+
<arch-select
|
|
7
|
+
assistive-text="Search language"
|
|
8
|
+
value={language}
|
|
9
|
+
onchange={handleLanguageChange}
|
|
10
|
+
>
|
|
11
|
+
<template for:each={localeOptions} for:item="locale">
|
|
12
|
+
<option key={locale.id} value={locale.id}>
|
|
13
|
+
{locale.displayText}
|
|
14
|
+
</option>
|
|
15
|
+
</template>
|
|
16
|
+
</arch-select>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
<div class="search-sort-selector">
|
|
20
|
+
<arch-select
|
|
21
|
+
assistive-text="Sort results"
|
|
22
|
+
value={sort}
|
|
23
|
+
onchange={handleSortChange}
|
|
24
|
+
>
|
|
25
|
+
<template for:each={sortChoices} for:item="choice">
|
|
26
|
+
<option key={choice.id} value={choice.id}>
|
|
27
|
+
{choice.displayText}
|
|
28
|
+
</option>
|
|
29
|
+
</template>
|
|
30
|
+
</arch-select>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<template lwc:if={showFacets}>
|
|
35
|
+
<div class="search-facets" role="group" aria-label="Filter by type">
|
|
36
|
+
<template for:each={contentTypeFacets} for:item="facet">
|
|
37
|
+
<button
|
|
38
|
+
key={facet.value}
|
|
39
|
+
type="button"
|
|
40
|
+
class="search-facet-chip"
|
|
41
|
+
data-value={facet.value}
|
|
42
|
+
aria-pressed={facet.active}
|
|
43
|
+
onclick={handleFacetClick}
|
|
44
|
+
>
|
|
45
|
+
{facet.label}
|
|
46
|
+
<span class="search-facet-count">{facet.count}</span>
|
|
47
|
+
</button>
|
|
48
|
+
</template>
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<template lwc:if={isLoading}>
|
|
53
|
+
<div class="search-state search-state-loading">
|
|
54
|
+
<arch-spinner size="medium"></arch-spinner>
|
|
55
|
+
</div>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<template lwc:if={isIdle}>
|
|
59
|
+
<div class="search-state search-state-idle">
|
|
60
|
+
<p>Enter a search to get started.</p>
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
|
|
64
|
+
<template lwc:if={isError}>
|
|
65
|
+
<div class="search-state search-state-error" role="alert">
|
|
66
|
+
<p>{errorMessage}</p>
|
|
67
|
+
</div>
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<template lwc:if={isEmpty}>
|
|
71
|
+
<div class="search-state search-state-empty">
|
|
72
|
+
<center>
|
|
73
|
+
<img
|
|
74
|
+
src="https://developer.salesforce.com/ns-assets/ruth_search.png"
|
|
75
|
+
alt="Search tips illustration"
|
|
76
|
+
/>
|
|
77
|
+
<h4 style="padding-top: 8px">Here are some search tips</h4>
|
|
78
|
+
<span style="display: block">
|
|
79
|
+
Check the spelling of your keywords.
|
|
80
|
+
</span>
|
|
81
|
+
<span style="display: block">
|
|
82
|
+
Try using fewer, different, or more general words.
|
|
83
|
+
</span>
|
|
84
|
+
</center>
|
|
85
|
+
</div>
|
|
86
|
+
</template>
|
|
87
|
+
|
|
88
|
+
<template lwc:if={hasResults}>
|
|
89
|
+
<p class="search-summary">{summaryText}</p>
|
|
90
|
+
<ul class="search-result-list">
|
|
91
|
+
<template for:each={results} for:item="result">
|
|
92
|
+
<li class="search-result-item" key={result.key}>
|
|
93
|
+
<arch-summary
|
|
94
|
+
compact
|
|
95
|
+
display-mode="brick-tile"
|
|
96
|
+
path={result.url}
|
|
97
|
+
title={result.decodedTitle}
|
|
98
|
+
>
|
|
99
|
+
<div slot="pretitle">
|
|
100
|
+
<template lwc:if={result.hasContentType}>
|
|
101
|
+
<span class="search-result-type">
|
|
102
|
+
{result.contentType}
|
|
103
|
+
</span>
|
|
104
|
+
</template>
|
|
105
|
+
</div>
|
|
106
|
+
<span slot="meta-right">
|
|
107
|
+
<template lwc:if={result.hasDate}>
|
|
108
|
+
<time>{result.displayDate}</time>
|
|
109
|
+
</template>
|
|
110
|
+
</span>
|
|
111
|
+
<span slot="meta-left">
|
|
112
|
+
<template lwc:if={result.hasDescription}>
|
|
113
|
+
{result.decodedDescription}
|
|
114
|
+
</template>
|
|
115
|
+
</span>
|
|
116
|
+
</arch-summary>
|
|
117
|
+
<!-- prettier-ignore -->
|
|
118
|
+
<hr>
|
|
119
|
+
</li>
|
|
120
|
+
</template>
|
|
121
|
+
</ul>
|
|
122
|
+
|
|
123
|
+
<template lwc:if={showPagination}>
|
|
124
|
+
<nav
|
|
125
|
+
class="search-pagination"
|
|
126
|
+
aria-label="Search results pages"
|
|
127
|
+
>
|
|
128
|
+
<button
|
|
129
|
+
type="button"
|
|
130
|
+
class="search-page-prev"
|
|
131
|
+
aria-label="Previous page"
|
|
132
|
+
disabled={isFirstPage}
|
|
133
|
+
onclick={handlePrevPage}
|
|
134
|
+
>
|
|
135
|
+
Previous
|
|
136
|
+
</button>
|
|
137
|
+
<template for:each={pageButtons} for:item="pageButton">
|
|
138
|
+
<button
|
|
139
|
+
key={pageButton.page}
|
|
140
|
+
type="button"
|
|
141
|
+
class="search-page-number"
|
|
142
|
+
data-page={pageButton.page}
|
|
143
|
+
aria-label={pageButton.label}
|
|
144
|
+
aria-current={pageButton.ariaCurrent}
|
|
145
|
+
disabled={pageButton.isCurrent}
|
|
146
|
+
onclick={handlePageClick}
|
|
147
|
+
>
|
|
148
|
+
{pageButton.label}
|
|
149
|
+
</button>
|
|
150
|
+
</template>
|
|
151
|
+
<button
|
|
152
|
+
type="button"
|
|
153
|
+
class="search-page-next"
|
|
154
|
+
aria-label="Next page"
|
|
155
|
+
disabled={isLastPage}
|
|
156
|
+
onclick={handleNextPage}
|
|
157
|
+
>
|
|
158
|
+
Next
|
|
159
|
+
</button>
|
|
160
|
+
</nav>
|
|
161
|
+
</template>
|
|
162
|
+
</template>
|
|
163
|
+
</arch-section-a>
|
|
164
|
+
</template>
|