@internetarchive/modal-manager 2.0.2 → 2.0.3

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.
@@ -6,6 +6,7 @@ import '@internetarchive/icon-close';
6
6
 
7
7
  import { ModalConfig } from './modal-config';
8
8
  import IALogoIcon from './assets/ia-logo-icon';
9
+ import arrowLeftIcon from './assets/arrow-left-icon';
9
10
 
10
11
  @customElement('modal-template')
11
12
  export class ModalTemplate extends LitElement {
@@ -23,6 +24,9 @@ export class ModalTemplate extends LitElement {
23
24
  <div class="modal-wrapper">
24
25
  <div class="modal-container">
25
26
  <header style="background-color: ${this.config.headerColor}">
27
+ ${this.config.showLeftNavButton
28
+ ? this.leftNavButtonTemplate
29
+ : nothing}
26
30
  ${this.config.showCloseButton ? this.closeButtonTemplate : ''}
27
31
  ${this.config.showHeaderLogo
28
32
  ? html`<div class="logo-icon">${IALogoIcon}</div>`
@@ -84,6 +88,25 @@ export class ModalTemplate extends LitElement {
84
88
  this.dispatchEvent(event);
85
89
  }
86
90
 
91
+ /**
92
+ * Dispatch the `leftNavButtonPressed` event to the consumer
93
+ *
94
+ * @private
95
+ * @memberof ModalTemplate
96
+ */
97
+ private handleLeftNavButtonPressed(e: Event): void {
98
+ e.preventDefault();
99
+ if (
100
+ e.type === 'keydown' &&
101
+ (e as KeyboardEvent).key !== ' ' &&
102
+ (e as KeyboardEvent).key !== 'Enter'
103
+ ) {
104
+ return;
105
+ }
106
+ const event = new Event('leftNavButtonPressed');
107
+ this.dispatchEvent(event);
108
+ }
109
+
87
110
  /**
88
111
  * The close button template
89
112
  *
@@ -105,6 +128,17 @@ export class ModalTemplate extends LitElement {
105
128
  `;
106
129
  }
107
130
 
131
+ private get leftNavButtonTemplate(): TemplateResult {
132
+ return html`<button
133
+ type="button"
134
+ class="back-button"
135
+ @click=${this.handleLeftNavButtonPressed}
136
+ @keydown=${this.handleLeftNavButtonPressed}
137
+ >
138
+ ${arrowLeftIcon} ${this.config.leftNavButtonText ?? ''}
139
+ </button> `;
140
+ }
141
+
108
142
  /** @inheritdoc */
109
143
  static get styles(): CSSResult {
110
144
  const modalLogoSize = css`var(--modalLogoSize, 6.5rem)`;
@@ -261,6 +295,28 @@ export class ModalTemplate extends LitElement {
261
295
  0 4px 4px 0 rgba(0, 0, 0, 0.08);
262
296
  }
263
297
 
298
+ .back-button {
299
+ position: absolute;
300
+ left: 1.2rem;
301
+ top: 1.2rem;
302
+ height: 2rem;
303
+ background-color: transparent;
304
+ outline: none;
305
+ border: none;
306
+ padding: 0;
307
+ cursor: pointer;
308
+ color: white;
309
+ font-family: inherit;
310
+ display: flex;
311
+ flex-direction: row;
312
+ align-items: center;
313
+ gap: 0.5rem;
314
+ }
315
+
316
+ .back-button svg {
317
+ height: 1.5rem;
318
+ }
319
+
264
320
  .sr-only {
265
321
  position: absolute;
266
322
  width: 1px;
@@ -24,6 +24,8 @@ describe('Modal Config', () => {
24
24
  const showProcessingIndicator = true;
25
25
  const processingImageMode = 'processing';
26
26
  const showCloseButton = false;
27
+ const showLeftNavButton = false;
28
+ const leftNavButtonText = 'Previous';
27
29
  const showHeaderLogo = false;
28
30
  const closeOnBackdropClick = false;
29
31
 
@@ -36,6 +38,8 @@ describe('Modal Config', () => {
36
38
  showProcessingIndicator: showProcessingIndicator,
37
39
  processingImageMode: processingImageMode,
38
40
  showCloseButton: showCloseButton,
41
+ showLeftNavButton: showLeftNavButton,
42
+ leftNavButtonText: leftNavButtonText,
39
43
  showHeaderLogo: showHeaderLogo,
40
44
  closeOnBackdropClick: closeOnBackdropClick,
41
45
  });
@@ -49,6 +53,8 @@ describe('Modal Config', () => {
49
53
  expect(config.showProcessingIndicator).to.equal(showProcessingIndicator);
50
54
  expect(config.processingImageMode).to.equal(processingImageMode);
51
55
  expect(config.showCloseButton).to.equal(showCloseButton);
56
+ expect(config.showLeftNavButton).to.equal(showLeftNavButton);
57
+ expect(config.leftNavButtonText).to.equal(leftNavButtonText);
52
58
  expect(config.showHeaderLogo).to.equal(showHeaderLogo);
53
59
  expect(config.closeOnBackdropClick).to.equal(closeOnBackdropClick);
54
60
  });
@@ -63,6 +69,8 @@ describe('Modal Config', () => {
63
69
  expect(config.showProcessingIndicator).to.equal(false);
64
70
  expect(config.processingImageMode).to.equal('complete');
65
71
  expect(config.showCloseButton).to.equal(true);
72
+ expect(config.showLeftNavButton).to.equal(false);
73
+ expect(config.leftNavButtonText).to.equal('');
66
74
  expect(config.showHeaderLogo).to.equal(true);
67
75
  expect(config.closeOnBackdropClick).to.equal(true);
68
76
  });
@@ -151,6 +151,34 @@ describe('Modal Manager', () => {
151
151
  expect(callbackCalled).to.equal(false);
152
152
  });
153
153
 
154
+ it('calls the userPressedLeftNavButtonCallback when the user clicks the left nav button', async () => {
155
+ const el = (await fixture(html`
156
+ <modal-manager></modal-manager>
157
+ `)) as ModalManager;
158
+
159
+ const config = new ModalConfig();
160
+ config.showLeftNavButton = true;
161
+
162
+ let callbackCalled = false;
163
+ const callback = (): void => {
164
+ callbackCalled = true;
165
+ };
166
+ el.showModal({
167
+ config,
168
+ userPressedLeftNavButtonCallback: callback,
169
+ });
170
+ await elementUpdated(el);
171
+
172
+ const modalTemplate = el.shadowRoot?.querySelector('modal-template');
173
+ expect(modalTemplate).to.exist;
174
+
175
+ modalTemplate?.dispatchEvent(new Event('leftNavButtonPressed'));
176
+
177
+ await elementUpdated(el);
178
+
179
+ expect(callbackCalled).to.equal(true);
180
+ });
181
+
154
182
  it('mode is set to closed when close button is pressed', async () => {
155
183
  const el = (await fixture(html`
156
184
  <modal-manager></modal-manager>
@@ -57,6 +57,40 @@ describe('Modal Template', () => {
57
57
  expect(response).to.exist;
58
58
  });
59
59
 
60
+ it('emits leftNavButtonPressed event when left nav button is pressed', async () => {
61
+ const config = new ModalConfig();
62
+ config.showLeftNavButton = true;
63
+ const el = await fixture(html`
64
+ <modal-template .config=${config}></modal-template>
65
+ `);
66
+
67
+ const leftNavButton = el.shadowRoot?.querySelector('.back-button');
68
+ const clickEvent = new MouseEvent('click');
69
+
70
+ setTimeout(() => {
71
+ leftNavButton?.dispatchEvent(clickEvent);
72
+ });
73
+ const response = await oneEvent(el, 'leftNavButtonPressed', false);
74
+ expect(response).to.exist;
75
+ });
76
+
77
+ it('emits leftNavButtonPressed event when left nav button gets spacebar pressed', async () => {
78
+ const config = new ModalConfig();
79
+ config.showLeftNavButton = true;
80
+ const el = await fixture(html`
81
+ <modal-template .config=${config}></modal-template>
82
+ `);
83
+
84
+ const leftNavButton = el.shadowRoot?.querySelector('.back-button');
85
+ const clickEvent = new KeyboardEvent('keydown', { key: ' ' });
86
+
87
+ setTimeout(() => {
88
+ leftNavButton?.dispatchEvent(clickEvent);
89
+ });
90
+ const response = await oneEvent(el, 'leftNavButtonPressed', false);
91
+ expect(response).to.exist;
92
+ });
93
+
60
94
  it('shows the processing indicator if configured to', async () => {
61
95
  const config = new ModalConfig();
62
96
  config.showProcessingIndicator = true;
@@ -70,6 +104,54 @@ describe('Modal Template', () => {
70
104
  expect('hidden' in classList).to.equal(false);
71
105
  });
72
106
 
107
+ it('shows the left nav button if configured to', async () => {
108
+ const config = new ModalConfig();
109
+ config.showLeftNavButton = true;
110
+ const el = await fixture(html`
111
+ <modal-template .config=${config}></modal-template>
112
+ `);
113
+
114
+ const leftNavButton = el.shadowRoot?.querySelector('.back-button');
115
+ expect(leftNavButton).to.exist;
116
+ });
117
+
118
+ it('hides the left nav button if configured to', async () => {
119
+ const config = new ModalConfig();
120
+ config.showCloseButton = false;
121
+ const el = await fixture(html`
122
+ <modal-template .config=${config}></modal-template>
123
+ `);
124
+
125
+ const closeButton = el.shadowRoot?.querySelector('.close-button');
126
+ expect(closeButton).to.not.exist;
127
+ });
128
+
129
+ it('uses custom text for the left nav button if configured to', async () => {
130
+ const config = new ModalConfig();
131
+ config.showLeftNavButton = true;
132
+ config.leftNavButtonText = 'Previous';
133
+ const el = await fixture(html`
134
+ <modal-template .config=${config}></modal-template>
135
+ `);
136
+
137
+ const leftNavButton = el.shadowRoot?.querySelector('.back-button');
138
+
139
+ expect(leftNavButton).to.exist;
140
+ expect(leftNavButton?.innerHTML).to.contain('Previous');
141
+ });
142
+
143
+ it('does not use any text for the left nav button if not configured to', async () => {
144
+ const config = new ModalConfig();
145
+ config.showLeftNavButton = true;
146
+
147
+ const el = await fixture(html`
148
+ <modal-template .config=${config}></modal-template>
149
+ `);
150
+
151
+ const leftNavButton = el.shadowRoot?.querySelector('.back-button');
152
+ expect(leftNavButton?.innerHTML).not.to.contain('Previous');
153
+ });
154
+
73
155
  it('shows the close button if configured to', async () => {
74
156
  const config = new ModalConfig();
75
157
  config.showCloseButton = true;