@brightspace-ui/core 3.145.1 → 3.146.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.
@@ -1,8 +1,12 @@
1
1
  import './breadcrumb.js';
2
2
  import { css, html, LitElement } from 'lit';
3
+ import { getFlag } from '../../helpers/flags.js';
3
4
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
5
+ import { overflowEllipsisDeclarations } from '../../helpers/overflow.js';
4
6
  import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
5
7
 
8
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
9
+
6
10
  /**
7
11
  * Help users understand where they are within the application, and provide useful clues about how the space is organized. They also provide a convenient navigation mechanism.
8
12
  * @slot - Breadcrumb items
@@ -21,12 +25,15 @@ class Breadcrumbs extends LocalizeCoreElement(RtlMixin(LitElement)) {
21
25
  static get styles() {
22
26
  return css`
23
27
  :host {
28
+ ${overflowClipEnabled ? css`clip-path: rect(-1em 100% calc(100% + 1em) -1em);` : css``}
24
29
  display: block;
25
30
  font-size: 0.7rem;
26
31
  line-height: 1.05rem;
27
- overflow: hidden;
28
32
  position: relative;
29
- white-space: nowrap;
33
+ ${overflowClipEnabled ? overflowEllipsisDeclarations : css`
34
+ overflow: hidden;
35
+ white-space: nowrap;
36
+ `}
30
37
  }
31
38
  :host([hidden]) {
32
39
  display: none;
@@ -2,9 +2,13 @@ import '../colors/colors.js';
2
2
  import { css, html, LitElement } from 'lit';
3
3
  import { bodySmallStyles } from '../typography/styles.js';
4
4
  import { classMap } from 'lit/directives/class-map.js';
5
+ import { getFlag } from '../../helpers/flags.js';
6
+ import { getOverflowDeclarations } from '../../helpers/overflow.js';
5
7
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
6
8
  import { styleMap } from 'lit/directives/style-map.js';
7
9
 
10
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
11
+
8
12
  /**
9
13
  * A component for a "summary item" child component that describes the content in a collapsible panel.
10
14
  */
@@ -38,10 +42,12 @@ class CollapsiblePanelSummaryItem extends SkeletonMixin(LitElement) {
38
42
  line-height: 1.2rem;
39
43
  }
40
44
  p.truncate {
41
- -webkit-box-orient: vertical;
42
- display: -webkit-box;
43
- overflow: hidden;
44
- overflow-wrap: anywhere;
45
+ ${overflowClipEnabled ? getOverflowDeclarations({ lines: 1 }) : css`
46
+ -webkit-box-orient: vertical;
47
+ display: -webkit-box;
48
+ overflow: hidden;
49
+ overflow-wrap: anywhere;
50
+ `}
45
51
  }
