@carbon/ibm-products-web-components 0.1.0-rc.0 → 0.1.1-canary.3599

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. package/.storybook/main.ts +15 -1
  2. package/.storybook/preview-head.html +5 -1
  3. package/.storybook/{theme.ts → theme.js} +2 -2
  4. package/CHANGELOG.md +8 -0
  5. package/es/components/side-panel/side-panel.d.ts +61 -80
  6. package/es/components/side-panel/side-panel.scss.js +1 -1
  7. package/es/components/tearsheet/defs.d.ts +26 -0
  8. package/es/components/tearsheet/defs.js +39 -0
  9. package/es/components/tearsheet/defs.js.map +1 -0
  10. package/es/components/tearsheet/index.d.ts +9 -0
  11. package/es/components/tearsheet/index.js +9 -0
  12. package/es/components/tearsheet/index.js.map +1 -0
  13. package/es/components/tearsheet/tearsheet.d.ts +490 -0
  14. package/es/components/tearsheet/tearsheet.js +685 -0
  15. package/es/components/tearsheet/tearsheet.js.map +1 -0
  16. package/es/components/tearsheet/tearsheet.scss.js +13 -0
  17. package/es/components/tearsheet/tearsheet.scss.js.map +1 -0
  18. package/es/components/tearsheet/tearsheet.test.d.ts +7 -0
  19. package/es/components/tearsheet/tearsheet.test.js +122 -0
  20. package/es/components/tearsheet/tearsheet.test.js.map +1 -0
  21. package/es/index.d.ts +1 -0
  22. package/es/index.js +1 -0
  23. package/es/index.js.map +1 -1
  24. package/lib/components/side-panel/side-panel.d.ts +61 -80
  25. package/lib/components/tearsheet/defs.d.ts +26 -0
  26. package/lib/components/tearsheet/defs.js +39 -0
  27. package/lib/components/tearsheet/defs.js.map +1 -0
  28. package/lib/components/tearsheet/index.d.ts +9 -0
  29. package/lib/components/tearsheet/tearsheet.d.ts +490 -0
  30. package/lib/components/tearsheet/tearsheet.test.d.ts +7 -0
  31. package/lib/index.d.ts +1 -0
  32. package/package.json +18 -18
  33. package/scss/components/tearsheet/story-styles.scss +23 -0
  34. package/scss/components/tearsheet/tearsheet.scss +318 -0
  35. package/src/components/tearsheet/defs.ts +30 -0
  36. package/src/components/tearsheet/index.ts +10 -0
  37. package/src/components/tearsheet/story-styles.scss +23 -0
  38. package/src/components/tearsheet/tearsheet.mdx +101 -0
  39. package/src/components/tearsheet/tearsheet.scss +318 -0
  40. package/src/components/tearsheet/tearsheet.stories.ts +703 -0
  41. package/src/components/tearsheet/tearsheet.test.ts +118 -0
  42. package/src/components/tearsheet/tearsheet.ts +792 -0
  43. package/src/index.ts +1 -0
  44. package/netlify.toml +0 -8
  45. /package/.storybook/{Preview.ts → preview.ts} +0 -0
