@asd20/ui-next 2.10.8 → 2.10.10

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.10.10](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.10.9...ui-next-v2.10.10) (2026-05-20)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * normalize card slugs ([d5a7119](https://github.com/academydistrict20/asd20-ui-next/commit/d5a7119690c453a3b19a879aac311dcf43f945b5))
9
+
10
+ ## [2.10.9](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.10.8...ui-next-v2.10.9) (2026-05-19)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * add storybook fix for _media urls; add event modal animation ([55c1167](https://github.com/academydistrict20/asd20-ui-next/commit/55c1167e6a6259c8fc2580a6c3bd29b0e5675651))
16
+
3
17
  ## [2.10.8](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.10.7...ui-next-v2.10.8) (2026-05-15)
4
18
 
5
19
  ## [2.10.7](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.10.6...ui-next-v2.10.7) (2026-05-15)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asd20/ui-next",
3
- "version": "2.10.8",
3
+ "version": "2.10.10",
4
4
  "private": false,
5
5
  "description": "ASD20 UI component library for Vue 3.",
6
6
  "license": "MIT",
@@ -1,9 +1,11 @@
1
1
  <template>
2
- <div :class="['asd20-language-translation', { 'asd20-language-translation--no-label': noLabel }]">
3
- <asd20-loader
4
- v-show="_languageLoading"
5
- size="sm"
6
- ></asd20-loader>
2
+ <div
3
+ :class="[
4
+ 'asd20-language-translation',
5
+ { 'asd20-language-translation--no-label': noLabel },
6
+ ]"
7
+ >
8
+ <asd20-loader v-show="_languageLoading" size="sm"></asd20-loader>
7
9
  <asd20-select-input
8
10
  v-show="languageOptions"
9
11
  v-model="resolvedLanguageCode"
@@ -94,18 +96,29 @@ export default {
94
96
  /* margin-bottom: space(0.5);*/
95
97
  background: transparent;
96
98
  }
99
+ & :deep(.asd20-select-input__select-wrapper:focus) {
100
+ border-top-right-radius: 1rem;
101
+ border-bottom-right-radius: 1rem;
102
+ }
97
103
  & :deep(.asd20-select-input) {
98
104
  margin-bottom: 0;
105
+ padding-right: 0.5rem;
99
106
  .asd20-icon {
100
- margin-left: space(0.25);
107
+ margin: 0 space(0.25);
101
108
  width: 32px !important;
102
109
  height: 32px !important;
103
110
  --line-color: var(--website-icon__line-color) !important;
104
111
  --fill-color: var(--website-menu__icon-fill-color) !important;
105
112
  }
106
113
  }
107
- & :deep(.asd20-select-input__overlay-label)::after {
108
- margin-right: space(1);
114
+ & :deep(.asd20-select-input__overlay-label) {
115
+ padding: 0.375rem 0.75rem 0.375rem 0.5rem;
116
+ border-top-right-radius: 1rem;
117
+ border-bottom-right-radius: 1rem;
118
+ }
119
+ & :deep(.asd20-select-input select:focus) {
120
+ border-top-right-radius: 1rem;
121
+ border-bottom-right-radius: 1rem;
109
122
  }
110
123
  &--no-label {
111
124
  border-radius: 50%;
@@ -504,11 +504,15 @@ export default {
504
504
  height: 2.75rem;
505
505
  font-size: 0.95rem;
506
506
  background: transparent;
507
+ padding-left: 2.5rem;
508
+ padding-right: 1rem;
507
509
  }
508
510
 
509
511
  :deep(.asd20-search-field input:focus) {
510
- box-shadow: none;
511
- outline: none;
512
+ // box-shadow: none !important;
513
+ // outline: none !important;
514
+ border-top-left-radius: 2rem;
515
+ border-bottom-left-radius: 2rem;
512
516
  }
513
517
 
514
518
  :deep(.asd20-search-field input::-webkit-search-cancel-button) {
@@ -558,6 +562,7 @@ export default {
558
562
  position: relative;
559
563
  flex: 1 1 auto;
560
564
  min-width: 0;
565
+ padding-left: 0.5rem;
561
566
  }
562
567
 
563
568
  &__go-button {
@@ -22,6 +22,7 @@
22
22
  <script>
23
23
  import Asd20PageFooter from '../../../components/organisms/Asd20PageFooter'
24
24
  import Asd20QuicklinksMenu from '../../../components/organisms/Asd20QuicklinksMenu'
25
+ import { resolveMediaCssUrl } from '../../../helpers/mediaUrl'
25
26
 
26
27
  export default {
27
28
  name: 'Asd20DistrictVideoFooter',
@@ -56,7 +57,9 @@ export default {
56
57
  if (isDistrict) {
57
58
  return {
58
59
  '--asd20-district-footer-image':
59
- "url('/_media/asd20-images/page-images/asd20-footer-image.jpg')",
60
+ resolveMediaCssUrl(
61
+ 'asd20-images/page-images/asd20-footer-image.jpg'
62
+ ),
60
63
  }
61
64
  }
62
65
 
@@ -191,6 +191,43 @@ export default {
191
191
  height: 10rem;
192
192
  margin-bottom: space(1);
193
193
  border-radius: 999px;
194
+ &::before {
195
+ content: '';
196
+ position: absolute;
197
+ z-index: -1;
198
+ inset: -0.15rem;
199
+ border-radius: inherit;
200
+ background: conic-gradient(
201
+ from 0deg,
202
+ transparent 0deg,
203
+ transparent 55deg,
204
+ rgba(255, 255, 255, 0.2) 80deg,
205
+ rgba(255, 255, 255, 0.75) 98deg,
206
+ var(--accent-color) 114deg,
207
+ rgba(255, 255, 255, 0.25) 132deg,
208
+ transparent 160deg,
209
+ transparent 235deg,
210
+ rgba(255, 255, 255, 0.2) 260deg,
211
+ rgba(255, 255, 255, 0.75) 278deg,
212
+ var(--accent-color) 294deg,
213
+ rgba(255, 255, 255, 0.25) 312deg,
214
+ transparent 340deg,
215
+ transparent 360deg
216
+ );
217
+ filter: blur(0.5px);
218
+ -webkit-mask: radial-gradient(
219
+ farthest-side,
220
+ transparent calc(100% - 0.22rem),
221
+ #000 calc(100% - 0.18rem)
222
+ );
223
+ mask: radial-gradient(
224
+ farthest-side,
225
+ transparent calc(100% - 0.22rem),
226
+ #000 calc(100% - 0.18rem)
227
+ );
228
+ opacity: 0.6;
229
+ animation: asd20-event-date-ring 14s linear infinite;
230
+ }
194
231
  small {
195
232
  color: var(---website-card__reverse-foreground-color);
196
233
  }
@@ -240,6 +277,23 @@ export default {
240
277
  }
241
278
  }
242
279
  }
280
+
281
+ @media (prefers-reduced-motion: reduce) {
282
+ .asd20-event-modal {
283
+ &__date {
284
+ &::before {
285
+ animation: none;
286
+ }
287
+ }
288
+ }
289
+ }
290
+
291
+ @keyframes asd20-event-date-ring {
292
+ to {
293
+ transform: rotate(360deg);
294
+ }
295
+ }
296
+
243
297
  @media (min-width: 1024px) {
244
298
  .asd20-event-modal {
245
299
  &__header {
@@ -179,6 +179,7 @@ import Asd20Logo from '../../../components/atoms/Asd20Logo'
179
179
  import Asd20DistrictLogo from '../../../components/atoms/Asd20DistrictLogo'
180
180
  import organizationAddress from '../../../data/organization-address.json'
181
181
  import { navigateInternalHref } from '../../../helpers/linkPolicy'
182
+ import { resolveMediaCssUrl } from '../../../helpers/mediaUrl'
182
183
  import {
183
184
  organizationLevel,
184
185
  organizationName,
@@ -266,7 +267,9 @@ export default {
266
267
  if (isDistrict) {
267
268
  return {
268
269
  '--asd20-district-footer-image':
269
- "url('/_media/asd20-images/page-images/asd20-footer-image.jpg')",
270
+ resolveMediaCssUrl(
271
+ 'asd20-images/page-images/asd20-footer-image.jpg'
272
+ ),
270
273
  }
271
274
  }
272
275
 
@@ -147,6 +147,7 @@
147
147
  reversed
148
148
  horizontal
149
149
  centered
150
+ highlighted
150
151
  />
151
152
  <asd20-button
152
153
  v-if="callsToAction.length >= 2"
@@ -158,6 +159,7 @@
158
159
  reversed
159
160
  horizontal
160
161
  centered
162
+ highlighted
161
163
  />
162
164
  </div>
163
165
  <div
@@ -34,6 +34,7 @@
34
34
  <script>
35
35
  import Asd20Messaging from '../../atoms/Asd20Messaging'
36
36
  import _get from 'lodash/get'
37
+ import { resolveMediaCssUrl } from '../../../helpers/mediaUrl'
37
38
 
38
39
  export default {
39
40
  name: 'Asd20PrimaryHeader',
@@ -61,7 +62,7 @@ export default {
61
62
  photoStripStyle() {
62
63
  return {
63
64
  '--asd20-photo-strip-image':
64
- "url('/_media/asd20-images/page-images/ASD20PhotoStrip.jpg')",
65
+ resolveMediaCssUrl('asd20-images/page-images/ASD20PhotoStrip.jpg'),
65
66
  }
66
67
  },
67
68
  firstMessage() {
@@ -10,6 +10,7 @@
10
10
 
11
11
  <script>
12
12
  import Asd20Messaging from '../../atoms/Asd20Messaging'
13
+ import { resolveMediaCssUrl } from '../../../helpers/mediaUrl'
13
14
 
14
15
  export default {
15
16
  name: 'Asd20TertiaryHeader',
@@ -29,7 +30,9 @@ export default {
29
30
  headerStyle() {
30
31
  return {
31
32
  '--asd20-header-divider-image':
32
- "url('/_media/asd20-images/page-images/asd20-header-divider.jpg')",
33
+ resolveMediaCssUrl(
34
+ 'asd20-images/page-images/asd20-header-divider.jpg'
35
+ ),
33
36
  }
34
37
  },
35
38
  },
@@ -68,6 +68,22 @@ function formatApDate(iso) {
68
68
  }
69
69
  }
70
70
 
71
+ function normalizeMessageSlug(slug) {
72
+ return typeof slug === 'string'
73
+ ? slug.trim().replace(/^\/+/, '').replace(/\/+$/, '')
74
+ : ''
75
+ }
76
+
77
+ function buildMessageLink({ prefix, slug, website = '' }) {
78
+ const normalizedSlug = normalizeMessageSlug(slug)
79
+ const normalizedWebsite = website.replace(/\/+$/, '')
80
+
81
+ if (!prefix || !normalizedSlug) return normalizedWebsite || prefix || '/'
82
+
83
+ const normalizedPrefix = prefix.endsWith('/') ? prefix : `${prefix}/`
84
+ return `${normalizedWebsite}${normalizedPrefix}${normalizedSlug}/`
85
+ }
86
+
71
87
  export default function mapMessageToCard(
72
88
  message,
73
89
  options = {},
@@ -97,7 +113,10 @@ export default function mapMessageToCard(
97
113
  }
98
114
 
99
115
  // Check for organization ID match
100
- let baseLink = `${channelPrefixMap[channelTitle]}${message.slug}`
116
+ let baseLink = buildMessageLink({
117
+ prefix: channelPrefixMap[channelTitle],
118
+ slug: message.slug,
119
+ })
101
120
  let sourceOrg = null
102
121
  let websiteLogo = null
103
122
 
@@ -119,7 +138,11 @@ export default function mapMessageToCard(
119
138
 
120
139
  // Keep destination-targeted content on the current site URL.
121
140
  if (!hasDestinations && matchedOrg.website) {
122
- baseLink = `${matchedOrg.website}${channelPrefixMap[channelTitle]}${message.slug}`
141
+ baseLink = buildMessageLink({
142
+ prefix: channelPrefixMap[channelTitle],
143
+ slug: message.slug,
144
+ website: matchedOrg.website,
145
+ })
123
146
  }
124
147
  } else {
125
148
  websiteLogo = organization.logoImageUrl
@@ -0,0 +1,46 @@
1
+ import { normalizeBaseUrl, resolveRuntimeConfigValue } from './runtimeConfig'
2
+
3
+ const DEFAULT_MEDIA_BASE_URL = '/_media'
4
+ const STORYBOOK_MEDIA_BASE_URL =
5
+ 'https://asd20websitestorage.blob.core.windows.net'
6
+
7
+ function normalizeMediaPath(path) {
8
+ return typeof path === 'string' ? path.trim().replace(/^\/+/, '') : ''
9
+ }
10
+
11
+ function isStorybookRuntime() {
12
+ return (
13
+ typeof window !== 'undefined' &&
14
+ Boolean(window.__ASD20_UI_STORYBOOK__)
15
+ )
16
+ }
17
+
18
+ export function resolveMediaUrl(path, options = {}) {
19
+ const mediaPath = normalizeMediaPath(path)
20
+
21
+ if (!mediaPath) {
22
+ return ''
23
+ }
24
+
25
+ const configuredBaseUrl = resolveRuntimeConfigValue({
26
+ explicitValue: options.mediaBaseUrl,
27
+ runtimeConfig: options.runtimeConfig,
28
+ runtimeConfigKeys: ['mediaBaseUrl', 'mediaEndpoint'],
29
+ envKeys: ['MEDIA_BASE_URL', 'VUE_APP_MEDIA_BASE_URL'],
30
+ })
31
+
32
+ const baseUrl = normalizeBaseUrl(
33
+ configuredBaseUrl ||
34
+ (isStorybookRuntime()
35
+ ? STORYBOOK_MEDIA_BASE_URL
36
+ : DEFAULT_MEDIA_BASE_URL)
37
+ )
38
+
39
+ return `${baseUrl}/${mediaPath}`
40
+ }
41
+
42
+ export function resolveMediaCssUrl(path, options = {}) {
43
+ const mediaUrl = resolveMediaUrl(path, options)
44
+
45
+ return mediaUrl ? `url(${JSON.stringify(mediaUrl)})` : ''
46
+ }