46
52
  `];
47
53
  }
@@ -23,10 +23,12 @@ import '../tooltip/tooltip.js';
23
23
 
24
24
  import { bodyCompactStyles, bodySmallStyles, bodyStandardStyles, heading4Styles } from '../typography/styles.js';
25
25
  import { css, html, LitElement, nothing } from 'lit';
26
+ import { getOverflowDeclarations, overflowEllipsisDeclarations } from '../../helpers/overflow.js';
26
27
  import { announce } from '../../helpers/announce.js';
27
28
  import { classMap } from 'lit/directives/class-map.js';
28
29
  import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
29
30
  import { formatNumber } from '@brightspace-ui/intl/lib/number.js';
31
+ import { getFlag } from '../../helpers/flags.js';
30
32
  import { ifDefined } from 'lit/directives/if-defined.js';
31
33
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
32
34
  import { offscreenStyles } from '../offscreen/offscreen.js';
@@ -38,6 +40,8 @@ const ESCAPE_KEY_CODE = 27;
38
40
  const FILTER_CONTENT_CLASS = 'd2l-filter-dropdown-content';
39
41
  const SET_DIMENSION_ID_PREFIX = 'list-';
40
42
 
43
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
44
+
41
45
  let hasDisplayedKeyboardTooltip = false;
42
46
 
43
47
  export function resetHasDisplayedKeyboardTooltip() {
@@ -143,26 +147,24 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
143
147
  flex-grow: 1;
144
148
  padding-right: calc(2rem + 2px);
145
149
  text-align: center;
146
- text-overflow: ellipsis;
147
- white-space: nowrap;
150
+ ${overflowClipEnabled ? overflowEllipsisDeclarations : css`
151
+ overflow: hidden;
152
+ text-overflow: ellipsis;
153
+ white-space: nowrap;
154
+ `}
148
155
  }
149
156
  :host([dir="rtl"]) .d2l-filter-dimension-header-text {
150
157
  padding-left: calc(2rem + 2px);
151
158
  padding-right: 0;
152
159
  }
153
160
 
154
- .d2l-filter-dimension-header-text,
155
- .d2l-filter-dimension-set-value-text {
156
- overflow: hidden;
157
- }
158
-
159
161
  .d2l-filter-dimension-set-value {
160
162
  align-items: center;
161
163
  color: var(--d2l-color-ferrite);
162
164
  display: flex;
163
165
  gap: 0.45rem;
164
166
  line-height: unset;
165
- overflow: hidden;
167
+ ${overflowClipEnabled ? css`` : css`overflow: hidden;`}
166
168
  }
167
169
  .d2l-filter-dimension-set-value d2l-icon {
168
170
  flex-shrink: 0;
@@ -176,11 +178,14 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
176
178
  }
177
179
 
178
180
  .d2l-filter-dimension-set-value-text {
179
- -webkit-box-orient: vertical;
180
- display: -webkit-box;
181
181
  hyphens: auto;
182
- -webkit-line-clamp: 2;
183
- overflow-wrap: anywhere;
182
+ ${overflowClipEnabled ? getOverflowDeclarations({ lines: 2 }) : css`
183
+ -webkit-box-orient: vertical;
184
+ display: -webkit-box;
185
+ -webkit-line-clamp: 2;
186
+ overflow: hidden;
187
+ overflow-wrap: anywhere;
188
+ `}
184
189
  }
185
190
 
186
191
  d2l-list-item[selection-disabled] .d2l-filter-dimension-set-value,
@@ -637,8 +642,8 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
637
642
  ${item.additionalContent ? html`<d2l-icon icon="${item.selected ? 'tier1:arrow-collapse-small' : 'tier1:arrow-expand-small'}" aria-hidden="true"></d2l-icon>` : nothing}
638
643
  </div>
639
644
  ${item.additionalContent ? html`
640
- <d2l-expand-collapse-content
641
- ?expanded="${item.selected}"
645
+ <d2l-expand-collapse-content
646
+ ?expanded="${item.selected}"
642
647
  @d2l-expand-collapse-content-collapse="${this._handleExpandCollapse}"
643
648
  @d2l-expand-collapse-content-expand="${this._handleExpandCollapse}">
644
649
  ${item.additionalContent()}
@@ -3,12 +3,16 @@ import '../icons/icon.js';
3
3
  import { css, html, LitElement, nothing } from 'lit';
4
4
  import { classMap } from 'lit/directives/class-map.js';
5
5
  import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
6
+ import { getFlag } from '../../helpers/flags.js';
6
7
  import { getFocusRingStyles } from '../../helpers/focus.js';
8
+ import { getOverflowDeclarations } from '../../helpers/overflow.js';
7
9
  import { ifDefined } from 'lit/directives/if-defined.js';
8
10
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
9
11
  import { offscreenStyles } from '../offscreen/offscreen.js';
10
12
  import { styleMap } from 'lit/directives/style-map.js';
11
13
 
