@brightspace-ui/core 3.314.5 → 3.314.6

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.
@@ -3,12 +3,18 @@ import '../colors/colors.js';
3
3
  import '../icons/icon.js';
4
4
  import './page-header-custom.js';
5
5
  import { bodyCompactStyles, heading3Styles, labelStyles } from '../typography/styles.js';
6
+ import { createRef, ref } from 'lit/directives/ref.js';
6
7
  import { css, html, LitElement } from 'lit';
7
8
  import { highlightBorderStyles, highlightLinkStyles } from './page-header-styles.js';
9
+ import { classMap } from 'lit/directives/class-map.js';
8
10
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
11
+ import { offscreenStyles } from '../offscreen/offscreen.js';
9
12
  import { overflowEllipsisDeclarations } from '../../helpers/overflow.js';
10
13
  import { RequesterMixin } from '../../mixins/provider/provider-mixin.js';
11
14
 
15
+ const CONTAINER_GAP = 24;
16
+ const MINIMUM_TITLE_WIDTH = 100;
17
+
12
18
  class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)) {
13
19
 
14
20
  static properties = {
@@ -17,10 +23,12 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
17
23
  titleText: { attribute: 'title-text', type: String },
18
24
  subtitleText: { attribute: 'subtitle-text', type: String },
19
25
  _error: { state: true },
20
- _hasActions: { state: true }
26
+ _hasActions: { state: true },
27
+ _hasTitleSlot: { state: true },
28
+ _titleHidden: { state: true }
21
29
  };
22
30
 
23
- static styles = [bodyCompactStyles, heading3Styles, labelStyles, highlightBorderStyles, highlightLinkStyles, css`
31
+ static styles = [bodyCompactStyles, heading3Styles, labelStyles, highlightBorderStyles, highlightLinkStyles, offscreenStyles, css`
24
32
  :host {
25
33
  display: block;
26
34
  }
@@ -31,7 +39,7 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
31
39
  .container {
32
40
  align-items: stretch;
33
41
  display: flex;
34
- gap: 24px;
42
+ gap: ${CONTAINER_GAP}px;
35
43
  height: 3.1rem;
36
44
  }
37
45
  .title {
@@ -39,14 +47,20 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
39
47
  min-width: 0;
40
48
  width: 100%;
41
49
  }
50
+ .title-wrapper {
51
+ height: 100%;
52
+ }
42
53
  .back,
43
54
  .actions {
44
55
  flex: 0 0 auto;
45
56
  }
46
57
  .title,
47
- .actions {
58
+ .actions.has-title {
48
59
  border-inline-start: 1px solid var(--d2l-color-gypsum);
49
- padding-inline-start: 24px;
60
+ }
61
+ .title.has-title,
62
+ .actions.has-title {
63
+ padding-inline-start: ${CONTAINER_GAP}px;
50
64
  }
51
65
  .title h1 {
52
66
  display: flex;
@@ -74,6 +88,11 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
74
88
  display: inline;
75
89
  }
76
90
  }
91
+ @media (max-width: 360px) {
92
+ .back-text-short {
93
+ display: none;
94
+ }
95
+ }
77
96
  d2l-alert {
78
97
  margin: 10px auto;
79
98
  }
@@ -86,6 +105,8 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
86
105
  super();
87
106
  this._error = false;
88
107
  this._hasActions = false;
108
+ this._hasTitleSlot = false;
109
+ this._titleHidden = false;
89
110
  }
90
111
 
91
112
  connectedCallback() {
@@ -98,14 +119,30 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
98
119
  }
99
120
  }
100
121
 
122
+ disconnectedCallback() {
123
+ super.disconnectedCallback();
124
+ this.#resizeObserver.disconnect();
125
+ }
126
+
127
+ firstUpdated(changedProperties) {
128
+ super.firstUpdated(changedProperties);
129
+ if (this.#refTitle.value !== undefined) {
130
+ this.#resizeObserver.observe(this.#refTitle.value);
131
+ }
132
+ }
133
+
101
134
  render() {
102
135
  if (this._error) return this.#renderError();
136
+ const actionsClasses = {
137
+ 'actions': true,
138
+ 'has-title': this.#hasVisibleTitle()
139
+ };
103
140
  return html`
104
141
  <d2l-page-header-custom>
105
142
  <div class="container" slot="top">
106
143
  ${this.#renderBack()}
107
144
  ${this.#renderTitle()}
108
- <div class="actions" ?hidden="${!this._hasActions}">
145
+ <div class="${classMap(actionsClasses)}" ?hidden="${!this._hasActions}">
109
146
  <slot name="actions" @slotchange="${this.#handleActionsSlotChange}"></slot>
110
147
  </div>
111
148
  </div>
@@ -113,6 +150,9 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
113
150
  `;
114
151
  }
