@asd20/ui-next 2.34.2 → 2.34.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.34.4](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.34.3...ui-next-v2.34.4) (2026-11-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * edits to related page links in search results ([01e82a9](https://github.com/academydistrict20/asd20-ui-next/commit/01e82a98caef6c5ca809714a67c59e944682fd16))
9
+
10
+ ## [2.34.3](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.34.2...ui-next-v2.34.3) (2026-11-02)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * add relevant related links to page search results using keyword searches ([c1f9025](https://github.com/academydistrict20/asd20-ui-next/commit/c1f9025943fb45f35948c19259a3fa0642532d2d))
16
+
3
17
  ## [2.34.2](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.34.1...ui-next-v2.34.2) (2026-11-02)
4
18
 
5
19
  ## [2.34.1](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.34.0...ui-next-v2.34.1) (2026-10-28)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asd20/ui-next",
3
- "version": "2.34.2",
3
+ "version": "2.34.4",
4
4
  "private": false,
5
5
  "description": "ASD20 UI component library for Vue 3.",
6
6
  "license": "MIT",
@@ -0,0 +1,166 @@
1
+ <template>
2
+ <section
3
+ v-if="links.length"
4
+ class="asd20-matching-search-links"
5
+ aria-label="Matching links on this page"
6
+ @click.stop
7
+ >
8
+ <ul>
9
+ <li
10
+ v-for="link in visibleLinks"
11
+ :key="link.url"
12
+ >
13
+ <a
14
+ :href="link.url"
15
+ :target="link.newWindow ? '_blank' : undefined"
16
+ :rel="link.newWindow ? 'noopener noreferrer' : undefined"
17
+ @click="$emit('navigate', $event)"
18
+ >
19
+ {{ link.title }}
20
+ <span
21
+ v-if="link.external"
22
+ class="asd20-matching-search-links__external"
23
+ aria-label="External link"
24
+ >↗</span>
25
+ </a>
26
+ <p
27
+ v-if="link.description"
28
+ class="asd20-matching-search-links__description"
29
+ >
30
+ {{ link.description }}
31
+ </p>
32
+ </li>
33
+ </ul>
34
+ <button
35
+ v-if="links.length > 2"
36
+ type="button"
37
+ :aria-expanded="expanded"
38
+ @click="expanded = !expanded"
39
+ >
40
+ {{
41
+ expanded
42
+ ? 'Show fewer matching links'
43
+ : `Show ${links.length - 2} more matching links`
44
+ }}
45
+ </button>
46
+ </section>
47
+ </template>
48
+
49
+ <script>
50
+ import {
51
+ shouldOpenInNewWindow,
52
+ shouldShowExternalIcon,
53
+ } from '../../../helpers/linkPolicy'
54
+
55
+ export default {
56
+ name: 'Asd20MatchingSearchLinks',
57
+ props: {
58
+ matchingLinks: { type: Array, default: () => [] },
59
+ keywords: { type: String, default: '' },
60
+ pageUrl: { type: String, default: '' },
61
+ },
62
+ emits: ['navigate'],
63
+ data: () => ({ expanded: false }),
64
+ computed: {
65
+ links() {
66
+ const seen = new Set()
67
+ return this.matchingLinks
68
+ .flatMap(link => {
69
+ if (
70
+ !link ||
71
+ typeof link.title !== 'string' ||
72
+ !link.title.trim() ||
73
+ typeof link.url !== 'string' ||
74
+ !/^https?:\/\//i.test(link.url)
75
+ )
76
+ return []
77
+ try {
78
+ const url = new URL(link.url)
79
+ if (url.username || url.password || seen.has(url.href)) return []
80
+ seen.add(url.href)
81
+ const pageHost = this.pageUrl
82
+ ? new URL(this.pageUrl, 'https://www.asd20.org').hostname
83
+ : ''
84
+ return [
85
+ {
86
+ title: link.title.trim(),
87
+ url: url.href,
88
+ description:
89
+ typeof link.description === 'string' ? link.description : '',
90
+ external: shouldShowExternalIcon(url.href, pageHost),
91
+ newWindow: shouldOpenInNewWindow(url.href),
92
+ },
93
+ ]
94
+ } catch (_error) {
95
+ return []
96
+ }
97
+ })
98
+ .slice(0, 8)
99
+ },
100
+ visibleLinks() {
101
+ return this.expanded ? this.links : this.links.slice(0, 2)
102
+ },
103
+ },
104
+ watch: {
105
+ keywords() {
106
+ this.expanded = false
107
+ },
108
+ matchingLinks() {
109
+ this.expanded = false
110
+ },
111
+ },
112
+ }
113
+ </script>
114
+
115
+ <style scoped>
116
+ .asd20-matching-search-links {
117
+ padding: 0 1rem 1rem 3.25rem;
118
+ font-family: var(--website-typography__font-family-body);
119
+ min-width: 0;
120
+ overflow-wrap: anywhere;
121
+ }
122
+ ul {
123
+ list-style: none;
124
+ padding: 0;
125
+ margin: 0;
126
+ }
127
+ li {
128
+ border-inline-start: 2px solid var(--color__tertiary);
129
+ padding-inline-start: 0.75rem;
130
+ }
131
+ li + li {
132
+ margin-top: 0.75rem;
133
+ }
134
+ a {
135
+ color: var(--color__primary);
136
+ font-weight: 600;
137
+ text-decoration: none;
138
+ }
139
+ a:focus-visible,
140
+ button:focus-visible {
141
+ outline: 2px solid currentColor;
142
+ outline-offset: 3px;
143
+ }
144
+ .asd20-matching-search-links__description {
145
+ margin: 0.25rem 0;
146
+ font-size: 0.9375rem;
147
+ }
148
+ .asd20-matching-search-links__external {
149
+ margin-inline-start: 0.25rem;
150
+ }
151
+ button {
152
+ margin-top: 0.75rem;
153
+ padding: 0.25rem 0;
154
+ border: 0;
155
+ background: transparent;
156
+ color: var(--color__primary);
157
+ font: inherit;
158
+ text-decoration: underline;
159
+ cursor: pointer;
160
+ }
161
+ @media (max-width: 600px) {
162
+ .asd20-matching-search-links {
163
+ padding-inline: 1rem;
164
+ }
165
+ }
166
+ </style>
@@ -285,11 +285,28 @@
285
285
  />
286
286
 
287
287
  <asd20-list @click="dismiss">
288
- <asd20-list-item
288
+ <div
289
289
  v-for="item in pageListItems"
290
- v-bind="item"
291
290
  :key="item.page.id"
292
- />
291
+ class="asd20-site-search__page-result"
292
+ :class="{
293
+ 'asd20-site-search__page-result--matching':
294
+ item.page.matchingLinks && item.page.matchingLinks.length,
295
+ }"
296
+ >
297
+ <asd20-list-item
298
+ v-bind="item"
299
+ :bordered="
300
+ !(item.page.matchingLinks && item.page.matchingLinks.length)
301
+ "
302
+ />
303
+ <asd20-matching-search-links
304
+ :matching-links="item.page.matchingLinks || []"
305
+ :keywords="keywords"
306
+ :page-url="item.page.url"
307
+ @navigate="dismiss"
308
+ />
309
+ </div>
293
310
  </asd20-list>
294
311
 
295
312
  <asd20-loader
@@ -555,6 +572,7 @@ import Asd20Spinner from '../../atoms/Asd20Spinner'
555
572
 
556
573
  import debounce from 'lodash/debounce'
557
574
  import mapPagesToListItems from '../../../helpers/mapPagesToListItems'
575
+ import Asd20MatchingSearchLinks from '../../molecules/Asd20MatchingSearchLinks'
558
576
  import mapFilesToListItems from '../../../helpers/mapFilesToListItems'
559
577
  import mapPeopleToListItems from '../../../helpers/mapPeopleToListItems'
560
578
  import logSearchAnalytics from '../../../helpers/logSearchAnalytics'
@@ -610,6 +628,7 @@ export default {
610
628
  name: 'Asd20SiteSearch',
611
629
 
612
630
  components: {
631
+ Asd20MatchingSearchLinks,
613
632
  Asd20SearchField,
614
633
  Asd20List,
615
634
  Asd20ListItem,
@@ -3622,6 +3641,14 @@ export default {
3622
3641
  <style lang="scss" scoped>
3623
3642
  @use '../../../design/component-stack' as *;
3624
3643
 
3644
+ .asd20-site-search__page-result {
3645
+ min-width: 0;
3646
+ width: 100%;
3647
+ }
3648
+ .asd20-site-search__page-result--matching {
3649
+ border-bottom: 1px solid var(--color__tertiary);
3650
+ }
3651
+
3625
3652
  .asd20-site-search {
3626
3653
  position: fixed;
3627
3654
  z-index: 311;