14
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
15
+
12
16
  export const linkStyles = css`
13
17
  .d2l-link, .d2l-link:visited, .d2l-link:active, .d2l-link:link {
14
18
  --d2l-focus-ring-offset: 1px;
@@ -109,10 +113,12 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
109
113
  display: inherit;
110
114
  }
111
115
  a.truncate {
112
- -webkit-box-orient: vertical;
113
- display: -webkit-box;
114
- overflow: hidden;
115
- overflow-wrap: anywhere;
116
+ ${overflowClipEnabled ? getOverflowDeclarations({ lines: 1 }) : css`
117
+ -webkit-box-orient: vertical;
118
+ display: -webkit-box;
119
+ overflow: hidden;
120
+ overflow-wrap: anywhere;
121
+ `}
116
122
  }
117
123
  d2l-icon {
118
124
  color: var(--d2l-color-celestine);
@@ -1,6 +1,9 @@
1
1
  import '../colors/colors.js';
2
2
  import { bodyCompactStyles, bodySmallStyles } from '../typography/styles.js';
3
3
  import { css, html, LitElement } from 'lit';
4
+ import { getFlag } from '../../helpers/flags.js';
5
+
6
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
4
7
 
5
8
  /**
6
9
  * A component for consistent layout of primary and secondary text in a list item.
@@ -33,14 +36,18 @@ class ListItemContent extends LitElement {
33
36
 
34
37
  .d2l-list-item-content-text-secondary {
35
38
  color: var(--d2l-list-item-content-text-secondary-color, var(--d2l-color-tungsten));
36
- margin: 0;
37
- overflow: hidden;
39
+ ${overflowClipEnabled ? css`` : css`
40
+ margin: 0;
41
+ overflow: hidden;
42
+ `}
38
43
  }
39
44
 
40
45
  .d2l-list-item-content-text-supporting-info {
41
46
  color: var(--d2l-color-ferrite);
42
- margin: 0;
43
- overflow: hidden;
47
+ ${overflowClipEnabled ? css`` : css`
48
+ margin: 0;
49
+ overflow: hidden;
50
+ `}
44
51
  }
45
52
 
46
53
  .d2l-list-item-content-text-secondary ::slotted(*),
@@ -3,14 +3,17 @@ import { css, html, LitElement } from 'lit';
3
3
  import { getComposedChildren, isComposedAncestor } from '../../helpers/dom.js';
4
4
  import { classMap } from 'lit/directives/class-map.js';
5
5
  import { getComposedActiveElement } from '../../helpers/focus.js';
6
+ import { getFlag } from '../../helpers/flags.js';
6
7
  import { getUniqueId } from '../../helpers/uniqueId.js';
7
8
  import { ifDefined } from 'lit/directives/if-defined.js';
8
9
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
10
+ import { overflowHiddenDeclarations } from '../../helpers/overflow.js';
9
11
  import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
10
12
  import { styleMap } from 'lit/directives/style-map.js';
11
13
 
12
- const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
13
14
  const transitionDur = matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : 400;
15
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
16
+ const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
14
17
 
15
18
  /**
16
19
  * A component used to minimize the display of long content, while providing a way to reveal the full content.
@@ -51,11 +54,18 @@ class MoreLess extends LocalizeCoreElement(LitElement) {
51
54
  static get styles() {
52
55
  return css`
53
56
  :host {
54
- display: block;
57
+ ${overflowClipEnabled ? css`display: flow-root;` : css`display: block;`}
55
58
  }
56
59
 
57
60
  .d2l-more-less-content {
58
- overflow: hidden;
61
+ ${overflowClipEnabled ? css`
62
+ display: flow-root;
63
+ margin: -1em -1em 0;
64
+ padding: 1em 1em 0;
65
+ ${overflowHiddenDeclarations}
66
+ ` : css`
67
+ overflow: hidden;
68
+ `}
59
69
  }