115
152
 
153
+ #refTitle = createRef();
154
+ #resizeObserver = new ResizeObserver((entries) => this.#updateSizes(entries));
155
+
116
156
  #handleActionsSlotChange(e) {
117
157
  this._hasActions = e.target.assignedNodes({ flatten: true })?.length > 0;
118
158
  }
@@ -126,6 +166,18 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
126
166
  );
127
167
  }
128
168
 
169
+ #handleTitleSlotChange(e) {
170
+ this._hasTitleSlot = e.target.assignedNodes({ flatten: true })?.length > 0;
171
+ }
172
+
173
+ #hasTitle() {
174
+ return this._hasTitleSlot || this.titleText || this.subtitleText;
175
+ }
176
+
177
+ #hasVisibleTitle() {
178
+ return !this._titleHidden && this.#hasTitle();
179
+ }
180
+
129
181
  #renderBack() {
130
182
  const href = this.backHref || 'javascript:void(0);';
131
183
  const commonText = this.localizeCommon('navigation:back:title');
@@ -152,12 +204,37 @@ class PageHeaderImmersive extends RequesterMixin(LocalizeCoreElement(LitElement)
152
204
  const title = this.titleText ? html`<div class="title-text d2l-heading-3">${this.titleText}</div>` : '';
153
205
  const subtitle = this.subtitleText ? html`<div class="title-text d2l-label-text">${this.subtitleText}</div>` : '';
154
206
  const heading = (title || subtitle) && html`<h1>${title}${subtitle}</h1>`;
207
+ const titleClasses = {
208
+ 'title': true,
209
+ 'has-title': this.#hasVisibleTitle()
210
+ };
211
+ const wrapperClasses = {
212
+ 'title-wrapper': true,
213
+ 'd2l-offscreen': this._titleHidden
214
+ };
155
215
  return html`
156
- <div class="title">
157
- <slot name="title">${heading}</slot>
216
+ <div class="${classMap(titleClasses)}" ${ref(this.#refTitle)}>
217
+ <div class="${classMap(wrapperClasses)}">
218
+ <slot name="title" @slotchange="${this.#handleTitleSlotChange}">${heading}</slot>
219
+ </div>
158
220
  </div>
159
221
  `;
160
222
  }
161
223
 
224
+ #updateSizes(entries) {
225
+ entries.forEach(entry => {
226
+ if (entry.target === this.#refTitle.value) {
227
+ if (this.#hasTitle()) {
228
+ if (this._titleHidden) {
229
+ const extraSpace = this._hasActions ? (CONTAINER_GAP * 2 + 1) : (CONTAINER_GAP + 1);
230
+ this._titleHidden = entry.contentRect.width - extraSpace < MINIMUM_TITLE_WIDTH;
231
+ } else {
232
+ this._titleHidden = entry.contentRect.width < MINIMUM_TITLE_WIDTH;
233
+ }
234
+ }
235
+ }
236
+ });
237
+ }
238
+
162
239
  }
163
240
  customElements.define('d2l-page-header-immersive', PageHeaderImmersive);
@@ -13676,7 +13676,7 @@
13676
13676
  {
13677
13677
  "name": "styles",
13678
13678
  "type": "array",
13679
- "default": "[\"bodyCompactStyles\",\"heading3Styles\",\"labelStyles\",\"highlightBorderStyles\",\"highlightLinkStyles\",null]"
13679
+ "default": "[\"bodyCompactStyles\",\"heading3Styles\",\"labelStyles\",\"highlightBorderStyles\",\"highlightLinkStyles\",\"offscreenStyles\",null]"
13680
13680
  }
13681
13681
  ],
13682
13682
  "events": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.314.5",
3
+ "version": "3.314.6",
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",