@carbon/ibm-products-web-components 0.0.1-canary.3564

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. package/.storybook/Preview.ts +161 -0
  2. package/.storybook/_container.scss +73 -0
  3. package/.storybook/container.ts +41 -0
  4. package/.storybook/main.ts +25 -0
  5. package/.storybook/manager.ts +13 -0
  6. package/.storybook/preview-head.html +3 -0
  7. package/.storybook/templates/with-layer.scss +38 -0
  8. package/.storybook/templates/with-layer.ts +90 -0
  9. package/.storybook/theme.ts +12 -0
  10. package/LICENSE +201 -0
  11. package/es/components/side-panel/defs.d.ts +39 -0
  12. package/es/components/side-panel/defs.js +51 -0
  13. package/es/components/side-panel/defs.js.map +1 -0
  14. package/es/components/side-panel/index.d.ts +9 -0
  15. package/es/components/side-panel/index.js +9 -0
  16. package/es/components/side-panel/index.js.map +1 -0
  17. package/es/components/side-panel/side-panel.d.ts +539 -0
  18. package/es/components/side-panel/side-panel.js +837 -0
  19. package/es/components/side-panel/side-panel.js.map +1 -0
  20. package/es/components/side-panel/side-panel.scss.js +13 -0
  21. package/es/components/side-panel/side-panel.scss.js.map +1 -0
  22. package/es/components/side-panel/side-panel.test.d.ts +7 -0
  23. package/es/components/side-panel/side-panel.test.js +56 -0
  24. package/es/components/side-panel/side-panel.test.js.map +1 -0
  25. package/es/globals/internal/handle.d.ts +18 -0
  26. package/es/globals/internal/handle.js +8 -0
  27. package/es/globals/internal/handle.js.map +1 -0
  28. package/es/globals/settings.d.ts +15 -0
  29. package/es/globals/settings.js +28 -0
  30. package/es/globals/settings.js.map +1 -0
  31. package/es/index.d.ts +9 -0
  32. package/es/index.js +9 -0
  33. package/es/index.js.map +1 -0
  34. package/lib/components/side-panel/defs.d.ts +39 -0
  35. package/lib/components/side-panel/defs.js +51 -0
  36. package/lib/components/side-panel/defs.js.map +1 -0
  37. package/lib/components/side-panel/index.d.ts +9 -0
  38. package/lib/components/side-panel/side-panel.d.ts +539 -0
  39. package/lib/components/side-panel/side-panel.test.d.ts +7 -0
  40. package/lib/globals/internal/handle.d.ts +18 -0
  41. package/lib/globals/settings.d.ts +15 -0
  42. package/lib/globals/settings.js +32 -0
  43. package/lib/globals/settings.js.map +1 -0
  44. package/lib/index.d.ts +9 -0
  45. package/netlify.toml +8 -0
  46. package/package.json +96 -0
  47. package/scss/components/side-panel/side-panel.scss +302 -0
  48. package/scss/components/side-panel/story-styles.scss +46 -0
  49. package/src/components/side-panel/defs.ts +46 -0
  50. package/src/components/side-panel/index.ts +10 -0
  51. package/src/components/side-panel/side-panel.mdx +106 -0
  52. package/src/components/side-panel/side-panel.scss +302 -0
  53. package/src/components/side-panel/side-panel.stories.ts +525 -0
  54. package/src/components/side-panel/side-panel.test.ts +52 -0
  55. package/src/components/side-panel/side-panel.ts +980 -0
  56. package/src/components/side-panel/story-styles.scss +46 -0
  57. package/src/globals/internal/handle.ts +19 -0
  58. package/src/globals/settings.ts +22 -0
  59. package/src/index.ts +10 -0
  60. package/src/typings/resources.d.ts +26 -0
  61. package/tasks/build.js +165 -0
  62. package/tools/rollup-plugin-icon-paths.js +39 -0
  63. package/tools/rollup-plugin-icons.js +73 -0
  64. package/tools/rollup-plugin-lit-scss.js +89 -0
  65. package/tools/svg-result-carbon-icon-loader.js +28 -0
  66. package/tools/svg-result-carbon-icon.js +42 -0
  67. package/tools/vite-svg-result-carbon-icon-loader.ts +65 -0
  68. package/tsconfig.json +36 -0
  69. package/vite.config.ts +32 -0