60
70
  .d2l-more-less-transition {
61
71
  transition: max-height ${transitionDur}ms cubic-bezier(0, 0.7, 0.5, 1);
@@ -228,18 +238,27 @@ class MoreLess extends LocalizeCoreElement(LitElement) {
228
238
 
229
239
  const target = e.composedPath()[0] || e.target;
230
240
 
231
- if (isSafari) {
232
- target.scrollIntoViewIfNeeded?.();
233
- setTimeout(() => this.__content.scrollTo({ top: 0, behavior: 'instant' }), 1);
234
- }
241
+ if (overflowClipEnabled) {
242
+ const em = parseInt(getComputedStyle(this.__content).getPropertyValue('font-size'));
243
+ const { y: contentY, height: contentHeight } = this.__content.getBoundingClientRect();
244
+ const { y: targetY, height: targetHeight } = target.getBoundingClientRect();
235
245
 
236
- if (this.__content.scrollTop) {
237
- this.__content.scrollTo({ top: 0, behavior: 'instant' });
238
- this.__expand();
239
- this.__autoExpanded = true;
240
- await (transitionDur && new Promise(r => setTimeout(r, transitionDur)));
241
- if (target.getRootNode().activeElement === target) {
242
- target.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' });
246
+ if (targetY + targetHeight > contentY + contentHeight - em) {
247
+ this.__expand();
248
+ this.__autoExpanded = true;
249
+ await (transitionDur && new Promise(r => setTimeout(r, transitionDur)));
250
+ }
251
+ } else {
252
+ if (isSafari) {
253
+ target.scrollIntoViewIfNeeded?.();
254
+ setTimeout(() => this.__content.scrollTo({ top: 0, behavior: 'instant' }), 1);
255
+ }
256
+
257
+ if (this.__content.scrollTop) {
258
+ this.__content.scrollTo({ top: 0, behavior: 'instant' });
259
+ this.__expand();
260
+ this.__autoExpanded = true;
261
+ await (transitionDur && new Promise(r => setTimeout(r, transitionDur)));
243
262
  }
244
263
  }
245
264
  }
@@ -155,7 +155,7 @@ Promise.resolve(tabs.hideTab((tab))).then(() => {
155
155
 
156
156
  The `TabMixin` can be used to create custom tabs. It is IMPORTANT to call the `dispatchContentChangeEvent` function in `TabMixin` when content changes in the consumer in order to properly trigger calculations. Ensure that there is only one element in any custom tab to focus on, else the focus and keyboard navigation behaviors become confusing for users. Note that the parent `d2l-tabs` element handles `tabindex` focus management, and so consumers should not be rendering focusable elements within custom tabs.
157
157
 
158
- Before creating a custom tab, ensure that the case is not covered by using a standard `d2l-tab` with content in the `before` and/or `after` slot(s).
158
+ Before creating a custom tab, ensure that the case is not covered by using a standard `d2l-tab` with content in the `before` and/or `after` slot(s).
159
159
 
160
160
  <!-- docs: demo code sandboxTitle:'TabMixin' display:block-->
161
161
  ```html
@@ -170,7 +170,8 @@ Before creating a custom tab, ensure that the case is not covered by using a sta
170
170
  const styles = [ css`
171
171
  .d2l-tab-custom-content {
172
172
  margin: 0.5rem;
173
- overflow: hidden;
173
+ overflow: clip;
174
+ overflow-clip-margin: 1em;
174
175
  padding: 0.1rem;
175
176
  white-space: nowrap;
176
177
  }
@@ -269,4 +270,4 @@ The `tabs` components were built following [W3C best practices for Tabs](https:/
269
270
  - Following recommended keyboard control patterns (with the exception of the "Optional" Home, End, and Delete key patterns)
270
271
  - Using the roles of `tablist` and `tab` appropriately in order to facilitate screen reader information (e.g., "tab, 2 of 7") and adding an `aria-label` to the `tablist`
271
272
  - Using `aria-selected` to indicate `tab` selection state
272
- - Using `aria-labelledby` and `aria-controls` in order to match the `tab` with the `tabpanel` for screen reader users
273
+ - Using `aria-labelledby` and `aria-controls` in order to match the `tab` with the `tabpanel` for screen reader users
@@ -9,7 +9,8 @@ class TabCustom extends TabMixin(LitElement) {
9
9
  .d2l-tab-custom-content {
10
10
  --d2l-focus-ring-offset: 0;
11
11
  margin: 0.5rem;
12
- overflow: hidden;
12
+ overflow: clip;
13
+ overflow-clip-margin: 1em;
13
14
  padding: 0.1rem;
14
15
  white-space: nowrap;
15
16
  }
@@ -1,9 +1,13 @@
1
1
  import '../colors/colors.js';
2
2
  import { css, html, LitElement } from 'lit';
3
3
  import { classMap } from 'lit/directives/class-map.js';
4
+ import { getFlag } from '../../helpers/flags.js';
4
5
  import { getFocusRingStyles } from '../../helpers/focus.js';
6
+ import { overflowEllipsisDeclarations } from '../../helpers/overflow.js';
5
7
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
6
8
 
9
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
10
+
7
11
  const keyCodes = {
8
12
  ENTER: 13,
9
13
  SPACE: 32
@@ -34,10 +38,12 @@ class Tab extends SkeletonMixin(LitElement) {
34
38
  .d2l-tab-text {
35
39
  --d2l-focus-ring-offset: 0;
36
40
  margin: 0.5rem;
37
- overflow: hidden;
38
41
  padding: 0.1rem;
39
- text-overflow: ellipsis;
40
- white-space: nowrap;
42
+ ${overflowClipEnabled ? overflowEllipsisDeclarations : css`
43
+ overflow: hidden;
44
+ text-overflow: ellipsis;
45
+ white-space: nowrap;
46
+ `}
41
47
  }
42
48
  :host([skeleton]) .d2l-tab-text.d2l-skeletize::before {
43
49
  bottom: 0.15rem;
@@ -1,8 +1,12 @@
1
1
  import { css, html, LitElement, unsafeCSS } from 'lit';
2
2
  import { getFocusPseudoClass, getFocusRingStyles } from '../../helpers/focus.js';
3
3
  import { classMap } from 'lit/directives/class-map.js';
4
+ import { getFlag } from '../../helpers/flags.js';
5
+ import { overflowEllipsisDeclarations } from '../../helpers/overflow.js';
4
6
  import { TabMixin } from './tab-mixin.js';
5
7
 
8
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
9
+
6
10
  const focusRingStyles = getFocusRingStyles(
7
11
  pseudoClass => `:host(:${pseudoClass}) .d2l-tab-text-inner-content`,
8
12
  { extraStyles: css`border-radius: 0.3rem; color: var(--d2l-color-celestine);` }
@@ -51,9 +55,11 @@ class Tab extends TabMixin(LitElement) {
51
55
  color: var(--d2l-color-celestine);
52
56
  }
53
57
  span {
54
- overflow: hidden;
55
- text-overflow: ellipsis;
56
- white-space: nowrap;
58
+ ${overflowClipEnabled ? overflowEllipsisDeclarations : css`
59
+ overflow: hidden;
60
+ text-overflow: ellipsis;
61
+ white-space: nowrap;
62
+ `}
57
63
  }
58
64
  .d2l-tab-text-skeletize-override {
59
65
  min-width: 50px;
@@ -8,6 +8,8 @@ import { getFocusPseudoClass, getFocusRingStyles } from '../../helpers/focus.js'
8
8
  import { ArrowKeysMixin } from '../../mixins/arrow-keys/arrow-keys-mixin.js';
9
9
  import { bodyCompactStyles } from '../typography/styles.js';
10
10
  import { classMap } from 'lit/directives/class-map.js';
11
+ import { getFlag } from '../../helpers/flags.js';
12
+ import { getOverflowDeclarations } from '../../helpers/overflow.js';
11
13
  import { ifDefined } from 'lit/directives/if-defined.js';
12
14
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
13
15
  import { repeat } from 'lit/directives/repeat.js';
@@ -16,6 +18,7 @@ import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
16
18
  import { styleMap } from 'lit/directives/style-map.js';
17
19
 
18
20
  const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
21
+ const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
19
22
 
20
23
  const scrollButtonWidth = 56;
21
24
 
@@ -87,13 +90,15 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
87
90
  box-sizing: border-box;
88
91
  flex: auto;
89
92
  margin-left: -3px;
90
- overflow: hidden;
91
- overflow-x: hidden;
92
93
  padding-left: 3px;
93
94
  position: relative;
94
95
  -webkit-transition: max-width 200ms ease-in;
95
96
  transition: max-width 200ms ease-in;
96
- white-space: nowrap;
97
+ ${overflowClipEnabled ? getOverflowDeclarations({ textOverflow: 'clip' }) : css`
98
+ overflow: hidden;
99
+ overflow-x: hidden;
100
+ white-space: nowrap;
101
+ `}
97
102
  }
98
103
  .d2l-tabs-container-ext {
99
104
  flex: none;
@@ -110,6 +115,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
110
115
  .d2l-tabs-scroll-next-container {
111
116
  background-color: var(--d2l-tabs-background-color);
112
117
  box-shadow: 0 0 12px 18px var(--d2l-tabs-background-color);
118
+ ${overflowClipEnabled ? css`clip-path: rect(0% 200% 100% -100%);` : css``}
113
119
  display: none;
114
120
  height: 100%;
115
121
  position: absolute;
@@ -0,0 +1,34 @@
1
+ import { set } from './template-tags.js';
2
+ import { unsafeCSS } from 'lit';
3
+
4
+ export const overflowHiddenDeclarations = getOverflowDeclarations({});
5
+ export const overflowEllipsisDeclarations = getOverflowDeclarations({ textOverflow: 'ellipsis' });
6
+
7
+ export function getOverflowDeclarations({ textOverflow = '', lines = 0, lit = true } = {}) {
8
+ if (!arguments.length) return overflowHiddenDeclarations;
9
+
10
+ const declarations = set`
11
+ min-width: 0; /* clamps width of flex items */
12
+ overflow-x: clip;
13
+ ${lines
14
+ ? set`
15
+ display: -webkit-box;
16
+ overflow-clip-margin: 0.2em;
17
+ overflow-wrap: anywhere;
18
+ overflow-y: clip;
19
+ text-overflow: ${textOverflow || 'ellipsis'};
20
+ -webkit-box-orient: vertical;
21
+ -webkit-line-clamp: ${lines};`
22
+ : set`
23
+ overflow-clip-margin: 1em;
24
+ ${textOverflow
25
+ ? set`
26
+ overflow-y: visible;
27
+ text-overflow: ${textOverflow};
28
+ white-space: nowrap;`
29
+ :
30
+ 'overflow-y: clip;'}
31
+ `}
32
+ `;
33
+ return lit ? unsafeCSS(declarations) : declarations;
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.145.1",
3
+ "version": "3.146.0",
4
4
  "description": "A collection of accessible, free, open-source web components for building Brightspace applications",
5
5
  "type": "module",
6
6
  "repository": "https://github.com/BrightspaceUI/core.git",