@@ -0,0 +1,685 @@
1
+ /**
2
+ * Copyright IBM Corp. 2024
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import { __decorate } from '../../node_modules/tslib/tslib.es6.js';
9
+ import { LitElement, html } from 'lit';
10
+ import { query, queryAssignedElements, state, property } from 'lit/decorators.js';
11
+ import { prefix, carbonPrefix, selectorTabbable } from '../../globals/settings.js';
12
+ import HostListener from '@carbon/web-components/es/globals/decorators/host-listener.js';
13
+ import HostListenerMixin from '@carbon/web-components/es/globals/mixins/host-listener.js';
14
+ import styles from './tearsheet.scss.js';
15
+ import { carbonElement } from '@carbon/web-components/es/globals/decorators/carbon-element.js';
16
+ import '@carbon/web-components/es/components/button/index.js';
17
+ import '@carbon/web-components/es/components/layer/index.js';
18
+ import '@carbon/web-components/es/components/button/button-set-base.js';
19
+ import '@carbon/web-components/es/components/modal/index.js';
20
+ import { TEARSHEET_INFLUENCER_PLACEMENT, TEARSHEET_INFLUENCER_WIDTH, TEARSHEET_WIDTH } from './defs.js';
21
+
22
+ /**
23
+ * @license
24
+ *
25
+ * Copyright IBM Corp. 2023, 2024
26
+ *
27
+ * This source code is licensed under the Apache-2.0 license found in the
28
+ * LICENSE file in the root directory of this source tree.
29
+ */
30
+ var CDSTearsheet_1;
31
+ const maxStackDepth = 3;
32
+ // eslint-disable-next-line no-bitwise
33
+ const PRECEDING = Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_POSITION_CONTAINS;
34
+ // eslint-disable-next-line no-bitwise
35
+ const FOLLOWING = Node.DOCUMENT_POSITION_FOLLOWING | Node.DOCUMENT_POSITION_CONTAINED_BY;
36
+ const blockClass = `${prefix}--tearsheet`;
37
+ const blockClassModalHeader = `${carbonPrefix}--modal-header`;
38
+ const blockClassActionSet = `${prefix}--action-set`;
39
+ /**
40
+ * Tries to focus on the given elements and bails out if one of them is successful.
41
+ *
42
+ * @param elements The elements.
43
+ * @param reverse `true` to go through the list in reverse order.
44
+ * @returns `true` if one of the attempts is successful, `false` otherwise.
45
+ */
46
+ function tryFocusElements(elements, reverse) {
47
+ if (!reverse) {
48
+ for (let i = 0; i < elements.length; ++i) {
49
+ const elem = elements[i];
50
+ elem.focus();
51
+ if (elem.ownerDocument.activeElement === elem) {
52
+ return true;
53
+ }
54
+ }
55
+ }
56
+ else {
57
+ for (let i = elements.length - 1; i >= 0; --i) {
58
+ const elem = elements[i];
59
+ elem.focus();
60
+ if (elem.ownerDocument.activeElement === elem) {
61
+ return true;
62
+ }
63
+ }
64
+ }
65
+ return false;
66
+ }
67
+ /**
68
+ * Tearsheet.
69
+ *
70
+ * @element c4p-tearsheet
71
+ * @csspart dialog The dialog.
72
+ * @fires c4p-tearsheet-beingclosed
73
+ * The custom event fired before this tearsheet is being closed upon a user gesture.
74
+ * Cancellation of this event stops the user-initiated action of closing this tearsheet.
75
+ * @fires c4p-tearsheet-closed - The custom event fired after this tearsheet is closed upon a user gesture.
76
+ */
77
+ let CDSTearsheet = CDSTearsheet_1 = class CDSTearsheet extends HostListenerMixin(LitElement) {
78
+ constructor() {
79
+ super(...arguments);
80
+ /**
81
+ * The element that had focus before this tearsheet gets open.
82
+ */
83
+ this._launcher = null;
84
+ this._actionsCount = 0;
85
+ this._hasHeaderActions = false;
86
+ this._hasLabel = false;
87
+ this._hasSlug = false;
88
+ this._hasTitle = false;
89
+ this._hasDescription = false;
90
+ this._hasInfluencerLeft = false;
91
+ this._hasInfluencerRight = false;
92
+ this._isOpen = false;
93
+ this._hasHeaderNavigation = false;
94
+ /**
95
+ * Handles `click` event on this element.
96
+ *
97
+ * @param event The event.
98
+ */
99
+ this._handleClick = (event) => {
100
+ if (event.composedPath().indexOf(this.shadowRoot) < 0 &&
101
+ !this.preventCloseOnClickOutside) {
102
+ this._handleUserInitiatedClose(event.target);
103
+ }
104
+ };
105
+ /**
106
+ * Handles `blur` event on this element.
107
+ *
108
+ * @param event The event.
109
+ * @param event.target The event target.
110
+ * @param event.relatedTarget The event relatedTarget.
111
+ */
112
+ this._handleBlur = async ({ target, relatedTarget }) => {
113
+ var _a;
114
+ if (!this._topOfStack()) {
115
+ return;
116
+ }
117
+ const {
118
+ // condensedActions,
119
+ open, _startSentinelNode: startSentinelNode, _endSentinelNode: endSentinelNode, } = this;
120
+ const oldContains = target !== this && this.contains(target);
121
+ const currentContains = relatedTarget !== this &&
122
+ (this.contains(relatedTarget) ||
123
+ (((_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(relatedTarget)) &&
124
+ relatedTarget !== startSentinelNode &&
125
+ relatedTarget !== endSentinelNode));
126
+ // Performs focus wrapping if _all_ of the following is met:
127
+ // * This tearsheet is open
128
+ // * The viewport still has focus
129
+ // * Tearsheet body used to have focus but no longer has focus
130
+ const { selectorTabbable: selectorTabbableForTearsheet } = this
131
+ .constructor;
132
+ if (open && relatedTarget && oldContains && !currentContains) {
133
+ const comparisonResult = target.compareDocumentPosition(relatedTarget);
134
+ // eslint-disable-next-line no-bitwise
135
+ if (relatedTarget === startSentinelNode || comparisonResult & PRECEDING) {
136
+ await this.constructor._delay();
137
+ if (!tryFocusElements(this.querySelectorAll(selectorTabbableForTearsheet), true) &&
138
+ relatedTarget !== this) {
139
+ this.focus();
140
+ }
141
+ }
142
+ // eslint-disable-next-line no-bitwise
143
+ else if (relatedTarget === endSentinelNode ||
144
+ comparisonResult & FOLLOWING) {
145
+ await this.constructor._delay();
146
+ if (!tryFocusElements(this.querySelectorAll(selectorTabbableForTearsheet), true)) {
147
+ this.focus();
148
+ }
149
+ }
150
+ }
151
+ };
152
+ this._handleKeydown = ({ key, target }) => {
153
+ if ((key === 'Esc' || key === 'Escape') && this._topOfStack()) {
154
+ this._handleUserInitiatedClose(target);
155
+ }
156
+ };
157
+ /**
158
+ * Optional aria label for the tearsheet
159
+ */
160
+ this.ariaLabel = '';
161
+ /**
162
+ * Sets the close button icon description
163
+ */
164
+ this.closeIconDescription = 'Close';
165
+ /**
166
+ * Enable a close icon ('x') in the header area of the tearsheet. By default,
167
+ * (when this prop is omitted, or undefined or null) a tearsheet does not
168
+ * display a close icon if there are navigation actions ("transactional
169
+ * tearsheet") and displays one if there are no navigation actions ("passive
170
+ * tearsheet"), and that behavior can be overridden if required by setting
171
+ * this prop to either true or false.
172
+ */
173
+ this.hasCloseIcon = false;
174
+ /**
175
+ * The placement of the influencer section, 'left' or 'right'.
176
+ */
177
+ this.influencerPlacement = TEARSHEET_INFLUENCER_PLACEMENT.RIGHT;
178
+ /**
179
+ * The width of the influencer section, 'narrow' or 'wide'.
180
+ */
181
+ this.influencerWidth = TEARSHEET_INFLUENCER_WIDTH.NARROW;
182
+ /**
183
+ * `true` if the tearsheet should be open.
184
+ */
185
+ this.open = false;
186
+ /**
187
+ * Prevent closing on click outside of tearsheet
188
+ */
189
+ this.preventCloseOnClickOutside = false;
190
+ /**
191
+ * The width of the influencer section, 'narrow' or 'wide'.
192
+ */
193
+ this.width = TEARSHEET_WIDTH.NARROW;
194
+ this._checkUpdateActionSizes = () => {
195
+ if (this._actions) {
196
+ for (let i = 0; i < this._actions.length; i++) {
197
+ this._actions[i].setAttribute('size', this.width === 'wide' ? '2xl' : 'xl');
198
+ }
199
+ }
200
+ };
201
+ this._maxActions = 4;
202
+ // Data structure to communicate the state of tearsheet stacking
203
+ // (i.e. when more than one tearsheet is open). Each tearsheet supplies a
204
+ // handler to be called whenever the stacking of the tearsheets changes, which
205
+ // happens when a tearsheet opens or closes. The 'open' array contains one
206
+ // handler per OPEN tearsheet ordered from lowest to highest in visual z-order.
207
+ // The 'all' array contains all the handlers for open and closed tearsheets.
208
+ this._stackDepth = -1;
209
+ this._stackPosition = -1;
210
+ this._topOfStack = () => {
211
+ return this._stackDepth === this._stackPosition;
212
+ };
213
+ this._notifyStack = () => {
214
+ CDSTearsheet_1._stack.all.forEach((handler) => {
215
+ handler(Math.min(CDSTearsheet_1._stack.open.length, maxStackDepth), CDSTearsheet_1._stack.open.indexOf(handler) + 1);
216
+ });
217
+ };
218
+ this._handleStackChange = (newDepth, newPosition) => {
219
+ this._stackDepth = newDepth;
220
+ this._stackPosition = newPosition;
221
+ if (this._stackDepth > 1 && this._stackPosition > 0) {
222
+ this.setAttribute('stack-position', `${newPosition}`);
223
+ this.setAttribute('stack-depth', `${this._stackDepth}`);
224
+ }
225
+ else {
226
+ this.removeAttribute('stack-position');
227
+ this.removeAttribute('stack-depth');
228
+ }
229
+ };
230
+ this._updateStack = () => {
231
+ if (this.open) {
232
+ CDSTearsheet_1._stack.open.push(this._handleStackChange);
233
+ }
234
+ else {
235
+ const indexOpen = CDSTearsheet_1._stack.open.indexOf(this._handleStackChange);
236
+ if (indexOpen >= 0) {
237
+ CDSTearsheet_1._stack.open.splice(indexOpen, 1);
238
+ }
239
+ }
240
+ this._notifyStack();
241
+ };
242
+ this.actionsMultiple = ['', 'single', 'double', 'triple'][this._actionsCount];
243
+ this._checkSetOpen = () => {
244
+ const { _tearsheet: tearsheet } = this;
245
+ if (tearsheet && this._isOpen) {
246
+ // wait until the tearsheet has transitioned off the screen to remove
247
+ tearsheet.addEventListener('transitionend', () => {
248
+ this._isOpen = false;
249
+ });
250
+ }
251
+ else {
252
+ // allow the html to render before animating in the tearsheet
253
+ window.requestAnimationFrame(() => {
254
+ this._isOpen = this.open;
255
+ });
256
+ }
257
+ };
258
+ }
259
+ _checkSetHasSlot(e) {
260
+ var _a, _b;
261
+ const t = e.target;
262
+ const dataPostfix = t.getAttribute('data-postfix');
263
+ const postfix = dataPostfix ? `-${dataPostfix}` : '';
264
+ // snake `ab-cd-ef` to _has camel case _hasAbCdEf
265
+ const hasName = `_has-${t.name}${postfix}`.replace(/-./g, (c) => c[1].toUpperCase());
266
+ this[hasName] = ((_b = (_a = t === null || t === void 0 ? void 0 : t.assignedElements()) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0;
267
+ }
268
+ /**
269
+ * Handles `click` event on the modal container.
270
+ *
271
+ * @param event The event.
272
+ */
273
+ _handleClickContainer(event) {
274
+ if (event.target.matches(this.constructor.selectorCloseButton)) {
275
+ this._handleUserInitiatedClose(event.target);
276
+ }
277
+ }
278
+ /**
279
+ * Handles user-initiated close request of this tearsheet.
280
+ *
281
+ * @param triggeredBy The element that triggered this close request.
282
+ */
283
+ _handleUserInitiatedClose(triggeredBy) {
284
+ if (this.open) {
285
+ const init = {
286
+ bubbles: true,
287
+ cancelable: true,
288
+ composed: true,
289
+ detail: {
290
+ triggeredBy,
291
+ },
292
+ };
293
+ if (this.dispatchEvent(new CustomEvent(this.constructor.eventBeforeClose, init))) {
294
+ this.open = false;
295
+ this.dispatchEvent(new CustomEvent(this.constructor.eventClose, init));
296
+ }
297
+ }
298
+ }
299
+ _handleSlugChange(e) {
300
+ const childItems = e.target.assignedElements();
301
+ this._hasSlug = childItems.length > 0;
302
+ if (this._hasSlug) {
303
+ childItems[0].setAttribute('size', 'lg');
304
+ this.setAttribute('slug', '');
305
+ }
306
+ else {
307
+ this.removeAttribute('slug');
308
+ }
309
+ }
310
+ _handleActionsChange(e) {
311
+ var _a;
312
+ const target = e.target;
313
+ const actions = target === null || target === void 0 ? void 0 : target.assignedElements();
314
+ const actionsCount = (_a = actions === null || actions === void 0 ? void 0 : actions.length) !== null && _a !== void 0 ? _a : 0;
315
+ if (actionsCount > this._maxActions) {
316
+ this._actionsCount = this._maxActions;
317
+ console.error(`Too many tearsheet actions, max ${this._maxActions}.`);
318
+ }
319
+ else {
320
+ this._actionsCount = actionsCount;
321
+ }
322
+ for (let i = 0; i < (actions === null || actions === void 0 ? void 0 : actions.length); i++) {
323
+ if (i + 1 > this._maxActions) {
324
+ // hide excessive tearsheet actions
325
+ actions[i].setAttribute('hidden', 'true');
326
+ actions[i].setAttribute(`data-actions-limit-${this._maxActions}-exceeded`, `${actions.length}`);
327
+ }
328
+ else {
329
+ actions[i].classList.add(`${blockClassActionSet}__action-button`);
330
+ }
331
+ }
332
+ this._checkUpdateActionSizes();
333
+ }
334
+ connectedCallback() {
335
+ super.connectedCallback();
336
+ CDSTearsheet_1._stack.all.push(this._handleStackChange);
337
+ }
338
+ disconnectedCallback() {
339
+ super.disconnectedCallback();
340
+ const indexAll = CDSTearsheet_1._stack.all.indexOf(this._handleStackChange);
341
+ CDSTearsheet_1._stack.all.splice(indexAll, 1);
342
+ const indexOpen = CDSTearsheet_1._stack.all.indexOf(this._handleStackChange);
343
+ CDSTearsheet_1._stack.open.splice(indexOpen, 1);
344
+ }
345
+ render() {
346
+ const { closeIconDescription, influencerPlacement, influencerWidth, open, width, } = this;
347
+ const actionsMultiple = ['', 'single', 'double', 'triple'][this._actionsCount];
348
+ const headerFieldsTemplate = html `<div
349
+ class=${`${blockClass}__header-fields`}
350
+ >
351
+ <h2 class=${`${blockClassModalHeader}__label`} ?hidden=${!this._hasLabel}>
352
+ <slot name="label" @slotchange=${this._checkSetHasSlot}></slot>
353
+ </h2>
354
+ <h3
355
+ class=${`${blockClassModalHeader}__heading ${blockClass}__heading`}
356
+ ?hidden=${!this._hasTitle}
357
+ >
358
+ <slot name="title" @slotchange=${this._checkSetHasSlot}></slot>
359
+ </h3>
360
+ <div
361
+ class=${`${blockClass}__header-description`}
362
+ ?hidden=${!this._hasDescription}
363
+ >
364
+ <slot name="description" @slotchange=${this._checkSetHasSlot}></slot>
365
+ </div>
366
+ </div>`;
367
+ const headerActionsTemplate = html ` <div
368
+ class=${`${blockClass}__header-actions`}
369
+ ?hidden=${!this._hasHeaderActions || this.width === 'narrow'}
370
+ >
371
+ <slot name="header-actions" @slotchange=${this._checkSetHasSlot}></slot>
372
+ </div>`;
373
+ const headerTemplate = html ` <cds-modal-header
374
+ class=${`${blockClass}__header`}
375
+ ?has-close-icon=${this.hasCloseIcon || (this === null || this === void 0 ? void 0 : this._actionsCount) === 0}
376
+ ?has-navigation=${this._hasHeaderNavigation && this.width === 'wide'}
377
+ ?has-header-actions=${this._hasHeaderActions && this.width === 'wide'}
378
+ ?has-actions=${(this === null || this === void 0 ? void 0 : this._actionsCount) > 0}
379
+ ?has-slug=${this === null || this === void 0 ? void 0 : this._hasSlug}
380
+ width=${width}
381
+ >
382
+ ${this.width === TEARSHEET_WIDTH.WIDE
383
+ ? html `<cds-layer level="1" class=${`${blockClass}__header-content`}
384
+ >${headerFieldsTemplate}${headerActionsTemplate}</cds-layer
385
+ >`
386
+ : html `<div>${headerFieldsTemplate}${headerActionsTemplate}</div>`}
387
+
388
+ <div
389
+ class=${`${blockClass}__header-navigation`}
390
+ ?hidden=${!this._hasHeaderNavigation || this.width === 'narrow'}
391
+ >
392
+ <slot
393
+ name="header-navigation"
394
+ @slotchange=${this._checkSetHasSlot}
395
+ ></slot>
396
+ </div>
397
+ <slot name="slug" @slotchange=${this._handleSlugChange}></slot>
398
+ ${this.hasCloseIcon || (this === null || this === void 0 ? void 0 : this._actionsCount) === 0
399
+ ? html `<cds-modal-close-button
400
+ close-button-label=${closeIconDescription}
401
+ @click=${this._handleUserInitiatedClose}
402
+ ></cds-modal-close-button>`
403
+ : ''}
404
+ </cds-modal-header>`;
405
+ return html `
406
+ <a
407
+ id="start-sentinel"
408
+ class="${prefix}--visually-hidden"
409
+ href="javascript:void 0"
410
+ role="navigation"
411
+ ></a>
412
+ <div
413
+ aria-label=${this.ariaLabel}
414
+ class=${`${blockClass}__container ${carbonPrefix}--modal-container ${carbonPrefix}--modal-container--sm`}
415
+ part="dialog"
416
+ role="complementary"
417
+ ?open=${this._isOpen}
418
+ ?opening=${open && !this._isOpen}
419
+ ?closing=${!open && this._isOpen}
420
+ width=${width}
421
+ stack-position=${this._stackPosition}
422
+ stack-depth=${this._stackDepth}
423
+ @click=${this._handleClickContainer}
424
+ >
425
+ <!-- Header -->
426
+ ${headerTemplate}
427
+
428
+ <!-- Body -->
429
+ <cds-modal-body class=${`${blockClass}__body`} width=${width}>
430
+ <!-- Influencer when on left -->
431
+ ${influencerPlacement !== TEARSHEET_INFLUENCER_PLACEMENT.RIGHT
432
+ ? html `<div
433
+ class=${`${blockClass}__influencer`}
434
+ ?wide=${influencerWidth === 'wide'}
435
+ ?hidden=${!this._hasInfluencerLeft ||
436
+ this.width === TEARSHEET_WIDTH.NARROW}
437
+ >
438
+ <slot
439
+ name="influencer"
440
+ data-postfix="left"
441
+ @slotchange=${this._checkSetHasSlot}
442
+ ></slot>
443
+ </div>`
444
+ : ''}
445
+
446
+ <div class=${`${blockClass}__right`}>
447
+ <div class=${`${blockClass}__main`}>
448
+ <div class=${`${blockClass}__content`}>
449
+ <cds-layer level="0">
450
+ <slot></slot>
451
+ </cds-layer>
452
+ </div>
453
+
454
+ <!-- Influencer when on right -->
455
+ ${influencerPlacement === TEARSHEET_INFLUENCER_PLACEMENT.RIGHT
456
+ ? html `<div
457
+ class=${`${blockClass}__influencer`}
458
+ ?wide=${influencerWidth}
459
+ ?hidden=${!this._hasInfluencerRight ||
460
+ this.width === TEARSHEET_WIDTH.NARROW}
461
+ >
462
+ <slot
463
+ name="influencer"
464
+ data-postfix="right"
465
+ @slotchange=${this._checkSetHasSlot}
466
+ ></slot>
467
+ </div>`
468
+ : ''}
469
+ </div>
470
+ <!-- Action buttons -->
471
+ <cds-button-set-base
472
+ class=${`${blockClass}__buttons ${blockClass}__button-container`}
473
+ actions-multiple=${actionsMultiple}
474
+ ?tearsheet-wide=${width === 'wide'}
475
+ ?hidden=${this._actionsCount === 0}
476
+ >
477
+ <slot
478
+ name="actions"
479
+ @slotchange=${this._handleActionsChange}
480
+ ></slot>
481
+ </cds-button-set-base>
482
+ </div>
483
+ </cds-modal-body>
484
+ </div>
485
+ <a
486
+ id="end-sentinel"
487
+ class="${prefix}--visually-hidden"
488
+ href="javascript:void 0"
489
+ role="navigation"
490
+ ></a>
491
+ `;
492
+ }
493
+ async updated(changedProperties) {
494
+ if (changedProperties.has('width')) {
495
+ this._checkUpdateActionSizes();
496
+ }
497
+ if (process.env.NODE_ENV === 'development' &&
498
+ (changedProperties.has('width') ||
499
+ changedProperties.has('_hasHeaderNavigation') ||
500
+ changedProperties.has('_hasInfluencerLeft') ||
501
+ changedProperties.has('_hasInfluencerRight') ||
502
+ changedProperties.has('_hasHeaderActions'))) {
503
+ if (this.width === 'narrow') {
504
+ if (this._hasHeaderNavigation) {
505
+ console.error(`Header navigation is not permitted in narrow Tearsheet.`);
506
+ }
507
+ if (this._hasInfluencerLeft || this._hasInfluencerRight) {
508
+ console.error(`Influencer is not permitted in narrow Tearsheet.`);
509
+ }
510
+ if (this._hasHeaderActions) {
511
+ console.error(`Header actions are not permitted in narrow Tearsheet.`);
512
+ }
513
+ }
514
+ }
515
+ if (changedProperties.has('open')) {
516
+ this._updateStack();
517
+ this._checkSetOpen();
518
+ if (this.open) {
519
+ this._launcher = this.ownerDocument.activeElement;
520
+ const focusNode = this.selectorInitialFocus &&
521
+ this.querySelector(this.selectorInitialFocus);
522
+ await this.constructor._delay();
523
+ if (focusNode) {
524
+ // For cases where a `carbon-web-components` component (e.g. `<cds-button>`) being `primaryFocusNode`,
525
+ // where its first update/render cycle that makes it focusable happens after `<c4p-tearsheet>`'s first update/render cycle
526
+ focusNode.focus();
527
+ }
528
+ else if (!tryFocusElements(this.querySelectorAll(this.constructor.selectorTabbable), true)) {
529
+ this.focus();
530
+ }
531
+ }
532
+ else if (this._launcher &&
533
+ typeof this._launcher.focus === 'function') {
534
+ this._launcher.focus();
535
+ this._launcher = null;
536
+ }
537
+ }
538
+ }
539
+ /**
540
+ * @param ms The number of milliseconds.
541
+ * @returns A promise that is resolves after the given milliseconds.
542
+ */
543
+ static _delay(ms = 0) {
544
+ return new Promise((resolve) => {
545
+ setTimeout(resolve, ms);
546
+ });
547
+ }
548
+ /**
549
+ * A selector selecting buttons that should close this modal.
550
+ */
551
+ static get selectorCloseButton() {
552
+ return `[data-modal-close],${carbonPrefix}-modal-close-button`;
553
+ }
554
+ /**
555
+ * A selector selecting tabbable nodes.
556
+ */
557
+ static get selectorTabbable() {
558
+ return selectorTabbable;
559
+ }
560
+ /**
561
+ * The name of the custom event fired before this tearsheet is being closed upon a user gesture.
562
+ * Cancellation of this event stops the user-initiated action of closing this tearsheet.
563
+ */
564
+ static get eventBeforeClose() {
565
+ return `${prefix}-tearsheet-beingclosed`;
566
+ }
567
+ /**
568
+ * The name of the custom event fired after this tearsheet is closed upon a user gesture.
569
+ */
570
+ static get eventClose() {
571
+ return `${prefix}-tearsheet-closed`;
572
+ }
573
+ /**
574
+ * The name of the custom event fired on clicking the navigate back button
575
+ */
576
+ static get eventNavigateBack() {
577
+ return `${prefix}-tearsheet-header-navigate-back`;
578
+ }
579
+ };
580
+ CDSTearsheet._stack = {
581
+ open: [],
582
+ all: [],
583
+ };
584
+ CDSTearsheet.styles = styles; // `styles` here is a `CSSResult` generated by custom WebPack loader
585
+ __decorate([
586
+ query('#start-sentinel')
587
+ ], CDSTearsheet.prototype, "_startSentinelNode", void 0);
588
+ __decorate([
589
+ query('#end-sentinel')
590
+ ], CDSTearsheet.prototype, "_endSentinelNode", void 0);
591
+ __decorate([
592
+ query(`.${blockClass}__container`)
593
+ ], CDSTearsheet.prototype, "_tearsheet", void 0);
594
+ __decorate([
595
+ queryAssignedElements({
596
+ slot: 'actions',
597
+ selector: `${carbonPrefix}-button`,
598
+ })
599
+ ], CDSTearsheet.prototype, "_actions", void 0);
600
+ __decorate([
601
+ state()
602
+ ], CDSTearsheet.prototype, "_actionsCount", void 0);
603
+ __decorate([
604
+ state()
605
+ ], CDSTearsheet.prototype, "_hasHeaderActions", void 0);
606
+ __decorate([
607
+ state()
608
+ ], CDSTearsheet.prototype, "_hasLabel", void 0);
609
+ __decorate([
610
+ state()
611
+ ], CDSTearsheet.prototype, "_hasSlug", void 0);
612
+ __decorate([
613
+ state()
614
+ ], CDSTearsheet.prototype, "_hasTitle", void 0);
615
+ __decorate([
616
+ state()
617
+ ], CDSTearsheet.prototype, "_hasDescription", void 0);
618
+ __decorate([
619
+ state()
620
+ ], CDSTearsheet.prototype, "_hasInfluencerLeft", void 0);
621
+ __decorate([
622
+ state()
623
+ ], CDSTearsheet.prototype, "_hasInfluencerRight", void 0);
624
+ __decorate([
625
+ state()
626
+ ], CDSTearsheet.prototype, "_isOpen", void 0);
627
+ __decorate([
628
+ state()
629
+ ], CDSTearsheet.prototype, "_hasHeaderNavigation", void 0);
630
+ __decorate([
631
+ HostListener('click')
632
+ // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to
633
+ ], CDSTearsheet.prototype, "_handleClick", void 0);
634
+ __decorate([
635
+ HostListener('shadowRoot:focusout')
636
+ // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to
637
+ ], CDSTearsheet.prototype, "_handleBlur", void 0);
638
+ __decorate([
639
+ HostListener('document:keydown')
640
+ // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to
641
+ ], CDSTearsheet.prototype, "_handleKeydown", void 0);
642
+ __decorate([
643
+ property({ reflect: true, attribute: 'aria-label' })
644
+ ], CDSTearsheet.prototype, "ariaLabel", void 0);
645
+ __decorate([
646
+ property({ reflect: true, attribute: 'close-icon-description' })
647
+ ], CDSTearsheet.prototype, "closeIconDescription", void 0);
648
+ __decorate([
649
+ property({ reflect: true, type: Boolean, attribute: 'has-close-icon' })
650
+ ], CDSTearsheet.prototype, "hasCloseIcon", void 0);
651
+ __decorate([
652
+ property({ reflect: true, attribute: 'influencer-placement' })
653
+ ], CDSTearsheet.prototype, "influencerPlacement", void 0);
654
+ __decorate([
655
+ property({ reflect: true, attribute: 'influencer-width' })
656
+ ], CDSTearsheet.prototype, "influencerWidth", void 0);
657
+ __decorate([
658
+ property({ type: Boolean, reflect: true })
659
+ ], CDSTearsheet.prototype, "open", void 0);
660
+ __decorate([
661
+ property({ type: Boolean, attribute: 'prevent-close-on-click-outside' })
662
+ ], CDSTearsheet.prototype, "preventCloseOnClickOutside", void 0);
663
+ __decorate([
664
+ property({
665
+ reflect: true,
666
+ attribute: 'selector-initial-focus',
667
+ type: String,
668
+ })
669
+ ], CDSTearsheet.prototype, "selectorInitialFocus", void 0);
670
+ __decorate([
671
+ property({ reflect: true, attribute: 'width' })
672
+ ], CDSTearsheet.prototype, "width", void 0);
673
+ __decorate([
674
+ state()
675
+ ], CDSTearsheet.prototype, "_stackDepth", void 0);
676
+ __decorate([
677
+ state()
678
+ ], CDSTearsheet.prototype, "_stackPosition", void 0);
679
+ CDSTearsheet = CDSTearsheet_1 = __decorate([
680
+ carbonElement(`${prefix}-tearsheet`)
681
+ ], CDSTearsheet);
682
+ var CDSTearsheet$1 = CDSTearsheet;
683
+
684
+ export { TEARSHEET_INFLUENCER_PLACEMENT, TEARSHEET_INFLUENCER_WIDTH, TEARSHEET_WIDTH, CDSTearsheet$1 as default };
685
+ //# sourceMappingURL=tearsheet.js.map