@@ -0,0 +1,837 @@
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 } 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 { SIDE_PANEL_PLACEMENT, SIDE_PANEL_SIZE } from './defs.js';
15
+ import styles from './side-panel.scss.js';
16
+ import { selectorTabbable } from '@carbon/web-components/es/globals/settings.js';
17
+ import { carbonElement } from '@carbon/web-components/es/globals/decorators/carbon-element.js';
18
+ import ArrowLeft16 from '../../icons/arrow--left/16';
19
+ import Close20 from '../../icons/close/20';
20
+ import { moderate02 } from '@carbon/motion';
21
+ import '@carbon/web-components/es/components/button/index.js';
22
+ import '@carbon/web-components/es/components/button/button-set-base.js';
23
+ import '@carbon/web-components/es/components/icon-button/index.js';
24
+ import '@carbon/web-components/es/components/layer/index.js';
25
+
26
+ /**
27
+ * @license
28
+ *
29
+ * Copyright IBM Corp. 2023, 2024
30
+ *
31
+ * This source code is licensed under the Apache-2.0 license found in the
32
+ * LICENSE file in the root directory of this source tree.
33
+ */
34
+ const blockClass = `${prefix}--side-panel`;
35
+ const blockClassActionSet = `${prefix}--action-set`;
36
+ /**
37
+ * Observes resize of the given element with the given resize observer.
38
+ *
39
+ * @param observer The resize observer.
40
+ * @param elem The element to observe the resize.
41
+ */
42
+ const observeResize = (observer, elem) => {
43
+ if (!elem) {
44
+ return null;
45
+ }
46
+ observer.observe(elem);
47
+ return {
48
+ release() {
49
+ observer.unobserve(elem);
50
+ return null;
51
+ },
52
+ };
53
+ };
54
+ /**
55
+ * Tries to focus on the given elements and bails out if one of them is successful.
56
+ *
57
+ * @param elements The elements.
58
+ * @param reverse `true` to go through the list in reverse order.
59
+ * @returns `true` if one of the attempts is successful, `false` otherwise.
60
+ */
61
+ function tryFocusElements(elements, reverse) {
62
+ if (!reverse) {
63
+ for (let i = 0; i < elements.length; ++i) {
64
+ const elem = elements[i];
65
+ elem.focus();
66
+ if (elem.ownerDocument.activeElement === elem) {
67
+ return true;
68
+ }
69
+ }
70
+ }
71
+ else {
72
+ for (let i = elements.length - 1; i >= 0; --i) {
73
+ const elem = elements[i];
74
+ elem.focus();
75
+ if (elem.ownerDocument.activeElement === elem) {
76
+ return true;
77
+ }
78
+ }
79
+ }
80
+ return false;
81
+ }
82
+ /**
83
+ * SidePanel.
84
+ *
85
+ * @element cds-side-panel
86
+ * @csspart dialog The dialog.
87
+ * @fires cds-side-panel-beingclosed
88
+ * The custom event fired before this side-panel is being closed upon a user gesture.
89
+ * Cancellation of this event stops the user-initiated action of closing this side-panel.
90
+ * @fires cds-side-panel-closed - The custom event fired after this side-panel is closed upon a user gesture.
91
+ * @fires cds-side-panel-navigate-back - custom event fired when clicking navigate back (available when step > 0)
92
+ */
93
+ let CDSSidePanel = class CDSSidePanel extends HostListenerMixin(LitElement) {
94
+ constructor() {
95
+ super(...arguments);
96
+ /**
97
+ * The handle for observing resize of the parent element of this element.
98
+ */
99
+ this._hObserveResize = null;
100
+ /**
101
+ * The element that had focus before this side-panel gets open.
102
+ */
103
+ this._launcher = null;
104
+ this._doAnimateTitle = true;
105
+ this._isOpen = false;
106
+ this._containerScrollTop = -16;
107
+ this._hasSubtitle = false;
108
+ this._hasSlug = false;
109
+ this._hasActionToolbar = false;
110
+ this._actionsCount = 0;
111
+ this._slugCloseSize = 'sm';
112
+ /**
113
+ * Handles `blur` event on this element.
114
+ *
115
+ * @param event The event.
116
+ * @param event.target The event target.
117
+ * @param event.relatedTarget The event relatedTarget.
118
+ */
119
+ this._handleBlur = async ({ target, relatedTarget }) => {
120
+ var _a;
121
+ const { open, _startSentinelNode: startSentinelNode, _endSentinelNode: endSentinelNode, } = this;
122
+ const oldContains = target !== this && this.contains(target);
123
+ const currentContains = relatedTarget !== this &&
124
+ (this.contains(relatedTarget) ||
125
+ (((_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(relatedTarget)) &&
126
+ relatedTarget !== startSentinelNode &&
127
+ relatedTarget !== endSentinelNode));
128
+ // Performs focus wrapping if _all_ of the following is met:
129
+ // * This side-panel is open
130
+ // * The viewport still has focus
131
+ // * SidePanel body used to have focus but no longer has focus
132
+ const { selectorTabbable: selectorTabbableForSidePanel } = this
133
+ .constructor;
134
+ if (open && relatedTarget && oldContains && !currentContains) {
135
+ const comparisonResult = target.compareDocumentPosition(relatedTarget);
136
+ // eslint-disable-next-line no-bitwise
137
+ if (relatedTarget === startSentinelNode || comparisonResult) {
138
+ await this.constructor._delay();
139
+ if (!tryFocusElements(this.querySelectorAll(selectorTabbableForSidePanel), true) &&
140
+ relatedTarget !== this) {
141
+ this.focus();
142
+ }
143
+ }
144
+ // eslint-disable-next-line no-bitwise
145
+ else if (relatedTarget === endSentinelNode || comparisonResult) {
146
+ await this.constructor._delay();
147
+ if (!tryFocusElements(this.querySelectorAll(selectorTabbableForSidePanel), true)) {
148
+ this.focus();
149
+ }
150
+ }
151
+ }
152
+ };
153
+ this._handleKeydown = ({ key, target }) => {
154
+ if (key === 'Esc' || key === 'Escape') {
155
+ this._handleUserInitiatedClose(target);
156
+ }
157
+ };
158
+ this._reducedMotion = typeof window !== 'undefined' && (window === null || window === void 0 ? void 0 : window.matchMedia)
159
+ ? window.matchMedia('(prefers-reduced-motion: reduce)')
160
+ : { matches: true };
161
+ this._adjustPageContent = () => {
162
+ var _a, _b;
163
+ // sets/resets styles based on slideIn property and selectorPageContent;
164
+ if (this.selectorPageContent) {
165
+ const pageContentEl = document.querySelector(this.selectorPageContent);
166
+ if (pageContentEl) {
167
+ const newValues = {
168
+ marginInlineStart: '',
169
+ marginInlineEnd: '',
170
+ inlineSize: '',
171
+ transition: this._reducedMotion.matches
172
+ ? 'none'
173
+ : `all ${moderate02}`,
174
+ transitionProperty: 'margin-inline-start, margin-inline-end',
175
+ };
176
+ if (this.open) {
177
+ newValues.inlineSize = 'auto';
178
+ if (this.placement === 'left') {
179
+ newValues.marginInlineStart = `${(_a = this === null || this === void 0 ? void 0 : this._sidePanel) === null || _a === void 0 ? void 0 : _a.offsetWidth}px`;
180
+ }
181
+ else {
182
+ newValues.marginInlineEnd = `${(_b = this === null || this === void 0 ? void 0 : this._sidePanel) === null || _b === void 0 ? void 0 : _b.offsetWidth}px`;
183
+ }
184
+ }
185
+ Object.keys(newValues).forEach((key) => {
186
+ pageContentEl.style[key] = newValues[key];
187
+ });
188
+ }
189
+ }
190
+ };
191
+ this._checkSetOpen = () => {
192
+ const { _sidePanel: sidePanel } = this;
193
+ if (sidePanel && this._isOpen) {
194
+ if (this._reducedMotion) {
195
+ this._isOpen = false;
196
+ }
197
+ else {
198
+ // wait until the side panel has transitioned off the screen to remove
199
+ sidePanel.addEventListener('transitionend', () => {
200
+ this._isOpen = false;
201
+ });
202
+ }
203
+ }
204
+ else {
205
+ // allow the html to render before animating in the side panel
206
+ this._isOpen = this.open;
207
+ }
208
+ };
209
+ this._checkUpdateIconButtonSizes = () => {
210
+ var _a, _b;
211
+ const slug = this.querySelector(`${prefix}-slug`);
212
+ const otherButtons = (_a = this === null || this === void 0 ? void 0 : this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('#nav-back-button, #close-button');
213
+ let iconButtonSize = 'sm';
214
+ if (slug || (otherButtons === null || otherButtons === void 0 ? void 0 : otherButtons.length)) {
215
+ const actions = (_b = this === null || this === void 0 ? void 0 : this.querySelectorAll) === null || _b === void 0 ? void 0 : _b.call(this, `${prefix}-button[slot='actions']`);
216
+ if ((actions === null || actions === void 0 ? void 0 : actions.length) && /l/.test(this.size)) {
217
+ iconButtonSize = 'md';
218
+ }
219
+ }
220
+ if (slug) {
221
+ slug === null || slug === void 0 ? void 0 : slug.setAttribute('size', iconButtonSize);
222
+ }
223
+ if (otherButtons) {
224
+ [...otherButtons].forEach((btn) => {
225
+ btn.setAttribute('size', iconButtonSize);
226
+ });
227
+ }
228
+ };
229
+ this._checkUpdateActionSizes = () => {
230
+ if (this._actions) {
231
+ for (let i = 0; i < this._actions.length; i++) {
232
+ this._actions[i].setAttribute('size', this.condensedActions ? 'lg' : 'xl');
233
+ }
234
+ }
235
+ };
236
+ this._maxActions = 3;
237
+ this._checkSetDoAnimateTitle = () => {
238
+ var _a, _b, _c;
239
+ let canDoAnimateTitle = false;
240
+ if (this._sidePanel &&
241
+ this.open &&
242
+ this.animateTitle &&
243
+ ((_a = this === null || this === void 0 ? void 0 : this.title) === null || _a === void 0 ? void 0 : _a.length) &&
244
+ !this._reducedMotion.matches) {
245
+ const scrollAnimationDistance = this._getScrollAnimationDistance();
246
+ // used to calculate the header moves
247
+ (_c = (_b = this === null || this === void 0 ? void 0 : this._sidePanel) === null || _b === void 0 ? void 0 : _b.style) === null || _c === void 0 ? void 0 : _c.setProperty(`--${blockClass}--scroll-animation-distance`, `${scrollAnimationDistance}`);
248
+ let scrollEl = this._animateScrollWrapper;
249
+ if (!scrollEl && this.animateTitle && !this._doAnimateTitle) {
250
+ scrollEl = this._innerContent;
251
+ }
252
+ if (scrollEl) {
253
+ const innerComputed = window === null || window === void 0 ? void 0 : window.getComputedStyle(this._innerContent);
254
+ const innerPaddingHeight = innerComputed
255
+ ? parseFloat(innerComputed === null || innerComputed === void 0 ? void 0 : innerComputed.paddingTop) +
256
+ parseFloat(innerComputed === null || innerComputed === void 0 ? void 0 : innerComputed.paddingBottom)
257
+ : 0;
258
+ canDoAnimateTitle =
259
+ (!!this.labelText || !!this._hasActionToolbar || this._hasSubtitle) &&
260
+ scrollEl.scrollHeight - scrollEl.clientHeight >=
261
+ scrollAnimationDistance + innerPaddingHeight;
262
+ }
263
+ }
264
+ this._doAnimateTitle = canDoAnimateTitle;
265
+ };
266
+ /**
267
+ * The `ResizeObserver` instance for observing element resizes for re-positioning floating menu position.
268
+ */
269
+ // TODO: Wait for `.d.ts` update to support `ResizeObserver`
270
+ // @ts-ignore
271
+ this._resizeObserver = new ResizeObserver(() => {
272
+ if (this._sidePanel) {
273
+ this._checkSetDoAnimateTitle();
274
+ }
275
+ });
276
+ this._getScrollAnimationDistance = () => {
277
+ var _a, _b, _c, _d;
278
+ const labelHeight = (_b = (_a = this === null || this === void 0 ? void 0 : this._label) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 0;
279
+ const subtitleHeight = (_d = (_c = this === null || this === void 0 ? void 0 : this._subtitle) === null || _c === void 0 ? void 0 : _c.offsetHeight) !== null && _d !== void 0 ? _d : 0;
280
+ const titleVerticalBorder = this._hasActionToolbar
281
+ ? this._title.offsetHeight - this._title.clientHeight
282
+ : 0;
283
+ return labelHeight + subtitleHeight + titleVerticalBorder;
284
+ };
285
+ this._scrollObserver = () => {
286
+ var _a, _b, _c, _d;
287
+ const scrollTop = (_b = (_a = this._animateScrollWrapper) === null || _a === void 0 ? void 0 : _a.scrollTop) !== null && _b !== void 0 ? _b : 0;
288
+ const scrollAnimationDistance = this._getScrollAnimationDistance();
289
+ (_d = (_c = this === null || this === void 0 ? void 0 : this._sidePanel) === null || _c === void 0 ? void 0 : _c.style) === null || _d === void 0 ? void 0 : _d.setProperty(`--${blockClass}--scroll-animation-progress`, `${Math.min(scrollTop, scrollAnimationDistance) / scrollAnimationDistance}`);
290
+ };
291
+ this._handleCurrentStepUpdate = () => {
292
+ var _a;
293
+ const scrollable = (_a = this._animateScrollWrapper) !== null && _a !== void 0 ? _a : this._innerContent;
294
+ if (scrollable) {
295
+ scrollable.scrollTop = 0;
296
+ }
297
+ };
298
+ /**
299
+ * Determines if the title will animate on scroll
300
+ */
301
+ this.animateTitle = true;
302
+ /**
303
+ * Sets the close button icon description
304
+ */
305
+ this.closeIconDescription = 'Close';
306
+ /**
307
+ * Determines whether the side panel should render the condensed version (affects action buttons primarily)
308
+ */
309
+ this.condensedActions = false;
310
+ /**
311
+ * Determines whether the side panel should render with an overlay
312
+ */
313
+ this.includeOverlay = false;
314
+ /**
315
+ * Sets the icon description for the navigation back icon button
316
+ */
317
+ this.navigationBackIconDescription = 'Back';
318
+ /**
319
+ * `true` if the side-panel should be open.
320
+ */
321
+ this.open = false;
322
+ /**
323
+ * SidePanel placement.
324
+ */
325
+ this.placement = SIDE_PANEL_PLACEMENT.RIGHT;
326
+ /**
327
+ * Prevent closing on click outside of side-panel
328
+ */
329
+ this.preventCloseOnClickOutside = false;
330
+ /**
331
+ * Selector for page content, used to push content to side except
332
+ */
333
+ this.selectorPageContent = '';
334
+ /**
335
+ * SidePanel size.
336
+ */
337
+ this.size = SIDE_PANEL_SIZE.MEDIUM;
338
+ /**
339
+ * Determines if this panel slides in
340
+ */
341
+ this.slideIn = false;
342
+ }
343
+ /**
344
+ * Handles `click` event on the side-panel container.
345
+ *
346
+ * @param event The event.
347
+ */
348
+ _handleClickOnOverlay(event) {
349
+ if (!this.preventCloseOnClickOutside) {
350
+ this._handleUserInitiatedClose(event.target);
351
+ }
352
+ }
353
+ /**
354
+ * Handles `click` event on the side-panel container.
355
+ *
356
+ * @param event The event.
357
+ */
358
+ _handleCloseClick(event) {
359
+ this._handleUserInitiatedClose(event.target);
360
+ }
361
+ /**
362
+ * Handles user-initiated close request of this side-panel.
363
+ *
364
+ * @param triggeredBy The element that triggered this close request.
365
+ */
366
+ _handleUserInitiatedClose(triggeredBy) {
367
+ if (this.open) {
368
+ const init = {
369
+ bubbles: true,
370
+ cancelable: true,
371
+ composed: true,
372
+ detail: {
373
+ triggeredBy,
374
+ },
375
+ };
376
+ if (this.dispatchEvent(new CustomEvent(this.constructor.eventBeforeClose, init))) {
377
+ this.open = false;
378
+ this.dispatchEvent(new CustomEvent(this.constructor.eventClose, init));
379
+ }
380
+ }
381
+ }
382
+ _handleNavigateBack(triggeredBy) {
383
+ this.dispatchEvent(new CustomEvent(this.constructor.eventNavigateBack, {
384
+ composed: true,
385
+ detail: {
386
+ triggeredBy,
387
+ },
388
+ }));
389
+ }
390
+ _handleSlugChange(e) {
391
+ this._checkUpdateIconButtonSizes();
392
+ const childItems = e.target.assignedElements();
393
+ this._hasSlug = childItems.length > 0;
394
+ }
395
+ _handleSubtitleChange(e) {
396
+ const target = e.target;
397
+ const subtitle = target === null || target === void 0 ? void 0 : target.assignedElements();
398
+ this._hasSubtitle = subtitle.length > 0;
399
+ }
400
+ // eslint-disable-next-line class-methods-use-this
401
+ _handleActionToolbarChange(e) {
402
+ const target = e.target;
403
+ const toolbarActions = target === null || target === void 0 ? void 0 : target.assignedElements();
404
+ this._hasActionToolbar = toolbarActions && toolbarActions.length > 0;
405
+ if (this._hasActionToolbar) {
406
+ for (const toolbarAction of toolbarActions) {
407
+ // toolbar actions size should always be sm
408
+ toolbarAction.setAttribute('size', 'sm');
409
+ }
410
+ }
411
+ }
412
+ _handleActionsChange(e) {
413
+ var _a;
414
+ const target = e.target;
415
+ const actions = target === null || target === void 0 ? void 0 : target.assignedElements();
416
+ // update slug size
417
+ this._checkUpdateIconButtonSizes();
418
+ const actionsCount = (_a = actions === null || actions === void 0 ? void 0 : actions.length) !== null && _a !== void 0 ? _a : 0;
419
+ if (actionsCount > this._maxActions) {
420
+ this._actionsCount = this._maxActions;
421
+ if (process.env.NODE_ENV === 'development') {
422
+ console.error(`Too many side-panel actions, max ${this._maxActions}.`);
423
+ }
424
+ }
425
+ else {
426
+ this._actionsCount = actionsCount;
427
+ }
428
+ for (let i = 0; i < (actions === null || actions === void 0 ? void 0 : actions.length); i++) {
429
+ if (i + 1 > this._maxActions) {
430
+ // hide excessive side panel actions
431
+ actions[i].setAttribute('hidden', 'true');
432
+ actions[i].setAttribute(`data-actions-limit-${this._maxActions}-exceeded`, `${actions.length}`);
433
+ }
434
+ else {
435
+ actions[i].classList.add(`${blockClassActionSet}__action-button`);
436
+ }
437
+ }
438
+ this._checkUpdateActionSizes();
439
+ }
440
+ async connectObservers() {
441
+ await this.updateComplete;
442
+ this._hObserveResize = observeResize(this._resizeObserver, this._sidePanel);
443
+ }
444
+ disconnectObservers() {
445
+ if (this._hObserveResize) {
446
+ this._hObserveResize = this._hObserveResize.release();
447
+ }
448
+ }
449
+ connectedCallback() {
450
+ super.connectedCallback();
451
+ this.disconnectObservers();
452
+ this.connectObservers();
453
+ }
454
+ disconnectedCallback() {
455
+ super.disconnectedCallback();
456
+ this.disconnectObservers();
457
+ }
458
+ render() {
459
+ const { closeIconDescription, condensedActions, currentStep, includeOverlay, labelText, navigationBackIconDescription, open, placement, size, slideIn, title, } = this;
460
+ if (!open && !this._isOpen) {
461
+ return html ``;
462
+ }
463
+ const actionsMultiple = ['', 'single', 'double', 'triple'][this._actionsCount];
464
+ const titleTemplate = html `<div
465
+ class=${`${blockClass}__title`}
466
+ ?no-label=${!!labelText}
467
+ >
468
+ <h2 class=${title ? `${blockClass}__title-text` : ''} title=${title}>
469
+ ${title}
470
+ </h2>
471
+
472
+ ${this._doAnimateTitle
473
+ ? html `<h2
474
+ class=${`${blockClass}__collapsed-title-text`}
475
+ title=${title}
476
+ aria-hidden="true"
477
+ >
478
+ ${title}
479
+ </h2>`
480
+ : ''}
481
+ </div>`;
482
+ const headerHasTitleClass = this.title
483
+ ? ` ${blockClass}__header--has-title `
484
+ : '';
485
+ const headerTemplate = html `
486
+ <div
487
+ class=${`${blockClass}__header${headerHasTitleClass}`}
488
+ ?detail-step=${currentStep > 0}
489
+ ?no-title-animation=${!this._doAnimateTitle}
490
+ ?reduced-motion=${this._reducedMotion.matches}
491
+ >
492
+ <!-- render back button -->
493
+ ${currentStep > 0
494
+ ? html `<cds-icon-button
495
+ align="bottom-left"
496
+ aria-label=${navigationBackIconDescription}
497
+ kind="ghost"
498
+ size="sm"
499
+ class=${`${prefix}--btn ${blockClass}__navigation-back-button`}
500
+ @click=${this._handleNavigateBack}
501
+ >
502
+ ${ArrowLeft16({ slot: 'icon' })}
503
+ <span slot="tooltip-content">
504
+ ${navigationBackIconDescription}
505
+ </span>
506
+ </cds-icon-button>`
507
+ : ''}
508
+
509
+ <!-- render title label -->
510
+ ${(title === null || title === void 0 ? void 0 : title.length) && (labelText === null || labelText === void 0 ? void 0 : labelText.length)
511
+ ? html ` <p class=${`${blockClass}__label-text`}>${labelText}</p>`
512
+ : ''}
513
+
514
+ <!-- title -->
515
+ ${title ? titleTemplate : ''}
516
+
517
+ <!-- render slug and close button area -->
518
+ <div class=${`${blockClass}__slug-and-close`}>
519
+ <slot name="slug" @slotchange=${this._handleSlugChange}></slot>
520
+ <!-- {normalizedSlug} -->
521
+ <cds-icon-button
522
+ align="bottom-right"
523
+ aria-label=${closeIconDescription}
524
+ kind="ghost"
525
+ size="sm"
526
+ class=${`${blockClass}__close-button`}
527
+ @click=${this._handleCloseClick}
528
+ >
529
+ ${Close20({ slot: 'icon' })}
530
+ <span slot="tooltip-content"> ${closeIconDescription} </span>
531
+ </cds-icon-button>
532
+ </div>
533
+
534
+ <!-- render sub title -->
535
+ <p
536
+ class=${this._hasSubtitle ? `${blockClass}__subtitle-text` : ''}
537
+ ?hidden=${!this._hasSubtitle}
538
+ ?no-title-animation=${!this._doAnimateTitle}
539
+ ?no-action-toolbar=${!this._hasActionToolbar}
540
+ ?no-title=${!title}
541
+ >
542
+ <slot
543
+ name="subtitle"
544
+ @slotchange=${this._handleSubtitleChange}
545
+ ></slot>
546
+ </p>
547
+
548
+ <div
549
+ class=${this._hasActionToolbar ? `${blockClass}__action-toolbar` : ''}
550
+ ?hidden=${!this._hasActionToolbar}
551
+ ?no-title-animation=${!this._doAnimateTitle}
552
+ >
553
+ <slot
554
+ name="action-toolbar"
555
+ @slotchange=${this._handleActionToolbarChange}
556
+ ></slot>
557
+ </div>
558
+ </div>
559
+ `;
560
+ const mainTemplate = html `<div
561
+ class=${`${blockClass}__inner-content`}
562
+ ?scrolls=${!this._doAnimateTitle}
563
+ >
564
+ <cds-layer level="1">
565
+ <slot></slot>
566
+ </cds-layer>
567
+ </div> `;
568
+ const sidePanelAnimateTitleClass = this._doAnimateTitle
569
+ ? ` ${blockClass}--animated-title`
570
+ : '';
571
+ return html `
572
+ <div
573
+ class=${`${blockClass}${sidePanelAnimateTitleClass}`}
574
+ part="dialog"
575
+ role="complementary"
576
+ placement="${placement}"
577
+ ?has-slug=${this._hasSlug}
578
+ ?open=${this._isOpen}
579
+ ?opening=${open && !this._isOpen}
580
+ ?closing=${!open && this._isOpen}
581
+ ?condensed-actions=${condensedActions}
582
+ ?overlay=${includeOverlay || slideIn}
583
+ ?slide-in=${slideIn}
584
+ size=${size}
585
+ >
586
+ <a
587
+ id="start-sentinel"
588
+ class="sentinel"
589
+ hidden
590
+ href="javascript:void 0"
591
+ role="navigation"
592
+ ></a>
593
+
594
+ ${this._doAnimateTitle
595
+ ? html `<div class=${`${blockClass}__animated-scroll-wrapper`} scrolls>
596
+ ${headerTemplate} ${mainTemplate}
597
+ </div>`
598
+ : html ` ${headerTemplate} ${mainTemplate}`}
599
+
600
+ <cds-button-set-base
601
+ class=${`${blockClass}__actions-container`}
602
+ ?hidden=${this._actionsCount === 0}
603
+ ?condensed=${condensedActions}
604
+ actions-multiple=${actionsMultiple}
605
+ size=${size}
606
+ >
607
+ <slot name="actions" @slotchange=${this._handleActionsChange}></slot>
608
+ </cds-button-set-base>
609
+
610
+ <a
611
+ id="end-sentinel"
612
+ class="sentinel"
613
+ hidden
614
+ href="javascript:void 0"
615
+ role="navigation"
616
+ ></a>
617
+ </div>
618
+
619
+ ${includeOverlay
620
+ ? html `<div
621
+ ?slide-in=${slideIn}
622
+ class=${`${blockClass}__overlay`}
623
+ ?open=${this.open}
624
+ ?opening=${open && !this._isOpen}
625
+ ?closing=${!open && this._isOpen}
626
+ tabindex="-1"
627
+ @click=${this._handleClickOnOverlay}
628
+ ></div>`
629
+ : ''}
630
+ `;
631
+ }
632
+ async updated(changedProperties) {
633
+ var _a, _b, _c, _d;
634
+ if (changedProperties.has('condensedActions')) {
635
+ this._checkUpdateActionSizes();
636
+ }
637
+ if (changedProperties.has('currentStep')) {
638
+ this._handleCurrentStepUpdate();
639
+ }
640
+ if (changedProperties.has('_doAnimateTitle')) {
641
+ (_a = this === null || this === void 0 ? void 0 : this._animateScrollWrapper) === null || _a === void 0 ? void 0 : _a.removeEventListener('scroll', this._scrollObserver);
642
+ if (this._doAnimateTitle) {
643
+ (_b = this === null || this === void 0 ? void 0 : this._animateScrollWrapper) === null || _b === void 0 ? void 0 : _b.addEventListener('scroll', this._scrollObserver);
644
+ }
645
+ else {
646
+ (_d = (_c = this === null || this === void 0 ? void 0 : this._sidePanel) === null || _c === void 0 ? void 0 : _c.style) === null || _d === void 0 ? void 0 : _d.setProperty(`--${blockClass}--scroll-animation-progress`, '0');
647
+ }
648
+ }
649
+ if (changedProperties.has('_isOpen') ||
650
+ changedProperties.has('animateTitle')) {
651
+ /* @state property changed */
652
+ this._checkSetDoAnimateTitle();
653
+ }
654
+ if (changedProperties.has('slideIn') ||
655
+ changedProperties.has('open') ||
656
+ changedProperties.has('includeOverlay')) {
657
+ this._adjustPageContent();
658
+ }
659
+ if (changedProperties.has('open')) {
660
+ this._checkSetOpen();
661
+ this.disconnectObservers();
662
+ if (this.open) {
663
+ this.connectObservers();
664
+ this._launcher = this.ownerDocument.activeElement;
665
+ const focusNode = this.selectorInitialFocus &&
666
+ this.querySelector(this.selectorInitialFocus);
667
+ await this.constructor._delay();
668
+ if (focusNode) {
669
+ // For cases where a `carbon-web-components` component (e.g. `<cds-button>`) being `primaryFocusNode`,
670
+ // where its first update/render cycle that makes it focusable happens after `<cds-side-panel>`'s first update/render cycle
671
+ focusNode.focus();
672
+ }
673
+ else if (!tryFocusElements(this.querySelectorAll(this.constructor.selectorTabbable), true)) {
674
+ this.focus();
675
+ }
676
+ }
677
+ else if (this._launcher &&
678
+ typeof this._launcher.focus === 'function') {
679
+ this._launcher.focus();
680
+ this._launcher = null;
681
+ }
682
+ }
683
+ }
684
+ /**
685
+ * @param ms The number of milliseconds.
686
+ * @returns A promise that is resolves after the given milliseconds.
687
+ */
688
+ static _delay(ms = 0) {
689
+ return new Promise((resolve) => {
690
+ setTimeout(resolve, ms);
691
+ });
692
+ }
693
+ /**
694
+ * A selector selecting tabbable nodes.
695
+ */
696
+ static get selectorTabbable() {
697
+ return selectorTabbable;
698
+ }
699
+ /**
700
+ * The name of the custom event fired before this side-panel is being closed upon a user gesture.
701
+ * Cancellation of this event stops the user-initiated action of closing this side-panel.
702
+ */
703
+ static get eventBeforeClose() {
704
+ return `${prefix}-side-panel-beingclosed`;
705
+ }
706
+ /**
707
+ * The name of the custom event fired after this side-panel is closed upon a user gesture.
708
+ */
709
+ static get eventClose() {
710
+ return `${prefix}-side-panel-closed`;
711
+ }
712
+ /**
713
+ * The name of the custom event fired on clicking the navigate back button
714
+ */
715
+ static get eventNavigateBack() {
716
+ return `${prefix}-side-panel-navigate-back`;
717
+ }
718
+ };
719
+ CDSSidePanel.styles = styles; // `styles` here is a `CSSResult` generated by custom WebPack loader
720
+ __decorate([
721
+ query('#start-sentinel')
722
+ ], CDSSidePanel.prototype, "_startSentinelNode", void 0);
723
+ __decorate([
724
+ query('#end-sentinel')
725
+ ], CDSSidePanel.prototype, "_endSentinelNode", void 0);
726
+ __decorate([
727
+ query(`.${blockClass}`)
728
+ ], CDSSidePanel.prototype, "_sidePanel", void 0);
729
+ __decorate([
730
+ query(`.${blockClass}__animated-scroll-wrapper`)
731
+ ], CDSSidePanel.prototype, "_animateScrollWrapper", void 0);
732
+ __decorate([
733
+ query(`.${blockClass}__label-text`)
734
+ ], CDSSidePanel.prototype, "_label", void 0);
735
+ __decorate([
736
+ query(`.${blockClass}__title-text`)
737
+ ], CDSSidePanel.prototype, "_title", void 0);
738
+ __decorate([
739
+ query(`.${blockClass}__subtitle-text`)
740
+ ], CDSSidePanel.prototype, "_subtitle", void 0);
741
+ __decorate([
742
+ query(`.${blockClass}__inner-content`)
743
+ ], CDSSidePanel.prototype, "_innerContent", void 0);
744
+ __decorate([
745
+ queryAssignedElements({
746
+ slot: 'actions',
747
+ selector: `${carbonPrefix}-button`,
748
+ })
749
+ ], CDSSidePanel.prototype, "_actions", void 0);
750
+ __decorate([
751
+ state()
752
+ ], CDSSidePanel.prototype, "_doAnimateTitle", void 0);
753
+ __decorate([
754
+ state()
755
+ ], CDSSidePanel.prototype, "_isOpen", void 0);
756
+ __decorate([
757
+ state()
758
+ ], CDSSidePanel.prototype, "_containerScrollTop", void 0);
759
+ __decorate([
760
+ state()
761
+ ], CDSSidePanel.prototype, "_hasSubtitle", void 0);
762
+ __decorate([
763
+ state()
764
+ ], CDSSidePanel.prototype, "_hasSlug", void 0);
765
+ __decorate([
766
+ state()
767
+ ], CDSSidePanel.prototype, "_hasActionToolbar", void 0);
768
+ __decorate([
769
+ state()
770
+ ], CDSSidePanel.prototype, "_actionsCount", void 0);
771
+ __decorate([
772
+ state()
773
+ ], CDSSidePanel.prototype, "_slugCloseSize", void 0);
774
+ __decorate([
775
+ HostListener('shadowRoot:focusout')
776
+ // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to
777
+ ], CDSSidePanel.prototype, "_handleBlur", void 0);
778
+ __decorate([
779
+ HostListener('document:keydown')
780
+ // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to
781
+ ], CDSSidePanel.prototype, "_handleKeydown", void 0);
782
+ __decorate([
783
+ property({ reflect: true, attribute: 'animate-title', type: Boolean })
784
+ ], CDSSidePanel.prototype, "animateTitle", void 0);
785
+ __decorate([
786
+ property({ reflect: true, attribute: 'close-icon-description' })
787
+ ], CDSSidePanel.prototype, "closeIconDescription", void 0);
788
+ __decorate([
789
+ property({ type: Boolean, reflect: true, attribute: 'condensed-actions' })
790
+ ], CDSSidePanel.prototype, "condensedActions", void 0);
791
+ __decorate([
792
+ property({ reflect: true, attribute: 'current-step', type: Number })
793
+ ], CDSSidePanel.prototype, "currentStep", void 0);
794
+ __decorate([
795
+ property({ attribute: 'include-overlay', type: Boolean, reflect: true })
796
+ ], CDSSidePanel.prototype, "includeOverlay", void 0);
797
+ __decorate([
798
+ property({ reflect: true, attribute: 'label-text' })
799
+ ], CDSSidePanel.prototype, "labelText", void 0);
800
+ __decorate([
801
+ property({ reflect: true, attribute: 'navigation-back-icon-description' })
802
+ ], CDSSidePanel.prototype, "navigationBackIconDescription", void 0);
803
+ __decorate([
804
+ property({ type: Boolean, reflect: true })
805
+ ], CDSSidePanel.prototype, "open", void 0);
806
+ __decorate([
807
+ property({ reflect: true, type: String })
808
+ ], CDSSidePanel.prototype, "placement", void 0);
809
+ __decorate([
810
+ property({ type: Boolean, attribute: 'prevent-close-on-click-outside' })
811
+ ], CDSSidePanel.prototype, "preventCloseOnClickOutside", void 0);
812
+ __decorate([
813
+ property({
814
+ reflect: true,
815
+ attribute: 'selector-initial-focus',
816
+ type: String,
817
+ })
818
+ ], CDSSidePanel.prototype, "selectorInitialFocus", void 0);
819
+ __decorate([
820
+ property({ reflect: true, attribute: 'selector-page-content' })
821
+ ], CDSSidePanel.prototype, "selectorPageContent", void 0);
822
+ __decorate([
823
+ property({ reflect: true, type: String })
824
+ ], CDSSidePanel.prototype, "size", void 0);
825
+ __decorate([
826
+ property({ attribute: 'slide-in', type: Boolean, reflect: true })
827
+ ], CDSSidePanel.prototype, "slideIn", void 0);
828
+ __decorate([
829
+ property({ reflect: false, type: String })
830
+ ], CDSSidePanel.prototype, "title", void 0);
831
+ CDSSidePanel = __decorate([
832
+ carbonElement(`${prefix}-side-panel`)
833
+ ], CDSSidePanel);
834
+ var CDSSidePanel$1 = CDSSidePanel;
835
+
836
+ export { SIDE_PANEL_PLACEMENT, SIDE_PANEL_SIZE, CDSSidePanel$1 as default };
837
+ //# sourceMappingURL=side-panel.js.map